From 7c35bd58c6f91601ebb2aaea3b83f130e8c3753b Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Thu, 14 Sep 2023 16:51:56 -0700 Subject: [PATCH 1/7] Add xcryptobackendswap, implement SHA3 using backend --- .../0002-Add-crypto-backend-foundation.patch | 44 +- patches/0004-Add-OpenSSL-crypto-backend.patch | 40 +- patches/0005-Add-CNG-crypto-backend.patch | 41 +- patches/0009-Add-xcryptobackendswap.patch | 625 + patches/0010-Add-modified-x-crypto.patch | 107284 +++++++++++++++ 5 files changed, 108000 insertions(+), 34 deletions(-) create mode 100644 patches/0009-Add-xcryptobackendswap.patch create mode 100644 patches/0010-Add-modified-x-crypto.patch diff --git a/patches/0002-Add-crypto-backend-foundation.patch b/patches/0002-Add-crypto-backend-foundation.patch index fc01c56c619..d4de136d665 100644 --- a/patches/0002-Add-crypto-backend-foundation.patch +++ b/patches/0002-Add-crypto-backend-foundation.patch @@ -17,9 +17,9 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/hmac/hmac_test.go | 2 +- src/crypto/internal/backend/backend_test.go | 30 +++++ src/crypto/internal/backend/bbig/big.go | 17 +++ - src/crypto/internal/backend/common.go | 78 ++++++++++++ + src/crypto/internal/backend/common.go | 78 +++++++++++ src/crypto/internal/backend/isrequirefips.go | 9 ++ - src/crypto/internal/backend/nobackend.go | 125 +++++++++++++++++++ + src/crypto/internal/backend/nobackend.go | 135 +++++++++++++++++++ src/crypto/internal/backend/norequirefips.go | 9 ++ src/crypto/internal/backend/stub.s | 10 ++ src/crypto/rand/rand_unix.go | 2 +- @@ -38,7 +38,7 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/tls/cipher_suites.go | 2 +- src/go/build/deps_test.go | 2 + src/runtime/runtime_boring.go | 5 + - 34 files changed, 314 insertions(+), 29 deletions(-) + 34 files changed, 324 insertions(+), 29 deletions(-) create mode 100644 src/crypto/internal/backend/backend_test.go create mode 100644 src/crypto/internal/backend/bbig/big.go create mode 100644 src/crypto/internal/backend/common.go @@ -355,10 +355,10 @@ index 00000000000000..e5d7570d6d4363 +const isRequireFIPS = true diff --git a/src/crypto/internal/backend/nobackend.go b/src/crypto/internal/backend/nobackend.go new file mode 100644 -index 00000000000000..3698bbac41e5c8 +index 00000000000000..205fe23d4b51b2 --- /dev/null +++ b/src/crypto/internal/backend/nobackend.go -@@ -0,0 +1,125 @@ +@@ -0,0 +1,135 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -386,17 +386,27 @@ index 00000000000000..3698bbac41e5c8 + +const RandReader = randReader(0) + -+func NewSHA1() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA224() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA256() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA384() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA512() hash.Hash { panic("cryptobackend: not available") } -+ -+func SHA1(p []byte) (sum [20]byte) { panic("cryptobackend: not available") } -+func SHA224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } -+func SHA256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } -+func SHA384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } -+func SHA512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } ++func NewSHA1() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA224() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA256() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA384() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA512() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_224() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_256() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_384() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_512() hash.Hash { panic("cryptobackend: not available") } ++ ++func SHA1(p []byte) (sum [20]byte) { panic("cryptobackend: not available") } ++func SHA224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } ++func SHA256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } ++func SHA384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } ++func SHA512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } ++func SHA3_224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } ++func SHA3_256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } ++func SHA3_384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } ++func SHA3_512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } ++ ++func SupportsHash(h crypto.Hash) bool { panic("cryptobackend: not available") } + +func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("cryptobackend: not available") } + @@ -703,7 +713,7 @@ index 589e8b6fafbba3..0a6d665ee3096d 100644 "crypto/sha1" "crypto/sha256" diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index ff03691eb90397..1a8530d999b0c9 100644 +index ca0c4089a2e505..4a6d42b18c46bc 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -428,6 +428,7 @@ var depsRules = ` diff --git a/patches/0004-Add-OpenSSL-crypto-backend.patch b/patches/0004-Add-OpenSSL-crypto-backend.patch index 1ab7fde9b85..4491091b373 100644 --- a/patches/0004-Add-OpenSSL-crypto-backend.patch +++ b/patches/0004-Add-OpenSSL-crypto-backend.patch @@ -14,7 +14,7 @@ Subject: [PATCH] Add OpenSSL crypto backend src/crypto/ecdsa/notboring.go | 2 +- src/crypto/internal/backend/bbig/big.go | 2 +- .../internal/backend/bbig/big_openssl.go | 12 + - src/crypto/internal/backend/openssl_linux.go | 235 ++++++++++++++++++ + src/crypto/internal/backend/openssl_linux.go | 253 ++++++++++++++++++ src/crypto/internal/boring/fipstls/stub.s | 2 +- src/crypto/internal/boring/fipstls/tls.go | 2 +- src/crypto/rsa/boring.go | 2 +- @@ -37,7 +37,7 @@ Subject: [PATCH] Add OpenSSL crypto backend .../goexperiment/exp_opensslcrypto_on.go | 9 + src/internal/goexperiment/flags.go | 1 + src/os/exec/exec_test.go | 9 + - 33 files changed, 335 insertions(+), 24 deletions(-) + 33 files changed, 353 insertions(+), 24 deletions(-) create mode 100644 src/crypto/internal/backend/bbig/big_openssl.go create mode 100644 src/crypto/internal/backend/openssl_linux.go create mode 100644 src/internal/goexperiment/exp_opensslcrypto_off.go @@ -190,10 +190,10 @@ index 00000000000000..e6695dd66b1d02 +var Dec = bbig.Dec diff --git a/src/crypto/internal/backend/openssl_linux.go b/src/crypto/internal/backend/openssl_linux.go new file mode 100644 -index 00000000000000..9995444d1f1e9f +index 00000000000000..31e28bd1ac31e4 --- /dev/null +++ b/src/crypto/internal/backend/openssl_linux.go -@@ -0,0 +1,235 @@ +@@ -0,0 +1,253 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -308,11 +308,15 @@ index 00000000000000..9995444d1f1e9f + +const RandReader = openssl.RandReader + -+func NewSHA1() hash.Hash { return openssl.NewSHA1() } -+func NewSHA224() hash.Hash { return openssl.NewSHA224() } -+func NewSHA256() hash.Hash { return openssl.NewSHA256() } -+func NewSHA384() hash.Hash { return openssl.NewSHA384() } -+func NewSHA512() hash.Hash { return openssl.NewSHA512() } ++func NewSHA1() hash.Hash { return openssl.NewSHA1() } ++func NewSHA224() hash.Hash { return openssl.NewSHA224() } ++func NewSHA256() hash.Hash { return openssl.NewSHA256() } ++func NewSHA384() hash.Hash { return openssl.NewSHA384() } ++func NewSHA512() hash.Hash { return openssl.NewSHA512() } ++func NewSHA3_224() hash.Hash { return openssl.NewSHA3_224() } ++func NewSHA3_256() hash.Hash { return openssl.NewSHA3_256() } ++func NewSHA3_384() hash.Hash { return openssl.NewSHA3_384() } ++func NewSHA3_512() hash.Hash { return openssl.NewSHA3_512() } + +func SHA1(p []byte) (sum [20]byte) { return openssl.SHA1(p) } +func SHA224(p []byte) (sum [28]byte) { return openssl.SHA224(p) } @@ -320,6 +324,20 @@ index 00000000000000..9995444d1f1e9f +func SHA384(p []byte) (sum [48]byte) { return openssl.SHA384(p) } +func SHA512(p []byte) (sum [64]byte) { return openssl.SHA512(p) } + ++// xcrypto_backend_map:noescape ++func SHA3_224(p []byte) (sum [28]byte) { return openssl.SHA3_224(p) } ++ ++// xcrypto_backend_map:noescape ++func SHA3_256(p []byte) (sum [32]byte) { return openssl.SHA3_256(p) } ++ ++// xcrypto_backend_map:noescape ++func SHA3_384(p []byte) (sum [48]byte) { return openssl.SHA3_384(p) } ++ ++// xcrypto_backend_map:noescape ++func SHA3_512(p []byte) (sum [64]byte) { return openssl.SHA3_512(p) } ++ ++func SupportsHash(h crypto.Hash) bool { return openssl.SupportsHash(h) } ++ +func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { return openssl.NewHMAC(h, key) } + +func NewAESCipher(key []byte) (cipher.Block, error) { return openssl.NewAESCipher(key) } @@ -561,7 +579,7 @@ index f8485dc3ca1c29..9c1d3d279c472f 100644 package fipsonly diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go -index d7f082c9ee1e04..ee9d4650e3523b 100644 +index d7f082c9ee1e04..5ceaa04e4bc7ed 100644 --- a/src/crypto/tls/key_schedule.go +++ b/src/crypto/tls/key_schedule.go @@ -7,9 +7,11 @@ package tls @@ -683,7 +701,7 @@ index 81b83159f77a36..ff87d3883113cd 100644 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/net v0.14.1-0.20230809150940-1e23797619c9 h1:eQR0jFW5dN2q8lFzSF7rjkRCOOnBf0llczNvITm6ICs= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index 1a8530d999b0c9..a31878487bc285 100644 +index 4a6d42b18c46bc..0a6be3cc0231fc 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -427,6 +427,8 @@ var depsRules = ` diff --git a/patches/0005-Add-CNG-crypto-backend.patch b/patches/0005-Add-CNG-crypto-backend.patch index 67a43719ee7..6d07ea05d7b 100644 --- a/patches/0005-Add-CNG-crypto-backend.patch +++ b/patches/0005-Add-CNG-crypto-backend.patch @@ -12,7 +12,7 @@ Subject: [PATCH] Add CNG crypto backend src/crypto/internal/backend/backend_test.go | 4 +- src/crypto/internal/backend/bbig/big.go | 2 +- src/crypto/internal/backend/bbig/big_cng.go | 12 + - src/crypto/internal/backend/cng_windows.go | 216 ++++++++++++++++++ + src/crypto/internal/backend/cng_windows.go | 245 ++++++++++++++++++ src/crypto/internal/backend/common.go | 33 ++- src/crypto/internal/boring/fipstls/stub.s | 2 +- src/crypto/internal/boring/fipstls/tls.go | 2 +- @@ -47,7 +47,7 @@ Subject: [PATCH] Add CNG crypto backend .../goexperiment/exp_cngcrypto_off.go | 9 + src/internal/goexperiment/exp_cngcrypto_on.go | 9 + src/internal/goexperiment/flags.go | 1 + - 43 files changed, 408 insertions(+), 42 deletions(-) + 43 files changed, 437 insertions(+), 42 deletions(-) create mode 100644 src/crypto/internal/backend/bbig/big_cng.go create mode 100644 src/crypto/internal/backend/cng_windows.go create mode 100644 src/internal/goexperiment/exp_cngcrypto_off.go @@ -166,10 +166,10 @@ index 00000000000000..92623031fd87d0 +var Dec = bbig.Dec diff --git a/src/crypto/internal/backend/cng_windows.go b/src/crypto/internal/backend/cng_windows.go new file mode 100644 -index 00000000000000..6841062f39dfbb +index 00000000000000..37fc8f69dc9ae4 --- /dev/null +++ b/src/crypto/internal/backend/cng_windows.go -@@ -0,0 +1,216 @@ +@@ -0,0 +1,245 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -230,6 +230,18 @@ index 00000000000000..6841062f39dfbb + return cng.NewSHA512() +} + ++func NewSHA3_256() hash.Hash { ++ return cng.NewSHA3_256() ++} ++ ++func NewSHA3_384() hash.Hash { ++ return cng.NewSHA3_384() ++} ++ ++func NewSHA3_512() hash.Hash { ++ return cng.NewSHA3_512() ++} ++ +func SHA1(p []byte) (sum [20]byte) { + return cng.SHA1(p) +} @@ -248,6 +260,23 @@ index 00000000000000..6841062f39dfbb + return cng.SHA512(p) +} + ++// xcrypto_backend_map:noescape ++func SHA3_256(p []byte) (sum [32]byte) { ++ return cng.SHA3_256(p) ++} ++ ++// xcrypto_backend_map:noescape ++func SHA3_384(p []byte) (sum [48]byte) { ++ return cng.SHA3_384(p) ++} ++ ++// xcrypto_backend_map:noescape ++func SHA3_512(p []byte) (sum [64]byte) { ++ return cng.SHA3_512(p) ++} ++ ++func SupportsHash(h crypto.Hash) bool { return cng.SupportsHash(h) } ++ +func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { + return cng.NewHMAC(h, key) +} @@ -949,7 +978,7 @@ index 07b1a3851e0714..6fae2b4ba22540 100644 } state, err := marshaler.MarshalBinary() diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go -index ee9d4650e3523b..4d792561cabe04 100644 +index 5ceaa04e4bc7ed..3a8490bf32cffb 100644 --- a/src/crypto/tls/key_schedule.go +++ b/src/crypto/tls/key_schedule.go @@ -62,7 +62,7 @@ func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []by @@ -1047,7 +1076,7 @@ index ff87d3883113cd..497d219d18acd9 100644 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/net v0.14.1-0.20230809150940-1e23797619c9 h1:eQR0jFW5dN2q8lFzSF7rjkRCOOnBf0llczNvITm6ICs= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index a31878487bc285..0a7ef1f77b040a 100644 +index 0a6be3cc0231fc..d9cf7f503b107b 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -427,6 +427,10 @@ var depsRules = ` diff --git a/patches/0009-Add-xcryptobackendswap.patch b/patches/0009-Add-xcryptobackendswap.patch new file mode 100644 index 00000000000..78df7a3854b --- /dev/null +++ b/patches/0009-Add-xcryptobackendswap.patch @@ -0,0 +1,625 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Davis Goodin +Date: Tue, 22 Aug 2023 17:16:04 -0500 +Subject: [PATCH] Add xcryptobackendswap + +Use '-modfile' for x/crypto replacement when the xcryptobackendswap +experiment is enabled. + +Points at an x/crypto copy in the GOROOT directory. + +Includes tests for x/crypto backend swap, using the standard library cmd/go +test framework to run tests on the swapping functionality. + +These can be run without running the other tests using: + + go test cmd/go -testwork -run=Script/^modswap_.*$ +--- + ms_mod/README.md | 5 + + src/cmd/go/internal/modload/import.go | 6 +- + src/cmd/go/internal/modload/init.go | 10 ++ + src/cmd/go/internal/modload/vendor.go | 16 ++ + src/cmd/go/internal/modload/xcryptoswap.go | 152 ++++++++++++++++++ + src/cmd/go/testdata/script/modswap_basics.txt | 65 ++++++++ + .../script/modswap_compatible_vendoring.txt | 40 +++++ + .../go/testdata/script/modswap_nocrypto.txt | 28 ++++ + .../testdata/script/modswap_reject_work.txt | 22 +++ + .../testdata/script/modswap_test_openssl.txt | 43 +++++ + .../testdata/script/modswap_uses_openssl.txt | 60 +++++++ + .../exp_xcryptobackendswap_off.go | 9 ++ + .../goexperiment/exp_xcryptobackendswap_on.go | 9 ++ + src/internal/goexperiment/flags.go | 6 + + 14 files changed, 470 insertions(+), 1 deletion(-) + create mode 100644 ms_mod/README.md + create mode 100644 src/cmd/go/internal/modload/xcryptoswap.go + create mode 100644 src/cmd/go/testdata/script/modswap_basics.txt + create mode 100644 src/cmd/go/testdata/script/modswap_compatible_vendoring.txt + create mode 100644 src/cmd/go/testdata/script/modswap_nocrypto.txt + create mode 100644 src/cmd/go/testdata/script/modswap_reject_work.txt + create mode 100644 src/cmd/go/testdata/script/modswap_test_openssl.txt + create mode 100644 src/cmd/go/testdata/script/modswap_uses_openssl.txt + create mode 100644 src/internal/goexperiment/exp_xcryptobackendswap_off.go + create mode 100644 src/internal/goexperiment/exp_xcryptobackendswap_on.go + +diff --git a/ms_mod/README.md b/ms_mod/README.md +new file mode 100644 +index 00000000000000..cc658f4a25528d +--- /dev/null ++++ b/ms_mod/README.md +@@ -0,0 +1,5 @@ ++# ms_mod: Microsoft modules shipped with the Go toolset ++ ++This dir contains modules that are shipped with the Microsoft Go toolset. ++It is essentially a vendor directory that takes priority over a project's local vendor directory. ++Patches to the toolset enable this behavior if `GOEXPERIMENT` includes `xcryptobackendswap`. +diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go +index cc6a482fd450d0..16f056c042481c 100644 +--- a/src/cmd/go/internal/modload/import.go ++++ b/src/cmd/go/internal/modload/import.go +@@ -336,7 +336,11 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M + } + } + +- if HasModRoot() { ++ if dir, vendorDir, ok := toolsetOverridePackage(path); ok { ++ mods = append(mods, vendorPkgModule[path]) ++ dirs = append(dirs, dir) ++ roots = append(roots, vendorDir) ++ } else if HasModRoot() { + vendorDir := VendorDir() + dir, vendorOK, _ := dirInModule(path, "", vendorDir, false) + if vendorOK { +diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go +index e1575de2e0e72b..e2424182cef766 100644 +--- a/src/cmd/go/internal/modload/init.go ++++ b/src/cmd/go/internal/modload/init.go +@@ -481,6 +481,11 @@ func Init() { + // We're in module mode. Set any global variables that need to be set. + cfg.ModulesEnabled = true + setDefaultBuildMod() ++ ++ if err := initXCryptoSwap(); err != nil { ++ base.Fatalf("go: failed to initialize x/crypto replacement: %v", err) ++ } ++ + list := filepath.SplitList(cfg.BuildContext.GOPATH) + if len(list) > 0 && list[0] != "" { + gopath = list[0] +@@ -827,6 +832,11 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) + // For example, 'go get' does this, since it is expected to resolve paths. + // + // See golang.org/issue/32027. ++ } else if xCryptoSwap { ++ // We duplicated the go.mod file, but keep using the existing go.sum. ++ // The old sum file will contain an unused x/crypto entry, but this is ++ // fine. We still need it for other modules. ++ modfetch.GoSumFile = strings.TrimSuffix(preXCryptoSwapModFile, ".mod") + ".sum" + } else { + modfetch.GoSumFile = strings.TrimSuffix(modFilePath(modRoots[0]), ".mod") + ".sum" + } +diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go +index b2cb44100ec4d2..23bee33d44d1ba 100644 +--- a/src/cmd/go/internal/modload/vendor.go ++++ b/src/cmd/go/internal/modload/vendor.go +@@ -134,6 +134,22 @@ func readVendorList(vendorDir string) { + } + } + } ++ // Fix "inconsistent vendoring" errors in -mod= and -mod=vendor modes: ++ // ++ // golang.org/x/crypto: is replaced in /tmp/xcrypto-replacement-go-89165251.mod, but not marked as replaced in vendor/modules.txt ++ // ++ // We need to fix this without modifying vendor/modules.txt, so create a ++ // fake replacement here. Doing this in the read func means the rest of ++ // the code should behave as if this is correct, and we don't need to ++ // modify e.g. checkVendorConsistency. ++ if xCryptoSwap { ++ mod.Path = "golang.org/x/crypto" ++ mod.Version = "" ++ meta := vendorMeta[mod] ++ meta.Replacement = module.Version{Path: xCryptoNewModPath()} ++ vendorReplaced = append(vendorReplaced, mod) ++ vendorMeta[mod] = meta ++ } + }) + } + +diff --git a/src/cmd/go/internal/modload/xcryptoswap.go b/src/cmd/go/internal/modload/xcryptoswap.go +new file mode 100644 +index 00000000000000..be7b46ded2be0a +--- /dev/null ++++ b/src/cmd/go/internal/modload/xcryptoswap.go +@@ -0,0 +1,152 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package modload ++ ++import ( ++ "cmd/go/internal/base" ++ "cmd/go/internal/cfg" ++ "cmd/go/internal/lockedfile" ++ "fmt" ++ "io" ++ "os" ++ "path/filepath" ++ "strings" ++ ++ "golang.org/x/mod/modfile" ++) ++ ++var ( ++ // True if x/crypto is being swapped out with a module replacement. ++ xCryptoSwap bool ++ // The path to the original go.mod file before x/crypto was swapped out. ++ // Empty string if no replacement happened. ++ preXCryptoSwapModFile string ++) ++ ++// initXCryptoSwap determines whether x/crypto should be swapped out and if so, performs the swap by ++// creating a temp go.mod with a new replace directive and passing it to cfg.ModFile. ++func initXCryptoSwap() error { ++ // Use build constraint evaluation to find if swapping is enabled in this build context. ++ // This runs the build tag through the same system that is used to evaluate build tags in source ++ // code, so we know it will match up with the build tags the dev intends to use. ++ // ++ // This looks weird: there is no "easy" API to check a build tag. We follow an approach also ++ // used in go/build/build_test.go TestMatchFile: copy the build context to avoid modifying the ++ // original and assign OpenFile to a new func that defines the content of a source file without ++ // actually needing to write anything to disk. ++ backendCheckContext := cfg.BuildContext ++ backendCheckContext.OpenFile = func(path string) (io.ReadCloser, error) { ++ source := "//go:build goexperiment.xcryptobackendswap" ++ return io.NopCloser(strings.NewReader(source)), nil ++ } ++ match, err := backendCheckContext.MatchFile("", "backendcheck.go") ++ if err != nil { ++ return fmt.Errorf("error checking for crypto backend: %v", err) ++ } ++ if !match { ++ return nil ++ } ++ ++ switch cfg.CmdName { ++ // Look for commands where we must not include the replace directive. ++ // ++ // As of writing, this follows the approach of setDefaultBuildMod and checks for specific ++ // command names. When the TODO in setDefaultBuildMod is addressed to handle this more ++ // elegantly (https://github.com/golang/go/issues/40775), we should follow suit. ++ // ++ // E.g. if we included the replacement with "go mod download", it could update the go.sum ++ // file but without the checksum necessary to build with ordinary golang.org/x/crypto. ++ case "get", "mod download", "mod init", "mod tidy", "mod edit", "mod vendor": ++ return nil ++ } ++ if workFilePath != "" { ++ return fmt.Errorf("unable to replace in workspace mode because '-modfile' is not supported") ++ } ++ // At this point there are no known reasons there would be 0 or >1 modRoots, but check just in ++ // case we're missing a scenario. ++ if len(modRoots) != 1 { ++ return fmt.Errorf("expected 1 modroot, found %v, %#v", len(modRoots), modRoots) ++ } ++ ++ oldFilePath := modFilePath(modRoots[0]) ++ data, err := lockedfile.Read(oldFilePath) ++ if err != nil { ++ return fmt.Errorf("failed to read go.mod file: %v", err) ++ } ++ modFile, err := modfile.Parse(oldFilePath, data, nil) ++ if err != nil { ++ return fmt.Errorf("failed to parse go.mod file: %v", err) ++ } ++ // If this is "go build -mod=mod", include the replacement even if the go.mod doesn't include ++ // x/crypto. There might be a transitive dependency we don't know about until imports are ++ // evaluated and find an x/crypto reference. ++ if !modFileUsesXCrypto(modFile) && cfg.BuildMod != "mod" { ++ return nil ++ } ++ // Add (or update!) a replace directive. ++ modFile.AddReplace( ++ "golang.org/x/crypto", ++ "", ++ xCryptoNewModPath(), ++ "", ++ ) ++ modFile.Cleanup() ++ afterData, err := modFile.Format() ++ if err != nil { ++ return fmt.Errorf("failed to format (marshal) go.mod file: %v", err) ++ } ++ f, err := os.CreateTemp("", "xcrypto-replacement-go-*.mod") ++ if err != nil { ++ return fmt.Errorf("failed to create temp go.mod file: %v", err) ++ } ++ base.AtExit(func() { ++ // Best effort cleanup. ++ if err := os.Remove(f.Name()); err != nil { ++ base.Errorf("go: failed to remove temp go.mod file %q with x/crypto replacement: %v", f.Name(), err) ++ } ++ }) ++ if _, err := f.Write(afterData); err != nil { ++ return fmt.Errorf("failed to write temp go.mod file data: %v", err) ++ } ++ cfg.ModFile = f.Name() ++ xCryptoSwap = true ++ preXCryptoSwapModFile = oldFilePath ++ return nil ++} ++ ++func modFileUsesXCrypto(m *modfile.File) bool { ++ for _, r := range m.Require { ++ if r.Mod.Path == "golang.org/x/crypto" { ++ return true ++ } ++ } ++ return false ++} ++ ++// toolsetOverrideModuleDir returns the path to a directory in GOROOT where copies of modules are ++// kept that may be used when building a program with that particular toolset. It is similar to a ++// vendor directory, but only contains the modules, no modules.txt. ++func toolsetOverrideModuleDir() string { ++ return filepath.Join(cfg.BuildContext.GOROOT, "ms_mod") ++} ++ ++// xCryptoNewModPath returns the module path that x/crypto should be replaced with. ++func xCryptoNewModPath() string { ++ return filepath.Join(toolsetOverrideModuleDir(), "golang.org", "x", "crypto") ++} ++ ++func toolsetOverridePackage(path string) (dir string, vendorDir string, ok bool) { ++ if !HasModRoot() || !xCryptoSwap { ++ return "", "", false ++ } ++ vendorDir = toolsetOverrideModuleDir() ++ // Before checking the main vendor directory, check the toolset's override vendor directory. ++ // This is where the x/crypto fork is located that needs to be swapped in. ++ dir, haveGoFiles, _ := dirInModule(path, "", vendorDir, false) ++ if !haveGoFiles { ++ return "", "", false ++ } ++ return dir, vendorDir, true ++} +diff --git a/src/cmd/go/testdata/script/modswap_basics.txt b/src/cmd/go/testdata/script/modswap_basics.txt +new file mode 100644 +index 00000000000000..0f28da05789d1c +--- /dev/null ++++ b/src/cmd/go/testdata/script/modswap_basics.txt +@@ -0,0 +1,65 @@ ++# Test the basics of the x/crypto swap. ++ ++[!net:golang.org] skip ++[!git] skip ++ ++env GO111MODULE=on ++env GOPROXY=direct ++env GOSUMDB=off ++ ++go mod tidy ++ ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++ ++# When vendoring isn't involved, the replacement path is used. ++go list -mod= -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++go list -mod=mod -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++go list -mod=readonly -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++ ++# Make sure the build works other than vendor mode. ++go build -mod= . ++go build -mod=mod . ++go build -mod=readonly . ++ ++# Vendor mode shouldn't work because we haven't vendored yet. ++! go list -mod=vendor -deps -f '{{.Dir}}' ++stderr 'inconsistent vendoring' ++! go build -mod=vendor . ++ ++# We must not do the swap when vendoring or else the replacement gets baked in. ++env GOEXPERIMENT= ++go mod vendor ++ ++# Now that vendoring is involved, still use the replacement path. ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++go list -mod= -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++go list -mod=mod -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++go list -mod=readonly -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++go list -mod=vendor -deps -f '{{.Dir}}' ++stdout $GOROOT/ms_mod/golang.org/x/crypto ++ ++# Make sure the build works and is always the same. ++go build -mod= -o no_mod.out . ++go build -mod=mod -o mod_mod.out . ++go build -mod=readonly -o readonly_mod.out . ++go build -mod=vendor -o vendor_mod.out . ++ ++cmp mod_mod.out no_mod.out ++cmp mod_mod.out readonly_mod.out ++cmp mod_mod.out vendor_mod.out ++ ++-- go.mod -- ++module example.com/modswap ++ ++require golang.org/x/crypto v0.12.0 ++ ++-- imports.go -- ++package replace ++ ++import _ "golang.org/x/crypto/sha3" +diff --git a/src/cmd/go/testdata/script/modswap_compatible_vendoring.txt b/src/cmd/go/testdata/script/modswap_compatible_vendoring.txt +new file mode 100644 +index 00000000000000..9505055005ac9b +--- /dev/null ++++ b/src/cmd/go/testdata/script/modswap_compatible_vendoring.txt +@@ -0,0 +1,40 @@ ++# Test that if we vendor x/crypto while swapping is enabled, the replacement isn't applied and we ++# vendor "normal" x/crypto. ++ ++[!net:golang.org] skip ++[!git] skip ++[!GOOS:linux] skip ++[!GOARCH:amd64] skip ++[!cgo] skip ++ ++env GO111MODULE=on ++env GOPROXY=direct ++env GOSUMDB=off ++ ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++go mod tidy ++go mod vendor ++ ++env GOEXPERIMENT= ++# If we got it wrong and the replacement was applied during "go mod vendor", ++# this will fail due to inconsistent vendoring. ++go test . ++ ++-- go.mod -- ++module example.com/modswap ++ ++require golang.org/x/crypto v0.12.0 ++ ++-- modswap_test.go -- ++package modswap ++ ++import ( ++ "testing" ++ ++ "golang.org/x/crypto/sha3" ++) ++ ++func TestCallSha3_256(t *testing.T) { ++ hash := sha3.New256() ++ hash.Sum([]byte("some data to hash")) ++} +diff --git a/src/cmd/go/testdata/script/modswap_nocrypto.txt b/src/cmd/go/testdata/script/modswap_nocrypto.txt +new file mode 100644 +index 00000000000000..978ef92a7e1700 +--- /dev/null ++++ b/src/cmd/go/testdata/script/modswap_nocrypto.txt +@@ -0,0 +1,28 @@ ++# Test that if there is no use of x/crypto, the swap feature doesn't change the output assembly. ++ ++env GO111MODULE=on ++ ++env GOEXPERIMENT= ++go build -gcflags=-S . ++cp stderr ordinary.out ++ ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++go build -gcflags=-S . ++cp stderr swapped.out ++ ++# We can't directly compare compiled output: the experiment list is embedded ++# in the binary, making it unavoidably different. ++# So, check for the swap by comparing assembly instead. ++cmp ordinary.out swapped.out ++ ++-- go.mod -- ++module example.com/hello ++ ++-- main.go -- ++package replace ++ ++import "fmt" ++ ++func main() { ++ fmt.Println("Hello, world!") ++} +diff --git a/src/cmd/go/testdata/script/modswap_reject_work.txt b/src/cmd/go/testdata/script/modswap_reject_work.txt +new file mode 100644 +index 00000000000000..dc29c609a5c012 +--- /dev/null ++++ b/src/cmd/go/testdata/script/modswap_reject_work.txt +@@ -0,0 +1,22 @@ ++# x/crypto replacement doesn't work with go.work files. Check that it is properly rejected. ++ ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++! go build . ++stderr 'go: failed to initialize x/crypto replacement: unable to replace in workspace mode' ++ ++-- go.work -- ++go 1.22 ++ ++use . ++ ++-- go.mod -- ++module example.com/hello ++ ++-- main.go -- ++package replace ++ ++import "fmt" ++ ++func main() { ++ fmt.Println("Hello, world!") ++} +diff --git a/src/cmd/go/testdata/script/modswap_test_openssl.txt b/src/cmd/go/testdata/script/modswap_test_openssl.txt +new file mode 100644 +index 00000000000000..ee762ee8e36487 +--- /dev/null ++++ b/src/cmd/go/testdata/script/modswap_test_openssl.txt +@@ -0,0 +1,43 @@ ++# Test that "go test" works with the x/crypto swap feature. ++ ++[!net:golang.org] skip ++[!git] skip ++[!GOOS:linux] skip ++[!GOARCH:amd64] skip ++[!cgo] skip ++ ++env GO111MODULE=on ++env GOPROXY=direct ++env GOSUMDB=off ++ ++go mod tidy ++ ++go test . ++ ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++go test . ++ ++-- go.mod -- ++module example.com/modswap ++ ++require golang.org/x/crypto v0.12.0 ++ ++-- modswap_test.go -- ++package modswap ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++ ++ "golang.org/x/crypto/sha3" ++) ++ ++func TestKnownValueSha3_256(t *testing.T) { ++ hash := sha3.New256() ++ r := hash.Sum([]byte("some data to hash")) ++ want, _ := hex.DecodeString("736f6d65206461746120746f2068617368a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a") ++ if !bytes.Equal(r, want) { ++ t.Errorf("want %x, got %x", want, r) ++ } ++} +diff --git a/src/cmd/go/testdata/script/modswap_uses_openssl.txt b/src/cmd/go/testdata/script/modswap_uses_openssl.txt +new file mode 100644 +index 00000000000000..03cbd2ca4a81ac +--- /dev/null ++++ b/src/cmd/go/testdata/script/modswap_uses_openssl.txt +@@ -0,0 +1,60 @@ ++# When x/crypto is swapped (and only then!), the app should use the OpenSSL backend. ++ ++[!net:golang.org] skip ++[!git] skip ++[!GOOS:linux] skip ++[!GOARCH:amd64] skip ++[!cgo] skip ++ ++env GO111MODULE=on ++env GOPROXY=direct ++env GOSUMDB=off ++ ++go mod tidy ++ ++env GOEXPERIMENT= ++go test -run=^TestStandardHasher$ . ++env GOEXPERIMENT=systemcrypto ++go test -run=^TestStandardHasher$ . ++env GOEXPERIMENT=systemcrypto,xcryptobackendswap ++go test -run=^TestOpenSSLHasher$ . ++ ++-- go.mod -- ++module example.com/modswap ++ ++require golang.org/x/crypto v0.12.0 ++ ++-- modswap_test.go -- ++package modswap ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "reflect" ++ "testing" ++ ++ "golang.org/x/crypto/sha3" ++) ++ ++func TestStandardHasher(t *testing.T) { ++ testHasher(t, "*sha3.state") ++} ++ ++func TestOpenSSLHasher(t *testing.T) { ++ testHasher(t, "*openssl.sha3_256Hash") ++} ++ ++func testHasher(t *testing.T, wantTypeName string) { ++ hash := sha3.New256() ++ // Test that it functions correctly. ++ r := hash.Sum([]byte("some data to hash")) ++ want, _ := hex.DecodeString("736f6d65206461746120746f2068617368a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a") ++ if !bytes.Equal(r, want) { ++ t.Errorf("want %x, got %x", want, r) ++ } ++ // Test that the hasher is from the expected backend. ++ typeName := reflect.TypeOf(hash).String() ++ if typeName != wantTypeName { ++ t.Errorf("want %q, got %q", wantTypeName, typeName) ++ } ++} +diff --git a/src/internal/goexperiment/exp_xcryptobackendswap_off.go b/src/internal/goexperiment/exp_xcryptobackendswap_off.go +new file mode 100644 +index 00000000000000..8fceaa28b7e6f0 +--- /dev/null ++++ b/src/internal/goexperiment/exp_xcryptobackendswap_off.go +@@ -0,0 +1,9 @@ ++// Code generated by mkconsts.go. DO NOT EDIT. ++ ++//go:build !goexperiment.xcryptobackendswap ++// +build !goexperiment.xcryptobackendswap ++ ++package goexperiment ++ ++const XCryptoBackendSwap = false ++const XCryptoBackendSwapInt = 0 +diff --git a/src/internal/goexperiment/exp_xcryptobackendswap_on.go b/src/internal/goexperiment/exp_xcryptobackendswap_on.go +new file mode 100644 +index 00000000000000..77018702a444be +--- /dev/null ++++ b/src/internal/goexperiment/exp_xcryptobackendswap_on.go +@@ -0,0 +1,9 @@ ++// Code generated by mkconsts.go. DO NOT EDIT. ++ ++//go:build goexperiment.xcryptobackendswap ++// +build goexperiment.xcryptobackendswap ++ ++package goexperiment ++ ++const XCryptoBackendSwap = true ++const XCryptoBackendSwapInt = 1 +diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go +index d4134300ca0269..9f4058556cb751 100644 +--- a/src/internal/goexperiment/flags.go ++++ b/src/internal/goexperiment/flags.go +@@ -85,6 +85,12 @@ type Flags struct { + // GOEXPERIMENT=opensslcrypto,allowcryptofallback must be used to succeed. + AllowCryptoFallback bool + ++ // XCryptoBackendSwap enables detection of the golang.org/x/crypto module ++ // and automatically replaces it with an x/crypto module maintained in the ++ // Microsoft Go fork that implements the same API but with the chosen crypto ++ // backend. ++ XCryptoBackendSwap bool ++ + // Regabi is split into several sub-experiments that can be + // enabled individually. Not all combinations work. + // The "regabi" GOEXPERIMENT is an alias for all "working" diff --git a/patches/0010-Add-modified-x-crypto.patch b/patches/0010-Add-modified-x-crypto.patch new file mode 100644 index 00000000000..6861099b7e0 --- /dev/null +++ b/patches/0010-Add-modified-x-crypto.patch @@ -0,0 +1,107284 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Davis Goodin +Date: Thu, 14 Sep 2023 16:29:00 -0700 +Subject: [PATCH] Add modified x/crypto + +Uses xcryptobackendgen to generate a modified copy of x/crypto that uses +the crypto backends defined in this toolset. + +From the microsoft/go repository root: + + xcryptobackendgen \ + -fork \ + -backend go/src/crypto/internal/backend \ + -out go/ms_mod/golang.org/x/crypto +--- + ms_mod/golang.org/x/crypto/.gitattributes | 10 + + ms_mod/golang.org/x/crypto/.gitignore | 2 + + ms_mod/golang.org/x/crypto/CONTRIBUTING.md | 26 + + ms_mod/golang.org/x/crypto/LICENSE | 27 + + ms_mod/golang.org/x/crypto/PATENTS | 22 + + ms_mod/golang.org/x/crypto/README.md | 23 + + ms_mod/golang.org/x/crypto/acme/acme.go | 818 ++++ + ms_mod/golang.org/x/crypto/acme/acme_test.go | 855 ++++ + .../x/crypto/acme/autocert/autocert.go | 1198 ++++++ + .../x/crypto/acme/autocert/autocert_test.go | 996 +++++ + .../x/crypto/acme/autocert/cache.go | 135 + + .../x/crypto/acme/autocert/cache_test.go | 66 + + .../x/crypto/acme/autocert/example_test.go | 35 + + .../acme/autocert/internal/acmetest/ca.go | 796 ++++ + .../x/crypto/acme/autocert/listener.go | 155 + + .../x/crypto/acme/autocert/renewal.go | 156 + + .../x/crypto/acme/autocert/renewal_test.go | 269 ++ + ms_mod/golang.org/x/crypto/acme/http.go | 325 ++ + ms_mod/golang.org/x/crypto/acme/http_test.go | 255 ++ + .../crypto/acme/internal/acmeprobe/prober.go | 433 ++ + ms_mod/golang.org/x/crypto/acme/jws.go | 257 ++ + ms_mod/golang.org/x/crypto/acme/jws_test.go | 550 +++ + ms_mod/golang.org/x/crypto/acme/rfc8555.go | 476 ++ + .../golang.org/x/crypto/acme/rfc8555_test.go | 1017 +++++ + ms_mod/golang.org/x/crypto/acme/types.go | 614 +++ + ms_mod/golang.org/x/crypto/acme/types_test.go | 219 + + .../golang.org/x/crypto/acme/version_go112.go | 28 + + ms_mod/golang.org/x/crypto/argon2/argon2.go | 283 ++ + .../golang.org/x/crypto/argon2/argon2_test.go | 233 + + ms_mod/golang.org/x/crypto/argon2/blake2b.go | 53 + + .../x/crypto/argon2/blamka_amd64.go | 61 + + .../golang.org/x/crypto/argon2/blamka_amd64.s | 244 ++ + .../x/crypto/argon2/blamka_generic.go | 163 + + .../golang.org/x/crypto/argon2/blamka_ref.go | 16 + + ms_mod/golang.org/x/crypto/bcrypt/base64.go | 35 + + ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go | 304 ++ + .../golang.org/x/crypto/bcrypt/bcrypt_test.go | 250 ++ + ms_mod/golang.org/x/crypto/blake2b/blake2b.go | 291 ++ + .../x/crypto/blake2b/blake2bAVX2_amd64.go | 38 + + .../x/crypto/blake2b/blake2bAVX2_amd64.s | 745 ++++ + .../x/crypto/blake2b/blake2b_amd64.go | 25 + + .../x/crypto/blake2b/blake2b_amd64.s | 279 ++ + .../x/crypto/blake2b/blake2b_generic.go | 182 + + .../x/crypto/blake2b/blake2b_ref.go | 12 + + .../x/crypto/blake2b/blake2b_test.go | 847 ++++ + ms_mod/golang.org/x/crypto/blake2b/blake2x.go | 177 + + .../golang.org/x/crypto/blake2b/register.go | 33 + + ms_mod/golang.org/x/crypto/blake2s/blake2s.go | 246 ++ + .../x/crypto/blake2s/blake2s_386.go | 33 + + .../golang.org/x/crypto/blake2s/blake2s_386.s | 430 ++ + .../x/crypto/blake2s/blake2s_amd64.go | 38 + + .../x/crypto/blake2s/blake2s_amd64.s | 433 ++ + .../x/crypto/blake2s/blake2s_generic.go | 178 + + .../x/crypto/blake2s/blake2s_ref.go | 18 + + .../x/crypto/blake2s/blake2s_test.go | 1050 +++++ + ms_mod/golang.org/x/crypto/blake2s/blake2x.go | 178 + + .../golang.org/x/crypto/blake2s/register.go | 22 + + ms_mod/golang.org/x/crypto/blowfish/block.go | 159 + + .../x/crypto/blowfish/blowfish_test.go | 274 ++ + ms_mod/golang.org/x/crypto/blowfish/cipher.go | 99 + + ms_mod/golang.org/x/crypto/blowfish/const.go | 199 + + ms_mod/golang.org/x/crypto/bn256/bn256.go | 429 ++ + .../golang.org/x/crypto/bn256/bn256_test.go | 304 ++ + ms_mod/golang.org/x/crypto/bn256/constants.go | 44 + + ms_mod/golang.org/x/crypto/bn256/curve.go | 287 ++ + .../golang.org/x/crypto/bn256/example_test.go | 43 + + ms_mod/golang.org/x/crypto/bn256/gfp12.go | 200 + + ms_mod/golang.org/x/crypto/bn256/gfp2.go | 219 + + ms_mod/golang.org/x/crypto/bn256/gfp6.go | 296 ++ + ms_mod/golang.org/x/crypto/bn256/optate.go | 395 ++ + ms_mod/golang.org/x/crypto/bn256/twist.go | 258 ++ + ms_mod/golang.org/x/crypto/cast5/cast5.go | 536 +++ + .../golang.org/x/crypto/cast5/cast5_test.go | 106 + + .../x/crypto/chacha20/chacha_arm64.go | 17 + + .../x/crypto/chacha20/chacha_arm64.s | 308 ++ + .../x/crypto/chacha20/chacha_generic.go | 398 ++ + .../x/crypto/chacha20/chacha_noasm.go | 14 + + .../x/crypto/chacha20/chacha_ppc64le.go | 17 + + .../x/crypto/chacha20/chacha_ppc64le.s | 450 ++ + .../x/crypto/chacha20/chacha_s390x.go | 28 + + .../x/crypto/chacha20/chacha_s390x.s | 225 + + .../x/crypto/chacha20/chacha_test.go | 274 ++ + .../x/crypto/chacha20/vectors_test.go | 511 +++ + ms_mod/golang.org/x/crypto/chacha20/xor.go | 42 + + .../chacha20poly1305/chacha20poly1305.go | 98 + + .../chacha20poly1305_amd64.go | 87 + + .../chacha20poly1305/chacha20poly1305_amd64.s | 2696 ++++++++++++ + .../chacha20poly1305_generic.go | 81 + + .../chacha20poly1305_noasm.go | 16 + + .../chacha20poly1305/chacha20poly1305_test.go | 268 ++ + .../chacha20poly1305_vectors_test.go | 727 ++++ + .../chacha20poly1305/xchacha20poly1305.go | 86 + + ms_mod/golang.org/x/crypto/codereview.cfg | 1 + + ms_mod/golang.org/x/crypto/cryptobyte/asn1.go | 824 ++++ + .../x/crypto/cryptobyte/asn1/asn1.go | 46 + + .../x/crypto/cryptobyte/asn1_test.go | 435 ++ + .../golang.org/x/crypto/cryptobyte/builder.go | 345 ++ + .../x/crypto/cryptobyte/cryptobyte_test.go | 536 +++ + .../x/crypto/cryptobyte/example_test.go | 154 + + .../golang.org/x/crypto/cryptobyte/string.go | 172 + + .../x/crypto/curve25519/curve25519.go | 59 + + .../x/crypto/curve25519/curve25519_compat.go | 105 + + .../x/crypto/curve25519/curve25519_go120.go | 46 + + .../x/crypto/curve25519/curve25519_test.go | 142 + + .../x/crypto/curve25519/internal/field/README | 7 + + .../internal/field/_asm/fe_amd64_asm.go | 298 ++ + .../curve25519/internal/field/_asm/go.mod | 10 + + .../curve25519/internal/field/_asm/go.sum | 34 + + .../x/crypto/curve25519/internal/field/fe.go | 416 ++ + .../internal/field/fe_alias_test.go | 126 + + .../curve25519/internal/field/fe_amd64.go | 16 + + .../curve25519/internal/field/fe_amd64.s | 379 ++ + .../internal/field/fe_amd64_noasm.go | 12 + + .../curve25519/internal/field/fe_arm64.go | 16 + + .../curve25519/internal/field/fe_arm64.s | 43 + + .../internal/field/fe_arm64_noasm.go | 12 + + .../internal/field/fe_bench_test.go | 36 + + .../curve25519/internal/field/fe_generic.go | 264 ++ + .../curve25519/internal/field/fe_test.go | 558 +++ + .../curve25519/internal/field/sync.checkpoint | 1 + + .../crypto/curve25519/internal/field/sync.sh | 19 + + .../x/crypto/curve25519/vectors_test.go | 105 + + ms_mod/golang.org/x/crypto/ed25519/ed25519.go | 71 + + .../x/crypto/ed25519/ed25519_test.go | 22 + + ms_mod/golang.org/x/crypto/go.mod | 11 + + ms_mod/golang.org/x/crypto/go.sum | 41 + + .../golang.org/x/crypto/hkdf/example_test.go | 56 + + ms_mod/golang.org/x/crypto/hkdf/hkdf.go | 95 + + ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go | 449 ++ + .../x/crypto/internal/alias/alias.go | 32 + + .../x/crypto/internal/alias/alias_purego.go | 35 + + .../x/crypto/internal/alias/alias_test.go | 46 + + .../x/crypto/internal/backend/boring_linux.go | 95 + + .../x/crypto/internal/backend/cng_windows.go | 77 + + .../x/crypto/internal/backend/nobackend.go | 49 + + .../crypto/internal/backend/openssl_linux.go | 69 + + .../x/crypto/internal/poly1305/bits_compat.go | 40 + + .../x/crypto/internal/poly1305/bits_go1.13.go | 22 + + .../x/crypto/internal/poly1305/mac_noasm.go | 10 + + .../x/crypto/internal/poly1305/poly1305.go | 99 + + .../crypto/internal/poly1305/poly1305_test.go | 276 ++ + .../x/crypto/internal/poly1305/sum_amd64.go | 48 + + .../x/crypto/internal/poly1305/sum_amd64.s | 109 + + .../x/crypto/internal/poly1305/sum_generic.go | 309 ++ + .../x/crypto/internal/poly1305/sum_ppc64le.go | 48 + + .../x/crypto/internal/poly1305/sum_ppc64le.s | 182 + + .../x/crypto/internal/poly1305/sum_s390x.go | 77 + + .../x/crypto/internal/poly1305/sum_s390x.s | 504 +++ + .../crypto/internal/poly1305/vectors_test.go | 3000 +++++++++++++ + .../x/crypto/internal/testenv/exec.go | 120 + + .../internal/testenv/testenv_notunix.go | 15 + + .../x/crypto/internal/testenv/testenv_unix.go | 15 + + .../x/crypto/internal/wycheproof/README.md | 12 + + .../x/crypto/internal/wycheproof/aead_test.go | 176 + + .../internal/wycheproof/aes_cbc_test.go | 127 + + .../x/crypto/internal/wycheproof/boring.go | 9 + + .../x/crypto/internal/wycheproof/dsa_test.go | 123 + + .../internal/wycheproof/ecdh_stdlib_test.go | 142 + + .../x/crypto/internal/wycheproof/ecdh_test.go | 163 + + .../crypto/internal/wycheproof/ecdsa_test.go | 105 + + .../crypto/internal/wycheproof/eddsa_test.go | 101 + + .../x/crypto/internal/wycheproof/hkdf_test.go | 111 + + .../x/crypto/internal/wycheproof/hmac_test.go | 105 + + .../internal/wycheproof/internal/dsa/dsa.go | 33 + + .../x/crypto/internal/wycheproof/notboring.go | 9 + + .../wycheproof/rsa_oaep_decrypt_test.go | 149 + + .../internal/wycheproof/rsa_pss_test.go | 169 + + .../internal/wycheproof/rsa_signature_test.go | 123 + + .../internal/wycheproof/wycheproof_test.go | 141 + + .../golang.org/x/crypto/md4/example_test.go | 20 + + ms_mod/golang.org/x/crypto/md4/md4.go | 122 + + ms_mod/golang.org/x/crypto/md4/md4_test.go | 71 + + ms_mod/golang.org/x/crypto/md4/md4block.go | 91 + + ms_mod/golang.org/x/crypto/nacl/auth/auth.go | 58 + + .../x/crypto/nacl/auth/auth_test.go | 172 + + .../x/crypto/nacl/auth/example_test.go | 36 + + ms_mod/golang.org/x/crypto/nacl/box/box.go | 182 + + .../golang.org/x/crypto/nacl/box/box_test.go | 181 + + .../x/crypto/nacl/box/example_test.go | 95 + + .../x/crypto/nacl/secretbox/example_test.go | 53 + + .../x/crypto/nacl/secretbox/secretbox.go | 173 + + .../x/crypto/nacl/secretbox/secretbox_test.go | 154 + + ms_mod/golang.org/x/crypto/nacl/sign/sign.go | 90 + + .../x/crypto/nacl/sign/sign_test.go | 74 + + ms_mod/golang.org/x/crypto/ocsp/ocsp.go | 792 ++++ + ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go | 746 ++++ + .../x/crypto/openpgp/armor/armor.go | 232 + + .../x/crypto/openpgp/armor/armor_test.go | 95 + + .../x/crypto/openpgp/armor/encode.go | 161 + + .../x/crypto/openpgp/canonical_text.go | 59 + + .../x/crypto/openpgp/canonical_text_test.go | 52 + + .../x/crypto/openpgp/clearsign/clearsign.go | 424 ++ + .../openpgp/clearsign/clearsign_test.go | 398 ++ + .../x/crypto/openpgp/elgamal/elgamal.go | 130 + + .../x/crypto/openpgp/elgamal/elgamal_test.go | 64 + + .../x/crypto/openpgp/errors/errors.go | 78 + + ms_mod/golang.org/x/crypto/openpgp/keys.go | 693 +++ + .../x/crypto/openpgp/keys_data_test.go | 200 + + .../golang.org/x/crypto/openpgp/keys_test.go | 495 +++ + .../x/crypto/openpgp/packet/compressed.go | 123 + + .../crypto/openpgp/packet/compressed_test.go | 40 + + .../x/crypto/openpgp/packet/config.go | 91 + + .../x/crypto/openpgp/packet/encrypted_key.go | 208 + + .../openpgp/packet/encrypted_key_test.go | 220 + + .../x/crypto/openpgp/packet/literal.go | 89 + + .../x/crypto/openpgp/packet/ocfb.go | 143 + + .../x/crypto/openpgp/packet/ocfb_test.go | 46 + + .../openpgp/packet/one_pass_signature.go | 73 + + .../x/crypto/openpgp/packet/opaque.go | 161 + + .../x/crypto/openpgp/packet/opaque_test.go | 67 + + .../x/crypto/openpgp/packet/packet.go | 590 +++ + .../x/crypto/openpgp/packet/packet_test.go | 290 ++ + .../x/crypto/openpgp/packet/private_key.go | 384 ++ + .../crypto/openpgp/packet/private_key_test.go | 249 ++ + .../x/crypto/openpgp/packet/public_key.go | 753 ++++ + .../crypto/openpgp/packet/public_key_test.go | 228 + + .../x/crypto/openpgp/packet/public_key_v3.go | 279 ++ + .../openpgp/packet/public_key_v3_test.go | 82 + + .../x/crypto/openpgp/packet/reader.go | 76 + + .../x/crypto/openpgp/packet/signature.go | 731 ++++ + .../x/crypto/openpgp/packet/signature_test.go | 78 + + .../x/crypto/openpgp/packet/signature_v3.go | 146 + + .../openpgp/packet/signature_v3_test.go | 96 + + .../openpgp/packet/symmetric_key_encrypted.go | 155 + + .../packet/symmetric_key_encrypted_test.go | 116 + + .../openpgp/packet/symmetrically_encrypted.go | 290 ++ + .../packet/symmetrically_encrypted_test.go | 122 + + .../x/crypto/openpgp/packet/userattribute.go | 90 + + .../openpgp/packet/userattribute_test.go | 109 + + .../x/crypto/openpgp/packet/userid.go | 159 + + .../x/crypto/openpgp/packet/userid_test.go | 87 + + ms_mod/golang.org/x/crypto/openpgp/read.go | 448 ++ + .../golang.org/x/crypto/openpgp/read_test.go | 612 +++ + ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go | 279 ++ + .../x/crypto/openpgp/s2k/s2k_test.go | 137 + + ms_mod/golang.org/x/crypto/openpgp/write.go | 418 ++ + .../golang.org/x/crypto/openpgp/write_test.go | 361 ++ + .../x/crypto/otr/libotr_test_helper.c | 197 + + ms_mod/golang.org/x/crypto/otr/otr.go | 1419 ++++++ + ms_mod/golang.org/x/crypto/otr/otr_test.go | 470 ++ + ms_mod/golang.org/x/crypto/otr/smp.go | 572 +++ + ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go | 77 + + .../golang.org/x/crypto/pbkdf2/pbkdf2_test.go | 176 + + .../golang.org/x/crypto/pkcs12/bmp-string.go | 50 + + .../x/crypto/pkcs12/bmp-string_test.go | 63 + + ms_mod/golang.org/x/crypto/pkcs12/crypto.go | 131 + + .../golang.org/x/crypto/pkcs12/crypto_test.go | 125 + + ms_mod/golang.org/x/crypto/pkcs12/errors.go | 23 + + .../crypto/pkcs12/internal/rc2/bench_test.go | 27 + + .../x/crypto/pkcs12/internal/rc2/rc2.go | 268 ++ + .../x/crypto/pkcs12/internal/rc2/rc2_test.go | 92 + + ms_mod/golang.org/x/crypto/pkcs12/mac.go | 45 + + ms_mod/golang.org/x/crypto/pkcs12/mac_test.go | 42 + + ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go | 170 + + .../golang.org/x/crypto/pkcs12/pbkdf_test.go | 34 + + ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go | 360 ++ + .../golang.org/x/crypto/pkcs12/pkcs12_test.go | 141 + + ms_mod/golang.org/x/crypto/pkcs12/safebags.go | 57 + + .../x/crypto/poly1305/poly1305_compat.go | 91 + + .../x/crypto/ripemd160/ripemd160.go | 124 + + .../x/crypto/ripemd160/ripemd160_test.go | 72 + + .../x/crypto/ripemd160/ripemd160block.go | 165 + + .../x/crypto/salsa20/salsa/hsalsa20.go | 146 + + .../x/crypto/salsa20/salsa/salsa208.go | 201 + + .../x/crypto/salsa20/salsa/salsa20_amd64.go | 24 + + .../x/crypto/salsa20/salsa/salsa20_amd64.s | 881 ++++ + .../salsa20/salsa/salsa20_amd64_test.go | 32 + + .../x/crypto/salsa20/salsa/salsa20_noasm.go | 15 + + .../x/crypto/salsa20/salsa/salsa20_ref.go | 233 + + .../x/crypto/salsa20/salsa/salsa_test.go | 54 + + ms_mod/golang.org/x/crypto/salsa20/salsa20.go | 58 + + .../x/crypto/salsa20/salsa20_test.go | 139 + + .../x/crypto/scrypt/example_test.go | 26 + + ms_mod/golang.org/x/crypto/scrypt/scrypt.go | 212 + + .../golang.org/x/crypto/scrypt/scrypt_test.go | 162 + + ms_mod/golang.org/x/crypto/sha3/doc.go | 62 + + ms_mod/golang.org/x/crypto/sha3/hashes.go | 116 + + .../x/crypto/sha3/hashes_generic.go | 28 + + ms_mod/golang.org/x/crypto/sha3/keccakf.go | 415 ++ + .../golang.org/x/crypto/sha3/keccakf_amd64.go | 14 + + .../golang.org/x/crypto/sha3/keccakf_amd64.s | 391 ++ + ms_mod/golang.org/x/crypto/sha3/register.go | 19 + + ms_mod/golang.org/x/crypto/sha3/sha3.go | 193 + + ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go | 287 ++ + ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s | 34 + + ms_mod/golang.org/x/crypto/sha3/sha3_test.go | 490 +++ + ms_mod/golang.org/x/crypto/sha3/shake.go | 173 + + .../golang.org/x/crypto/sha3/shake_generic.go | 20 + + .../sha3/testdata/keccakKats.json.deflate | Bin 0 -> 540828 bytes + ms_mod/golang.org/x/crypto/sha3/xor.go | 24 + + .../golang.org/x/crypto/sha3/xor_generic.go | 28 + + .../golang.org/x/crypto/sha3/xor_unaligned.go | 68 + + .../golang.org/x/crypto/ssh/agent/client.go | 849 ++++ + .../x/crypto/ssh/agent/client_test.go | 537 +++ + .../x/crypto/ssh/agent/example_test.go | 41 + + .../golang.org/x/crypto/ssh/agent/forward.go | 103 + + .../golang.org/x/crypto/ssh/agent/keyring.go | 241 ++ + .../x/crypto/ssh/agent/keyring_test.go | 76 + + .../golang.org/x/crypto/ssh/agent/server.go | 570 +++ + .../x/crypto/ssh/agent/server_test.go | 262 ++ + .../x/crypto/ssh/agent/testdata_test.go | 64 + + .../golang.org/x/crypto/ssh/benchmark_test.go | 127 + + ms_mod/golang.org/x/crypto/ssh/buffer.go | 97 + + ms_mod/golang.org/x/crypto/ssh/buffer_test.go | 87 + + ms_mod/golang.org/x/crypto/ssh/certs.go | 589 +++ + ms_mod/golang.org/x/crypto/ssh/certs_test.go | 320 ++ + ms_mod/golang.org/x/crypto/ssh/channel.go | 633 +++ + ms_mod/golang.org/x/crypto/ssh/cipher.go | 789 ++++ + ms_mod/golang.org/x/crypto/ssh/cipher_test.go | 231 + + ms_mod/golang.org/x/crypto/ssh/client.go | 282 ++ + ms_mod/golang.org/x/crypto/ssh/client_auth.go | 725 ++++ + .../x/crypto/ssh/client_auth_test.go | 1078 +++++ + ms_mod/golang.org/x/crypto/ssh/client_test.go | 346 ++ + ms_mod/golang.org/x/crypto/ssh/common.go | 471 ++ + ms_mod/golang.org/x/crypto/ssh/common_test.go | 176 + + ms_mod/golang.org/x/crypto/ssh/connection.go | 143 + + ms_mod/golang.org/x/crypto/ssh/doc.go | 22 + + .../golang.org/x/crypto/ssh/example_test.go | 320 ++ + ms_mod/golang.org/x/crypto/ssh/handshake.go | 735 ++++ + .../golang.org/x/crypto/ssh/handshake_test.go | 622 +++ + .../ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go | 93 + + .../bcrypt_pbkdf/bcrypt_pbkdf_test.go | 97 + + ms_mod/golang.org/x/crypto/ssh/kex.go | 786 ++++ + ms_mod/golang.org/x/crypto/ssh/kex_test.go | 106 + + ms_mod/golang.org/x/crypto/ssh/keys.go | 1447 +++++++ + ms_mod/golang.org/x/crypto/ssh/keys_test.go | 618 +++ + .../x/crypto/ssh/knownhosts/knownhosts.go | 540 +++ + .../crypto/ssh/knownhosts/knownhosts_test.go | 356 ++ + ms_mod/golang.org/x/crypto/ssh/mac.go | 68 + + .../golang.org/x/crypto/ssh/mempipe_test.go | 110 + + ms_mod/golang.org/x/crypto/ssh/messages.go | 877 ++++ + .../golang.org/x/crypto/ssh/messages_test.go | 288 ++ + ms_mod/golang.org/x/crypto/ssh/mux.go | 351 ++ + ms_mod/golang.org/x/crypto/ssh/mux_test.go | 761 ++++ + ms_mod/golang.org/x/crypto/ssh/server.go | 774 ++++ + ms_mod/golang.org/x/crypto/ssh/session.go | 647 +++ + .../golang.org/x/crypto/ssh/session_test.go | 845 ++++ + ms_mod/golang.org/x/crypto/ssh/ssh_gss.go | 139 + + .../golang.org/x/crypto/ssh/ssh_gss_test.go | 109 + + ms_mod/golang.org/x/crypto/ssh/streamlocal.go | 116 + + ms_mod/golang.org/x/crypto/ssh/tcpip.go | 474 ++ + ms_mod/golang.org/x/crypto/ssh/tcpip_test.go | 20 + + .../x/crypto/ssh/terminal/terminal.go | 76 + + .../x/crypto/ssh/test/agent_unix_test.go | 59 + + .../x/crypto/ssh/test/banner_test.go | 32 + + .../golang.org/x/crypto/ssh/test/cert_test.go | 77 + + .../x/crypto/ssh/test/dial_unix_test.go | 127 + + ms_mod/golang.org/x/crypto/ssh/test/doc.go | 7 + + .../x/crypto/ssh/test/forward_unix_test.go | 198 + + .../x/crypto/ssh/test/multi_auth_test.go | 144 + + .../x/crypto/ssh/test/session_test.go | 455 ++ + .../x/crypto/ssh/test/sshd_test_pw.c | 173 + + .../x/crypto/ssh/test/test_unix_test.go | 364 ++ + .../x/crypto/ssh/test/testdata_test.go | 64 + + .../golang.org/x/crypto/ssh/testdata/doc.go | 8 + + .../golang.org/x/crypto/ssh/testdata/keys.go | 314 ++ + .../golang.org/x/crypto/ssh/testdata_test.go | 63 + + ms_mod/golang.org/x/crypto/ssh/transport.go | 358 ++ + .../golang.org/x/crypto/ssh/transport_test.go | 113 + + ms_mod/golang.org/x/crypto/tea/cipher.go | 116 + + ms_mod/golang.org/x/crypto/tea/tea_test.go | 93 + + ms_mod/golang.org/x/crypto/twofish/twofish.go | 341 ++ + .../x/crypto/twofish/twofish_test.go | 129 + + .../x/crypto/x509roots/fallback/bundle.go | 3827 +++++++++++++++++ + .../x/crypto/x509roots/fallback/fallback.go | 31 + + .../x/crypto/x509roots/fallback/go.mod | 3 + + .../internal/goissue52287/goissue52287.go | 8 + + .../x/crypto/x509roots/gen_fallback_bundle.go | 135 + + .../x/crypto/x509roots/nss/parser.go | 259 ++ + .../x/crypto/x509roots/nss/parser_test.go | 1216 ++++++ + ms_mod/golang.org/x/crypto/xtea/block.go | 66 + + ms_mod/golang.org/x/crypto/xtea/cipher.go | 90 + + ms_mod/golang.org/x/crypto/xtea/xtea_test.go | 229 + + ms_mod/golang.org/x/crypto/xts/xts.go | 164 + + ms_mod/golang.org/x/crypto/xts/xts_test.go | 121 + + 375 files changed, 93859 insertions(+) + create mode 100644 ms_mod/golang.org/x/crypto/.gitattributes + create mode 100644 ms_mod/golang.org/x/crypto/.gitignore + create mode 100644 ms_mod/golang.org/x/crypto/CONTRIBUTING.md + create mode 100644 ms_mod/golang.org/x/crypto/LICENSE + create mode 100644 ms_mod/golang.org/x/crypto/PATENTS + create mode 100644 ms_mod/golang.org/x/crypto/README.md + create mode 100644 ms_mod/golang.org/x/crypto/acme/acme.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/acme_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/autocert.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/cache.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/listener.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/renewal.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/http.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/http_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/jws.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/jws_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/rfc8555.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/rfc8555_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/types.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/types_test.go + create mode 100644 ms_mod/golang.org/x/crypto/acme/version_go112.go + create mode 100644 ms_mod/golang.org/x/crypto/argon2/argon2.go + create mode 100644 ms_mod/golang.org/x/crypto/argon2/argon2_test.go + create mode 100644 ms_mod/golang.org/x/crypto/argon2/blake2b.go + create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_ref.go + create mode 100644 ms_mod/golang.org/x/crypto/bcrypt/base64.go + create mode 100644 ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go + create mode 100644 ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2x.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2b/register.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2x.go + create mode 100644 ms_mod/golang.org/x/crypto/blake2s/register.go + create mode 100644 ms_mod/golang.org/x/crypto/blowfish/block.go + create mode 100644 ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go + create mode 100644 ms_mod/golang.org/x/crypto/blowfish/cipher.go + create mode 100644 ms_mod/golang.org/x/crypto/blowfish/const.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/bn256.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/bn256_test.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/constants.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/curve.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/gfp12.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/gfp2.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/gfp6.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/optate.go + create mode 100644 ms_mod/golang.org/x/crypto/bn256/twist.go + create mode 100644 ms_mod/golang.org/x/crypto/cast5/cast5.go + create mode 100644 ms_mod/golang.org/x/crypto/cast5/cast5_test.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_test.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/vectors_test.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20/xor.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go + create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go + create mode 100644 ms_mod/golang.org/x/crypto/codereview.cfg + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/asn1.go + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/builder.go + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/string.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/README + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh + create mode 100644 ms_mod/golang.org/x/crypto/curve25519/vectors_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ed25519/ed25519.go + create mode 100644 ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go + create mode 100644 ms_mod/golang.org/x/crypto/go.mod + create mode 100644 ms_mod/golang.org/x/crypto/go.sum + create mode 100644 ms_mod/golang.org/x/crypto/hkdf/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/hkdf/hkdf.go + create mode 100644 ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/alias/alias.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/alias/alias_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/nobackend.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s + create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/testenv/exec.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/README.md + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go + create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go + create mode 100644 ms_mod/golang.org/x/crypto/md4/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/md4/md4.go + create mode 100644 ms_mod/golang.org/x/crypto/md4/md4_test.go + create mode 100644 ms_mod/golang.org/x/crypto/md4/md4block.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/auth/auth.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/auth/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/box/box.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/box/box_test.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/box/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/sign/sign.go + create mode 100644 ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ocsp/ocsp.go + create mode 100644 ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/armor/armor.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/armor/encode.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/canonical_text.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/errors/errors.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/keys.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/keys_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/config.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/literal.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/packet.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/reader.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userid.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/read.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/read_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/write.go + create mode 100644 ms_mod/golang.org/x/crypto/openpgp/write_test.go + create mode 100644 ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c + create mode 100644 ms_mod/golang.org/x/crypto/otr/otr.go + create mode 100644 ms_mod/golang.org/x/crypto/otr/otr_test.go + create mode 100644 ms_mod/golang.org/x/crypto/otr/smp.go + create mode 100644 ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go + create mode 100644 ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/crypto.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/errors.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/mac.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/mac_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go + create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/safebags.go + create mode 100644 ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go + create mode 100644 ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go + create mode 100644 ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa20.go + create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go + create mode 100644 ms_mod/golang.org/x/crypto/scrypt/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/scrypt/scrypt.go + create mode 100644 ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/doc.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/hashes.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/hashes_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/keccakf.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s + create mode 100644 ms_mod/golang.org/x/crypto/sha3/register.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s + create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3_test.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/shake.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/shake_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate + create mode 100644 ms_mod/golang.org/x/crypto/sha3/xor.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/xor_generic.go + create mode 100644 ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/client.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/client_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/forward.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/keyring.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/server.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/server_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/benchmark_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/buffer.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/buffer_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/certs.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/certs_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/channel.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/cipher.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/cipher_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/client.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/client_auth.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/client_auth_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/client_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/common.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/common_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/connection.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/doc.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/example_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/handshake.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/handshake_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/kex.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/kex_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/keys.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/keys_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/mac.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/mempipe_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/messages.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/messages_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/mux.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/mux_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/server.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/session.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/session_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/ssh_gss.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/streamlocal.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/tcpip.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/tcpip_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/banner_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/cert_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/doc.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/session_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/testdata/doc.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/testdata/keys.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/testdata_test.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/transport.go + create mode 100644 ms_mod/golang.org/x/crypto/ssh/transport_test.go + create mode 100644 ms_mod/golang.org/x/crypto/tea/cipher.go + create mode 100644 ms_mod/golang.org/x/crypto/tea/tea_test.go + create mode 100644 ms_mod/golang.org/x/crypto/twofish/twofish.go + create mode 100644 ms_mod/golang.org/x/crypto/twofish/twofish_test.go + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/nss/parser.go + create mode 100644 ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go + create mode 100644 ms_mod/golang.org/x/crypto/xtea/block.go + create mode 100644 ms_mod/golang.org/x/crypto/xtea/cipher.go + create mode 100644 ms_mod/golang.org/x/crypto/xtea/xtea_test.go + create mode 100644 ms_mod/golang.org/x/crypto/xts/xts.go + create mode 100644 ms_mod/golang.org/x/crypto/xts/xts_test.go + +diff --git a/ms_mod/golang.org/x/crypto/.gitattributes b/ms_mod/golang.org/x/crypto/.gitattributes +new file mode 100644 +index 00000000000000..d2f212e5da80c5 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/.gitattributes +@@ -0,0 +1,10 @@ ++# Treat all files in this repo as binary, with no git magic updating ++# line endings. Windows users contributing to Go will need to use a ++# modern version of git and editors capable of LF line endings. ++# ++# We'll prevent accidental CRLF line endings from entering the repo ++# via the git-review gofmt checks. ++# ++# See golang.org/issue/9281 ++ ++* -text +diff --git a/ms_mod/golang.org/x/crypto/.gitignore b/ms_mod/golang.org/x/crypto/.gitignore +new file mode 100644 +index 00000000000000..5a9d62efd40246 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/.gitignore +@@ -0,0 +1,2 @@ ++# Add no patterns to .gitignore except for files generated by the build. ++last-change +diff --git a/ms_mod/golang.org/x/crypto/CONTRIBUTING.md b/ms_mod/golang.org/x/crypto/CONTRIBUTING.md +new file mode 100644 +index 00000000000000..d0485e887a2b59 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/CONTRIBUTING.md +@@ -0,0 +1,26 @@ ++# Contributing to Go ++ ++Go is an open source project. ++ ++It is the work of hundreds of contributors. We appreciate your help! ++ ++## Filing issues ++ ++When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: ++ ++1. What version of Go are you using (`go version`)? ++2. What operating system and processor architecture are you using? ++3. What did you do? ++4. What did you expect to see? ++5. What did you see instead? ++ ++General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. ++The gophers there will answer or ask you to file an issue if you've tripped over a bug. ++ ++## Contributing code ++ ++Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) ++before sending patches. ++ ++Unless otherwise noted, the Go source files are distributed under ++the BSD-style license found in the LICENSE file. +diff --git a/ms_mod/golang.org/x/crypto/LICENSE b/ms_mod/golang.org/x/crypto/LICENSE +new file mode 100644 +index 00000000000000..6a66aea5eafe0c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/LICENSE +@@ -0,0 +1,27 @@ ++Copyright (c) 2009 The Go Authors. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are ++met: ++ ++ * Redistributions of source code must retain the above copyright ++notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above ++copyright notice, this list of conditions and the following disclaimer ++in the documentation and/or other materials provided with the ++distribution. ++ * Neither the name of Google Inc. nor the names of its ++contributors may be used to endorse or promote products derived from ++this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +diff --git a/ms_mod/golang.org/x/crypto/PATENTS b/ms_mod/golang.org/x/crypto/PATENTS +new file mode 100644 +index 00000000000000..733099041f84fa +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/PATENTS +@@ -0,0 +1,22 @@ ++Additional IP Rights Grant (Patents) ++ ++"This implementation" means the copyrightable works distributed by ++Google as part of the Go project. ++ ++Google hereby grants to You a perpetual, worldwide, non-exclusive, ++no-charge, royalty-free, irrevocable (except as stated in this section) ++patent license to make, have made, use, offer to sell, sell, import, ++transfer and otherwise run, modify and propagate the contents of this ++implementation of Go, where such license applies only to those patent ++claims, both currently owned or controlled by Google and acquired in ++the future, licensable by Google that are necessarily infringed by this ++implementation of Go. This grant does not include claims that would be ++infringed only as a consequence of further modification of this ++implementation. If you or your agent or exclusive licensee institute or ++order or agree to the institution of patent litigation against any ++entity (including a cross-claim or counterclaim in a lawsuit) alleging ++that this implementation of Go or any code incorporated within this ++implementation of Go constitutes direct or contributory patent ++infringement, or inducement of patent infringement, then any patent ++rights granted to you under this License for this implementation of Go ++shall terminate as of the date such litigation is filed. +diff --git a/ms_mod/golang.org/x/crypto/README.md b/ms_mod/golang.org/x/crypto/README.md +new file mode 100644 +index 00000000000000..92f73cdfbfeeb8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/README.md +@@ -0,0 +1,23 @@ ++# Go Cryptography ++ ++[![Go Reference](https://pkg.go.dev/badge/golang.org/x/crypto.svg)](https://pkg.go.dev/golang.org/x/crypto) ++ ++This repository holds supplementary Go cryptography libraries. ++ ++## Download/Install ++ ++The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You ++can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`. ++ ++## Report Issues / Send Patches ++ ++This repository uses Gerrit for code changes. To learn how to submit changes to ++this repository, see https://golang.org/doc/contribute.html. ++ ++The main issue tracker for the crypto repository is located at ++https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the ++subject line, so it is easy to find. ++ ++Note that contributions to the cryptography package receive additional scrutiny ++due to their sensitive nature. Patches may take longer than normal to receive ++feedback. +diff --git a/ms_mod/golang.org/x/crypto/acme/acme.go b/ms_mod/golang.org/x/crypto/acme/acme.go +new file mode 100644 +index 00000000000000..aaafea2bc08296 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/acme.go +@@ -0,0 +1,818 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package acme provides an implementation of the ++// Automatic Certificate Management Environment (ACME) spec, ++// most famously used by Let's Encrypt. ++// ++// The initial implementation of this package was based on an early version ++// of the spec. The current implementation supports only the modern ++// RFC 8555 but some of the old API surface remains for compatibility. ++// While code using the old API will still compile, it will return an error. ++// Note the deprecation comments to update your code. ++// ++// See https://tools.ietf.org/html/rfc8555 for the spec. ++// ++// Most common scenarios will want to use autocert subdirectory instead, ++// which provides automatic access to certificates from Let's Encrypt ++// and any other ACME-based CA. ++package acme ++ ++import ( ++ "context" ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/sha256" ++ "crypto/tls" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "encoding/base64" ++ "encoding/hex" ++ "encoding/json" ++ "encoding/pem" ++ "errors" ++ "fmt" ++ "math/big" ++ "net/http" ++ "strings" ++ "sync" ++ "time" ++) ++ ++const ( ++ // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. ++ LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory" ++ ++ // ALPNProto is the ALPN protocol name used by a CA server when validating ++ // tls-alpn-01 challenges. ++ // ++ // Package users must ensure their servers can negotiate the ACME ALPN in ++ // order for tls-alpn-01 challenge verifications to succeed. ++ // See the crypto/tls package's Config.NextProtos field. ++ ALPNProto = "acme-tls/1" ++) ++ ++// idPeACMEIdentifier is the OID for the ACME extension for the TLS-ALPN challenge. ++// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1 ++var idPeACMEIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} ++ ++const ( ++ maxChainLen = 5 // max depth and breadth of a certificate chain ++ maxCertSize = 1 << 20 // max size of a certificate, in DER bytes ++ // Used for decoding certs from application/pem-certificate-chain response, ++ // the default when in RFC mode. ++ maxCertChainSize = maxCertSize * maxChainLen ++ ++ // Max number of collected nonces kept in memory. ++ // Expect usual peak of 1 or 2. ++ maxNonces = 100 ++) ++ ++// Client is an ACME client. ++// ++// The only required field is Key. An example of creating a client with a new key ++// is as follows: ++// ++// key, err := rsa.GenerateKey(rand.Reader, 2048) ++// if err != nil { ++// log.Fatal(err) ++// } ++// client := &Client{Key: key} ++type Client struct { ++ // Key is the account key used to register with a CA and sign requests. ++ // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey. ++ // ++ // The following algorithms are supported: ++ // RS256, ES256, ES384 and ES512. ++ // See RFC 7518 for more details about the algorithms. ++ Key crypto.Signer ++ ++ // HTTPClient optionally specifies an HTTP client to use ++ // instead of http.DefaultClient. ++ HTTPClient *http.Client ++ ++ // DirectoryURL points to the CA directory endpoint. ++ // If empty, LetsEncryptURL is used. ++ // Mutating this value after a successful call of Client's Discover method ++ // will have no effect. ++ DirectoryURL string ++ ++ // RetryBackoff computes the duration after which the nth retry of a failed request ++ // should occur. The value of n for the first call on failure is 1. ++ // The values of r and resp are the request and response of the last failed attempt. ++ // If the returned value is negative or zero, no more retries are done and an error ++ // is returned to the caller of the original method. ++ // ++ // Requests which result in a 4xx client error are not retried, ++ // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests. ++ // ++ // If RetryBackoff is nil, a truncated exponential backoff algorithm ++ // with the ceiling of 10 seconds is used, where each subsequent retry n ++ // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter), ++ // preferring the former if "Retry-After" header is found in the resp. ++ // The jitter is a random value up to 1 second. ++ RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration ++ ++ // UserAgent is prepended to the User-Agent header sent to the ACME server, ++ // which by default is this package's name and version. ++ // ++ // Reusable libraries and tools in particular should set this value to be ++ // identifiable by the server, in case they are causing issues. ++ UserAgent string ++ ++ cacheMu sync.Mutex ++ dir *Directory // cached result of Client's Discover method ++ // KID is the key identifier provided by the CA. If not provided it will be ++ // retrieved from the CA by making a call to the registration endpoint. ++ KID KeyID ++ ++ noncesMu sync.Mutex ++ nonces map[string]struct{} // nonces collected from previous responses ++} ++ ++// accountKID returns a key ID associated with c.Key, the account identity ++// provided by the CA during RFC based registration. ++// It assumes c.Discover has already been called. ++// ++// accountKID requires at most one network roundtrip. ++// It caches only successful result. ++// ++// When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID ++// returns noKeyID. ++func (c *Client) accountKID(ctx context.Context) KeyID { ++ c.cacheMu.Lock() ++ defer c.cacheMu.Unlock() ++ if c.KID != noKeyID { ++ return c.KID ++ } ++ a, err := c.getRegRFC(ctx) ++ if err != nil { ++ return noKeyID ++ } ++ c.KID = KeyID(a.URI) ++ return c.KID ++} ++ ++var errPreRFC = errors.New("acme: server does not support the RFC 8555 version of ACME") ++ ++// Discover performs ACME server discovery using c.DirectoryURL. ++// ++// It caches successful result. So, subsequent calls will not result in ++// a network round-trip. This also means mutating c.DirectoryURL after successful call ++// of this method will have no effect. ++func (c *Client) Discover(ctx context.Context) (Directory, error) { ++ c.cacheMu.Lock() ++ defer c.cacheMu.Unlock() ++ if c.dir != nil { ++ return *c.dir, nil ++ } ++ ++ res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK)) ++ if err != nil { ++ return Directory{}, err ++ } ++ defer res.Body.Close() ++ c.addNonce(res.Header) ++ ++ var v struct { ++ Reg string `json:"newAccount"` ++ Authz string `json:"newAuthz"` ++ Order string `json:"newOrder"` ++ Revoke string `json:"revokeCert"` ++ Nonce string `json:"newNonce"` ++ KeyChange string `json:"keyChange"` ++ Meta struct { ++ Terms string `json:"termsOfService"` ++ Website string `json:"website"` ++ CAA []string `json:"caaIdentities"` ++ ExternalAcct bool `json:"externalAccountRequired"` ++ } ++ } ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return Directory{}, err ++ } ++ if v.Order == "" { ++ return Directory{}, errPreRFC ++ } ++ c.dir = &Directory{ ++ RegURL: v.Reg, ++ AuthzURL: v.Authz, ++ OrderURL: v.Order, ++ RevokeURL: v.Revoke, ++ NonceURL: v.Nonce, ++ KeyChangeURL: v.KeyChange, ++ Terms: v.Meta.Terms, ++ Website: v.Meta.Website, ++ CAA: v.Meta.CAA, ++ ExternalAccountRequired: v.Meta.ExternalAcct, ++ } ++ return *c.dir, nil ++} ++ ++func (c *Client) directoryURL() string { ++ if c.DirectoryURL != "" { ++ return c.DirectoryURL ++ } ++ return LetsEncryptURL ++} ++ ++// CreateCert was part of the old version of ACME. It is incompatible with RFC 8555. ++// ++// Deprecated: this was for the pre-RFC 8555 version of ACME. Callers should use CreateOrderCert. ++func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) { ++ return nil, "", errPreRFC ++} ++ ++// FetchCert retrieves already issued certificate from the given url, in DER format. ++// It retries the request until the certificate is successfully retrieved, ++// context is cancelled by the caller or an error response is received. ++// ++// If the bundle argument is true, the returned value also contains the CA (issuer) ++// certificate chain. ++// ++// FetchCert returns an error if the CA's response or chain was unreasonably large. ++// Callers are encouraged to parse the returned value to ensure the certificate is valid ++// and has expected features. ++func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ return c.fetchCertRFC(ctx, url, bundle) ++} ++ ++// RevokeCert revokes a previously issued certificate cert, provided in DER format. ++// ++// The key argument, used to sign the request, must be authorized ++// to revoke the certificate. It's up to the CA to decide which keys are authorized. ++// For instance, the key pair of the certificate may be authorized. ++// If the key is nil, c.Key is used instead. ++func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { ++ if _, err := c.Discover(ctx); err != nil { ++ return err ++ } ++ return c.revokeCertRFC(ctx, key, cert, reason) ++} ++ ++// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service ++// during account registration. See Register method of Client for more details. ++func AcceptTOS(tosURL string) bool { return true } ++ ++// Register creates a new account with the CA using c.Key. ++// It returns the registered account. The account acct is not modified. ++// ++// The registration may require the caller to agree to the CA's Terms of Service (TOS). ++// If so, and the account has not indicated the acceptance of the terms (see Account for details), ++// Register calls prompt with a TOS URL provided by the CA. Prompt should report ++// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS. ++// ++// When interfacing with an RFC-compliant CA, non-RFC 8555 fields of acct are ignored ++// and prompt is called if Directory's Terms field is non-zero. ++// Also see Error's Instance field for when a CA requires already registered accounts to agree ++// to an updated Terms of Service. ++func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { ++ if c.Key == nil { ++ return nil, errors.New("acme: client.Key must be set to Register") ++ } ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ return c.registerRFC(ctx, acct, prompt) ++} ++ ++// GetReg retrieves an existing account associated with c.Key. ++// ++// The url argument is a legacy artifact of the pre-RFC 8555 API ++// and is ignored. ++func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ return c.getRegRFC(ctx) ++} ++ ++// UpdateReg updates an existing registration. ++// It returns an updated account copy. The provided account is not modified. ++// ++// The account's URI is ignored and the account URL associated with ++// c.Key is used instead. ++func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ return c.updateRegRFC(ctx, acct) ++} ++ ++// AccountKeyRollover attempts to transition a client's account key to a new key. ++// On success client's Key is updated which is not concurrency safe. ++// On failure an error will be returned. ++// The new key is already registered with the ACME provider if the following is true: ++// - error is of type acme.Error ++// - StatusCode should be 409 (Conflict) ++// - Location header will have the KID of the associated account ++// ++// More about account key rollover can be found at ++// https://tools.ietf.org/html/rfc8555#section-7.3.5. ++func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error { ++ return c.accountKeyRollover(ctx, newKey) ++} ++ ++// Authorize performs the initial step in the pre-authorization flow, ++// as opposed to order-based flow. ++// The caller will then need to choose from and perform a set of returned ++// challenges using c.Accept in order to successfully complete authorization. ++// ++// Once complete, the caller can use AuthorizeOrder which the CA ++// should provision with the already satisfied authorization. ++// For pre-RFC CAs, the caller can proceed directly to requesting a certificate ++// using CreateCert method. ++// ++// If an authorization has been previously granted, the CA may return ++// a valid authorization which has its Status field set to StatusValid. ++// ++// More about pre-authorization can be found at ++// https://tools.ietf.org/html/rfc8555#section-7.4.1. ++func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) { ++ return c.authorize(ctx, "dns", domain) ++} ++ ++// AuthorizeIP is the same as Authorize but requests IP address authorization. ++// Clients which successfully obtain such authorization may request to issue ++// a certificate for IP addresses. ++// ++// See the ACME spec extension for more details about IP address identifiers: ++// https://tools.ietf.org/html/draft-ietf-acme-ip. ++func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) { ++ return c.authorize(ctx, "ip", ipaddr) ++} ++ ++func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ ++ type authzID struct { ++ Type string `json:"type"` ++ Value string `json:"value"` ++ } ++ req := struct { ++ Resource string `json:"resource"` ++ Identifier authzID `json:"identifier"` ++ }{ ++ Resource: "new-authz", ++ Identifier: authzID{Type: typ, Value: val}, ++ } ++ res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ ++ var v wireAuthz ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return nil, fmt.Errorf("acme: invalid response: %v", err) ++ } ++ if v.Status != StatusPending && v.Status != StatusValid { ++ return nil, fmt.Errorf("acme: unexpected status: %s", v.Status) ++ } ++ return v.authorization(res.Header.Get("Location")), nil ++} ++ ++// GetAuthorization retrieves an authorization identified by the given URL. ++// ++// If a caller needs to poll an authorization until its status is final, ++// see the WaitAuthorization method. ++func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ var v wireAuthz ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return nil, fmt.Errorf("acme: invalid response: %v", err) ++ } ++ return v.authorization(url), nil ++} ++ ++// RevokeAuthorization relinquishes an existing authorization identified ++// by the given URL. ++// The url argument is an Authorization.URI value. ++// ++// If successful, the caller will be required to obtain a new authorization ++// using the Authorize or AuthorizeOrder methods before being able to request ++// a new certificate for the domain associated with the authorization. ++// ++// It does not revoke existing certificates. ++func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { ++ if _, err := c.Discover(ctx); err != nil { ++ return err ++ } ++ ++ req := struct { ++ Resource string `json:"resource"` ++ Status string `json:"status"` ++ Delete bool `json:"delete"` ++ }{ ++ Resource: "authz", ++ Status: "deactivated", ++ Delete: true, ++ } ++ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) ++ if err != nil { ++ return err ++ } ++ defer res.Body.Close() ++ return nil ++} ++ ++// WaitAuthorization polls an authorization at the given URL ++// until it is in one of the final states, StatusValid or StatusInvalid, ++// the ACME CA responded with a 4xx error code, or the context is done. ++// ++// It returns a non-nil Authorization only if its Status is StatusValid. ++// In all other cases WaitAuthorization returns an error. ++// If the Status is StatusInvalid, the returned error is of type *AuthorizationError. ++func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ for { ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) ++ if err != nil { ++ return nil, err ++ } ++ ++ var raw wireAuthz ++ err = json.NewDecoder(res.Body).Decode(&raw) ++ res.Body.Close() ++ switch { ++ case err != nil: ++ // Skip and retry. ++ case raw.Status == StatusValid: ++ return raw.authorization(url), nil ++ case raw.Status == StatusInvalid: ++ return nil, raw.error(url) ++ } ++ ++ // Exponential backoff is implemented in c.get above. ++ // This is just to prevent continuously hitting the CA ++ // while waiting for a final authorization status. ++ d := retryAfter(res.Header.Get("Retry-After")) ++ if d == 0 { ++ // Given that the fastest challenges TLS-SNI and HTTP-01 ++ // require a CA to make at least 1 network round trip ++ // and most likely persist a challenge state, ++ // this default delay seems reasonable. ++ d = time.Second ++ } ++ t := time.NewTimer(d) ++ select { ++ case <-ctx.Done(): ++ t.Stop() ++ return nil, ctx.Err() ++ case <-t.C: ++ // Retry. ++ } ++ } ++} ++ ++// GetChallenge retrieves the current status of an challenge. ++// ++// A client typically polls a challenge status using this method. ++func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) ++ if err != nil { ++ return nil, err ++ } ++ ++ defer res.Body.Close() ++ v := wireChallenge{URI: url} ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return nil, fmt.Errorf("acme: invalid response: %v", err) ++ } ++ return v.challenge(), nil ++} ++ ++// Accept informs the server that the client accepts one of its challenges ++// previously obtained with c.Authorize. ++// ++// The server will then perform the validation asynchronously. ++func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ ++ res, err := c.post(ctx, nil, chal.URI, json.RawMessage("{}"), wantStatus( ++ http.StatusOK, // according to the spec ++ http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md) ++ )) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ ++ var v wireChallenge ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return nil, fmt.Errorf("acme: invalid response: %v", err) ++ } ++ return v.challenge(), nil ++} ++ ++// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response. ++// A TXT record containing the returned value must be provisioned under ++// "_acme-challenge" name of the domain being validated. ++// ++// The token argument is a Challenge.Token value. ++func (c *Client) DNS01ChallengeRecord(token string) (string, error) { ++ ka, err := keyAuth(c.Key.Public(), token) ++ if err != nil { ++ return "", err ++ } ++ b := sha256.Sum256([]byte(ka)) ++ return base64.RawURLEncoding.EncodeToString(b[:]), nil ++} ++ ++// HTTP01ChallengeResponse returns the response for an http-01 challenge. ++// Servers should respond with the value to HTTP requests at the URL path ++// provided by HTTP01ChallengePath to validate the challenge and prove control ++// over a domain name. ++// ++// The token argument is a Challenge.Token value. ++func (c *Client) HTTP01ChallengeResponse(token string) (string, error) { ++ return keyAuth(c.Key.Public(), token) ++} ++ ++// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge ++// should be provided by the servers. ++// The response value can be obtained with HTTP01ChallengeResponse. ++// ++// The token argument is a Challenge.Token value. ++func (c *Client) HTTP01ChallengePath(token string) string { ++ return "/.well-known/acme-challenge/" + token ++} ++ ++// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response. ++// ++// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec. ++func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { ++ ka, err := keyAuth(c.Key.Public(), token) ++ if err != nil { ++ return tls.Certificate{}, "", err ++ } ++ b := sha256.Sum256([]byte(ka)) ++ h := hex.EncodeToString(b[:]) ++ name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:]) ++ cert, err = tlsChallengeCert([]string{name}, opt) ++ if err != nil { ++ return tls.Certificate{}, "", err ++ } ++ return cert, name, nil ++} ++ ++// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response. ++// ++// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec. ++func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { ++ b := sha256.Sum256([]byte(token)) ++ h := hex.EncodeToString(b[:]) ++ sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:]) ++ ++ ka, err := keyAuth(c.Key.Public(), token) ++ if err != nil { ++ return tls.Certificate{}, "", err ++ } ++ b = sha256.Sum256([]byte(ka)) ++ h = hex.EncodeToString(b[:]) ++ sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:]) ++ ++ cert, err = tlsChallengeCert([]string{sanA, sanB}, opt) ++ if err != nil { ++ return tls.Certificate{}, "", err ++ } ++ return cert, sanA, nil ++} ++ ++// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response. ++// Servers can present the certificate to validate the challenge and prove control ++// over a domain name. For more details on TLS-ALPN-01 see ++// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3 ++// ++// The token argument is a Challenge.Token value. ++// If a WithKey option is provided, its private part signs the returned cert, ++// and the public part is used to specify the signee. ++// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. ++// ++// The returned certificate is valid for the next 24 hours and must be presented only when ++// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol ++// has been specified. ++func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) { ++ ka, err := keyAuth(c.Key.Public(), token) ++ if err != nil { ++ return tls.Certificate{}, err ++ } ++ shasum := sha256.Sum256([]byte(ka)) ++ extValue, err := asn1.Marshal(shasum[:]) ++ if err != nil { ++ return tls.Certificate{}, err ++ } ++ acmeExtension := pkix.Extension{ ++ Id: idPeACMEIdentifier, ++ Critical: true, ++ Value: extValue, ++ } ++ ++ tmpl := defaultTLSChallengeCertTemplate() ++ ++ var newOpt []CertOption ++ for _, o := range opt { ++ switch o := o.(type) { ++ case *certOptTemplate: ++ t := *(*x509.Certificate)(o) // shallow copy is ok ++ tmpl = &t ++ default: ++ newOpt = append(newOpt, o) ++ } ++ } ++ tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension) ++ newOpt = append(newOpt, WithTemplate(tmpl)) ++ return tlsChallengeCert([]string{domain}, newOpt) ++} ++ ++// popNonce returns a nonce value previously stored with c.addNonce ++// or fetches a fresh one from c.dir.NonceURL. ++// If NonceURL is empty, it first tries c.directoryURL() and, failing that, ++// the provided url. ++func (c *Client) popNonce(ctx context.Context, url string) (string, error) { ++ c.noncesMu.Lock() ++ defer c.noncesMu.Unlock() ++ if len(c.nonces) == 0 { ++ if c.dir != nil && c.dir.NonceURL != "" { ++ return c.fetchNonce(ctx, c.dir.NonceURL) ++ } ++ dirURL := c.directoryURL() ++ v, err := c.fetchNonce(ctx, dirURL) ++ if err != nil && url != dirURL { ++ v, err = c.fetchNonce(ctx, url) ++ } ++ return v, err ++ } ++ var nonce string ++ for nonce = range c.nonces { ++ delete(c.nonces, nonce) ++ break ++ } ++ return nonce, nil ++} ++ ++// clearNonces clears any stored nonces ++func (c *Client) clearNonces() { ++ c.noncesMu.Lock() ++ defer c.noncesMu.Unlock() ++ c.nonces = make(map[string]struct{}) ++} ++ ++// addNonce stores a nonce value found in h (if any) for future use. ++func (c *Client) addNonce(h http.Header) { ++ v := nonceFromHeader(h) ++ if v == "" { ++ return ++ } ++ c.noncesMu.Lock() ++ defer c.noncesMu.Unlock() ++ if len(c.nonces) >= maxNonces { ++ return ++ } ++ if c.nonces == nil { ++ c.nonces = make(map[string]struct{}) ++ } ++ c.nonces[v] = struct{}{} ++} ++ ++func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) { ++ r, err := http.NewRequest("HEAD", url, nil) ++ if err != nil { ++ return "", err ++ } ++ resp, err := c.doNoRetry(ctx, r) ++ if err != nil { ++ return "", err ++ } ++ defer resp.Body.Close() ++ nonce := nonceFromHeader(resp.Header) ++ if nonce == "" { ++ if resp.StatusCode > 299 { ++ return "", responseError(resp) ++ } ++ return "", errors.New("acme: nonce not found") ++ } ++ return nonce, nil ++} ++ ++func nonceFromHeader(h http.Header) string { ++ return h.Get("Replay-Nonce") ++} ++ ++// linkHeader returns URI-Reference values of all Link headers ++// with relation-type rel. ++// See https://tools.ietf.org/html/rfc5988#section-5 for details. ++func linkHeader(h http.Header, rel string) []string { ++ var links []string ++ for _, v := range h["Link"] { ++ parts := strings.Split(v, ";") ++ for _, p := range parts { ++ p = strings.TrimSpace(p) ++ if !strings.HasPrefix(p, "rel=") { ++ continue ++ } ++ if v := strings.Trim(p[4:], `"`); v == rel { ++ links = append(links, strings.Trim(parts[0], "<>")) ++ } ++ } ++ } ++ return links ++} ++ ++// keyAuth generates a key authorization string for a given token. ++func keyAuth(pub crypto.PublicKey, token string) (string, error) { ++ th, err := JWKThumbprint(pub) ++ if err != nil { ++ return "", err ++ } ++ return fmt.Sprintf("%s.%s", token, th), nil ++} ++ ++// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges. ++func defaultTLSChallengeCertTemplate() *x509.Certificate { ++ return &x509.Certificate{ ++ SerialNumber: big.NewInt(1), ++ NotBefore: time.Now(), ++ NotAfter: time.Now().Add(24 * time.Hour), ++ BasicConstraintsValid: true, ++ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ++ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ++ } ++} ++ ++// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges ++// with the given SANs and auto-generated public/private key pair. ++// The Subject Common Name is set to the first SAN to aid debugging. ++// To create a cert with a custom key pair, specify WithKey option. ++func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { ++ var key crypto.Signer ++ tmpl := defaultTLSChallengeCertTemplate() ++ for _, o := range opt { ++ switch o := o.(type) { ++ case *certOptKey: ++ if key != nil { ++ return tls.Certificate{}, errors.New("acme: duplicate key option") ++ } ++ key = o.key ++ case *certOptTemplate: ++ t := *(*x509.Certificate)(o) // shallow copy is ok ++ tmpl = &t ++ default: ++ // package's fault, if we let this happen: ++ panic(fmt.Sprintf("unsupported option type %T", o)) ++ } ++ } ++ if key == nil { ++ var err error ++ if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil { ++ return tls.Certificate{}, err ++ } ++ } ++ tmpl.DNSNames = san ++ if len(san) > 0 { ++ tmpl.Subject.CommonName = san[0] ++ } ++ ++ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key) ++ if err != nil { ++ return tls.Certificate{}, err ++ } ++ return tls.Certificate{ ++ Certificate: [][]byte{der}, ++ PrivateKey: key, ++ }, nil ++} ++ ++// encodePEM returns b encoded as PEM with block of type typ. ++func encodePEM(typ string, b []byte) []byte { ++ pb := &pem.Block{Type: typ, Bytes: b} ++ return pem.EncodeToMemory(pb) ++} ++ ++// timeNow is time.Now, except in tests which can mess with it. ++var timeNow = time.Now +diff --git a/ms_mod/golang.org/x/crypto/acme/acme_test.go b/ms_mod/golang.org/x/crypto/acme/acme_test.go +new file mode 100644 +index 00000000000000..3f6e2748f31a01 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/acme_test.go +@@ -0,0 +1,855 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "bytes" ++ "context" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/tls" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/base64" ++ "encoding/hex" ++ "encoding/json" ++ "fmt" ++ "io" ++ "math/big" ++ "net/http" ++ "net/http/httptest" ++ "reflect" ++ "sort" ++ "strings" ++ "testing" ++ "time" ++) ++ ++// newTestClient creates a client with a non-nil Directory so that it skips ++// the discovery which is otherwise done on the first call of almost every ++// exported method. ++func newTestClient() *Client { ++ return &Client{ ++ Key: testKeyEC, ++ dir: &Directory{}, // skip discovery ++ } ++} ++ ++// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided ++// interface. ++func decodeJWSRequest(t *testing.T, v interface{}, r io.Reader) { ++ // Decode request ++ var req struct{ Payload string } ++ if err := json.NewDecoder(r).Decode(&req); err != nil { ++ t.Fatal(err) ++ } ++ payload, err := base64.RawURLEncoding.DecodeString(req.Payload) ++ if err != nil { ++ t.Fatal(err) ++ } ++ err = json.Unmarshal(payload, v) ++ if err != nil { ++ t.Fatal(err) ++ } ++} ++ ++type jwsHead struct { ++ Alg string ++ Nonce string ++ URL string `json:"url"` ++ KID string `json:"kid"` ++ JWK map[string]string `json:"jwk"` ++} ++ ++func decodeJWSHead(r io.Reader) (*jwsHead, error) { ++ var req struct{ Protected string } ++ if err := json.NewDecoder(r).Decode(&req); err != nil { ++ return nil, err ++ } ++ b, err := base64.RawURLEncoding.DecodeString(req.Protected) ++ if err != nil { ++ return nil, err ++ } ++ var head jwsHead ++ if err := json.Unmarshal(b, &head); err != nil { ++ return nil, err ++ } ++ return &head, nil ++} ++ ++func TestRegisterWithoutKey(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if r.Method == "HEAD" { ++ w.Header().Set("Replay-Nonce", "test-nonce") ++ return ++ } ++ w.WriteHeader(http.StatusCreated) ++ fmt.Fprint(w, `{}`) ++ })) ++ defer ts.Close() ++ // First verify that using a complete client results in success. ++ c := Client{ ++ Key: testKeyEC, ++ DirectoryURL: ts.URL, ++ dir: &Directory{RegURL: ts.URL}, ++ } ++ if _, err := c.Register(context.Background(), &Account{}, AcceptTOS); err != nil { ++ t.Fatalf("c.Register() = %v; want success with a complete test client", err) ++ } ++ c.Key = nil ++ if _, err := c.Register(context.Background(), &Account{}, AcceptTOS); err == nil { ++ t.Error("c.Register() from client without key succeeded, wanted error") ++ } ++} ++ ++func TestAuthorize(t *testing.T) { ++ tt := []struct{ typ, value string }{ ++ {"dns", "example.com"}, ++ {"ip", "1.2.3.4"}, ++ } ++ for _, test := range tt { ++ t.Run(test.typ, func(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if r.Method == "HEAD" { ++ w.Header().Set("Replay-Nonce", "test-nonce") ++ return ++ } ++ if r.Method != "POST" { ++ t.Errorf("r.Method = %q; want POST", r.Method) ++ } ++ ++ var j struct { ++ Resource string ++ Identifier struct { ++ Type string ++ Value string ++ } ++ } ++ decodeJWSRequest(t, &j, r.Body) ++ ++ // Test request ++ if j.Resource != "new-authz" { ++ t.Errorf("j.Resource = %q; want new-authz", j.Resource) ++ } ++ if j.Identifier.Type != test.typ { ++ t.Errorf("j.Identifier.Type = %q; want %q", j.Identifier.Type, test.typ) ++ } ++ if j.Identifier.Value != test.value { ++ t.Errorf("j.Identifier.Value = %q; want %q", j.Identifier.Value, test.value) ++ } ++ ++ w.Header().Set("Location", "https://ca.tld/acme/auth/1") ++ w.WriteHeader(http.StatusCreated) ++ fmt.Fprintf(w, `{ ++ "identifier": {"type":%q,"value":%q}, ++ "status":"pending", ++ "challenges":[ ++ { ++ "type":"http-01", ++ "status":"pending", ++ "uri":"https://ca.tld/acme/challenge/publickey/id1", ++ "token":"token1" ++ }, ++ { ++ "type":"tls-sni-01", ++ "status":"pending", ++ "uri":"https://ca.tld/acme/challenge/publickey/id2", ++ "token":"token2" ++ } ++ ], ++ "combinations":[[0],[1]] ++ }`, test.typ, test.value) ++ })) ++ defer ts.Close() ++ ++ var ( ++ auth *Authorization ++ err error ++ ) ++ cl := Client{ ++ Key: testKeyEC, ++ DirectoryURL: ts.URL, ++ dir: &Directory{AuthzURL: ts.URL}, ++ } ++ switch test.typ { ++ case "dns": ++ auth, err = cl.Authorize(context.Background(), test.value) ++ case "ip": ++ auth, err = cl.AuthorizeIP(context.Background(), test.value) ++ default: ++ t.Fatalf("unknown identifier type: %q", test.typ) ++ } ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if auth.URI != "https://ca.tld/acme/auth/1" { ++ t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI) ++ } ++ if auth.Status != "pending" { ++ t.Errorf("Status = %q; want pending", auth.Status) ++ } ++ if auth.Identifier.Type != test.typ { ++ t.Errorf("Identifier.Type = %q; want %q", auth.Identifier.Type, test.typ) ++ } ++ if auth.Identifier.Value != test.value { ++ t.Errorf("Identifier.Value = %q; want %q", auth.Identifier.Value, test.value) ++ } ++ ++ if n := len(auth.Challenges); n != 2 { ++ t.Fatalf("len(auth.Challenges) = %d; want 2", n) ++ } ++ ++ c := auth.Challenges[0] ++ if c.Type != "http-01" { ++ t.Errorf("c.Type = %q; want http-01", c.Type) ++ } ++ if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { ++ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) ++ } ++ if c.Token != "token1" { ++ t.Errorf("c.Token = %q; want token1", c.Token) ++ } ++ ++ c = auth.Challenges[1] ++ if c.Type != "tls-sni-01" { ++ t.Errorf("c.Type = %q; want tls-sni-01", c.Type) ++ } ++ if c.URI != "https://ca.tld/acme/challenge/publickey/id2" { ++ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI) ++ } ++ if c.Token != "token2" { ++ t.Errorf("c.Token = %q; want token2", c.Token) ++ } ++ ++ combs := [][]int{{0}, {1}} ++ if !reflect.DeepEqual(auth.Combinations, combs) { ++ t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs) ++ } ++ ++ }) ++ } ++} ++ ++func TestAuthorizeValid(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if r.Method == "HEAD" { ++ w.Header().Set("Replay-Nonce", "nonce") ++ return ++ } ++ w.WriteHeader(http.StatusCreated) ++ w.Write([]byte(`{"status":"valid"}`)) ++ })) ++ defer ts.Close() ++ client := Client{ ++ Key: testKey, ++ DirectoryURL: ts.URL, ++ dir: &Directory{AuthzURL: ts.URL}, ++ } ++ _, err := client.Authorize(context.Background(), "example.com") ++ if err != nil { ++ t.Errorf("err = %v", err) ++ } ++} ++ ++func TestWaitAuthorization(t *testing.T) { ++ t.Run("wait loop", func(t *testing.T) { ++ var count int ++ authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { ++ count++ ++ w.Header().Set("Retry-After", "0") ++ if count > 1 { ++ fmt.Fprintf(w, `{"status":"valid"}`) ++ return ++ } ++ fmt.Fprintf(w, `{"status":"pending"}`) ++ }) ++ if err != nil { ++ t.Fatalf("non-nil error: %v", err) ++ } ++ if authz == nil { ++ t.Fatal("authz is nil") ++ } ++ }) ++ t.Run("invalid status", func(t *testing.T) { ++ _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { ++ fmt.Fprintf(w, `{"status":"invalid"}`) ++ }) ++ if _, ok := err.(*AuthorizationError); !ok { ++ t.Errorf("err is %v (%T); want non-nil *AuthorizationError", err, err) ++ } ++ }) ++ t.Run("invalid status with error returns the authorization error", func(t *testing.T) { ++ _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { ++ fmt.Fprintf(w, `{ ++ "type": "dns-01", ++ "status": "invalid", ++ "error": { ++ "type": "urn:ietf:params:acme:error:caa", ++ "detail": "CAA record for prevents issuance", ++ "status": 403 ++ }, ++ "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/xxx/xxx", ++ "token": "xxx", ++ "validationRecord": [ ++ { ++ "hostname": "" ++ } ++ ] ++ }`) ++ }) ++ ++ want := &AuthorizationError{ ++ Errors: []error{ ++ (&wireError{ ++ Status: 403, ++ Type: "urn:ietf:params:acme:error:caa", ++ Detail: "CAA record for prevents issuance", ++ }).error(nil), ++ }, ++ } ++ ++ _, ok := err.(*AuthorizationError) ++ if !ok { ++ t.Errorf("err is %T; want non-nil *AuthorizationError", err) ++ } ++ ++ if err.Error() != want.Error() { ++ t.Errorf("err is %v; want %v", err, want) ++ } ++ }) ++ t.Run("non-retriable error", func(t *testing.T) { ++ const code = http.StatusBadRequest ++ _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { ++ w.WriteHeader(code) ++ }) ++ res, ok := err.(*Error) ++ if !ok { ++ t.Fatalf("err is %v (%T); want a non-nil *Error", err, err) ++ } ++ if res.StatusCode != code { ++ t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code) ++ } ++ }) ++ for _, code := range []int{http.StatusTooManyRequests, http.StatusInternalServerError} { ++ t.Run(fmt.Sprintf("retriable %d error", code), func(t *testing.T) { ++ var count int ++ authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { ++ count++ ++ w.Header().Set("Retry-After", "0") ++ if count > 1 { ++ fmt.Fprintf(w, `{"status":"valid"}`) ++ return ++ } ++ w.WriteHeader(code) ++ }) ++ if err != nil { ++ t.Fatalf("non-nil error: %v", err) ++ } ++ if authz == nil { ++ t.Fatal("authz is nil") ++ } ++ }) ++ } ++ t.Run("context cancel", func(t *testing.T) { ++ ctx, cancel := context.WithCancel(context.Background()) ++ defer cancel() ++ _, err := runWaitAuthorization(ctx, t, func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Retry-After", "60") ++ fmt.Fprintf(w, `{"status":"pending"}`) ++ time.AfterFunc(1*time.Millisecond, cancel) ++ }) ++ if err == nil { ++ t.Error("err is nil") ++ } ++ }) ++} ++ ++func runWaitAuthorization(ctx context.Context, t *testing.T, h http.HandlerFunc) (*Authorization, error) { ++ t.Helper() ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Replay-Nonce", fmt.Sprintf("bad-test-nonce-%v", time.Now().UnixNano())) ++ h(w, r) ++ })) ++ defer ts.Close() ++ ++ client := &Client{ ++ Key: testKey, ++ DirectoryURL: ts.URL, ++ dir: &Directory{}, ++ KID: "some-key-id", // set to avoid lookup attempt ++ } ++ return client.WaitAuthorization(ctx, ts.URL) ++} ++ ++func TestRevokeAuthorization(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if r.Method == "HEAD" { ++ w.Header().Set("Replay-Nonce", "nonce") ++ return ++ } ++ switch r.URL.Path { ++ case "/1": ++ var req struct { ++ Resource string ++ Status string ++ Delete bool ++ } ++ decodeJWSRequest(t, &req, r.Body) ++ if req.Resource != "authz" { ++ t.Errorf("req.Resource = %q; want authz", req.Resource) ++ } ++ if req.Status != "deactivated" { ++ t.Errorf("req.Status = %q; want deactivated", req.Status) ++ } ++ if !req.Delete { ++ t.Errorf("req.Delete is false") ++ } ++ case "/2": ++ w.WriteHeader(http.StatusBadRequest) ++ } ++ })) ++ defer ts.Close() ++ client := &Client{ ++ Key: testKey, ++ DirectoryURL: ts.URL, // don't dial outside of localhost ++ dir: &Directory{}, // don't do discovery ++ } ++ ctx := context.Background() ++ if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil { ++ t.Errorf("err = %v", err) ++ } ++ if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil { ++ t.Error("nil error") ++ } ++} ++ ++func TestFetchCertCancel(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ <-r.Context().Done() ++ w.Header().Set("Retry-After", "0") ++ w.WriteHeader(http.StatusBadRequest) ++ })) ++ defer ts.Close() ++ ctx, cancel := context.WithCancel(context.Background()) ++ done := make(chan struct{}) ++ var err error ++ go func() { ++ cl := newTestClient() ++ _, err = cl.FetchCert(ctx, ts.URL, false) ++ close(done) ++ }() ++ cancel() ++ <-done ++ if err != context.Canceled { ++ t.Errorf("err = %v; want %v", err, context.Canceled) ++ } ++} ++ ++func TestFetchCertDepth(t *testing.T) { ++ var count byte ++ var ts *httptest.Server ++ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ count++ ++ if count > maxChainLen+1 { ++ t.Errorf("count = %d; want at most %d", count, maxChainLen+1) ++ w.WriteHeader(http.StatusInternalServerError) ++ } ++ w.Header().Set("Link", fmt.Sprintf("<%s>;rel=up", ts.URL)) ++ w.Write([]byte{count}) ++ })) ++ defer ts.Close() ++ cl := newTestClient() ++ _, err := cl.FetchCert(context.Background(), ts.URL, true) ++ if err == nil { ++ t.Errorf("err is nil") ++ } ++} ++ ++func TestFetchCertBreadth(t *testing.T) { ++ var ts *httptest.Server ++ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ for i := 0; i < maxChainLen+1; i++ { ++ w.Header().Add("Link", fmt.Sprintf("<%s>;rel=up", ts.URL)) ++ } ++ w.Write([]byte{1}) ++ })) ++ defer ts.Close() ++ cl := newTestClient() ++ _, err := cl.FetchCert(context.Background(), ts.URL, true) ++ if err == nil { ++ t.Errorf("err is nil") ++ } ++} ++ ++func TestFetchCertSize(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ b := bytes.Repeat([]byte{1}, maxCertSize+1) ++ w.Write(b) ++ })) ++ defer ts.Close() ++ cl := newTestClient() ++ _, err := cl.FetchCert(context.Background(), ts.URL, false) ++ if err == nil { ++ t.Errorf("err is nil") ++ } ++} ++ ++func TestNonce_add(t *testing.T) { ++ var c Client ++ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) ++ c.addNonce(http.Header{"Replay-Nonce": {}}) ++ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) ++ ++ nonces := map[string]struct{}{"nonce": {}} ++ if !reflect.DeepEqual(c.nonces, nonces) { ++ t.Errorf("c.nonces = %q; want %q", c.nonces, nonces) ++ } ++} ++ ++func TestNonce_addMax(t *testing.T) { ++ c := &Client{nonces: make(map[string]struct{})} ++ for i := 0; i < maxNonces; i++ { ++ c.nonces[fmt.Sprintf("%d", i)] = struct{}{} ++ } ++ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) ++ if n := len(c.nonces); n != maxNonces { ++ t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces) ++ } ++} ++ ++func TestNonce_fetch(t *testing.T) { ++ tests := []struct { ++ code int ++ nonce string ++ }{ ++ {http.StatusOK, "nonce1"}, ++ {http.StatusBadRequest, "nonce2"}, ++ {http.StatusOK, ""}, ++ } ++ var i int ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if r.Method != "HEAD" { ++ t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method) ++ } ++ w.Header().Set("Replay-Nonce", tests[i].nonce) ++ w.WriteHeader(tests[i].code) ++ })) ++ defer ts.Close() ++ for ; i < len(tests); i++ { ++ test := tests[i] ++ c := newTestClient() ++ n, err := c.fetchNonce(context.Background(), ts.URL) ++ if n != test.nonce { ++ t.Errorf("%d: n=%q; want %q", i, n, test.nonce) ++ } ++ switch { ++ case err == nil && test.nonce == "": ++ t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err) ++ case err != nil && test.nonce != "": ++ t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce) ++ } ++ } ++} ++ ++func TestNonce_fetchError(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.WriteHeader(http.StatusTooManyRequests) ++ })) ++ defer ts.Close() ++ c := newTestClient() ++ _, err := c.fetchNonce(context.Background(), ts.URL) ++ e, ok := err.(*Error) ++ if !ok { ++ t.Fatalf("err is %T; want *Error", err) ++ } ++ if e.StatusCode != http.StatusTooManyRequests { ++ t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests) ++ } ++} ++ ++func TestNonce_popWhenEmpty(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if r.Method != "HEAD" { ++ t.Errorf("r.Method = %q; want HEAD", r.Method) ++ } ++ switch r.URL.Path { ++ case "/dir-with-nonce": ++ w.Header().Set("Replay-Nonce", "dirnonce") ++ case "/new-nonce": ++ w.Header().Set("Replay-Nonce", "newnonce") ++ case "/dir-no-nonce", "/empty": ++ // No nonce in the header. ++ default: ++ t.Errorf("Unknown URL: %s", r.URL) ++ } ++ })) ++ defer ts.Close() ++ ctx := context.Background() ++ ++ tt := []struct { ++ dirURL, popURL, nonce string ++ wantOK bool ++ }{ ++ {ts.URL + "/dir-with-nonce", ts.URL + "/new-nonce", "dirnonce", true}, ++ {ts.URL + "/dir-no-nonce", ts.URL + "/new-nonce", "newnonce", true}, ++ {ts.URL + "/dir-no-nonce", ts.URL + "/empty", "", false}, ++ } ++ for _, test := range tt { ++ t.Run(fmt.Sprintf("nonce:%s wantOK:%v", test.nonce, test.wantOK), func(t *testing.T) { ++ c := Client{DirectoryURL: test.dirURL} ++ v, err := c.popNonce(ctx, test.popURL) ++ if !test.wantOK { ++ if err == nil { ++ t.Fatalf("c.popNonce(%q) returned nil error", test.popURL) ++ } ++ return ++ } ++ if err != nil { ++ t.Fatalf("c.popNonce(%q): %v", test.popURL, err) ++ } ++ if v != test.nonce { ++ t.Errorf("c.popNonce(%q) = %q; want %q", test.popURL, v, test.nonce) ++ } ++ }) ++ } ++} ++ ++func TestLinkHeader(t *testing.T) { ++ h := http.Header{"Link": { ++ `;rel="next"`, ++ `; rel=recover`, ++ `; foo=bar; rel="terms-of-service"`, ++ `;rel="next"`, ++ }} ++ tests := []struct { ++ rel string ++ out []string ++ }{ ++ {"next", []string{"https://example.com/acme/new-authz", "dup"}}, ++ {"recover", []string{"https://example.com/acme/recover-reg"}}, ++ {"terms-of-service", []string{"https://example.com/acme/terms"}}, ++ {"empty", nil}, ++ } ++ for i, test := range tests { ++ if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) { ++ t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out) ++ } ++ } ++} ++ ++func TestTLSSNI01ChallengeCert(t *testing.T) { ++ const ( ++ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" ++ // echo -n | shasum -a 256 ++ san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid" ++ ) ++ ++ tlscert, name, err := newTestClient().TLSSNI01ChallengeCert(token) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if n := len(tlscert.Certificate); n != 1 { ++ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) ++ } ++ cert, err := x509.ParseCertificate(tlscert.Certificate[0]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san { ++ t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san) ++ } ++ if cert.DNSNames[0] != name { ++ t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name) ++ } ++ if cn := cert.Subject.CommonName; cn != san { ++ t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san) ++ } ++} ++ ++func TestTLSSNI02ChallengeCert(t *testing.T) { ++ const ( ++ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" ++ // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256 ++ sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid" ++ // echo -n | shasum -a 256 ++ sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid" ++ ) ++ ++ tlscert, name, err := newTestClient().TLSSNI02ChallengeCert(token) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if n := len(tlscert.Certificate); n != 1 { ++ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) ++ } ++ cert, err := x509.ParseCertificate(tlscert.Certificate[0]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ names := []string{sanA, sanB} ++ if !reflect.DeepEqual(cert.DNSNames, names) { ++ t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) ++ } ++ sort.Strings(cert.DNSNames) ++ i := sort.SearchStrings(cert.DNSNames, name) ++ if i >= len(cert.DNSNames) || cert.DNSNames[i] != name { ++ t.Errorf("%v doesn't have %q", cert.DNSNames, name) ++ } ++ if cn := cert.Subject.CommonName; cn != sanA { ++ t.Errorf("CommonName = %q; want %q", cn, sanA) ++ } ++} ++ ++func TestTLSALPN01ChallengeCert(t *testing.T) { ++ const ( ++ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" ++ keyAuth = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA." + testKeyECThumbprint ++ // echo -n | shasum -a 256 ++ h = "0420dbbd5eefe7b4d06eb9d1d9f5acb4c7cda27d320e4b30332f0b6cb441734ad7b0" ++ domain = "example.com" ++ ) ++ ++ extValue, err := hex.DecodeString(h) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ tlscert, err := newTestClient().TLSALPN01ChallengeCert(token, domain) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if n := len(tlscert.Certificate); n != 1 { ++ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) ++ } ++ cert, err := x509.ParseCertificate(tlscert.Certificate[0]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ names := []string{domain} ++ if !reflect.DeepEqual(cert.DNSNames, names) { ++ t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) ++ } ++ if cn := cert.Subject.CommonName; cn != domain { ++ t.Errorf("CommonName = %q; want %q", cn, domain) ++ } ++ acmeExts := []pkix.Extension{} ++ for _, ext := range cert.Extensions { ++ if idPeACMEIdentifier.Equal(ext.Id) { ++ acmeExts = append(acmeExts, ext) ++ } ++ } ++ if len(acmeExts) != 1 { ++ t.Errorf("acmeExts = %v; want exactly one", acmeExts) ++ } ++ if !acmeExts[0].Critical { ++ t.Errorf("acmeExt.Critical = %v; want true", acmeExts[0].Critical) ++ } ++ if bytes.Compare(acmeExts[0].Value, extValue) != 0 { ++ t.Errorf("acmeExt.Value = %v; want %v", acmeExts[0].Value, extValue) ++ } ++ ++} ++ ++func TestTLSChallengeCertOpt(t *testing.T) { ++ key, err := rsa.GenerateKey(rand.Reader, 512) ++ if err != nil { ++ t.Fatal(err) ++ } ++ tmpl := &x509.Certificate{ ++ SerialNumber: big.NewInt(2), ++ Subject: pkix.Name{Organization: []string{"Test"}}, ++ DNSNames: []string{"should-be-overwritten"}, ++ } ++ opts := []CertOption{WithKey(key), WithTemplate(tmpl)} ++ ++ client := newTestClient() ++ cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...) ++ if err != nil { ++ t.Fatal(err) ++ } ++ cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ for i, tlscert := range []tls.Certificate{cert1, cert2} { ++ // verify generated cert private key ++ tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey) ++ if !ok { ++ t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey) ++ continue ++ } ++ if tlskey.D.Cmp(key.D) != 0 { ++ t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D) ++ } ++ // verify generated cert public key ++ x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0]) ++ if err != nil { ++ t.Errorf("%d: %v", i, err) ++ continue ++ } ++ tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey) ++ if !ok { ++ t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey) ++ continue ++ } ++ if tlspub.N.Cmp(key.N) != 0 { ++ t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N) ++ } ++ // verify template option ++ sn := big.NewInt(2) ++ if x509Cert.SerialNumber.Cmp(sn) != 0 { ++ t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn) ++ } ++ org := []string{"Test"} ++ if !reflect.DeepEqual(x509Cert.Subject.Organization, org) { ++ t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org) ++ } ++ for _, v := range x509Cert.DNSNames { ++ if !strings.HasSuffix(v, ".acme.invalid") { ++ t.Errorf("%d: invalid DNSNames element: %q", i, v) ++ } ++ } ++ } ++} ++ ++func TestHTTP01Challenge(t *testing.T) { ++ const ( ++ token = "xxx" ++ // thumbprint is precomputed for testKeyEC in jws_test.go ++ value = token + "." + testKeyECThumbprint ++ urlpath = "/.well-known/acme-challenge/" + token ++ ) ++ client := newTestClient() ++ val, err := client.HTTP01ChallengeResponse(token) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if val != value { ++ t.Errorf("val = %q; want %q", val, value) ++ } ++ if path := client.HTTP01ChallengePath(token); path != urlpath { ++ t.Errorf("path = %q; want %q", path, urlpath) ++ } ++} ++ ++func TestDNS01ChallengeRecord(t *testing.T) { ++ // echo -n xxx. | \ ++ // openssl dgst -binary -sha256 | \ ++ // base64 | tr -d '=' | tr '/+' '_-' ++ const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo" ++ ++ val, err := newTestClient().DNS01ChallengeRecord("xxx") ++ if err != nil { ++ t.Fatal(err) ++ } ++ if val != value { ++ t.Errorf("val = %q; want %q", val, value) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/autocert.go b/ms_mod/golang.org/x/crypto/acme/autocert/autocert.go +new file mode 100644 +index 00000000000000..6b4cdf406d3b6e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/autocert.go +@@ -0,0 +1,1198 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package autocert provides automatic access to certificates from Let's Encrypt ++// and any other ACME-based CA. ++// ++// This package is a work in progress and makes no API stability promises. ++package autocert ++ ++import ( ++ "bytes" ++ "context" ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/tls" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/pem" ++ "errors" ++ "fmt" ++ "io" ++ mathrand "math/rand" ++ "net" ++ "net/http" ++ "path" ++ "strings" ++ "sync" ++ "time" ++ ++ "golang.org/x/crypto/acme" ++ "golang.org/x/net/idna" ++) ++ ++// DefaultACMEDirectory is the default ACME Directory URL used when the Manager's Client is nil. ++const DefaultACMEDirectory = "https://acme-v02.api.letsencrypt.org/directory" ++ ++// createCertRetryAfter is how much time to wait before removing a failed state ++// entry due to an unsuccessful createCert call. ++// This is a variable instead of a const for testing. ++// TODO: Consider making it configurable or an exp backoff? ++var createCertRetryAfter = time.Minute ++ ++// pseudoRand is safe for concurrent use. ++var pseudoRand *lockedMathRand ++ ++var errPreRFC = errors.New("autocert: ACME server doesn't support RFC 8555") ++ ++func init() { ++ src := mathrand.NewSource(time.Now().UnixNano()) ++ pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} ++} ++ ++// AcceptTOS is a Manager.Prompt function that always returns true to ++// indicate acceptance of the CA's Terms of Service during account ++// registration. ++func AcceptTOS(tosURL string) bool { return true } ++ ++// HostPolicy specifies which host names the Manager is allowed to respond to. ++// It returns a non-nil error if the host should be rejected. ++// The returned error is accessible via tls.Conn.Handshake and its callers. ++// See Manager's HostPolicy field and GetCertificate method docs for more details. ++type HostPolicy func(ctx context.Context, host string) error ++ ++// HostWhitelist returns a policy where only the specified host names are allowed. ++// Only exact matches are currently supported. Subdomains, regexp or wildcard ++// will not match. ++// ++// Note that all hosts will be converted to Punycode via idna.Lookup.ToASCII so that ++// Manager.GetCertificate can handle the Unicode IDN and mixedcase hosts correctly. ++// Invalid hosts will be silently ignored. ++func HostWhitelist(hosts ...string) HostPolicy { ++ whitelist := make(map[string]bool, len(hosts)) ++ for _, h := range hosts { ++ if h, err := idna.Lookup.ToASCII(h); err == nil { ++ whitelist[h] = true ++ } ++ } ++ return func(_ context.Context, host string) error { ++ if !whitelist[host] { ++ return fmt.Errorf("acme/autocert: host %q not configured in HostWhitelist", host) ++ } ++ return nil ++ } ++} ++ ++// defaultHostPolicy is used when Manager.HostPolicy is not set. ++func defaultHostPolicy(context.Context, string) error { ++ return nil ++} ++ ++// Manager is a stateful certificate manager built on top of acme.Client. ++// It obtains and refreshes certificates automatically using "tls-alpn-01" ++// or "http-01" challenge types, as well as providing them to a TLS server ++// via tls.Config. ++// ++// You must specify a cache implementation, such as DirCache, ++// to reuse obtained certificates across program restarts. ++// Otherwise your server is very likely to exceed the certificate ++// issuer's request rate limits. ++type Manager struct { ++ // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS). ++ // The registration may require the caller to agree to the CA's TOS. ++ // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report ++ // whether the caller agrees to the terms. ++ // ++ // To always accept the terms, the callers can use AcceptTOS. ++ Prompt func(tosURL string) bool ++ ++ // Cache optionally stores and retrieves previously-obtained certificates ++ // and other state. If nil, certs will only be cached for the lifetime of ++ // the Manager. Multiple Managers can share the same Cache. ++ // ++ // Using a persistent Cache, such as DirCache, is strongly recommended. ++ Cache Cache ++ ++ // HostPolicy controls which domains the Manager will attempt ++ // to retrieve new certificates for. It does not affect cached certs. ++ // ++ // If non-nil, HostPolicy is called before requesting a new cert. ++ // If nil, all hosts are currently allowed. This is not recommended, ++ // as it opens a potential attack where clients connect to a server ++ // by IP address and pretend to be asking for an incorrect host name. ++ // Manager will attempt to obtain a certificate for that host, incorrectly, ++ // eventually reaching the CA's rate limit for certificate requests ++ // and making it impossible to obtain actual certificates. ++ // ++ // See GetCertificate for more details. ++ HostPolicy HostPolicy ++ ++ // RenewBefore optionally specifies how early certificates should ++ // be renewed before they expire. ++ // ++ // If zero, they're renewed 30 days before expiration. ++ RenewBefore time.Duration ++ ++ // Client is used to perform low-level operations, such as account registration ++ // and requesting new certificates. ++ // ++ // If Client is nil, a zero-value acme.Client is used with DefaultACMEDirectory ++ // as the directory endpoint. ++ // If the Client.Key is nil, a new ECDSA P-256 key is generated and, ++ // if Cache is not nil, stored in cache. ++ // ++ // Mutating the field after the first call of GetCertificate method will have no effect. ++ Client *acme.Client ++ ++ // Email optionally specifies a contact email address. ++ // This is used by CAs, such as Let's Encrypt, to notify about problems ++ // with issued certificates. ++ // ++ // If the Client's account key is already registered, Email is not used. ++ Email string ++ ++ // ForceRSA used to make the Manager generate RSA certificates. It is now ignored. ++ // ++ // Deprecated: the Manager will request the correct type of certificate based ++ // on what each client supports. ++ ForceRSA bool ++ ++ // ExtraExtensions are used when generating a new CSR (Certificate Request), ++ // thus allowing customization of the resulting certificate. ++ // For instance, TLS Feature Extension (RFC 7633) can be used ++ // to prevent an OCSP downgrade attack. ++ // ++ // The field value is passed to crypto/x509.CreateCertificateRequest ++ // in the template's ExtraExtensions field as is. ++ ExtraExtensions []pkix.Extension ++ ++ // ExternalAccountBinding optionally represents an arbitrary binding to an ++ // account of the CA to which the ACME server is tied. ++ // See RFC 8555, Section 7.3.4 for more details. ++ ExternalAccountBinding *acme.ExternalAccountBinding ++ ++ clientMu sync.Mutex ++ client *acme.Client // initialized by acmeClient method ++ ++ stateMu sync.Mutex ++ state map[certKey]*certState ++ ++ // renewal tracks the set of domains currently running renewal timers. ++ renewalMu sync.Mutex ++ renewal map[certKey]*domainRenewal ++ ++ // challengeMu guards tryHTTP01, certTokens and httpTokens. ++ challengeMu sync.RWMutex ++ // tryHTTP01 indicates whether the Manager should try "http-01" challenge type ++ // during the authorization flow. ++ tryHTTP01 bool ++ // httpTokens contains response body values for http-01 challenges ++ // and is keyed by the URL path at which a challenge response is expected ++ // to be provisioned. ++ // The entries are stored for the duration of the authorization flow. ++ httpTokens map[string][]byte ++ // certTokens contains temporary certificates for tls-alpn-01 challenges ++ // and is keyed by the domain name which matches the ClientHello server name. ++ // The entries are stored for the duration of the authorization flow. ++ certTokens map[string]*tls.Certificate ++ ++ // nowFunc, if not nil, returns the current time. This may be set for ++ // testing purposes. ++ nowFunc func() time.Time ++} ++ ++// certKey is the key by which certificates are tracked in state, renewal and cache. ++type certKey struct { ++ domain string // without trailing dot ++ isRSA bool // RSA cert for legacy clients (as opposed to default ECDSA) ++ isToken bool // tls-based challenge token cert; key type is undefined regardless of isRSA ++} ++ ++func (c certKey) String() string { ++ if c.isToken { ++ return c.domain + "+token" ++ } ++ if c.isRSA { ++ return c.domain + "+rsa" ++ } ++ return c.domain ++} ++ ++// TLSConfig creates a new TLS config suitable for net/http.Server servers, ++// supporting HTTP/2 and the tls-alpn-01 ACME challenge type. ++func (m *Manager) TLSConfig() *tls.Config { ++ return &tls.Config{ ++ GetCertificate: m.GetCertificate, ++ NextProtos: []string{ ++ "h2", "http/1.1", // enable HTTP/2 ++ acme.ALPNProto, // enable tls-alpn ACME challenges ++ }, ++ } ++} ++ ++// GetCertificate implements the tls.Config.GetCertificate hook. ++// It provides a TLS certificate for hello.ServerName host, including answering ++// tls-alpn-01 challenges. ++// All other fields of hello are ignored. ++// ++// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting ++// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation. ++// The error is propagated back to the caller of GetCertificate and is user-visible. ++// This does not affect cached certs. See HostPolicy field description for more details. ++// ++// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will ++// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler for http-01. ++func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { ++ if m.Prompt == nil { ++ return nil, errors.New("acme/autocert: Manager.Prompt not set") ++ } ++ ++ name := hello.ServerName ++ if name == "" { ++ return nil, errors.New("acme/autocert: missing server name") ++ } ++ if !strings.Contains(strings.Trim(name, "."), ".") { ++ return nil, errors.New("acme/autocert: server name component count invalid") ++ } ++ ++ // Note that this conversion is necessary because some server names in the handshakes ++ // started by some clients (such as cURL) are not converted to Punycode, which will ++ // prevent us from obtaining certificates for them. In addition, we should also treat ++ // example.com and EXAMPLE.COM as equivalent and return the same certificate for them. ++ // Fortunately, this conversion also helped us deal with this kind of mixedcase problems. ++ // ++ // Due to the "σςΣ" problem (see https://unicode.org/faq/idn.html#22), we can't use ++ // idna.Punycode.ToASCII (or just idna.ToASCII) here. ++ name, err := idna.Lookup.ToASCII(name) ++ if err != nil { ++ return nil, errors.New("acme/autocert: server name contains invalid character") ++ } ++ ++ // In the worst-case scenario, the timeout needs to account for caching, host policy, ++ // domain ownership verification and certificate issuance. ++ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) ++ defer cancel() ++ ++ // Check whether this is a token cert requested for TLS-ALPN challenge. ++ if wantsTokenCert(hello) { ++ m.challengeMu.RLock() ++ defer m.challengeMu.RUnlock() ++ if cert := m.certTokens[name]; cert != nil { ++ return cert, nil ++ } ++ if cert, err := m.cacheGet(ctx, certKey{domain: name, isToken: true}); err == nil { ++ return cert, nil ++ } ++ // TODO: cache error results? ++ return nil, fmt.Errorf("acme/autocert: no token cert for %q", name) ++ } ++ ++ // regular domain ++ ck := certKey{ ++ domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114 ++ isRSA: !supportsECDSA(hello), ++ } ++ cert, err := m.cert(ctx, ck) ++ if err == nil { ++ return cert, nil ++ } ++ if err != ErrCacheMiss { ++ return nil, err ++ } ++ ++ // first-time ++ if err := m.hostPolicy()(ctx, name); err != nil { ++ return nil, err ++ } ++ cert, err = m.createCert(ctx, ck) ++ if err != nil { ++ return nil, err ++ } ++ m.cachePut(ctx, ck, cert) ++ return cert, nil ++} ++ ++// wantsTokenCert reports whether a TLS request with SNI is made by a CA server ++// for a challenge verification. ++func wantsTokenCert(hello *tls.ClientHelloInfo) bool { ++ // tls-alpn-01 ++ if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto { ++ return true ++ } ++ return false ++} ++ ++func supportsECDSA(hello *tls.ClientHelloInfo) bool { ++ // The "signature_algorithms" extension, if present, limits the key exchange ++ // algorithms allowed by the cipher suites. See RFC 5246, section 7.4.1.4.1. ++ if hello.SignatureSchemes != nil { ++ ecdsaOK := false ++ schemeLoop: ++ for _, scheme := range hello.SignatureSchemes { ++ const tlsECDSAWithSHA1 tls.SignatureScheme = 0x0203 // constant added in Go 1.10 ++ switch scheme { ++ case tlsECDSAWithSHA1, tls.ECDSAWithP256AndSHA256, ++ tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512: ++ ecdsaOK = true ++ break schemeLoop ++ } ++ } ++ if !ecdsaOK { ++ return false ++ } ++ } ++ if hello.SupportedCurves != nil { ++ ecdsaOK := false ++ for _, curve := range hello.SupportedCurves { ++ if curve == tls.CurveP256 { ++ ecdsaOK = true ++ break ++ } ++ } ++ if !ecdsaOK { ++ return false ++ } ++ } ++ for _, suite := range hello.CipherSuites { ++ switch suite { ++ case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, ++ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, ++ tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, ++ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, ++ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, ++ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: ++ return true ++ } ++ } ++ return false ++} ++ ++// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses. ++// It returns an http.Handler that responds to the challenges and must be ++// running on port 80. If it receives a request that is not an ACME challenge, ++// it delegates the request to the optional fallback handler. ++// ++// If fallback is nil, the returned handler redirects all GET and HEAD requests ++// to the default TLS port 443 with 302 Found status code, preserving the original ++// request path and query. It responds with 400 Bad Request to all other HTTP methods. ++// The fallback is not protected by the optional HostPolicy. ++// ++// Because the fallback handler is run with unencrypted port 80 requests, ++// the fallback should not serve TLS-only requests. ++// ++// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01" ++// challenge for domain verification. ++func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { ++ m.challengeMu.Lock() ++ defer m.challengeMu.Unlock() ++ m.tryHTTP01 = true ++ ++ if fallback == nil { ++ fallback = http.HandlerFunc(handleHTTPRedirect) ++ } ++ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if !strings.HasPrefix(r.URL.Path, "/.well-known/acme-challenge/") { ++ fallback.ServeHTTP(w, r) ++ return ++ } ++ // A reasonable context timeout for cache and host policy only, ++ // because we don't wait for a new certificate issuance here. ++ ctx, cancel := context.WithTimeout(r.Context(), time.Minute) ++ defer cancel() ++ if err := m.hostPolicy()(ctx, r.Host); err != nil { ++ http.Error(w, err.Error(), http.StatusForbidden) ++ return ++ } ++ data, err := m.httpToken(ctx, r.URL.Path) ++ if err != nil { ++ http.Error(w, err.Error(), http.StatusNotFound) ++ return ++ } ++ w.Write(data) ++ }) ++} ++ ++func handleHTTPRedirect(w http.ResponseWriter, r *http.Request) { ++ if r.Method != "GET" && r.Method != "HEAD" { ++ http.Error(w, "Use HTTPS", http.StatusBadRequest) ++ return ++ } ++ target := "https://" + stripPort(r.Host) + r.URL.RequestURI() ++ http.Redirect(w, r, target, http.StatusFound) ++} ++ ++func stripPort(hostport string) string { ++ host, _, err := net.SplitHostPort(hostport) ++ if err != nil { ++ return hostport ++ } ++ return net.JoinHostPort(host, "443") ++} ++ ++// cert returns an existing certificate either from m.state or cache. ++// If a certificate is found in cache but not in m.state, the latter will be filled ++// with the cached value. ++func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error) { ++ m.stateMu.Lock() ++ if s, ok := m.state[ck]; ok { ++ m.stateMu.Unlock() ++ s.RLock() ++ defer s.RUnlock() ++ return s.tlscert() ++ } ++ defer m.stateMu.Unlock() ++ cert, err := m.cacheGet(ctx, ck) ++ if err != nil { ++ return nil, err ++ } ++ signer, ok := cert.PrivateKey.(crypto.Signer) ++ if !ok { ++ return nil, errors.New("acme/autocert: private key cannot sign") ++ } ++ if m.state == nil { ++ m.state = make(map[certKey]*certState) ++ } ++ s := &certState{ ++ key: signer, ++ cert: cert.Certificate, ++ leaf: cert.Leaf, ++ } ++ m.state[ck] = s ++ m.startRenew(ck, s.key, s.leaf.NotAfter) ++ return cert, nil ++} ++ ++// cacheGet always returns a valid certificate, or an error otherwise. ++// If a cached certificate exists but is not valid, ErrCacheMiss is returned. ++func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, error) { ++ if m.Cache == nil { ++ return nil, ErrCacheMiss ++ } ++ data, err := m.Cache.Get(ctx, ck.String()) ++ if err != nil { ++ return nil, err ++ } ++ ++ // private ++ priv, pub := pem.Decode(data) ++ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { ++ return nil, ErrCacheMiss ++ } ++ privKey, err := parsePrivateKey(priv.Bytes) ++ if err != nil { ++ return nil, err ++ } ++ ++ // public ++ var pubDER [][]byte ++ for len(pub) > 0 { ++ var b *pem.Block ++ b, pub = pem.Decode(pub) ++ if b == nil { ++ break ++ } ++ pubDER = append(pubDER, b.Bytes) ++ } ++ if len(pub) > 0 { ++ // Leftover content not consumed by pem.Decode. Corrupt. Ignore. ++ return nil, ErrCacheMiss ++ } ++ ++ // verify and create TLS cert ++ leaf, err := validCert(ck, pubDER, privKey, m.now()) ++ if err != nil { ++ return nil, ErrCacheMiss ++ } ++ tlscert := &tls.Certificate{ ++ Certificate: pubDER, ++ PrivateKey: privKey, ++ Leaf: leaf, ++ } ++ return tlscert, nil ++} ++ ++func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certificate) error { ++ if m.Cache == nil { ++ return nil ++ } ++ ++ // contains PEM-encoded data ++ var buf bytes.Buffer ++ ++ // private ++ switch key := tlscert.PrivateKey.(type) { ++ case *ecdsa.PrivateKey: ++ if err := encodeECDSAKey(&buf, key); err != nil { ++ return err ++ } ++ case *rsa.PrivateKey: ++ b := x509.MarshalPKCS1PrivateKey(key) ++ pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b} ++ if err := pem.Encode(&buf, pb); err != nil { ++ return err ++ } ++ default: ++ return errors.New("acme/autocert: unknown private key type") ++ } ++ ++ // public ++ for _, b := range tlscert.Certificate { ++ pb := &pem.Block{Type: "CERTIFICATE", Bytes: b} ++ if err := pem.Encode(&buf, pb); err != nil { ++ return err ++ } ++ } ++ ++ return m.Cache.Put(ctx, ck.String(), buf.Bytes()) ++} ++ ++func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { ++ b, err := x509.MarshalECPrivateKey(key) ++ if err != nil { ++ return err ++ } ++ pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} ++ return pem.Encode(w, pb) ++} ++ ++// createCert starts the domain ownership verification and returns a certificate ++// for that domain upon success. ++// ++// If the domain is already being verified, it waits for the existing verification to complete. ++// Either way, createCert blocks for the duration of the whole process. ++func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) { ++ // TODO: maybe rewrite this whole piece using sync.Once ++ state, err := m.certState(ck) ++ if err != nil { ++ return nil, err ++ } ++ // state may exist if another goroutine is already working on it ++ // in which case just wait for it to finish ++ if !state.locked { ++ state.RLock() ++ defer state.RUnlock() ++ return state.tlscert() ++ } ++ ++ // We are the first; state is locked. ++ // Unblock the readers when domain ownership is verified ++ // and we got the cert or the process failed. ++ defer state.Unlock() ++ state.locked = false ++ ++ der, leaf, err := m.authorizedCert(ctx, state.key, ck) ++ if err != nil { ++ // Remove the failed state after some time, ++ // making the manager call createCert again on the following TLS hello. ++ didRemove := testDidRemoveState // The lifetime of this timer is untracked, so copy mutable local state to avoid races. ++ time.AfterFunc(createCertRetryAfter, func() { ++ defer didRemove(ck) ++ m.stateMu.Lock() ++ defer m.stateMu.Unlock() ++ // Verify the state hasn't changed and it's still invalid ++ // before deleting. ++ s, ok := m.state[ck] ++ if !ok { ++ return ++ } ++ if _, err := validCert(ck, s.cert, s.key, m.now()); err == nil { ++ return ++ } ++ delete(m.state, ck) ++ }) ++ return nil, err ++ } ++ state.cert = der ++ state.leaf = leaf ++ m.startRenew(ck, state.key, state.leaf.NotAfter) ++ return state.tlscert() ++} ++ ++// certState returns a new or existing certState. ++// If a new certState is returned, state.exist is false and the state is locked. ++// The returned error is non-nil only in the case where a new state could not be created. ++func (m *Manager) certState(ck certKey) (*certState, error) { ++ m.stateMu.Lock() ++ defer m.stateMu.Unlock() ++ if m.state == nil { ++ m.state = make(map[certKey]*certState) ++ } ++ // existing state ++ if state, ok := m.state[ck]; ok { ++ return state, nil ++ } ++ ++ // new locked state ++ var ( ++ err error ++ key crypto.Signer ++ ) ++ if ck.isRSA { ++ key, err = rsa.GenerateKey(rand.Reader, 2048) ++ } else { ++ key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ } ++ if err != nil { ++ return nil, err ++ } ++ ++ state := &certState{ ++ key: key, ++ locked: true, ++ } ++ state.Lock() // will be unlocked by m.certState caller ++ m.state[ck] = state ++ return state, nil ++} ++ ++// authorizedCert starts the domain ownership verification process and requests a new cert upon success. ++// The key argument is the certificate private key. ++func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) { ++ csr, err := certRequest(key, ck.domain, m.ExtraExtensions) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ client, err := m.acmeClient(ctx) ++ if err != nil { ++ return nil, nil, err ++ } ++ dir, err := client.Discover(ctx) ++ if err != nil { ++ return nil, nil, err ++ } ++ if dir.OrderURL == "" { ++ return nil, nil, errPreRFC ++ } ++ ++ o, err := m.verifyRFC(ctx, client, ck.domain) ++ if err != nil { ++ return nil, nil, err ++ } ++ chain, _, err := client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ leaf, err = validCert(ck, chain, key, m.now()) ++ if err != nil { ++ return nil, nil, err ++ } ++ return chain, leaf, nil ++} ++ ++// verifyRFC runs the identifier (domain) order-based authorization flow for RFC compliant CAs ++// using each applicable ACME challenge type. ++func (m *Manager) verifyRFC(ctx context.Context, client *acme.Client, domain string) (*acme.Order, error) { ++ // Try each supported challenge type starting with a new order each time. ++ // The nextTyp index of the next challenge type to try is shared across ++ // all order authorizations: if we've tried a challenge type once and it didn't work, ++ // it will most likely not work on another order's authorization either. ++ challengeTypes := m.supportedChallengeTypes() ++ nextTyp := 0 // challengeTypes index ++AuthorizeOrderLoop: ++ for { ++ o, err := client.AuthorizeOrder(ctx, acme.DomainIDs(domain)) ++ if err != nil { ++ return nil, err ++ } ++ // Remove all hanging authorizations to reduce rate limit quotas ++ // after we're done. ++ defer func(urls []string) { ++ go m.deactivatePendingAuthz(urls) ++ }(o.AuthzURLs) ++ ++ // Check if there's actually anything we need to do. ++ switch o.Status { ++ case acme.StatusReady: ++ // Already authorized. ++ return o, nil ++ case acme.StatusPending: ++ // Continue normal Order-based flow. ++ default: ++ return nil, fmt.Errorf("acme/autocert: invalid new order status %q; order URL: %q", o.Status, o.URI) ++ } ++ ++ // Satisfy all pending authorizations. ++ for _, zurl := range o.AuthzURLs { ++ z, err := client.GetAuthorization(ctx, zurl) ++ if err != nil { ++ return nil, err ++ } ++ if z.Status != acme.StatusPending { ++ // We are interested only in pending authorizations. ++ continue ++ } ++ // Pick the next preferred challenge. ++ var chal *acme.Challenge ++ for chal == nil && nextTyp < len(challengeTypes) { ++ chal = pickChallenge(challengeTypes[nextTyp], z.Challenges) ++ nextTyp++ ++ } ++ if chal == nil { ++ return nil, fmt.Errorf("acme/autocert: unable to satisfy %q for domain %q: no viable challenge type found", z.URI, domain) ++ } ++ // Respond to the challenge and wait for validation result. ++ cleanup, err := m.fulfill(ctx, client, chal, domain) ++ if err != nil { ++ continue AuthorizeOrderLoop ++ } ++ defer cleanup() ++ if _, err := client.Accept(ctx, chal); err != nil { ++ continue AuthorizeOrderLoop ++ } ++ if _, err := client.WaitAuthorization(ctx, z.URI); err != nil { ++ continue AuthorizeOrderLoop ++ } ++ } ++ ++ // All authorizations are satisfied. ++ // Wait for the CA to update the order status. ++ o, err = client.WaitOrder(ctx, o.URI) ++ if err != nil { ++ continue AuthorizeOrderLoop ++ } ++ return o, nil ++ } ++} ++ ++func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { ++ for _, c := range chal { ++ if c.Type == typ { ++ return c ++ } ++ } ++ return nil ++} ++ ++func (m *Manager) supportedChallengeTypes() []string { ++ m.challengeMu.RLock() ++ defer m.challengeMu.RUnlock() ++ typ := []string{"tls-alpn-01"} ++ if m.tryHTTP01 { ++ typ = append(typ, "http-01") ++ } ++ return typ ++} ++ ++// deactivatePendingAuthz relinquishes all authorizations identified by the elements ++// of the provided uri slice which are in "pending" state. ++// It ignores revocation errors. ++// ++// deactivatePendingAuthz takes no context argument and instead runs with its own ++// "detached" context because deactivations are done in a goroutine separate from ++// that of the main issuance or renewal flow. ++func (m *Manager) deactivatePendingAuthz(uri []string) { ++ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) ++ defer cancel() ++ client, err := m.acmeClient(ctx) ++ if err != nil { ++ return ++ } ++ for _, u := range uri { ++ z, err := client.GetAuthorization(ctx, u) ++ if err == nil && z.Status == acme.StatusPending { ++ client.RevokeAuthorization(ctx, u) ++ } ++ } ++} ++ ++// fulfill provisions a response to the challenge chal. ++// The cleanup is non-nil only if provisioning succeeded. ++func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) { ++ switch chal.Type { ++ case "tls-alpn-01": ++ cert, err := client.TLSALPN01ChallengeCert(chal.Token, domain) ++ if err != nil { ++ return nil, err ++ } ++ m.putCertToken(ctx, domain, &cert) ++ return func() { go m.deleteCertToken(domain) }, nil ++ case "http-01": ++ resp, err := client.HTTP01ChallengeResponse(chal.Token) ++ if err != nil { ++ return nil, err ++ } ++ p := client.HTTP01ChallengePath(chal.Token) ++ m.putHTTPToken(ctx, p, resp) ++ return func() { go m.deleteHTTPToken(p) }, nil ++ } ++ return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type) ++} ++ ++// putCertToken stores the token certificate with the specified name ++// in both m.certTokens map and m.Cache. ++func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { ++ m.challengeMu.Lock() ++ defer m.challengeMu.Unlock() ++ if m.certTokens == nil { ++ m.certTokens = make(map[string]*tls.Certificate) ++ } ++ m.certTokens[name] = cert ++ m.cachePut(ctx, certKey{domain: name, isToken: true}, cert) ++} ++ ++// deleteCertToken removes the token certificate with the specified name ++// from both m.certTokens map and m.Cache. ++func (m *Manager) deleteCertToken(name string) { ++ m.challengeMu.Lock() ++ defer m.challengeMu.Unlock() ++ delete(m.certTokens, name) ++ if m.Cache != nil { ++ ck := certKey{domain: name, isToken: true} ++ m.Cache.Delete(context.Background(), ck.String()) ++ } ++} ++ ++// httpToken retrieves an existing http-01 token value from an in-memory map ++// or the optional cache. ++func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) { ++ m.challengeMu.RLock() ++ defer m.challengeMu.RUnlock() ++ if v, ok := m.httpTokens[tokenPath]; ok { ++ return v, nil ++ } ++ if m.Cache == nil { ++ return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath) ++ } ++ return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath)) ++} ++ ++// putHTTPToken stores an http-01 token value using tokenPath as key ++// in both in-memory map and the optional Cache. ++// ++// It ignores any error returned from Cache.Put. ++func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) { ++ m.challengeMu.Lock() ++ defer m.challengeMu.Unlock() ++ if m.httpTokens == nil { ++ m.httpTokens = make(map[string][]byte) ++ } ++ b := []byte(val) ++ m.httpTokens[tokenPath] = b ++ if m.Cache != nil { ++ m.Cache.Put(ctx, httpTokenCacheKey(tokenPath), b) ++ } ++} ++ ++// deleteHTTPToken removes an http-01 token value from both in-memory map ++// and the optional Cache, ignoring any error returned from the latter. ++// ++// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout. ++func (m *Manager) deleteHTTPToken(tokenPath string) { ++ m.challengeMu.Lock() ++ defer m.challengeMu.Unlock() ++ delete(m.httpTokens, tokenPath) ++ if m.Cache != nil { ++ m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath)) ++ } ++} ++ ++// httpTokenCacheKey returns a key at which an http-01 token value may be stored ++// in the Manager's optional Cache. ++func httpTokenCacheKey(tokenPath string) string { ++ return path.Base(tokenPath) + "+http-01" ++} ++ ++// startRenew starts a cert renewal timer loop, one per domain. ++// ++// The loop is scheduled in two cases: ++// - a cert was fetched from cache for the first time (wasn't in m.state) ++// - a new cert was created by m.createCert ++// ++// The key argument is a certificate private key. ++// The exp argument is the cert expiration time (NotAfter). ++func (m *Manager) startRenew(ck certKey, key crypto.Signer, exp time.Time) { ++ m.renewalMu.Lock() ++ defer m.renewalMu.Unlock() ++ if m.renewal[ck] != nil { ++ // another goroutine is already on it ++ return ++ } ++ if m.renewal == nil { ++ m.renewal = make(map[certKey]*domainRenewal) ++ } ++ dr := &domainRenewal{m: m, ck: ck, key: key} ++ m.renewal[ck] = dr ++ dr.start(exp) ++} ++ ++// stopRenew stops all currently running cert renewal timers. ++// The timers are not restarted during the lifetime of the Manager. ++func (m *Manager) stopRenew() { ++ m.renewalMu.Lock() ++ defer m.renewalMu.Unlock() ++ for name, dr := range m.renewal { ++ delete(m.renewal, name) ++ dr.stop() ++ } ++} ++ ++func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { ++ const keyName = "acme_account+key" ++ ++ // Previous versions of autocert stored the value under a different key. ++ const legacyKeyName = "acme_account.key" ++ ++ genKey := func() (*ecdsa.PrivateKey, error) { ++ return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ } ++ ++ if m.Cache == nil { ++ return genKey() ++ } ++ ++ data, err := m.Cache.Get(ctx, keyName) ++ if err == ErrCacheMiss { ++ data, err = m.Cache.Get(ctx, legacyKeyName) ++ } ++ if err == ErrCacheMiss { ++ key, err := genKey() ++ if err != nil { ++ return nil, err ++ } ++ var buf bytes.Buffer ++ if err := encodeECDSAKey(&buf, key); err != nil { ++ return nil, err ++ } ++ if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil { ++ return nil, err ++ } ++ return key, nil ++ } ++ if err != nil { ++ return nil, err ++ } ++ ++ priv, _ := pem.Decode(data) ++ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { ++ return nil, errors.New("acme/autocert: invalid account key found in cache") ++ } ++ return parsePrivateKey(priv.Bytes) ++} ++ ++func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) { ++ m.clientMu.Lock() ++ defer m.clientMu.Unlock() ++ if m.client != nil { ++ return m.client, nil ++ } ++ ++ client := m.Client ++ if client == nil { ++ client = &acme.Client{DirectoryURL: DefaultACMEDirectory} ++ } ++ if client.Key == nil { ++ var err error ++ client.Key, err = m.accountKey(ctx) ++ if err != nil { ++ return nil, err ++ } ++ } ++ if client.UserAgent == "" { ++ client.UserAgent = "autocert" ++ } ++ var contact []string ++ if m.Email != "" { ++ contact = []string{"mailto:" + m.Email} ++ } ++ a := &acme.Account{Contact: contact, ExternalAccountBinding: m.ExternalAccountBinding} ++ _, err := client.Register(ctx, a, m.Prompt) ++ if err == nil || isAccountAlreadyExist(err) { ++ m.client = client ++ err = nil ++ } ++ return m.client, err ++} ++ ++// isAccountAlreadyExist reports whether the err, as returned from acme.Client.Register, ++// indicates the account has already been registered. ++func isAccountAlreadyExist(err error) bool { ++ if err == acme.ErrAccountAlreadyExists { ++ return true ++ } ++ ae, ok := err.(*acme.Error) ++ return ok && ae.StatusCode == http.StatusConflict ++} ++ ++func (m *Manager) hostPolicy() HostPolicy { ++ if m.HostPolicy != nil { ++ return m.HostPolicy ++ } ++ return defaultHostPolicy ++} ++ ++func (m *Manager) renewBefore() time.Duration { ++ if m.RenewBefore > renewJitter { ++ return m.RenewBefore ++ } ++ return 720 * time.Hour // 30 days ++} ++ ++func (m *Manager) now() time.Time { ++ if m.nowFunc != nil { ++ return m.nowFunc() ++ } ++ return time.Now() ++} ++ ++// certState is ready when its mutex is unlocked for reading. ++type certState struct { ++ sync.RWMutex ++ locked bool // locked for read/write ++ key crypto.Signer // private key for cert ++ cert [][]byte // DER encoding ++ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil ++} ++ ++// tlscert creates a tls.Certificate from s.key and s.cert. ++// Callers should wrap it in s.RLock() and s.RUnlock(). ++func (s *certState) tlscert() (*tls.Certificate, error) { ++ if s.key == nil { ++ return nil, errors.New("acme/autocert: missing signer") ++ } ++ if len(s.cert) == 0 { ++ return nil, errors.New("acme/autocert: missing certificate") ++ } ++ return &tls.Certificate{ ++ PrivateKey: s.key, ++ Certificate: s.cert, ++ Leaf: s.leaf, ++ }, nil ++} ++ ++// certRequest generates a CSR for the given common name. ++func certRequest(key crypto.Signer, name string, ext []pkix.Extension) ([]byte, error) { ++ req := &x509.CertificateRequest{ ++ Subject: pkix.Name{CommonName: name}, ++ DNSNames: []string{name}, ++ ExtraExtensions: ext, ++ } ++ return x509.CreateCertificateRequest(rand.Reader, req, key) ++} ++ ++// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates ++// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. ++// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. ++// ++// Inspired by parsePrivateKey in crypto/tls/tls.go. ++func parsePrivateKey(der []byte) (crypto.Signer, error) { ++ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { ++ return key, nil ++ } ++ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { ++ switch key := key.(type) { ++ case *rsa.PrivateKey: ++ return key, nil ++ case *ecdsa.PrivateKey: ++ return key, nil ++ default: ++ return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping") ++ } ++ } ++ if key, err := x509.ParseECPrivateKey(der); err == nil { ++ return key, nil ++ } ++ ++ return nil, errors.New("acme/autocert: failed to parse private key") ++} ++ ++// validCert parses a cert chain provided as der argument and verifies the leaf and der[0] ++// correspond to the private key, the domain and key type match, and expiration dates ++// are valid. It doesn't do any revocation checking. ++// ++// The returned value is the verified leaf cert. ++func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf *x509.Certificate, err error) { ++ // parse public part(s) ++ var n int ++ for _, b := range der { ++ n += len(b) ++ } ++ pub := make([]byte, n) ++ n = 0 ++ for _, b := range der { ++ n += copy(pub[n:], b) ++ } ++ x509Cert, err := x509.ParseCertificates(pub) ++ if err != nil || len(x509Cert) == 0 { ++ return nil, errors.New("acme/autocert: no public key found") ++ } ++ // verify the leaf is not expired and matches the domain name ++ leaf = x509Cert[0] ++ if now.Before(leaf.NotBefore) { ++ return nil, errors.New("acme/autocert: certificate is not valid yet") ++ } ++ if now.After(leaf.NotAfter) { ++ return nil, errors.New("acme/autocert: expired certificate") ++ } ++ if err := leaf.VerifyHostname(ck.domain); err != nil { ++ return nil, err ++ } ++ // renew certificates revoked by Let's Encrypt in January 2022 ++ if isRevokedLetsEncrypt(leaf) { ++ return nil, errors.New("acme/autocert: certificate was probably revoked by Let's Encrypt") ++ } ++ // ensure the leaf corresponds to the private key and matches the certKey type ++ switch pub := leaf.PublicKey.(type) { ++ case *rsa.PublicKey: ++ prv, ok := key.(*rsa.PrivateKey) ++ if !ok { ++ return nil, errors.New("acme/autocert: private key type does not match public key type") ++ } ++ if pub.N.Cmp(prv.N) != 0 { ++ return nil, errors.New("acme/autocert: private key does not match public key") ++ } ++ if !ck.isRSA && !ck.isToken { ++ return nil, errors.New("acme/autocert: key type does not match expected value") ++ } ++ case *ecdsa.PublicKey: ++ prv, ok := key.(*ecdsa.PrivateKey) ++ if !ok { ++ return nil, errors.New("acme/autocert: private key type does not match public key type") ++ } ++ if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 { ++ return nil, errors.New("acme/autocert: private key does not match public key") ++ } ++ if ck.isRSA && !ck.isToken { ++ return nil, errors.New("acme/autocert: key type does not match expected value") ++ } ++ default: ++ return nil, errors.New("acme/autocert: unknown public key algorithm") ++ } ++ return leaf, nil ++} ++ ++// https://community.letsencrypt.org/t/2022-01-25-issue-with-tls-alpn-01-validation-method/170450 ++var letsEncryptFixDeployTime = time.Date(2022, time.January, 26, 00, 48, 0, 0, time.UTC) ++ ++// isRevokedLetsEncrypt returns whether the certificate is likely to be part of ++// a batch of certificates revoked by Let's Encrypt in January 2022. This check ++// can be safely removed from May 2022. ++func isRevokedLetsEncrypt(cert *x509.Certificate) bool { ++ O := cert.Issuer.Organization ++ return len(O) == 1 && O[0] == "Let's Encrypt" && ++ cert.NotBefore.Before(letsEncryptFixDeployTime) ++} ++ ++type lockedMathRand struct { ++ sync.Mutex ++ rnd *mathrand.Rand ++} ++ ++func (r *lockedMathRand) int63n(max int64) int64 { ++ r.Lock() ++ n := r.rnd.Int63n(max) ++ r.Unlock() ++ return n ++} ++ ++// For easier testing. ++var ( ++ // Called when a state is removed. ++ testDidRemoveState = func(certKey) {} ++) +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go +new file mode 100644 +index 00000000000000..725677574bb6cc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go +@@ -0,0 +1,996 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert ++ ++import ( ++ "bytes" ++ "context" ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/tls" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "fmt" ++ "io" ++ "math/big" ++ "net/http" ++ "net/http/httptest" ++ "reflect" ++ "strings" ++ "sync" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/acme" ++ "golang.org/x/crypto/acme/autocert/internal/acmetest" ++) ++ ++var ( ++ exampleDomain = "example.org" ++ exampleCertKey = certKey{domain: exampleDomain} ++ exampleCertKeyRSA = certKey{domain: exampleDomain, isRSA: true} ++) ++ ++type memCache struct { ++ t *testing.T ++ mu sync.Mutex ++ keyData map[string][]byte ++} ++ ++func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) { ++ m.mu.Lock() ++ defer m.mu.Unlock() ++ ++ v, ok := m.keyData[key] ++ if !ok { ++ return nil, ErrCacheMiss ++ } ++ return v, nil ++} ++ ++// filenameSafe returns whether all characters in s are printable ASCII ++// and safe to use in a filename on most filesystems. ++func filenameSafe(s string) bool { ++ for _, c := range s { ++ if c < 0x20 || c > 0x7E { ++ return false ++ } ++ switch c { ++ case '\\', '/', ':', '*', '?', '"', '<', '>', '|': ++ return false ++ } ++ } ++ return true ++} ++ ++func (m *memCache) Put(ctx context.Context, key string, data []byte) error { ++ if !filenameSafe(key) { ++ m.t.Errorf("invalid characters in cache key %q", key) ++ } ++ ++ m.mu.Lock() ++ defer m.mu.Unlock() ++ ++ m.keyData[key] = data ++ return nil ++} ++ ++func (m *memCache) Delete(ctx context.Context, key string) error { ++ m.mu.Lock() ++ defer m.mu.Unlock() ++ ++ delete(m.keyData, key) ++ return nil ++} ++ ++func newMemCache(t *testing.T) *memCache { ++ return &memCache{ ++ t: t, ++ keyData: make(map[string][]byte), ++ } ++} ++ ++func (m *memCache) numCerts() int { ++ m.mu.Lock() ++ defer m.mu.Unlock() ++ ++ res := 0 ++ for key := range m.keyData { ++ if strings.HasSuffix(key, "+token") || ++ strings.HasSuffix(key, "+key") || ++ strings.HasSuffix(key, "+http-01") { ++ continue ++ } ++ res++ ++ } ++ return res ++} ++ ++func dummyCert(pub interface{}, san ...string) ([]byte, error) { ++ return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...) ++} ++ ++func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) { ++ // use EC key to run faster on 386 ++ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ return nil, err ++ } ++ t := &x509.Certificate{ ++ SerialNumber: randomSerial(), ++ NotBefore: start, ++ NotAfter: end, ++ BasicConstraintsValid: true, ++ KeyUsage: x509.KeyUsageKeyEncipherment, ++ DNSNames: san, ++ } ++ if pub == nil { ++ pub = &key.PublicKey ++ } ++ return x509.CreateCertificate(rand.Reader, t, t, pub, key) ++} ++ ++func randomSerial() *big.Int { ++ serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 32)) ++ if err != nil { ++ panic(err) ++ } ++ return serial ++} ++ ++type algorithmSupport int ++ ++const ( ++ algRSA algorithmSupport = iota ++ algECDSA ++) ++ ++func clientHelloInfo(sni string, alg algorithmSupport) *tls.ClientHelloInfo { ++ hello := &tls.ClientHelloInfo{ ++ ServerName: sni, ++ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, ++ } ++ if alg == algECDSA { ++ hello.CipherSuites = append(hello.CipherSuites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) ++ } ++ return hello ++} ++ ++func testManager(t *testing.T) *Manager { ++ man := &Manager{ ++ Prompt: AcceptTOS, ++ Cache: newMemCache(t), ++ } ++ t.Cleanup(man.stopRenew) ++ return man ++} ++ ++func TestGetCertificate(t *testing.T) { ++ tests := []struct { ++ name string ++ hello *tls.ClientHelloInfo ++ domain string ++ expectError string ++ prepare func(t *testing.T, man *Manager, s *acmetest.CAServer) ++ verify func(t *testing.T, man *Manager, leaf *x509.Certificate) ++ disableALPN bool ++ disableHTTP bool ++ }{ ++ { ++ name: "ALPN", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ disableHTTP: true, ++ }, ++ { ++ name: "HTTP", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ disableALPN: true, ++ }, ++ { ++ name: "nilPrompt", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ man.Prompt = nil ++ }, ++ expectError: "Manager.Prompt not set", ++ }, ++ { ++ name: "trailingDot", ++ hello: clientHelloInfo("example.org.", algECDSA), ++ domain: "example.org", ++ }, ++ { ++ name: "unicodeIDN", ++ hello: clientHelloInfo("éé.com", algECDSA), ++ domain: "xn--9caa.com", ++ }, ++ { ++ name: "unicodeIDN/mixedCase", ++ hello: clientHelloInfo("éÉ.com", algECDSA), ++ domain: "xn--9caa.com", ++ }, ++ { ++ name: "upperCase", ++ hello: clientHelloInfo("EXAMPLE.ORG", algECDSA), ++ domain: "example.org", ++ }, ++ { ++ name: "goodCache", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ // Make a valid cert and cache it. ++ c := s.Start().LeafCert(exampleDomain, "ECDSA", ++ // Use a time before the Let's Encrypt revocation cutoff to also test ++ // that non-Let's Encrypt certificates are not renewed. ++ time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), ++ time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), ++ ) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ }, ++ // Break the server to check that the cache is used. ++ disableALPN: true, disableHTTP: true, ++ }, ++ { ++ name: "expiredCache", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ // Make an expired cert and cache it. ++ c := s.Start().LeafCert(exampleDomain, "ECDSA", time.Now().Add(-10*time.Minute), time.Now().Add(-5*time.Minute)) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ }, ++ }, ++ { ++ name: "forceRSA", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ man.ForceRSA = true ++ }, ++ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { ++ if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { ++ t.Errorf("leaf.PublicKey is %T; want *ecdsa.PublicKey", leaf.PublicKey) ++ } ++ }, ++ }, ++ { ++ name: "goodLetsEncrypt", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ // Make a valid certificate issued after the TLS-ALPN-01 ++ // revocation window and cache it. ++ s.IssuerName(pkix.Name{Country: []string{"US"}, ++ Organization: []string{"Let's Encrypt"}, CommonName: "R3"}) ++ c := s.Start().LeafCert(exampleDomain, "ECDSA", ++ time.Date(2022, time.January, 26, 12, 0, 0, 0, time.UTC), ++ time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), ++ ) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ }, ++ // Break the server to check that the cache is used. ++ disableALPN: true, disableHTTP: true, ++ }, ++ { ++ name: "revokedLetsEncrypt", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ // Make a certificate issued during the TLS-ALPN-01 ++ // revocation window and cache it. ++ s.IssuerName(pkix.Name{Country: []string{"US"}, ++ Organization: []string{"Let's Encrypt"}, CommonName: "R3"}) ++ c := s.Start().LeafCert(exampleDomain, "ECDSA", ++ time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), ++ time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), ++ ) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ }, ++ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { ++ if leaf.NotBefore.Before(time.Now().Add(-10 * time.Minute)) { ++ t.Error("certificate was not reissued") ++ } ++ }, ++ }, ++ { ++ // TestGetCertificate/tokenCache tests the fallback of token ++ // certificate fetches to cache when Manager.certTokens misses. ++ name: "tokenCacheALPN", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ // Make a separate manager with a shared cache, simulating ++ // separate nodes that serve requests for the same domain. ++ man2 := testManager(t) ++ man2.Cache = man.Cache ++ // Redirect the verification request to man2, although the ++ // client request will hit man, testing that they can complete a ++ // verification by communicating through the cache. ++ s.ResolveGetCertificate("example.org", man2.GetCertificate) ++ }, ++ // Drop the default verification paths. ++ disableALPN: true, ++ }, ++ { ++ name: "tokenCacheHTTP", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ man2 := testManager(t) ++ man2.Cache = man.Cache ++ s.ResolveHandler("example.org", man2.HTTPHandler(nil)) ++ }, ++ disableHTTP: true, ++ }, ++ { ++ name: "ecdsa", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { ++ if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { ++ t.Error("an ECDSA client was served a non-ECDSA certificate") ++ } ++ }, ++ }, ++ { ++ name: "rsa", ++ hello: clientHelloInfo("example.org", algRSA), ++ domain: "example.org", ++ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { ++ if _, ok := leaf.PublicKey.(*rsa.PublicKey); !ok { ++ t.Error("an RSA client was served a non-RSA certificate") ++ } ++ }, ++ }, ++ { ++ name: "wrongCacheKeyType", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ // Make an RSA cert and cache it without suffix. ++ c := s.Start().LeafCert(exampleDomain, "RSA", time.Now(), time.Now().Add(90*24*time.Hour)) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ }, ++ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { ++ // The RSA cached cert should be silently ignored and replaced. ++ if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { ++ t.Error("an ECDSA client was served a non-ECDSA certificate") ++ } ++ if numCerts := man.Cache.(*memCache).numCerts(); numCerts != 1 { ++ t.Errorf("found %d certificates in cache; want %d", numCerts, 1) ++ } ++ }, ++ }, ++ { ++ name: "almostExpiredCache", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ man.RenewBefore = 24 * time.Hour ++ // Cache an almost expired cert. ++ c := s.Start().LeafCert(exampleDomain, "ECDSA", time.Now(), time.Now().Add(10*time.Minute)) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ }, ++ }, ++ { ++ name: "provideExternalAuth", ++ hello: clientHelloInfo("example.org", algECDSA), ++ domain: "example.org", ++ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { ++ s.ExternalAccountRequired() ++ ++ man.ExternalAccountBinding = &acme.ExternalAccountBinding{ ++ KID: "test-key", ++ Key: make([]byte, 32), ++ } ++ }, ++ }, ++ } ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ man := testManager(t) ++ s := acmetest.NewCAServer(t) ++ if !tt.disableALPN { ++ s.ResolveGetCertificate(tt.domain, man.GetCertificate) ++ } ++ if !tt.disableHTTP { ++ s.ResolveHandler(tt.domain, man.HTTPHandler(nil)) ++ } ++ ++ if tt.prepare != nil { ++ tt.prepare(t, man, s) ++ } ++ ++ s.Start() ++ ++ man.Client = &acme.Client{DirectoryURL: s.URL()} ++ ++ tlscert, err := man.GetCertificate(tt.hello) ++ if tt.expectError != "" { ++ if err == nil { ++ t.Fatal("expected error, got certificate") ++ } ++ if !strings.Contains(err.Error(), tt.expectError) { ++ t.Errorf("got %q, expected %q", err, tt.expectError) ++ } ++ return ++ } ++ if err != nil { ++ t.Fatalf("man.GetCertificate: %v", err) ++ } ++ ++ leaf, err := x509.ParseCertificate(tlscert.Certificate[0]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ opts := x509.VerifyOptions{ ++ DNSName: tt.domain, ++ Intermediates: x509.NewCertPool(), ++ Roots: s.Roots(), ++ } ++ for _, cert := range tlscert.Certificate[1:] { ++ c, err := x509.ParseCertificate(cert) ++ if err != nil { ++ t.Fatal(err) ++ } ++ opts.Intermediates.AddCert(c) ++ } ++ if _, err := leaf.Verify(opts); err != nil { ++ t.Error(err) ++ } ++ ++ if san := leaf.DNSNames[0]; san != tt.domain { ++ t.Errorf("got SAN %q, expected %q", san, tt.domain) ++ } ++ ++ if tt.verify != nil { ++ tt.verify(t, man, leaf) ++ } ++ }) ++ } ++} ++ ++func TestGetCertificate_failedAttempt(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.WriteHeader(http.StatusBadRequest) ++ })) ++ defer ts.Close() ++ ++ d := createCertRetryAfter ++ f := testDidRemoveState ++ defer func() { ++ createCertRetryAfter = d ++ testDidRemoveState = f ++ }() ++ createCertRetryAfter = 0 ++ done := make(chan struct{}) ++ testDidRemoveState = func(ck certKey) { ++ if ck != exampleCertKey { ++ t.Errorf("testDidRemoveState: domain = %v; want %v", ck, exampleCertKey) ++ } ++ close(done) ++ } ++ ++ man := &Manager{ ++ Prompt: AcceptTOS, ++ Client: &acme.Client{ ++ DirectoryURL: ts.URL, ++ }, ++ } ++ defer man.stopRenew() ++ hello := clientHelloInfo(exampleDomain, algECDSA) ++ if _, err := man.GetCertificate(hello); err == nil { ++ t.Error("GetCertificate: err is nil") ++ } ++ ++ <-done ++ man.stateMu.Lock() ++ defer man.stateMu.Unlock() ++ if v, exist := man.state[exampleCertKey]; exist { ++ t.Errorf("state exists for %v: %+v", exampleCertKey, v) ++ } ++} ++ ++func TestRevokeFailedAuthz(t *testing.T) { ++ ca := acmetest.NewCAServer(t) ++ // Make the authz unfulfillable on the client side, so it will be left ++ // pending at the end of the verification attempt. ++ ca.ChallengeTypes("fake-01", "fake-02") ++ ca.Start() ++ ++ m := testManager(t) ++ m.Client = &acme.Client{DirectoryURL: ca.URL()} ++ ++ _, err := m.GetCertificate(clientHelloInfo("example.org", algECDSA)) ++ if err == nil { ++ t.Fatal("expected GetCertificate to fail") ++ } ++ ++ logTicker := time.NewTicker(3 * time.Second) ++ defer logTicker.Stop() ++ for { ++ authz, err := m.Client.GetAuthorization(context.Background(), ca.URL()+"/authz/0") ++ if err != nil { ++ t.Fatal(err) ++ } ++ if authz.Status == acme.StatusDeactivated { ++ return ++ } ++ ++ select { ++ case <-logTicker.C: ++ t.Logf("still waiting on revocations") ++ default: ++ } ++ time.Sleep(50 * time.Millisecond) ++ } ++} ++ ++func TestHTTPHandlerDefaultFallback(t *testing.T) { ++ tt := []struct { ++ method, url string ++ wantCode int ++ wantLocation string ++ }{ ++ {"GET", "http://example.org", 302, "https://example.org/"}, ++ {"GET", "http://example.org/foo", 302, "https://example.org/foo"}, ++ {"GET", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, ++ {"GET", "http://example.org/?a=b", 302, "https://example.org/?a=b"}, ++ {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, ++ {"GET", "http://example.org:80/foo?a=b", 302, "https://example.org:443/foo?a=b"}, ++ {"GET", "http://example.org:80/foo%20bar", 302, "https://example.org:443/foo%20bar"}, ++ {"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"}, ++ {"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"}, ++ {"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"}, ++ {"HEAD", "http://example.org", 302, "https://example.org/"}, ++ {"HEAD", "http://example.org/foo", 302, "https://example.org/foo"}, ++ {"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, ++ {"HEAD", "http://example.org/?a=b", 302, "https://example.org/?a=b"}, ++ {"HEAD", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, ++ {"POST", "http://example.org", 400, ""}, ++ {"PUT", "http://example.org", 400, ""}, ++ {"GET", "http://example.org/.well-known/acme-challenge/x", 404, ""}, ++ } ++ var m Manager ++ h := m.HTTPHandler(nil) ++ for i, test := range tt { ++ r := httptest.NewRequest(test.method, test.url, nil) ++ w := httptest.NewRecorder() ++ h.ServeHTTP(w, r) ++ if w.Code != test.wantCode { ++ t.Errorf("%d: w.Code = %d; want %d", i, w.Code, test.wantCode) ++ t.Errorf("%d: body: %s", i, w.Body.Bytes()) ++ } ++ if v := w.Header().Get("Location"); v != test.wantLocation { ++ t.Errorf("%d: Location = %q; want %q", i, v, test.wantLocation) ++ } ++ } ++} ++ ++func TestAccountKeyCache(t *testing.T) { ++ m := Manager{Cache: newMemCache(t)} ++ ctx := context.Background() ++ k1, err := m.accountKey(ctx) ++ if err != nil { ++ t.Fatal(err) ++ } ++ k2, err := m.accountKey(ctx) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if !reflect.DeepEqual(k1, k2) { ++ t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2) ++ } ++} ++ ++func TestCache(t *testing.T) { ++ ecdsaKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatal(err) ++ } ++ cert, err := dummyCert(ecdsaKey.Public(), exampleDomain) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ecdsaCert := &tls.Certificate{ ++ Certificate: [][]byte{cert}, ++ PrivateKey: ecdsaKey, ++ } ++ ++ rsaKey, err := rsa.GenerateKey(rand.Reader, 512) ++ if err != nil { ++ t.Fatal(err) ++ } ++ cert, err = dummyCert(rsaKey.Public(), exampleDomain) ++ if err != nil { ++ t.Fatal(err) ++ } ++ rsaCert := &tls.Certificate{ ++ Certificate: [][]byte{cert}, ++ PrivateKey: rsaKey, ++ } ++ ++ man := &Manager{Cache: newMemCache(t)} ++ defer man.stopRenew() ++ ctx := context.Background() ++ ++ if err := man.cachePut(ctx, exampleCertKey, ecdsaCert); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ if err := man.cachePut(ctx, exampleCertKeyRSA, rsaCert); err != nil { ++ t.Fatalf("man.cachePut: %v", err) ++ } ++ ++ res, err := man.cacheGet(ctx, exampleCertKey) ++ if err != nil { ++ t.Fatalf("man.cacheGet: %v", err) ++ } ++ if res == nil || !bytes.Equal(res.Certificate[0], ecdsaCert.Certificate[0]) { ++ t.Errorf("man.cacheGet = %+v; want %+v", res, ecdsaCert) ++ } ++ ++ res, err = man.cacheGet(ctx, exampleCertKeyRSA) ++ if err != nil { ++ t.Fatalf("man.cacheGet: %v", err) ++ } ++ if res == nil || !bytes.Equal(res.Certificate[0], rsaCert.Certificate[0]) { ++ t.Errorf("man.cacheGet = %+v; want %+v", res, rsaCert) ++ } ++} ++ ++func TestHostWhitelist(t *testing.T) { ++ policy := HostWhitelist("example.com", "EXAMPLE.ORG", "*.example.net", "éÉ.com") ++ tt := []struct { ++ host string ++ allow bool ++ }{ ++ {"example.com", true}, ++ {"example.org", true}, ++ {"xn--9caa.com", true}, // éé.com ++ {"one.example.com", false}, ++ {"two.example.org", false}, ++ {"three.example.net", false}, ++ {"dummy", false}, ++ } ++ for i, test := range tt { ++ err := policy(nil, test.host) ++ if err != nil && test.allow { ++ t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err) ++ } ++ if err == nil && !test.allow { ++ t.Errorf("%d: policy(%q): nil; want an error", i, test.host) ++ } ++ } ++} ++ ++func TestValidCert(t *testing.T) { ++ key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatal(err) ++ } ++ key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatal(err) ++ } ++ key3, err := rsa.GenerateKey(rand.Reader, 512) ++ if err != nil { ++ t.Fatal(err) ++ } ++ cert1, err := dummyCert(key1.Public(), "example.org") ++ if err != nil { ++ t.Fatal(err) ++ } ++ cert2, err := dummyCert(key2.Public(), "example.org") ++ if err != nil { ++ t.Fatal(err) ++ } ++ cert3, err := dummyCert(key3.Public(), "example.org") ++ if err != nil { ++ t.Fatal(err) ++ } ++ now := time.Now() ++ early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org") ++ if err != nil { ++ t.Fatal(err) ++ } ++ expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org") ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ tt := []struct { ++ ck certKey ++ key crypto.Signer ++ cert [][]byte ++ ok bool ++ }{ ++ {certKey{domain: "example.org"}, key1, [][]byte{cert1}, true}, ++ {certKey{domain: "example.org", isRSA: true}, key3, [][]byte{cert3}, true}, ++ {certKey{domain: "example.org"}, key1, [][]byte{cert1, cert2, cert3}, true}, ++ {certKey{domain: "example.org"}, key1, [][]byte{cert1, {1}}, false}, ++ {certKey{domain: "example.org"}, key1, [][]byte{{1}}, false}, ++ {certKey{domain: "example.org"}, key1, [][]byte{cert2}, false}, ++ {certKey{domain: "example.org"}, key2, [][]byte{cert1}, false}, ++ {certKey{domain: "example.org"}, key1, [][]byte{cert3}, false}, ++ {certKey{domain: "example.org"}, key3, [][]byte{cert1}, false}, ++ {certKey{domain: "example.net"}, key1, [][]byte{cert1}, false}, ++ {certKey{domain: "example.org"}, key1, [][]byte{early}, false}, ++ {certKey{domain: "example.org"}, key1, [][]byte{expired}, false}, ++ {certKey{domain: "example.org", isRSA: true}, key1, [][]byte{cert1}, false}, ++ {certKey{domain: "example.org"}, key3, [][]byte{cert3}, false}, ++ } ++ for i, test := range tt { ++ leaf, err := validCert(test.ck, test.cert, test.key, now) ++ if err != nil && test.ok { ++ t.Errorf("%d: err = %v", i, err) ++ } ++ if err == nil && !test.ok { ++ t.Errorf("%d: err is nil", i) ++ } ++ if err == nil && test.ok && leaf == nil { ++ t.Errorf("%d: leaf is nil", i) ++ } ++ } ++} ++ ++type cacheGetFunc func(ctx context.Context, key string) ([]byte, error) ++ ++func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) { ++ return f(ctx, key) ++} ++ ++func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error { ++ return fmt.Errorf("unsupported Put of %q = %q", key, data) ++} ++ ++func (f cacheGetFunc) Delete(ctx context.Context, key string) error { ++ return fmt.Errorf("unsupported Delete of %q", key) ++} ++ ++func TestManagerGetCertificateBogusSNI(t *testing.T) { ++ m := Manager{ ++ Prompt: AcceptTOS, ++ Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) { ++ return nil, fmt.Errorf("cache.Get of %s", key) ++ }), ++ } ++ tests := []struct { ++ name string ++ wantErr string ++ }{ ++ {"foo.com", "cache.Get of foo.com"}, ++ {"foo.com.", "cache.Get of foo.com"}, ++ {`a\b.com`, "acme/autocert: server name contains invalid character"}, ++ {`a/b.com`, "acme/autocert: server name contains invalid character"}, ++ {"", "acme/autocert: missing server name"}, ++ {"foo", "acme/autocert: server name component count invalid"}, ++ {".foo", "acme/autocert: server name component count invalid"}, ++ {"foo.", "acme/autocert: server name component count invalid"}, ++ {"fo.o", "cache.Get of fo.o"}, ++ } ++ for _, tt := range tests { ++ _, err := m.GetCertificate(clientHelloInfo(tt.name, algECDSA)) ++ got := fmt.Sprint(err) ++ if got != tt.wantErr { ++ t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr) ++ } ++ } ++} ++ ++func TestCertRequest(t *testing.T) { ++ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatal(err) ++ } ++ // An extension from RFC7633. Any will do. ++ ext := pkix.Extension{ ++ Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1}, ++ Value: []byte("dummy"), ++ } ++ b, err := certRequest(key, "example.org", []pkix.Extension{ext}) ++ if err != nil { ++ t.Fatalf("certRequest: %v", err) ++ } ++ r, err := x509.ParseCertificateRequest(b) ++ if err != nil { ++ t.Fatalf("ParseCertificateRequest: %v", err) ++ } ++ var found bool ++ for _, v := range r.Extensions { ++ if v.Id.Equal(ext.Id) { ++ found = true ++ break ++ } ++ } ++ if !found { ++ t.Errorf("want %v in Extensions: %v", ext, r.Extensions) ++ } ++} ++ ++func TestSupportsECDSA(t *testing.T) { ++ tests := []struct { ++ CipherSuites []uint16 ++ SignatureSchemes []tls.SignatureScheme ++ SupportedCurves []tls.CurveID ++ ecdsaOk bool ++ }{ ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ++ }, nil, nil, false}, ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ }, nil, nil, true}, ++ ++ // SignatureSchemes limits, not extends, CipherSuites ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ++ }, []tls.SignatureScheme{ ++ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, ++ }, nil, false}, ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ }, []tls.SignatureScheme{ ++ tls.PKCS1WithSHA256, ++ }, nil, false}, ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ }, []tls.SignatureScheme{ ++ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, ++ }, nil, true}, ++ ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ }, []tls.SignatureScheme{ ++ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, ++ }, []tls.CurveID{ ++ tls.CurveP521, ++ }, false}, ++ {[]uint16{ ++ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ++ }, []tls.SignatureScheme{ ++ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, ++ }, []tls.CurveID{ ++ tls.CurveP256, ++ tls.CurveP521, ++ }, true}, ++ } ++ for i, tt := range tests { ++ result := supportsECDSA(&tls.ClientHelloInfo{ ++ CipherSuites: tt.CipherSuites, ++ SignatureSchemes: tt.SignatureSchemes, ++ SupportedCurves: tt.SupportedCurves, ++ }) ++ if result != tt.ecdsaOk { ++ t.Errorf("%d: supportsECDSA = %v; want %v", i, result, tt.ecdsaOk) ++ } ++ } ++} ++ ++func TestEndToEndALPN(t *testing.T) { ++ const domain = "example.org" ++ ++ // ACME CA server ++ ca := acmetest.NewCAServer(t).Start() ++ ++ // User HTTPS server. ++ m := &Manager{ ++ Prompt: AcceptTOS, ++ Client: &acme.Client{DirectoryURL: ca.URL()}, ++ } ++ us := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Write([]byte("OK")) ++ })) ++ us.TLS = &tls.Config{ ++ NextProtos: []string{"http/1.1", acme.ALPNProto}, ++ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { ++ cert, err := m.GetCertificate(hello) ++ if err != nil { ++ t.Errorf("m.GetCertificate: %v", err) ++ } ++ return cert, err ++ }, ++ } ++ us.StartTLS() ++ defer us.Close() ++ // In TLS-ALPN challenge verification, CA connects to the domain:443 in question. ++ // Because the domain won't resolve in tests, we need to tell the CA ++ // where to dial to instead. ++ ca.Resolve(domain, strings.TrimPrefix(us.URL, "https://")) ++ ++ // A client visiting user's HTTPS server. ++ tr := &http.Transport{ ++ TLSClientConfig: &tls.Config{ ++ RootCAs: ca.Roots(), ++ ServerName: domain, ++ }, ++ } ++ client := &http.Client{Transport: tr} ++ res, err := client.Get(us.URL) ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer res.Body.Close() ++ b, err := io.ReadAll(res.Body) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if v := string(b); v != "OK" { ++ t.Errorf("user server response: %q; want 'OK'", v) ++ } ++} ++ ++func TestEndToEndHTTP(t *testing.T) { ++ const domain = "example.org" ++ ++ // ACME CA server. ++ ca := acmetest.NewCAServer(t).ChallengeTypes("http-01").Start() ++ ++ // User HTTP server for the ACME challenge. ++ m := testManager(t) ++ m.Client = &acme.Client{DirectoryURL: ca.URL()} ++ s := httptest.NewServer(m.HTTPHandler(nil)) ++ defer s.Close() ++ ++ // User HTTPS server. ++ ss := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Write([]byte("OK")) ++ })) ++ ss.TLS = &tls.Config{ ++ NextProtos: []string{"http/1.1", acme.ALPNProto}, ++ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { ++ cert, err := m.GetCertificate(hello) ++ if err != nil { ++ t.Errorf("m.GetCertificate: %v", err) ++ } ++ return cert, err ++ }, ++ } ++ ss.StartTLS() ++ defer ss.Close() ++ ++ // Redirect the CA requests to the HTTP server. ++ ca.Resolve(domain, strings.TrimPrefix(s.URL, "http://")) ++ ++ // A client visiting user's HTTPS server. ++ tr := &http.Transport{ ++ TLSClientConfig: &tls.Config{ ++ RootCAs: ca.Roots(), ++ ServerName: domain, ++ }, ++ } ++ client := &http.Client{Transport: tr} ++ res, err := client.Get(ss.URL) ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer res.Body.Close() ++ b, err := io.ReadAll(res.Body) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if v := string(b); v != "OK" { ++ t.Errorf("user server response: %q; want 'OK'", v) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/cache.go b/ms_mod/golang.org/x/crypto/acme/autocert/cache.go +new file mode 100644 +index 00000000000000..758ab12cb225fc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/cache.go +@@ -0,0 +1,135 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert ++ ++import ( ++ "context" ++ "errors" ++ "os" ++ "path/filepath" ++) ++ ++// ErrCacheMiss is returned when a certificate is not found in cache. ++var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") ++ ++// Cache is used by Manager to store and retrieve previously obtained certificates ++// and other account data as opaque blobs. ++// ++// Cache implementations should not rely on the key naming pattern. Keys can ++// include any printable ASCII characters, except the following: \/:*?"<>| ++type Cache interface { ++ // Get returns a certificate data for the specified key. ++ // If there's no such key, Get returns ErrCacheMiss. ++ Get(ctx context.Context, key string) ([]byte, error) ++ ++ // Put stores the data in the cache under the specified key. ++ // Underlying implementations may use any data storage format, ++ // as long as the reverse operation, Get, results in the original data. ++ Put(ctx context.Context, key string, data []byte) error ++ ++ // Delete removes a certificate data from the cache under the specified key. ++ // If there's no such key in the cache, Delete returns nil. ++ Delete(ctx context.Context, key string) error ++} ++ ++// DirCache implements Cache using a directory on the local filesystem. ++// If the directory does not exist, it will be created with 0700 permissions. ++type DirCache string ++ ++// Get reads a certificate data from the specified file name. ++func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { ++ name = filepath.Join(string(d), filepath.Clean("/"+name)) ++ var ( ++ data []byte ++ err error ++ done = make(chan struct{}) ++ ) ++ go func() { ++ data, err = os.ReadFile(name) ++ close(done) ++ }() ++ select { ++ case <-ctx.Done(): ++ return nil, ctx.Err() ++ case <-done: ++ } ++ if os.IsNotExist(err) { ++ return nil, ErrCacheMiss ++ } ++ return data, err ++} ++ ++// Put writes the certificate data to the specified file name. ++// The file will be created with 0600 permissions. ++func (d DirCache) Put(ctx context.Context, name string, data []byte) error { ++ if err := os.MkdirAll(string(d), 0700); err != nil { ++ return err ++ } ++ ++ done := make(chan struct{}) ++ var err error ++ go func() { ++ defer close(done) ++ var tmp string ++ if tmp, err = d.writeTempFile(name, data); err != nil { ++ return ++ } ++ defer os.Remove(tmp) ++ select { ++ case <-ctx.Done(): ++ // Don't overwrite the file if the context was canceled. ++ default: ++ newName := filepath.Join(string(d), filepath.Clean("/"+name)) ++ err = os.Rename(tmp, newName) ++ } ++ }() ++ select { ++ case <-ctx.Done(): ++ return ctx.Err() ++ case <-done: ++ } ++ return err ++} ++ ++// Delete removes the specified file name. ++func (d DirCache) Delete(ctx context.Context, name string) error { ++ name = filepath.Join(string(d), filepath.Clean("/"+name)) ++ var ( ++ err error ++ done = make(chan struct{}) ++ ) ++ go func() { ++ err = os.Remove(name) ++ close(done) ++ }() ++ select { ++ case <-ctx.Done(): ++ return ctx.Err() ++ case <-done: ++ } ++ if err != nil && !os.IsNotExist(err) { ++ return err ++ } ++ return nil ++} ++ ++// writeTempFile writes b to a temporary file, closes the file and returns its path. ++func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) { ++ // TempFile uses 0600 permissions ++ f, err := os.CreateTemp(string(d), prefix) ++ if err != nil { ++ return "", err ++ } ++ defer func() { ++ if reterr != nil { ++ os.Remove(f.Name()) ++ } ++ }() ++ if _, err := f.Write(b); err != nil { ++ f.Close() ++ return "", err ++ } ++ return f.Name(), f.Close() ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go +new file mode 100644 +index 00000000000000..582e6b05804975 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go +@@ -0,0 +1,66 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert ++ ++import ( ++ "context" ++ "os" ++ "path/filepath" ++ "reflect" ++ "testing" ++) ++ ++// make sure DirCache satisfies Cache interface ++var _ Cache = DirCache("/") ++ ++func TestDirCache(t *testing.T) { ++ dir, err := os.MkdirTemp("", "autocert") ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer os.RemoveAll(dir) ++ dir = filepath.Join(dir, "certs") // a nonexistent dir ++ cache := DirCache(dir) ++ ctx := context.Background() ++ ++ // test cache miss ++ if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss { ++ t.Errorf("get: %v; want ErrCacheMiss", err) ++ } ++ ++ // test put/get ++ b1 := []byte{1} ++ if err := cache.Put(ctx, "dummy", b1); err != nil { ++ t.Fatalf("put: %v", err) ++ } ++ b2, err := cache.Get(ctx, "dummy") ++ if err != nil { ++ t.Fatalf("get: %v", err) ++ } ++ if !reflect.DeepEqual(b1, b2) { ++ t.Errorf("b1 = %v; want %v", b1, b2) ++ } ++ name := filepath.Join(dir, "dummy") ++ if _, err := os.Stat(name); err != nil { ++ t.Error(err) ++ } ++ ++ // test put deletes temp file ++ tmp, err := filepath.Glob(name + "?*") ++ if err != nil { ++ t.Error(err) ++ } ++ if tmp != nil { ++ t.Errorf("temp file exists: %s", tmp) ++ } ++ ++ // test delete ++ if err := cache.Delete(ctx, "dummy"); err != nil { ++ t.Fatalf("delete: %v", err) ++ } ++ if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss { ++ t.Errorf("get: %v; want ErrCacheMiss", err) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/example_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/example_test.go +new file mode 100644 +index 00000000000000..6c7458b0d53fcc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/example_test.go +@@ -0,0 +1,35 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert_test ++ ++import ( ++ "fmt" ++ "log" ++ "net/http" ++ ++ "golang.org/x/crypto/acme/autocert" ++) ++ ++func ExampleNewListener() { ++ mux := http.NewServeMux() ++ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { ++ fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS) ++ }) ++ log.Fatal(http.Serve(autocert.NewListener("example.com"), mux)) ++} ++ ++func ExampleManager() { ++ m := &autocert.Manager{ ++ Cache: autocert.DirCache("secret-dir"), ++ Prompt: autocert.AcceptTOS, ++ Email: "example@example.org", ++ HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"), ++ } ++ s := &http.Server{ ++ Addr: ":https", ++ TLSConfig: m.TLSConfig(), ++ } ++ s.ListenAndServeTLS("", "") ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go b/ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go +new file mode 100644 +index 00000000000000..0a5ebe7ab7652e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go +@@ -0,0 +1,796 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package acmetest provides types for testing acme and autocert packages. ++// ++// TODO: Consider moving this to x/crypto/acme/internal/acmetest for acme tests as well. ++package acmetest ++ ++import ( ++ "context" ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/tls" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "encoding/base64" ++ "encoding/json" ++ "encoding/pem" ++ "fmt" ++ "io" ++ "math/big" ++ "net" ++ "net/http" ++ "net/http/httptest" ++ "path" ++ "strconv" ++ "strings" ++ "sync" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/acme" ++) ++ ++// CAServer is a simple test server which implements ACME spec bits needed for testing. ++type CAServer struct { ++ rootKey crypto.Signer ++ rootCert []byte // DER encoding ++ rootTemplate *x509.Certificate ++ ++ t *testing.T ++ server *httptest.Server ++ issuer pkix.Name ++ challengeTypes []string ++ url string ++ roots *x509.CertPool ++ eabRequired bool ++ ++ mu sync.Mutex ++ certCount int // number of issued certs ++ acctRegistered bool // set once an account has been registered ++ domainAddr map[string]string // domain name to addr:port resolution ++ domainGetCert map[string]getCertificateFunc // domain name to GetCertificate function ++ domainHandler map[string]http.Handler // domain name to Handle function ++ validAuthz map[string]*authorization // valid authz, keyed by domain name ++ authorizations []*authorization // all authz, index is used as ID ++ orders []*order // index is used as order ID ++ errors []error // encountered client errors ++} ++ ++type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) ++ ++// NewCAServer creates a new ACME test server. The returned CAServer issues ++// certs signed with the CA roots available in the Roots field. ++func NewCAServer(t *testing.T) *CAServer { ++ ca := &CAServer{t: t, ++ challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"}, ++ domainAddr: make(map[string]string), ++ domainGetCert: make(map[string]getCertificateFunc), ++ domainHandler: make(map[string]http.Handler), ++ validAuthz: make(map[string]*authorization), ++ } ++ ++ ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle)) ++ ++ r, err := rand.Int(rand.Reader, big.NewInt(1000000)) ++ if err != nil { ++ panic(fmt.Sprintf("rand.Int: %v", err)) ++ } ++ ca.issuer = pkix.Name{ ++ Organization: []string{"Test Acme Co"}, ++ CommonName: "Root CA " + r.String(), ++ } ++ ++ return ca ++} ++ ++func (ca *CAServer) generateRoot() { ++ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err)) ++ } ++ tmpl := &x509.Certificate{ ++ SerialNumber: big.NewInt(1), ++ Subject: ca.issuer, ++ NotBefore: time.Now(), ++ NotAfter: time.Now().Add(365 * 24 * time.Hour), ++ KeyUsage: x509.KeyUsageCertSign, ++ BasicConstraintsValid: true, ++ IsCA: true, ++ } ++ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) ++ if err != nil { ++ panic(fmt.Sprintf("x509.CreateCertificate: %v", err)) ++ } ++ cert, err := x509.ParseCertificate(der) ++ if err != nil { ++ panic(fmt.Sprintf("x509.ParseCertificate: %v", err)) ++ } ++ ca.roots = x509.NewCertPool() ++ ca.roots.AddCert(cert) ++ ca.rootKey = key ++ ca.rootCert = der ++ ca.rootTemplate = tmpl ++} ++ ++// IssuerName sets the name of the issuing CA. ++func (ca *CAServer) IssuerName(name pkix.Name) *CAServer { ++ if ca.url != "" { ++ panic("IssuerName must be called before Start") ++ } ++ ca.issuer = name ++ return ca ++} ++ ++// ChallengeTypes sets the supported challenge types. ++func (ca *CAServer) ChallengeTypes(types ...string) *CAServer { ++ if ca.url != "" { ++ panic("ChallengeTypes must be called before Start") ++ } ++ ca.challengeTypes = types ++ return ca ++} ++ ++// URL returns the server address, after Start has been called. ++func (ca *CAServer) URL() string { ++ if ca.url == "" { ++ panic("URL called before Start") ++ } ++ return ca.url ++} ++ ++// Roots returns a pool cointaining the CA root. ++func (ca *CAServer) Roots() *x509.CertPool { ++ if ca.url == "" { ++ panic("Roots called before Start") ++ } ++ return ca.roots ++} ++ ++// ExternalAccountRequired makes an EAB JWS required for account registration. ++func (ca *CAServer) ExternalAccountRequired() *CAServer { ++ if ca.url != "" { ++ panic("ExternalAccountRequired must be called before Start") ++ } ++ ca.eabRequired = true ++ return ca ++} ++ ++// Start starts serving requests. The server address becomes available in the ++// URL field. ++func (ca *CAServer) Start() *CAServer { ++ if ca.url == "" { ++ ca.generateRoot() ++ ca.server.Start() ++ ca.t.Cleanup(ca.server.Close) ++ ca.url = ca.server.URL ++ } ++ return ca ++} ++ ++func (ca *CAServer) serverURL(format string, arg ...interface{}) string { ++ return ca.server.URL + fmt.Sprintf(format, arg...) ++} ++ ++func (ca *CAServer) addr(domain string) (string, bool) { ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ addr, ok := ca.domainAddr[domain] ++ return addr, ok ++} ++ ++func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) { ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ f, ok := ca.domainGetCert[domain] ++ return f, ok ++} ++ ++func (ca *CAServer) getHandler(domain string) (http.Handler, bool) { ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ h, ok := ca.domainHandler[domain] ++ return h, ok ++} ++ ++func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) { ++ s := fmt.Sprintf(format, a...) ++ ca.t.Errorf(format, a...) ++ http.Error(w, s, code) ++} ++ ++// Resolve adds a domain to address resolution for the ca to dial to ++// when validating challenges for the domain authorization. ++func (ca *CAServer) Resolve(domain, addr string) { ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ ca.domainAddr[domain] = addr ++} ++ ++// ResolveGetCertificate redirects TLS connections for domain to f when ++// validating challenges for the domain authorization. ++func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) { ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ ca.domainGetCert[domain] = f ++} ++ ++// ResolveHandler redirects HTTP requests for domain to f when ++// validating challenges for the domain authorization. ++func (ca *CAServer) ResolveHandler(domain string, h http.Handler) { ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ ca.domainHandler[domain] = h ++} ++ ++type discovery struct { ++ NewNonce string `json:"newNonce"` ++ NewAccount string `json:"newAccount"` ++ NewOrder string `json:"newOrder"` ++ NewAuthz string `json:"newAuthz"` ++ ++ Meta discoveryMeta `json:"meta,omitempty"` ++} ++ ++type discoveryMeta struct { ++ ExternalAccountRequired bool `json:"externalAccountRequired,omitempty"` ++} ++ ++type challenge struct { ++ URI string `json:"uri"` ++ Type string `json:"type"` ++ Token string `json:"token"` ++} ++ ++type authorization struct { ++ Status string `json:"status"` ++ Challenges []challenge `json:"challenges"` ++ ++ domain string ++ id int ++} ++ ++type order struct { ++ Status string `json:"status"` ++ AuthzURLs []string `json:"authorizations"` ++ FinalizeURL string `json:"finalize"` // CSR submit URL ++ CertURL string `json:"certificate"` // already issued cert ++ ++ leaf []byte // issued cert in DER format ++} ++ ++func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { ++ ca.t.Logf("%s %s", r.Method, r.URL) ++ w.Header().Set("Replay-Nonce", "nonce") ++ // TODO: Verify nonce header for all POST requests. ++ ++ switch { ++ default: ++ ca.httpErrorf(w, http.StatusBadRequest, "unrecognized r.URL.Path: %s", r.URL.Path) ++ ++ // Discovery request. ++ case r.URL.Path == "/": ++ resp := &discovery{ ++ NewNonce: ca.serverURL("/new-nonce"), ++ NewAccount: ca.serverURL("/new-account"), ++ NewOrder: ca.serverURL("/new-order"), ++ Meta: discoveryMeta{ ++ ExternalAccountRequired: ca.eabRequired, ++ }, ++ } ++ if err := json.NewEncoder(w).Encode(resp); err != nil { ++ panic(fmt.Sprintf("discovery response: %v", err)) ++ } ++ ++ // Nonce requests. ++ case r.URL.Path == "/new-nonce": ++ // Nonce values are always set. Nothing else to do. ++ return ++ ++ // Client key registration request. ++ case r.URL.Path == "/new-account": ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ if ca.acctRegistered { ++ ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented") ++ return ++ } ++ ca.acctRegistered = true ++ ++ var req struct { ++ ExternalAccountBinding json.RawMessage ++ } ++ ++ if err := decodePayload(&req, r.Body); err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) ++ return ++ } ++ ++ if ca.eabRequired && len(req.ExternalAccountBinding) == 0 { ++ ca.httpErrorf(w, http.StatusBadRequest, "registration failed: no JWS for EAB") ++ return ++ } ++ ++ // TODO: Check the user account key against a ca.accountKeys? ++ w.Header().Set("Location", ca.serverURL("/accounts/1")) ++ w.WriteHeader(http.StatusCreated) ++ w.Write([]byte("{}")) ++ ++ // New order request. ++ case r.URL.Path == "/new-order": ++ var req struct { ++ Identifiers []struct{ Value string } ++ } ++ if err := decodePayload(&req, r.Body); err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) ++ return ++ } ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ o := &order{Status: acme.StatusPending} ++ for _, id := range req.Identifiers { ++ z := ca.authz(id.Value) ++ o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id)) ++ } ++ orderID := len(ca.orders) ++ ca.orders = append(ca.orders, o) ++ w.Header().Set("Location", ca.serverURL("/orders/%d", orderID)) ++ w.WriteHeader(http.StatusCreated) ++ if err := json.NewEncoder(w).Encode(o); err != nil { ++ panic(err) ++ } ++ ++ // Existing order status requests. ++ case strings.HasPrefix(r.URL.Path, "/orders/"): ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/")) ++ if err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) ++ return ++ } ++ if err := json.NewEncoder(w).Encode(o); err != nil { ++ panic(err) ++ } ++ ++ // Accept challenge requests. ++ case strings.HasPrefix(r.URL.Path, "/challenge/"): ++ parts := strings.Split(r.URL.Path, "/") ++ typ, id := parts[len(parts)-2], parts[len(parts)-1] ++ ca.mu.Lock() ++ supported := false ++ for _, suppTyp := range ca.challengeTypes { ++ if suppTyp == typ { ++ supported = true ++ } ++ } ++ a, err := ca.storedAuthz(id) ++ ca.mu.Unlock() ++ if !supported { ++ ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ) ++ return ++ } ++ if err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err) ++ return ++ } ++ ca.validateChallenge(a, typ) ++ w.Write([]byte("{}")) ++ ++ // Get authorization status requests. ++ case strings.HasPrefix(r.URL.Path, "/authz/"): ++ var req struct{ Status string } ++ decodePayload(&req, r.Body) ++ deactivate := req.Status == "deactivated" ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/")) ++ if err != nil { ++ ca.httpErrorf(w, http.StatusNotFound, "%v", err) ++ return ++ } ++ if deactivate { ++ // Note we don't invalidate authorized orders as we should. ++ authz.Status = "deactivated" ++ ca.t.Logf("authz %d is now %s", authz.id, authz.Status) ++ ca.updatePendingOrders() ++ } ++ if err := json.NewEncoder(w).Encode(authz); err != nil { ++ panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err)) ++ } ++ ++ // Certificate issuance request. ++ case strings.HasPrefix(r.URL.Path, "/new-cert/"): ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/") ++ o, err := ca.storedOrder(orderID) ++ if err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) ++ return ++ } ++ if o.Status != acme.StatusReady { ++ ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) ++ return ++ } ++ // Validate CSR request. ++ var req struct { ++ CSR string `json:"csr"` ++ } ++ decodePayload(&req, r.Body) ++ b, _ := base64.RawURLEncoding.DecodeString(req.CSR) ++ csr, err := x509.ParseCertificateRequest(b) ++ if err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) ++ return ++ } ++ // Issue the certificate. ++ der, err := ca.leafCert(csr) ++ if err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, "new-cert response: ca.leafCert: %v", err) ++ return ++ } ++ o.leaf = der ++ o.CertURL = ca.serverURL("/issued-cert/%s", orderID) ++ o.Status = acme.StatusValid ++ if err := json.NewEncoder(w).Encode(o); err != nil { ++ panic(err) ++ } ++ ++ // Already issued cert download requests. ++ case strings.HasPrefix(r.URL.Path, "/issued-cert/"): ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/")) ++ if err != nil { ++ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) ++ return ++ } ++ if o.Status != acme.StatusValid { ++ ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) ++ return ++ } ++ w.Header().Set("Content-Type", "application/pem-certificate-chain") ++ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: o.leaf}) ++ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: ca.rootCert}) ++ } ++} ++ ++// storedOrder retrieves a previously created order at index i. ++// It requires ca.mu to be locked. ++func (ca *CAServer) storedOrder(i string) (*order, error) { ++ idx, err := strconv.Atoi(i) ++ if err != nil { ++ return nil, fmt.Errorf("storedOrder: %v", err) ++ } ++ if idx < 0 { ++ return nil, fmt.Errorf("storedOrder: invalid order index %d", idx) ++ } ++ if idx > len(ca.orders)-1 { ++ return nil, fmt.Errorf("storedOrder: no such order %d", idx) ++ } ++ ++ ca.updatePendingOrders() ++ return ca.orders[idx], nil ++} ++ ++// storedAuthz retrieves a previously created authz at index i. ++// It requires ca.mu to be locked. ++func (ca *CAServer) storedAuthz(i string) (*authorization, error) { ++ idx, err := strconv.Atoi(i) ++ if err != nil { ++ return nil, fmt.Errorf("storedAuthz: %v", err) ++ } ++ if idx < 0 { ++ return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx) ++ } ++ if idx > len(ca.authorizations)-1 { ++ return nil, fmt.Errorf("storedAuthz: no such authz %d", idx) ++ } ++ return ca.authorizations[idx], nil ++} ++ ++// authz returns an existing valid authorization for the identifier or creates a ++// new one. It requires ca.mu to be locked. ++func (ca *CAServer) authz(identifier string) *authorization { ++ authz, ok := ca.validAuthz[identifier] ++ if !ok { ++ authzId := len(ca.authorizations) ++ authz = &authorization{ ++ id: authzId, ++ domain: identifier, ++ Status: acme.StatusPending, ++ } ++ for _, typ := range ca.challengeTypes { ++ authz.Challenges = append(authz.Challenges, challenge{ ++ Type: typ, ++ URI: ca.serverURL("/challenge/%s/%d", typ, authzId), ++ Token: challengeToken(authz.domain, typ, authzId), ++ }) ++ } ++ ca.authorizations = append(ca.authorizations, authz) ++ } ++ return authz ++} ++ ++// leafCert issues a new certificate. ++// It requires ca.mu to be locked. ++func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) { ++ ca.certCount++ // next leaf cert serial number ++ leaf := &x509.Certificate{ ++ SerialNumber: big.NewInt(int64(ca.certCount)), ++ Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, ++ NotBefore: time.Now(), ++ NotAfter: time.Now().Add(90 * 24 * time.Hour), ++ KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ++ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ++ DNSNames: csr.DNSNames, ++ BasicConstraintsValid: true, ++ } ++ if len(csr.DNSNames) == 0 { ++ leaf.DNSNames = []string{csr.Subject.CommonName} ++ } ++ return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey) ++} ++ ++// LeafCert issues a leaf certificate. ++func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate { ++ if ca.url == "" { ++ panic("LeafCert called before Start") ++ } ++ ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ var pk crypto.Signer ++ switch keyType { ++ case "RSA": ++ var err error ++ pk, err = rsa.GenerateKey(rand.Reader, 1024) ++ if err != nil { ++ ca.t.Fatal(err) ++ } ++ case "ECDSA": ++ var err error ++ pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ ca.t.Fatal(err) ++ } ++ default: ++ panic("LeafCert: unknown key type") ++ } ++ ca.certCount++ // next leaf cert serial number ++ leaf := &x509.Certificate{ ++ SerialNumber: big.NewInt(int64(ca.certCount)), ++ Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, ++ NotBefore: notBefore, ++ NotAfter: notAfter, ++ KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ++ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ++ DNSNames: []string{name}, ++ BasicConstraintsValid: true, ++ } ++ der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey) ++ if err != nil { ++ ca.t.Fatal(err) ++ } ++ return &tls.Certificate{ ++ Certificate: [][]byte{der}, ++ PrivateKey: pk, ++ } ++} ++ ++func (ca *CAServer) validateChallenge(authz *authorization, typ string) { ++ var err error ++ switch typ { ++ case "tls-alpn-01": ++ err = ca.verifyALPNChallenge(authz) ++ case "http-01": ++ err = ca.verifyHTTPChallenge(authz) ++ default: ++ panic(fmt.Sprintf("validation of %q is not implemented", typ)) ++ } ++ ca.mu.Lock() ++ defer ca.mu.Unlock() ++ if err != nil { ++ authz.Status = "invalid" ++ } else { ++ authz.Status = "valid" ++ ca.validAuthz[authz.domain] = authz ++ } ++ ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err) ++ ca.t.Logf("authz %d is now %s", authz.id, authz.Status) ++ ++ ca.updatePendingOrders() ++} ++ ++func (ca *CAServer) updatePendingOrders() { ++ // Update all pending orders. ++ // An order becomes "ready" if all authorizations are "valid". ++ // An order becomes "invalid" if any authorization is "invalid". ++ // Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6 ++ for i, o := range ca.orders { ++ if o.Status != acme.StatusPending { ++ continue ++ } ++ ++ countValid, countInvalid := ca.validateAuthzURLs(o.AuthzURLs, i) ++ if countInvalid > 0 { ++ o.Status = acme.StatusInvalid ++ ca.t.Logf("order %d is now invalid", i) ++ continue ++ } ++ if countValid == len(o.AuthzURLs) { ++ o.Status = acme.StatusReady ++ o.FinalizeURL = ca.serverURL("/new-cert/%d", i) ++ ca.t.Logf("order %d is now ready", i) ++ } ++ } ++} ++ ++func (ca *CAServer) validateAuthzURLs(urls []string, orderNum int) (countValid, countInvalid int) { ++ for _, zurl := range urls { ++ z, err := ca.storedAuthz(path.Base(zurl)) ++ if err != nil { ++ ca.t.Logf("no authz %q for order %d", zurl, orderNum) ++ continue ++ } ++ if z.Status == acme.StatusInvalid { ++ countInvalid++ ++ } ++ if z.Status == acme.StatusValid { ++ countValid++ ++ } ++ } ++ return countValid, countInvalid ++} ++ ++func (ca *CAServer) verifyALPNChallenge(a *authorization) error { ++ const acmeALPNProto = "acme-tls/1" ++ ++ addr, haveAddr := ca.addr(a.domain) ++ getCert, haveGetCert := ca.getCert(a.domain) ++ if !haveAddr && !haveGetCert { ++ return fmt.Errorf("no resolution information for %q", a.domain) ++ } ++ if haveAddr && haveGetCert { ++ return fmt.Errorf("overlapping resolution information for %q", a.domain) ++ } ++ ++ var crt *x509.Certificate ++ switch { ++ case haveAddr: ++ conn, err := tls.Dial("tcp", addr, &tls.Config{ ++ ServerName: a.domain, ++ InsecureSkipVerify: true, ++ NextProtos: []string{acmeALPNProto}, ++ MinVersion: tls.VersionTLS12, ++ }) ++ if err != nil { ++ return err ++ } ++ if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { ++ return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) ++ } ++ if n := len(conn.ConnectionState().PeerCertificates); n != 1 { ++ return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) ++ } ++ crt = conn.ConnectionState().PeerCertificates[0] ++ case haveGetCert: ++ hello := &tls.ClientHelloInfo{ ++ ServerName: a.domain, ++ // TODO: support selecting ECDSA. ++ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, ++ SupportedProtos: []string{acme.ALPNProto}, ++ SupportedVersions: []uint16{tls.VersionTLS12}, ++ } ++ c, err := getCert(hello) ++ if err != nil { ++ return err ++ } ++ crt, err = x509.ParseCertificate(c.Certificate[0]) ++ if err != nil { ++ return err ++ } ++ } ++ ++ if err := crt.VerifyHostname(a.domain); err != nil { ++ return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err) ++ } ++ // See RFC 8737, Section 6.1. ++ oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} ++ for _, x := range crt.Extensions { ++ if x.Id.Equal(oid) { ++ // TODO: check the token. ++ return nil ++ } ++ } ++ return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found") ++} ++ ++func (ca *CAServer) verifyHTTPChallenge(a *authorization) error { ++ addr, haveAddr := ca.addr(a.domain) ++ handler, haveHandler := ca.getHandler(a.domain) ++ if !haveAddr && !haveHandler { ++ return fmt.Errorf("no resolution information for %q", a.domain) ++ } ++ if haveAddr && haveHandler { ++ return fmt.Errorf("overlapping resolution information for %q", a.domain) ++ } ++ ++ token := challengeToken(a.domain, "http-01", a.id) ++ path := "/.well-known/acme-challenge/" + token ++ ++ var body string ++ switch { ++ case haveAddr: ++ t := &http.Transport{ ++ DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { ++ return (&net.Dialer{}).DialContext(ctx, network, addr) ++ }, ++ } ++ req, err := http.NewRequest("GET", "http://"+a.domain+path, nil) ++ if err != nil { ++ return err ++ } ++ res, err := t.RoundTrip(req) ++ if err != nil { ++ return err ++ } ++ if res.StatusCode != http.StatusOK { ++ return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK) ++ } ++ b, err := io.ReadAll(res.Body) ++ if err != nil { ++ return err ++ } ++ body = string(b) ++ case haveHandler: ++ r := httptest.NewRequest("GET", path, nil) ++ r.Host = a.domain ++ w := httptest.NewRecorder() ++ handler.ServeHTTP(w, r) ++ if w.Code != http.StatusOK { ++ return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) ++ } ++ body = w.Body.String() ++ } ++ ++ if !strings.HasPrefix(body, token) { ++ return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body) ++ } ++ return nil ++} ++ ++func decodePayload(v interface{}, r io.Reader) error { ++ var req struct{ Payload string } ++ if err := json.NewDecoder(r).Decode(&req); err != nil { ++ return err ++ } ++ payload, err := base64.RawURLEncoding.DecodeString(req.Payload) ++ if err != nil { ++ return err ++ } ++ return json.Unmarshal(payload, v) ++} ++ ++func challengeToken(domain, challType string, authzID int) string { ++ return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID) ++} ++ ++func unique(a []string) []string { ++ seen := make(map[string]bool) ++ var res []string ++ for _, s := range a { ++ if s != "" && !seen[s] { ++ seen[s] = true ++ res = append(res, s) ++ } ++ } ++ return res ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/listener.go b/ms_mod/golang.org/x/crypto/acme/autocert/listener.go +new file mode 100644 +index 00000000000000..9d62f8cedcd4c7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/listener.go +@@ -0,0 +1,155 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert ++ ++import ( ++ "crypto/tls" ++ "log" ++ "net" ++ "os" ++ "path/filepath" ++ "runtime" ++ "time" ++) ++ ++// NewListener returns a net.Listener that listens on the standard TLS ++// port (443) on all interfaces and returns *tls.Conn connections with ++// LetsEncrypt certificates for the provided domain or domains. ++// ++// It enables one-line HTTPS servers: ++// ++// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) ++// ++// NewListener is a convenience function for a common configuration. ++// More complex or custom configurations can use the autocert.Manager ++// type instead. ++// ++// Use of this function implies acceptance of the LetsEncrypt Terms of ++// Service. If domains is not empty, the provided domains are passed ++// to HostWhitelist. If domains is empty, the listener will do ++// LetsEncrypt challenges for any requested domain, which is not ++// recommended. ++// ++// Certificates are cached in a "golang-autocert" directory under an ++// operating system-specific cache or temp directory. This may not ++// be suitable for servers spanning multiple machines. ++// ++// The returned listener uses a *tls.Config that enables HTTP/2, and ++// should only be used with servers that support HTTP/2. ++// ++// The returned Listener also enables TCP keep-alives on the accepted ++// connections. The returned *tls.Conn are returned before their TLS ++// handshake has completed. ++func NewListener(domains ...string) net.Listener { ++ m := &Manager{ ++ Prompt: AcceptTOS, ++ } ++ if len(domains) > 0 { ++ m.HostPolicy = HostWhitelist(domains...) ++ } ++ dir := cacheDir() ++ if err := os.MkdirAll(dir, 0700); err != nil { ++ log.Printf("warning: autocert.NewListener not using a cache: %v", err) ++ } else { ++ m.Cache = DirCache(dir) ++ } ++ return m.Listener() ++} ++ ++// Listener listens on the standard TLS port (443) on all interfaces ++// and returns a net.Listener returning *tls.Conn connections. ++// ++// The returned listener uses a *tls.Config that enables HTTP/2, and ++// should only be used with servers that support HTTP/2. ++// ++// The returned Listener also enables TCP keep-alives on the accepted ++// connections. The returned *tls.Conn are returned before their TLS ++// handshake has completed. ++// ++// Unlike NewListener, it is the caller's responsibility to initialize ++// the Manager m's Prompt, Cache, HostPolicy, and other desired options. ++func (m *Manager) Listener() net.Listener { ++ ln := &listener{ ++ conf: m.TLSConfig(), ++ } ++ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") ++ return ln ++} ++ ++type listener struct { ++ conf *tls.Config ++ ++ tcpListener net.Listener ++ tcpListenErr error ++} ++ ++func (ln *listener) Accept() (net.Conn, error) { ++ if ln.tcpListenErr != nil { ++ return nil, ln.tcpListenErr ++ } ++ conn, err := ln.tcpListener.Accept() ++ if err != nil { ++ return nil, err ++ } ++ tcpConn := conn.(*net.TCPConn) ++ ++ // Because Listener is a convenience function, help out with ++ // this too. This is not possible for the caller to set once ++ // we return a *tcp.Conn wrapping an inaccessible net.Conn. ++ // If callers don't want this, they can do things the manual ++ // way and tweak as needed. But this is what net/http does ++ // itself, so copy that. If net/http changes, we can change ++ // here too. ++ tcpConn.SetKeepAlive(true) ++ tcpConn.SetKeepAlivePeriod(3 * time.Minute) ++ ++ return tls.Server(tcpConn, ln.conf), nil ++} ++ ++func (ln *listener) Addr() net.Addr { ++ if ln.tcpListener != nil { ++ return ln.tcpListener.Addr() ++ } ++ // net.Listen failed. Return something non-nil in case callers ++ // call Addr before Accept: ++ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443} ++} ++ ++func (ln *listener) Close() error { ++ if ln.tcpListenErr != nil { ++ return ln.tcpListenErr ++ } ++ return ln.tcpListener.Close() ++} ++ ++func homeDir() string { ++ if runtime.GOOS == "windows" { ++ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") ++ } ++ if h := os.Getenv("HOME"); h != "" { ++ return h ++ } ++ return "/" ++} ++ ++func cacheDir() string { ++ const base = "golang-autocert" ++ switch runtime.GOOS { ++ case "darwin": ++ return filepath.Join(homeDir(), "Library", "Caches", base) ++ case "windows": ++ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} { ++ if v := os.Getenv(ev); v != "" { ++ return filepath.Join(v, base) ++ } ++ } ++ // Worst case: ++ return filepath.Join(homeDir(), base) ++ } ++ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" { ++ return filepath.Join(xdg, base) ++ } ++ return filepath.Join(homeDir(), ".cache", base) ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/renewal.go b/ms_mod/golang.org/x/crypto/acme/autocert/renewal.go +new file mode 100644 +index 00000000000000..0df7da78a6f6cc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/renewal.go +@@ -0,0 +1,156 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert ++ ++import ( ++ "context" ++ "crypto" ++ "sync" ++ "time" ++) ++ ++// renewJitter is the maximum deviation from Manager.RenewBefore. ++const renewJitter = time.Hour ++ ++// domainRenewal tracks the state used by the periodic timers ++// renewing a single domain's cert. ++type domainRenewal struct { ++ m *Manager ++ ck certKey ++ key crypto.Signer ++ ++ timerMu sync.Mutex ++ timer *time.Timer ++ timerClose chan struct{} // if non-nil, renew closes this channel (and nils out the timer fields) instead of running ++} ++ ++// start starts a cert renewal timer at the time ++// defined by the certificate expiration time exp. ++// ++// If the timer is already started, calling start is a noop. ++func (dr *domainRenewal) start(exp time.Time) { ++ dr.timerMu.Lock() ++ defer dr.timerMu.Unlock() ++ if dr.timer != nil { ++ return ++ } ++ dr.timer = time.AfterFunc(dr.next(exp), dr.renew) ++} ++ ++// stop stops the cert renewal timer and waits for any in-flight calls to renew ++// to complete. If the timer is already stopped, calling stop is a noop. ++func (dr *domainRenewal) stop() { ++ dr.timerMu.Lock() ++ defer dr.timerMu.Unlock() ++ for { ++ if dr.timer == nil { ++ return ++ } ++ if dr.timer.Stop() { ++ dr.timer = nil ++ return ++ } else { ++ // dr.timer fired, and we acquired dr.timerMu before the renew callback did. ++ // (We know this because otherwise the renew callback would have reset dr.timer!) ++ timerClose := make(chan struct{}) ++ dr.timerClose = timerClose ++ dr.timerMu.Unlock() ++ <-timerClose ++ dr.timerMu.Lock() ++ } ++ } ++} ++ ++// renew is called periodically by a timer. ++// The first renew call is kicked off by dr.start. ++func (dr *domainRenewal) renew() { ++ dr.timerMu.Lock() ++ defer dr.timerMu.Unlock() ++ if dr.timerClose != nil { ++ close(dr.timerClose) ++ dr.timer, dr.timerClose = nil, nil ++ return ++ } ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) ++ defer cancel() ++ // TODO: rotate dr.key at some point? ++ next, err := dr.do(ctx) ++ if err != nil { ++ next = renewJitter / 2 ++ next += time.Duration(pseudoRand.int63n(int64(next))) ++ } ++ testDidRenewLoop(next, err) ++ dr.timer = time.AfterFunc(next, dr.renew) ++} ++ ++// updateState locks and replaces the relevant Manager.state item with the given ++// state. It additionally updates dr.key with the given state's key. ++func (dr *domainRenewal) updateState(state *certState) { ++ dr.m.stateMu.Lock() ++ defer dr.m.stateMu.Unlock() ++ dr.key = state.key ++ dr.m.state[dr.ck] = state ++} ++ ++// do is similar to Manager.createCert but it doesn't lock a Manager.state item. ++// Instead, it requests a new certificate independently and, upon success, ++// replaces dr.m.state item with a new one and updates cache for the given domain. ++// ++// It may lock and update the Manager.state if the expiration date of the currently ++// cached cert is far enough in the future. ++// ++// The returned value is a time interval after which the renewal should occur again. ++func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { ++ // a race is likely unavoidable in a distributed environment ++ // but we try nonetheless ++ if tlscert, err := dr.m.cacheGet(ctx, dr.ck); err == nil { ++ next := dr.next(tlscert.Leaf.NotAfter) ++ if next > dr.m.renewBefore()+renewJitter { ++ signer, ok := tlscert.PrivateKey.(crypto.Signer) ++ if ok { ++ state := &certState{ ++ key: signer, ++ cert: tlscert.Certificate, ++ leaf: tlscert.Leaf, ++ } ++ dr.updateState(state) ++ return next, nil ++ } ++ } ++ } ++ ++ der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.ck) ++ if err != nil { ++ return 0, err ++ } ++ state := &certState{ ++ key: dr.key, ++ cert: der, ++ leaf: leaf, ++ } ++ tlscert, err := state.tlscert() ++ if err != nil { ++ return 0, err ++ } ++ if err := dr.m.cachePut(ctx, dr.ck, tlscert); err != nil { ++ return 0, err ++ } ++ dr.updateState(state) ++ return dr.next(leaf.NotAfter), nil ++} ++ ++func (dr *domainRenewal) next(expiry time.Time) time.Duration { ++ d := expiry.Sub(dr.m.now()) - dr.m.renewBefore() ++ // add a bit of randomness to renew deadline ++ n := pseudoRand.int63n(int64(renewJitter)) ++ d -= time.Duration(n) ++ if d < 0 { ++ return 0 ++ } ++ return d ++} ++ ++var testDidRenewLoop = func(next time.Duration, err error) {} +diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go +new file mode 100644 +index 00000000000000..ffe4af2a5ce2f5 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go +@@ -0,0 +1,269 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package autocert ++ ++import ( ++ "context" ++ "crypto" ++ "crypto/ecdsa" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/acme" ++ "golang.org/x/crypto/acme/autocert/internal/acmetest" ++) ++ ++func TestRenewalNext(t *testing.T) { ++ now := time.Now() ++ man := &Manager{ ++ RenewBefore: 7 * 24 * time.Hour, ++ nowFunc: func() time.Time { return now }, ++ } ++ defer man.stopRenew() ++ tt := []struct { ++ expiry time.Time ++ min, max time.Duration ++ }{ ++ {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour}, ++ {now.Add(time.Hour), 0, 1}, ++ {now, 0, 1}, ++ {now.Add(-time.Hour), 0, 1}, ++ } ++ ++ dr := &domainRenewal{m: man} ++ for i, test := range tt { ++ next := dr.next(test.expiry) ++ if next < test.min || test.max < next { ++ t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max) ++ } ++ } ++} ++ ++func TestRenewFromCache(t *testing.T) { ++ man := testManager(t) ++ man.RenewBefore = 24 * time.Hour ++ ++ ca := acmetest.NewCAServer(t).Start() ++ ca.ResolveGetCertificate(exampleDomain, man.GetCertificate) ++ ++ man.Client = &acme.Client{ ++ DirectoryURL: ca.URL(), ++ } ++ ++ // cache an almost expired cert ++ now := time.Now() ++ c := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Minute)) ++ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { ++ t.Fatal(err) ++ } ++ ++ // verify the renewal happened ++ defer func() { ++ // Stop the timers that read and execute testDidRenewLoop before restoring it. ++ // Otherwise the timer callback may race with the deferred write. ++ man.stopRenew() ++ testDidRenewLoop = func(next time.Duration, err error) {} ++ }() ++ renewed := make(chan bool, 1) ++ testDidRenewLoop = func(next time.Duration, err error) { ++ defer func() { ++ select { ++ case renewed <- true: ++ default: ++ // The renewal timer uses a random backoff. If the first renewal fails for ++ // some reason, we could end up with multiple calls here before the test ++ // stops the timer. ++ } ++ }() ++ ++ if err != nil { ++ t.Errorf("testDidRenewLoop: %v", err) ++ } ++ // Next should be about 90 days: ++ // CaServer creates 90days expiry + account for man.RenewBefore. ++ // Previous expiration was within 1 min. ++ future := 88 * 24 * time.Hour ++ if next < future { ++ t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future) ++ } ++ ++ // ensure the new cert is cached ++ after := time.Now().Add(future) ++ tlscert, err := man.cacheGet(context.Background(), exampleCertKey) ++ if err != nil { ++ t.Errorf("man.cacheGet: %v", err) ++ return ++ } ++ if !tlscert.Leaf.NotAfter.After(after) { ++ t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) ++ } ++ ++ // verify the old cert is also replaced in memory ++ man.stateMu.Lock() ++ defer man.stateMu.Unlock() ++ s := man.state[exampleCertKey] ++ if s == nil { ++ t.Errorf("m.state[%q] is nil", exampleCertKey) ++ return ++ } ++ tlscert, err = s.tlscert() ++ if err != nil { ++ t.Errorf("s.tlscert: %v", err) ++ return ++ } ++ if !tlscert.Leaf.NotAfter.After(after) { ++ t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) ++ } ++ } ++ ++ // trigger renew ++ hello := clientHelloInfo(exampleDomain, algECDSA) ++ if _, err := man.GetCertificate(hello); err != nil { ++ t.Fatal(err) ++ } ++ <-renewed ++} ++ ++func TestRenewFromCacheAlreadyRenewed(t *testing.T) { ++ ca := acmetest.NewCAServer(t).Start() ++ man := testManager(t) ++ man.RenewBefore = 24 * time.Hour ++ man.Client = &acme.Client{ ++ DirectoryURL: "invalid", ++ } ++ ++ // cache a recently renewed cert with a different private key ++ now := time.Now() ++ newCert := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Hour*24*90)) ++ if err := man.cachePut(context.Background(), exampleCertKey, newCert); err != nil { ++ t.Fatal(err) ++ } ++ newLeaf, err := validCert(exampleCertKey, newCert.Certificate, newCert.PrivateKey.(crypto.Signer), now) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // set internal state to an almost expired cert ++ oldCert := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Minute)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ oldLeaf, err := validCert(exampleCertKey, oldCert.Certificate, oldCert.PrivateKey.(crypto.Signer), now) ++ if err != nil { ++ t.Fatal(err) ++ } ++ man.stateMu.Lock() ++ if man.state == nil { ++ man.state = make(map[certKey]*certState) ++ } ++ s := &certState{ ++ key: oldCert.PrivateKey.(crypto.Signer), ++ cert: oldCert.Certificate, ++ leaf: oldLeaf, ++ } ++ man.state[exampleCertKey] = s ++ man.stateMu.Unlock() ++ ++ // verify the renewal accepted the newer cached cert ++ defer func() { ++ // Stop the timers that read and execute testDidRenewLoop before restoring it. ++ // Otherwise the timer callback may race with the deferred write. ++ man.stopRenew() ++ testDidRenewLoop = func(next time.Duration, err error) {} ++ }() ++ renewed := make(chan bool, 1) ++ testDidRenewLoop = func(next time.Duration, err error) { ++ defer func() { ++ select { ++ case renewed <- true: ++ default: ++ // The renewal timer uses a random backoff. If the first renewal fails for ++ // some reason, we could end up with multiple calls here before the test ++ // stops the timer. ++ } ++ }() ++ ++ if err != nil { ++ t.Errorf("testDidRenewLoop: %v", err) ++ } ++ // Next should be about 90 days ++ // Previous expiration was within 1 min. ++ future := 88 * 24 * time.Hour ++ if next < future { ++ t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future) ++ } ++ ++ // ensure the cached cert was not modified ++ tlscert, err := man.cacheGet(context.Background(), exampleCertKey) ++ if err != nil { ++ t.Errorf("man.cacheGet: %v", err) ++ return ++ } ++ if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { ++ t.Errorf("cache leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) ++ } ++ ++ // verify the old cert is also replaced in memory ++ man.stateMu.Lock() ++ defer man.stateMu.Unlock() ++ s := man.state[exampleCertKey] ++ if s == nil { ++ t.Errorf("m.state[%q] is nil", exampleCertKey) ++ return ++ } ++ stateKey := s.key.Public().(*ecdsa.PublicKey) ++ if !stateKey.Equal(newLeaf.PublicKey) { ++ t.Error("state key was not updated from cache") ++ return ++ } ++ tlscert, err = s.tlscert() ++ if err != nil { ++ t.Errorf("s.tlscert: %v", err) ++ return ++ } ++ if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { ++ t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) ++ } ++ } ++ ++ // assert the expiring cert is returned from state ++ hello := clientHelloInfo(exampleDomain, algECDSA) ++ tlscert, err := man.GetCertificate(hello) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if !oldLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { ++ t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, oldLeaf.NotAfter) ++ } ++ ++ // trigger renew ++ man.startRenew(exampleCertKey, s.key, s.leaf.NotAfter) ++ <-renewed ++ func() { ++ man.renewalMu.Lock() ++ defer man.renewalMu.Unlock() ++ ++ // verify the private key is replaced in the renewal state ++ r := man.renewal[exampleCertKey] ++ if r == nil { ++ t.Errorf("m.renewal[%q] is nil", exampleCertKey) ++ return ++ } ++ renewalKey := r.key.Public().(*ecdsa.PublicKey) ++ if !renewalKey.Equal(newLeaf.PublicKey) { ++ t.Error("renewal private key was not updated from cache") ++ } ++ }() ++ ++ // assert the new cert is returned from state after renew ++ hello = clientHelloInfo(exampleDomain, algECDSA) ++ tlscert, err = man.GetCertificate(hello) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if !newLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { ++ t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/http.go b/ms_mod/golang.org/x/crypto/acme/http.go +new file mode 100644 +index 00000000000000..58836e5d303e01 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/http.go +@@ -0,0 +1,325 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "bytes" ++ "context" ++ "crypto" ++ "crypto/rand" ++ "encoding/json" ++ "errors" ++ "fmt" ++ "io" ++ "math/big" ++ "net/http" ++ "strconv" ++ "strings" ++ "time" ++) ++ ++// retryTimer encapsulates common logic for retrying unsuccessful requests. ++// It is not safe for concurrent use. ++type retryTimer struct { ++ // backoffFn provides backoff delay sequence for retries. ++ // See Client.RetryBackoff doc comment. ++ backoffFn func(n int, r *http.Request, res *http.Response) time.Duration ++ // n is the current retry attempt. ++ n int ++} ++ ++func (t *retryTimer) inc() { ++ t.n++ ++} ++ ++// backoff pauses the current goroutine as described in Client.RetryBackoff. ++func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error { ++ d := t.backoffFn(t.n, r, res) ++ if d <= 0 { ++ return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n) ++ } ++ wakeup := time.NewTimer(d) ++ defer wakeup.Stop() ++ select { ++ case <-ctx.Done(): ++ return ctx.Err() ++ case <-wakeup.C: ++ return nil ++ } ++} ++ ++func (c *Client) retryTimer() *retryTimer { ++ f := c.RetryBackoff ++ if f == nil { ++ f = defaultBackoff ++ } ++ return &retryTimer{backoffFn: f} ++} ++ ++// defaultBackoff provides default Client.RetryBackoff implementation ++// using a truncated exponential backoff algorithm, ++// as described in Client.RetryBackoff. ++// ++// The n argument is always bounded between 1 and 30. ++// The returned value is always greater than 0. ++func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration { ++ const max = 10 * time.Second ++ var jitter time.Duration ++ if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { ++ // Set the minimum to 1ms to avoid a case where ++ // an invalid Retry-After value is parsed into 0 below, ++ // resulting in the 0 returned value which would unintentionally ++ // stop the retries. ++ jitter = (1 + time.Duration(x.Int64())) * time.Millisecond ++ } ++ if v, ok := res.Header["Retry-After"]; ok { ++ return retryAfter(v[0]) + jitter ++ } ++ ++ if n < 1 { ++ n = 1 ++ } ++ if n > 30 { ++ n = 30 ++ } ++ d := time.Duration(1< max { ++ return max ++ } ++ return d ++} ++ ++// retryAfter parses a Retry-After HTTP header value, ++// trying to convert v into an int (seconds) or use http.ParseTime otherwise. ++// It returns zero value if v cannot be parsed. ++func retryAfter(v string) time.Duration { ++ if i, err := strconv.Atoi(v); err == nil { ++ return time.Duration(i) * time.Second ++ } ++ t, err := http.ParseTime(v) ++ if err != nil { ++ return 0 ++ } ++ return t.Sub(timeNow()) ++} ++ ++// resOkay is a function that reports whether the provided response is okay. ++// It is expected to keep the response body unread. ++type resOkay func(*http.Response) bool ++ ++// wantStatus returns a function which reports whether the code ++// matches the status code of a response. ++func wantStatus(codes ...int) resOkay { ++ return func(res *http.Response) bool { ++ for _, code := range codes { ++ if code == res.StatusCode { ++ return true ++ } ++ } ++ return false ++ } ++} ++ ++// get issues an unsigned GET request to the specified URL. ++// It returns a non-error value only when ok reports true. ++// ++// get retries unsuccessful attempts according to c.RetryBackoff ++// until the context is done or a non-retriable error is received. ++func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) { ++ retry := c.retryTimer() ++ for { ++ req, err := http.NewRequest("GET", url, nil) ++ if err != nil { ++ return nil, err ++ } ++ res, err := c.doNoRetry(ctx, req) ++ switch { ++ case err != nil: ++ return nil, err ++ case ok(res): ++ return res, nil ++ case isRetriable(res.StatusCode): ++ retry.inc() ++ resErr := responseError(res) ++ res.Body.Close() ++ // Ignore the error value from retry.backoff ++ // and return the one from last retry, as received from the CA. ++ if retry.backoff(ctx, req, res) != nil { ++ return nil, resErr ++ } ++ default: ++ defer res.Body.Close() ++ return nil, responseError(res) ++ } ++ } ++} ++ ++// postAsGet is POST-as-GET, a replacement for GET in RFC 8555 ++// as described in https://tools.ietf.org/html/rfc8555#section-6.3. ++// It makes a POST request in KID form with zero JWS payload. ++// See nopayload doc comments in jws.go. ++func (c *Client) postAsGet(ctx context.Context, url string, ok resOkay) (*http.Response, error) { ++ return c.post(ctx, nil, url, noPayload, ok) ++} ++ ++// post issues a signed POST request in JWS format using the provided key ++// to the specified URL. If key is nil, c.Key is used instead. ++// It returns a non-error value only when ok reports true. ++// ++// post retries unsuccessful attempts according to c.RetryBackoff ++// until the context is done or a non-retriable error is received. ++// It uses postNoRetry to make individual requests. ++func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) { ++ retry := c.retryTimer() ++ for { ++ res, req, err := c.postNoRetry(ctx, key, url, body) ++ if err != nil { ++ return nil, err ++ } ++ if ok(res) { ++ return res, nil ++ } ++ resErr := responseError(res) ++ res.Body.Close() ++ switch { ++ // Check for bad nonce before isRetriable because it may have been returned ++ // with an unretriable response code such as 400 Bad Request. ++ case isBadNonce(resErr): ++ // Consider any previously stored nonce values to be invalid. ++ c.clearNonces() ++ case !isRetriable(res.StatusCode): ++ return nil, resErr ++ } ++ retry.inc() ++ // Ignore the error value from retry.backoff ++ // and return the one from last retry, as received from the CA. ++ if err := retry.backoff(ctx, req, res); err != nil { ++ return nil, resErr ++ } ++ } ++} ++ ++// postNoRetry signs the body with the given key and POSTs it to the provided url. ++// It is used by c.post to retry unsuccessful attempts. ++// The body argument must be JSON-serializable. ++// ++// If key argument is nil, c.Key is used to sign the request. ++// If key argument is nil and c.accountKID returns a non-zero keyID, ++// the request is sent in KID form. Otherwise, JWK form is used. ++// ++// In practice, when interfacing with RFC-compliant CAs most requests are sent in KID form ++// and JWK is used only when KID is unavailable: new account endpoint and certificate ++// revocation requests authenticated by a cert key. ++// See jwsEncodeJSON for other details. ++func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) { ++ kid := noKeyID ++ if key == nil { ++ if c.Key == nil { ++ return nil, nil, errors.New("acme: Client.Key must be populated to make POST requests") ++ } ++ key = c.Key ++ kid = c.accountKID(ctx) ++ } ++ nonce, err := c.popNonce(ctx, url) ++ if err != nil { ++ return nil, nil, err ++ } ++ b, err := jwsEncodeJSON(body, key, kid, nonce, url) ++ if err != nil { ++ return nil, nil, err ++ } ++ req, err := http.NewRequest("POST", url, bytes.NewReader(b)) ++ if err != nil { ++ return nil, nil, err ++ } ++ req.Header.Set("Content-Type", "application/jose+json") ++ res, err := c.doNoRetry(ctx, req) ++ if err != nil { ++ return nil, nil, err ++ } ++ c.addNonce(res.Header) ++ return res, req, nil ++} ++ ++// doNoRetry issues a request req, replacing its context (if any) with ctx. ++func (c *Client) doNoRetry(ctx context.Context, req *http.Request) (*http.Response, error) { ++ req.Header.Set("User-Agent", c.userAgent()) ++ res, err := c.httpClient().Do(req.WithContext(ctx)) ++ if err != nil { ++ select { ++ case <-ctx.Done(): ++ // Prefer the unadorned context error. ++ // (The acme package had tests assuming this, previously from ctxhttp's ++ // behavior, predating net/http supporting contexts natively) ++ // TODO(bradfitz): reconsider this in the future. But for now this ++ // requires no test updates. ++ return nil, ctx.Err() ++ default: ++ return nil, err ++ } ++ } ++ return res, nil ++} ++ ++func (c *Client) httpClient() *http.Client { ++ if c.HTTPClient != nil { ++ return c.HTTPClient ++ } ++ return http.DefaultClient ++} ++ ++// packageVersion is the version of the module that contains this package, for ++// sending as part of the User-Agent header. It's set in version_go112.go. ++var packageVersion string ++ ++// userAgent returns the User-Agent header value. It includes the package name, ++// the module version (if available), and the c.UserAgent value (if set). ++func (c *Client) userAgent() string { ++ ua := "golang.org/x/crypto/acme" ++ if packageVersion != "" { ++ ua += "@" + packageVersion ++ } ++ if c.UserAgent != "" { ++ ua = c.UserAgent + " " + ua ++ } ++ return ua ++} ++ ++// isBadNonce reports whether err is an ACME "badnonce" error. ++func isBadNonce(err error) bool { ++ // According to the spec badNonce is urn:ietf:params:acme:error:badNonce. ++ // However, ACME servers in the wild return their versions of the error. ++ // See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 ++ // and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66. ++ ae, ok := err.(*Error) ++ return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") ++} ++ ++// isRetriable reports whether a request can be retried ++// based on the response status code. ++// ++// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code. ++// Callers should parse the response and check with isBadNonce. ++func isRetriable(code int) bool { ++ return code <= 399 || code >= 500 || code == http.StatusTooManyRequests ++} ++ ++// responseError creates an error of Error type from resp. ++func responseError(resp *http.Response) error { ++ // don't care if ReadAll returns an error: ++ // json.Unmarshal will fail in that case anyway ++ b, _ := io.ReadAll(resp.Body) ++ e := &wireError{Status: resp.StatusCode} ++ if err := json.Unmarshal(b, e); err != nil { ++ // this is not a regular error response: ++ // populate detail with anything we received, ++ // e.Status will already contain HTTP response code value ++ e.Detail = string(b) ++ if e.Detail == "" { ++ e.Detail = resp.Status ++ } ++ } ++ return e.error(resp.Header) ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/http_test.go b/ms_mod/golang.org/x/crypto/acme/http_test.go +new file mode 100644 +index 00000000000000..d124e4e219abe6 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/http_test.go +@@ -0,0 +1,255 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "context" ++ "fmt" ++ "io" ++ "net/http" ++ "net/http/httptest" ++ "reflect" ++ "strings" ++ "testing" ++ "time" ++) ++ ++func TestDefaultBackoff(t *testing.T) { ++ tt := []struct { ++ nretry int ++ retryAfter string // Retry-After header ++ out time.Duration // expected min; max = min + jitter ++ }{ ++ {-1, "", time.Second}, // verify the lower bound is 1 ++ {0, "", time.Second}, // verify the lower bound is 1 ++ {100, "", 10 * time.Second}, // verify the ceiling ++ {1, "3600", time.Hour}, // verify the header value is used ++ {1, "", 1 * time.Second}, ++ {2, "", 2 * time.Second}, ++ {3, "", 4 * time.Second}, ++ {4, "", 8 * time.Second}, ++ } ++ for i, test := range tt { ++ r := httptest.NewRequest("GET", "/", nil) ++ resp := &http.Response{Header: http.Header{}} ++ if test.retryAfter != "" { ++ resp.Header.Set("Retry-After", test.retryAfter) ++ } ++ d := defaultBackoff(test.nretry, r, resp) ++ max := test.out + time.Second // + max jitter ++ if d < test.out || max < d { ++ t.Errorf("%d: defaultBackoff(%v) = %v; want between %v and %v", i, test.nretry, d, test.out, max) ++ } ++ } ++} ++ ++func TestErrorResponse(t *testing.T) { ++ s := `{ ++ "status": 400, ++ "type": "urn:acme:error:xxx", ++ "detail": "text" ++ }` ++ res := &http.Response{ ++ StatusCode: 400, ++ Status: "400 Bad Request", ++ Body: io.NopCloser(strings.NewReader(s)), ++ Header: http.Header{"X-Foo": {"bar"}}, ++ } ++ err := responseError(res) ++ v, ok := err.(*Error) ++ if !ok { ++ t.Fatalf("err = %+v (%T); want *Error type", err, err) ++ } ++ if v.StatusCode != 400 { ++ t.Errorf("v.StatusCode = %v; want 400", v.StatusCode) ++ } ++ if v.ProblemType != "urn:acme:error:xxx" { ++ t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType) ++ } ++ if v.Detail != "text" { ++ t.Errorf("v.Detail = %q; want text", v.Detail) ++ } ++ if !reflect.DeepEqual(v.Header, res.Header) { ++ t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header) ++ } ++} ++ ++func TestPostWithRetries(t *testing.T) { ++ var count int ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ count++ ++ w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) ++ if r.Method == "HEAD" { ++ // We expect the client to do 2 head requests to fetch ++ // nonces, one to start and another after getting badNonce ++ return ++ } ++ ++ head, err := decodeJWSHead(r.Body) ++ switch { ++ case err != nil: ++ t.Errorf("decodeJWSHead: %v", err) ++ case head.Nonce == "": ++ t.Error("head.Nonce is empty") ++ case head.Nonce == "nonce1": ++ // Return a badNonce error to force the call to retry. ++ w.Header().Set("Retry-After", "0") ++ w.WriteHeader(http.StatusBadRequest) ++ w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`)) ++ return ++ } ++ // Make client.Authorize happy; we're not testing its result. ++ w.WriteHeader(http.StatusCreated) ++ w.Write([]byte(`{"status":"valid"}`)) ++ })) ++ defer ts.Close() ++ ++ client := &Client{ ++ Key: testKey, ++ DirectoryURL: ts.URL, ++ dir: &Directory{AuthzURL: ts.URL}, ++ } ++ // This call will fail with badNonce, causing a retry ++ if _, err := client.Authorize(context.Background(), "example.com"); err != nil { ++ t.Errorf("client.Authorize 1: %v", err) ++ } ++ if count != 3 { ++ t.Errorf("total requests count: %d; want 3", count) ++ } ++} ++ ++func TestRetryErrorType(t *testing.T) { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Replay-Nonce", "nonce") ++ w.WriteHeader(http.StatusTooManyRequests) ++ w.Write([]byte(`{"type":"rateLimited"}`)) ++ })) ++ defer ts.Close() ++ ++ client := &Client{ ++ Key: testKey, ++ RetryBackoff: func(n int, r *http.Request, res *http.Response) time.Duration { ++ // Do no retries. ++ return 0 ++ }, ++ dir: &Directory{AuthzURL: ts.URL}, ++ } ++ ++ t.Run("post", func(t *testing.T) { ++ testRetryErrorType(t, func() error { ++ _, err := client.Authorize(context.Background(), "example.com") ++ return err ++ }) ++ }) ++ t.Run("get", func(t *testing.T) { ++ testRetryErrorType(t, func() error { ++ _, err := client.GetAuthorization(context.Background(), ts.URL) ++ return err ++ }) ++ }) ++} ++ ++func testRetryErrorType(t *testing.T, callClient func() error) { ++ t.Helper() ++ err := callClient() ++ if err == nil { ++ t.Fatal("client.Authorize returned nil error") ++ } ++ acmeErr, ok := err.(*Error) ++ if !ok { ++ t.Fatalf("err is %v (%T); want *Error", err, err) ++ } ++ if acmeErr.StatusCode != http.StatusTooManyRequests { ++ t.Errorf("acmeErr.StatusCode = %d; want %d", acmeErr.StatusCode, http.StatusTooManyRequests) ++ } ++ if acmeErr.ProblemType != "rateLimited" { ++ t.Errorf("acmeErr.ProblemType = %q; want 'rateLimited'", acmeErr.ProblemType) ++ } ++} ++ ++func TestRetryBackoffArgs(t *testing.T) { ++ const resCode = http.StatusInternalServerError ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Replay-Nonce", "test-nonce") ++ w.WriteHeader(resCode) ++ })) ++ defer ts.Close() ++ ++ // Canceled in backoff. ++ ctx, cancel := context.WithCancel(context.Background()) ++ ++ var nretry int ++ backoff := func(n int, r *http.Request, res *http.Response) time.Duration { ++ nretry++ ++ if n != nretry { ++ t.Errorf("n = %d; want %d", n, nretry) ++ } ++ if nretry == 3 { ++ cancel() ++ } ++ ++ if r == nil { ++ t.Error("r is nil") ++ } ++ if res.StatusCode != resCode { ++ t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, resCode) ++ } ++ return time.Millisecond ++ } ++ ++ client := &Client{ ++ Key: testKey, ++ RetryBackoff: backoff, ++ dir: &Directory{AuthzURL: ts.URL}, ++ } ++ if _, err := client.Authorize(ctx, "example.com"); err == nil { ++ t.Error("err is nil") ++ } ++ if nretry != 3 { ++ t.Errorf("nretry = %d; want 3", nretry) ++ } ++} ++ ++func TestUserAgent(t *testing.T) { ++ for _, custom := range []string{"", "CUSTOM_UA"} { ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ t.Log(r.UserAgent()) ++ if s := "golang.org/x/crypto/acme"; !strings.Contains(r.UserAgent(), s) { ++ t.Errorf("expected User-Agent to contain %q, got %q", s, r.UserAgent()) ++ } ++ if !strings.Contains(r.UserAgent(), custom) { ++ t.Errorf("expected User-Agent to contain %q, got %q", custom, r.UserAgent()) ++ } ++ ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"newOrder": "sure"}`)) ++ })) ++ defer ts.Close() ++ ++ client := &Client{ ++ Key: testKey, ++ DirectoryURL: ts.URL, ++ UserAgent: custom, ++ } ++ if _, err := client.Discover(context.Background()); err != nil { ++ t.Errorf("client.Discover: %v", err) ++ } ++ } ++} ++ ++func TestAccountKidLoop(t *testing.T) { ++ // if Client.postNoRetry is called with a nil key argument ++ // then Client.Key must be set, otherwise we fall into an ++ // infinite loop (which also causes a deadlock). ++ client := &Client{dir: &Directory{OrderURL: ":)"}} ++ _, _, err := client.postNoRetry(context.Background(), nil, "", nil) ++ if err == nil { ++ t.Fatal("Client.postNoRetry didn't fail with a nil key") ++ } ++ expected := "acme: Client.Key must be populated to make POST requests" ++ if err.Error() != expected { ++ t.Fatalf("Unexpected error returned: wanted %q, got %q", expected, err.Error()) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go b/ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go +new file mode 100644 +index 00000000000000..25dba0c50e951f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go +@@ -0,0 +1,433 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// The acmeprober program runs against an actual ACME CA implementation. ++// It spins up an HTTP server to fulfill authorization challenges ++// or execute a DNS script to provision a response to dns-01 challenge. ++// ++// For http-01 and tls-alpn-01 challenge types this requires the ACME CA ++// to be able to reach the HTTP server. ++// ++// A usage example: ++// ++// go run prober.go \ ++// -d https://acme-staging-v02.api.letsencrypt.org/directory \ ++// -f order \ ++// -t http-01 \ ++// -a :8080 \ ++// -domain some.example.org ++// ++// The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 ++// in order for the test to be able to fulfill http-01 challenge. ++// To test tls-alpn-01 challenge, 443 port would need to be tunneled ++// to 0.0.0.0:8080. ++// When running with dns-01 challenge type, use -s argument instead of -a. ++package main ++ ++import ( ++ "context" ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/tls" ++ "crypto/x509" ++ "encoding/pem" ++ "errors" ++ "flag" ++ "fmt" ++ "log" ++ "net" ++ "net/http" ++ "os" ++ "os/exec" ++ "strings" ++ "time" ++ ++ "golang.org/x/crypto/acme" ++) ++ ++var ( ++ // ACME CA directory URL. ++ // Let's Encrypt v2 prod: https://acme-v02.api.letsencrypt.org/directory ++ // Let's Encrypt v2 staging: https://acme-staging-v02.api.letsencrypt.org/directory ++ // See the following for more CAs implementing ACME protocol: ++ // https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment#CAs_&_PKIs_that_offer_ACME_certificates ++ directory = flag.String("d", "", "ACME directory URL.") ++ reginfo = flag.String("r", "", "ACME account registration info.") ++ flow = flag.String("f", "", `Flow to run: "order" or "preauthz" (RFC8555).`) ++ chaltyp = flag.String("t", "", "Challenge type: tls-alpn-01, http-01 or dns-01.") ++ addr = flag.String("a", "", "Local server address for tls-alpn-01 and http-01.") ++ dnsscript = flag.String("s", "", "Script to run for provisioning dns-01 challenges.") ++ domain = flag.String("domain", "", "Space separate domain identifiers.") ++ ipaddr = flag.String("ip", "", "Space separate IP address identifiers.") ++) ++ ++func main() { ++ flag.Usage = func() { ++ fmt.Fprintln(flag.CommandLine.Output(), ` ++The prober program runs against an actual ACME CA implementation. ++It spins up an HTTP server to fulfill authorization challenges ++or execute a DNS script to provision a response to dns-01 challenge. ++ ++For http-01 and tls-alpn-01 challenge types this requires the ACME CA ++to be able to reach the HTTP server. ++ ++A usage example: ++ ++ go run prober.go \ ++ -d https://acme-staging-v02.api.letsencrypt.org/directory \ ++ -f order \ ++ -t http-01 \ ++ -a :8080 \ ++ -domain some.example.org ++ ++The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 ++in order for the test to be able to fulfill http-01 challenge. ++To test tls-alpn-01 challenge, 443 port would need to be tunneled ++to 0.0.0.0:8080. ++When running with dns-01 challenge type, use -s argument instead of -a. ++ `) ++ flag.PrintDefaults() ++ } ++ flag.Parse() ++ ++ identifiers := acme.DomainIDs(strings.Fields(*domain)...) ++ identifiers = append(identifiers, acme.IPIDs(strings.Fields(*ipaddr)...)...) ++ if len(identifiers) == 0 { ++ log.Fatal("at least one domain or IP addr identifier is required") ++ } ++ ++ // Duration of the whole run. ++ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) ++ defer cancel() ++ ++ // Create and register a new account. ++ akey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ log.Fatal(err) ++ } ++ cl := &acme.Client{Key: akey, DirectoryURL: *directory} ++ a := &acme.Account{Contact: strings.Fields(*reginfo)} ++ if _, err := cl.Register(ctx, a, acme.AcceptTOS); err != nil { ++ log.Fatalf("Register: %v", err) ++ } ++ ++ // Run the desired flow test. ++ p := &prober{ ++ client: cl, ++ chalType: *chaltyp, ++ localAddr: *addr, ++ dnsScript: *dnsscript, ++ } ++ switch *flow { ++ case "order": ++ p.runOrder(ctx, identifiers) ++ case "preauthz": ++ p.runPreauthz(ctx, identifiers) ++ default: ++ log.Fatalf("unknown flow: %q", *flow) ++ } ++ if len(p.errors) > 0 { ++ os.Exit(1) ++ } ++} ++ ++type prober struct { ++ client *acme.Client ++ chalType string ++ localAddr string ++ dnsScript string ++ ++ errors []error ++} ++ ++func (p *prober) errorf(format string, a ...interface{}) { ++ err := fmt.Errorf(format, a...) ++ log.Print(err) ++ p.errors = append(p.errors, err) ++} ++ ++func (p *prober) runOrder(ctx context.Context, identifiers []acme.AuthzID) { ++ // Create a new order and pick a challenge. ++ // Note that Let's Encrypt will reply with 400 error:malformed ++ // "NotBefore and NotAfter are not supported" when providing a NotAfter ++ // value like WithOrderNotAfter(time.Now().Add(24 * time.Hour)). ++ o, err := p.client.AuthorizeOrder(ctx, identifiers) ++ if err != nil { ++ log.Fatalf("AuthorizeOrder: %v", err) ++ } ++ ++ var zurls []string ++ for _, u := range o.AuthzURLs { ++ z, err := p.client.GetAuthorization(ctx, u) ++ if err != nil { ++ log.Fatalf("GetAuthorization(%q): %v", u, err) ++ } ++ log.Printf("%+v", z) ++ if z.Status != acme.StatusPending { ++ log.Printf("authz status is %q; skipping", z.Status) ++ continue ++ } ++ if err := p.fulfill(ctx, z); err != nil { ++ log.Fatalf("fulfill(%s): %v", z.URI, err) ++ } ++ zurls = append(zurls, z.URI) ++ log.Printf("authorized for %+v", z.Identifier) ++ } ++ ++ log.Print("all challenges are done") ++ if _, err := p.client.WaitOrder(ctx, o.URI); err != nil { ++ log.Fatalf("WaitOrder(%q): %v", o.URI, err) ++ } ++ csr, certkey := newCSR(identifiers) ++ der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) ++ if err != nil { ++ log.Fatalf("CreateOrderCert: %v", err) ++ } ++ log.Printf("cert URL: %s", curl) ++ if err := checkCert(der, identifiers); err != nil { ++ p.errorf("invalid cert: %v", err) ++ } ++ ++ // Deactivate all authorizations we satisfied earlier. ++ for _, v := range zurls { ++ if err := p.client.RevokeAuthorization(ctx, v); err != nil { ++ p.errorf("RevokAuthorization(%q): %v", v, err) ++ continue ++ } ++ } ++ // Deactivate the account. We don't need it for any further calls. ++ if err := p.client.DeactivateReg(ctx); err != nil { ++ p.errorf("DeactivateReg: %v", err) ++ } ++ // Try revoking the issued cert using its private key. ++ if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { ++ p.errorf("RevokeCert: %v", err) ++ } ++} ++ ++func (p *prober) runPreauthz(ctx context.Context, identifiers []acme.AuthzID) { ++ dir, err := p.client.Discover(ctx) ++ if err != nil { ++ log.Fatalf("Discover: %v", err) ++ } ++ if dir.AuthzURL == "" { ++ log.Fatal("CA does not support pre-authorization") ++ } ++ ++ var zurls []string ++ for _, id := range identifiers { ++ z, err := authorize(ctx, p.client, id) ++ if err != nil { ++ log.Fatalf("AuthorizeID(%+v): %v", z, err) ++ } ++ if z.Status == acme.StatusValid { ++ log.Printf("authz %s is valid; skipping", z.URI) ++ continue ++ } ++ if err := p.fulfill(ctx, z); err != nil { ++ log.Fatalf("fulfill(%s): %v", z.URI, err) ++ } ++ zurls = append(zurls, z.URI) ++ log.Printf("authorized for %+v", id) ++ } ++ ++ // We should be all set now. ++ // Expect all authorizations to be satisfied. ++ log.Print("all challenges are done") ++ o, err := p.client.AuthorizeOrder(ctx, identifiers) ++ if err != nil { ++ log.Fatalf("AuthorizeOrder: %v", err) ++ } ++ waitCtx, cancel := context.WithTimeout(ctx, time.Minute) ++ defer cancel() ++ if _, err := p.client.WaitOrder(waitCtx, o.URI); err != nil { ++ log.Fatalf("WaitOrder(%q): %v", o.URI, err) ++ } ++ csr, certkey := newCSR(identifiers) ++ der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) ++ if err != nil { ++ log.Fatalf("CreateOrderCert: %v", err) ++ } ++ log.Printf("cert URL: %s", curl) ++ if err := checkCert(der, identifiers); err != nil { ++ p.errorf("invalid cert: %v", err) ++ } ++ ++ // Deactivate all authorizations we satisfied earlier. ++ for _, v := range zurls { ++ if err := p.client.RevokeAuthorization(ctx, v); err != nil { ++ p.errorf("RevokeAuthorization(%q): %v", v, err) ++ continue ++ } ++ } ++ // Deactivate the account. We don't need it for any further calls. ++ if err := p.client.DeactivateReg(ctx); err != nil { ++ p.errorf("DeactivateReg: %v", err) ++ } ++ // Try revoking the issued cert using its private key. ++ if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { ++ p.errorf("RevokeCert: %v", err) ++ } ++} ++ ++func (p *prober) fulfill(ctx context.Context, z *acme.Authorization) error { ++ var chal *acme.Challenge ++ for i, c := range z.Challenges { ++ log.Printf("challenge %d: %+v", i, c) ++ if c.Type == p.chalType { ++ log.Printf("picked %s for authz %s", c.URI, z.URI) ++ chal = c ++ } ++ } ++ if chal == nil { ++ return fmt.Errorf("challenge type %q wasn't offered for authz %s", p.chalType, z.URI) ++ } ++ ++ switch chal.Type { ++ case "tls-alpn-01": ++ return p.runTLSALPN01(ctx, z, chal) ++ case "http-01": ++ return p.runHTTP01(ctx, z, chal) ++ case "dns-01": ++ return p.runDNS01(ctx, z, chal) ++ default: ++ return fmt.Errorf("unknown challenge type %q", chal.Type) ++ } ++} ++ ++func (p *prober) runTLSALPN01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { ++ tokenCert, err := p.client.TLSALPN01ChallengeCert(chal.Token, z.Identifier.Value) ++ if err != nil { ++ return fmt.Errorf("TLSALPN01ChallengeCert: %v", err) ++ } ++ s := &http.Server{ ++ Addr: p.localAddr, ++ TLSConfig: &tls.Config{ ++ NextProtos: []string{acme.ALPNProto}, ++ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { ++ log.Printf("hello: %+v", hello) ++ return &tokenCert, nil ++ }, ++ }, ++ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ log.Printf("%s %s", r.Method, r.URL) ++ w.WriteHeader(http.StatusNotFound) ++ }), ++ } ++ go s.ListenAndServeTLS("", "") ++ defer s.Close() ++ ++ if _, err := p.client.Accept(ctx, chal); err != nil { ++ return fmt.Errorf("Accept(%q): %v", chal.URI, err) ++ } ++ _, zerr := p.client.WaitAuthorization(ctx, z.URI) ++ return zerr ++} ++ ++func (p *prober) runHTTP01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { ++ body, err := p.client.HTTP01ChallengeResponse(chal.Token) ++ if err != nil { ++ return fmt.Errorf("HTTP01ChallengeResponse: %v", err) ++ } ++ s := &http.Server{ ++ Addr: p.localAddr, ++ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ log.Printf("%s %s", r.Method, r.URL) ++ if r.URL.Path != p.client.HTTP01ChallengePath(chal.Token) { ++ w.WriteHeader(http.StatusNotFound) ++ return ++ } ++ w.Write([]byte(body)) ++ }), ++ } ++ go s.ListenAndServe() ++ defer s.Close() ++ ++ if _, err := p.client.Accept(ctx, chal); err != nil { ++ return fmt.Errorf("Accept(%q): %v", chal.URI, err) ++ } ++ _, zerr := p.client.WaitAuthorization(ctx, z.URI) ++ return zerr ++} ++ ++func (p *prober) runDNS01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { ++ token, err := p.client.DNS01ChallengeRecord(chal.Token) ++ if err != nil { ++ return fmt.Errorf("DNS01ChallengeRecord: %v", err) ++ } ++ ++ name := fmt.Sprintf("_acme-challenge.%s", z.Identifier.Value) ++ cmd := exec.CommandContext(ctx, p.dnsScript, name, token) ++ cmd.Stdin = os.Stdin ++ cmd.Stdout = os.Stdout ++ cmd.Stderr = os.Stderr ++ if err := cmd.Run(); err != nil { ++ return fmt.Errorf("%s: %v", p.dnsScript, err) ++ } ++ ++ if _, err := p.client.Accept(ctx, chal); err != nil { ++ return fmt.Errorf("Accept(%q): %v", chal.URI, err) ++ } ++ _, zerr := p.client.WaitAuthorization(ctx, z.URI) ++ return zerr ++} ++ ++func authorize(ctx context.Context, client *acme.Client, id acme.AuthzID) (*acme.Authorization, error) { ++ if id.Type == "ip" { ++ return client.AuthorizeIP(ctx, id.Value) ++ } ++ return client.Authorize(ctx, id.Value) ++} ++ ++func checkCert(derChain [][]byte, id []acme.AuthzID) error { ++ if len(derChain) == 0 { ++ return errors.New("cert chain is zero bytes") ++ } ++ for i, b := range derChain { ++ crt, err := x509.ParseCertificate(b) ++ if err != nil { ++ return fmt.Errorf("%d: ParseCertificate: %v", i, err) ++ } ++ log.Printf("%d: serial: 0x%s", i, crt.SerialNumber) ++ log.Printf("%d: subject: %s", i, crt.Subject) ++ log.Printf("%d: issuer: %s", i, crt.Issuer) ++ log.Printf("%d: expires in %.1f day(s)", i, time.Until(crt.NotAfter).Hours()/24) ++ if i > 0 { // not a leaf cert ++ continue ++ } ++ p := &pem.Block{Type: "CERTIFICATE", Bytes: b} ++ log.Printf("%d: leaf:\n%s", i, pem.EncodeToMemory(p)) ++ for _, v := range id { ++ if err := crt.VerifyHostname(v.Value); err != nil { ++ return err ++ } ++ } ++ } ++ return nil ++} ++ ++func newCSR(identifiers []acme.AuthzID) ([]byte, crypto.Signer) { ++ var csr x509.CertificateRequest ++ for _, id := range identifiers { ++ switch id.Type { ++ case "dns": ++ csr.DNSNames = append(csr.DNSNames, id.Value) ++ case "ip": ++ csr.IPAddresses = append(csr.IPAddresses, net.ParseIP(id.Value)) ++ default: ++ panic(fmt.Sprintf("newCSR: unknown identifier type %q", id.Type)) ++ } ++ } ++ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ panic(fmt.Sprintf("newCSR: ecdsa.GenerateKey for a cert: %v", err)) ++ } ++ b, err := x509.CreateCertificateRequest(rand.Reader, &csr, k) ++ if err != nil { ++ panic(fmt.Sprintf("newCSR: x509.CreateCertificateRequest: %v", err)) ++ } ++ return b, k ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/jws.go b/ms_mod/golang.org/x/crypto/acme/jws.go +new file mode 100644 +index 00000000000000..b38828d85935c3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/jws.go +@@ -0,0 +1,257 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/hmac" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/sha256" ++ _ "crypto/sha512" // need for EC keys ++ "encoding/asn1" ++ "encoding/base64" ++ "encoding/json" ++ "errors" ++ "fmt" ++ "math/big" ++) ++ ++// KeyID is the account key identity provided by a CA during registration. ++type KeyID string ++ ++// noKeyID indicates that jwsEncodeJSON should compute and use JWK instead of a KID. ++// See jwsEncodeJSON for details. ++const noKeyID = KeyID("") ++ ++// noPayload indicates jwsEncodeJSON will encode zero-length octet string ++// in a JWS request. This is called POST-as-GET in RFC 8555 and is used to make ++// authenticated GET requests via POSTing with an empty payload. ++// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details. ++const noPayload = "" ++ ++// noNonce indicates that the nonce should be omitted from the protected header. ++// See jwsEncodeJSON for details. ++const noNonce = "" ++ ++// jsonWebSignature can be easily serialized into a JWS following ++// https://tools.ietf.org/html/rfc7515#section-3.2. ++type jsonWebSignature struct { ++ Protected string `json:"protected"` ++ Payload string `json:"payload"` ++ Sig string `json:"signature"` ++} ++ ++// jwsEncodeJSON signs claimset using provided key and a nonce. ++// The result is serialized in JSON format containing either kid or jwk ++// fields based on the provided KeyID value. ++// ++// The claimset is marshalled using json.Marshal unless it is a string. ++// In which case it is inserted directly into the message. ++// ++// If kid is non-empty, its quoted value is inserted in the protected header ++// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted ++// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive. ++// ++// If nonce is non-empty, its quoted value is inserted in the protected header. ++// ++// See https://tools.ietf.org/html/rfc7515#section-7. ++func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) { ++ if key == nil { ++ return nil, errors.New("nil key") ++ } ++ alg, sha := jwsHasher(key.Public()) ++ if alg == "" || !sha.Available() { ++ return nil, ErrUnsupportedKey ++ } ++ headers := struct { ++ Alg string `json:"alg"` ++ KID string `json:"kid,omitempty"` ++ JWK json.RawMessage `json:"jwk,omitempty"` ++ Nonce string `json:"nonce,omitempty"` ++ URL string `json:"url"` ++ }{ ++ Alg: alg, ++ Nonce: nonce, ++ URL: url, ++ } ++ switch kid { ++ case noKeyID: ++ jwk, err := jwkEncode(key.Public()) ++ if err != nil { ++ return nil, err ++ } ++ headers.JWK = json.RawMessage(jwk) ++ default: ++ headers.KID = string(kid) ++ } ++ phJSON, err := json.Marshal(headers) ++ if err != nil { ++ return nil, err ++ } ++ phead := base64.RawURLEncoding.EncodeToString([]byte(phJSON)) ++ var payload string ++ if val, ok := claimset.(string); ok { ++ payload = val ++ } else { ++ cs, err := json.Marshal(claimset) ++ if err != nil { ++ return nil, err ++ } ++ payload = base64.RawURLEncoding.EncodeToString(cs) ++ } ++ hash := sha.New() ++ hash.Write([]byte(phead + "." + payload)) ++ sig, err := jwsSign(key, sha, hash.Sum(nil)) ++ if err != nil { ++ return nil, err ++ } ++ enc := jsonWebSignature{ ++ Protected: phead, ++ Payload: payload, ++ Sig: base64.RawURLEncoding.EncodeToString(sig), ++ } ++ return json.Marshal(&enc) ++} ++ ++// jwsWithMAC creates and signs a JWS using the given key and the HS256 ++// algorithm. kid and url are included in the protected header. rawPayload ++// should not be base64-URL-encoded. ++func jwsWithMAC(key []byte, kid, url string, rawPayload []byte) (*jsonWebSignature, error) { ++ if len(key) == 0 { ++ return nil, errors.New("acme: cannot sign JWS with an empty MAC key") ++ } ++ header := struct { ++ Algorithm string `json:"alg"` ++ KID string `json:"kid"` ++ URL string `json:"url,omitempty"` ++ }{ ++ // Only HMAC-SHA256 is supported. ++ Algorithm: "HS256", ++ KID: kid, ++ URL: url, ++ } ++ rawProtected, err := json.Marshal(header) ++ if err != nil { ++ return nil, err ++ } ++ protected := base64.RawURLEncoding.EncodeToString(rawProtected) ++ payload := base64.RawURLEncoding.EncodeToString(rawPayload) ++ ++ h := hmac.New(sha256.New, key) ++ if _, err := h.Write([]byte(protected + "." + payload)); err != nil { ++ return nil, err ++ } ++ mac := h.Sum(nil) ++ ++ return &jsonWebSignature{ ++ Protected: protected, ++ Payload: payload, ++ Sig: base64.RawURLEncoding.EncodeToString(mac), ++ }, nil ++} ++ ++// jwkEncode encodes public part of an RSA or ECDSA key into a JWK. ++// The result is also suitable for creating a JWK thumbprint. ++// https://tools.ietf.org/html/rfc7517 ++func jwkEncode(pub crypto.PublicKey) (string, error) { ++ switch pub := pub.(type) { ++ case *rsa.PublicKey: ++ // https://tools.ietf.org/html/rfc7518#section-6.3.1 ++ n := pub.N ++ e := big.NewInt(int64(pub.E)) ++ // Field order is important. ++ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. ++ return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, ++ base64.RawURLEncoding.EncodeToString(e.Bytes()), ++ base64.RawURLEncoding.EncodeToString(n.Bytes()), ++ ), nil ++ case *ecdsa.PublicKey: ++ // https://tools.ietf.org/html/rfc7518#section-6.2.1 ++ p := pub.Curve.Params() ++ n := p.BitSize / 8 ++ if p.BitSize%8 != 0 { ++ n++ ++ } ++ x := pub.X.Bytes() ++ if n > len(x) { ++ x = append(make([]byte, n-len(x)), x...) ++ } ++ y := pub.Y.Bytes() ++ if n > len(y) { ++ y = append(make([]byte, n-len(y)), y...) ++ } ++ // Field order is important. ++ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. ++ return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, ++ p.Name, ++ base64.RawURLEncoding.EncodeToString(x), ++ base64.RawURLEncoding.EncodeToString(y), ++ ), nil ++ } ++ return "", ErrUnsupportedKey ++} ++ ++// jwsSign signs the digest using the given key. ++// The hash is unused for ECDSA keys. ++func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) { ++ switch pub := key.Public().(type) { ++ case *rsa.PublicKey: ++ return key.Sign(rand.Reader, digest, hash) ++ case *ecdsa.PublicKey: ++ sigASN1, err := key.Sign(rand.Reader, digest, hash) ++ if err != nil { ++ return nil, err ++ } ++ ++ var rs struct{ R, S *big.Int } ++ if _, err := asn1.Unmarshal(sigASN1, &rs); err != nil { ++ return nil, err ++ } ++ ++ rb, sb := rs.R.Bytes(), rs.S.Bytes() ++ size := pub.Params().BitSize / 8 ++ if size%8 > 0 { ++ size++ ++ } ++ sig := make([]byte, size*2) ++ copy(sig[size-len(rb):], rb) ++ copy(sig[size*2-len(sb):], sb) ++ return sig, nil ++ } ++ return nil, ErrUnsupportedKey ++} ++ ++// jwsHasher indicates suitable JWS algorithm name and a hash function ++// to use for signing a digest with the provided key. ++// It returns ("", 0) if the key is not supported. ++func jwsHasher(pub crypto.PublicKey) (string, crypto.Hash) { ++ switch pub := pub.(type) { ++ case *rsa.PublicKey: ++ return "RS256", crypto.SHA256 ++ case *ecdsa.PublicKey: ++ switch pub.Params().Name { ++ case "P-256": ++ return "ES256", crypto.SHA256 ++ case "P-384": ++ return "ES384", crypto.SHA384 ++ case "P-521": ++ return "ES512", crypto.SHA512 ++ } ++ } ++ return "", 0 ++} ++ ++// JWKThumbprint creates a JWK thumbprint out of pub ++// as specified in https://tools.ietf.org/html/rfc7638. ++func JWKThumbprint(pub crypto.PublicKey) (string, error) { ++ jwk, err := jwkEncode(pub) ++ if err != nil { ++ return "", err ++ } ++ b := sha256.Sum256([]byte(jwk)) ++ return base64.RawURLEncoding.EncodeToString(b[:]), nil ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/jws_test.go b/ms_mod/golang.org/x/crypto/acme/jws_test.go +new file mode 100644 +index 00000000000000..d5f00ba2d32458 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/jws_test.go +@@ -0,0 +1,550 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rsa" ++ "crypto/sha256" ++ "crypto/x509" ++ "encoding/base64" ++ "encoding/json" ++ "encoding/pem" ++ "fmt" ++ "io" ++ "math/big" ++ "testing" ++) ++ ++// The following shell command alias is used in the comments ++// throughout this file: ++// alias b64raw="base64 -w0 | tr -d '=' | tr '/+' '_-'" ++ ++const ( ++ // Modulus in raw base64: ++ // 4xgZ3eRPkwoRvy7qeRUbmMDe0V-xH9eWLdu0iheeLlrmD2mqWXfP9IeSKApbn34 ++ // g8TuAS9g5zhq8ELQ3kmjr-KV86GAMgI6VAcGlq3QrzpTCf_30Ab7-zawrfRaFON ++ // a1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosqEXeaIkVYBEhbh ++ // Nu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZfoyFyek380mHg ++ // JAumQ_I2fjj98_97mk3ihOY4AgVdCDj1z_GCoZkG5Rq7nbCGyosyKWyDX00Zs-n ++ // NqVhoLeIvXC4nnWdJMZ6rogxyQQ ++ testKeyPEM = ` ++-----BEGIN RSA PRIVATE KEY----- ++MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq ++WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30 ++Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq ++EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf ++oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy ++KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV ++9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H ++r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm ++ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP ++G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS ++zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6 ++9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s ++8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc ++7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL ++qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ ++Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU ++RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o ++JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd ++4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt ++jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q ++YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73 ++c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G ++N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7 ++EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO ++9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx ++-----END RSA PRIVATE KEY----- ++` ++ ++ // This thumbprint is for the testKey defined above. ++ testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ" ++ ++ // openssl ecparam -name secp256k1 -genkey -noout ++ testKeyECPEM = ` ++-----BEGIN EC PRIVATE KEY----- ++MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49 ++AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5 ++QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ== ++-----END EC PRIVATE KEY----- ++` ++ // openssl ecparam -name secp384r1 -genkey -noout ++ testKeyEC384PEM = ` ++-----BEGIN EC PRIVATE KEY----- ++MIGkAgEBBDAQ4lNtXRORWr1bgKR1CGysr9AJ9SyEk4jiVnlUWWUChmSNL+i9SLSD ++Oe/naPqXJ6CgBwYFK4EEACKhZANiAAQzKtj+Ms0vHoTX5dzv3/L5YMXOWuI5UKRj ++JigpahYCqXD2BA1j0E/2xt5vlPf+gm0PL+UHSQsCokGnIGuaHCsJAp3ry0gHQEke ++WYXapUUFdvaK1R2/2hn5O+eiQM8YzCg= ++-----END EC PRIVATE KEY----- ++` ++ // openssl ecparam -name secp521r1 -genkey -noout ++ testKeyEC512PEM = ` ++-----BEGIN EC PRIVATE KEY----- ++MIHcAgEBBEIBSNZKFcWzXzB/aJClAb305ibalKgtDA7+70eEkdPt28/3LZMM935Z ++KqYHh/COcxuu3Kt8azRAUz3gyr4zZKhlKUSgBwYFK4EEACOhgYkDgYYABAHUNKbx ++7JwC7H6pa2sV0tERWhHhB3JmW+OP6SUgMWryvIKajlx73eS24dy4QPGrWO9/ABsD ++FqcRSkNVTXnIv6+0mAF25knqIBIg5Q8M9BnOu9GGAchcwt3O7RDHmqewnJJDrbjd ++GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ== ++-----END EC PRIVATE KEY----- ++` ++ // 1. openssl ec -in key.pem -noout -text ++ // 2. remove first byte, 04 (the header); the rest is X and Y ++ // 3. convert each with: echo | xxd -r -p | b64raw ++ testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ" ++ testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk" ++ testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt" ++ testKeyEC384PubY = "Dy_lB0kLAqJBpyBrmhwrCQKd68tIB0BJHlmF2qVFBXb2itUdv9oZ-TvnokDPGMwo" ++ testKeyEC512PubX = "AdQ0pvHsnALsfqlraxXS0RFaEeEHcmZb44_pJSAxavK8gpqOXHvd5Lbh3LhA8atY738AGwMWpxFKQ1VNeci_r7SY" ++ testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax" ++ ++ // echo -n '{"crv":"P-256","kty":"EC","x":"","y":""}' | \ ++ // openssl dgst -binary -sha256 | b64raw ++ testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU" ++) ++ ++var ( ++ testKey *rsa.PrivateKey ++ testKeyEC *ecdsa.PrivateKey ++ testKeyEC384 *ecdsa.PrivateKey ++ testKeyEC512 *ecdsa.PrivateKey ++) ++ ++func init() { ++ testKey = parseRSA(testKeyPEM, "testKeyPEM") ++ testKeyEC = parseEC(testKeyECPEM, "testKeyECPEM") ++ testKeyEC384 = parseEC(testKeyEC384PEM, "testKeyEC384PEM") ++ testKeyEC512 = parseEC(testKeyEC512PEM, "testKeyEC512PEM") ++} ++ ++func decodePEM(s, name string) []byte { ++ d, _ := pem.Decode([]byte(s)) ++ if d == nil { ++ panic("no block found in " + name) ++ } ++ return d.Bytes ++} ++ ++func parseRSA(s, name string) *rsa.PrivateKey { ++ b := decodePEM(s, name) ++ k, err := x509.ParsePKCS1PrivateKey(b) ++ if err != nil { ++ panic(fmt.Sprintf("%s: %v", name, err)) ++ } ++ return k ++} ++ ++func parseEC(s, name string) *ecdsa.PrivateKey { ++ b := decodePEM(s, name) ++ k, err := x509.ParseECPrivateKey(b) ++ if err != nil { ++ panic(fmt.Sprintf("%s: %v", name, err)) ++ } ++ return k ++} ++ ++func TestJWSEncodeJSON(t *testing.T) { ++ claims := struct{ Msg string }{"Hello JWS"} ++ // JWS signed with testKey and "nonce" as the nonce value ++ // JSON-serialized JWS fields are split for easier testing ++ const ( ++ // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce","url":"url"} ++ protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + ++ "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + ++ "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + ++ "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" + ++ "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" + ++ "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" + ++ "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" + ++ "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + ++ "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + ++ "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + ++ "UVEifSwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" ++ // {"Msg":"Hello JWS"} ++ payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" ++ // printf '.' | openssl dgst -binary -sha256 -sign testKey | b64raw ++ signature = "YFyl_xz1E7TR-3E1bIuASTr424EgCvBHjt25WUFC2VaDjXYV0Rj_" + ++ "Hd3dJ_2IRqBrXDZZ2n4ZeA_4mm3QFwmwyeDwe2sWElhb82lCZ8iX" + ++ "uFnjeOmSOjx-nWwPa5ibCXzLq13zZ-OBV1Z4oN_TuailQeRoSfA3" + ++ "nO8gG52mv1x2OMQ5MAFtt8jcngBLzts4AyhI6mBJ2w7Yaj3ZCriq" + ++ "DWA3GLFvvHdW1Ba9Z01wtGT2CuZI7DUk_6Qj1b3BkBGcoKur5C9i" + ++ "bUJtCkABwBMvBQNyD3MmXsrRFRTgvVlyU_yMaucYm7nmzEr_2PaQ" + ++ "50rFt_9qOfJ4sfbLtG1Wwae57BQx1g" ++ ) ++ ++ b, err := jwsEncodeJSON(claims, testKey, noKeyID, "nonce", "url") ++ if err != nil { ++ t.Fatal(err) ++ } ++ var jws struct{ Protected, Payload, Signature string } ++ if err := json.Unmarshal(b, &jws); err != nil { ++ t.Fatal(err) ++ } ++ if jws.Protected != protected { ++ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) ++ } ++ if jws.Payload != payload { ++ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) ++ } ++ if jws.Signature != signature { ++ t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature) ++ } ++} ++ ++func TestJWSEncodeNoNonce(t *testing.T) { ++ kid := KeyID("https://example.org/account/1") ++ claims := "RawString" ++ const ( ++ // {"alg":"ES256","kid":"https://example.org/account/1","nonce":"nonce","url":"url"} ++ protected = "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYWNjb3VudC8xIiwidXJsIjoidXJsIn0" ++ // "Raw String" ++ payload = "RawString" ++ ) ++ ++ b, err := jwsEncodeJSON(claims, testKeyEC, kid, "", "url") ++ if err != nil { ++ t.Fatal(err) ++ } ++ var jws struct{ Protected, Payload, Signature string } ++ if err := json.Unmarshal(b, &jws); err != nil { ++ t.Fatal(err) ++ } ++ if jws.Protected != protected { ++ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) ++ } ++ if jws.Payload != payload { ++ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) ++ } ++ ++ sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) ++ if err != nil { ++ t.Fatalf("jws.Signature: %v", err) ++ } ++ r, s := big.NewInt(0), big.NewInt(0) ++ r.SetBytes(sig[:len(sig)/2]) ++ s.SetBytes(sig[len(sig)/2:]) ++ h := sha256.Sum256([]byte(protected + "." + payload)) ++ if !ecdsa.Verify(testKeyEC.Public().(*ecdsa.PublicKey), h[:], r, s) { ++ t.Error("invalid signature") ++ } ++} ++ ++func TestJWSEncodeKID(t *testing.T) { ++ kid := KeyID("https://example.org/account/1") ++ claims := struct{ Msg string }{"Hello JWS"} ++ // JWS signed with testKeyEC ++ const ( ++ // {"alg":"ES256","kid":"https://example.org/account/1","nonce":"nonce","url":"url"} ++ protected = "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5" + ++ "vcmcvYWNjb3VudC8xIiwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" ++ // {"Msg":"Hello JWS"} ++ payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" ++ ) ++ ++ b, err := jwsEncodeJSON(claims, testKeyEC, kid, "nonce", "url") ++ if err != nil { ++ t.Fatal(err) ++ } ++ var jws struct{ Protected, Payload, Signature string } ++ if err := json.Unmarshal(b, &jws); err != nil { ++ t.Fatal(err) ++ } ++ if jws.Protected != protected { ++ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) ++ } ++ if jws.Payload != payload { ++ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) ++ } ++ ++ sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) ++ if err != nil { ++ t.Fatalf("jws.Signature: %v", err) ++ } ++ r, s := big.NewInt(0), big.NewInt(0) ++ r.SetBytes(sig[:len(sig)/2]) ++ s.SetBytes(sig[len(sig)/2:]) ++ h := sha256.Sum256([]byte(protected + "." + payload)) ++ if !ecdsa.Verify(testKeyEC.Public().(*ecdsa.PublicKey), h[:], r, s) { ++ t.Error("invalid signature") ++ } ++} ++ ++func TestJWSEncodeJSONEC(t *testing.T) { ++ tt := []struct { ++ key *ecdsa.PrivateKey ++ x, y string ++ alg, crv string ++ }{ ++ {testKeyEC, testKeyECPubX, testKeyECPubY, "ES256", "P-256"}, ++ {testKeyEC384, testKeyEC384PubX, testKeyEC384PubY, "ES384", "P-384"}, ++ {testKeyEC512, testKeyEC512PubX, testKeyEC512PubY, "ES512", "P-521"}, ++ } ++ for i, test := range tt { ++ claims := struct{ Msg string }{"Hello JWS"} ++ b, err := jwsEncodeJSON(claims, test.key, noKeyID, "nonce", "url") ++ if err != nil { ++ t.Errorf("%d: %v", i, err) ++ continue ++ } ++ var jws struct{ Protected, Payload, Signature string } ++ if err := json.Unmarshal(b, &jws); err != nil { ++ t.Errorf("%d: %v", i, err) ++ continue ++ } ++ ++ b, err = base64.RawURLEncoding.DecodeString(jws.Protected) ++ if err != nil { ++ t.Errorf("%d: jws.Protected: %v", i, err) ++ } ++ var head struct { ++ Alg string ++ Nonce string ++ URL string `json:"url"` ++ KID string `json:"kid"` ++ JWK struct { ++ Crv string ++ Kty string ++ X string ++ Y string ++ } `json:"jwk"` ++ } ++ if err := json.Unmarshal(b, &head); err != nil { ++ t.Errorf("%d: jws.Protected: %v", i, err) ++ } ++ if head.Alg != test.alg { ++ t.Errorf("%d: head.Alg = %q; want %q", i, head.Alg, test.alg) ++ } ++ if head.Nonce != "nonce" { ++ t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce) ++ } ++ if head.URL != "url" { ++ t.Errorf("%d: head.URL = %q; want 'url'", i, head.URL) ++ } ++ if head.KID != "" { ++ // We used noKeyID in jwsEncodeJSON: expect no kid value. ++ t.Errorf("%d: head.KID = %q; want empty", i, head.KID) ++ } ++ if head.JWK.Crv != test.crv { ++ t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv) ++ } ++ if head.JWK.Kty != "EC" { ++ t.Errorf("%d: head.JWK.Kty = %q; want EC", i, head.JWK.Kty) ++ } ++ if head.JWK.X != test.x { ++ t.Errorf("%d: head.JWK.X = %q; want %q", i, head.JWK.X, test.x) ++ } ++ if head.JWK.Y != test.y { ++ t.Errorf("%d: head.JWK.Y = %q; want %q", i, head.JWK.Y, test.y) ++ } ++ } ++} ++ ++type customTestSigner struct { ++ sig []byte ++ pub crypto.PublicKey ++} ++ ++func (s *customTestSigner) Public() crypto.PublicKey { return s.pub } ++func (s *customTestSigner) Sign(io.Reader, []byte, crypto.SignerOpts) ([]byte, error) { ++ return s.sig, nil ++} ++ ++func TestJWSEncodeJSONCustom(t *testing.T) { ++ claims := struct{ Msg string }{"hello"} ++ const ( ++ // printf '{"Msg":"hello"}' | b64raw ++ payload = "eyJNc2ciOiJoZWxsbyJ9" ++ // printf 'testsig' | b64raw ++ testsig = "dGVzdHNpZw" ++ ++ // the example P256 curve point from https://tools.ietf.org/html/rfc7515#appendix-A.3.1 ++ // encoded as ASN.1… ++ es256stdsig = "MEUCIA7RIVN5Y2xIPC9/FVgH1AKjsigDOvl8fheBmsMWnqZlAiEA" + ++ "xQoH04w8cOXY8S2vCEpUgKZlkMXyk1Cajz9/ioOjVNU" ++ // …and RFC7518 (https://tools.ietf.org/html/rfc7518#section-3.4) ++ es256jwsig = "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw" + ++ "5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" ++ ++ // printf '{"alg":"ES256","jwk":{"crv":"P-256","kty":"EC","x":,"y":},"nonce":"nonce","url":"url"}' | b64raw ++ es256phead = "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0" + ++ "eSI6IkVDIiwieCI6IjVsaEV1ZzV4SzR4QkRaMm5BYmF4THRhTGl2" + ++ "ODVieEo3ZVBkMWRrTzIzSFEiLCJ5IjoiNGFpSzcyc0JlVUFHa3Yw" + ++ "VGFMc213b2tZVVl5TnhHc1M1RU1JS3dzTklLayJ9LCJub25jZSI6" + ++ "Im5vbmNlIiwidXJsIjoidXJsIn0" ++ ++ // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce","url":"url"} ++ rs256phead = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + ++ "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + ++ "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + ++ "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" + ++ "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" + ++ "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" + ++ "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" + ++ "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + ++ "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + ++ "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + ++ "UVEifSwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" ++ ) ++ ++ tt := []struct { ++ alg, phead string ++ pub crypto.PublicKey ++ stdsig, jwsig string ++ }{ ++ {"ES256", es256phead, testKeyEC.Public(), es256stdsig, es256jwsig}, ++ {"RS256", rs256phead, testKey.Public(), testsig, testsig}, ++ } ++ for _, tc := range tt { ++ tc := tc ++ t.Run(tc.alg, func(t *testing.T) { ++ stdsig, err := base64.RawStdEncoding.DecodeString(tc.stdsig) ++ if err != nil { ++ t.Errorf("couldn't decode test vector: %v", err) ++ } ++ signer := &customTestSigner{ ++ sig: stdsig, ++ pub: tc.pub, ++ } ++ ++ b, err := jwsEncodeJSON(claims, signer, noKeyID, "nonce", "url") ++ if err != nil { ++ t.Fatal(err) ++ } ++ var j jsonWebSignature ++ if err := json.Unmarshal(b, &j); err != nil { ++ t.Fatal(err) ++ } ++ if j.Protected != tc.phead { ++ t.Errorf("j.Protected = %q\nwant %q", j.Protected, tc.phead) ++ } ++ if j.Payload != payload { ++ t.Errorf("j.Payload = %q\nwant %q", j.Payload, payload) ++ } ++ if j.Sig != tc.jwsig { ++ t.Errorf("j.Sig = %q\nwant %q", j.Sig, tc.jwsig) ++ } ++ }) ++ } ++} ++ ++func TestJWSWithMAC(t *testing.T) { ++ // Example from RFC 7520 Section 4.4.3. ++ // https://tools.ietf.org/html/rfc7520#section-4.4.3 ++ b64Key := "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg" ++ rawPayload := []byte("It\xe2\x80\x99s a dangerous business, Frodo, going out your " + ++ "door. You step onto the road, and if you don't keep your feet, " + ++ "there\xe2\x80\x99s no knowing where you might be swept off " + ++ "to.") ++ protected := "eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LW" + ++ "VlZjMxNGJjNzAzNyJ9" ++ payload := "SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywg" + ++ "Z29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9h" + ++ "ZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXi" + ++ "gJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9m" + ++ "ZiB0by4" ++ sig := "s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0" ++ ++ key, err := base64.RawURLEncoding.DecodeString(b64Key) ++ if err != nil { ++ t.Fatalf("unable to decode key: %q", b64Key) ++ } ++ got, err := jwsWithMAC(key, "018c0ae5-4d9b-471b-bfd6-eef314bc7037", "", rawPayload) ++ if err != nil { ++ t.Fatalf("jwsWithMAC() = %q", err) ++ } ++ if got.Protected != protected { ++ t.Errorf("got.Protected = %q\nwant %q", got.Protected, protected) ++ } ++ if got.Payload != payload { ++ t.Errorf("got.Payload = %q\nwant %q", got.Payload, payload) ++ } ++ if got.Sig != sig { ++ t.Errorf("got.Signature = %q\nwant %q", got.Sig, sig) ++ } ++} ++ ++func TestJWSWithMACError(t *testing.T) { ++ p := "{}" ++ if _, err := jwsWithMAC(nil, "", "", []byte(p)); err == nil { ++ t.Errorf("jwsWithMAC(nil, ...) = success; want err") ++ } ++} ++ ++func TestJWKThumbprintRSA(t *testing.T) { ++ // Key example from RFC 7638 ++ const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" + ++ "VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" + ++ "4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" + ++ "W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" + ++ "1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" + ++ "aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw" ++ const base64E = "AQAB" ++ const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" ++ ++ b, err := base64.RawURLEncoding.DecodeString(base64N) ++ if err != nil { ++ t.Fatalf("Error parsing example key N: %v", err) ++ } ++ n := new(big.Int).SetBytes(b) ++ ++ b, err = base64.RawURLEncoding.DecodeString(base64E) ++ if err != nil { ++ t.Fatalf("Error parsing example key E: %v", err) ++ } ++ e := new(big.Int).SetBytes(b) ++ ++ pub := &rsa.PublicKey{N: n, E: int(e.Uint64())} ++ th, err := JWKThumbprint(pub) ++ if err != nil { ++ t.Error(err) ++ } ++ if th != expected { ++ t.Errorf("thumbprint = %q; want %q", th, expected) ++ } ++} ++ ++func TestJWKThumbprintEC(t *testing.T) { ++ // Key example from RFC 7520 ++ // expected was computed with ++ // printf '{"crv":"P-521","kty":"EC","x":"","y":""}' | \ ++ // openssl dgst -binary -sha256 | b64raw ++ const ( ++ base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" + ++ "KqjqvjyekWF-7ytDyRXYgCF5cj0Kt" ++ base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" + ++ "QkAgDPrwQrJmbnX9cwlGfP-HqHZR1" ++ expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M" ++ ) ++ ++ b, err := base64.RawURLEncoding.DecodeString(base64X) ++ if err != nil { ++ t.Fatalf("Error parsing example key X: %v", err) ++ } ++ x := new(big.Int).SetBytes(b) ++ ++ b, err = base64.RawURLEncoding.DecodeString(base64Y) ++ if err != nil { ++ t.Fatalf("Error parsing example key Y: %v", err) ++ } ++ y := new(big.Int).SetBytes(b) ++ ++ pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y} ++ th, err := JWKThumbprint(pub) ++ if err != nil { ++ t.Error(err) ++ } ++ if th != expected { ++ t.Errorf("thumbprint = %q; want %q", th, expected) ++ } ++} ++ ++func TestJWKThumbprintErrUnsupportedKey(t *testing.T) { ++ _, err := JWKThumbprint(struct{}{}) ++ if err != ErrUnsupportedKey { ++ t.Errorf("err = %q; want %q", err, ErrUnsupportedKey) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/rfc8555.go b/ms_mod/golang.org/x/crypto/acme/rfc8555.go +new file mode 100644 +index 00000000000000..3152e531b65cf4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/rfc8555.go +@@ -0,0 +1,476 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "context" ++ "crypto" ++ "encoding/base64" ++ "encoding/json" ++ "encoding/pem" ++ "errors" ++ "fmt" ++ "io" ++ "net/http" ++ "time" ++) ++ ++// DeactivateReg permanently disables an existing account associated with c.Key. ++// A deactivated account can no longer request certificate issuance or access ++// resources related to the account, such as orders or authorizations. ++// ++// It only works with CAs implementing RFC 8555. ++func (c *Client) DeactivateReg(ctx context.Context) error { ++ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID ++ return err ++ } ++ url := string(c.accountKID(ctx)) ++ if url == "" { ++ return ErrNoAccount ++ } ++ req := json.RawMessage(`{"status": "deactivated"}`) ++ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) ++ if err != nil { ++ return err ++ } ++ res.Body.Close() ++ return nil ++} ++ ++// registerRFC is equivalent to c.Register but for CAs implementing RFC 8555. ++// It expects c.Discover to have already been called. ++func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { ++ c.cacheMu.Lock() // guard c.kid access ++ defer c.cacheMu.Unlock() ++ ++ req := struct { ++ TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"` ++ Contact []string `json:"contact,omitempty"` ++ ExternalAccountBinding *jsonWebSignature `json:"externalAccountBinding,omitempty"` ++ }{ ++ Contact: acct.Contact, ++ } ++ if c.dir.Terms != "" { ++ req.TermsAgreed = prompt(c.dir.Terms) ++ } ++ ++ // set 'externalAccountBinding' field if requested ++ if acct.ExternalAccountBinding != nil { ++ eabJWS, err := c.encodeExternalAccountBinding(acct.ExternalAccountBinding) ++ if err != nil { ++ return nil, fmt.Errorf("acme: failed to encode external account binding: %v", err) ++ } ++ req.ExternalAccountBinding = eabJWS ++ } ++ ++ res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus( ++ http.StatusOK, // account with this key already registered ++ http.StatusCreated, // new account created ++ )) ++ if err != nil { ++ return nil, err ++ } ++ ++ defer res.Body.Close() ++ a, err := responseAccount(res) ++ if err != nil { ++ return nil, err ++ } ++ // Cache Account URL even if we return an error to the caller. ++ // It is by all means a valid and usable "kid" value for future requests. ++ c.KID = KeyID(a.URI) ++ if res.StatusCode == http.StatusOK { ++ return nil, ErrAccountAlreadyExists ++ } ++ return a, nil ++} ++ ++// encodeExternalAccountBinding will encode an external account binding stanza ++// as described in https://tools.ietf.org/html/rfc8555#section-7.3.4. ++func (c *Client) encodeExternalAccountBinding(eab *ExternalAccountBinding) (*jsonWebSignature, error) { ++ jwk, err := jwkEncode(c.Key.Public()) ++ if err != nil { ++ return nil, err ++ } ++ return jwsWithMAC(eab.Key, eab.KID, c.dir.RegURL, []byte(jwk)) ++} ++ ++// updateRegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555. ++// It expects c.Discover to have already been called. ++func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) { ++ url := string(c.accountKID(ctx)) ++ if url == "" { ++ return nil, ErrNoAccount ++ } ++ req := struct { ++ Contact []string `json:"contact,omitempty"` ++ }{ ++ Contact: a.Contact, ++ } ++ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ return responseAccount(res) ++} ++ ++// getRegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555. ++// It expects c.Discover to have already been called. ++func (c *Client) getRegRFC(ctx context.Context) (*Account, error) { ++ req := json.RawMessage(`{"onlyReturnExisting": true}`) ++ res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK)) ++ if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" { ++ return nil, ErrNoAccount ++ } ++ if err != nil { ++ return nil, err ++ } ++ ++ defer res.Body.Close() ++ return responseAccount(res) ++} ++ ++func responseAccount(res *http.Response) (*Account, error) { ++ var v struct { ++ Status string ++ Contact []string ++ Orders string ++ } ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return nil, fmt.Errorf("acme: invalid account response: %v", err) ++ } ++ return &Account{ ++ URI: res.Header.Get("Location"), ++ Status: v.Status, ++ Contact: v.Contact, ++ OrdersURL: v.Orders, ++ }, nil ++} ++ ++// accountKeyRollover attempts to perform account key rollover. ++// On success it will change client.Key to the new key. ++func (c *Client) accountKeyRollover(ctx context.Context, newKey crypto.Signer) error { ++ dir, err := c.Discover(ctx) // Also required by c.accountKID ++ if err != nil { ++ return err ++ } ++ kid := c.accountKID(ctx) ++ if kid == noKeyID { ++ return ErrNoAccount ++ } ++ oldKey, err := jwkEncode(c.Key.Public()) ++ if err != nil { ++ return err ++ } ++ payload := struct { ++ Account string `json:"account"` ++ OldKey json.RawMessage `json:"oldKey"` ++ }{ ++ Account: string(kid), ++ OldKey: json.RawMessage(oldKey), ++ } ++ inner, err := jwsEncodeJSON(payload, newKey, noKeyID, noNonce, dir.KeyChangeURL) ++ if err != nil { ++ return err ++ } ++ ++ res, err := c.post(ctx, nil, dir.KeyChangeURL, base64.RawURLEncoding.EncodeToString(inner), wantStatus(http.StatusOK)) ++ if err != nil { ++ return err ++ } ++ defer res.Body.Close() ++ c.Key = newKey ++ return nil ++} ++ ++// AuthorizeOrder initiates the order-based application for certificate issuance, ++// as opposed to pre-authorization in Authorize. ++// It is only supported by CAs implementing RFC 8555. ++// ++// The caller then needs to fetch each authorization with GetAuthorization, ++// identify those with StatusPending status and fulfill a challenge using Accept. ++// Once all authorizations are satisfied, the caller will typically want to poll ++// order status using WaitOrder until it's in StatusReady state. ++// To finalize the order and obtain a certificate, the caller submits a CSR with CreateOrderCert. ++func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error) { ++ dir, err := c.Discover(ctx) ++ if err != nil { ++ return nil, err ++ } ++ ++ req := struct { ++ Identifiers []wireAuthzID `json:"identifiers"` ++ NotBefore string `json:"notBefore,omitempty"` ++ NotAfter string `json:"notAfter,omitempty"` ++ }{} ++ for _, v := range id { ++ req.Identifiers = append(req.Identifiers, wireAuthzID{ ++ Type: v.Type, ++ Value: v.Value, ++ }) ++ } ++ for _, o := range opt { ++ switch o := o.(type) { ++ case orderNotBeforeOpt: ++ req.NotBefore = time.Time(o).Format(time.RFC3339) ++ case orderNotAfterOpt: ++ req.NotAfter = time.Time(o).Format(time.RFC3339) ++ default: ++ // Package's fault if we let this happen. ++ panic(fmt.Sprintf("unsupported order option type %T", o)) ++ } ++ } ++ ++ res, err := c.post(ctx, nil, dir.OrderURL, req, wantStatus(http.StatusCreated)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ return responseOrder(res) ++} ++ ++// GetOrder retrives an order identified by the given URL. ++// For orders created with AuthorizeOrder, the url value is Order.URI. ++// ++// If a caller needs to poll an order until its status is final, ++// see the WaitOrder method. ++func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ return responseOrder(res) ++} ++ ++// WaitOrder polls an order from the given URL until it is in one of the final states, ++// StatusReady, StatusValid or StatusInvalid, the CA responded with a non-retryable error ++// or the context is done. ++// ++// It returns a non-nil Order only if its Status is StatusReady or StatusValid. ++// In all other cases WaitOrder returns an error. ++// If the Status is StatusInvalid, the returned error is of type *OrderError. ++func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) { ++ if _, err := c.Discover(ctx); err != nil { ++ return nil, err ++ } ++ for { ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, err ++ } ++ o, err := responseOrder(res) ++ res.Body.Close() ++ switch { ++ case err != nil: ++ // Skip and retry. ++ case o.Status == StatusInvalid: ++ return nil, &OrderError{OrderURL: o.URI, Status: o.Status} ++ case o.Status == StatusReady || o.Status == StatusValid: ++ return o, nil ++ } ++ ++ d := retryAfter(res.Header.Get("Retry-After")) ++ if d == 0 { ++ // Default retry-after. ++ // Same reasoning as in WaitAuthorization. ++ d = time.Second ++ } ++ t := time.NewTimer(d) ++ select { ++ case <-ctx.Done(): ++ t.Stop() ++ return nil, ctx.Err() ++ case <-t.C: ++ // Retry. ++ } ++ } ++} ++ ++func responseOrder(res *http.Response) (*Order, error) { ++ var v struct { ++ Status string ++ Expires time.Time ++ Identifiers []wireAuthzID ++ NotBefore time.Time ++ NotAfter time.Time ++ Error *wireError ++ Authorizations []string ++ Finalize string ++ Certificate string ++ } ++ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { ++ return nil, fmt.Errorf("acme: error reading order: %v", err) ++ } ++ o := &Order{ ++ URI: res.Header.Get("Location"), ++ Status: v.Status, ++ Expires: v.Expires, ++ NotBefore: v.NotBefore, ++ NotAfter: v.NotAfter, ++ AuthzURLs: v.Authorizations, ++ FinalizeURL: v.Finalize, ++ CertURL: v.Certificate, ++ } ++ for _, id := range v.Identifiers { ++ o.Identifiers = append(o.Identifiers, AuthzID{Type: id.Type, Value: id.Value}) ++ } ++ if v.Error != nil { ++ o.Error = v.Error.error(nil /* headers */) ++ } ++ return o, nil ++} ++ ++// CreateOrderCert submits the CSR (Certificate Signing Request) to a CA at the specified URL. ++// The URL is the FinalizeURL field of an Order created with AuthorizeOrder. ++// ++// If the bundle argument is true, the returned value also contain the CA (issuer) ++// certificate chain. Otherwise, only a leaf certificate is returned. ++// The returned URL can be used to re-fetch the certificate using FetchCert. ++// ++// This method is only supported by CAs implementing RFC 8555. See CreateCert for pre-RFC CAs. ++// ++// CreateOrderCert returns an error if the CA's response is unreasonably large. ++// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features. ++func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) { ++ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID ++ return nil, "", err ++ } ++ ++ // RFC describes this as "finalize order" request. ++ req := struct { ++ CSR string `json:"csr"` ++ }{ ++ CSR: base64.RawURLEncoding.EncodeToString(csr), ++ } ++ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, "", err ++ } ++ defer res.Body.Close() ++ o, err := responseOrder(res) ++ if err != nil { ++ return nil, "", err ++ } ++ ++ // Wait for CA to issue the cert if they haven't. ++ if o.Status != StatusValid { ++ o, err = c.WaitOrder(ctx, o.URI) ++ } ++ if err != nil { ++ return nil, "", err ++ } ++ // The only acceptable status post finalize and WaitOrder is "valid". ++ if o.Status != StatusValid { ++ return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status} ++ } ++ crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle) ++ return crt, o.CertURL, err ++} ++ ++// fetchCertRFC downloads issued certificate from the given URL. ++// It expects the CA to respond with PEM-encoded certificate chain. ++// ++// The URL argument is the CertURL field of Order. ++func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][]byte, error) { ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ ++ // Get all the bytes up to a sane maximum. ++ // Account very roughly for base64 overhead. ++ const max = maxCertChainSize + maxCertChainSize/33 ++ b, err := io.ReadAll(io.LimitReader(res.Body, max+1)) ++ if err != nil { ++ return nil, fmt.Errorf("acme: fetch cert response stream: %v", err) ++ } ++ if len(b) > max { ++ return nil, errors.New("acme: certificate chain is too big") ++ } ++ ++ // Decode PEM chain. ++ var chain [][]byte ++ for { ++ var p *pem.Block ++ p, b = pem.Decode(b) ++ if p == nil { ++ break ++ } ++ if p.Type != "CERTIFICATE" { ++ return nil, fmt.Errorf("acme: invalid PEM cert type %q", p.Type) ++ } ++ ++ chain = append(chain, p.Bytes) ++ if !bundle { ++ return chain, nil ++ } ++ if len(chain) > maxChainLen { ++ return nil, errors.New("acme: certificate chain is too long") ++ } ++ } ++ if len(chain) == 0 { ++ return nil, errors.New("acme: certificate chain is empty") ++ } ++ return chain, nil ++} ++ ++// sends a cert revocation request in either JWK form when key is non-nil or KID form otherwise. ++func (c *Client) revokeCertRFC(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { ++ req := &struct { ++ Cert string `json:"certificate"` ++ Reason int `json:"reason"` ++ }{ ++ Cert: base64.RawURLEncoding.EncodeToString(cert), ++ Reason: int(reason), ++ } ++ res, err := c.post(ctx, key, c.dir.RevokeURL, req, wantStatus(http.StatusOK)) ++ if err != nil { ++ if isAlreadyRevoked(err) { ++ // Assume it is not an error to revoke an already revoked cert. ++ return nil ++ } ++ return err ++ } ++ defer res.Body.Close() ++ return nil ++} ++ ++func isAlreadyRevoked(err error) bool { ++ e, ok := err.(*Error) ++ return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked" ++} ++ ++// ListCertAlternates retrieves any alternate certificate chain URLs for the ++// given certificate chain URL. These alternate URLs can be passed to FetchCert ++// in order to retrieve the alternate certificate chains. ++// ++// If there are no alternate issuer certificate chains, a nil slice will be ++// returned. ++func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) { ++ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID ++ return nil, err ++ } ++ ++ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) ++ if err != nil { ++ return nil, err ++ } ++ defer res.Body.Close() ++ ++ // We don't need the body but we need to discard it so we don't end up ++ // preventing keep-alive ++ if _, err := io.Copy(io.Discard, res.Body); err != nil { ++ return nil, fmt.Errorf("acme: cert alternates response stream: %v", err) ++ } ++ alts := linkHeader(res.Header, "alternate") ++ return alts, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/rfc8555_test.go b/ms_mod/golang.org/x/crypto/acme/rfc8555_test.go +new file mode 100644 +index 00000000000000..d65720a356e81a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/rfc8555_test.go +@@ -0,0 +1,1017 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "bytes" ++ "context" ++ "crypto/hmac" ++ "crypto/rand" ++ "crypto/sha256" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/base64" ++ "encoding/json" ++ "encoding/pem" ++ "errors" ++ "fmt" ++ "io" ++ "math/big" ++ "net/http" ++ "net/http/httptest" ++ "reflect" ++ "strings" ++ "sync" ++ "testing" ++ "time" ++) ++ ++// While contents of this file is pertinent only to RFC8555, ++// it is complementary to the tests in the other _test.go files ++// many of which are valid for both pre- and RFC8555. ++// This will make it easier to clean up the tests once non-RFC compliant ++// code is removed. ++ ++func TestRFC_Discover(t *testing.T) { ++ const ( ++ nonce = "https://example.com/acme/new-nonce" ++ reg = "https://example.com/acme/new-acct" ++ order = "https://example.com/acme/new-order" ++ authz = "https://example.com/acme/new-authz" ++ revoke = "https://example.com/acme/revoke-cert" ++ keychange = "https://example.com/acme/key-change" ++ metaTerms = "https://example.com/acme/terms/2017-5-30" ++ metaWebsite = "https://www.example.com/" ++ metaCAA = "example.com" ++ ) ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Content-Type", "application/json") ++ fmt.Fprintf(w, `{ ++ "newNonce": %q, ++ "newAccount": %q, ++ "newOrder": %q, ++ "newAuthz": %q, ++ "revokeCert": %q, ++ "keyChange": %q, ++ "meta": { ++ "termsOfService": %q, ++ "website": %q, ++ "caaIdentities": [%q], ++ "externalAccountRequired": true ++ } ++ }`, nonce, reg, order, authz, revoke, keychange, metaTerms, metaWebsite, metaCAA) ++ })) ++ defer ts.Close() ++ c := &Client{DirectoryURL: ts.URL} ++ dir, err := c.Discover(context.Background()) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if dir.NonceURL != nonce { ++ t.Errorf("dir.NonceURL = %q; want %q", dir.NonceURL, nonce) ++ } ++ if dir.RegURL != reg { ++ t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg) ++ } ++ if dir.OrderURL != order { ++ t.Errorf("dir.OrderURL = %q; want %q", dir.OrderURL, order) ++ } ++ if dir.AuthzURL != authz { ++ t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz) ++ } ++ if dir.RevokeURL != revoke { ++ t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke) ++ } ++ if dir.KeyChangeURL != keychange { ++ t.Errorf("dir.KeyChangeURL = %q; want %q", dir.KeyChangeURL, keychange) ++ } ++ if dir.Terms != metaTerms { ++ t.Errorf("dir.Terms = %q; want %q", dir.Terms, metaTerms) ++ } ++ if dir.Website != metaWebsite { ++ t.Errorf("dir.Website = %q; want %q", dir.Website, metaWebsite) ++ } ++ if len(dir.CAA) == 0 || dir.CAA[0] != metaCAA { ++ t.Errorf("dir.CAA = %q; want [%q]", dir.CAA, metaCAA) ++ } ++ if !dir.ExternalAccountRequired { ++ t.Error("dir.Meta.ExternalAccountRequired is false") ++ } ++} ++ ++func TestRFC_popNonce(t *testing.T) { ++ var count int ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ // The Client uses only Directory.NonceURL when specified. ++ // Expect no other URL paths. ++ if r.URL.Path != "/new-nonce" { ++ t.Errorf("r.URL.Path = %q; want /new-nonce", r.URL.Path) ++ } ++ if count > 0 { ++ w.WriteHeader(http.StatusTooManyRequests) ++ return ++ } ++ count++ ++ w.Header().Set("Replay-Nonce", "second") ++ })) ++ cl := &Client{ ++ DirectoryURL: ts.URL, ++ dir: &Directory{NonceURL: ts.URL + "/new-nonce"}, ++ } ++ cl.addNonce(http.Header{"Replay-Nonce": {"first"}}) ++ ++ for i, nonce := range []string{"first", "second"} { ++ v, err := cl.popNonce(context.Background(), "") ++ if err != nil { ++ t.Errorf("%d: cl.popNonce: %v", i, err) ++ } ++ if v != nonce { ++ t.Errorf("%d: cl.popNonce = %q; want %q", i, v, nonce) ++ } ++ } ++ // No more nonces and server replies with an error past first nonce fetch. ++ // Expected to fail. ++ if _, err := cl.popNonce(context.Background(), ""); err == nil { ++ t.Error("last cl.popNonce returned nil error") ++ } ++} ++ ++func TestRFC_postKID(t *testing.T) { ++ var ts *httptest.Server ++ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ switch r.URL.Path { ++ case "/new-nonce": ++ w.Header().Set("Replay-Nonce", "nonce") ++ case "/new-account": ++ w.Header().Set("Location", "/account-1") ++ w.Write([]byte(`{"status":"valid"}`)) ++ case "/post": ++ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx ++ head, err := decodeJWSHead(bytes.NewReader(b)) ++ if err != nil { ++ t.Errorf("decodeJWSHead: %v", err) ++ return ++ } ++ if head.KID != "/account-1" { ++ t.Errorf("head.KID = %q; want /account-1", head.KID) ++ } ++ if len(head.JWK) != 0 { ++ t.Errorf("head.JWK = %q; want zero map", head.JWK) ++ } ++ if v := ts.URL + "/post"; head.URL != v { ++ t.Errorf("head.URL = %q; want %q", head.URL, v) ++ } ++ ++ var payload struct{ Msg string } ++ decodeJWSRequest(t, &payload, bytes.NewReader(b)) ++ if payload.Msg != "ping" { ++ t.Errorf("payload.Msg = %q; want ping", payload.Msg) ++ } ++ w.Write([]byte("pong")) ++ default: ++ t.Errorf("unhandled %s %s", r.Method, r.URL) ++ w.WriteHeader(http.StatusBadRequest) ++ } ++ })) ++ defer ts.Close() ++ ++ ctx := context.Background() ++ cl := &Client{ ++ Key: testKey, ++ DirectoryURL: ts.URL, ++ dir: &Directory{ ++ NonceURL: ts.URL + "/new-nonce", ++ RegURL: ts.URL + "/new-account", ++ OrderURL: "/force-rfc-mode", ++ }, ++ } ++ req := json.RawMessage(`{"msg":"ping"}`) ++ res, err := cl.post(ctx, nil /* use kid */, ts.URL+"/post", req, wantStatus(http.StatusOK)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer res.Body.Close() ++ b, _ := io.ReadAll(res.Body) // don't care about err - just checking b ++ if string(b) != "pong" { ++ t.Errorf("res.Body = %q; want pong", b) ++ } ++} ++ ++// acmeServer simulates a subset of RFC 8555 compliant CA. ++// ++// TODO: We also have x/crypto/acme/autocert/acmetest and startACMEServerStub in autocert_test.go. ++// It feels like this acmeServer is a sweet spot between usefulness and added complexity. ++// Also, acmetest and startACMEServerStub were both written for draft-02, no RFC support. ++// The goal is to consolidate all into one ACME test server. ++type acmeServer struct { ++ ts *httptest.Server ++ handler map[string]http.HandlerFunc // keyed by r.URL.Path ++ ++ mu sync.Mutex ++ nnonce int ++} ++ ++func newACMEServer() *acmeServer { ++ return &acmeServer{handler: make(map[string]http.HandlerFunc)} ++} ++ ++func (s *acmeServer) handle(path string, f func(http.ResponseWriter, *http.Request)) { ++ s.handler[path] = http.HandlerFunc(f) ++} ++ ++func (s *acmeServer) start() { ++ s.ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Content-Type", "application/json") ++ ++ // Directory request. ++ if r.URL.Path == "/" { ++ fmt.Fprintf(w, `{ ++ "newNonce": %q, ++ "newAccount": %q, ++ "newOrder": %q, ++ "newAuthz": %q, ++ "revokeCert": %q, ++ "keyChange": %q, ++ "meta": {"termsOfService": %q} ++ }`, ++ s.url("/acme/new-nonce"), ++ s.url("/acme/new-account"), ++ s.url("/acme/new-order"), ++ s.url("/acme/new-authz"), ++ s.url("/acme/revoke-cert"), ++ s.url("/acme/key-change"), ++ s.url("/terms"), ++ ) ++ return ++ } ++ ++ // All other responses contain a nonce value unconditionally. ++ w.Header().Set("Replay-Nonce", s.nonce()) ++ if r.URL.Path == "/acme/new-nonce" { ++ return ++ } ++ ++ h := s.handler[r.URL.Path] ++ if h == nil { ++ w.WriteHeader(http.StatusBadRequest) ++ fmt.Fprintf(w, "Unhandled %s", r.URL.Path) ++ return ++ } ++ h.ServeHTTP(w, r) ++ })) ++} ++ ++func (s *acmeServer) close() { ++ s.ts.Close() ++} ++ ++func (s *acmeServer) url(path string) string { ++ return s.ts.URL + path ++} ++ ++func (s *acmeServer) nonce() string { ++ s.mu.Lock() ++ defer s.mu.Unlock() ++ s.nnonce++ ++ return fmt.Sprintf("nonce%d", s.nnonce) ++} ++ ++func (s *acmeServer) error(w http.ResponseWriter, e *wireError) { ++ w.WriteHeader(e.Status) ++ json.NewEncoder(w).Encode(e) ++} ++ ++func TestRFC_Register(t *testing.T) { ++ const email = "mailto:user@example.org" ++ ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusCreated) // 201 means new account created ++ fmt.Fprintf(w, `{ ++ "status": "valid", ++ "contact": [%q], ++ "orders": %q ++ }`, email, s.url("/accounts/1/orders")) ++ ++ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx ++ head, err := decodeJWSHead(bytes.NewReader(b)) ++ if err != nil { ++ t.Errorf("decodeJWSHead: %v", err) ++ return ++ } ++ if len(head.JWK) == 0 { ++ t.Error("head.JWK is empty") ++ } ++ ++ var req struct{ Contact []string } ++ decodeJWSRequest(t, &req, bytes.NewReader(b)) ++ if len(req.Contact) != 1 || req.Contact[0] != email { ++ t.Errorf("req.Contact = %q; want [%q]", req.Contact, email) ++ } ++ }) ++ s.start() ++ defer s.close() ++ ++ ctx := context.Background() ++ cl := &Client{ ++ Key: testKeyEC, ++ DirectoryURL: s.url("/"), ++ } ++ ++ var didPrompt bool ++ a := &Account{Contact: []string{email}} ++ acct, err := cl.Register(ctx, a, func(tos string) bool { ++ didPrompt = true ++ terms := s.url("/terms") ++ if tos != terms { ++ t.Errorf("tos = %q; want %q", tos, terms) ++ } ++ return true ++ }) ++ if err != nil { ++ t.Fatal(err) ++ } ++ okAccount := &Account{ ++ URI: s.url("/accounts/1"), ++ Status: StatusValid, ++ Contact: []string{email}, ++ OrdersURL: s.url("/accounts/1/orders"), ++ } ++ if !reflect.DeepEqual(acct, okAccount) { ++ t.Errorf("acct = %+v; want %+v", acct, okAccount) ++ } ++ if !didPrompt { ++ t.Error("tos prompt wasn't called") ++ } ++ if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) { ++ t.Errorf("account kid = %q; want %q", v, okAccount.URI) ++ } ++} ++ ++func TestRFC_RegisterExternalAccountBinding(t *testing.T) { ++ eab := &ExternalAccountBinding{ ++ KID: "kid-1", ++ Key: []byte("secret"), ++ } ++ ++ type protected struct { ++ Algorithm string `json:"alg"` ++ KID string `json:"kid"` ++ URL string `json:"url"` ++ } ++ const email = "mailto:user@example.org" ++ ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ if r.Method != "POST" { ++ t.Errorf("r.Method = %q; want POST", r.Method) ++ } ++ ++ var j struct { ++ Protected string ++ Contact []string ++ TermsOfServiceAgreed bool ++ ExternalaccountBinding struct { ++ Protected string ++ Payload string ++ Signature string ++ } ++ } ++ decodeJWSRequest(t, &j, r.Body) ++ protData, err := base64.RawURLEncoding.DecodeString(j.ExternalaccountBinding.Protected) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ var prot protected ++ err = json.Unmarshal(protData, &prot) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if !reflect.DeepEqual(j.Contact, []string{email}) { ++ t.Errorf("j.Contact = %v; want %v", j.Contact, []string{email}) ++ } ++ if !j.TermsOfServiceAgreed { ++ t.Error("j.TermsOfServiceAgreed = false; want true") ++ } ++ ++ // Ensure same KID. ++ if prot.KID != eab.KID { ++ t.Errorf("j.ExternalAccountBinding.KID = %s; want %s", prot.KID, eab.KID) ++ } ++ // Ensure expected Algorithm. ++ if prot.Algorithm != "HS256" { ++ t.Errorf("j.ExternalAccountBinding.Alg = %s; want %s", ++ prot.Algorithm, "HS256") ++ } ++ ++ // Ensure same URL as outer JWS. ++ url := fmt.Sprintf("http://%s/acme/new-account", r.Host) ++ if prot.URL != url { ++ t.Errorf("j.ExternalAccountBinding.URL = %s; want %s", ++ prot.URL, url) ++ } ++ ++ // Ensure payload is base64URL encoded string of JWK in outer JWS ++ jwk, err := jwkEncode(testKeyEC.Public()) ++ if err != nil { ++ t.Fatal(err) ++ } ++ decodedPayload, err := base64.RawURLEncoding.DecodeString(j.ExternalaccountBinding.Payload) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if jwk != string(decodedPayload) { ++ t.Errorf("j.ExternalAccountBinding.Payload = %s; want %s", decodedPayload, jwk) ++ } ++ ++ // Check signature on inner external account binding JWS ++ hmac := hmac.New(sha256.New, []byte("secret")) ++ _, err = hmac.Write([]byte(j.ExternalaccountBinding.Protected + "." + j.ExternalaccountBinding.Payload)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ mac := hmac.Sum(nil) ++ encodedMAC := base64.RawURLEncoding.EncodeToString(mac) ++ ++ if !bytes.Equal([]byte(encodedMAC), []byte(j.ExternalaccountBinding.Signature)) { ++ t.Errorf("j.ExternalAccountBinding.Signature = %v; want %v", ++ []byte(j.ExternalaccountBinding.Signature), encodedMAC) ++ } ++ ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusCreated) ++ b, _ := json.Marshal([]string{email}) ++ fmt.Fprintf(w, `{"status":"valid","orders":"%s","contact":%s}`, s.url("/accounts/1/orders"), b) ++ }) ++ s.start() ++ defer s.close() ++ ++ ctx := context.Background() ++ cl := &Client{ ++ Key: testKeyEC, ++ DirectoryURL: s.url("/"), ++ } ++ ++ var didPrompt bool ++ a := &Account{Contact: []string{email}, ExternalAccountBinding: eab} ++ acct, err := cl.Register(ctx, a, func(tos string) bool { ++ didPrompt = true ++ terms := s.url("/terms") ++ if tos != terms { ++ t.Errorf("tos = %q; want %q", tos, terms) ++ } ++ return true ++ }) ++ if err != nil { ++ t.Fatal(err) ++ } ++ okAccount := &Account{ ++ URI: s.url("/accounts/1"), ++ Status: StatusValid, ++ Contact: []string{email}, ++ OrdersURL: s.url("/accounts/1/orders"), ++ } ++ if !reflect.DeepEqual(acct, okAccount) { ++ t.Errorf("acct = %+v; want %+v", acct, okAccount) ++ } ++ if !didPrompt { ++ t.Error("tos prompt wasn't called") ++ } ++ if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) { ++ t.Errorf("account kid = %q; want %q", v, okAccount.URI) ++ } ++} ++ ++func TestRFC_RegisterExisting(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) // 200 means account already exists ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ _, err := cl.Register(context.Background(), &Account{}, AcceptTOS) ++ if err != ErrAccountAlreadyExists { ++ t.Errorf("err = %v; want %v", err, ErrAccountAlreadyExists) ++ } ++ kid := KeyID(s.url("/accounts/1")) ++ if v := cl.accountKID(context.Background()); v != kid { ++ t.Errorf("account kid = %q; want %q", v, kid) ++ } ++} ++ ++func TestRFC_UpdateReg(t *testing.T) { ++ const email = "mailto:user@example.org" ++ ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ var didUpdate bool ++ s.handle("/accounts/1", func(w http.ResponseWriter, r *http.Request) { ++ didUpdate = true ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ ++ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx ++ head, err := decodeJWSHead(bytes.NewReader(b)) ++ if err != nil { ++ t.Errorf("decodeJWSHead: %v", err) ++ return ++ } ++ if len(head.JWK) != 0 { ++ t.Error("head.JWK is non-zero") ++ } ++ kid := s.url("/accounts/1") ++ if head.KID != kid { ++ t.Errorf("head.KID = %q; want %q", head.KID, kid) ++ } ++ ++ var req struct{ Contact []string } ++ decodeJWSRequest(t, &req, bytes.NewReader(b)) ++ if len(req.Contact) != 1 || req.Contact[0] != email { ++ t.Errorf("req.Contact = %q; want [%q]", req.Contact, email) ++ } ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ _, err := cl.UpdateReg(context.Background(), &Account{Contact: []string{email}}) ++ if err != nil { ++ t.Error(err) ++ } ++ if !didUpdate { ++ t.Error("UpdateReg didn't update the account") ++ } ++} ++ ++func TestRFC_GetReg(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ ++ head, err := decodeJWSHead(r.Body) ++ if err != nil { ++ t.Errorf("decodeJWSHead: %v", err) ++ return ++ } ++ if len(head.JWK) == 0 { ++ t.Error("head.JWK is empty") ++ } ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ acct, err := cl.GetReg(context.Background(), "") ++ if err != nil { ++ t.Fatal(err) ++ } ++ okAccount := &Account{ ++ URI: s.url("/accounts/1"), ++ Status: StatusValid, ++ } ++ if !reflect.DeepEqual(acct, okAccount) { ++ t.Errorf("acct = %+v; want %+v", acct, okAccount) ++ } ++} ++ ++func TestRFC_GetRegNoAccount(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ s.error(w, &wireError{ ++ Status: http.StatusBadRequest, ++ Type: "urn:ietf:params:acme:error:accountDoesNotExist", ++ }) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ if _, err := cl.GetReg(context.Background(), ""); err != ErrNoAccount { ++ t.Errorf("err = %v; want %v", err, ErrNoAccount) ++ } ++} ++ ++func TestRFC_GetRegOtherError(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.WriteHeader(http.StatusBadRequest) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ if _, err := cl.GetReg(context.Background(), ""); err == nil || err == ErrNoAccount { ++ t.Errorf("GetReg: %v; want any other non-nil err", err) ++ } ++} ++ ++func TestRFC_AccountKeyRollover(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ s.handle("/acme/key-change", func(w http.ResponseWriter, r *http.Request) { ++ w.WriteHeader(http.StatusOK) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ if err := cl.AccountKeyRollover(context.Background(), testKeyEC384); err != nil { ++ t.Errorf("AccountKeyRollover: %v, wanted no error", err) ++ } else if cl.Key != testKeyEC384 { ++ t.Error("AccountKeyRollover did not rotate the client key") ++ } ++} ++ ++func TestRFC_DeactivateReg(t *testing.T) { ++ const email = "mailto:user@example.org" ++ curStatus := StatusValid ++ ++ type account struct { ++ Status string `json:"status"` ++ Contact []string `json:"contact"` ++ AcceptTOS bool `json:"termsOfServiceAgreed"` ++ Orders string `json:"orders"` ++ } ++ ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) // 200 means existing account ++ json.NewEncoder(w).Encode(account{ ++ Status: curStatus, ++ Contact: []string{email}, ++ AcceptTOS: true, ++ Orders: s.url("/accounts/1/orders"), ++ }) ++ ++ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx ++ head, err := decodeJWSHead(bytes.NewReader(b)) ++ if err != nil { ++ t.Errorf("decodeJWSHead: %v", err) ++ return ++ } ++ if len(head.JWK) == 0 { ++ t.Error("head.JWK is empty") ++ } ++ ++ var req struct { ++ Status string `json:"status"` ++ Contact []string `json:"contact"` ++ AcceptTOS bool `json:"termsOfServiceAgreed"` ++ OnlyExisting bool `json:"onlyReturnExisting"` ++ } ++ decodeJWSRequest(t, &req, bytes.NewReader(b)) ++ if !req.OnlyExisting { ++ t.Errorf("req.OnlyReturnExisting = %t; want = %t", req.OnlyExisting, true) ++ } ++ }) ++ s.handle("/accounts/1", func(w http.ResponseWriter, r *http.Request) { ++ if curStatus == StatusValid { ++ curStatus = StatusDeactivated ++ w.WriteHeader(http.StatusOK) ++ } else { ++ s.error(w, &wireError{ ++ Status: http.StatusUnauthorized, ++ Type: "urn:ietf:params:acme:error:unauthorized", ++ }) ++ } ++ var req account ++ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx ++ head, err := decodeJWSHead(bytes.NewReader(b)) ++ if err != nil { ++ t.Errorf("decodeJWSHead: %v", err) ++ return ++ } ++ if len(head.JWK) != 0 { ++ t.Error("head.JWK is not empty") ++ } ++ if !strings.HasSuffix(head.KID, "/accounts/1") { ++ t.Errorf("head.KID = %q; want suffix /accounts/1", head.KID) ++ } ++ ++ decodeJWSRequest(t, &req, bytes.NewReader(b)) ++ if req.Status != StatusDeactivated { ++ t.Errorf("req.Status = %q; want = %q", req.Status, StatusDeactivated) ++ } ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ if err := cl.DeactivateReg(context.Background()); err != nil { ++ t.Errorf("DeactivateReg: %v, wanted no error", err) ++ } ++ if err := cl.DeactivateReg(context.Background()); err == nil { ++ t.Errorf("DeactivateReg: %v, wanted error for unauthorized", err) ++ } ++} ++ ++func TestRF_DeactivateRegNoAccount(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ s.error(w, &wireError{ ++ Status: http.StatusBadRequest, ++ Type: "urn:ietf:params:acme:error:accountDoesNotExist", ++ }) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ if err := cl.DeactivateReg(context.Background()); !errors.Is(err, ErrNoAccount) { ++ t.Errorf("DeactivateReg: %v, wanted ErrNoAccount", err) ++ } ++} ++ ++func TestRFC_AuthorizeOrder(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ s.handle("/acme/new-order", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/orders/1")) ++ w.WriteHeader(http.StatusCreated) ++ fmt.Fprintf(w, `{ ++ "status": "pending", ++ "expires": "2019-09-01T00:00:00Z", ++ "notBefore": "2019-08-31T00:00:00Z", ++ "notAfter": "2019-09-02T00:00:00Z", ++ "identifiers": [{"type":"dns", "value":"example.org"}], ++ "authorizations": [%q] ++ }`, s.url("/authz/1")) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ o, err := cl.AuthorizeOrder(context.Background(), DomainIDs("example.org"), ++ WithOrderNotBefore(time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC)), ++ WithOrderNotAfter(time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC)), ++ ) ++ if err != nil { ++ t.Fatal(err) ++ } ++ okOrder := &Order{ ++ URI: s.url("/orders/1"), ++ Status: StatusPending, ++ Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC), ++ NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC), ++ NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC), ++ Identifiers: []AuthzID{AuthzID{Type: "dns", Value: "example.org"}}, ++ AuthzURLs: []string{s.url("/authz/1")}, ++ } ++ if !reflect.DeepEqual(o, okOrder) { ++ t.Errorf("AuthorizeOrder = %+v; want %+v", o, okOrder) ++ } ++} ++ ++func TestRFC_GetOrder(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/orders/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{ ++ "status": "invalid", ++ "expires": "2019-09-01T00:00:00Z", ++ "notBefore": "2019-08-31T00:00:00Z", ++ "notAfter": "2019-09-02T00:00:00Z", ++ "identifiers": [{"type":"dns", "value":"example.org"}], ++ "authorizations": ["/authz/1"], ++ "finalize": "/orders/1/fin", ++ "certificate": "/orders/1/cert", ++ "error": {"type": "badRequest"} ++ }`)) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ o, err := cl.GetOrder(context.Background(), s.url("/orders/1")) ++ if err != nil { ++ t.Fatal(err) ++ } ++ okOrder := &Order{ ++ URI: s.url("/orders/1"), ++ Status: StatusInvalid, ++ Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC), ++ NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC), ++ NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC), ++ Identifiers: []AuthzID{AuthzID{Type: "dns", Value: "example.org"}}, ++ AuthzURLs: []string{"/authz/1"}, ++ FinalizeURL: "/orders/1/fin", ++ CertURL: "/orders/1/cert", ++ Error: &Error{ProblemType: "badRequest"}, ++ } ++ if !reflect.DeepEqual(o, okOrder) { ++ t.Errorf("GetOrder = %+v\nwant %+v", o, okOrder) ++ } ++} ++ ++func TestRFC_WaitOrder(t *testing.T) { ++ for _, st := range []string{StatusReady, StatusValid} { ++ t.Run(st, func(t *testing.T) { ++ testWaitOrderStatus(t, st) ++ }) ++ } ++} ++ ++func testWaitOrderStatus(t *testing.T, okStatus string) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ var count int ++ s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/orders/1")) ++ w.WriteHeader(http.StatusOK) ++ s := StatusPending ++ if count > 0 { ++ s = okStatus ++ } ++ fmt.Fprintf(w, `{"status": %q}`, s) ++ count++ ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ order, err := cl.WaitOrder(context.Background(), s.url("/orders/1")) ++ if err != nil { ++ t.Fatalf("WaitOrder: %v", err) ++ } ++ if order.Status != okStatus { ++ t.Errorf("order.Status = %q; want %q", order.Status, okStatus) ++ } ++} ++ ++func TestRFC_WaitOrderError(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.WriteHeader(http.StatusOK) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ var count int ++ s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/orders/1")) ++ w.WriteHeader(http.StatusOK) ++ s := StatusPending ++ if count > 0 { ++ s = StatusInvalid ++ } ++ fmt.Fprintf(w, `{"status": %q}`, s) ++ count++ ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ _, err := cl.WaitOrder(context.Background(), s.url("/orders/1")) ++ if err == nil { ++ t.Fatal("WaitOrder returned nil error") ++ } ++ e, ok := err.(*OrderError) ++ if !ok { ++ t.Fatalf("err = %v (%T); want OrderError", err, err) ++ } ++ if e.OrderURL != s.url("/orders/1") { ++ t.Errorf("e.OrderURL = %q; want %q", e.OrderURL, s.url("/orders/1")) ++ } ++ if e.Status != StatusInvalid { ++ t.Errorf("e.Status = %q; want %q", e.Status, StatusInvalid) ++ } ++} ++ ++func TestRFC_CreateOrderCert(t *testing.T) { ++ q := &x509.CertificateRequest{ ++ Subject: pkix.Name{CommonName: "example.org"}, ++ } ++ csr, err := x509.CreateCertificateRequest(rand.Reader, q, testKeyEC) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ tmpl := &x509.Certificate{SerialNumber: big.NewInt(1)} ++ leaf, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testKeyEC.PublicKey, testKeyEC) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ s := newACMEServer() ++ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/accounts/1")) ++ w.Write([]byte(`{"status": "valid"}`)) ++ }) ++ var count int ++ s.handle("/pleaseissue", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Location", s.url("/pleaseissue")) ++ st := StatusProcessing ++ if count > 0 { ++ st = StatusValid ++ } ++ fmt.Fprintf(w, `{"status":%q, "certificate":%q}`, st, s.url("/crt")) ++ count++ ++ }) ++ s.handle("/crt", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Content-Type", "application/pem-certificate-chain") ++ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: leaf}) ++ }) ++ s.start() ++ defer s.close() ++ ctx := context.Background() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ cert, curl, err := cl.CreateOrderCert(ctx, s.url("/pleaseissue"), csr, true) ++ if err != nil { ++ t.Fatalf("CreateOrderCert: %v", err) ++ } ++ if _, err := x509.ParseCertificate(cert[0]); err != nil { ++ t.Errorf("ParseCertificate: %v", err) ++ } ++ if !reflect.DeepEqual(cert[0], leaf) { ++ t.Errorf("cert and leaf bytes don't match") ++ } ++ if u := s.url("/crt"); curl != u { ++ t.Errorf("curl = %q; want %q", curl, u) ++ } ++} ++ ++func TestRFC_AlreadyRevokedCert(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/acme/revoke-cert", func(w http.ResponseWriter, r *http.Request) { ++ s.error(w, &wireError{ ++ Status: http.StatusBadRequest, ++ Type: "urn:ietf:params:acme:error:alreadyRevoked", ++ }) ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ err := cl.RevokeCert(context.Background(), testKeyEC, []byte{0}, CRLReasonUnspecified) ++ if err != nil { ++ t.Fatalf("RevokeCert: %v", err) ++ } ++} ++ ++func TestRFC_ListCertAlternates(t *testing.T) { ++ s := newACMEServer() ++ s.handle("/crt", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Content-Type", "application/pem-certificate-chain") ++ w.Header().Add("Link", `;rel="alternate"`) ++ w.Header().Add("Link", `; rel="alternate"`) ++ w.Header().Add("Link", `; rel="index"`) ++ }) ++ s.handle("/crt2", func(w http.ResponseWriter, r *http.Request) { ++ w.Header().Set("Content-Type", "application/pem-certificate-chain") ++ }) ++ s.start() ++ defer s.close() ++ ++ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} ++ crts, err := cl.ListCertAlternates(context.Background(), s.url("/crt")) ++ if err != nil { ++ t.Fatalf("ListCertAlternates: %v", err) ++ } ++ want := []string{"https://example.com/crt/2", "https://example.com/crt/3"} ++ if !reflect.DeepEqual(crts, want) { ++ t.Errorf("ListCertAlternates(/crt): %v; want %v", crts, want) ++ } ++ crts, err = cl.ListCertAlternates(context.Background(), s.url("/crt2")) ++ if err != nil { ++ t.Fatalf("ListCertAlternates: %v", err) ++ } ++ if crts != nil { ++ t.Errorf("ListCertAlternates(/crt2): %v; want nil", crts) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/types.go b/ms_mod/golang.org/x/crypto/acme/types.go +new file mode 100644 +index 00000000000000..4888726fecdea8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/types.go +@@ -0,0 +1,614 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "crypto" ++ "crypto/x509" ++ "errors" ++ "fmt" ++ "net/http" ++ "strings" ++ "time" ++) ++ ++// ACME status values of Account, Order, Authorization and Challenge objects. ++// See https://tools.ietf.org/html/rfc8555#section-7.1.6 for details. ++const ( ++ StatusDeactivated = "deactivated" ++ StatusExpired = "expired" ++ StatusInvalid = "invalid" ++ StatusPending = "pending" ++ StatusProcessing = "processing" ++ StatusReady = "ready" ++ StatusRevoked = "revoked" ++ StatusUnknown = "unknown" ++ StatusValid = "valid" ++) ++ ++// CRLReasonCode identifies the reason for a certificate revocation. ++type CRLReasonCode int ++ ++// CRL reason codes as defined in RFC 5280. ++const ( ++ CRLReasonUnspecified CRLReasonCode = 0 ++ CRLReasonKeyCompromise CRLReasonCode = 1 ++ CRLReasonCACompromise CRLReasonCode = 2 ++ CRLReasonAffiliationChanged CRLReasonCode = 3 ++ CRLReasonSuperseded CRLReasonCode = 4 ++ CRLReasonCessationOfOperation CRLReasonCode = 5 ++ CRLReasonCertificateHold CRLReasonCode = 6 ++ CRLReasonRemoveFromCRL CRLReasonCode = 8 ++ CRLReasonPrivilegeWithdrawn CRLReasonCode = 9 ++ CRLReasonAACompromise CRLReasonCode = 10 ++) ++ ++var ( ++ // ErrUnsupportedKey is returned when an unsupported key type is encountered. ++ ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported") ++ ++ // ErrAccountAlreadyExists indicates that the Client's key has already been registered ++ // with the CA. It is returned by Register method. ++ ErrAccountAlreadyExists = errors.New("acme: account already exists") ++ ++ // ErrNoAccount indicates that the Client's key has not been registered with the CA. ++ ErrNoAccount = errors.New("acme: account does not exist") ++) ++ ++// A Subproblem describes an ACME subproblem as reported in an Error. ++type Subproblem struct { ++ // Type is a URI reference that identifies the problem type, ++ // typically in a "urn:acme:error:xxx" form. ++ Type string ++ // Detail is a human-readable explanation specific to this occurrence of the problem. ++ Detail string ++ // Instance indicates a URL that the client should direct a human user to visit ++ // in order for instructions on how to agree to the updated Terms of Service. ++ // In such an event CA sets StatusCode to 403, Type to ++ // "urn:ietf:params:acme:error:userActionRequired", and adds a Link header with relation ++ // "terms-of-service" containing the latest TOS URL. ++ Instance string ++ // Identifier may contain the ACME identifier that the error is for. ++ Identifier *AuthzID ++} ++ ++func (sp Subproblem) String() string { ++ str := fmt.Sprintf("%s: ", sp.Type) ++ if sp.Identifier != nil { ++ str += fmt.Sprintf("[%s: %s] ", sp.Identifier.Type, sp.Identifier.Value) ++ } ++ str += sp.Detail ++ return str ++} ++ ++// Error is an ACME error, defined in Problem Details for HTTP APIs doc ++// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem. ++type Error struct { ++ // StatusCode is The HTTP status code generated by the origin server. ++ StatusCode int ++ // ProblemType is a URI reference that identifies the problem type, ++ // typically in a "urn:acme:error:xxx" form. ++ ProblemType string ++ // Detail is a human-readable explanation specific to this occurrence of the problem. ++ Detail string ++ // Instance indicates a URL that the client should direct a human user to visit ++ // in order for instructions on how to agree to the updated Terms of Service. ++ // In such an event CA sets StatusCode to 403, ProblemType to ++ // "urn:ietf:params:acme:error:userActionRequired" and a Link header with relation ++ // "terms-of-service" containing the latest TOS URL. ++ Instance string ++ // Header is the original server error response headers. ++ // It may be nil. ++ Header http.Header ++ // Subproblems may contain more detailed information about the individual problems ++ // that caused the error. This field is only sent by RFC 8555 compatible ACME ++ // servers. Defined in RFC 8555 Section 6.7.1. ++ Subproblems []Subproblem ++} ++ ++func (e *Error) Error() string { ++ str := fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail) ++ if len(e.Subproblems) > 0 { ++ str += fmt.Sprintf("; subproblems:") ++ for _, sp := range e.Subproblems { ++ str += fmt.Sprintf("\n\t%s", sp) ++ } ++ } ++ return str ++} ++ ++// AuthorizationError indicates that an authorization for an identifier ++// did not succeed. ++// It contains all errors from Challenge items of the failed Authorization. ++type AuthorizationError struct { ++ // URI uniquely identifies the failed Authorization. ++ URI string ++ ++ // Identifier is an AuthzID.Value of the failed Authorization. ++ Identifier string ++ ++ // Errors is a collection of non-nil error values of Challenge items ++ // of the failed Authorization. ++ Errors []error ++} ++ ++func (a *AuthorizationError) Error() string { ++ e := make([]string, len(a.Errors)) ++ for i, err := range a.Errors { ++ e[i] = err.Error() ++ } ++ ++ if a.Identifier != "" { ++ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; ")) ++ } ++ ++ return fmt.Sprintf("acme: authorization error: %s", strings.Join(e, "; ")) ++} ++ ++// OrderError is returned from Client's order related methods. ++// It indicates the order is unusable and the clients should start over with ++// AuthorizeOrder. ++// ++// The clients can still fetch the order object from CA using GetOrder ++// to inspect its state. ++type OrderError struct { ++ OrderURL string ++ Status string ++} ++ ++func (oe *OrderError) Error() string { ++ return fmt.Sprintf("acme: order %s status: %s", oe.OrderURL, oe.Status) ++} ++ ++// RateLimit reports whether err represents a rate limit error and ++// any Retry-After duration returned by the server. ++// ++// See the following for more details on rate limiting: ++// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6 ++func RateLimit(err error) (time.Duration, bool) { ++ e, ok := err.(*Error) ++ if !ok { ++ return 0, false ++ } ++ // Some CA implementations may return incorrect values. ++ // Use case-insensitive comparison. ++ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") { ++ return 0, false ++ } ++ if e.Header == nil { ++ return 0, true ++ } ++ return retryAfter(e.Header.Get("Retry-After")), true ++} ++ ++// Account is a user account. It is associated with a private key. ++// Non-RFC 8555 fields are empty when interfacing with a compliant CA. ++type Account struct { ++ // URI is the account unique ID, which is also a URL used to retrieve ++ // account data from the CA. ++ // When interfacing with RFC 8555-compliant CAs, URI is the "kid" field ++ // value in JWS signed requests. ++ URI string ++ ++ // Contact is a slice of contact info used during registration. ++ // See https://tools.ietf.org/html/rfc8555#section-7.3 for supported ++ // formats. ++ Contact []string ++ ++ // Status indicates current account status as returned by the CA. ++ // Possible values are StatusValid, StatusDeactivated, and StatusRevoked. ++ Status string ++ ++ // OrdersURL is a URL from which a list of orders submitted by this account ++ // can be fetched. ++ OrdersURL string ++ ++ // The terms user has agreed to. ++ // A value not matching CurrentTerms indicates that the user hasn't agreed ++ // to the actual Terms of Service of the CA. ++ // ++ // It is non-RFC 8555 compliant. Package users can store the ToS they agree to ++ // during Client's Register call in the prompt callback function. ++ AgreedTerms string ++ ++ // Actual terms of a CA. ++ // ++ // It is non-RFC 8555 compliant. Use Directory's Terms field. ++ // When a CA updates their terms and requires an account agreement, ++ // a URL at which instructions to do so is available in Error's Instance field. ++ CurrentTerms string ++ ++ // Authz is the authorization URL used to initiate a new authz flow. ++ // ++ // It is non-RFC 8555 compliant. Use Directory's AuthzURL or OrderURL. ++ Authz string ++ ++ // Authorizations is a URI from which a list of authorizations ++ // granted to this account can be fetched via a GET request. ++ // ++ // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. ++ Authorizations string ++ ++ // Certificates is a URI from which a list of certificates ++ // issued for this account can be fetched via a GET request. ++ // ++ // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. ++ Certificates string ++ ++ // ExternalAccountBinding represents an arbitrary binding to an account of ++ // the CA which the ACME server is tied to. ++ // See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. ++ ExternalAccountBinding *ExternalAccountBinding ++} ++ ++// ExternalAccountBinding contains the data needed to form a request with ++// an external account binding. ++// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. ++type ExternalAccountBinding struct { ++ // KID is the Key ID of the symmetric MAC key that the CA provides to ++ // identify an external account from ACME. ++ KID string ++ ++ // Key is the bytes of the symmetric key that the CA provides to identify ++ // the account. Key must correspond to the KID. ++ Key []byte ++} ++ ++func (e *ExternalAccountBinding) String() string { ++ return fmt.Sprintf("&{KID: %q, Key: redacted}", e.KID) ++} ++ ++// Directory is ACME server discovery data. ++// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details. ++type Directory struct { ++ // NonceURL indicates an endpoint where to fetch fresh nonce values from. ++ NonceURL string ++ ++ // RegURL is an account endpoint URL, allowing for creating new accounts. ++ // Pre-RFC 8555 CAs also allow modifying existing accounts at this URL. ++ RegURL string ++ ++ // OrderURL is used to initiate the certificate issuance flow ++ // as described in RFC 8555. ++ OrderURL string ++ ++ // AuthzURL is used to initiate identifier pre-authorization flow. ++ // Empty string indicates the flow is unsupported by the CA. ++ AuthzURL string ++ ++ // CertURL is a new certificate issuance endpoint URL. ++ // It is non-RFC 8555 compliant and is obsoleted by OrderURL. ++ CertURL string ++ ++ // RevokeURL is used to initiate a certificate revocation flow. ++ RevokeURL string ++ ++ // KeyChangeURL allows to perform account key rollover flow. ++ KeyChangeURL string ++ ++ // Term is a URI identifying the current terms of service. ++ Terms string ++ ++ // Website is an HTTP or HTTPS URL locating a website ++ // providing more information about the ACME server. ++ Website string ++ ++ // CAA consists of lowercase hostname elements, which the ACME server ++ // recognises as referring to itself for the purposes of CAA record validation ++ // as defined in RFC 6844. ++ CAA []string ++ ++ // ExternalAccountRequired indicates that the CA requires for all account-related ++ // requests to include external account binding information. ++ ExternalAccountRequired bool ++} ++ ++// Order represents a client's request for a certificate. ++// It tracks the request flow progress through to issuance. ++type Order struct { ++ // URI uniquely identifies an order. ++ URI string ++ ++ // Status represents the current status of the order. ++ // It indicates which action the client should take. ++ // ++ // Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid. ++ // Pending means the CA does not believe that the client has fulfilled the requirements. ++ // Ready indicates that the client has fulfilled all the requirements and can submit a CSR ++ // to obtain a certificate. This is done with Client's CreateOrderCert. ++ // Processing means the certificate is being issued. ++ // Valid indicates the CA has issued the certificate. It can be downloaded ++ // from the Order's CertURL. This is done with Client's FetchCert. ++ // Invalid means the certificate will not be issued. Users should consider this order ++ // abandoned. ++ Status string ++ ++ // Expires is the timestamp after which CA considers this order invalid. ++ Expires time.Time ++ ++ // Identifiers contains all identifier objects which the order pertains to. ++ Identifiers []AuthzID ++ ++ // NotBefore is the requested value of the notBefore field in the certificate. ++ NotBefore time.Time ++ ++ // NotAfter is the requested value of the notAfter field in the certificate. ++ NotAfter time.Time ++ ++ // AuthzURLs represents authorizations to complete before a certificate ++ // for identifiers specified in the order can be issued. ++ // It also contains unexpired authorizations that the client has completed ++ // in the past. ++ // ++ // Authorization objects can be fetched using Client's GetAuthorization method. ++ // ++ // The required authorizations are dictated by CA policies. ++ // There may not be a 1:1 relationship between the identifiers and required authorizations. ++ // Required authorizations can be identified by their StatusPending status. ++ // ++ // For orders in the StatusValid or StatusInvalid state these are the authorizations ++ // which were completed. ++ AuthzURLs []string ++ ++ // FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate ++ // once all the authorizations are satisfied. ++ FinalizeURL string ++ ++ // CertURL points to the certificate that has been issued in response to this order. ++ CertURL string ++ ++ // The error that occurred while processing the order as received from a CA, if any. ++ Error *Error ++} ++ ++// OrderOption allows customizing Client.AuthorizeOrder call. ++type OrderOption interface { ++ privateOrderOpt() ++} ++ ++// WithOrderNotBefore sets order's NotBefore field. ++func WithOrderNotBefore(t time.Time) OrderOption { ++ return orderNotBeforeOpt(t) ++} ++ ++// WithOrderNotAfter sets order's NotAfter field. ++func WithOrderNotAfter(t time.Time) OrderOption { ++ return orderNotAfterOpt(t) ++} ++ ++type orderNotBeforeOpt time.Time ++ ++func (orderNotBeforeOpt) privateOrderOpt() {} ++ ++type orderNotAfterOpt time.Time ++ ++func (orderNotAfterOpt) privateOrderOpt() {} ++ ++// Authorization encodes an authorization response. ++type Authorization struct { ++ // URI uniquely identifies a authorization. ++ URI string ++ ++ // Status is the current status of an authorization. ++ // Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated, ++ // StatusExpired and StatusRevoked. ++ Status string ++ ++ // Identifier is what the account is authorized to represent. ++ Identifier AuthzID ++ ++ // The timestamp after which the CA considers the authorization invalid. ++ Expires time.Time ++ ++ // Wildcard is true for authorizations of a wildcard domain name. ++ Wildcard bool ++ ++ // Challenges that the client needs to fulfill in order to prove possession ++ // of the identifier (for pending authorizations). ++ // For valid authorizations, the challenge that was validated. ++ // For invalid authorizations, the challenge that was attempted and failed. ++ // ++ // RFC 8555 compatible CAs require users to fuflfill only one of the challenges. ++ Challenges []*Challenge ++ ++ // A collection of sets of challenges, each of which would be sufficient ++ // to prove possession of the identifier. ++ // Clients must complete a set of challenges that covers at least one set. ++ // Challenges are identified by their indices in the challenges array. ++ // If this field is empty, the client needs to complete all challenges. ++ // ++ // This field is unused in RFC 8555. ++ Combinations [][]int ++} ++ ++// AuthzID is an identifier that an account is authorized to represent. ++type AuthzID struct { ++ Type string // The type of identifier, "dns" or "ip". ++ Value string // The identifier itself, e.g. "example.org". ++} ++ ++// DomainIDs creates a slice of AuthzID with "dns" identifier type. ++func DomainIDs(names ...string) []AuthzID { ++ a := make([]AuthzID, len(names)) ++ for i, v := range names { ++ a[i] = AuthzID{Type: "dns", Value: v} ++ } ++ return a ++} ++ ++// IPIDs creates a slice of AuthzID with "ip" identifier type. ++// Each element of addr is textual form of an address as defined ++// in RFC 1123 Section 2.1 for IPv4 and in RFC 5952 Section 4 for IPv6. ++func IPIDs(addr ...string) []AuthzID { ++ a := make([]AuthzID, len(addr)) ++ for i, v := range addr { ++ a[i] = AuthzID{Type: "ip", Value: v} ++ } ++ return a ++} ++ ++// wireAuthzID is ACME JSON representation of authorization identifier objects. ++type wireAuthzID struct { ++ Type string `json:"type"` ++ Value string `json:"value"` ++} ++ ++// wireAuthz is ACME JSON representation of Authorization objects. ++type wireAuthz struct { ++ Identifier wireAuthzID ++ Status string ++ Expires time.Time ++ Wildcard bool ++ Challenges []wireChallenge ++ Combinations [][]int ++ Error *wireError ++} ++ ++func (z *wireAuthz) authorization(uri string) *Authorization { ++ a := &Authorization{ ++ URI: uri, ++ Status: z.Status, ++ Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, ++ Expires: z.Expires, ++ Wildcard: z.Wildcard, ++ Challenges: make([]*Challenge, len(z.Challenges)), ++ Combinations: z.Combinations, // shallow copy ++ } ++ for i, v := range z.Challenges { ++ a.Challenges[i] = v.challenge() ++ } ++ return a ++} ++ ++func (z *wireAuthz) error(uri string) *AuthorizationError { ++ err := &AuthorizationError{ ++ URI: uri, ++ Identifier: z.Identifier.Value, ++ } ++ ++ if z.Error != nil { ++ err.Errors = append(err.Errors, z.Error.error(nil)) ++ } ++ ++ for _, raw := range z.Challenges { ++ if raw.Error != nil { ++ err.Errors = append(err.Errors, raw.Error.error(nil)) ++ } ++ } ++ ++ return err ++} ++ ++// Challenge encodes a returned CA challenge. ++// Its Error field may be non-nil if the challenge is part of an Authorization ++// with StatusInvalid. ++type Challenge struct { ++ // Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01". ++ Type string ++ ++ // URI is where a challenge response can be posted to. ++ URI string ++ ++ // Token is a random value that uniquely identifies the challenge. ++ Token string ++ ++ // Status identifies the status of this challenge. ++ // In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid, ++ // and StatusInvalid. ++ Status string ++ ++ // Validated is the time at which the CA validated this challenge. ++ // Always zero value in pre-RFC 8555. ++ Validated time.Time ++ ++ // Error indicates the reason for an authorization failure ++ // when this challenge was used. ++ // The type of a non-nil value is *Error. ++ Error error ++} ++ ++// wireChallenge is ACME JSON challenge representation. ++type wireChallenge struct { ++ URL string `json:"url"` // RFC ++ URI string `json:"uri"` // pre-RFC ++ Type string ++ Token string ++ Status string ++ Validated time.Time ++ Error *wireError ++} ++ ++func (c *wireChallenge) challenge() *Challenge { ++ v := &Challenge{ ++ URI: c.URL, ++ Type: c.Type, ++ Token: c.Token, ++ Status: c.Status, ++ } ++ if v.URI == "" { ++ v.URI = c.URI // c.URL was empty; use legacy ++ } ++ if v.Status == "" { ++ v.Status = StatusPending ++ } ++ if c.Error != nil { ++ v.Error = c.Error.error(nil) ++ } ++ return v ++} ++ ++// wireError is a subset of fields of the Problem Details object ++// as described in https://tools.ietf.org/html/rfc7807#section-3.1. ++type wireError struct { ++ Status int ++ Type string ++ Detail string ++ Instance string ++ Subproblems []Subproblem ++} ++ ++func (e *wireError) error(h http.Header) *Error { ++ err := &Error{ ++ StatusCode: e.Status, ++ ProblemType: e.Type, ++ Detail: e.Detail, ++ Instance: e.Instance, ++ Header: h, ++ Subproblems: e.Subproblems, ++ } ++ return err ++} ++ ++// CertOption is an optional argument type for the TLS ChallengeCert methods for ++// customizing a temporary certificate for TLS-based challenges. ++type CertOption interface { ++ privateCertOpt() ++} ++ ++// WithKey creates an option holding a private/public key pair. ++// The private part signs a certificate, and the public part represents the signee. ++func WithKey(key crypto.Signer) CertOption { ++ return &certOptKey{key} ++} ++ ++type certOptKey struct { ++ key crypto.Signer ++} ++ ++func (*certOptKey) privateCertOpt() {} ++ ++// WithTemplate creates an option for specifying a certificate template. ++// See x509.CreateCertificate for template usage details. ++// ++// In TLS ChallengeCert methods, the template is also used as parent, ++// resulting in a self-signed certificate. ++// The DNSNames field of t is always overwritten for tls-sni challenge certs. ++func WithTemplate(t *x509.Certificate) CertOption { ++ return (*certOptTemplate)(t) ++} ++ ++type certOptTemplate x509.Certificate ++ ++func (*certOptTemplate) privateCertOpt() {} +diff --git a/ms_mod/golang.org/x/crypto/acme/types_test.go b/ms_mod/golang.org/x/crypto/acme/types_test.go +new file mode 100644 +index 00000000000000..59ce7e7602ca31 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/types_test.go +@@ -0,0 +1,219 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package acme ++ ++import ( ++ "errors" ++ "net/http" ++ "reflect" ++ "testing" ++ "time" ++) ++ ++func TestExternalAccountBindingString(t *testing.T) { ++ eab := ExternalAccountBinding{ ++ KID: "kid", ++ Key: []byte("key"), ++ } ++ got := eab.String() ++ want := `&{KID: "kid", Key: redacted}` ++ if got != want { ++ t.Errorf("eab.String() = %q, want: %q", got, want) ++ } ++} ++ ++func TestRateLimit(t *testing.T) { ++ now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC) ++ f := timeNow ++ defer func() { timeNow = f }() ++ timeNow = func() time.Time { return now } ++ ++ h120, hTime := http.Header{}, http.Header{} ++ h120.Set("Retry-After", "120") ++ hTime.Set("Retry-After", "Tue Apr 27 11:00:00 2017") ++ ++ err1 := &Error{ ++ ProblemType: "urn:ietf:params:acme:error:nolimit", ++ Header: h120, ++ } ++ err2 := &Error{ ++ ProblemType: "urn:ietf:params:acme:error:rateLimited", ++ Header: h120, ++ } ++ err3 := &Error{ ++ ProblemType: "urn:ietf:params:acme:error:rateLimited", ++ Header: nil, ++ } ++ err4 := &Error{ ++ ProblemType: "urn:ietf:params:acme:error:rateLimited", ++ Header: hTime, ++ } ++ ++ tt := []struct { ++ err error ++ res time.Duration ++ ok bool ++ }{ ++ {nil, 0, false}, ++ {errors.New("dummy"), 0, false}, ++ {err1, 0, false}, ++ {err2, 2 * time.Minute, true}, ++ {err3, 0, true}, ++ {err4, time.Hour, true}, ++ } ++ for i, test := range tt { ++ res, ok := RateLimit(test.err) ++ if ok != test.ok { ++ t.Errorf("%d: RateLimit(%+v): ok = %v; want %v", i, test.err, ok, test.ok) ++ continue ++ } ++ if res != test.res { ++ t.Errorf("%d: RateLimit(%+v) = %v; want %v", i, test.err, res, test.res) ++ } ++ } ++} ++ ++func TestAuthorizationError(t *testing.T) { ++ tests := []struct { ++ desc string ++ err *AuthorizationError ++ msg string ++ }{ ++ { ++ desc: "when auth error identifier is set", ++ err: &AuthorizationError{ ++ Identifier: "domain.com", ++ Errors: []error{ ++ (&wireError{ ++ Status: 403, ++ Type: "urn:ietf:params:acme:error:caa", ++ Detail: "CAA record for domain.com prevents issuance", ++ }).error(nil), ++ }, ++ }, ++ msg: "acme: authorization error for domain.com: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance", ++ }, ++ ++ { ++ desc: "when auth error identifier is unset", ++ err: &AuthorizationError{ ++ Errors: []error{ ++ (&wireError{ ++ Status: 403, ++ Type: "urn:ietf:params:acme:error:caa", ++ Detail: "CAA record for domain.com prevents issuance", ++ }).error(nil), ++ }, ++ }, ++ msg: "acme: authorization error: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance", ++ }, ++ } ++ ++ for _, tt := range tests { ++ if tt.err.Error() != tt.msg { ++ t.Errorf("got: %s\nwant: %s", tt.err, tt.msg) ++ } ++ } ++} ++ ++func TestSubproblems(t *testing.T) { ++ tests := []struct { ++ wire wireError ++ expectedOut Error ++ }{ ++ { ++ wire: wireError{ ++ Status: 1, ++ Type: "urn:error", ++ Detail: "it's an error", ++ }, ++ expectedOut: Error{ ++ StatusCode: 1, ++ ProblemType: "urn:error", ++ Detail: "it's an error", ++ }, ++ }, ++ { ++ wire: wireError{ ++ Status: 1, ++ Type: "urn:error", ++ Detail: "it's an error", ++ Subproblems: []Subproblem{ ++ { ++ Type: "urn:error:sub", ++ Detail: "it's a subproblem", ++ }, ++ }, ++ }, ++ expectedOut: Error{ ++ StatusCode: 1, ++ ProblemType: "urn:error", ++ Detail: "it's an error", ++ Subproblems: []Subproblem{ ++ { ++ Type: "urn:error:sub", ++ Detail: "it's a subproblem", ++ }, ++ }, ++ }, ++ }, ++ { ++ wire: wireError{ ++ Status: 1, ++ Type: "urn:error", ++ Detail: "it's an error", ++ Subproblems: []Subproblem{ ++ { ++ Type: "urn:error:sub", ++ Detail: "it's a subproblem", ++ Identifier: &AuthzID{Type: "dns", Value: "example"}, ++ }, ++ }, ++ }, ++ expectedOut: Error{ ++ StatusCode: 1, ++ ProblemType: "urn:error", ++ Detail: "it's an error", ++ Subproblems: []Subproblem{ ++ { ++ Type: "urn:error:sub", ++ Detail: "it's a subproblem", ++ Identifier: &AuthzID{Type: "dns", Value: "example"}, ++ }, ++ }, ++ }, ++ }, ++ } ++ ++ for _, tc := range tests { ++ out := tc.wire.error(nil) ++ if !reflect.DeepEqual(*out, tc.expectedOut) { ++ t.Errorf("Unexpected error: wanted %v, got %v", tc.expectedOut, *out) ++ } ++ } ++} ++ ++func TestErrorStringerWithSubproblems(t *testing.T) { ++ err := Error{ ++ StatusCode: 1, ++ ProblemType: "urn:error", ++ Detail: "it's an error", ++ Subproblems: []Subproblem{ ++ { ++ Type: "urn:error:sub", ++ Detail: "it's a subproblem", ++ }, ++ { ++ Type: "urn:error:sub", ++ Detail: "it's a subproblem", ++ Identifier: &AuthzID{Type: "dns", Value: "example"}, ++ }, ++ }, ++ } ++ expectedStr := "1 urn:error: it's an error; subproblems:\n\turn:error:sub: it's a subproblem\n\turn:error:sub: [dns: example] it's a subproblem" ++ if err.Error() != expectedStr { ++ t.Errorf("Unexpected error string: wanted %q, got %q", expectedStr, err.Error()) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/acme/version_go112.go b/ms_mod/golang.org/x/crypto/acme/version_go112.go +new file mode 100644 +index 00000000000000..b9efdb59e5851c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/acme/version_go112.go +@@ -0,0 +1,28 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.12 ++// +build go1.12 ++ ++package acme ++ ++import "runtime/debug" ++ ++func init() { ++ // Set packageVersion if the binary was built in modules mode and x/crypto ++ // was not replaced with a different module. ++ info, ok := debug.ReadBuildInfo() ++ if !ok { ++ return ++ } ++ for _, m := range info.Deps { ++ if m.Path != "golang.org/x/crypto" { ++ continue ++ } ++ if m.Replace == nil { ++ packageVersion = m.Version ++ } ++ break ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/argon2/argon2.go b/ms_mod/golang.org/x/crypto/argon2/argon2.go +new file mode 100644 +index 00000000000000..29f0a2de4514b6 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/argon2.go +@@ -0,0 +1,283 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package argon2 implements the key derivation function Argon2. ++// Argon2 was selected as the winner of the Password Hashing Competition and can ++// be used to derive cryptographic keys from passwords. ++// ++// For a detailed specification of Argon2 see [1]. ++// ++// If you aren't sure which function you need, use Argon2id (IDKey) and ++// the parameter recommendations for your scenario. ++// ++// # Argon2i ++// ++// Argon2i (implemented by Key) is the side-channel resistant version of Argon2. ++// It uses data-independent memory access, which is preferred for password ++// hashing and password-based key derivation. Argon2i requires more passes over ++// memory than Argon2id to protect from trade-off attacks. The recommended ++// parameters (taken from [2]) for non-interactive operations are time=3 and to ++// use the maximum available memory. ++// ++// # Argon2id ++// ++// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining ++// Argon2i and Argon2d. It uses data-independent memory access for the first ++// half of the first iteration over the memory and data-dependent memory access ++// for the rest. Argon2id is side-channel resistant and provides better brute- ++// force cost savings due to time-memory tradeoffs than Argon2i. The recommended ++// parameters for non-interactive operations (taken from [2]) are time=1 and to ++// use the maximum available memory. ++// ++// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf ++// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3 ++package argon2 ++ ++import ( ++ "encoding/binary" ++ "sync" ++ ++ "golang.org/x/crypto/blake2b" ++) ++ ++// The Argon2 version implemented by this package. ++const Version = 0x13 ++ ++const ( ++ argon2d = iota ++ argon2i ++ argon2id ++) ++ ++// Key derives a key from the password, salt, and cost parameters using Argon2i ++// returning a byte slice of length keyLen that can be used as cryptographic ++// key. The CPU cost and parallelism degree must be greater than zero. ++// ++// For example, you can get a derived key for e.g. AES-256 (which needs a ++// 32-byte key) by doing: ++// ++// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) ++// ++// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number. ++// If using that amount of memory (32 MB) is not possible in some contexts then ++// the time parameter can be increased to compensate. ++// ++// The time parameter specifies the number of passes over the memory and the ++// memory parameter specifies the size of the memory in KiB. For example ++// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be ++// adjusted to the number of available CPUs. The cost parameters should be ++// increased as memory latency and CPU parallelism increases. Remember to get a ++// good random salt. ++func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { ++ return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) ++} ++ ++// IDKey derives a key from the password, salt, and cost parameters using ++// Argon2id returning a byte slice of length keyLen that can be used as ++// cryptographic key. The CPU cost and parallelism degree must be greater than ++// zero. ++// ++// For example, you can get a derived key for e.g. AES-256 (which needs a ++// 32-byte key) by doing: ++// ++// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) ++// ++// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number. ++// If using that amount of memory (64 MB) is not possible in some contexts then ++// the time parameter can be increased to compensate. ++// ++// The time parameter specifies the number of passes over the memory and the ++// memory parameter specifies the size of the memory in KiB. For example ++// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be ++// adjusted to the numbers of available CPUs. The cost parameters should be ++// increased as memory latency and CPU parallelism increases. Remember to get a ++// good random salt. ++func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { ++ return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) ++} ++ ++func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { ++ if time < 1 { ++ panic("argon2: number of rounds too small") ++ } ++ if threads < 1 { ++ panic("argon2: parallelism degree too low") ++ } ++ h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode) ++ ++ memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads)) ++ if memory < 2*syncPoints*uint32(threads) { ++ memory = 2 * syncPoints * uint32(threads) ++ } ++ B := initBlocks(&h0, memory, uint32(threads)) ++ processBlocks(B, time, memory, uint32(threads), mode) ++ return extractKey(B, memory, uint32(threads), keyLen) ++} ++ ++const ( ++ blockLength = 128 ++ syncPoints = 4 ++) ++ ++type block [blockLength]uint64 ++ ++func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte { ++ var ( ++ h0 [blake2b.Size + 8]byte ++ params [24]byte ++ tmp [4]byte ++ ) ++ ++ b2, _ := blake2b.New512(nil) ++ binary.LittleEndian.PutUint32(params[0:4], threads) ++ binary.LittleEndian.PutUint32(params[4:8], keyLen) ++ binary.LittleEndian.PutUint32(params[8:12], memory) ++ binary.LittleEndian.PutUint32(params[12:16], time) ++ binary.LittleEndian.PutUint32(params[16:20], uint32(Version)) ++ binary.LittleEndian.PutUint32(params[20:24], uint32(mode)) ++ b2.Write(params[:]) ++ binary.LittleEndian.PutUint32(tmp[:], uint32(len(password))) ++ b2.Write(tmp[:]) ++ b2.Write(password) ++ binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt))) ++ b2.Write(tmp[:]) ++ b2.Write(salt) ++ binary.LittleEndian.PutUint32(tmp[:], uint32(len(key))) ++ b2.Write(tmp[:]) ++ b2.Write(key) ++ binary.LittleEndian.PutUint32(tmp[:], uint32(len(data))) ++ b2.Write(tmp[:]) ++ b2.Write(data) ++ b2.Sum(h0[:0]) ++ return h0 ++} ++ ++func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block { ++ var block0 [1024]byte ++ B := make([]block, memory) ++ for lane := uint32(0); lane < threads; lane++ { ++ j := lane * (memory / threads) ++ binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane) ++ ++ binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0) ++ blake2bHash(block0[:], h0[:]) ++ for i := range B[j+0] { ++ B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:]) ++ } ++ ++ binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1) ++ blake2bHash(block0[:], h0[:]) ++ for i := range B[j+1] { ++ B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:]) ++ } ++ } ++ return B ++} ++ ++func processBlocks(B []block, time, memory, threads uint32, mode int) { ++ lanes := memory / threads ++ segments := lanes / syncPoints ++ ++ processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) { ++ var addresses, in, zero block ++ if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { ++ in[0] = uint64(n) ++ in[1] = uint64(lane) ++ in[2] = uint64(slice) ++ in[3] = uint64(memory) ++ in[4] = uint64(time) ++ in[5] = uint64(mode) ++ } ++ ++ index := uint32(0) ++ if n == 0 && slice == 0 { ++ index = 2 // we have already generated the first two blocks ++ if mode == argon2i || mode == argon2id { ++ in[6]++ ++ processBlock(&addresses, &in, &zero) ++ processBlock(&addresses, &addresses, &zero) ++ } ++ } ++ ++ offset := lane*lanes + slice*segments + index ++ var random uint64 ++ for index < segments { ++ prev := offset - 1 ++ if index == 0 && slice == 0 { ++ prev += lanes // last block in lane ++ } ++ if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { ++ if index%blockLength == 0 { ++ in[6]++ ++ processBlock(&addresses, &in, &zero) ++ processBlock(&addresses, &addresses, &zero) ++ } ++ random = addresses[index%blockLength] ++ } else { ++ random = B[prev][0] ++ } ++ newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index) ++ processBlockXOR(&B[offset], &B[prev], &B[newOffset]) ++ index, offset = index+1, offset+1 ++ } ++ wg.Done() ++ } ++ ++ for n := uint32(0); n < time; n++ { ++ for slice := uint32(0); slice < syncPoints; slice++ { ++ var wg sync.WaitGroup ++ for lane := uint32(0); lane < threads; lane++ { ++ wg.Add(1) ++ go processSegment(n, slice, lane, &wg) ++ } ++ wg.Wait() ++ } ++ } ++ ++} ++ ++func extractKey(B []block, memory, threads, keyLen uint32) []byte { ++ lanes := memory / threads ++ for lane := uint32(0); lane < threads-1; lane++ { ++ for i, v := range B[(lane*lanes)+lanes-1] { ++ B[memory-1][i] ^= v ++ } ++ } ++ ++ var block [1024]byte ++ for i, v := range B[memory-1] { ++ binary.LittleEndian.PutUint64(block[i*8:], v) ++ } ++ key := make([]byte, keyLen) ++ blake2bHash(key, block[:]) ++ return key ++} ++ ++func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 { ++ refLane := uint32(rand>>32) % threads ++ if n == 0 && slice == 0 { ++ refLane = lane ++ } ++ m, s := 3*segments, ((slice+1)%syncPoints)*segments ++ if lane == refLane { ++ m += index ++ } ++ if n == 0 { ++ m, s = slice*segments, 0 ++ if slice == 0 || lane == refLane { ++ m += index ++ } ++ } ++ if index == 0 || lane == refLane { ++ m-- ++ } ++ return phi(rand, uint64(m), uint64(s), refLane, lanes) ++} ++ ++func phi(rand, m, s uint64, lane, lanes uint32) uint32 { ++ p := rand & 0xFFFFFFFF ++ p = (p * p) >> 32 ++ p = (p * m) >> 32 ++ return lane*lanes + uint32((s+m-(p+1))%uint64(lanes)) ++} +diff --git a/ms_mod/golang.org/x/crypto/argon2/argon2_test.go b/ms_mod/golang.org/x/crypto/argon2/argon2_test.go +new file mode 100644 +index 00000000000000..775b97a4048d6d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/argon2_test.go +@@ -0,0 +1,233 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package argon2 ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++) ++ ++var ( ++ genKatPassword = []byte{ ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ } ++ genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} ++ genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03} ++ genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04} ++) ++ ++func TestArgon2(t *testing.T) { ++ defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4) ++ ++ if useSSE4 { ++ t.Log("SSE4.1 version") ++ testArgon2i(t) ++ testArgon2d(t) ++ testArgon2id(t) ++ useSSE4 = false ++ } ++ t.Log("generic version") ++ testArgon2i(t) ++ testArgon2d(t) ++ testArgon2id(t) ++} ++ ++func testArgon2d(t *testing.T) { ++ want := []byte{ ++ 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97, ++ 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94, ++ 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1, ++ 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb, ++ } ++ hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) ++ if !bytes.Equal(hash, want) { ++ t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) ++ } ++} ++ ++func testArgon2i(t *testing.T) { ++ want := []byte{ ++ 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa, ++ 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1, ++ 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2, ++ 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8, ++ } ++ hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) ++ if !bytes.Equal(hash, want) { ++ t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) ++ } ++} ++ ++func testArgon2id(t *testing.T) { ++ want := []byte{ ++ 0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c, ++ 0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9, ++ 0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e, ++ 0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59, ++ } ++ hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) ++ if !bytes.Equal(hash, want) { ++ t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) ++ } ++} ++ ++func TestVectors(t *testing.T) { ++ password, salt := []byte("password"), []byte("somesalt") ++ for i, v := range testVectors { ++ want, err := hex.DecodeString(v.hash) ++ if err != nil { ++ t.Fatalf("Test %d: failed to decode hash: %v", i, err) ++ } ++ hash := deriveKey(v.mode, password, salt, nil, nil, v.time, v.memory, v.threads, uint32(len(want))) ++ if !bytes.Equal(hash, want) { ++ t.Errorf("Test %d - got: %s want: %s", i, hex.EncodeToString(hash), hex.EncodeToString(want)) ++ } ++ } ++} ++ ++func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) { ++ password := []byte("password") ++ salt := []byte("choosing random salts is hard") ++ b.ReportAllocs() ++ for i := 0; i < b.N; i++ { ++ deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen) ++ } ++} ++ ++func BenchmarkArgon2i(b *testing.B) { ++ b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) }) ++ b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) }) ++ b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) }) ++} ++ ++func BenchmarkArgon2d(b *testing.B) { ++ b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) }) ++ b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) }) ++ b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) }) ++} ++ ++func BenchmarkArgon2id(b *testing.B) { ++ b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) }) ++ b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) }) ++ b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) }) ++ b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) }) ++} ++ ++// Generated with the CLI of https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf ++var testVectors = []struct { ++ mode int ++ time, memory uint32 ++ threads uint8 ++ hash string ++}{ ++ { ++ mode: argon2i, time: 1, memory: 64, threads: 1, ++ hash: "b9c401d1844a67d50eae3967dc28870b22e508092e861a37", ++ }, ++ { ++ mode: argon2d, time: 1, memory: 64, threads: 1, ++ hash: "8727405fd07c32c78d64f547f24150d3f2e703a89f981a19", ++ }, ++ { ++ mode: argon2id, time: 1, memory: 64, threads: 1, ++ hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb", ++ }, ++ { ++ mode: argon2i, time: 2, memory: 64, threads: 1, ++ hash: "8cf3d8f76a6617afe35fac48eb0b7433a9a670ca4a07ed64", ++ }, ++ { ++ mode: argon2d, time: 2, memory: 64, threads: 1, ++ hash: "3be9ec79a69b75d3752acb59a1fbb8b295a46529c48fbb75", ++ }, ++ { ++ mode: argon2id, time: 2, memory: 64, threads: 1, ++ hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7", ++ }, ++ { ++ mode: argon2i, time: 2, memory: 64, threads: 2, ++ hash: "2089f3e78a799720f80af806553128f29b132cafe40d059f", ++ }, ++ { ++ mode: argon2d, time: 2, memory: 64, threads: 2, ++ hash: "68e2462c98b8bc6bb60ec68db418ae2c9ed24fc6748a40e9", ++ }, ++ { ++ mode: argon2id, time: 2, memory: 64, threads: 2, ++ hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362", ++ }, ++ { ++ mode: argon2i, time: 3, memory: 256, threads: 2, ++ hash: "f5bbf5d4c3836af13193053155b73ec7476a6a2eb93fd5e6", ++ }, ++ { ++ mode: argon2d, time: 3, memory: 256, threads: 2, ++ hash: "f4f0669218eaf3641f39cc97efb915721102f4b128211ef2", ++ }, ++ { ++ mode: argon2id, time: 3, memory: 256, threads: 2, ++ hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b", ++ }, ++ { ++ mode: argon2i, time: 4, memory: 4096, threads: 4, ++ hash: "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7", ++ }, ++ { ++ mode: argon2d, time: 4, memory: 4096, threads: 4, ++ hash: "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d", ++ }, ++ { ++ mode: argon2id, time: 4, memory: 4096, threads: 4, ++ hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a", ++ }, ++ { ++ mode: argon2i, time: 4, memory: 1024, threads: 8, ++ hash: "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17", ++ }, ++ { ++ mode: argon2d, time: 4, memory: 1024, threads: 8, ++ hash: "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9", ++ }, ++ { ++ mode: argon2id, time: 4, memory: 1024, threads: 8, ++ hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f", ++ }, ++ { ++ mode: argon2i, time: 2, memory: 64, threads: 3, ++ hash: "5cab452fe6b8479c8661def8cd703b611a3905a6d5477fe6", ++ }, ++ { ++ mode: argon2d, time: 2, memory: 64, threads: 3, ++ hash: "22474a423bda2ccd36ec9afd5119e5c8949798cadf659f51", ++ }, ++ { ++ mode: argon2id, time: 2, memory: 64, threads: 3, ++ hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079", ++ }, ++ { ++ mode: argon2i, time: 3, memory: 1024, threads: 6, ++ hash: "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced", ++ }, ++ { ++ mode: argon2d, time: 3, memory: 1024, threads: 6, ++ hash: "a3351b0319a53229152023d9206902f4ef59661cdca89481", ++ }, ++ { ++ mode: argon2id, time: 3, memory: 1024, threads: 6, ++ hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016", ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/argon2/blake2b.go b/ms_mod/golang.org/x/crypto/argon2/blake2b.go +new file mode 100644 +index 00000000000000..10f46948dc1053 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/blake2b.go +@@ -0,0 +1,53 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package argon2 ++ ++import ( ++ "encoding/binary" ++ "hash" ++ ++ "golang.org/x/crypto/blake2b" ++) ++ ++// blake2bHash computes an arbitrary long hash value of in ++// and writes the hash to out. ++func blake2bHash(out []byte, in []byte) { ++ var b2 hash.Hash ++ if n := len(out); n < blake2b.Size { ++ b2, _ = blake2b.New(n, nil) ++ } else { ++ b2, _ = blake2b.New512(nil) ++ } ++ ++ var buffer [blake2b.Size]byte ++ binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out))) ++ b2.Write(buffer[:4]) ++ b2.Write(in) ++ ++ if len(out) <= blake2b.Size { ++ b2.Sum(out[:0]) ++ return ++ } ++ ++ outLen := len(out) ++ b2.Sum(buffer[:0]) ++ b2.Reset() ++ copy(out, buffer[:32]) ++ out = out[32:] ++ for len(out) > blake2b.Size { ++ b2.Write(buffer[:]) ++ b2.Sum(buffer[:0]) ++ copy(out, buffer[:32]) ++ out = out[32:] ++ b2.Reset() ++ } ++ ++ if outLen%blake2b.Size > 0 { // outLen > 64 ++ r := ((outLen + 31) / 32) - 2 // βŒˆΟ„ /32βŒ‰-2 ++ b2, _ = blake2b.New(outLen-32*r, nil) ++ } ++ b2.Write(buffer[:]) ++ b2.Sum(out[:0]) ++} +diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go +new file mode 100644 +index 00000000000000..a014ac92aa9f30 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go +@@ -0,0 +1,61 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++package argon2 ++ ++import "golang.org/x/sys/cpu" ++ ++func init() { ++ useSSE4 = cpu.X86.HasSSE41 ++} ++ ++//go:noescape ++func mixBlocksSSE2(out, a, b, c *block) ++ ++//go:noescape ++func xorBlocksSSE2(out, a, b, c *block) ++ ++//go:noescape ++func blamkaSSE4(b *block) ++ ++func processBlockSSE(out, in1, in2 *block, xor bool) { ++ var t block ++ mixBlocksSSE2(&t, in1, in2, &t) ++ if useSSE4 { ++ blamkaSSE4(&t) ++ } else { ++ for i := 0; i < blockLength; i += 16 { ++ blamkaGeneric( ++ &t[i+0], &t[i+1], &t[i+2], &t[i+3], ++ &t[i+4], &t[i+5], &t[i+6], &t[i+7], ++ &t[i+8], &t[i+9], &t[i+10], &t[i+11], ++ &t[i+12], &t[i+13], &t[i+14], &t[i+15], ++ ) ++ } ++ for i := 0; i < blockLength/8; i += 2 { ++ blamkaGeneric( ++ &t[i], &t[i+1], &t[16+i], &t[16+i+1], ++ &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], ++ &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], ++ &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], ++ ) ++ } ++ } ++ if xor { ++ xorBlocksSSE2(out, in1, in2, &t) ++ } else { ++ mixBlocksSSE2(out, in1, in2, &t) ++ } ++} ++ ++func processBlock(out, in1, in2 *block) { ++ processBlockSSE(out, in1, in2, false) ++} ++ ++func processBlockXOR(out, in1, in2 *block) { ++ processBlockSSE(out, in1, in2, true) ++} +diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s +new file mode 100644 +index 00000000000000..b2cc0515049a7a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s +@@ -0,0 +1,244 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++#include "textflag.h" ++ ++DATA Β·c40<>+0x00(SB)/8, $0x0201000706050403 ++DATA Β·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b ++GLOBL Β·c40<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·c48<>+0x00(SB)/8, $0x0100070605040302 ++DATA Β·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a ++GLOBL Β·c48<>(SB), (NOPTR+RODATA), $16 ++ ++#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ ++ MOVO v4, t1; \ ++ MOVO v5, v4; \ ++ MOVO t1, v5; \ ++ MOVO v6, t1; \ ++ PUNPCKLQDQ v6, t2; \ ++ PUNPCKHQDQ v7, v6; \ ++ PUNPCKHQDQ t2, v6; \ ++ PUNPCKLQDQ v7, t2; \ ++ MOVO t1, v7; \ ++ MOVO v2, t1; \ ++ PUNPCKHQDQ t2, v7; \ ++ PUNPCKLQDQ v3, t2; \ ++ PUNPCKHQDQ t2, v2; \ ++ PUNPCKLQDQ t1, t2; \ ++ PUNPCKHQDQ t2, v3 ++ ++#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ ++ MOVO v4, t1; \ ++ MOVO v5, v4; \ ++ MOVO t1, v5; \ ++ MOVO v2, t1; \ ++ PUNPCKLQDQ v2, t2; \ ++ PUNPCKHQDQ v3, v2; \ ++ PUNPCKHQDQ t2, v2; \ ++ PUNPCKLQDQ v3, t2; \ ++ MOVO t1, v3; \ ++ MOVO v6, t1; \ ++ PUNPCKHQDQ t2, v3; \ ++ PUNPCKLQDQ v7, t2; \ ++ PUNPCKHQDQ t2, v6; \ ++ PUNPCKLQDQ t1, t2; \ ++ PUNPCKHQDQ t2, v7 ++ ++#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \ ++ MOVO v0, t0; \ ++ PMULULQ v2, t0; \ ++ PADDQ v2, v0; \ ++ PADDQ t0, v0; \ ++ PADDQ t0, v0; \ ++ PXOR v0, v6; \ ++ PSHUFD $0xB1, v6, v6; \ ++ MOVO v4, t0; \ ++ PMULULQ v6, t0; \ ++ PADDQ v6, v4; \ ++ PADDQ t0, v4; \ ++ PADDQ t0, v4; \ ++ PXOR v4, v2; \ ++ PSHUFB c40, v2; \ ++ MOVO v0, t0; \ ++ PMULULQ v2, t0; \ ++ PADDQ v2, v0; \ ++ PADDQ t0, v0; \ ++ PADDQ t0, v0; \ ++ PXOR v0, v6; \ ++ PSHUFB c48, v6; \ ++ MOVO v4, t0; \ ++ PMULULQ v6, t0; \ ++ PADDQ v6, v4; \ ++ PADDQ t0, v4; \ ++ PADDQ t0, v4; \ ++ PXOR v4, v2; \ ++ MOVO v2, t0; \ ++ PADDQ v2, t0; \ ++ PSRLQ $63, v2; \ ++ PXOR t0, v2; \ ++ MOVO v1, t0; \ ++ PMULULQ v3, t0; \ ++ PADDQ v3, v1; \ ++ PADDQ t0, v1; \ ++ PADDQ t0, v1; \ ++ PXOR v1, v7; \ ++ PSHUFD $0xB1, v7, v7; \ ++ MOVO v5, t0; \ ++ PMULULQ v7, t0; \ ++ PADDQ v7, v5; \ ++ PADDQ t0, v5; \ ++ PADDQ t0, v5; \ ++ PXOR v5, v3; \ ++ PSHUFB c40, v3; \ ++ MOVO v1, t0; \ ++ PMULULQ v3, t0; \ ++ PADDQ v3, v1; \ ++ PADDQ t0, v1; \ ++ PADDQ t0, v1; \ ++ PXOR v1, v7; \ ++ PSHUFB c48, v7; \ ++ MOVO v5, t0; \ ++ PMULULQ v7, t0; \ ++ PADDQ v7, v5; \ ++ PADDQ t0, v5; \ ++ PADDQ t0, v5; \ ++ PXOR v5, v3; \ ++ MOVO v3, t0; \ ++ PADDQ v3, t0; \ ++ PSRLQ $63, v3; \ ++ PXOR t0, v3 ++ ++#define LOAD_MSG_0(block, off) \ ++ MOVOU 8*(off+0)(block), X0; \ ++ MOVOU 8*(off+2)(block), X1; \ ++ MOVOU 8*(off+4)(block), X2; \ ++ MOVOU 8*(off+6)(block), X3; \ ++ MOVOU 8*(off+8)(block), X4; \ ++ MOVOU 8*(off+10)(block), X5; \ ++ MOVOU 8*(off+12)(block), X6; \ ++ MOVOU 8*(off+14)(block), X7 ++ ++#define STORE_MSG_0(block, off) \ ++ MOVOU X0, 8*(off+0)(block); \ ++ MOVOU X1, 8*(off+2)(block); \ ++ MOVOU X2, 8*(off+4)(block); \ ++ MOVOU X3, 8*(off+6)(block); \ ++ MOVOU X4, 8*(off+8)(block); \ ++ MOVOU X5, 8*(off+10)(block); \ ++ MOVOU X6, 8*(off+12)(block); \ ++ MOVOU X7, 8*(off+14)(block) ++ ++#define LOAD_MSG_1(block, off) \ ++ MOVOU 8*off+0*8(block), X0; \ ++ MOVOU 8*off+16*8(block), X1; \ ++ MOVOU 8*off+32*8(block), X2; \ ++ MOVOU 8*off+48*8(block), X3; \ ++ MOVOU 8*off+64*8(block), X4; \ ++ MOVOU 8*off+80*8(block), X5; \ ++ MOVOU 8*off+96*8(block), X6; \ ++ MOVOU 8*off+112*8(block), X7 ++ ++#define STORE_MSG_1(block, off) \ ++ MOVOU X0, 8*off+0*8(block); \ ++ MOVOU X1, 8*off+16*8(block); \ ++ MOVOU X2, 8*off+32*8(block); \ ++ MOVOU X3, 8*off+48*8(block); \ ++ MOVOU X4, 8*off+64*8(block); \ ++ MOVOU X5, 8*off+80*8(block); \ ++ MOVOU X6, 8*off+96*8(block); \ ++ MOVOU X7, 8*off+112*8(block) ++ ++#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \ ++ LOAD_MSG_0(block, off); \ ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ ++ SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ ++ STORE_MSG_0(block, off) ++ ++#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \ ++ LOAD_MSG_1(block, off); \ ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ ++ SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ ++ STORE_MSG_1(block, off) ++ ++// func blamkaSSE4(b *block) ++TEXT Β·blamkaSSE4(SB), 4, $0-8 ++ MOVQ b+0(FP), AX ++ ++ MOVOU Β·c40<>(SB), X10 ++ MOVOU Β·c48<>(SB), X11 ++ ++ BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11) ++ BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11) ++ ++ BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11) ++ BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11) ++ RET ++ ++// func mixBlocksSSE2(out, a, b, c *block) ++TEXT Β·mixBlocksSSE2(SB), 4, $0-32 ++ MOVQ out+0(FP), DX ++ MOVQ a+8(FP), AX ++ MOVQ b+16(FP), BX ++ MOVQ a+24(FP), CX ++ MOVQ $128, BP ++ ++loop: ++ MOVOU 0(AX), X0 ++ MOVOU 0(BX), X1 ++ MOVOU 0(CX), X2 ++ PXOR X1, X0 ++ PXOR X2, X0 ++ MOVOU X0, 0(DX) ++ ADDQ $16, AX ++ ADDQ $16, BX ++ ADDQ $16, CX ++ ADDQ $16, DX ++ SUBQ $2, BP ++ JA loop ++ RET ++ ++// func xorBlocksSSE2(out, a, b, c *block) ++TEXT Β·xorBlocksSSE2(SB), 4, $0-32 ++ MOVQ out+0(FP), DX ++ MOVQ a+8(FP), AX ++ MOVQ b+16(FP), BX ++ MOVQ a+24(FP), CX ++ MOVQ $128, BP ++ ++loop: ++ MOVOU 0(AX), X0 ++ MOVOU 0(BX), X1 ++ MOVOU 0(CX), X2 ++ MOVOU 0(DX), X3 ++ PXOR X1, X0 ++ PXOR X2, X0 ++ PXOR X3, X0 ++ MOVOU X0, 0(DX) ++ ADDQ $16, AX ++ ADDQ $16, BX ++ ADDQ $16, CX ++ ADDQ $16, DX ++ SUBQ $2, BP ++ JA loop ++ RET +diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_generic.go b/ms_mod/golang.org/x/crypto/argon2/blamka_generic.go +new file mode 100644 +index 00000000000000..a481b2243f855f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/blamka_generic.go +@@ -0,0 +1,163 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package argon2 ++ ++var useSSE4 bool ++ ++func processBlockGeneric(out, in1, in2 *block, xor bool) { ++ var t block ++ for i := range t { ++ t[i] = in1[i] ^ in2[i] ++ } ++ for i := 0; i < blockLength; i += 16 { ++ blamkaGeneric( ++ &t[i+0], &t[i+1], &t[i+2], &t[i+3], ++ &t[i+4], &t[i+5], &t[i+6], &t[i+7], ++ &t[i+8], &t[i+9], &t[i+10], &t[i+11], ++ &t[i+12], &t[i+13], &t[i+14], &t[i+15], ++ ) ++ } ++ for i := 0; i < blockLength/8; i += 2 { ++ blamkaGeneric( ++ &t[i], &t[i+1], &t[16+i], &t[16+i+1], ++ &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], ++ &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], ++ &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], ++ ) ++ } ++ if xor { ++ for i := range t { ++ out[i] ^= in1[i] ^ in2[i] ^ t[i] ++ } ++ } else { ++ for i := range t { ++ out[i] = in1[i] ^ in2[i] ^ t[i] ++ } ++ } ++} ++ ++func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) { ++ v00, v01, v02, v03 := *t00, *t01, *t02, *t03 ++ v04, v05, v06, v07 := *t04, *t05, *t06, *t07 ++ v08, v09, v10, v11 := *t08, *t09, *t10, *t11 ++ v12, v13, v14, v15 := *t12, *t13, *t14, *t15 ++ ++ v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) ++ v12 ^= v00 ++ v12 = v12>>32 | v12<<32 ++ v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) ++ v04 ^= v08 ++ v04 = v04>>24 | v04<<40 ++ ++ v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) ++ v12 ^= v00 ++ v12 = v12>>16 | v12<<48 ++ v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) ++ v04 ^= v08 ++ v04 = v04>>63 | v04<<1 ++ ++ v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) ++ v13 ^= v01 ++ v13 = v13>>32 | v13<<32 ++ v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) ++ v05 ^= v09 ++ v05 = v05>>24 | v05<<40 ++ ++ v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) ++ v13 ^= v01 ++ v13 = v13>>16 | v13<<48 ++ v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) ++ v05 ^= v09 ++ v05 = v05>>63 | v05<<1 ++ ++ v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) ++ v14 ^= v02 ++ v14 = v14>>32 | v14<<32 ++ v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) ++ v06 ^= v10 ++ v06 = v06>>24 | v06<<40 ++ ++ v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) ++ v14 ^= v02 ++ v14 = v14>>16 | v14<<48 ++ v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) ++ v06 ^= v10 ++ v06 = v06>>63 | v06<<1 ++ ++ v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) ++ v15 ^= v03 ++ v15 = v15>>32 | v15<<32 ++ v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) ++ v07 ^= v11 ++ v07 = v07>>24 | v07<<40 ++ ++ v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) ++ v15 ^= v03 ++ v15 = v15>>16 | v15<<48 ++ v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) ++ v07 ^= v11 ++ v07 = v07>>63 | v07<<1 ++ ++ v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) ++ v15 ^= v00 ++ v15 = v15>>32 | v15<<32 ++ v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) ++ v05 ^= v10 ++ v05 = v05>>24 | v05<<40 ++ ++ v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) ++ v15 ^= v00 ++ v15 = v15>>16 | v15<<48 ++ v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) ++ v05 ^= v10 ++ v05 = v05>>63 | v05<<1 ++ ++ v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) ++ v12 ^= v01 ++ v12 = v12>>32 | v12<<32 ++ v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) ++ v06 ^= v11 ++ v06 = v06>>24 | v06<<40 ++ ++ v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) ++ v12 ^= v01 ++ v12 = v12>>16 | v12<<48 ++ v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) ++ v06 ^= v11 ++ v06 = v06>>63 | v06<<1 ++ ++ v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) ++ v13 ^= v02 ++ v13 = v13>>32 | v13<<32 ++ v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) ++ v07 ^= v08 ++ v07 = v07>>24 | v07<<40 ++ ++ v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) ++ v13 ^= v02 ++ v13 = v13>>16 | v13<<48 ++ v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) ++ v07 ^= v08 ++ v07 = v07>>63 | v07<<1 ++ ++ v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) ++ v14 ^= v03 ++ v14 = v14>>32 | v14<<32 ++ v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) ++ v04 ^= v09 ++ v04 = v04>>24 | v04<<40 ++ ++ v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) ++ v14 ^= v03 ++ v14 = v14>>16 | v14<<48 ++ v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) ++ v04 ^= v09 ++ v04 = v04>>63 | v04<<1 ++ ++ *t00, *t01, *t02, *t03 = v00, v01, v02, v03 ++ *t04, *t05, *t06, *t07 = v04, v05, v06, v07 ++ *t08, *t09, *t10, *t11 = v08, v09, v10, v11 ++ *t12, *t13, *t14, *t15 = v12, v13, v14, v15 ++} +diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_ref.go b/ms_mod/golang.org/x/crypto/argon2/blamka_ref.go +new file mode 100644 +index 00000000000000..167c59d2d5ab74 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/argon2/blamka_ref.go +@@ -0,0 +1,16 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !amd64 || purego || !gc ++// +build !amd64 purego !gc ++ ++package argon2 ++ ++func processBlock(out, in1, in2 *block) { ++ processBlockGeneric(out, in1, in2, false) ++} ++ ++func processBlockXOR(out, in1, in2 *block) { ++ processBlockGeneric(out, in1, in2, true) ++} +diff --git a/ms_mod/golang.org/x/crypto/bcrypt/base64.go b/ms_mod/golang.org/x/crypto/bcrypt/base64.go +new file mode 100644 +index 00000000000000..fc311609081849 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bcrypt/base64.go +@@ -0,0 +1,35 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bcrypt ++ ++import "encoding/base64" ++ ++const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ++ ++var bcEncoding = base64.NewEncoding(alphabet) ++ ++func base64Encode(src []byte) []byte { ++ n := bcEncoding.EncodedLen(len(src)) ++ dst := make([]byte, n) ++ bcEncoding.Encode(dst, src) ++ for dst[n-1] == '=' { ++ n-- ++ } ++ return dst[:n] ++} ++ ++func base64Decode(src []byte) ([]byte, error) { ++ numOfEquals := 4 - (len(src) % 4) ++ for i := 0; i < numOfEquals; i++ { ++ src = append(src, '=') ++ } ++ ++ dst := make([]byte, bcEncoding.DecodedLen(len(src))) ++ n, err := bcEncoding.Decode(dst, src) ++ if err != nil { ++ return nil, err ++ } ++ return dst[:n], nil ++} +diff --git a/ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go +new file mode 100644 +index 00000000000000..5577c0f939a23e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go +@@ -0,0 +1,304 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package bcrypt implements Provos and MaziΓ¨res's bcrypt adaptive hashing ++// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf ++package bcrypt // import "golang.org/x/crypto/bcrypt" ++ ++// The code is a port of Provos and MaziΓ¨res's C implementation. ++import ( ++ "crypto/rand" ++ "crypto/subtle" ++ "errors" ++ "fmt" ++ "io" ++ "strconv" ++ ++ "golang.org/x/crypto/blowfish" ++) ++ ++const ( ++ MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword ++ MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword ++ DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword ++) ++ ++// The error returned from CompareHashAndPassword when a password and hash do ++// not match. ++var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") ++ ++// The error returned from CompareHashAndPassword when a hash is too short to ++// be a bcrypt hash. ++var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") ++ ++// The error returned from CompareHashAndPassword when a hash was created with ++// a bcrypt algorithm newer than this implementation. ++type HashVersionTooNewError byte ++ ++func (hv HashVersionTooNewError) Error() string { ++ return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) ++} ++ ++// The error returned from CompareHashAndPassword when a hash starts with something other than '$' ++type InvalidHashPrefixError byte ++ ++func (ih InvalidHashPrefixError) Error() string { ++ return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) ++} ++ ++type InvalidCostError int ++ ++func (ic InvalidCostError) Error() string { ++ return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), MinCost, MaxCost) ++} ++ ++const ( ++ majorVersion = '2' ++ minorVersion = 'a' ++ maxSaltSize = 16 ++ maxCryptedHashSize = 23 ++ encodedSaltSize = 22 ++ encodedHashSize = 31 ++ minHashSize = 59 ++) ++ ++// magicCipherData is an IV for the 64 Blowfish encryption calls in ++// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. ++var magicCipherData = []byte{ ++ 0x4f, 0x72, 0x70, 0x68, ++ 0x65, 0x61, 0x6e, 0x42, ++ 0x65, 0x68, 0x6f, 0x6c, ++ 0x64, 0x65, 0x72, 0x53, ++ 0x63, 0x72, 0x79, 0x44, ++ 0x6f, 0x75, 0x62, 0x74, ++} ++ ++type hashed struct { ++ hash []byte ++ salt []byte ++ cost int // allowed range is MinCost to MaxCost ++ major byte ++ minor byte ++} ++ ++// ErrPasswordTooLong is returned when the password passed to ++// GenerateFromPassword is too long (i.e. > 72 bytes). ++var ErrPasswordTooLong = errors.New("bcrypt: password length exceeds 72 bytes") ++ ++// GenerateFromPassword returns the bcrypt hash of the password at the given ++// cost. If the cost given is less than MinCost, the cost will be set to ++// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, ++// to compare the returned hashed password with its cleartext version. ++// GenerateFromPassword does not accept passwords longer than 72 bytes, which ++// is the longest password bcrypt will operate on. ++func GenerateFromPassword(password []byte, cost int) ([]byte, error) { ++ if len(password) > 72 { ++ return nil, ErrPasswordTooLong ++ } ++ p, err := newFromPassword(password, cost) ++ if err != nil { ++ return nil, err ++ } ++ return p.Hash(), nil ++} ++ ++// CompareHashAndPassword compares a bcrypt hashed password with its possible ++// plaintext equivalent. Returns nil on success, or an error on failure. ++func CompareHashAndPassword(hashedPassword, password []byte) error { ++ p, err := newFromHash(hashedPassword) ++ if err != nil { ++ return err ++ } ++ ++ otherHash, err := bcrypt(password, p.cost, p.salt) ++ if err != nil { ++ return err ++ } ++ ++ otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} ++ if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { ++ return nil ++ } ++ ++ return ErrMismatchedHashAndPassword ++} ++ ++// Cost returns the hashing cost used to create the given hashed ++// password. When, in the future, the hashing cost of a password system needs ++// to be increased in order to adjust for greater computational power, this ++// function allows one to establish which passwords need to be updated. ++func Cost(hashedPassword []byte) (int, error) { ++ p, err := newFromHash(hashedPassword) ++ if err != nil { ++ return 0, err ++ } ++ return p.cost, nil ++} ++ ++func newFromPassword(password []byte, cost int) (*hashed, error) { ++ if cost < MinCost { ++ cost = DefaultCost ++ } ++ p := new(hashed) ++ p.major = majorVersion ++ p.minor = minorVersion ++ ++ err := checkCost(cost) ++ if err != nil { ++ return nil, err ++ } ++ p.cost = cost ++ ++ unencodedSalt := make([]byte, maxSaltSize) ++ _, err = io.ReadFull(rand.Reader, unencodedSalt) ++ if err != nil { ++ return nil, err ++ } ++ ++ p.salt = base64Encode(unencodedSalt) ++ hash, err := bcrypt(password, p.cost, p.salt) ++ if err != nil { ++ return nil, err ++ } ++ p.hash = hash ++ return p, err ++} ++ ++func newFromHash(hashedSecret []byte) (*hashed, error) { ++ if len(hashedSecret) < minHashSize { ++ return nil, ErrHashTooShort ++ } ++ p := new(hashed) ++ n, err := p.decodeVersion(hashedSecret) ++ if err != nil { ++ return nil, err ++ } ++ hashedSecret = hashedSecret[n:] ++ n, err = p.decodeCost(hashedSecret) ++ if err != nil { ++ return nil, err ++ } ++ hashedSecret = hashedSecret[n:] ++ ++ // The "+2" is here because we'll have to append at most 2 '=' to the salt ++ // when base64 decoding it in expensiveBlowfishSetup(). ++ p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) ++ copy(p.salt, hashedSecret[:encodedSaltSize]) ++ ++ hashedSecret = hashedSecret[encodedSaltSize:] ++ p.hash = make([]byte, len(hashedSecret)) ++ copy(p.hash, hashedSecret) ++ ++ return p, nil ++} ++ ++func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { ++ cipherData := make([]byte, len(magicCipherData)) ++ copy(cipherData, magicCipherData) ++ ++ c, err := expensiveBlowfishSetup(password, uint32(cost), salt) ++ if err != nil { ++ return nil, err ++ } ++ ++ for i := 0; i < 24; i += 8 { ++ for j := 0; j < 64; j++ { ++ c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) ++ } ++ } ++ ++ // Bug compatibility with C bcrypt implementations. We only encode 23 of ++ // the 24 bytes encrypted. ++ hsh := base64Encode(cipherData[:maxCryptedHashSize]) ++ return hsh, nil ++} ++ ++func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { ++ csalt, err := base64Decode(salt) ++ if err != nil { ++ return nil, err ++ } ++ ++ // Bug compatibility with C bcrypt implementations. They use the trailing ++ // NULL in the key string during expansion. ++ // We copy the key to prevent changing the underlying array. ++ ckey := append(key[:len(key):len(key)], 0) ++ ++ c, err := blowfish.NewSaltedCipher(ckey, csalt) ++ if err != nil { ++ return nil, err ++ } ++ ++ var i, rounds uint64 ++ rounds = 1 << cost ++ for i = 0; i < rounds; i++ { ++ blowfish.ExpandKey(ckey, c) ++ blowfish.ExpandKey(csalt, c) ++ } ++ ++ return c, nil ++} ++ ++func (p *hashed) Hash() []byte { ++ arr := make([]byte, 60) ++ arr[0] = '$' ++ arr[1] = p.major ++ n := 2 ++ if p.minor != 0 { ++ arr[2] = p.minor ++ n = 3 ++ } ++ arr[n] = '$' ++ n++ ++ copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) ++ n += 2 ++ arr[n] = '$' ++ n++ ++ copy(arr[n:], p.salt) ++ n += encodedSaltSize ++ copy(arr[n:], p.hash) ++ n += encodedHashSize ++ return arr[:n] ++} ++ ++func (p *hashed) decodeVersion(sbytes []byte) (int, error) { ++ if sbytes[0] != '$' { ++ return -1, InvalidHashPrefixError(sbytes[0]) ++ } ++ if sbytes[1] > majorVersion { ++ return -1, HashVersionTooNewError(sbytes[1]) ++ } ++ p.major = sbytes[1] ++ n := 3 ++ if sbytes[2] != '$' { ++ p.minor = sbytes[2] ++ n++ ++ } ++ return n, nil ++} ++ ++// sbytes should begin where decodeVersion left off. ++func (p *hashed) decodeCost(sbytes []byte) (int, error) { ++ cost, err := strconv.Atoi(string(sbytes[0:2])) ++ if err != nil { ++ return -1, err ++ } ++ err = checkCost(cost) ++ if err != nil { ++ return -1, err ++ } ++ p.cost = cost ++ return 3, nil ++} ++ ++func (p *hashed) String() string { ++ return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) ++} ++ ++func checkCost(cost int) error { ++ if cost < MinCost || cost > MaxCost { ++ return InvalidCostError(cost) ++ } ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go +new file mode 100644 +index 00000000000000..8b589e36527a25 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go +@@ -0,0 +1,250 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bcrypt ++ ++import ( ++ "bytes" ++ "fmt" ++ "testing" ++) ++ ++func TestBcryptingIsEasy(t *testing.T) { ++ pass := []byte("mypassword") ++ hp, err := GenerateFromPassword(pass, 0) ++ if err != nil { ++ t.Fatalf("GenerateFromPassword error: %s", err) ++ } ++ ++ if CompareHashAndPassword(hp, pass) != nil { ++ t.Errorf("%v should hash %s correctly", hp, pass) ++ } ++ ++ notPass := "notthepass" ++ err = CompareHashAndPassword(hp, []byte(notPass)) ++ if err != ErrMismatchedHashAndPassword { ++ t.Errorf("%v and %s should be mismatched", hp, notPass) ++ } ++} ++ ++func TestBcryptingIsCorrect(t *testing.T) { ++ pass := []byte("allmine") ++ salt := []byte("XajjQvNhvvRt5GSeFk1xFe") ++ expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") ++ ++ hash, err := bcrypt(pass, 10, salt) ++ if err != nil { ++ t.Fatalf("bcrypt blew up: %v", err) ++ } ++ if !bytes.HasSuffix(expectedHash, hash) { ++ t.Errorf("%v should be the suffix of %v", hash, expectedHash) ++ } ++ ++ h, err := newFromHash(expectedHash) ++ if err != nil { ++ t.Errorf("Unable to parse %s: %v", string(expectedHash), err) ++ } ++ ++ // This is not the safe way to compare these hashes. We do this only for ++ // testing clarity. Use bcrypt.CompareHashAndPassword() ++ if err == nil && !bytes.Equal(expectedHash, h.Hash()) { ++ t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash) ++ } ++} ++ ++func TestVeryShortPasswords(t *testing.T) { ++ key := []byte("k") ++ salt := []byte("XajjQvNhvvRt5GSeFk1xFe") ++ _, err := bcrypt(key, 10, salt) ++ if err != nil { ++ t.Errorf("One byte key resulted in error: %s", err) ++ } ++} ++ ++func TestTooLongPasswordsWork(t *testing.T) { ++ salt := []byte("XajjQvNhvvRt5GSeFk1xFe") ++ // One byte over the usual 56 byte limit that blowfish has ++ tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") ++ tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C") ++ hash, err := bcrypt(tooLongPass, 10, salt) ++ if err != nil { ++ t.Fatalf("bcrypt blew up on long password: %v", err) ++ } ++ if !bytes.HasSuffix(tooLongExpected, hash) { ++ t.Errorf("%v should be the suffix of %v", hash, tooLongExpected) ++ } ++} ++ ++type InvalidHashTest struct { ++ err error ++ hash []byte ++} ++ ++var invalidTests = []InvalidHashTest{ ++ {ErrHashTooShort, []byte("$2a$10$fooo")}, ++ {ErrHashTooShort, []byte("$2a")}, ++ {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, ++ {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, ++ {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, ++} ++ ++func TestInvalidHashErrors(t *testing.T) { ++ check := func(name string, expected, err error) { ++ if err == nil { ++ t.Errorf("%s: Should have returned an error", name) ++ } ++ if err != nil && err != expected { ++ t.Errorf("%s gave err %v but should have given %v", name, err, expected) ++ } ++ } ++ for _, iht := range invalidTests { ++ _, err := newFromHash(iht.hash) ++ check("newFromHash", iht.err, err) ++ err = CompareHashAndPassword(iht.hash, []byte("anything")) ++ check("CompareHashAndPassword", iht.err, err) ++ } ++} ++ ++func TestUnpaddedBase64Encoding(t *testing.T) { ++ original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} ++ encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") ++ ++ encoded := base64Encode(original) ++ ++ if !bytes.Equal(encodedOriginal, encoded) { ++ t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal) ++ } ++ ++ decoded, err := base64Decode(encodedOriginal) ++ if err != nil { ++ t.Fatalf("base64Decode blew up: %s", err) ++ } ++ ++ if !bytes.Equal(decoded, original) { ++ t.Errorf("Decoded %v should have equaled %v", decoded, original) ++ } ++} ++ ++func TestCost(t *testing.T) { ++ suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C" ++ for _, vers := range []string{"2a", "2"} { ++ for _, cost := range []int{4, 10} { ++ s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix) ++ h := []byte(s) ++ actual, err := Cost(h) ++ if err != nil { ++ t.Errorf("Cost, error: %s", err) ++ continue ++ } ++ if actual != cost { ++ t.Errorf("Cost, expected: %d, actual: %d", cost, actual) ++ } ++ } ++ } ++ _, err := Cost([]byte("$a$a$" + suffix)) ++ if err == nil { ++ t.Errorf("Cost, malformed but no error returned") ++ } ++} ++ ++func TestCostValidationInHash(t *testing.T) { ++ if testing.Short() { ++ return ++ } ++ ++ pass := []byte("mypassword") ++ ++ for c := 0; c < MinCost; c++ { ++ p, _ := newFromPassword(pass, c) ++ if p.cost != DefaultCost { ++ t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) ++ } ++ } ++ ++ p, _ := newFromPassword(pass, 14) ++ if p.cost != 14 { ++ t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost) ++ } ++ ++ hp, _ := newFromHash(p.Hash()) ++ if p.cost != hp.cost { ++ t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost) ++ } ++ ++ _, err := newFromPassword(pass, 32) ++ if err == nil { ++ t.Fatalf("newFromPassword: should return a cost error") ++ } ++ if err != InvalidCostError(32) { ++ t.Errorf("newFromPassword: should return cost error, got %#v", err) ++ } ++} ++ ++func TestCostReturnsWithLeadingZeroes(t *testing.T) { ++ hp, _ := newFromPassword([]byte("abcdefgh"), 7) ++ cost := hp.Hash()[4:7] ++ expected := []byte("07$") ++ ++ if !bytes.Equal(expected, cost) { ++ t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) ++ } ++} ++ ++func TestMinorNotRequired(t *testing.T) { ++ noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") ++ h, err := newFromHash(noMinorHash) ++ if err != nil { ++ t.Fatalf("No minor hash blew up: %s", err) ++ } ++ if h.minor != 0 { ++ t.Errorf("Should leave minor version at 0, but was %d", h.minor) ++ } ++ ++ if !bytes.Equal(noMinorHash, h.Hash()) { ++ t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) ++ } ++} ++ ++func BenchmarkEqual(b *testing.B) { ++ b.StopTimer() ++ passwd := []byte("somepasswordyoulike") ++ hash, _ := GenerateFromPassword(passwd, DefaultCost) ++ b.StartTimer() ++ for i := 0; i < b.N; i++ { ++ CompareHashAndPassword(hash, passwd) ++ } ++} ++ ++func BenchmarkDefaultCost(b *testing.B) { ++ b.StopTimer() ++ passwd := []byte("mylongpassword1234") ++ b.StartTimer() ++ for i := 0; i < b.N; i++ { ++ GenerateFromPassword(passwd, DefaultCost) ++ } ++} ++ ++// See Issue https://github.com/golang/go/issues/20425. ++func TestNoSideEffectsFromCompare(t *testing.T) { ++ source := []byte("passw0rd123456") ++ password := source[:len(source)-6] ++ token := source[len(source)-6:] ++ want := make([]byte, len(source)) ++ copy(want, source) ++ ++ wantHash := []byte("$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa") ++ _ = CompareHashAndPassword(wantHash, password) ++ ++ got := bytes.Join([][]byte{password, token}, []byte("")) ++ if !bytes.Equal(got, want) { ++ t.Errorf("got=%q want=%q", got, want) ++ } ++} ++ ++func TestPasswordTooLong(t *testing.T) { ++ _, err := GenerateFromPassword(make([]byte, 73), 1) ++ if err != ErrPasswordTooLong { ++ t.Errorf("unexpected error: got %q, want %q", err, ErrPasswordTooLong) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b.go +new file mode 100644 +index 00000000000000..d2e98d4295bdb8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b.go +@@ -0,0 +1,291 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 ++// and the extendable output function (XOF) BLAKE2Xb. ++// ++// BLAKE2b is optimized for 64-bit platformsβ€”including NEON-enabled ARMsβ€”and ++// produces digests of any size between 1 and 64 bytes. ++// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf ++// and for BLAKE2Xb see https://blake2.net/blake2x.pdf ++// ++// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). ++// If you need a secret-key MAC (message authentication code), use the New512 ++// function with a non-nil key. ++// ++// BLAKE2X is a construction to compute hash values larger than 64 bytes. It ++// can produce hash values between 0 and 4 GiB. ++package blake2b ++ ++import ( ++ "encoding/binary" ++ "errors" ++ "hash" ++) ++ ++const ( ++ // The blocksize of BLAKE2b in bytes. ++ BlockSize = 128 ++ // The hash size of BLAKE2b-512 in bytes. ++ Size = 64 ++ // The hash size of BLAKE2b-384 in bytes. ++ Size384 = 48 ++ // The hash size of BLAKE2b-256 in bytes. ++ Size256 = 32 ++) ++ ++var ( ++ useAVX2 bool ++ useAVX bool ++ useSSE4 bool ++) ++ ++var ( ++ errKeySize = errors.New("blake2b: invalid key size") ++ errHashSize = errors.New("blake2b: invalid hash size") ++) ++ ++var iv = [8]uint64{ ++ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, ++ 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, ++} ++ ++// Sum512 returns the BLAKE2b-512 checksum of the data. ++func Sum512(data []byte) [Size]byte { ++ var sum [Size]byte ++ checkSum(&sum, Size, data) ++ return sum ++} ++ ++// Sum384 returns the BLAKE2b-384 checksum of the data. ++func Sum384(data []byte) [Size384]byte { ++ var sum [Size]byte ++ var sum384 [Size384]byte ++ checkSum(&sum, Size384, data) ++ copy(sum384[:], sum[:Size384]) ++ return sum384 ++} ++ ++// Sum256 returns the BLAKE2b-256 checksum of the data. ++func Sum256(data []byte) [Size256]byte { ++ var sum [Size]byte ++ var sum256 [Size256]byte ++ checkSum(&sum, Size256, data) ++ copy(sum256[:], sum[:Size256]) ++ return sum256 ++} ++ ++// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil ++// key turns the hash into a MAC. The key must be between zero and 64 bytes long. ++func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } ++ ++// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil ++// key turns the hash into a MAC. The key must be between zero and 64 bytes long. ++func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } ++ ++// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil ++// key turns the hash into a MAC. The key must be between zero and 64 bytes long. ++func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } ++ ++// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. ++// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. ++// The hash size can be a value between 1 and 64 but it is highly recommended to use ++// values equal or greater than: ++// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). ++// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). ++// When the key is nil, the returned hash.Hash implements BinaryMarshaler ++// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. ++func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } ++ ++func newDigest(hashSize int, key []byte) (*digest, error) { ++ if hashSize < 1 || hashSize > Size { ++ return nil, errHashSize ++ } ++ if len(key) > Size { ++ return nil, errKeySize ++ } ++ d := &digest{ ++ size: hashSize, ++ keyLen: len(key), ++ } ++ copy(d.key[:], key) ++ d.Reset() ++ return d, nil ++} ++ ++func checkSum(sum *[Size]byte, hashSize int, data []byte) { ++ h := iv ++ h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) ++ var c [2]uint64 ++ ++ if length := len(data); length > BlockSize { ++ n := length &^ (BlockSize - 1) ++ if length == n { ++ n -= BlockSize ++ } ++ hashBlocks(&h, &c, 0, data[:n]) ++ data = data[n:] ++ } ++ ++ var block [BlockSize]byte ++ offset := copy(block[:], data) ++ remaining := uint64(BlockSize - offset) ++ if c[0] < remaining { ++ c[1]-- ++ } ++ c[0] -= remaining ++ ++ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) ++ ++ for i, v := range h[:(hashSize+7)/8] { ++ binary.LittleEndian.PutUint64(sum[8*i:], v) ++ } ++} ++ ++type digest struct { ++ h [8]uint64 ++ c [2]uint64 ++ size int ++ block [BlockSize]byte ++ offset int ++ ++ key [BlockSize]byte ++ keyLen int ++} ++ ++const ( ++ magic = "b2b" ++ marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 ++) ++ ++func (d *digest) MarshalBinary() ([]byte, error) { ++ if d.keyLen != 0 { ++ return nil, errors.New("crypto/blake2b: cannot marshal MACs") ++ } ++ b := make([]byte, 0, marshaledSize) ++ b = append(b, magic...) ++ for i := 0; i < 8; i++ { ++ b = appendUint64(b, d.h[i]) ++ } ++ b = appendUint64(b, d.c[0]) ++ b = appendUint64(b, d.c[1]) ++ // Maximum value for size is 64 ++ b = append(b, byte(d.size)) ++ b = append(b, d.block[:]...) ++ b = append(b, byte(d.offset)) ++ return b, nil ++} ++ ++func (d *digest) UnmarshalBinary(b []byte) error { ++ if len(b) < len(magic) || string(b[:len(magic)]) != magic { ++ return errors.New("crypto/blake2b: invalid hash state identifier") ++ } ++ if len(b) != marshaledSize { ++ return errors.New("crypto/blake2b: invalid hash state size") ++ } ++ b = b[len(magic):] ++ for i := 0; i < 8; i++ { ++ b, d.h[i] = consumeUint64(b) ++ } ++ b, d.c[0] = consumeUint64(b) ++ b, d.c[1] = consumeUint64(b) ++ d.size = int(b[0]) ++ b = b[1:] ++ copy(d.block[:], b[:BlockSize]) ++ b = b[BlockSize:] ++ d.offset = int(b[0]) ++ return nil ++} ++ ++func (d *digest) BlockSize() int { return BlockSize } ++ ++func (d *digest) Size() int { return d.size } ++ ++func (d *digest) Reset() { ++ d.h = iv ++ d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) ++ d.offset, d.c[0], d.c[1] = 0, 0, 0 ++ if d.keyLen > 0 { ++ d.block = d.key ++ d.offset = BlockSize ++ } ++} ++ ++func (d *digest) Write(p []byte) (n int, err error) { ++ n = len(p) ++ ++ if d.offset > 0 { ++ remaining := BlockSize - d.offset ++ if n <= remaining { ++ d.offset += copy(d.block[d.offset:], p) ++ return ++ } ++ copy(d.block[d.offset:], p[:remaining]) ++ hashBlocks(&d.h, &d.c, 0, d.block[:]) ++ d.offset = 0 ++ p = p[remaining:] ++ } ++ ++ if length := len(p); length > BlockSize { ++ nn := length &^ (BlockSize - 1) ++ if length == nn { ++ nn -= BlockSize ++ } ++ hashBlocks(&d.h, &d.c, 0, p[:nn]) ++ p = p[nn:] ++ } ++ ++ if len(p) > 0 { ++ d.offset += copy(d.block[:], p) ++ } ++ ++ return ++} ++ ++func (d *digest) Sum(sum []byte) []byte { ++ var hash [Size]byte ++ d.finalize(&hash) ++ return append(sum, hash[:d.size]...) ++} ++ ++func (d *digest) finalize(hash *[Size]byte) { ++ var block [BlockSize]byte ++ copy(block[:], d.block[:d.offset]) ++ remaining := uint64(BlockSize - d.offset) ++ ++ c := d.c ++ if c[0] < remaining { ++ c[1]-- ++ } ++ c[0] -= remaining ++ ++ h := d.h ++ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) ++ ++ for i, v := range h { ++ binary.LittleEndian.PutUint64(hash[8*i:], v) ++ } ++} ++ ++func appendUint64(b []byte, x uint64) []byte { ++ var a [8]byte ++ binary.BigEndian.PutUint64(a[:], x) ++ return append(b, a[:]...) ++} ++ ++func appendUint32(b []byte, x uint32) []byte { ++ var a [4]byte ++ binary.BigEndian.PutUint32(a[:], x) ++ return append(b, a[:]...) ++} ++ ++func consumeUint64(b []byte) ([]byte, uint64) { ++ x := binary.BigEndian.Uint64(b) ++ return b[8:], x ++} ++ ++func consumeUint32(b []byte) ([]byte, uint32) { ++ x := binary.BigEndian.Uint32(b) ++ return b[4:], x ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go +new file mode 100644 +index 00000000000000..56bfaaa17da6de +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go +@@ -0,0 +1,38 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.7 && amd64 && gc && !purego ++// +build go1.7,amd64,gc,!purego ++ ++package blake2b ++ ++import "golang.org/x/sys/cpu" ++ ++func init() { ++ useAVX2 = cpu.X86.HasAVX2 ++ useAVX = cpu.X86.HasAVX ++ useSSE4 = cpu.X86.HasSSE41 ++} ++ ++//go:noescape ++func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++ ++//go:noescape ++func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++ ++//go:noescape ++func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++ ++func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { ++ switch { ++ case useAVX2: ++ hashBlocksAVX2(h, c, flag, blocks) ++ case useAVX: ++ hashBlocksAVX(h, c, flag, blocks) ++ case useSSE4: ++ hashBlocksSSE4(h, c, flag, blocks) ++ default: ++ hashBlocksGeneric(h, c, flag, blocks) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s +new file mode 100644 +index 00000000000000..4b9daa18d9d9c3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s +@@ -0,0 +1,745 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.7 && amd64 && gc && !purego ++// +build go1.7,amd64,gc,!purego ++ ++#include "textflag.h" ++ ++DATA Β·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 ++DATA Β·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b ++DATA Β·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b ++DATA Β·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 ++GLOBL Β·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 ++ ++DATA Β·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 ++DATA Β·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f ++DATA Β·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b ++DATA Β·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 ++GLOBL Β·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 ++ ++DATA Β·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 ++DATA Β·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b ++DATA Β·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 ++DATA Β·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b ++GLOBL Β·AVX2_c40<>(SB), (NOPTR+RODATA), $32 ++ ++DATA Β·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 ++DATA Β·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a ++DATA Β·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 ++DATA Β·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a ++GLOBL Β·AVX2_c48<>(SB), (NOPTR+RODATA), $32 ++ ++DATA Β·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 ++DATA Β·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b ++GLOBL Β·AVX_iv0<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b ++DATA Β·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 ++GLOBL Β·AVX_iv1<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 ++DATA Β·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f ++GLOBL Β·AVX_iv2<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b ++DATA Β·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 ++GLOBL Β·AVX_iv3<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 ++DATA Β·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b ++GLOBL Β·AVX_c40<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 ++DATA Β·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a ++GLOBL Β·AVX_c48<>(SB), (NOPTR+RODATA), $16 ++ ++#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 ++#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 ++#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e ++#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 ++#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 ++ ++#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ ++ VPADDQ m0, Y0, Y0; \ ++ VPADDQ Y1, Y0, Y0; \ ++ VPXOR Y0, Y3, Y3; \ ++ VPSHUFD $-79, Y3, Y3; \ ++ VPADDQ Y3, Y2, Y2; \ ++ VPXOR Y2, Y1, Y1; \ ++ VPSHUFB c40, Y1, Y1; \ ++ VPADDQ m1, Y0, Y0; \ ++ VPADDQ Y1, Y0, Y0; \ ++ VPXOR Y0, Y3, Y3; \ ++ VPSHUFB c48, Y3, Y3; \ ++ VPADDQ Y3, Y2, Y2; \ ++ VPXOR Y2, Y1, Y1; \ ++ VPADDQ Y1, Y1, t; \ ++ VPSRLQ $63, Y1, Y1; \ ++ VPXOR t, Y1, Y1; \ ++ VPERMQ_0x39_Y1_Y1; \ ++ VPERMQ_0x4E_Y2_Y2; \ ++ VPERMQ_0x93_Y3_Y3; \ ++ VPADDQ m2, Y0, Y0; \ ++ VPADDQ Y1, Y0, Y0; \ ++ VPXOR Y0, Y3, Y3; \ ++ VPSHUFD $-79, Y3, Y3; \ ++ VPADDQ Y3, Y2, Y2; \ ++ VPXOR Y2, Y1, Y1; \ ++ VPSHUFB c40, Y1, Y1; \ ++ VPADDQ m3, Y0, Y0; \ ++ VPADDQ Y1, Y0, Y0; \ ++ VPXOR Y0, Y3, Y3; \ ++ VPSHUFB c48, Y3, Y3; \ ++ VPADDQ Y3, Y2, Y2; \ ++ VPXOR Y2, Y1, Y1; \ ++ VPADDQ Y1, Y1, t; \ ++ VPSRLQ $63, Y1, Y1; \ ++ VPXOR t, Y1, Y1; \ ++ VPERMQ_0x39_Y3_Y3; \ ++ VPERMQ_0x4E_Y2_Y2; \ ++ VPERMQ_0x93_Y1_Y1 ++ ++#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E ++#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 ++#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E ++#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 ++#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E ++ ++#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n ++#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n ++#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n ++#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n ++#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n ++ ++#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 ++#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 ++#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 ++#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 ++#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 ++ ++#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 ++#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 ++#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 ++#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 ++#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 ++ ++#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 ++#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 ++ ++// load msg: Y12 = (i0, i1, i2, i3) ++// i0, i1, i2, i3 must not be 0 ++#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ ++ VMOVQ_SI_X12(i0*8); \ ++ VMOVQ_SI_X11(i2*8); \ ++ VPINSRQ_1_SI_X12(i1*8); \ ++ VPINSRQ_1_SI_X11(i3*8); \ ++ VINSERTI128 $1, X11, Y12, Y12 ++ ++// load msg: Y13 = (i0, i1, i2, i3) ++// i0, i1, i2, i3 must not be 0 ++#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ ++ VMOVQ_SI_X13(i0*8); \ ++ VMOVQ_SI_X11(i2*8); \ ++ VPINSRQ_1_SI_X13(i1*8); \ ++ VPINSRQ_1_SI_X11(i3*8); \ ++ VINSERTI128 $1, X11, Y13, Y13 ++ ++// load msg: Y14 = (i0, i1, i2, i3) ++// i0, i1, i2, i3 must not be 0 ++#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ ++ VMOVQ_SI_X14(i0*8); \ ++ VMOVQ_SI_X11(i2*8); \ ++ VPINSRQ_1_SI_X14(i1*8); \ ++ VPINSRQ_1_SI_X11(i3*8); \ ++ VINSERTI128 $1, X11, Y14, Y14 ++ ++// load msg: Y15 = (i0, i1, i2, i3) ++// i0, i1, i2, i3 must not be 0 ++#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ ++ VMOVQ_SI_X15(i0*8); \ ++ VMOVQ_SI_X11(i2*8); \ ++ VPINSRQ_1_SI_X15(i1*8); \ ++ VPINSRQ_1_SI_X11(i3*8); \ ++ VINSERTI128 $1, X11, Y15, Y15 ++ ++#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ ++ VMOVQ_SI_X12_0; \ ++ VMOVQ_SI_X11(4*8); \ ++ VPINSRQ_1_SI_X12(2*8); \ ++ VPINSRQ_1_SI_X11(6*8); \ ++ VINSERTI128 $1, X11, Y12, Y12; \ ++ LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ ++ LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ ++ LOAD_MSG_AVX2_Y15(9, 11, 13, 15) ++ ++#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ ++ LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ ++ LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ ++ VMOVQ_SI_X11(11*8); \ ++ VPSHUFD $0x4E, 0*8(SI), X14; \ ++ VPINSRQ_1_SI_X11(5*8); \ ++ VINSERTI128 $1, X11, Y14, Y14; \ ++ LOAD_MSG_AVX2_Y15(12, 2, 7, 3) ++ ++#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ ++ VMOVQ_SI_X11(5*8); \ ++ VMOVDQU 11*8(SI), X12; \ ++ VPINSRQ_1_SI_X11(15*8); \ ++ VINSERTI128 $1, X11, Y12, Y12; \ ++ VMOVQ_SI_X13(8*8); \ ++ VMOVQ_SI_X11(2*8); \ ++ VPINSRQ_1_SI_X13_0; \ ++ VPINSRQ_1_SI_X11(13*8); \ ++ VINSERTI128 $1, X11, Y13, Y13; \ ++ LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ ++ LOAD_MSG_AVX2_Y15(14, 6, 1, 4) ++ ++#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ ++ LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ ++ LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ ++ LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ ++ VMOVQ_SI_X15(6*8); \ ++ VMOVQ_SI_X11_0; \ ++ VPINSRQ_1_SI_X15(10*8); \ ++ VPINSRQ_1_SI_X11(8*8); \ ++ VINSERTI128 $1, X11, Y15, Y15 ++ ++#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ ++ LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ ++ VMOVQ_SI_X13_0; \ ++ VMOVQ_SI_X11(4*8); \ ++ VPINSRQ_1_SI_X13(7*8); \ ++ VPINSRQ_1_SI_X11(15*8); \ ++ VINSERTI128 $1, X11, Y13, Y13; \ ++ LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ ++ LOAD_MSG_AVX2_Y15(1, 12, 8, 13) ++ ++#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ ++ VMOVQ_SI_X12(2*8); \ ++ VMOVQ_SI_X11_0; \ ++ VPINSRQ_1_SI_X12(6*8); \ ++ VPINSRQ_1_SI_X11(8*8); \ ++ VINSERTI128 $1, X11, Y12, Y12; \ ++ LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ ++ LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ ++ LOAD_MSG_AVX2_Y15(13, 5, 14, 9) ++ ++#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ ++ LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ ++ LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ ++ VMOVQ_SI_X14_0; \ ++ VPSHUFD $0x4E, 8*8(SI), X11; \ ++ VPINSRQ_1_SI_X14(6*8); \ ++ VINSERTI128 $1, X11, Y14, Y14; \ ++ LOAD_MSG_AVX2_Y15(7, 3, 2, 11) ++ ++#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ ++ LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ ++ LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ ++ LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ ++ VMOVQ_SI_X15_0; \ ++ VMOVQ_SI_X11(6*8); \ ++ VPINSRQ_1_SI_X15(4*8); \ ++ VPINSRQ_1_SI_X11(10*8); \ ++ VINSERTI128 $1, X11, Y15, Y15 ++ ++#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ ++ VMOVQ_SI_X12(6*8); \ ++ VMOVQ_SI_X11(11*8); \ ++ VPINSRQ_1_SI_X12(14*8); \ ++ VPINSRQ_1_SI_X11_0; \ ++ VINSERTI128 $1, X11, Y12, Y12; \ ++ LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ ++ VMOVQ_SI_X11(1*8); \ ++ VMOVDQU 12*8(SI), X14; \ ++ VPINSRQ_1_SI_X11(10*8); \ ++ VINSERTI128 $1, X11, Y14, Y14; \ ++ VMOVQ_SI_X15(2*8); \ ++ VMOVDQU 4*8(SI), X11; \ ++ VPINSRQ_1_SI_X15(7*8); \ ++ VINSERTI128 $1, X11, Y15, Y15 ++ ++#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ ++ LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ ++ VMOVQ_SI_X13(2*8); \ ++ VPSHUFD $0x4E, 5*8(SI), X11; \ ++ VPINSRQ_1_SI_X13(4*8); \ ++ VINSERTI128 $1, X11, Y13, Y13; \ ++ LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ ++ VMOVQ_SI_X15(11*8); \ ++ VMOVQ_SI_X11(12*8); \ ++ VPINSRQ_1_SI_X15(14*8); \ ++ VPINSRQ_1_SI_X11_0; \ ++ VINSERTI128 $1, X11, Y15, Y15 ++ ++// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++TEXT Β·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment ++ MOVQ h+0(FP), AX ++ MOVQ c+8(FP), BX ++ MOVQ flag+16(FP), CX ++ MOVQ blocks_base+24(FP), SI ++ MOVQ blocks_len+32(FP), DI ++ ++ MOVQ SP, DX ++ ADDQ $31, DX ++ ANDQ $~31, DX ++ ++ MOVQ CX, 16(DX) ++ XORQ CX, CX ++ MOVQ CX, 24(DX) ++ ++ VMOVDQU Β·AVX2_c40<>(SB), Y4 ++ VMOVDQU Β·AVX2_c48<>(SB), Y5 ++ ++ VMOVDQU 0(AX), Y8 ++ VMOVDQU 32(AX), Y9 ++ VMOVDQU Β·AVX2_iv0<>(SB), Y6 ++ VMOVDQU Β·AVX2_iv1<>(SB), Y7 ++ ++ MOVQ 0(BX), R8 ++ MOVQ 8(BX), R9 ++ MOVQ R9, 8(DX) ++ ++loop: ++ ADDQ $128, R8 ++ MOVQ R8, 0(DX) ++ CMPQ R8, $128 ++ JGE noinc ++ INCQ R9 ++ MOVQ R9, 8(DX) ++ ++noinc: ++ VMOVDQA Y8, Y0 ++ VMOVDQA Y9, Y1 ++ VMOVDQA Y6, Y2 ++ VPXOR 0(DX), Y7, Y3 ++ ++ LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() ++ VMOVDQA Y12, 32(DX) ++ VMOVDQA Y13, 64(DX) ++ VMOVDQA Y14, 96(DX) ++ VMOVDQA Y15, 128(DX) ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() ++ VMOVDQA Y12, 160(DX) ++ VMOVDQA Y13, 192(DX) ++ VMOVDQA Y14, 224(DX) ++ VMOVDQA Y15, 256(DX) ++ ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() ++ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) ++ ++ ROUND_AVX2(32(DX), 64(DX), 96(DX), 128(DX), Y10, Y4, Y5) ++ ROUND_AVX2(160(DX), 192(DX), 224(DX), 256(DX), Y10, Y4, Y5) ++ ++ VPXOR Y0, Y8, Y8 ++ VPXOR Y1, Y9, Y9 ++ VPXOR Y2, Y8, Y8 ++ VPXOR Y3, Y9, Y9 ++ ++ LEAQ 128(SI), SI ++ SUBQ $128, DI ++ JNE loop ++ ++ MOVQ R8, 0(BX) ++ MOVQ R9, 8(BX) ++ ++ VMOVDQU Y8, 0(AX) ++ VMOVDQU Y9, 32(AX) ++ VZEROUPPER ++ ++ RET ++ ++#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA ++#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB ++#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF ++#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD ++#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE ++ ++#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 ++#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF ++#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 ++#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF ++#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 ++#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 ++#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF ++#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF ++ ++#define SHUFFLE_AVX() \ ++ VMOVDQA X6, X13; \ ++ VMOVDQA X2, X14; \ ++ VMOVDQA X4, X6; \ ++ VPUNPCKLQDQ_X13_X13_X15; \ ++ VMOVDQA X5, X4; \ ++ VMOVDQA X6, X5; \ ++ VPUNPCKHQDQ_X15_X7_X6; \ ++ VPUNPCKLQDQ_X7_X7_X15; \ ++ VPUNPCKHQDQ_X15_X13_X7; \ ++ VPUNPCKLQDQ_X3_X3_X15; \ ++ VPUNPCKHQDQ_X15_X2_X2; \ ++ VPUNPCKLQDQ_X14_X14_X15; \ ++ VPUNPCKHQDQ_X15_X3_X3; \ ++ ++#define SHUFFLE_AVX_INV() \ ++ VMOVDQA X2, X13; \ ++ VMOVDQA X4, X14; \ ++ VPUNPCKLQDQ_X2_X2_X15; \ ++ VMOVDQA X5, X4; \ ++ VPUNPCKHQDQ_X15_X3_X2; \ ++ VMOVDQA X14, X5; \ ++ VPUNPCKLQDQ_X3_X3_X15; \ ++ VMOVDQA X6, X14; \ ++ VPUNPCKHQDQ_X15_X13_X3; \ ++ VPUNPCKLQDQ_X7_X7_X15; \ ++ VPUNPCKHQDQ_X15_X6_X6; \ ++ VPUNPCKLQDQ_X14_X14_X15; \ ++ VPUNPCKHQDQ_X15_X7_X7; \ ++ ++#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ ++ VPADDQ m0, v0, v0; \ ++ VPADDQ v2, v0, v0; \ ++ VPADDQ m1, v1, v1; \ ++ VPADDQ v3, v1, v1; \ ++ VPXOR v0, v6, v6; \ ++ VPXOR v1, v7, v7; \ ++ VPSHUFD $-79, v6, v6; \ ++ VPSHUFD $-79, v7, v7; \ ++ VPADDQ v6, v4, v4; \ ++ VPADDQ v7, v5, v5; \ ++ VPXOR v4, v2, v2; \ ++ VPXOR v5, v3, v3; \ ++ VPSHUFB c40, v2, v2; \ ++ VPSHUFB c40, v3, v3; \ ++ VPADDQ m2, v0, v0; \ ++ VPADDQ v2, v0, v0; \ ++ VPADDQ m3, v1, v1; \ ++ VPADDQ v3, v1, v1; \ ++ VPXOR v0, v6, v6; \ ++ VPXOR v1, v7, v7; \ ++ VPSHUFB c48, v6, v6; \ ++ VPSHUFB c48, v7, v7; \ ++ VPADDQ v6, v4, v4; \ ++ VPADDQ v7, v5, v5; \ ++ VPXOR v4, v2, v2; \ ++ VPXOR v5, v3, v3; \ ++ VPADDQ v2, v2, t0; \ ++ VPSRLQ $63, v2, v2; \ ++ VPXOR t0, v2, v2; \ ++ VPADDQ v3, v3, t0; \ ++ VPSRLQ $63, v3, v3; \ ++ VPXOR t0, v3, v3 ++ ++// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) ++// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 ++#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ ++ VMOVQ_SI_X12(i0*8); \ ++ VMOVQ_SI_X13(i2*8); \ ++ VMOVQ_SI_X14(i4*8); \ ++ VMOVQ_SI_X15(i6*8); \ ++ VPINSRQ_1_SI_X12(i1*8); \ ++ VPINSRQ_1_SI_X13(i3*8); \ ++ VPINSRQ_1_SI_X14(i5*8); \ ++ VPINSRQ_1_SI_X15(i7*8) ++ ++// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) ++#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ ++ VMOVQ_SI_X12_0; \ ++ VMOVQ_SI_X13(4*8); \ ++ VMOVQ_SI_X14(1*8); \ ++ VMOVQ_SI_X15(5*8); \ ++ VPINSRQ_1_SI_X12(2*8); \ ++ VPINSRQ_1_SI_X13(6*8); \ ++ VPINSRQ_1_SI_X14(3*8); \ ++ VPINSRQ_1_SI_X15(7*8) ++ ++// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) ++#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ ++ VPSHUFD $0x4E, 0*8(SI), X12; \ ++ VMOVQ_SI_X13(11*8); \ ++ VMOVQ_SI_X14(12*8); \ ++ VMOVQ_SI_X15(7*8); \ ++ VPINSRQ_1_SI_X13(5*8); \ ++ VPINSRQ_1_SI_X14(2*8); \ ++ VPINSRQ_1_SI_X15(3*8) ++ ++// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) ++#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ ++ VMOVDQU 11*8(SI), X12; \ ++ VMOVQ_SI_X13(5*8); \ ++ VMOVQ_SI_X14(8*8); \ ++ VMOVQ_SI_X15(2*8); \ ++ VPINSRQ_1_SI_X13(15*8); \ ++ VPINSRQ_1_SI_X14_0; \ ++ VPINSRQ_1_SI_X15(13*8) ++ ++// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) ++#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ ++ VMOVQ_SI_X12(2*8); \ ++ VMOVQ_SI_X13(4*8); \ ++ VMOVQ_SI_X14(6*8); \ ++ VMOVQ_SI_X15_0; \ ++ VPINSRQ_1_SI_X12(5*8); \ ++ VPINSRQ_1_SI_X13(15*8); \ ++ VPINSRQ_1_SI_X14(10*8); \ ++ VPINSRQ_1_SI_X15(8*8) ++ ++// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) ++#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ ++ VMOVQ_SI_X12(9*8); \ ++ VMOVQ_SI_X13(2*8); \ ++ VMOVQ_SI_X14_0; \ ++ VMOVQ_SI_X15(4*8); \ ++ VPINSRQ_1_SI_X12(5*8); \ ++ VPINSRQ_1_SI_X13(10*8); \ ++ VPINSRQ_1_SI_X14(7*8); \ ++ VPINSRQ_1_SI_X15(15*8) ++ ++// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) ++#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ ++ VMOVQ_SI_X12(2*8); \ ++ VMOVQ_SI_X13_0; \ ++ VMOVQ_SI_X14(12*8); \ ++ VMOVQ_SI_X15(11*8); \ ++ VPINSRQ_1_SI_X12(6*8); \ ++ VPINSRQ_1_SI_X13(8*8); \ ++ VPINSRQ_1_SI_X14(10*8); \ ++ VPINSRQ_1_SI_X15(3*8) ++ ++// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) ++#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ ++ MOVQ 0*8(SI), X12; \ ++ VPSHUFD $0x4E, 8*8(SI), X13; \ ++ MOVQ 7*8(SI), X14; \ ++ MOVQ 2*8(SI), X15; \ ++ VPINSRQ_1_SI_X12(6*8); \ ++ VPINSRQ_1_SI_X14(3*8); \ ++ VPINSRQ_1_SI_X15(11*8) ++ ++// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) ++#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ ++ MOVQ 6*8(SI), X12; \ ++ MOVQ 11*8(SI), X13; \ ++ MOVQ 15*8(SI), X14; \ ++ MOVQ 3*8(SI), X15; \ ++ VPINSRQ_1_SI_X12(14*8); \ ++ VPINSRQ_1_SI_X13_0; \ ++ VPINSRQ_1_SI_X14(9*8); \ ++ VPINSRQ_1_SI_X15(8*8) ++ ++// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) ++#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ ++ MOVQ 5*8(SI), X12; \ ++ MOVQ 8*8(SI), X13; \ ++ MOVQ 0*8(SI), X14; \ ++ MOVQ 6*8(SI), X15; \ ++ VPINSRQ_1_SI_X12(15*8); \ ++ VPINSRQ_1_SI_X13(2*8); \ ++ VPINSRQ_1_SI_X14(4*8); \ ++ VPINSRQ_1_SI_X15(10*8) ++ ++// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) ++#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ ++ VMOVDQU 12*8(SI), X12; \ ++ MOVQ 1*8(SI), X13; \ ++ MOVQ 2*8(SI), X14; \ ++ VPINSRQ_1_SI_X13(10*8); \ ++ VPINSRQ_1_SI_X14(7*8); \ ++ VMOVDQU 4*8(SI), X15 ++ ++// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) ++#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ ++ MOVQ 15*8(SI), X12; \ ++ MOVQ 3*8(SI), X13; \ ++ MOVQ 11*8(SI), X14; \ ++ MOVQ 12*8(SI), X15; \ ++ VPINSRQ_1_SI_X12(9*8); \ ++ VPINSRQ_1_SI_X13(13*8); \ ++ VPINSRQ_1_SI_X14(14*8); \ ++ VPINSRQ_1_SI_X15_0 ++ ++// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++TEXT Β·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment ++ MOVQ h+0(FP), AX ++ MOVQ c+8(FP), BX ++ MOVQ flag+16(FP), CX ++ MOVQ blocks_base+24(FP), SI ++ MOVQ blocks_len+32(FP), DI ++ ++ MOVQ SP, R10 ++ ADDQ $15, R10 ++ ANDQ $~15, R10 ++ ++ VMOVDQU Β·AVX_c40<>(SB), X0 ++ VMOVDQU Β·AVX_c48<>(SB), X1 ++ VMOVDQA X0, X8 ++ VMOVDQA X1, X9 ++ ++ VMOVDQU Β·AVX_iv3<>(SB), X0 ++ VMOVDQA X0, 0(R10) ++ XORQ CX, 0(R10) // 0(R10) = Β·AVX_iv3 ^ (CX || 0) ++ ++ VMOVDQU 0(AX), X10 ++ VMOVDQU 16(AX), X11 ++ VMOVDQU 32(AX), X2 ++ VMOVDQU 48(AX), X3 ++ ++ MOVQ 0(BX), R8 ++ MOVQ 8(BX), R9 ++ ++loop: ++ ADDQ $128, R8 ++ CMPQ R8, $128 ++ JGE noinc ++ INCQ R9 ++ ++noinc: ++ VMOVQ_R8_X15 ++ VPINSRQ_1_R9_X15 ++ ++ VMOVDQA X10, X0 ++ VMOVDQA X11, X1 ++ VMOVDQU Β·AVX_iv0<>(SB), X4 ++ VMOVDQU Β·AVX_iv1<>(SB), X5 ++ VMOVDQU Β·AVX_iv2<>(SB), X6 ++ ++ VPXOR X15, X6, X6 ++ VMOVDQA 0(R10), X7 ++ ++ LOAD_MSG_AVX_0_2_4_6_1_3_5_7() ++ VMOVDQA X12, 16(R10) ++ VMOVDQA X13, 32(R10) ++ VMOVDQA X14, 48(R10) ++ VMOVDQA X15, 64(R10) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) ++ VMOVDQA X12, 80(R10) ++ VMOVDQA X13, 96(R10) ++ VMOVDQA X14, 112(R10) ++ VMOVDQA X15, 128(R10) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) ++ VMOVDQA X12, 144(R10) ++ VMOVDQA X13, 160(R10) ++ VMOVDQA X14, 176(R10) ++ VMOVDQA X15, 192(R10) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX_1_0_11_5_12_2_7_3() ++ VMOVDQA X12, 208(R10) ++ VMOVDQA X13, 224(R10) ++ VMOVDQA X14, 240(R10) ++ VMOVDQA X15, 256(R10) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX_11_12_5_15_8_0_2_13() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX_2_5_4_15_6_10_0_8() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX_9_5_2_10_0_7_4_15() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX_2_6_0_8_12_10_11_3() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX_0_6_9_8_7_3_2_11() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX_5_15_8_2_0_4_6_10() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX_6_14_11_0_15_9_3_8() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX_12_13_1_10_2_7_4_5() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX() ++ LOAD_MSG_AVX_15_9_3_13_11_14_12_0() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X15, X8, X9) ++ SHUFFLE_AVX() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X15, X8, X9) ++ SHUFFLE_AVX() ++ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X15, X8, X9) ++ SHUFFLE_AVX_INV() ++ ++ VMOVDQU 32(AX), X14 ++ VMOVDQU 48(AX), X15 ++ VPXOR X0, X10, X10 ++ VPXOR X1, X11, X11 ++ VPXOR X2, X14, X14 ++ VPXOR X3, X15, X15 ++ VPXOR X4, X10, X10 ++ VPXOR X5, X11, X11 ++ VPXOR X6, X14, X2 ++ VPXOR X7, X15, X3 ++ VMOVDQU X2, 32(AX) ++ VMOVDQU X3, 48(AX) ++ ++ LEAQ 128(SI), SI ++ SUBQ $128, DI ++ JNE loop ++ ++ VMOVDQU X10, 0(AX) ++ VMOVDQU X11, 16(AX) ++ ++ MOVQ R8, 0(BX) ++ MOVQ R9, 8(BX) ++ VZEROUPPER ++ ++ RET +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go +new file mode 100644 +index 00000000000000..5fa1b32841df3a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go +@@ -0,0 +1,25 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !go1.7 && amd64 && gc && !purego ++// +build !go1.7,amd64,gc,!purego ++ ++package blake2b ++ ++import "golang.org/x/sys/cpu" ++ ++func init() { ++ useSSE4 = cpu.X86.HasSSE41 ++} ++ ++//go:noescape ++func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++ ++func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { ++ if useSSE4 { ++ hashBlocksSSE4(h, c, flag, blocks) ++ } else { ++ hashBlocksGeneric(h, c, flag, blocks) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s +new file mode 100644 +index 00000000000000..ae75eb9afcd7a1 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s +@@ -0,0 +1,279 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++#include "textflag.h" ++ ++DATA Β·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 ++DATA Β·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b ++GLOBL Β·iv0<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b ++DATA Β·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 ++GLOBL Β·iv1<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·iv2<>+0x00(SB)/8, $0x510e527fade682d1 ++DATA Β·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f ++GLOBL Β·iv2<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b ++DATA Β·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 ++GLOBL Β·iv3<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·c40<>+0x00(SB)/8, $0x0201000706050403 ++DATA Β·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b ++GLOBL Β·c40<>(SB), (NOPTR+RODATA), $16 ++ ++DATA Β·c48<>+0x00(SB)/8, $0x0100070605040302 ++DATA Β·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a ++GLOBL Β·c48<>(SB), (NOPTR+RODATA), $16 ++ ++#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ ++ MOVO v4, t1; \ ++ MOVO v5, v4; \ ++ MOVO t1, v5; \ ++ MOVO v6, t1; \ ++ PUNPCKLQDQ v6, t2; \ ++ PUNPCKHQDQ v7, v6; \ ++ PUNPCKHQDQ t2, v6; \ ++ PUNPCKLQDQ v7, t2; \ ++ MOVO t1, v7; \ ++ MOVO v2, t1; \ ++ PUNPCKHQDQ t2, v7; \ ++ PUNPCKLQDQ v3, t2; \ ++ PUNPCKHQDQ t2, v2; \ ++ PUNPCKLQDQ t1, t2; \ ++ PUNPCKHQDQ t2, v3 ++ ++#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ ++ MOVO v4, t1; \ ++ MOVO v5, v4; \ ++ MOVO t1, v5; \ ++ MOVO v2, t1; \ ++ PUNPCKLQDQ v2, t2; \ ++ PUNPCKHQDQ v3, v2; \ ++ PUNPCKHQDQ t2, v2; \ ++ PUNPCKLQDQ v3, t2; \ ++ MOVO t1, v3; \ ++ MOVO v6, t1; \ ++ PUNPCKHQDQ t2, v3; \ ++ PUNPCKLQDQ v7, t2; \ ++ PUNPCKHQDQ t2, v6; \ ++ PUNPCKLQDQ t1, t2; \ ++ PUNPCKHQDQ t2, v7 ++ ++#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ ++ PADDQ m0, v0; \ ++ PADDQ m1, v1; \ ++ PADDQ v2, v0; \ ++ PADDQ v3, v1; \ ++ PXOR v0, v6; \ ++ PXOR v1, v7; \ ++ PSHUFD $0xB1, v6, v6; \ ++ PSHUFD $0xB1, v7, v7; \ ++ PADDQ v6, v4; \ ++ PADDQ v7, v5; \ ++ PXOR v4, v2; \ ++ PXOR v5, v3; \ ++ PSHUFB c40, v2; \ ++ PSHUFB c40, v3; \ ++ PADDQ m2, v0; \ ++ PADDQ m3, v1; \ ++ PADDQ v2, v0; \ ++ PADDQ v3, v1; \ ++ PXOR v0, v6; \ ++ PXOR v1, v7; \ ++ PSHUFB c48, v6; \ ++ PSHUFB c48, v7; \ ++ PADDQ v6, v4; \ ++ PADDQ v7, v5; \ ++ PXOR v4, v2; \ ++ PXOR v5, v3; \ ++ MOVOU v2, t0; \ ++ PADDQ v2, t0; \ ++ PSRLQ $63, v2; \ ++ PXOR t0, v2; \ ++ MOVOU v3, t0; \ ++ PADDQ v3, t0; \ ++ PSRLQ $63, v3; \ ++ PXOR t0, v3 ++ ++#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ ++ MOVQ i0*8(src), m0; \ ++ PINSRQ $1, i1*8(src), m0; \ ++ MOVQ i2*8(src), m1; \ ++ PINSRQ $1, i3*8(src), m1; \ ++ MOVQ i4*8(src), m2; \ ++ PINSRQ $1, i5*8(src), m2; \ ++ MOVQ i6*8(src), m3; \ ++ PINSRQ $1, i7*8(src), m3 ++ ++// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) ++TEXT Β·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment ++ MOVQ h+0(FP), AX ++ MOVQ c+8(FP), BX ++ MOVQ flag+16(FP), CX ++ MOVQ blocks_base+24(FP), SI ++ MOVQ blocks_len+32(FP), DI ++ ++ MOVQ SP, R10 ++ ADDQ $15, R10 ++ ANDQ $~15, R10 ++ ++ MOVOU Β·iv3<>(SB), X0 ++ MOVO X0, 0(R10) ++ XORQ CX, 0(R10) // 0(R10) = Β·iv3 ^ (CX || 0) ++ ++ MOVOU Β·c40<>(SB), X13 ++ MOVOU Β·c48<>(SB), X14 ++ ++ MOVOU 0(AX), X12 ++ MOVOU 16(AX), X15 ++ ++ MOVQ 0(BX), R8 ++ MOVQ 8(BX), R9 ++ ++loop: ++ ADDQ $128, R8 ++ CMPQ R8, $128 ++ JGE noinc ++ INCQ R9 ++ ++noinc: ++ MOVQ R8, X8 ++ PINSRQ $1, R9, X8 ++ ++ MOVO X12, X0 ++ MOVO X15, X1 ++ MOVOU 32(AX), X2 ++ MOVOU 48(AX), X3 ++ MOVOU Β·iv0<>(SB), X4 ++ MOVOU Β·iv1<>(SB), X5 ++ MOVOU Β·iv2<>(SB), X6 ++ ++ PXOR X8, X6 ++ MOVO 0(R10), X7 ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) ++ MOVO X8, 16(R10) ++ MOVO X9, 32(R10) ++ MOVO X10, 48(R10) ++ MOVO X11, 64(R10) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) ++ MOVO X8, 80(R10) ++ MOVO X9, 96(R10) ++ MOVO X10, 112(R10) ++ MOVO X11, 128(R10) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) ++ MOVO X8, 144(R10) ++ MOVO X9, 160(R10) ++ MOVO X10, 176(R10) ++ MOVO X11, 192(R10) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) ++ MOVO X8, 208(R10) ++ MOVO X9, 224(R10) ++ MOVO X10, 240(R10) ++ MOVO X11, 256(R10) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X11, X13, X14) ++ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) ++ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X11, X13, X14) ++ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) ++ ++ MOVOU 32(AX), X10 ++ MOVOU 48(AX), X11 ++ PXOR X0, X12 ++ PXOR X1, X15 ++ PXOR X2, X10 ++ PXOR X3, X11 ++ PXOR X4, X12 ++ PXOR X5, X15 ++ PXOR X6, X10 ++ PXOR X7, X11 ++ MOVOU X10, 32(AX) ++ MOVOU X11, 48(AX) ++ ++ LEAQ 128(SI), SI ++ SUBQ $128, DI ++ JNE loop ++ ++ MOVOU X12, 0(AX) ++ MOVOU X15, 16(AX) ++ ++ MOVQ R8, 0(BX) ++ MOVQ R9, 8(BX) ++ ++ RET +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go +new file mode 100644 +index 00000000000000..3168a8aa3c834a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go +@@ -0,0 +1,182 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blake2b ++ ++import ( ++ "encoding/binary" ++ "math/bits" ++) ++ ++// the precomputed values for BLAKE2b ++// there are 12 16-byte arrays - one for each round ++// the entries are calculated from the sigma constants. ++var precomputed = [12][16]byte{ ++ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, ++ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, ++ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, ++ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, ++ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, ++ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, ++ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, ++ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, ++ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, ++ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, ++ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first ++ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second ++} ++ ++func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { ++ var m [16]uint64 ++ c0, c1 := c[0], c[1] ++ ++ for i := 0; i < len(blocks); { ++ c0 += BlockSize ++ if c0 < BlockSize { ++ c1++ ++ } ++ ++ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] ++ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] ++ v12 ^= c0 ++ v13 ^= c1 ++ v14 ^= flag ++ ++ for j := range m { ++ m[j] = binary.LittleEndian.Uint64(blocks[i:]) ++ i += 8 ++ } ++ ++ for j := range precomputed { ++ s := &(precomputed[j]) ++ ++ v0 += m[s[0]] ++ v0 += v4 ++ v12 ^= v0 ++ v12 = bits.RotateLeft64(v12, -32) ++ v8 += v12 ++ v4 ^= v8 ++ v4 = bits.RotateLeft64(v4, -24) ++ v1 += m[s[1]] ++ v1 += v5 ++ v13 ^= v1 ++ v13 = bits.RotateLeft64(v13, -32) ++ v9 += v13 ++ v5 ^= v9 ++ v5 = bits.RotateLeft64(v5, -24) ++ v2 += m[s[2]] ++ v2 += v6 ++ v14 ^= v2 ++ v14 = bits.RotateLeft64(v14, -32) ++ v10 += v14 ++ v6 ^= v10 ++ v6 = bits.RotateLeft64(v6, -24) ++ v3 += m[s[3]] ++ v3 += v7 ++ v15 ^= v3 ++ v15 = bits.RotateLeft64(v15, -32) ++ v11 += v15 ++ v7 ^= v11 ++ v7 = bits.RotateLeft64(v7, -24) ++ ++ v0 += m[s[4]] ++ v0 += v4 ++ v12 ^= v0 ++ v12 = bits.RotateLeft64(v12, -16) ++ v8 += v12 ++ v4 ^= v8 ++ v4 = bits.RotateLeft64(v4, -63) ++ v1 += m[s[5]] ++ v1 += v5 ++ v13 ^= v1 ++ v13 = bits.RotateLeft64(v13, -16) ++ v9 += v13 ++ v5 ^= v9 ++ v5 = bits.RotateLeft64(v5, -63) ++ v2 += m[s[6]] ++ v2 += v6 ++ v14 ^= v2 ++ v14 = bits.RotateLeft64(v14, -16) ++ v10 += v14 ++ v6 ^= v10 ++ v6 = bits.RotateLeft64(v6, -63) ++ v3 += m[s[7]] ++ v3 += v7 ++ v15 ^= v3 ++ v15 = bits.RotateLeft64(v15, -16) ++ v11 += v15 ++ v7 ^= v11 ++ v7 = bits.RotateLeft64(v7, -63) ++ ++ v0 += m[s[8]] ++ v0 += v5 ++ v15 ^= v0 ++ v15 = bits.RotateLeft64(v15, -32) ++ v10 += v15 ++ v5 ^= v10 ++ v5 = bits.RotateLeft64(v5, -24) ++ v1 += m[s[9]] ++ v1 += v6 ++ v12 ^= v1 ++ v12 = bits.RotateLeft64(v12, -32) ++ v11 += v12 ++ v6 ^= v11 ++ v6 = bits.RotateLeft64(v6, -24) ++ v2 += m[s[10]] ++ v2 += v7 ++ v13 ^= v2 ++ v13 = bits.RotateLeft64(v13, -32) ++ v8 += v13 ++ v7 ^= v8 ++ v7 = bits.RotateLeft64(v7, -24) ++ v3 += m[s[11]] ++ v3 += v4 ++ v14 ^= v3 ++ v14 = bits.RotateLeft64(v14, -32) ++ v9 += v14 ++ v4 ^= v9 ++ v4 = bits.RotateLeft64(v4, -24) ++ ++ v0 += m[s[12]] ++ v0 += v5 ++ v15 ^= v0 ++ v15 = bits.RotateLeft64(v15, -16) ++ v10 += v15 ++ v5 ^= v10 ++ v5 = bits.RotateLeft64(v5, -63) ++ v1 += m[s[13]] ++ v1 += v6 ++ v12 ^= v1 ++ v12 = bits.RotateLeft64(v12, -16) ++ v11 += v12 ++ v6 ^= v11 ++ v6 = bits.RotateLeft64(v6, -63) ++ v2 += m[s[14]] ++ v2 += v7 ++ v13 ^= v2 ++ v13 = bits.RotateLeft64(v13, -16) ++ v8 += v13 ++ v7 ^= v8 ++ v7 = bits.RotateLeft64(v7, -63) ++ v3 += m[s[15]] ++ v3 += v4 ++ v14 ^= v3 ++ v14 = bits.RotateLeft64(v14, -16) ++ v9 += v14 ++ v4 ^= v9 ++ v4 = bits.RotateLeft64(v4, -63) ++ ++ } ++ ++ h[0] ^= v0 ^ v8 ++ h[1] ^= v1 ^ v9 ++ h[2] ^= v2 ^ v10 ++ h[3] ^= v3 ^ v11 ++ h[4] ^= v4 ^ v12 ++ h[5] ^= v5 ^ v13 ++ h[6] ^= v6 ^ v14 ++ h[7] ^= v7 ^ v15 ++ } ++ c[0], c[1] = c0, c1 ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go +new file mode 100644 +index 00000000000000..b0137cdf025cb1 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go +@@ -0,0 +1,12 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !amd64 || purego || !gc ++// +build !amd64 purego !gc ++ ++package blake2b ++ ++func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { ++ hashBlocksGeneric(h, c, flag, blocks) ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go +new file mode 100644 +index 00000000000000..723327ab563e5e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go +@@ -0,0 +1,847 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blake2b ++ ++import ( ++ "bytes" ++ "encoding" ++ "encoding/hex" ++ "fmt" ++ "hash" ++ "io" ++ "testing" ++) ++ ++func fromHex(s string) []byte { ++ b, err := hex.DecodeString(s) ++ if err != nil { ++ panic(err) ++ } ++ return b ++} ++ ++func TestHashes(t *testing.T) { ++ defer func(sse4, avx, avx2 bool) { ++ useSSE4, useAVX, useAVX2 = sse4, avx, avx2 ++ }(useSSE4, useAVX, useAVX2) ++ ++ if useAVX2 { ++ t.Log("AVX2 version") ++ testHashes(t) ++ useAVX2 = false ++ } ++ if useAVX { ++ t.Log("AVX version") ++ testHashes(t) ++ useAVX = false ++ } ++ if useSSE4 { ++ t.Log("SSE4 version") ++ testHashes(t) ++ useSSE4 = false ++ } ++ t.Log("generic version") ++ testHashes(t) ++} ++ ++func TestHashes2X(t *testing.T) { ++ defer func(sse4, avx, avx2 bool) { ++ useSSE4, useAVX, useAVX2 = sse4, avx, avx2 ++ }(useSSE4, useAVX, useAVX2) ++ ++ if useAVX2 { ++ t.Log("AVX2 version") ++ testHashes2X(t) ++ useAVX2 = false ++ } ++ if useAVX { ++ t.Log("AVX version") ++ testHashes2X(t) ++ useAVX = false ++ } ++ if useSSE4 { ++ t.Log("SSE4 version") ++ testHashes2X(t) ++ useSSE4 = false ++ } ++ t.Log("generic version") ++ testHashes2X(t) ++} ++ ++func TestMarshal(t *testing.T) { ++ input := make([]byte, 255) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ for _, size := range []int{Size, Size256, Size384, 12, 25, 63} { ++ for i := 0; i < 256; i++ { ++ h, err := New(size, nil) ++ if err != nil { ++ t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) ++ } ++ h2, err := New(size, nil) ++ if err != nil { ++ t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) ++ } ++ ++ h.Write(input[:i/2]) ++ halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() ++ if err != nil { ++ t.Fatalf("size=%d, len(input)=%d: could not marshal: %v", size, i, err) ++ } ++ err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) ++ if err != nil { ++ t.Fatalf("size=%d, len(input)=%d: could not unmarshal: %v", size, i, err) ++ } ++ ++ h.Write(input[i/2 : i]) ++ sum := h.Sum(nil) ++ h2.Write(input[i/2 : i]) ++ sum2 := h2.Sum(nil) ++ ++ if !bytes.Equal(sum, sum2) { ++ t.Fatalf("size=%d, len(input)=%d: results do not match; sum = %v, sum2 = %v", size, i, sum, sum2) ++ } ++ ++ h3, err := New(size, nil) ++ if err != nil { ++ t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) ++ } ++ h3.Write(input[:i]) ++ sum3 := h3.Sum(nil) ++ if !bytes.Equal(sum, sum3) { ++ t.Fatalf("size=%d, len(input)=%d: sum = %v, want %v", size, i, sum, sum3) ++ } ++ } ++ } ++} ++ ++func testHashes(t *testing.T) { ++ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") ++ ++ input := make([]byte, 255) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ ++ for i, expectedHex := range hashes { ++ h, err := New512(key) ++ if err != nil { ++ t.Fatalf("#%d: error from New512: %v", i, err) ++ } ++ ++ h.Write(input[:i]) ++ sum := h.Sum(nil) ++ ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ ++ h.Reset() ++ for j := 0; j < i; j++ { ++ h.Write(input[j : j+1]) ++ } ++ ++ sum = h.Sum(sum[:0]) ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ } ++} ++ ++func testHashes2X(t *testing.T) { ++ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") ++ ++ input := make([]byte, 256) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ ++ for i, expectedHex := range hashes2X { ++ length := uint32(len(expectedHex) / 2) ++ sum := make([]byte, int(length)) ++ ++ h, err := NewXOF(length, key) ++ if err != nil { ++ t.Fatalf("#%d: error from NewXOF: %v", i, err) ++ } ++ ++ if _, err := h.Write(input); err != nil { ++ t.Fatalf("#%d (single write): error from Write: %v", i, err) ++ } ++ if _, err := h.Read(sum); err != nil { ++ t.Fatalf("#%d (single write): error from Read: %v", i, err) ++ } ++ if n, err := h.Read(sum); n != 0 || err != io.EOF { ++ t.Fatalf("#%d (single write): Read did not return (0, io.EOF) after exhaustion, got (%v, %v)", i, n, err) ++ } ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ ++ h.Reset() ++ for j := 0; j < len(input); j++ { ++ h.Write(input[j : j+1]) ++ } ++ for j := 0; j < len(sum); j++ { ++ h = h.Clone() ++ if _, err := h.Read(sum[j : j+1]); err != nil { ++ t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) ++ } ++ } ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ } ++ ++ h, err := NewXOF(OutputLengthUnknown, key) ++ if err != nil { ++ t.Fatalf("#unknown length: error from NewXOF: %v", err) ++ } ++ if _, err := h.Write(input); err != nil { ++ t.Fatalf("#unknown length: error from Write: %v", err) ++ } ++ ++ var result [64]byte ++ if n, err := h.Read(result[:]); err != nil { ++ t.Fatalf("#unknown length: error from Read: %v", err) ++ } else if n != len(result) { ++ t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) ++ } ++ ++ const expected = "3dbba8516da76bf7330055c66ea36cf1005e92714262b24d9710f51d9e126406e1bcd6497059f9331f1091c3634b695428d475ed432f987040575520a1c29f5e" ++ if fmt.Sprintf("%x", result) != expected { ++ t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) ++ } ++} ++ ++func generateSequence(out []byte, seed uint32) { ++ a := 0xDEAD4BAD * seed // prime ++ b := uint32(1) ++ ++ for i := range out { // fill the buf ++ a, b = b, a+b ++ out[i] = byte(b >> 24) ++ } ++} ++ ++func computeMAC(msg []byte, hashSize int, key []byte) (sum []byte) { ++ var h hash.Hash ++ switch hashSize { ++ case Size: ++ h, _ = New512(key) ++ case Size384: ++ h, _ = New384(key) ++ case Size256: ++ h, _ = New256(key) ++ case 20: ++ h, _ = newDigest(20, key) ++ default: ++ panic("unexpected hashSize") ++ } ++ ++ h.Write(msg) ++ return h.Sum(sum) ++} ++ ++func computeHash(msg []byte, hashSize int) (sum []byte) { ++ switch hashSize { ++ case Size: ++ hash := Sum512(msg) ++ return hash[:] ++ case Size384: ++ hash := Sum384(msg) ++ return hash[:] ++ case Size256: ++ hash := Sum256(msg) ++ return hash[:] ++ case 20: ++ var hash [64]byte ++ checkSum(&hash, 20, msg) ++ return hash[:20] ++ default: ++ panic("unexpected hashSize") ++ } ++} ++ ++// Test function from RFC 7693. ++func TestSelfTest(t *testing.T) { ++ hashLens := [4]int{20, 32, 48, 64} ++ msgLens := [6]int{0, 3, 128, 129, 255, 1024} ++ ++ msg := make([]byte, 1024) ++ key := make([]byte, 64) ++ ++ h, _ := New256(nil) ++ for _, hashSize := range hashLens { ++ for _, msgLength := range msgLens { ++ generateSequence(msg[:msgLength], uint32(msgLength)) // unkeyed hash ++ ++ md := computeHash(msg[:msgLength], hashSize) ++ h.Write(md) ++ ++ generateSequence(key[:], uint32(hashSize)) // keyed hash ++ md = computeMAC(msg[:msgLength], hashSize, key[:hashSize]) ++ h.Write(md) ++ } ++ } ++ ++ sum := h.Sum(nil) ++ expected := [32]byte{ ++ 0xc2, 0x3a, 0x78, 0x00, 0xd9, 0x81, 0x23, 0xbd, ++ 0x10, 0xf5, 0x06, 0xc6, 0x1e, 0x29, 0xda, 0x56, ++ 0x03, 0xd7, 0x63, 0xb8, 0xbb, 0xad, 0x2e, 0x73, ++ 0x7f, 0x5e, 0x76, 0x5a, 0x7b, 0xcc, 0xd4, 0x75, ++ } ++ if !bytes.Equal(sum, expected[:]) { ++ t.Fatalf("got %x, wanted %x", sum, expected) ++ } ++} ++ ++// Benchmarks ++ ++func benchmarkSum(b *testing.B, size int) { ++ data := make([]byte, size) ++ b.SetBytes(int64(size)) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ Sum512(data) ++ } ++} ++ ++func benchmarkWrite(b *testing.B, size int) { ++ data := make([]byte, size) ++ h, _ := New512(nil) ++ b.SetBytes(int64(size)) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ h.Write(data) ++ } ++} ++ ++func BenchmarkWrite128(b *testing.B) { benchmarkWrite(b, 128) } ++func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } ++ ++func BenchmarkSum128(b *testing.B) { benchmarkSum(b, 128) } ++func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } ++ ++// These values were taken from https://blake2.net/blake2b-test.txt. ++var hashes = []string{ ++ "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568", ++ "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd", ++ "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965", ++ "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1", ++ "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac", ++ "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb", ++ "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f", ++ "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52", ++ "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9", ++ "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637", ++ "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd", ++ "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b", ++ "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563", ++ "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355", ++ "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6", ++ "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e", ++ "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93", ++ "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1", ++ "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670", ++ "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9", ++ "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c", ++ "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd", ++ "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152", ++ "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9", ++ "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f", ++ "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b", ++ "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764", ++ "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d", ++ "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55", ++ "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b", ++ "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e", ++ "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7", ++ "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991", ++ "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347", ++ "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82", ++ "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42", ++ "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327", ++ "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760", ++ "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252", ++ "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55", ++ "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1", ++ "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee", ++ "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa", ++ "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7", ++ "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071", ++ "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4", ++ "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf", ++ "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d", ++ "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8", ++ "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487", ++ "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c", ++ "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2", ++ "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa", ++ "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33", ++ "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d", ++ "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e", ++ "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2", ++ "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4", ++ "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2", ++ "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a", ++ "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564", ++ "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f", ++ "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9", ++ "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa", ++ "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022", ++ "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c", ++ "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc", ++ "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f", ++ "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b", ++ "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866", ++ "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d", ++ "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8", ++ "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4", ++ "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3", ++ "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e", ++ "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745", ++ "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545", ++ "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063", ++ "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd", ++ "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a", ++ "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed", ++ "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd", ++ "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275", ++ "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897", ++ "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430", ++ "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab", ++ "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f", ++ "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46", ++ "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29", ++ "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab", ++ "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8", ++ "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a", ++ "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec", ++ "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79", ++ "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24", ++ "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b", ++ "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5", ++ "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463", ++ "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4", ++ "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3", ++ "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9", ++ "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d", ++ "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4", ++ "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a", ++ "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6", ++ "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73", ++ "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6", ++ "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6", ++ "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3", ++ "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa", ++ "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3", ++ "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b", ++ "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f", ++ "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc", ++ "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200", ++ "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6", ++ "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8", ++ "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f", ++ "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a", ++ "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e", ++ "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935", ++ "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74", ++ "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0", ++ "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c", ++ "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145", ++ "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f", ++ "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0", ++ "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb", ++ "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4", ++ "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91", ++ "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89", ++ "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444", ++ "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a", ++ "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414", ++ "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49", ++ "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b", ++ "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0", ++ "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469", ++ "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3", ++ "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd", ++ "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8", ++ "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21", ++ "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989", ++ "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1", ++ "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399", ++ "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0", ++ "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723", ++ "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff", ++ "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc", ++ "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38", ++ "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a", ++ "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051", ++ "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca", ++ "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4", ++ "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677", ++ "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1", ++ "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce", ++ "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347", ++ "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91", ++ "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209", ++ "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659", ++ "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381", ++ "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56", ++ "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7", ++ "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f", ++ "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972", ++ "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe", ++ "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e", ++ "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be", ++ "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8", ++ "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc", ++ "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8", ++ "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0", ++ "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc", ++ "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979", ++ "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29", ++ "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d", ++ "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108", ++ "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45", ++ "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4", ++ "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267", ++ "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d", ++ "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb", ++ "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813", ++ "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc", ++ "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29", ++ "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc", ++ "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16", ++ "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1", ++ "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c", ++ "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7", ++ "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a", ++ "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa", ++ "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e", ++ "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc", ++ "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5", ++ "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a", ++ "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3", ++ "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc", ++ "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d", ++ "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff", ++ "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb", ++ "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4", ++ "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc", ++ "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902", ++ "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e", ++ "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08", ++ "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816", ++ "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406", ++ "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4", ++ "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d", ++ "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d", ++ "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900", ++ "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06", ++ "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01", ++ "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0", ++ "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94", ++ "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02", ++ "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492", ++ "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2", ++ "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c", ++ "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb", ++ "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077", ++ "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727", ++ "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd", ++ "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c", ++ "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0", ++ "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403", ++ "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391", ++ "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8", ++ "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605", ++ "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9", ++ "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d", ++ "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe", ++ "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe", ++ "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1", ++ "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3", ++ "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb", ++ "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b", ++ "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef", ++ "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253", ++ "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec", ++ "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a", ++ "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473", ++ "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837", ++ "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a", ++ "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1", ++ "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d", ++ "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9", ++ "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537", ++ "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7", ++ "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2", ++ "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338", ++ "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15", ++ "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9", ++ "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461", ++} ++ ++var hashes2X = []string{ ++ "64", ++ "f457", ++ "e8c045", ++ "a74c6d0d", ++ "eb02ae482a", ++ "be65b981275e", ++ "8540ccd083a455", ++ "074a02fa58d7c7c0", ++ "da6da05e10db3022b6", ++ "542a5aae2f28f2c3b68c", ++ "ca3af2afc4afe891da78b1", ++ "e0f66b8dcebf4edc85f12c85", ++ "744224d383733b3fa2c53bfcf5", ++ "b09b653e85b72ef5cdf8fcfa95f3", ++ "dd51877f31f1cf7b9f68bbb09064a3", ++ "f5ebf68e7ebed6ad445ffc0c47e82650", ++ "ebdcfe03bcb7e21a9091202c5938c0a1bb", ++ "860fa5a72ff92efafc48a89df1632a4e2809", ++ "0d6d49daa26ae2818041108df3ce0a4db48c8d", ++ "e5d7e1bc5715f5ae991e4043e39533af5d53e47f", ++ "5232028a43b9d4dfa7f37439b49495926481ab8a29", ++ "c118803c922f9ae2397fb676a2ab7603dd9c29c21fe4", ++ "2af924f48b9bd7076bfd68794bba6402e2a7ae048de3ea", ++ "61255ac38231087c79ea1a0fa14538c26be1c851b6f318c0", ++ "f9712b8e42f0532162822f142cb946c40369f2f0e77b6b186e", ++ "76da0b89558df66f9b1e66a61d1e795b178ce77a359087793ff2", ++ "9036fd1eb32061bdecebc4a32aa524b343b8098a16768ee774d93c", ++ "f4ce5a05934e125d159678bea521f585574bcf9572629f155f63efcc", ++ "5e1c0d9fae56393445d3024d6b82692d1339f7b5936f68b062c691d3bf", ++ "538e35f3e11111d7c4bab69f83b30ade4f67addf1f45cdd2ac74bf299509", ++ "17572c4dcbb17faf8785f3bba9f6903895394352eae79b01ebd758377694cc", ++ "29f6bb55de7f8868e053176c878c9fe6c2055c4c5413b51ab0386c277fdbac75", ++ "bad026c8b2bd3d294907f2280a7145253ec2117d76e3800357be6d431b16366e41", ++ "386b7cb6e0fd4b27783125cbe80065af8eb9981fafc3ed18d8120863d972fa7427d9", ++ "06e8e6e26e756fff0b83b226dce974c21f970e44fb5b3e5bbada6e4b12f81cca666f48", ++ "2f9bd300244f5bc093ba6dcdb4a89fa29da22b1de9d2c9762af919b5fedf6998fbda305b", ++ "cf6bdcc46d788074511f9e8f0a4b86704365b2d3f98340b8db53920c385b959a38c8869ae7", ++ "1171e603e5cdeb4cda8fd7890222dd8390ede87b6f3284cac0f0d832d8250c9200715af7913d", ++ "bda7b2ad5d02bd35ffb009bdd72b7d7bc9c28b3a32f32b0ba31d6cbd3ee87c60b7b98c03404621", ++ "2001455324e748503aa08eff2fb2e52ae0170e81a6e9368ada054a36ca340fb779393fb045ac72b3", ++ "45f0761aefafbf87a68f9f1f801148d9bba52616ad5ee8e8ac9207e9846a782f487d5cca8b20355a18", ++ "3a7e05708be62f087f17b41ac9f20e4ef8115c5ab6d08e84d46af8c273fb46d3ce1aabebae5eea14e018", ++ "ea318da9d042ca337ccdfb2bee3e96ecb8f907876c8d143e8e44569178353c2e593e4a82c265931ba1dd79", ++ "e0f7c08f5bd712f87094b04528fadb283d83c9ceb82a3e39ec31c19a42a1a1c3bee5613b5640abe069b0d690", ++ "d35e63fb1f3f52ab8f7c6cd7c8247e9799042e53922fbaea808ab979fa0c096588cfea3009181d2f93002dfc11", ++ "b8b0ab69e3ae55a8699eb481dd665b6a2424c89bc6b7cca02d15fdf1b9854139cab49d34de498b50b2c7e8b910cf", ++ "fb65e3222a2950eae1701d4cdd4736266f65bf2c0d2e77968996eadb60ef74fb786f6234973a2524bdfe32d100aa0e", ++ "f28b4bb3a2e2c4d5c01a23ff134558559a2d3d704b75402983ee4e0f71d273ae056842c4153b18ee5c47e2bfa54313d4", ++ "7bb78794e58a53c3e4b1aeb161e756af051583d14e0a5a3205e094b7c9a8cf62d098fa9ea1db12f330a51ab9852c17f983", ++ "a879a8ebae4d0987789bcc58ec3448e35ba1fa1ee58c668d8295aba4eaeaf2762b053a677e25404f635a53037996974d418a", ++ "695865b353ec701ecc1cb38f3154489eed0d39829fc192bb68db286d20fa0a64235cde5639137819f7e99f86bd89afcef84a0f", ++ "a6ec25f369f71176952fb9b33305dc768589a6070463ee4c35996e1ced4964a865a5c3dc8f0d809eab71366450de702318e4834d", ++ "604749f7bfadb069a036409ffac5ba291fa05be8cba2f141554132f56d9bcb88d1ce12f2004cd3ade1aa66a26e6ef64e327514096d", ++ "daf9fa7dc2464a899533594e7916fc9bc585bd29dd60c930f3bfa78bc47f6c8439448043a45119fc9228c15bce5fd24f46baf9de736b", ++ "943ea5647a8666763084da6a6f15dcf0e8dc24f27fd0d9194805d25180fe3a6d98f4b2b5e0d6a04e9b41869817030f16ae975dd41fc35c", ++ "af4f73cbfc093760dfeb52d57ef45207bbd1a515f5523404e5d95a73c237d97ae65bd195b472de6d514c2c448b12fafc282166da132258e9", ++ "605f4ed72ed7f5046a342fe4cf6808100d4632e610d59f7ebb016e367d0ff0a95cf45b02c727ba71f147e95212f52046804d376c918cadd260", ++ "3750d8ab0a6b13f78e51d321dfd1aa801680e958de45b7b977d05732ee39f856b27cb2bcce8fbf3db6666d35e21244c2881fdcc27fbfea6b1672", ++ "8f1b929e80ab752b58abe9731b7b34eb61369536995abef1c0980d93903c1880da3637d367456895f0cb4769d6de3a979e38ed6f5f6ac4d48e9b32", ++ "d8469b7aa538b36cdc711a591d60dafecca22bd421973a70e2deef72f69d8014a6f0064eabfbebf5383cbb90f452c6e113d2110e4b1092c54a38b857", ++ "7d1f1ad2029f4880e1898af8289c23bc933a40863cc4ab697fead79c58b6b8e25b68cf5324579b0fe879fe7a12e6d03907f0140dfe7b29d33d6109ecf1", ++ "87a77aca6d551642288a0dff66078225ae39d288801607429d6725ca949eed7a6f199dd8a65523b4ee7cfa4187400e96597bfffc3e38ade0ae0ab88536a9", ++ "e101f43179d8e8546e5ce6a96d7556b7e6b9d4a7d00e7aade5579d085d527ce34a9329551ebcaf6ba946949bbe38e30a62ae344c1950b4bde55306b3bac432", ++ "4324561d76c370ef35ac36a4adf8f3773a50d86504bd284f71f7ce9e2bc4c1f1d34a7fb2d67561d101955d448b67577eb30dfee96a95c7f921ef53e20be8bc44", ++ "78f0ed6e220b3da3cc9381563b2f72c8dc830cb0f39a48c6ae479a6a78dcfa94002631dec467e9e9b47cc8f0887eb680e340aec3ec009d4a33d241533c76c8ca8c", ++ "9f6589c31a472e0a736f4eb22b6c70a9d332cc15304ccb66a6b97cd051b6ed82f8990e1d9bee2e4bb1c3c45e550ae0e7b96e93ae23f2fb8f63b309131e72b36cba6a", ++ "c138077ee4ed3d7ffa85ba851dfdf6e9843fc1dc00889d117237bfaad9aa757192f73556b959f98e6d24886ce48869f2a01a48c371785f12b6484eb2078f08c22066e1", ++ "f83e7c9e0954a500576ea1fc90a3db2cbd7994eaef647dab5b34e88ab9dc0b47addbc807b21c8e6dd3d0bd357f008471d4f3e0abb18450e1d4919e03a34545b9643f870e", ++ "3277a11f2628544fc66f50428f1ad56bcba6ee36ba2ca6ecdf7e255effc0c30235c039d13e01f04cf1efe95b5c2033ab72adda30994b62f2851d17c9920eadca9a251752dc", ++ "c2a834281a06fe7b730d3a03f90761daf02714c066e33fc07e1f59ac801ec2f4433486b5a2da8faa51a0cf3c34e29b2960cd0013378938dbd47c3a3d12d70db01d7d06c3e91e", ++ "47680182924a51cabe142a6175c9253e8ba7ea579ece8d9bcb78b1e9ca00db844fa08abcf41702bd758ee2c608d9612fed50e85854469cb4ef3038acf1e35b6ba4390561d8ae82", ++ "cec45830cd71869e83b109a99a3cd7d935f83a95de7c582f3adbd34e4938fa2f3f922f52f14f169c38cc6618d3f306a8a4d607b345b8a9c48017136fbf825aecf7b620e85f837fae", ++ "46fb53c70ab105079d5d78dc60eaa30d938f26e4d0b9df122e21ec85deda94744c1daf8038b8a6652d1ff3e7e15376f5abd30e564784a999f665078340d66b0e939e0c2ef03f9c08bb", ++ "7b0dcb52791a170cc52f2e8b95d8956f325c3751d3ef3b2b83b41d82d4496b46228a750d02b71a96012e56b0720949ca77dc68be9b1ef1ad6d6a5ceb86bf565cb972279039e209dddcdc", ++ "7153fd43e6b05f5e1a4401e0fef954a737ed142ec2f60bc4daeef9ce73ea1b40a0fcaf1a1e03a3513f930dd5335723632f59f7297fe3a98b68e125eadf478eb045ed9fc4ee566d13f537f5", ++ "c7f569c79c801dab50e9d9ca6542f25774b3841e49c83efe0b89109f569509ce7887bc0d2b57b50320eb81fab9017f16c4c870e59edb6c26620d93748500231d70a36f48a7c60747ca2d5986", ++ "0a81e0c547648595adca65623ce783411aac7f7d30c3ad269efafab288e7186f6895261972f5137877669c550f34f5128850ebb50e1884814ea1055ee29a866afd04b2087abed02d9592573428", ++ "6a7b6769e1f1c95314b0c7fe77013567891bd23416374f23e4f43e27bc4c55cfada13b53b1581948e07fb96a50676baa2756db0988077b0f27d36ac088e0ff0fe72eda1e8eb4b8facff3218d9af0", ++ "a399474595cb1ccab6107f18e80f03b1707745c7bf769fc9f260094dc9f8bc6fe09271cb0b131ebb2acd073de4a6521c8368e664278be86be216d1622393f23435fae4fbc6a2e7c961282a777c2d75", ++ "4f0fc590b2755a515ae6b46e9628092369d9c8e589e3239320639aa8f7aa44f8111c7c4b3fdbe6e55e036fbf5ebc9c0aa87a4e66851c11e86f6cbf0bd9eb1c98a378c7a7d3af900f55ee108b59bc9e5c", ++ "ed96a046f08dd675107331d267379c6fce3c352a9f8d7b243008a74cb4e9410836afaabe871dab6038ca94ce5f6d41fa922ce08aba58169f94cfc86d9f688f396abd24c11a6a9b0830572105a477c33e92", ++ "379955f539abf0eb2972ee99ed9546c4bbee363403991833005dc27904c271ef22a799bc32cb39f08d2e4ba6717d55153feb692d7c5efae70890bf29d96df02333c7b05ccc314e4835b018fec9141a82c745", ++ "e16cc8d41b96547ede0d0cf4d908c5fa393399daa4a9696e76a4c1f6a2a9fef70f17fb53551a8145ed88f18db8fe780a079d94732437023f7c1d1849ef69ad536a76204239e8ba5d97e507c36c7d042f87fe0e", ++ "a81de50750ece3f84536728f227208bf01ec5b7721579d007de72c88ee20663318332efe5bc7c09ad1fa8342be51f0609046ccf760a7957a7d8dc88941adb93666a4521ebe76618e5ddc2dd3261493d400b50073", ++ "b72c5fb7c7f60d243928fa41a2d711157b96aef290185c64b4de3dcfa3d644da67a8f37c2ac55caad79ec695a473e8b481f658c497edb8a191526592b11a412282d2a4010c90ef4647bd6ce745ebc9244a71d4876b", ++ "9550703877079c90e200e830f277b605624954c549e729c359ee01ee2b07741ecc4255cb37f96682dafcdbaade1063e2c5ccbd1918fb669926a67744101fb6de3ac016be4c74165a1e5a696b704ba2ebf4a953d44b95", ++ "a17eb44d4de502dc04a80d5a5e9507d17f27c96467f24c79b06bc98a4c410741d4ac2db98ec02c2a976d788531f1a4451b6c6204cef6dae1b6ebbcd0bde23e6fffb02754043c8fd3c783d90a670b16879ce68b5554fe1c", ++ "41d3ea1eaba5be4a206732dbb5b70b79b66a6e5908795ad4fb7cf9e67efb13f06fef8f90acb080ce082aadec6a1b543af759ab63fa6f1d3941186482b0c2b312f1151ea8386253a13ed3708093279b8eb04185636488b226", ++ "5e7cdd8373dc42a243c96013cd29df9283b5f28bb50453a903c85e2ce57f35861bf93f03029072b70dac0804e7d51fd0c578c8d9fa619f1e9ce3d8044f65d55634dba611280c1d5cfb59c836a595c803124f696b07ddfac718", ++ "26a14c4aa168907cb5de0d12a82e1373a128fb21f2ed11feba108b1bebce934ad63ed89f4ed7ea5e0bc8846e4fc10142f82de0bebd39d68f7874f615c3a9c896bab34190e85df05aaa316e14820b5e478d838fa89dfc94a7fc1e", ++ "0211dfc3c35881adc170e4ba6daab1b702dff88933db9a6829a76b8f4a7c2a6d658117132a974f0a0b3a38ceea1efc2488da21905345909e1d859921dc2b5054f09bce8eeb91fa2fc6d048ce00b9cd655e6aafbdaa3a2f19270a16", ++ "ddf015b01b68c4f5f72c3145d54049867d99ee6bef24282abf0eecdb506e295bacf8f23ffa65a4cd891f76a046b9dd82cae43a8d01e18a8dff3b50aeb92672be69d7c087ec1fa2d3b2a39196ea5b49b7baede37a586fea71aded587f", ++ "6ee721f71ca4dd5c9ce7873c5c04c6ce76a2c824b984251c15535afc96adc9a4d48ca314bfeb6b8ee65092f14cf2a7ca9614e1dcf24c2a7f0f0c11207d3d8aed4af92873b56e8b9ba2fbd659c3f4ca90fa24f113f74a37181bf0fdf758", ++ "689bd150e65ac123612524f720f54def78c095eaab8a87b8bcc72b443408e3227f5c8e2bd5af9bcac684d497bc3e41b7a022c28fb5458b95e8dfa2e8caccde0492936ff1902476bb7b4ef2125b19aca2cd3384d922d9f36dddbcd96ae0d6", ++ "3a3c0ef066fa4390ec76ad6be1dc9c31ddf45fef43fbfa1f49b439caa2eb9f3042253a9853e96a9cf86b4f873785a5d2c5d3b05f6501bc876e09031188e05f48937bf3c9b667d14800db62437590b84ce96aa70bb5141ee2ea41b55a6fd944", ++ "741ce384e5e0edaebb136701ce38b3d33215415197758ae81235307a4115777d4dab23891db530c6d28f63a957428391421f742789a0e04c99c828373d9903b64dd57f26b3a38b67df829ae243feef731ead0abfca049924667fdec49d40f665", ++ "a513f450d66cd5a48a115aee862c65b26e836f35a5eb6894a80519e2cd96cc4cad8ed7eb922b4fc9bbc55c973089d627b1da9c3a95f6c019ef1d47143cc545b15e4244424be28199c51a5efc7234dcd94e72d229897c392af85f523c2633427825", ++ "71f1554d2d49bb7bd9e62e71fa049fb54a2c097032f61ebda669b3e1d4593962e47fc62a0ab5d85706aebd6a2f9a192c88aa1ee2f6a46710cf4af6d3c25b7e68ad5c3db23ac009c8f13625ff85dc8e50a9a1b2682d3329330b973ec8cbb7bb73b2bd", ++ "167cc1067bc08a8d2c1a0c10041ebe1fc327b37043f6bd8f1c63569e9d36ded58519e66b162f34b6d8f1107ef1e3de199d97b36b44141a1fc4f49b883f40507ff11f909a017869dc8a2357fc7336ae68703d25f75710b0ff5f9765321c0fa53a51675c", ++ "cb859b35dc70e264efaad2a809fea1e71cd4a3f924be3b5a13f8687a1166b538c40b2ad51d5c3e47b0de482497382673140f547068ff0b3b0fb7501209e1bf36082509ae85f60bb98fd02ac50d883a1a8daa704952d83c1f6da60c9624bc7c99912930bf", ++ "afb1f0c6b7125b04fa2578dd40f60cb411b35ebc7026c702e25b3f0ae3d4695d44cfdf37cb755691dd9c365edadf21ee44245620e6a24d4c2497135b37cd7ac67e3bd0aaee9f63f107746f9b88859ea902bc7d6895406aa2161f480cad56327d0a5bba2836", ++ "13e9c0522587460d90c7cb354604de8f1bf850e75b4b176bda92862d35ec810861f7d5e7ff6ba9302f2c2c8642ff8b7776a2f53665790f570fcef3cac069a90d50db42227331c4affb33d6c040d75b9aeafc9086eb83ced38bb02c759e95ba08c92b17031288", ++ "0549812d62d3ed497307673a4806a21060987a4dbbf43d352b9b170a29240954cf04bc3e1e250476e6800b79e843a8bd8253b7d743de01ab336e978d4bea384eaff700ce020691647411b10a60acacb6f8837fb08ad666b8dcc9eaa87ccb42aef6914a3f3bc30a", ++ "3a263efbe1f2d463f20526e1d0fd735035fd3f808925f058b32c4d8788aeeab9b8ce233b3c34894731cd73361f465bd350395aebcabd2fb63010298ca025d849c1fa3cd573309b74d7f824bbfe383f09db24bcc565f636b877333206a6ad70815c3bef5574c5fc1c", ++ "3c6a7d8a84ef7e3eaa812fc1eb8e85105467230d2c9e4562edbfd808f4d1ac15d16b786cc6a02959c2bc17149c2ce74c6f85ee5ef22a8a96b9be1f197cffd214c1ab02a06a9227f37cd432579f8c28ff2b5ac91cca8ffe6240932739d56788c354e92c591e1dd76499", ++ "b571859294b02af17541a0b5e899a5f67d6f5e36d38255bc417486e69240db56b09cf2607fbf4f95d085a779358a8a8b41f36503438c1860c8f361ce0f2783a08b21bd7232b50ca6d35428335272a5c05b436b2631d8d5c84d60e8040083768ce56a250727fb0579dd5c", ++ "98ee1b7269d2a0dd490ca38d447279870ea55326571a1b430adbb2cf65c492131136f504145df3ab113a13abfb72c33663266b8bc9c458db4bf5d7ef03e1d3b8a99d5de0c024be8fabc8dc4f5dac82a0342d8ed65c329e7018d6997e69e29a01350516c86beaf153da65ac", ++ "41c5c95f088df320d35269e5bf86d10248f17aec6776f0fe653f1c356aae409788c938befeb67c86d1c8870e8099ca0ce61a80fbb5a6654c44529368f70fc9b9c2f912f5092047d0ffc339577d24142300e34948e086f62e23ecaca410d24f8a36b5c8c5a80e0926bc8aa16a", ++ "9f93c41f533b2a82a4df893c78faaaa793c1506974ba2a604cd33101713ca4adfd30819ffd8403402b8d40aff78106f3357f3e2c24312c0d3603a17184d7b999fc9908d14d50192aebabd90d05073da7af4be37dd3d81c90acc80e8333df546f17ab6874f1ec204392d1c0571e", ++ "3da5207245ac270a915fc91cdb314e5a2577c4f8e269c4e701f0d7493ba716de79935918b917a2bd5db98050dbd1eb3894b65fac5abf13e075abebc011e651c03cafb6127147771a5c8418223e1548137a89206635c26ca9c235ccc108dc25cf846e4732444bd0c2782b197b262b", ++ "96011af3965bb941dc8f749932ea484eccb9ba94e34b39f24c1e80410f96ce1d4f6e0aa5be606def4f54301e930493d4b55d484d93ab9dd4dc2c9cfb79345363af31ad42f4bd1aa6c77b8afc9f0d551bef7570b13b927afe3e7ac4de7603a0876d5edb1ad9be05e9ee8b53941e8f59", ++ "51dbbf2a7ca224e524e3454fe82ddc901fafd2120fa8603bc343f129484e9600f688586e040566de0351d1693829045232d04ff31aa6b80125c763faab2a9b233313d931903dcfaba490538b06e4688a35886dc24cdd32a13875e6acf45454a8eb8a315ab95e608ad8b6a49aef0e299a", ++ "5a6a422529e22104681e8b18d64bc0463a45df19ae2633751c7aae412c250f8fb2cd5e1270d3d0cf009c8aa69688ccd4e2b6536f5747a5bc479b20c135bf4e89d33a26118705a614c6be7ecfe766932471ad4ba01c4f045b1abb5070f90ec78439a27a1788db9327d1c32f939e5fb1d5ba", ++ "5d26c983642093cb12ff0afabd87b7c56e211d01844ad6da3f623b9f20a0c968034299f2a65e6673530c5980a532beb831c7d0697d12760445986681076dfb6fae5f3a4d8f17a0db5008ce8619f566d2cfe4cf2a6d6f9c3664e3a48564a351c0b3c945c5ee24587521e4112c57e318be1b6a", ++ "52641dbc6e36be4d905d8d60311e303e8e859cc47901ce30d6f67f152343e3c4030e3a33463793c19effd81fb7c4d631a9479a7505a983a052b1e948ce093b30efa595fab3a00f4cef9a2f664ceeb07ec61719212d58966bca9f00a7d7a8cb4024cf6476bab7fbccee5fd4e7c3f5e2b2975aa2", ++ "a34ce135b37bf3db1c4aaa4878b4499bd2ee17b85578fcaf605d41e1826b45fdaa1b083d8235dc642787f11469a5493e36806504fe2a2063905e821475e2d5ee217057950370492f5024995e77b82aa51b4f5bd8ea24dc71e0a8a640b0592c0d80c24a726169cf0a10b40944747113d03b52708c", ++ "46b3cdf4946e15a5334fc3244d6680f5fc132afa67bf43bfade23d0c9e0ec64e7dab76faaeca1870c05f96b7d019411d8b0873d9fed04fa5057c039d5949a4d592827f619471359d6171691cfa8a5d7cb07ef2804f6ccad4821c56d4988bea7765f660f09ef87405f0a80bcf8559efa111f2a0b419", ++ "8b9fc21691477f11252fca050b121c5334eb4280aa11659e267297de1fec2b2294c7ccee9b59a149b9930b08bd320d3943130930a7d931b71d2f10234f4480c67f1de883d9894ada5ed5071660e221d78ae402f1f05af47761e13fec979f2671e3c63fb0ae7aa1327cf9b8313adab90794a52686bbc4", ++ "cd6598924ce847de7ff45b20ac940aa6292a8a99b56a74eddc24f2cfb45797188614a21d4e8867e23ff75afd7cd324248d58fcf1ddc73fbd115dfa8c09e62022fab540a59f87c989c12a86ded05130939f00cd2f3b512963dfe0289f0e54acad881c1027d2a0292138fdee902d67d9669c0ca1034a9456", ++ "594e1cd7337248704e691854af0fdb021067ddf7832b049ba7b684438c32b029eded2df2c89a6ff5f2f2c311522ae2dc6db5a815afc60637b15ec24ef9541f1550409db2a006da3affffe548a1eaee7bd114e9b805d0756c8e90c4dc33cb05226bc2b393b18d953f8730d4c7ae693159cdba758ad28964e2", ++ "1f0d292453f04406ada8be4c161b82e3cdd69099a8637659e0ee40b8f6da46005cfc6085db9804852decfbe9f7b4dda019a7112612895a144ed430a960c8b2f5458d3d56b7f427cee6358915aee7146278aed2a0296cdd929e4d21ef95a3adf8b7a6beba673cdccdbdcfb2474711732d972ad054b2dc64f38d", ++ "b65a72d4e1f9f9f75911cc46ad0806b9b18c87d105332a3fe183f45f063a746c892dc6c4b9181b1485b3e3a2cc3b453eba2d4c39d6905a774ed3fb755468beb190925ecd8e57ecb0d985125741650c6b6a1b2a3a50e93e3892c21d47ed5884eed83aa94e1602288f2f49fe286624de9d01fcb54433a0dc4ad70b", ++ "705ce0ffa469250782aff725248fc88fe98eb76659e8407edc1c4842c9867d61fe64fb86f74e980598b92bc213d06f337bd5654fc28643c7ba769a4c31563427543c00808b627a19c90d86c322f33566ce020121cc322229c3337943d46f68ef939d613dcef0077269f88151d6398b6b009abb763410b154ad76a3", ++ "7fa881ce87498440ab6af13854f0d851a7e0404de33896999a9b3292a5d2f5b3ad033530c558168fe5d2fdb9b89a2354c46cf32a0e612afc6c6485d789511bfef26800c74bf1a4cfbe30bda310d5f6029c3dccdedb6149e4971274e276dccfabd63bc4b9955e8303feb57f8a688db55ecb4b33d1f9fe1b3a8ba7ac32", ++ "23a98f71c01c0408ae16843dc03be7db0aeaf055f951709d4e0dfdf64fffbffaf900ee592ee10929648e56f6c1e9f5be5793f7df66453eb56502c7c56c0f0c88da77abc8fa371e434104627ef7c663c49f40998dbad63fa6c7aa4fac17ae138d8bbe081f9bd168cd33c1fbc92fa35ed687679f48a64b87db1fe5bae675", ++ "7b8970b6a33237e5a7bcb39272703edb92285c55842b30b9a48834b1b507cc02a6764739f2f7ee6ae02a7b715a1c455e59e8c77a1ae98abb10161853f1234d20da99016588cd8602d6b7ec7e177d4011edfa61e6b3766a3c6f8d6e9eac893c568903eb6e6aba9c4725774f6b4343b7acaa6c031593a36eef6c72806ff309", ++ "f7f4d328ba108b7b1de4443e889a985ed52f485f3ca4e0c246aa5526590cbed344e9f4fe53e4eea0e761c82324649206ca8c2b45152157d4115e68c818644b03b65bb47ad79f94d37cb03c1d953b74c2b8adfa0e1c418bda9c518ddcd7050e0f149044740a2b16479413b63fc13c36144f80c73687513dca761ba8642a8ae0", ++ "2d7dc80c19a1d12d5fe3963569547a5d1d3e821e6f06c5d5e2c09401f946c9f7e13cd019f2f9a878b62dd850453b6294b99ccaa068e542993524b0f63832d48e865be31e8ec1ee103c718340c904b32efb69170b67f038d50a3252794b1b4076c0620621ab3d91215d55ffea99f23d54e161a90d8d4902fda5931d9f6a27146a", ++ "77dff4c7ad30c954338c4b23639dae4b275086cbe654d401a2343528065e4c9f1f2eca22aa025d49ca823e76fdbb35df78b1e5075ff2c82b680bca385c6d57f7ea7d1030bb392527b25dd73e9eeff97bea397cf3b9dda0c817a9c870ed12c006cc054968c64000e0da874e9b7d7d621b0679866912243ea096c7b38a1344e98f74", ++ "83bed0d556798f2b419f7056e6d3ffada06e939b95a688d0ec8c6ac5ea45ab73a4cf01043e0a170766e21395f27ab4b78c435f5f0dfe6e93ab80df38610e41158429ddf20296f53a06a017723359fe22dc08b5da33f0800a4fe50118e8d7eab2f83a85cd764bf8a166903bd0e9dcfeeceba44ff4ca4439846458d31ea2bb564645d1", ++ "ea12cf5a113543e39504123036f15a5bafa9c555562469f99cd29996a4dfaaab2a34b00557ccf15f37fc0cc1b3be427e725f2cd952e50af7970dda9200cd5ce252b1f29c40067fea3027ed686190803b59d834179d1b8f5b55abe55ad174b2a1188f7753ec0ae2fc01316e7d498b68ee3598a0e9baaaa664a60f7fb4f90edbed494ad7", ++ "55266358332d8d9e68bd13432088beadf95833aab67a0eb3b10650414255f299e2670c3e1a5b2976159a46c72a7ce57d59b7be14c15798e09ed50fa312a431b0264d7a1396aa6168bde897e208ece53d2cfc83786113b1e6eac5e9bb98984abb6c8d64eebb991903254abc650c999bb9958a5d7937434b869bc940e21b9dc1cc8982f2ba", ++ "4d6104ded730aefe02873f4c741232c8234a6d66d85393aff57fbf56ba6347666988dfc4d58f3cc895a0da598822edeee4533d24ec0ee292fd5e1ad04898ffbc1ff4bef14dec220babcb0f28fffe32a6e2c28aaaac16442bf4feb02917d18bb3a415d84fa9358d5a9852688d846c92271911f934181c30f82434d915f93f155a1ffbf0b125", ++ "eb5f579a4c476af554aac11e5719d378549497e613b35a929d6f36bb8831d7a466aa76de9be24ebb55543f1c13924f64cfd648a5b3fa90387315c16174dbf1e9a183c196d9bb8f84af65f1f8212429aadc11ef2426d07d4716062b85c8d5d2dff8e21b9e62b7fa7dbd57d72633054b464fb28583a56ca13ccc5ddc74dae942492f31731e7046", ++ "ebddec3dcaf18063e45a76ebeac39af85a1adc2818881ccce48c106288f5988365cca2b4b1d7f037322da46840f42bebdcbc7193838d426e101087d8cea03aaff743d573eb4f4e9a71a2c884390769a6503874125d194bee8d46a3a0d5e4fcf28ff8465887d8e9df771d70157e75df3642b331d2778ceb32ceba868640171ab7a5d22eede1ee44", ++ "26d87ec70b57691e3bb359633d3ddba17f029d62cdfe977f5fd42274d79b444a32494d1c01e9f72d03cce78c806df96e93ea78da3a054209924ed765edc4d570f66168dc25ee3114e4017e387440349c8f0a94804761c3055f88e4fda2a49b860b1486a9609095f6250f268b6a4d1aecc03a505632ebf0b9dc22d0755a736faf7ad7000858b5864b", ++ "3880f5cc2d08fa70ef44b1f263fcf534d062a298c1bd5ee2eee8c3265806c4ce50b004f3a1fc1fa5b024aaac7f528c023c8181f67c6e1c357425dc4d573bd46b93a542afa3a19bdb140a2ce666e1a01f5c4d2dcd681fa9f5839b797813c394738d5ee4971386c12c7c117d17c7bec324b760aa30cda9ab2aa850284ba6fa97946f710f02449d1883c6", ++ "3317d2f452105dd3f4a96f9257af8285a80be58066b50f6f54bd633749b49f6ab9d57d45652d2ae852a2f6940cd5ec3159dd7f333358b12f502325df38843508faf7e246352d201280babd90b14fbf7722641c3601d0e458474439973c611bb5502fd0eb3078f87124ca7e1a016fcb6cfeff65f6a565985aca7122cfa8c5a11da0cb47797c5132333179", ++ "f2c5c955d0224e784a46b9125f8fef8a5e1271e145eb08bbbd07ca8e1cfc848cef14fa3b36221ac62006403dbb7f7d77958ccc54a8566c837858b809f3e310ace8ca682515bc655d2a397cab238a663b464d511f02dc5d033dad4cb5e0e519e94a54b62a3896e460ec70e5716b5921bf8396aa86a60123e6287e34570bb01bdc602e113670bf498af2ff10", ++ "180e275205691a83630cf4b0c7b80e6df8fad6ef1c23ba8013d2f09aef7abade1827f23af230de90676240b4b3b0673f8afdea0327330055041741f65560d90348de696d34ca80dfe8afae582fe4879d4594b80e9408fb53e800e01ca58552b905c365e7f1416e51c080f517d6bbd30e64ae1535d59decdc76c6624d737868f49f2f719da39ba1344d59eab9", ++ "c517a84e4631a7f65ace170d1e5c2fdb259841535d88da323e68c0883e6af7b041cfe05908815a5a9d1b14fa712c2c16fadcf1ca54d3aa954d411240df331b2aebdfb65aced84d0b8aace56ec0aa7c13ec7d75ca883b6bcf6db74c9e98463c484a8262684f29910373430651f90ecffe18b072170e61ee58de20e2a6ff67b3ab00fccbb80af943f20b56b98107", ++ "d1a56a5ee990e02b84b5862fde62f69ec07567be2d7ccb769a461c4989d11fdda6c945d942fb8b2da795ed97e43a5b7dbdde7f8fd2ff7154544336d5c50fb7380341e660d4898c7fbc39b2b782f28defac6873523c7c1de8e52c65e4395c686ba483c35a220b0416d46357a063fa4c33fa9c52d5c207a1304ae141c791e62ba6a7374ed922b8dd94079b72b69302", ++ "4720b88d6bfb1ab43958e26827730d852d9ec30173ebd0fe0d273edcece2e788558984cd9306fe5978086a5cb6d37975755d2a3daeb16f99a8a11544b8247a8b7ed5587afc5bea1daf85dcea5703c5905cf56ae7cc76408ccabb8fcc25cacc5ff456db3f62fa559c45b9c71505eb5073df1f10fc4c9060843f0cd68bbb4e8edfb48d0fd81d9c21e53b28a2aae4f7ba", ++ "f4639b511db9e092823d47d2947efacbaae0e5b912dec3b284d2350b9262f3a51796a0cd9f8bc5a65879d6578ec24a060e293100c2e12ad82d5b2a0e9d22965858030e7cdf2ab3562bfa8ac084c6e8237aa22f54b94c4e92d69f22169ced6c85a293f5e16bfc326153bf629cdd6393675c6627cd949cd367eef02e0f54779f4d5210197698e4754a5fe490a3a7521c1c", ++ "3d9e7a860a718565e3670c29079ce80e381969fea91017cfd5952e0d8a4a79bb08e2cd1e26161f30ee03a24891d1bfa8c212861b51618d07429fb48000ff87ef09c6fca526567777e9c076d58a642d5c521b1caa5fb0fb3a4b8982dc14a444732b72b239b8f01fc8ba8ee86b3013b5d3e98a92b2aeaecd4879fca5d5e9e0bd880dbfffa6f96f94f3998812aac6a714f331", ++ "4d9bf551d7fd531e7482e2ec875c0651b0bcc6caa738f7497befd11e67ae0e036c9d7ae4301cc3c7906f0d0e1ed4738753f414f9b3cd9b8a71176e325c4c74ce020680ecbfb146889597f5b40487e93f974cd866817fb9fb24c7c7c16177e6e120bfe349e83aa82ba40e59e917565788658a2b254f25cf99bc65070b3794cea2259eb10e42bb54852cba3110baa773dcd70c", ++ "b91f65ab5bc059bfa5b43b6ebae243b1c46826f3da061338b5af02b2da76bb5ebad2b426de3c3134a633499c7c36a120369727cb48a0c6cbab0acecdda137057159aa117a5d687c4286868f561a272e0c18966b2fec3e55d75abea818ce2d339e26adc005c2658493fe06271ad0cc33fcb25065e6a2a286af45a518aee5e2532f81ec9256f93ff2d0d41c9b9a2efdb1a2af899", ++ "736f6e387acb9acbee026a6080f8a9eb8dbb5d7c54ac7053ce75dd184b2cb7b942e22a3497419ddb3a04cf9e4eb9340a1a6f9474c06ee1dcfc8513979fee1fc4768087617fd424f4d65f54782c787a1d2de6efc81534343e855f20b3f3589027a5436201eee747d45b9b8375e4294d72ab6a52e04dfbb2914db92ee58f134b026527ed52d4f794459e02a43a17b0d51ea69bd7f3", ++ "9242d3eb31d26d923b99d66954cfade94f25a18912e6356810b63b971ae74bb53bc58b3c01424208ea1e0b1499936daea27e63d904f9ed65fdf69de40780a3027b2e89d94bdf214f585472613ce328f628f4f0d56217dfb53db5f7a07f54c8d71db16e27de7cdb8d23988837b49b65c12f1771d979e8b192c9f4a16b8d9fba917bcf74ce5a82aac2075608ba6c2d485fa59864b9de", ++ "5da68704f4b592d41f08aca08f62d85e2e2466e5f3be010315d11d113db674c4b98764a509a2f5aacc7ae72c9deff2bcc42810b47f64d429b35745b9efff0b18c58653461e968aaa3c2c7fc455bc5771a8f10cd184be831040df767201ab8d32cb9a58c89afbebecb524502c9b940c1b838f8361bbcde90d272715017f67609ea39b20fac985332d82daaa023999e3f8bfa5f3758bb8", ++ "71ea2af9c8ac2e5ae44a176662882e01027ca3cdb41ec2c6785606a07d7231cd4a2bded7155c2feef3d44d8fd42afa73265cef826f6e03aa761c5c51d5b1f129ddc27503ff50d9c2d748322df4b13dd5cdc7d46381528ab22b79b0049011e4d2e57fe2735e0d58d8d56e92c75dbeac8c76c4239d7f3f24fb56697593b3e4afa6671d5bbc96c079a1c154fe20212ade67b05d49ceaa7a84", ++ "1d133170582fa4bff59a21953ebbc01bc202d43cd79c083d1f5c02fa15a43a0f519e36acb710bdabac880f04bc003800641c2487930de9c03c0e0deb347fa815efca0a38c6c5de694db698743bc955581f6a945deec4ae988ef7cdf40498b77796ddea3fae0ea844891ab751c7ee20917c5a4af53cd4ebd82170078f41ada2795e6eea17593fa90cbf5290a1095e299fc7f507f360f187cd", ++ "5ec4ac45d48fc15c72471d795066bdf8e99a483d5fdd599511b9cdc408de7c0616491b73924d0266da34a495331a935c4b8884f57d7ad8cce4cbe586875aa52482215ed39d7626cce55d50349c7767981c8bd6890f132a196184247343566fc972b86fe3c5369d6a6519e9f07942f0522b77ad01c751dcf7defe31e471a0ec00963765dd8518144a3b8c3c978ad108056516a25dbe3092e73c", ++ "0d5e74b78290c689f2b3cfea45fc9b6a84c822639cd438a7f05c07c374adced42cdc12d2a9233a4ffe80307efc1ac13cb04300e165f8d90dd01c0ea955e7657332c6e86ad6b43e78ba4c13c675aed83192d8427866fb6484e6a3071b2369a46fba9005f31232da7ffec7952f831aaaddf63e225263531c2cf387f8cc14fa856c8795137142c3a52ffa69b8e30ebc88ce3bbc227597bcc8dddd89", ++ "a0fe36f983259921dc2fa7d89002b3066241d63bfc2448caf7e10522a35562be0bfedc3dce49cfce2e614a04d4c64cfc0ab898873a7fc26928dc1927c009d12f6f9b7a278205d3d0057604f4ac746f8b9287c3bc6b929832bf253b6586192ac43fdd29ba585dbd9059aab9c6ff6000a7867c67fec1457b733f6b620881166b8fed92bc8d84f0426002e7be7fcd6ee0abf3755e2babfe5636ca0b37", ++ "1d29b6d8eca793bb801becf90b7d7de215b17618ec32340da4bac707cdbb58b951d5036ec02e105d83b5960e2a72002d19b7fa8e1128cc7c5049ed1f76b82a59eac6ed09e56eb73d9ade38a6739f0e07155afa6ec0d9f5cf13c4b30f5f9a465b162a9c3ba04b5a0b3363c2a63f13f2a3b57c590ec6aa7f64f4dcf7f1582d0ca157eb3b3e53b20e306b1f24e9bda87397d413f01b453ceffeca1fb1e7", ++ "6a2860c110cd0fc5a19bcaafcd30762ee10242d34739638e716bd89fd537ea4dc630e6f85d1bd88a25ad3892ca554c232c9830bd56980c9f08d378d28f7fa6fa7df4fcbf6ad98b1adfff3ec1f63310e50f920c99a5200b8e64c2c2ca249399a149942261f737d5d72da949e914c024d57c4b639cb89990fed2b38a37e5bcd24d17ca12dfcd36ce04691fd03c32f6ed5de2a2191ed7c826375ba81f78d0", ++ "7132aa291ddc9210c60dbe7eb3c19f9053f2dd74742cf57fdc5df98312adbf4710a73245de4a0c3b24e21ab8b466a77ae29d15500d5142555ef3088cbccbe685ed9119a10755148f0b9f0dbcf02b2b9bcadc8517c88346ea4e78285e9cbab122f824cc18faf53b742a87c008bb6aa47eed8e1c8709b8c2b9adb4cc4f07fb423e5830a8e503ab4f7945a2a02ab0a019b65d4fd71dc364d07bdc6e637990e3", ++ "3e664da330f2c6007bff0d5101d88288aaacd3c07913c09e871cce16e55a39fde1ce4db6b8379977c46cce08983ca686778afe0a77a41baf447854b9aa286c398c2b83c95a127b053101b6799c1638e5efd67273b2618df6ec0b96d8d040e8c1ee01a99b9b5c8fe63fea2f749e6c90d31f6fae4e1469ac09884c4fe1a8539acb313f42c941224a0e79c059e18affc2bcb6724975c436f7bf949ebdd8aef51c", ++ "7a6ea63a271eb49470f5ce77519ed61ae9b2f1be07a96855726bc3df1d0723af3a703fdfc2e739c9d31d25814daf661a23558b50982e66ee37ad880f5c8f11c8130fac8a5d0250583700d5a324894fae6d61993f6bf9327214f8674649f355b23fd634940b2c467973a839e659169c773119919f5b81ee171edb2e5f6940d7551f9e5a70625d9ea88711ad0ed8ab2da720ad358bef954456cb2d5636425717c2", ++ "c5106bbda114168c449172e49590c7eeb827fa4e1a2a7a87a3c1f721a9047d0c0a50fbf244731be1b7eb1a2ef30f5ae846a9f38f0df44f32af61b68dbdcd0226e741dfb6ef81a2503691af5e4b3171f48c59ba4ef91eba344b5b697f261df7bbbb734ca6e6daebaa4a179feb17002823281b8534d55a6531c59305f6e3fd3fa63b747bcf0deb654c392a02fe687a269effb1238f38bcaea6b208b221c45fe7fbe7", ++ "597716a5ebeebc4bf524c15518816f0b5dcda39cc833c3d66b6368ce39f3fd02ceba8d12072bfe6137c68d3acd50c849873150928b320b4fbc31c1456679ea1d0acaeeabf666d1f1bad3e6b9312c5cbdecf9b799d3e30b0316bed5f41245107b693366accc8b2bcef2a6be54209ffabc0bb6f93377abdcd57d1b25a89e046f16d8fd00f99d1c0cd247aafa72234386ae484510c084ee609f08aad32a005a0a5710cb", ++ "0771ffe789f4135704b6970b617bae41666bc9a6939d47bd04282e140d5a861c44cf05e0aa57190f5b02e298f1431265a365d29e3127d6fccd86ec0df600e26bcdda2d8f487d2e4b38fbb20f1667591f9b5730930788f2691b9ee1564829d1ada15fffc53e785e0c5e5dd11705a5a71e390ca66f4a592785be188fefe89b4bd085b2024b22a210cb7f4a71c2ad215f082ec63746c7367c22aedb5601f513d9f1ffc1f3", ++ "be6556c94313739c115895a7bad2b620c0708e24f0390daa55521c31d2c6782acf41156271238885c367a57c72b4fe999c160e804ad58d8e565edbce14a2dd90e443eb80626b3eab9d7ab75d6f8a062d7ca89b7af8eb292c98eaf87ad1dfd0db103d1bb6188bd7e7a63502153cf3ce23d43b60c5782602bac8ad92fb2324f5a79453898c5de18415639ecc5c7974d3077f76fc1df5b956723bb19a624d7ea3ec13ba3d86", ++ "4bc33729f14cd2f1dc2ff459abee8f6860dda1062845e4adab78b53c835d106bdfa35dd9e77219eaef403d4e80488ca6bd1c93dd76ef9d543fbb7c8904dccc5f71509a6214f73d0f4e467c3e038ea639b29e7fc442ee29f57117740576188ada15a739827c647a46b0271817ab235c023c30c90f2115e5c90cd8501e7b286962fc66ffc3fe7e8978746168314908a41998bd83a1eeffda9d714b864f4d490fdeb9c7a6edfa", ++ "ab12faea205b3d3a803cf6cb32b9698c32301a1e7f7c6c23a20174c95e98b7c3cfe93fffb3c970face8f5751312a261741141b948d777b8a2ea286fe69fc8ac84d34116a4674bb09a1a0b6af90a748e511749de4697908f4acb22be08e96ebc58ab1690acf73914286c198a2b57f1dd70ea8a52325d3045b8bdfe9a09792521526b7564a2a5fcd01e291f1f8894017ce7d3e8a5dba15332fb410fcfc8d62195a48a9e7c86fc4", ++ "7d421e59a567af70594757a49809a9c22e07fe14061090b9a041875bb77933deae36c823a9b47044fa0599187c75426b6b5ed94982ab1af7882d9e952eca399ee80a8903c4bc8ebe7a0fb035b6b26a2a013536e57fa9c94b16f8c2753c9dd79fb568f638966b06da81ce87cd77ac0793b7a36c45b8687c995bf4414d28289dbee977e77bf05d931b4feaa359a397ca41be529910077c8d498e0e8fb06e8e660cc6ebf07b77a02f", ++ "0c18ab727725d62fd3a2714b7185c09faca130438eff1675b38beca7f93a6962d7b98cb300ea33067a2035cdd694348784aa2eda2f16c731eca119a050d3b3ce7d5c0fd6c234354a1da98c0642451922f670984d035f8c6f35031d6188bbeb31a95e99e21b26f6eb5e2af3c7f8eea426357b3b5f83e0029f4c4732bca366c9aa625748297f039327c276cd8d9c9bf692a47af098aa50ca97b99961bef8bc2a7a802e0b8cfdb84319", ++ "92d5909d18a8b2b9971cd1627b461e98a74ba377186a6a9df5bd133635250b300abccb2254cacb775df6d99f7c7d0952653c28e6909b9f9a45adce691f7adc1afffcd9b06e49f775364cc2c62825b9c1a86089080e26b57e732aac98d80d009bfe50df01b95205aa07ed8ec5c873da3b92d00d53af825aa64b3c634c5ece40bff152c331222d3453fd92e0ca17cef19ecb96a6eed4961b627aca48b12fecd091754f770d52ba861546", ++ "802f22e4a388e874927fef24c797408254e03910bab5bf372320207f8067f2b1ea543917d4a27df89f5bf936ba12e04302bde23119533d0976beca9e20cc16b4dbf17a2ddc44b66aba76c61ad59d5e90de02a88327ead0a8b75463a1a68e307a6e2e53ecc1986274b9ee80bc9f3140671d5285bc5fb57b281042a8978a1175900c6073fd7bd740122956602c1aa773dd2896674d0a6beab24454b107f7c847acb31a0d332b4dfc5e3f2f", ++ "3844fe65db11c92fb90bf15e2e0cd216b5b5be91604baf3b84a0ca480e41ecfaca3709b32f8c6e8761406a635b88eec91e075c48799a16ca08f295d9766d74475c47f3f2a274eae8a6ee1d191a7f37ee413a4bf42cad52acd5564a651715ae42ac2cddd52f819c692ecdef52ecb763270322cdca7bd5aef71428fa73e844568b96b43c89bf1ed42a0abf209ffad0eeec286c6f141e8af073ba4adfbbdeda253752ae36c9957dfc905b4c49", ++ "329377f7bf3c8d74991a7d61b0cf39baff5d485d79751b0d5ad017d23bec570fb19810105bab79ab5acb102ab972165224d4ec888ec7de5148077fa9c1bb6820e0d91ae4e2591a21fec2f820606ce4bafc1e377f8dc3a5bd1a9e2772a57abccd0b757164d768872c91d02789545ab5b203f688d71dd08522a3fd2f5bcd7df507aebf1ca27ddff0a82afb7aa9c180008f49d1325adf97d047e77238fc75f56356de4e87d8c961575c9f6362c9", ++ "f7f269929b0d71ea8eef7120e55ccba691c582dd534692abef35c0fe9dec7dae973cd9702e5ad420d278fe0e653fdcb22fdcb63148109ec7e94f2d0750b28157dd1764376ae10fdb0a4aef3b304bd82793e0595f941226a2d72abbc929f53134dc495b0d65ced409914f94c2523f3dfbbdeeac84ae247ab5d1b9ea33dce1a808885a55be1f3683b46f4be73d9b62eec2585f690056858dfc427aabf591cd276724885bcd4c00b93bb51fb7484d", ++ "ac022309aa2c4d7fb628255b8b7fb4c3e3ae64b1cb65e0de711a6def1653d95d8088871cb8905fe8ae76423604988a8f77589f3f776dc1e4b30dbe9dd262b2187db02518a132d219bd1a06ebac13132b5164b6c420b37dd2ccee7d69b3b7fa12e54f0a53b853d490a68379ea1fa2d79762830ffb71bf86aab506b51f85c4b6a41b69325c7d0c7aa85b93b7144489d213e8f33dbb879fce22849865337b620b155cb2d2d36a68832889e30194d36d", ++ "d009c2b78a8f02e5e5dbb586ef71fc324b375092e15913ca1a5bfd22d516baadb96867bee3562e77c4a4852344a1a76c30728be5e22400b4cc41711f66754c246a520498d8c24f0205b9c873748dbeb67fe1ad099ad04cf89f4b517f0aa481136d9f6de2d727df01c6aa4099da59d4382b51e25fd47c33d9842c32b62331e50794bfe8b61b3ba9de1b8b704779c6d65edff3af00f121ab4a7ea384edabe47c6d0098a48991f387ca4444135ec59d46", ++ "c00bab36cce69899817d1425016d222d7303197ed3e3fdcac744705e7f178a1ac745968900f69299163e19b3161f3e0a4cc55aa2e4e71e0ee6ac427d1f4d14e063f68d303ddfbb18118335cfa7a6a90d99c38319ee76f7a884846a9e0b68030bf28e78bfbd56359b9368842814da42b04cb0e307d5d846dc22f049147bae31b9a956d17676a8cc348dafa3cabc2007a30e730e3894dddf9999fb8819086311f0703e141613ed6dcd7af8510e2dc435b0", ++ "c9789152a9fc29698d49ed95f09bd11b75f18a8c5615a73dbe54ae5e550027fd0ae6a8b60667040c1b12de3d1ee3f6bf061c78c951a3210effc912e19f482dd4de152063c588c44903bc11761706fd935afa040df085b08144d83d0dde32b46ab52f4fae98ac116c7ff11d7f553450c2e37b9c5f0b1dd9e0b8640a24cba6f2a5246c41f197f46e3dc8a29131c79bef3351c6e277a0a34442274d546ccd058891277473d668420f121750d19cd684267405", ++ "06a15a0731ce52557e368bcbaa11ef3399299e36fb9f2eda6e5726907c1d29c5c6fc581405ba48c7e2e522206a8f128d7c1c939d1132a00bd7d6366aa82724e968964eb2e373563f607dfa649590dcf5589114df69da5547fef8d1604cc4c6de1ed5783c8746918a4dd31168d6bc8784cd0c769206bd803d6ca8557b66748770402b075ef44b38157d4c0da7c6281725a2065d087b1f7b23455fa673bdeeba45b983311c44eabe9ef4b7bde3420ae9881863", ++ "d08aacef2d7a41aec09473bd8a44f628e15addb7b9e5b77a1e09c8ab4942f379a0bfcb324d580b774666f18ae78dd36710824ff12393f059068fe4b559c53662c2b0e6c69e23785c8f32554e837ec1714bee902e60737b639dd933af4f68cb9d7de77e1f3b28e5b122891afce62b79acd5b1ab4ba411662cc77d806449e69c5a45a143b742d98ac84a0826d68433b9b700ace6cd472ba2d58a90847f42ce9c43f38ffc017db4bf40450b2eee1f4594dc740c0f", ++ "6a6058b0a498b7ea76a93c646eb9b8629f0cba4a0c726420c5f67ba9b0412cade356abdf0a4fb94384bad32ce0d5dd9e23dcaae1d6f28ff8683616b30f1392890c67b3a2c04b360893b801f127e527e4da82e239f4c878da13f4a4f1c76db07190e77ec123995168102fb274434a2d1e12913b9b5cbab4aacaad2bd89d88b3ca2b8e60dacf7c22c9379097ff60880f552e320ca3b571994f52534470feee2b39e0dadb5cd88257a3e459a4cc6f12f17b8d54e1bb", ++ "adeced01fc5671531cbb45679f5ddd42b3a95151677b6125aaf6f5e8f82fbabaa5ecf7c3552c2458587224f0042870f178f5fca5465250e75d71352e652eeed23cdb7f915f5ebb44099b6db116ca1be45530ac8ed32b7f161d60ed4397ad3d7d649ae6bf75ca5bec891d8e595605be9764f3a03965e1fe0eaffbf212e3df4f0fa35e08ff9d0091e6d4ac4748edfe43b611085a6ffec163014655fdd839fd9e81b63b1fa8cae4ec335ec343289758e389a79ceedfae", ++ "d014592f3a83ba40af366f137c674724916c3cdd3f6cf9d4c5c7c8d6d51ebf26e315e2c12b3546be56fb52382904046ecbd2f5b883aa4ff473de6f0c26ab862c3fa34bf3d880cc1911ce39a4088c6617c179dc5faf68a2c488bbde12d67b50f73abcfab0e3b062e68c95363e11f5f1de8ec36ed01ea21442518089045df67d346135283ad5b3fff80cf57f20876849f6db9fa139728358415a90610f69ec720fc92d8234e3e122551e9df2c644c4a2c4e3734d07de8e", ++ "c0d0c37838873ba8757d6e41b409605043bc1635edcd731219587676d94217e9f0ab44b71de25000661ce7303b7015f45e6eaa7b7ebef92b8f4a34c902c908d2172185505fa33aca5a41be83079316cdfdd430fc2c45f505f85d867e6d516f7e1bf19c001d9f43018968aab65ec031b3801399231c83ec9e622dab5629922a6b424cab938c135ff7310501c2c02971bfd2f577e25904d1a618baf0859f77f4e8b1d0cde9544e95ec52ff710c0672fdb3d891feeea2b017", ++ "7022e7f00902219ba97baa0e940e8ac7727f58955aa068c29680fac4a16bcd812c03eeb5adbcfe867a7f7c6b5d89f4641adb9173b76a1a8438866f9b4f640ce2aedf5f1080c890bcf515b4be4e3e512352f1e5323c62ec46cb73f3d71be8235fee55a154763f7c3f9aeb61ffd28f4cd93d3310f608e2133586bf1ab3f102de96f64c68a4668de8acb2a76a7ce0cddddc8fa3df5e9d230823da16ed9ebb402d36e38e6e018795e5a71517ecab5f9ca472b9ced8ff69d2d195", ++ "acaf4baf3681ab865ab9abfae41697141ead9d5e98523c2e0e1eeb6373dd15405242a3393611e19b693cabaa4e45ac866cc66663a6e898dc73095a4132d43fb78ff7166724f06562fc6c546c78f2d5087467fcfb780478ec871ac38d9516c2f62bdb66c00218747e959b24f1f1795fafe39ee4109a1f84e3f82e96436a3f8e2c74ef1a665b0daaa459c7a80757b52c905e2fb4e30c4a3f882e87bce35d70e2925a1671205c28c89886a49e045e31434abaab4a7aed077ff22c", ++ "84cb6ec8a2da4f6c3b15edf77f9af9e44e13d67acc17b24bd4c7a33980f37050c0301ba3aa15ad92efe842cd3ebd3636cf945bb1f199fe0682037b9dacf86f162dadabfa625239c37f8b8db9901df0e618ff56fa62a57499f7ba83baebc085eaf3dda850835520344a67e09419368d81012168e5de5ea45158397af9a5c6a1657b26f319b66f816cd2c28996547d697e8df2bb163ccb9dda4d6691dffd102a13667ab9cde60ffbfb872187d9c425a7f67c1d9fffff9276ed0aeb", ++ "6a52c9bbbba454c14540b2be58230d78ecbeb391646a0c6fcce2f789086a78364b81ae85d5396d7cfa8b46bda41e3083ec5cf7b4c47dc601c8a697df52f557defca248506dbebab25657f5a561d09625b7f4b2f0119a12beeac087efc9d350a735c35d2431c1da7dda99befb17f41a3dc4da0f00bb95366be128538ce27763d81f832fe3c1d4efc07b5b08ad8dc9e65fb5e48546664e18cb2d3bb3fe1f56fa7aae718c5e3bbdeaf70e15023f6a25b72a2d177fcfd04211d40664fe", ++ "c3c4d3b31f1f5f9538923df3478c84fffaef411520a542da9a220ee4132eabb9d718b5076fb2f985485e8ba058330aed27ddfd3afa3db34aa60301088caec3d0053828c0c2bc87e2e61db5ea5a29f62fdad9c8b5fc5063ec4ee865e5b2e35fac0c7a835d5f57a1b1079833c25fc38fcb14311c54f8a3bd251bca19342d69e5785f9c2e43cf189d421c76c8e8db925d70fa0fae5ee3a28c4047c23a2b8a167ce53f35ced33bec822b88b06f41558c47d4fed1bfa3e21eb060df4d8ba1", ++ "8d55e92136992ba23856c1aea109766fc44772477efc932b3194af2265e433ed77d63b44d2a1cff2e8680eff120a430fe012f0f09c6201d546e13ad46fc4ce910eab27bb1569879abed2d9c37fae9f1267c2216ec5debcb20d4de58461a621e6ce8946899de81c0add44d35e27b7982a97f2a5e6314901caebe41dbba35f48bc9244ca6dca2bdde7306435892f287036df088633a070c2e385815ab3e2bfc1a47c05a5b9fe0e80dd6e38e4713a70c8f82bd32475eea8400c7bc67f59cf", ++ "5016284e20362610fa05ca9d789cad25f6d43263787e7e085476764ce4a8908ce99b262b375e9d106170b1bec1f473d5e777e0c1896533040e39c8c1465e07907ef5860e14e4d8310013e35f12090e0bfc687474b1f15f3dd2033a0edac5246102da4deec7e188c3517d84d9c2a0a4497a4c5f82a30f1ba009e45ee6eb3ab4368c720ea6feee428ffd2c4cc52debb8d634a64176572c72368f94a66689f23f8a01218f532117af5a8060d140e7ca435a92882fcb5630ebe14a4805f1dc83", ++ "05456ec59b8d41bbd736727976b96b38c43827f9e16169be673ff37870c2ecd5f0d1ea1a136be4cc7b047a02a4421d484fd2a12ece418e42ee391a13a0b1df5a0162b29ab70d3fe3e04ba6ab26b37d62b7cf05a5e2f033611bf970b8e1f30e198e483e740fa9618c1e8677e07b61296b94a9787a68fba622d7653b5568f4a8628025939b0f74389ea8fced6098c065bf2a869fd8e07d705eadb53006be2abb716a3114ceb0236d7e916f037cb954cf977720855d12be76d900ca124a2a66bb", ++ "eb6f60b83fcee77060ff346aaf6ec34d82a8af469947d3b5074cde8eb26566eb1fa039bcc707738df1e95869bd827c246e88436f0614d9834ead5392ef376105c4a9f370071cdeaaff6ca0f18b74c3a48d19a717253c49bd9009ccbfdd5728a08b7d112a2ed8dbafbbb46d7a75dc9a05e09bfde1a0a92d74a51887f9d123d7896e9f9d0057b660ed7d55454c069d3c5260411db4cdc67e7b74f680d7ac4b9dcc2f8baf72e15e6b3cafebcdf449a6436ed2c398b675f79c644747c57553bf7ea2", ++ "187a88e88514f6c4157c1ba40b442baae1ae563a6c989277443b12a219aa484cb9fa8adbb9a29d429f50155321b15664926317477079c7060dfdaa84c1d74bba78892c34e6f21ad35208d2ae622012401696bff5cd57b6485944b3db7b9071fa5f57fbfb1085d91bb9cff5808d662cdc6c8157249478262c44b7fbc397ed42a4977b202e817717bfccc9f0467294062313f7705251ed09573f16d23429361fada259dfb300369c4198f07341b38e84d02cdb74af5de6aab1fc2026208ea7c418c0", ++ "be31bc96606d0fab007e5caeded2f1c9f747c759777e9b6eef962bed49e45a1d4fc993e279d024915e600865ecb087b960584be18c41114d3c43f92169b9e0e1f85a0ebcd4e196376ccdc920e66103cd3b1c58407d0aafd0e003c4e341a1daddb9f4faba974362a32f35db83384b05ae8e3322d728893861afd8b1c940de5a17f691e763ce4969b6d94f67fb4a0235d100225bd8602f291388f0ca4a568748ad0d6040f1262eac2aede6cd27419bb78a394c1ffad72c262be8c3f9d9619d633e51d0", ++ "4d83d85ca838b4518588f2a90228a4dd18f14dd5b4c012d26298a97d848abbd825d221d02cceb6e8c701b4ad00e1dee4889b5c533e4bb60f1f41a4a61ee5478be2c1b1016c30345afd7a5253668260515e70751f22c8b4022d7fe4877d7bbce90b46531507dd3e89549e7fd58ea28f4cb23d33662bd003c1345ba94cc4b06867f778957901a8c441bee0f3b12e16463a51f7e50690356971dd73a686a49fda1eae46c9d54fba262811d698025d0ee053f1c58591c3bb3cbde69de0b31549ef5b69cf10", ++ "cdeb07d36dc5f9a1cd717a9e9cca37a2ce93caa298eee63571f7d6c5fde2a11c666cf53cf2dcb41ca2ea2319e7230ca68e38c647905928713a13982bf47fe33d7095ebd50b2df976208920a43eb2e29b942f32467403c45cea18bf44e0f6aeb155b48a8e5c471fec972a9d62f7ae093d2758f0aaec7ca50cb4725bfa219f1a3a46ad6bde7361f445f86b94d66b8ece080e56c510250693a5d0ea0ae87b4421860b853bcf0381eae4f1bf7c5c0472a93ad18407bc88475ab8560d344a921d3e86a02da397", ++ "a598fad52852c5d51ae3b10528fc1f722e21d44fbd42ae5acdf20e85a28532e646a223d27fd907bfd38eb8bb75175636892f8242877aab89e8c0824d368f3339ce7a82aa4e5af6db1f3b588a4d667a00f67bee37cfd2724dde06d2909fb9e58d892f4cfd2c4ca85acdf8256f5458b030a6bda151154ff2e6d7a8da90b54a2884c8a99fab5a4ac211ff23dc0975f4f592fd1b6b9dc7783bdcd2d4ca4e68d2902f2013e122cb62e2bff6b0a98ec55ba25837e21f1cfe67739b568d43e6413dab2bd1dc471e5a", ++ "17b68c74c9fe4926e8102070916a4e381b9fe25f5973c9bd4b04ce25749fc18931f37a65a356d3f5e5a1ef125d546f4f0ea797c15fb2efea6fbfcc5739c564693d47adeb12dcb3d98a2830719b13247792cb2491dca159a28138c6cff925aca42f4fdb02e73fbd508ec49b25c60703a7595a3e8f44b155b371d525e48e7e5dc84ac7b17c52bf5e526a67e7187234a2f19f57c548c70fc0b27183df73ffa53fa58b658034c896fa791ae9a7fd2620f5e46ce84c842a6e60e9324ae4db224ffc87d9617cb85ca2", ++ "b9e4267ea39e1de1fed0579f93bb351007c9f8fcdd811053fae33f09e2753d7428f04e1a9efcd45ea701a5d87a35b3afb2e6b65365dee6ead0bbb611b7797b212ac688653f542e604a39df277f12514ddfee3b4e27b98395c2cd97a203f1f1153c50327965770802ec2c9783edc428271762b275471e7ac65ac36523df28b0d7e6e6ccc7674268a132a63411fc82c0738dbb68af003b769a0bf9e6587b36476cb465350fee13f88ea355d47ffac7b0f964f4139db11b7642cb8d75fe1bc74d859b6d9e884f75ac", ++ "8ca704fe7208fe5f9c23110c0b3b4eee0ef632cae82bda68d8db2436ad409aa05cf159223586e1e6d8bdae9f316ea786809fbe7fe81ec61c61552d3a83cd6beaf652d1263862664df6aae321d0323440430f400f291c3efbe5d5c690b0cc6b0bf871b3933befb40bc870e2ee1ebb68025a2dcc11b68daadef6be29b5f21e440374301bde1e80dcfade4c9d681480e65ec494a6af48df232c3d51447b9d06be714949249c44c43cf73ed13ef0d533e770284e51369d94ae241a5fb2f163893071b2b4c118aeaf9eae", ++ "4fd8dd01012bb4df82bf42e0683f998e6f52dd9c5617bae33f867d6c0b69798cead8179346d70acc941abbbdd26e3229d5651361d2252c72ff22db2938d06ff6fc29a42fdf800ae967d06479bc7bbb8e71f40b1190a4b7189ffc9a7096cdb76d40aec424e1388e1eb7ef4ac3b34f3f089da8fda7d1927f5d775c0b2801d22dd1265c973158f640cec93edfed06dc80b20ef8c496b98289d54d46ccd205951cbb0f4e7daeb866b60bacb483411e4382b6f04d472843186bd0e31fbaa93e5c901ec028efafeb45fc551a", ++ "e9ee1b22b04b321a5fdd8301627011f583887d77560fb0f35552e207561f81e38ac58a0d0aeaf832d1ee72d913720d01f75574e9a321864fe95f4d0d8f0b8db97649a53e71e940aede5c40b4b9105daa42a6fb2811b61209247534cbaf830b07abe338d75d2f5f4eb1c3cf151e9edabe2c8d5f6fff08fac1495ef48160b100d30dcb0676700bcceb28723a29980ab0766a93abb8cb3d1963007db8458ed99b689d2a7c28c788743c80e8c1239b20982c81dadd0eed6740c65fbc4ef15c7b5569cb9fc997c6550a34b3b2", ++ "ec01e3a60964360f7f23ab0b22e021815765ad706f242265ebc19a2bb9e4eac94393952dcf61aae47682671a10f9165f0b20adf83a6706bfbdcf04c6faba6114653a35584267267873291c6fe7ff5f7695243143421509502c8875aafa9e9afe5be5ef2c851c7f35d69be5d3896000ccdbbfab5c238bb34d607cfe2d55d748880545b4aa7ca61137992925189025c62654b1f20d49c3ccd75aa73ce99cd7258dabedd6480a9f5185531fc0118beb68cc0a9cd182f6973287cf9252e12be5b619f15c25b65c71b7a316ebfd", ++ "db51a2f84704b78414093aa93708ec5e78573595c6e3a16c9e15744fa0f98ec78a1b3ed1e16f9717c01f6cab1bff0d56367ffc516c2e33261074935e0735ccf0d018744b4d28450f9a4db0dcf7ff504d3183aa967f76a507357948da9018fc38f150db53e2df6cea14466f03792f8bc11bdb5266dd6d508cde9e12ff04305c0295de29de19d491ad86e766774bb517e7e65befb1c5e2c267f013e235d8483e177214f89978b4cdc81aa7eff8b39f2825ad3a1b6ac1424e30edd49b067d770f16e74dd7a9c3af2ad74289a676", ++ "00e40f30ae3746edad0f5dd03d0e640933cf3d1694804c1e1ed6399ac36611d405196ee48f129344a8512feda16a354517871322bd5d9c6a1b592933eab531923efb393ffb23d9109cbe1075cebfa5fb917b40df028a621460ff6783c798792cb1d9635b5a6f84ec13918fa302924649b5c7fcb1f7007f0d2f06e9cfd7c27491e565a96c68a0c3644f92cd8f38857258c33801c5d537a83dfe583cba59d7eec7e394199c0a2660a62fabe3ed2099d57f315a6cd8de1a4ade29d977f15d65759cff433e5ac0c182aef3761163e1", ++ "3c5ea24d0d9b618294a263f062b2414a722be4eb10dfc346a6ec3b821d7396eba61cd6ef33618b04cd087a811f299d4606820227f16000d7c839062b96d3e3f59cd1a082448d13fc8f56b3fa7fb5f66d0350aa3b72dd7c165d590282f7da2e12cfe9e60e1796122bb8c2d40fdc2997af634b9c6b127a893dfb3467909378300db3da911be1d7b616bb8e0572433e65527e15d936500a2c60e9f9909dcf22ab5e4b6700f0238c205b4a813626fac3d945bab2637fb08203044a73d20c9a3fcf7c3fc4eb7807c3276dd5f73ce89597", ++ "9271aeeebfac46f4de85df78f1bfd36136aa8905e15835c9e1941176f71e3aa5b1b131843d40479735e23e182a2bd71f66f6149dccb7ed8c16469079dc8590bbf165374951785f4531f7e7361de62f936cfb23a2b5bdf186632e7042a0dd451fdc9b7208f923f3a5f250ae590ec348c63a16c3aacaf7379f53b5dd4152dcd40d23e683e2156e64c592ffc07e2cd6bbeebef4dd590b2f6b2bcbf08fcd111c079f5c4033adb6c17574f8756ecd87be27eff1d7c8e8d0324438d59ae171d5a17128fbcb5533d921bd044a2038a5046b33", ++ "4e3e533d5bcb15793d1b9d0468aaee801f32fdb486b11027183553a09ddbee8213924296f2815dc61577297459e834bf1c7a53f87d43782209e589b8295219ba7073a8fff18ad647fdb474fa39e1faa69911bf83438d5f64fe52f38ce6a991f25812c8f548de7bf2fdea7e9b4782beb4011d3567184c817521a2ba0ebad75b892f7f8e35d68b099827a1b08a84ec5e8125651d6f260295684d0ab1011a9209d2bdeb75128bf5364774d7df91e0746b7b08bda9185035f4f226e7d0a1946fcaa9c607a66b185d8546aac2800e85b74e67", ++ "b5d89fa2d94531093365d1259cc6fe8827fea48e6374c8b9a8c4d2209c280fa5c44958a1847222a692a59e6aa2696e6cdc8a543dd89b0ce03bc293b4e78d6ef48e1839694ccd5c65661143095c705b07e3ced84a0f5959114dd89deb956ab3fac8130eb4a878278205b801ae41a29e34146192308c4e759b374757b0c3b00319bce92a1b95a4d2ee179fd6714ff96155d26f693a5bc973f84ac8b3b91e3926276297532d98b46992a3f104c08100bf1671c43134bac280c617da711e90a0100137525375ebb12802a428885ae7fce6514a", ++ "40e3d8048fc10650cb8a7fc2e7113e26dec34f9ca2d5129cd10a8e8e44d113d61ee48c7d003e19fd307fc6debd70feb30243f298c510ccc4418355ce143066f067ad7c6de7288c3080e7ad46a23c8d34deb55a43e652fe90444ad3c57d3ec1e1c489d63ef915a24bc74a7925a0a7b1e1523f21ca8fee78df24e3d0a68d0013423db97c280799a0618229c0f2c167289a891e5c8d6661ab21285951c31710e3b5fe55f6347fe16d9b40507948a59252efeb616df83e5c098b07d0a7247cd371daff0e50491c582503fd89f79ba94d6af9ed76", ++ "1fa444de01dd3901e2b4684e3d7a799ffa02d85afd35fb30fe4c9d672837bee6dd8a3b8608b4bb5e589220ad5a854f46b46e41c6d57ad124a46beab4169ff69fee7e3838a6165e19dad8eb5d7bf53d4edd3cd2769daf219510a02fdd2afe0c0e1da3cd30fcd1aa88b68965586f07a25a1720fbd90a096ea30fc8e945e3637d7857c8a9c0ab4154ffb2000e57b5f9adfa4e4eaf8065bc3c2b2e75f495963325588785a6ce417dcddffd299873b15dcccca128d63cd4eeeadb64cda28099a9ad7c80d34844901f26b88b00b9aafeb2f90286d29d", ++ "fde0a0d9d813983bd1f55cf778a003a2023b34a555322ab280584537bc6bdd844d22a7d6066c18da83ec09f3d8d5a1aab4be0d5ce19b436052f6e259a4b49017a1f47f1fe2bf115d5bc8599fb216351c60dd6b1bedb2e6f4dcadf424b833501b6f099cbfad9e2290680fb69c25032b42a6274f7cb9b5c5950401354838a45f7cb77b95bf54718e2f3d3d9fb91eb2311903980277396398d9736d8e92fd838594ac8a537c6c529db5a8a4f89290e6ba6f20ac0e5ed6fef40901d0e0e8e3e502990811f9acaae555dd54eb1bcd96b513e2fe751bec", ++ "9f8e0caec87858599f5ab29bff86da78a841a918a023a111098687ecdf2747612d3f3809d9ca400b878bd4f92c43a1004f1c17c7f19a3cd1ce449bd2b23aff551623c37dd8c0be56bf3fd857b500c2b9f9ccea62481944090a3cf3b6ee81d9af8eeb60f65ef150f9fa4d3ed6ce4762d3d4f174ee8ccd460c25cafac0ea5ec8a6a4b2f9e8c0520cb7061155e532cb65f188b01e4b9086db951f504b060c296b326b3fc1c590498ecce594f828f4a10ea416675720ae505295d38a791bd0e93f428448a8f4c1fc0af53604a9e8255384d29ae5c334e2", ++ "33d1e683a4c97ee6bbaa5f9df1a88cb53b7f3c157b6045d70a56fda0ccbd3a1fa1f049cd564da072b53f415bf5fb843771c1d2551fd075d33377362b2f7c0645f9723123d11975991db8a2b518f02e2c7c30342a044754290bae2c77496d755e5981f12e6b0a0174280b958bf11ed628a9062775993ced04bf752ea8d165e3ac2177d7cd1b9371c44efa98f0b3e68602a839d384eec007979f46429dafb138cbc231ad928a9f65f7d66fac77416395e8f1debaaf76ec2e4e03e8674102cd26f614739f3ec9f949033df1fb97e87c2326d65aef94ed5f", ++ "180048f09d0b480887af7fd548a85abf605440c1ddde6afe4c30c30670233f7bf928f43b4681f59279ebbda5e8f8f2a1abefdee129e18ac60f9224e90b38b0aabd01308e0a27f41b6fb2ee07ee176ec9048c5fe33c3f7c791469c81f30e28170585b9f3e7e3c8c2e9d74370cb4518f13bf2dee048cbd98ffa32d85e43bcc64a626b40efb51ce712925fdd6fee006dc68b88004a81549d2121986dd1966084cd654a7c6686b3bae32afbd9625e09344e85cf9611ea08dfce835a2e5b3726e69ae8a76a97db60fcc539944ba4b1e8449e4d9802ae99fae86", ++ "13c0bc2f5eb887cd90eae426143764cf82b3545998c386007cca871890912217aa143ac4ed4ddb5a7495b704aa4de18419b8664b15bc26cfc6596a4d2ae408f98b47a566476d5802d594ba84c2f538def9d016661f6404bb2337a3932a24f6e30073a6c9c274b940c62c727242e24466084a3ea336365d71ea8fa6499c0ea8d59eea505f1126b99c795023c4963aa0d99323d0391e8701110edf551b2d3799e1063ca443f1add162156e445502ca1a052fe70c289838593b58839fc63de128a03e2bbf389e22ae0cf957fd03315ee407b096cc1cfd92dee6", ++ "6f1eb607d679efef065df08987a1174aab41bdac8aece7726dfa65805d6fff5b3d17a672d96b770dc32165f144f0f7324822a5c87563b7cd9e37a742ae83ef245d09006d91576f435a03476f509ea2936636232f66aa7f6cdf1ac187bbd1fcb8e20f8791866e60ed96c73374c12ac16795e999b891c64507d2dbd97e5fc29fac750ad27f2937cbcd29fdafccf27ab22453834d475f6186eaf975a36fad5c8bd61c21da554e1ded46c4c39765dcf5c8f5ccfb49b6a4dc562c919d0c7d8940ec536ab2448ec3c9a9c8b0e8fd4870cad9de2577c7b0c38563f355", ++ "dcdd993c94d3acbc555f464871a32c5da6f13b3d5bbc3e34429705e8ad2e76393fdd96a69a94acb652f5dc3c120d41187e9aa919669f727c4868013b0cb6acc165c1b7706c52248e15c3bf81eb6c147619467945c7c48fa14a73e7c3d5bec91706c567145342a026c9d97eff97ec672c5debb9df1a998083b0b0081d65c517b3e5634c95e347e781aa30ca1c8af815e2e494d844e847fdcb41622894a518dc36571123a40bfdbe8c4f4cff44d83c61dd9dcd24c464c53b395edb31efee9f3aa080e87cdc3d22d613ae84a53c9249c32c96f9a3bc4629bb126a70", ++ "49971f9823e63c3a72574d977953329e813b22a8387cd13f56d8ea77a5d1a8a20012632d1d8732bbcb9f756b9675aab5db927beacab7ca263e5718b8dfa7b2eed9a91bf5ed163b16139d45f7b8cc7e3f7bdda6202106f67dfb23b7c315ee3e17a09d466b1e6b13e7c7428184a979f5358667b4fa8bd40bcc8ea46058db44587a85377ac46bf155136c09ac58cb6c27f28e17028c91e7e8f74d5b500e56293b316974f02b9d9ea205d9b6ac4cfb74eb8eb0c944577fd2f41316368307beab3e327bf7dbaa0a4428836ec4e895dea635234abeaf113ceeadac33c7a3", ++ "c57a9cc958cee983599b04fe694f15fb470fcbc53e4bfcc00a27351b12d5d2434444253ad4184e87b81b738922ffd7ff1dc1e54f39c5518b49fb8fe50d63e3935f99e4bd125e8dc0ba8a17fd62de709339a43fabe15cf86d96a54010112170c340cfac4132182eed7301402bc7c8276089dec38488af145cb6222525894658f03501204b7a66aba0be1b557b28a2f652d66f7313ed825ecc4d8596c1be7420d4425b86a1a90a5b7f30d0f24e0d1aae0eb619ca457a71699e44be612a4011c597ee80b94d5507e429d7fc6af22579cd6ad642723b05ef169fade526fb", ++ "0568a672cd1ecbaa947045b712e2ac27995392fbef8f9488f79803cbee561c212287f080eca95adb5ba42739d78e3ba667f06045d87850d3a0499358649caa257ad29f1a9c511e7054db20554d15cbb55ff854afa45cae475c729cea72ede953522031865bc02b95589ed4d9841c552a8cc94904a93ed09ed77222f6c178195056be59bc4e96a815adf534e6b466fb47e262ff79c803c157a21b6e2269c2e0abeb494113cd868d8466e82d4b2f6a28b73645853d96bc9242515d803e33294848d3fe42fdff68da53c03491636beede47ff1399dd3d54a5e914d55d7adf", ++ "3f19f61a4cd085796731ac9f85a75a8bce77031932c31762d87d8b8d07b8bd19ff78d6b7d1bd1e87f3a4f41aad03b6c4d17a6cbc86be55f7c8b88ada047bb04f8d49f1c34bcf81cc0f3389ad01a758fc7eeb0072aa9ad1481992bfdde82e438e75590a4423832dfbe3756e2229ea873bc3606e6d72174cb2163bf40b5d49c81009dab85ecc03e311351bbf96e32c030a2b276a7698cb25bc2c967acb3213161a1fdde7d912cd6a804490f8056c47da1333f6e35c41e749c2c23919cb9af5eec5652e6e072b034fb1682e9aaa194a9c0bd456ea0b008d14dbce37967a7a8e", ++ "705f98f632d99d3651793825c38dc4deda56c59eac539da6a0159c83131cf8ab6f2ee0c3b74111fde351f7aa1a8c500a0cecab17c212d2c58ca09eae608c8eefc922b9902ef8d6832f799ba48c3c28aa702b3242107edeba01daafe424406a3822965056cfe8783455a671e93b1e2eae2321364f1871471c82124df33bc09e1b52882bd7e1c4c7d0b2f3dd4a28c2a002a43246768af0700f9659de99d62167be93177aabf19d678e79e9c726ac510d94e74873eda99620a3961930cd91937c88a06d8153d64fd60da7ca38cf26d1d4f04a0df273f52127c53fdc593f0f8df9", ++ "ea6f8e977c954657b45f25480ff42c36c7a10c77caa26eb1c907062e24fbca5aebc65cacca0de10abea8c78322f08672e13d8ac16996eca1aa17402eaea4c1cc6c800b22dc18cb8d620192d74bac02c07b5cfa61e513c7f28b7e29b9700e0e442720bf4c669d4995da19d19f841d9eb68cc74153592591e3bf059ef616b95305aa453b32fe99a91afb35bd482cf2b7aa42702837a53be3c38883d2963020e347556f841254ec6b85854485fe8c520b05f2ea67a9bf3981555c20991e2bacd4db5b418228b6002d8d41c025cb472bf5443aaa885974a408ea7f2e3f932c600deb", ++ "408190134ed06556811b1af808ab2d986aff152a28de2c41a2207c0ccc18125ac20f48384de89ea7c80cda1da14e60cc1599943646b4c0082bbcda2d9fa55a13e9df2934edf15eb4fd41f25fa3dd706ab6de522ed351b106321e494e7a27d5f7caf44ec6fadf1122d227eefc0f57aefc140d2c63d07dcbfd65790b1099745ed042cfd1548242076b98e616b76ff0d53db5179df8dd62c06a36a8b9e95a671e2a9b9dd3fb187a31ae5828d218ec5851913e0b52e2532bd4bf9e7b349f32de2b6d5d3cdf9f372d49617b6220c93c05962327e99a0480488443349f0fd54c1860f7c8", ++ "5f9e5c6f38573a85010a9d84d33f29c057003b2645e3ea6f72cbc7af95d197ce6a06b13fea81722853e6991791b8b15091cd066f5ed913592ed3d3af5370d39ba22beeb2a582a414b16824b77e194a094c2afdcc09aa73ce36f4943cca5ae32c5017dc398801dd92a47382d9327c9f6cffd38ca4167cd836f7855fc5ff048d8efba378cdde224905a0425e6b1de061fc951c5e624a5153b008ad41160a710b3ff2081748d5e02deb9f841f4fc6cf4a15153dd4fe874fd447482696283e79ee0e6bc8c1c0409baa5ab02c5209c319e3169b2476149c0c6e541c6197ca46e004eef533", ++ "218c6b3508aec69574f2b5039b30b942b72a8349d05f48ff945bbbe5c8957d5a6199492a6bf54bab821c9377e2edfa4c908384664d2c80112d5e805d66e0a551b941021be17dd20bd825bea9a3b6afb1b8c605805b3bda58750f03ea5c953a698494b425d8980c69f34d1c3f6b5866e8717031152a127215c256e08873c21b0f5cc85875d0f7c94601659150c04cd5fe5d381ba29983a2d94fcd3a65a94c53c7279cd000dddd4253d8cff8d7f6ace10247fe3bc30d63ba4bb54f557b3d22a3924369430d71ab37b701e9500bda70b5a643704858beed4726a889b6c9c91584194c68f1", ++ "dac26aa7273fc25d6e044c79fc2bfa46e59892a42bbca59a86826c91e76ab03e4bd9f7c0b5f08d1931d88b36ea77d94f7ba67cd4f1d3086e529427201119096ae066ae6f170940830ed7900de7bb9d66e09788287403a4ecc93c6da975d2fb08e918840a236c15f5d3a8f7375c2eeebbf6f01a6e7f29ca2b8d42df158414c320777433663c59fdcd1f39ca68e3473db721be7ce8c6dba5fddc024f94fedb286b0477581d451313ca8c737484daf60d67f9b2d56d4bcc271f7e9ae958c7f258efbc74d25753e0516f28282461941bf2dcc7dd8c7df6173b89760cefcac07190243ff863fb", ++ "c46e6512e6797cc7a54254a1b26b2de29aa83d6c4b1ea5a2786fbcec388270625b12635eae39e1fba013f8a65219421bca8b52a8ddfd431cda60299bdf160734d5a7450ec79620058522702174ae451b9bfa7c4a455fbbee3e1d048c7d4bac5131018228f137c8e130440c7059b4f15eaa34ce872a851a16ce86f982df78a00be4d564da2003a450ddee9ab43ea876b8b4b65c84f0b39265fd5456417afb5bc54997c986e66fc222f2123ba5e719c4d6b9a177b188277df384f1125821cf19d5248cef0be183ccdc84ac194506f740ed2188b2689ea4c9236a9e9e3a2fff85b6af4e9b49a3", ++ "1ccd4d278d67b65cf2564ecd4de1b55fe07adc80e1f735fe2f08ea53fd3977323689122c29c798957abaff6aba09bdcbf661d77f4dc8913ab1fe2bef38846166e3834785e7105d746484eff8c656af5d8c7854abc1c62b7fadb65521dc6f793d978bda9838eb3800417d32e8a24d8c8cb1d18a5de6ca79d9e1b0ff9aa25e6218fe944cf18666fecc1e31334b390260dbe0997539e1b02f6366b2aea4f4a21efe04f4b97568fcb39e59919d5ebac6543d5d0f48fc66b923c34aac377dc95c20329b837b6ed5e8d9a3d2089cd0d8f025658006ff41cbdaccca618822ca590ab155253f8bc1c7f5", ++ "9875209588395ee3c9fdd793fd48717cc84c8c3ea622b2ccc4a1be4448e6034b7810569855255031f10be5ffd714b05f9ce01972d712d40abf03d4d0ce175813a7a668f761324996093fc2aa5912f7fc2abdadd8775d2b4d9ad492216293381460ed8f6db3d641d1525f4242c348bbfe504c704f215dc461de51b5c75c1aae967936963848f16c673eca5e78dfd47eb19001d52d1bcf96c98956dad5ddf594a5da757e7ca35f2f69803b784e66ac5a58b75c228b8266ec592505e5d1ca87d81225738855f15bc0914677e81593fd409e77d159f8a908f67788de9eb06c5561547aada96c47c535", ++ "40c90e375e366f3756d89091eb3eed9fe0fbfc5638700af4617d358812bac53124a2205dd6756456787d49cd6a35e302479a0992288f47532e4ea7ab62fc5ad5adc690a5d9a446f7e035ad4641bd8dae83946aee3338ec984ccb5cc633e1409f2531eeffe05532a8b0062ba99454c9aeabf8ecb94db195af7032bfebc22912f49d39330add47ff8fa5720612d697f0b602738930e060a1bb214efc5e292224cf34e29deaea6b1b1ff847e94ecc997325ac38df61db45d82bf0e74a664d2fe085c20b04c39e90d6a170b68d2f1d373f00c731c524456ada73d659aaac9df3191a7a3865083343fc13", ++ "e8800d82e072210ca6d7fa2472028974780b76aad4bcb9ad362422dd05ae3232668251d164daa375a43b26a38cce28dbeb3dee1a4a579f70d0fe7febb29b5ece8aa836e050fb3d188c63aa9c3c0da6c717d86458a6096b5effceb964efdec7035960c09ccd10dea3c5f1c7f9f478d5887ebbe2e15c5ff85dbacbc444bb951c4eec7abecb89ed80187e409e2972ffe1a5f01562af109f2cf09471cf72cf83a3bb8f4e2ef38ed0e326b698296394e5b2718a5000c01425708e8ad0461e62462d8819c2377f13ab1be2c7c9f33dc06fe23cad27b87569f2ce2e56e4b2c60c7b1b3d370841d89ebdc1f192", ++ "796d6d1447d5b7e8c55cd8b2f8b7010db39f27565f907e3fc0e464ea2d4bb52b37f10e7c6dcfc59231b9cdee12c32aeb4adbc42b86e86eb6defb5b69e6ca75e1f4d0dae3e124e5a1b8b6697f7e10b0403f1f0a5ff848eef3752837a9ba17780f16a9a709188a8d5b89a2fa74adb2e651163b1c2b3d261e225c9158dcd9eb7ac3d6704cee290cdff6bcb3cb90cee030aa0d19d4693655c3c30ac6fc06d2ae37787c47126d57ed9a6bef5f8a6c56859aefc08755739a95aac57a4dd916a92ba9f3afbf969df8085949615033365c751a9a3e1a18cee98a69d22e64009bebf8307169b6c61de0617ecfafdf", ++ "4f9057183566153cf337b07c3f5556006de54c56b2a1e5326c07aaeabd1886ec6f1641358925db232b2f0dbf75229c796a7395b2f934c1f99090bec1123f3c841b1cb3c5b1ec42ed5408f2940f0c48a9470b852c46d6557853d459cecd2c32bbcd8ee21fa11e385eef0857cba4d8545a61b52a484cdd779db4739fbc7aa9860dcabe0488b98fa0b60c3f7d6153db279000a52ffb573dab37d2ab1896a90e5deb7ac6bbe56239085c325d83a917dc6e8a448425b718c2356b9f3066163555ec444f372e184e02c8c4c69b1c1c2ae2b51e45b98f73d933d18750968945ca85d6bbb22014b4c4015262e3c40d", ++ "79dcca7d8b81a61359e4aece21f3df7b99518ce70bd2f57a18bab5e7114af2add0a0cea7f319d69f231f060e0a539d9a23fb3e95451ce8c6340cfb09edf931df84203a39226dd9eb278f11b691ef612585b973daab373e65d11325898badf6732100371fd759960fa8fec373268421d28bffdb9b12a430b92fe4b07566ca0c89e616e49f8fc75ccd9cdc66db820d7c02e109aa5ed86b89770262918a518f90a2292f6b68d68ae03992e4259a17a23c84ec2a417f082b5abf3a26e44d2278ecb8ba9456965303a75f25394d1aaf5544590e74b14d8a4cc4050be2b0ebcfe4d2db6b12a02c68a3bcdda70301f3", ++ "848755dc31e25e9a42f9ec12d847d19f292c14c162c9aba49e972cb123b58b8e57bb263a923929833373858594ff52dbc298dbbc078599194e4c07b0e5fc1e10808bbacdb6e93c72b333685cf961f28eb0d5a395c63266b01f130d25db384b356e5da6d01042fc2359581b89c63b3bb2d1ce897fbc9e83fe85d9666cb60e6a8c657f70caad5387b8a045bf91095606802c8424ea8ac52ef29386dc46183378a5fcb2cb927428b8c070f1c42aafd3bc70ca25437807696a46873cfeb7b80ba2ebc3c4272443d445e46343a1465253a9eebd532a0d1d2c18264b91ff45159f245404ae9335f2af55c802772426b4", ++ "ecaa6e999ef355a0768730edb835db411829a3764f79d764bb5682af6d00f51b313e017b83fffe2e332cd4a3de0a81d6a52084d5748346a1f81eb9b183ff6d93d05edc00e938d001c90872dfe234e8dd085f639af168af4a07e18f1c56ca6c7c1addffc4a70eb4660666dda0321636c3f83479ad3b64e23d749620413a2ecdcc52ad4e6e63f2b817ce99c15b5d2da3792721d7158297cce65e0c04fe810d7e2434b969e4c7892b3840623e153576356e9a696fd9e7a801c25de621a7849da3f99158d3d09bf039f43c510c8ffb00fa3e9a3c12d2c8062dd25b8dabe53d8581e30427e81c3dfc2d455352487e1255", ++ "23a3fe80e3636313fdf922a1359514d9f31775e1adf24285e8001c04dbce866df055edf25b506e18953492a173ba5aa0c1ec758123406a97025ba9b6b7a97eb14734424d1a7841ec0eaeba0051d6e9734263bea1af9895a3b8c83d8c854da2ae7832bdd7c285b73f8113c3821cced38b3656b4e6369a9f8327cd368f04128f1d78b6b4260f55995277feffa15e34532cd0306c1f47354667c17018ee012a791af2dbbc7afc92c388008c601740cccbbe66f1eb06ea657e9d478066c2bd2093ab62cd94abadc002722f50968e8acf361658fc64f50685a5b1b004888b3b4f64a4ddb67bec7e4ac64c9ee8deeda896b9", ++ "758f3567cd992228386a1c01930f7c52a9dcce28fdc1aaa54b0fed97d9a54f1df805f31bac12d559e90a2063cd7df8311a148f6904f78c5440f75e49877c0c0855d59c7f7ee52837e6ef3e54a568a7b38a0d5b896e298c8e46a56d24d8cabda8aeff85a622a3e7c87483ba921f34156defd185f608e2241224286e38121a162c2ba7604f68484717196f6628861a948180e8f06c6cc1ec66d032cf8d16da039cd74277cde31e535bc1692a44046e16881c954af3cd91dc49b443a3680e4bc42a954a46ebd1368b1398edd7580f935514b15c7fbfa9b40048a35122283af731f5e460aa85b66e65f49a9d158699bd2870", ++ "fe511e86971cea2b6af91b2afa898d9b067fa71780790bb409189f5debe719f405e16acf7c4306a6e6ac5cd535290efe088943b9e6c5d25bfc508023c1b105d20d57252fee8cdbddb4d34a6ec2f72e8d55be55afcafd2e922ab8c31888bec4e816d04f0b2cd23df6e04720969c5152b3563c6da37e4608554cc7b8715bc10aba6a2e3b6fbcd35408df0dd73a9076bfad32b741fcdb0edfb563b3f753508b9b26f0a91673255f9bcda2b9a120f6bfa0632b6551ca517d846a747b66ebda1b2170891ece94c19ce8bf682cc94afdf0053fba4e4f0530935c07cdd6f879c999a8c4328ef6d3e0a37974a230ada83910604337", ++ "a6024f5b959698c0de45f4f29e1803f99dc8112989c536e5a1337e281bc856ff721e986de183d7b0ea9eb61166830ae5d6d6bc857dc833ff189b52889b8e2bd3f35b4937624d9b36dc5f19db44f0772508029784c7dac9568d28609058bc437e2f79f95b12307d8a8fb042d7fd6ee910a9e8df609ede3283f958ba918a9925a0b1d0f9f9f232062315f28a52cbd60e71c09d83e0f6600f508f0ae8ad7642c080ffc618fcd2314e26f67f1529342569f6df37017f7e3b2dac32ad88d56d175ab22205ee7e3ee94720d76933a21132e110fefbb0689a3adbaa4c685f43652136d09b3a359b5c671e38f11915cb5612db2ae294", ++ "af6de0e227bd78494acb559ddf34d8a7d55a03912384831be21c38376f39cda8a864aff7a48aed758f6bdf777779a669068a75ce82a06f6b3325c855ed83daf5513a078a61f7dc6c1622a633367e5f3a33e765c8ec5d8d54f48494006fdbf8922063e5340013e312871b7f8f8e5ea439c0d4cb78e2f19dd11f010729b692c65dd0d347f0ce53de9d849224666ea2f6487f1c6f953e8f9dbfd3d6de291c3e9d045e633cfd83c89d2f2327d0b2f31f72ac1604a3db1febc5f22cad08153278047210cc2894582c251a014c652e3951593e70e52a5d7451be8924b64f85c8247dab6268d24710b39fc1c07b4ac829fbda34ed79b5", ++ "d7314e8b1ff82100b8f5870da62b61c31ab37ace9e6a7b6f7d294571523783c1fdedcbc00dd487dd6f848c34aab493507d07071b5eb59d1a2346068c7f356755fbde3d2cab67514f8c3a12d6ff9f96a977a9ac9263491bd33122a904da5386b943d35a6ba383932df07f259b6b45f69e9b27b4ca124fb3ae143d709853eed86690bc2754d5f8865c355a44b5279d8eb31cdc00f7407fb5f5b34edc57fc7ace943565da2222dc80632ccf42f2f125ceb19714ea964c2e50603c9f8960c3f27c2ed0e18a559931c4352bd7422109a28c5e145003f55c9b7c664fdc985168868950396eaf6fefc7b73d815c1aca721d7c67da632925", ++ "2928b55c0e4d0f5cb4b60af59e9a702e3d616a8cf427c8bb03981fb8c29026d8f7d89161f36c11654f9a5e8ccb703595a58d671ecdc22c6a784abe363158682be4643002a7da5c9d268a30ea9a8d4cc24f562ab59f55c2b43af7dbcecc7e5ebe7494e82d74145a1e7d442125eb0431c5ea0939b27afa47f8ca97849f341f707660c7fbe49b7a0712fbcb6f7562ae2961425f27c7779c7534ecdeb8047ff3cb89a25159f3e1cefe42f9ef16426241f2c4d62c11d7ac43c4500dfcd184436bb4ef33260366f875230f26d81613c334dbda4736ba9d1d2966502914ec01bbe72d885606ec11da7a2cb01b29d35eebedbb0ecc73ed6c35", ++ "fd993f50e8a68c7b2c7f87511ce65b93c0aa94dcbdf2c9cca93816f0f3b2ab34c62c586fc507b4900a34cf9d0517e0fe10a89d154c5419c1f5e38de00e8834fe3dc1032abdeb10729a81655a69a12856a78ca6e12110580de879b086fd6608726541cfa9616326bdd36064bc0d1e5f9c93b41278bff6a13b2494b81e238c0c45aea1b07d855e8f3fe1478e373bd9d3957cf8a5e5b9003386793d994c7c575cff2322e2428cbbaa4f47560316ae3354a7478842ff7cc5dcbacb6e871e72b36f06d63a9aaeb9044cfb7974afdc238a5816f537dcf33ee40b4e1a5eb3cff2402b46d548264e133008d284f11b7e4e450bc3c5ff9f79b9c4", ++ "8df21892f5fc303b0de4adef1970186db6fe71bb3ea3094922e13afcfabf1d0be009f36d6f6310c5f9fda51f1a946507a055b645c296370440e5e83d8e906a2fb51f2b42de8856a81a4f28a73a8825c68ea08e5e366730bce8047011cb7d6d9be8c6f4211308fad21856284d5bc47d199988e0abf5badf8693ceeed0a2d98e8ae94b7775a42925edb1f697ffbd8e806af23145054a85e071819cca4cd48875290ca65e5ee72a9a54ff9f19c10ef4adaf8d04c9a9afcc73853fc128bbebc61f78702787c966ca6e1b1a0e4dab646acdfcd3c6bf3e5cfbec5ebe3e06c8abaa1de56e48421d87c46b5c78030afcafd91f27e7d7c85eb4872b", ++ "48ec6ec520f8e593d7b3f653eb15553de246723b81a6d0c3221aaa42a37420fba98a23796338dff5f845dce6d5a449be5ecc1887356619270461087e08d05fb60433a83d7bd00c002b09ea210b428965124b9b27d9105a71c826c1a2491cfd60e4cfa86c2da0c7100a8dc1c3f2f94b280d54e01e043acf0e966200d9fa8a41daf3b9382820786c75cadbb8841a1b2be5b6cbeb64878e4a231ae063a99b4e2308960ef0c8e2a16bb3545cc43bdf171493fb89a84f47e7973dc60cf75aeeca71e0a7ebe17d161d4fb9fe009941cc438f16a5bae6c99fcad08cac486eb2a48060b023d8730bf1d82fe60a2f036e6f52a5bff95f43bbe088933f", ++ "f4d84ed3e564c102600a795eaa9b1eaf4ad12f1a4deca1d042a0a2750ddf6201db03073d8bf553cb9dde48a1b0083827a609f7242b86584cc180964ae794b12ce55661e00e36a6ba4dbc389e6a5a85f1b45df9af7ead1b0a54db56e68639b9d438a91504e82c35d40c7bc7e048a53ac0b04accd0dadf4ac9884b0ca0e3cb5ba4336e3581be4c4760a553823ffa283a1120d4e145af56a59f2533903650f0b9e9ad9fe2e8a3c3c3dd03a1fcb709032c8835324839c735b0c051d0cbd8b5d867617c11023432e4bd275d3d0eb98a0b6cf58071a5b712922f2bc751ac7c2588c447444cde2f37a8ea5ec126425bf517e0d17c9e2999f52fee14b3", ++ "2ccea21bac9c2b70d3923309cbf2d7cb7abd1fcc8b8b002688870a80029c62397350c3c898194e5deea360bb963d26d485cb7963f8167586976ec0556950b2e86135f4a2800991ce8473bfd44a3c5e937a48b5e355ba5141bccf2131a83988d9d2a9e8e7635a956105b3512c05ef708139ced51d7a4e204c12d8a49a21e8dc6de2629a2fd092326885d9f218745fe09f6d91fb6afce250a30a63689534b6be1f26899ffa3767d835cf586aa47776700f94241bc999b1e3deefe188f37ff734f5f16ee6a00914323dc7b8a143c9137cdcc5cd08ae9566f04bb2941532674c97dff6ffa5ce3405ef8e5d27ec403114253dd6394c0167d72a0044c5", ++ "2b681c6398aee63bf862770341648bbcd31d7de7903c5903fe3d9469311320bb24d914f2af0cdca199c97214c7c679dc32a2800ba484a03c010ea6be3bb9f2c87e30a98b606050b8a3f297f12b8f92caaeceb3e844652115934874e0a1ab093a73d759b53f6a6c3096940dd22c2bb96ce6820a7b9c6d71a208de9892aa6a7209b0fff56a0cafea52b952cdd6f5752cff3309d448800b4e4c878aa595595b56b12b83fcd6ca89520c7da664e449d7b4438fc455888aad5de0fad9a06eed14afd3513b5ebbffe01775549b701181bd26370764f56eba52fdb24286ad1ac0f5418a7c429f7dfc7f3168437fa8eed7a2ed7c723a485e4c3ed14dea2e07", ++ "aadfd505a89f4aade2c3018258a7e039401b1fc6a7f3d87910dddbb880d372ec8a13c70d92245de5b8e5f9a285c33b99dc82fa2b22decee72b93a72211656ad7a52696c8e570f78be28c0e427a371dafde856e8d5ed24f83b0660b51e7fac05d93a8666dfde6def59af863f80f3e5f6801182c87422203df390dcb736b8f830052a8832eeeb0b4e27e732aaf793d166b5a3ec7745aeef3766937c2b75a276bddd145f6010c29d035e343e267cb2d828436876ec3a7ebe3b6347d4172f7a99d6821ce152e039e53deb33340b324c7f068ffb94b3cde35a8eaa12d15c3806a7ad0acec3e8c7078c1d32a28fd3eec9f32cb86e4c22166ff69e83785e851", ++ "1605b8cce529a9d6262fd4390d9e4ae5e14e0adc0ec89b028ef68dd0f373ea259aaa96f2967091dd0874c0105385e9e6da9ca68297c31afa44ef834535fb302ce5b4e49edacbbdf359fe1228a8172495b3e57014c27edd58b685110980056c50c398a64f4923f2d720b4df16d75cb36b4233660694182099c35028a972519c24764fc94e18e582b24deb3491535fc06b83837c7958522800e822201d694af0bd0aa3834e17d4b1ba36f470905ae5f8bbeeb6c4c8604d8af02baa347b07086d6989867ddd5e8e8ed7740c3469bfa2810519c55c6add1332c4c54ee9097961d6741cb12a09713a0d07645f784f42f5ad94b48b836b34263130b0483f15e3", ++ "ff9c6125b2f60bfd6c2427b279df070e430075096647599bdc68c531152c58e13858b82385d78c856092d6c74106e87ccf51ac7e673936332d9b223444eaa0e762ee258d8a733d3a515ec68ed73285e5ca183ae3278b4820b0ab2797feb1e7d8cc864df585dfb5ebe02a993325a9ad5e2d7d49d3132cf66013898351d044e0fe908ccdfeeebf651983601e3673a1f92d36510c0cc19b2e75856db8e4a41f92a51efa66d6cc22e414944c2c34a5a89ccde0be76f51410824e330d8e7c613194338c93732e8aea651fca18bcf1ac1824340c5553aff1e58d4ab8d7c8842b4712021e517cd6c140f6743c69c7bee05b10a8f24050a8caa4f96d1664909c5a06", ++ "6e85c2f8e1fdc3aaeb969da1258cb504bbf0070cd03d23b3fb5ee08feea5ee2e0ee1c71a5d0f4f701b351f4e4b4d74cb1e2ae6184814f77b62d2f08134b7236ebf6b67d8a6c9f01b4248b30667c555f5d8646dbfe291151b23c9c9857e33a4d5c847be29a5ee7b402e03bac02d1a4319acc0dd8f25e9c7a266f5e5c896cc11b5b238df96a0963ae806cb277abc515c298a3e61a3036b177acf87a56ca4478c4c6d0d468913de602ec891318bbaf52c97a77c35c5b7d164816cf24e4c4b0b5f45853882f716d61eb947a45ce2efa78f1c70a918512af1ad536cbe6148083385b34e207f5f690d7a954021e4b5f4258a385fd8a87809a481f34202af4caccb82", ++ "1e9b2c454e9de3a2d723d850331037dbf54133dbe27488ff757dd255833a27d8eb8a128ad12d0978b6884e25737086a704fb289aaaccf930d5b582ab4df1f55f0c429b6875edec3fe45464fa74164be056a55e243c4222c586bec5b18f39036aa903d98180f24f83d09a454dfa1e03a60e6a3ba4613e99c35f874d790174ee48a557f4f021ade4d1b278d7997ef094569b37b3db0505951e9ee8400adaea275c6db51b325ee730c69df97745b556ae41cd98741e28aa3a49544541eeb3da1b1e8fa4e8e9100d66dd0c7f5e2c271b1ecc077de79c462b9fe4c273543ecd82a5bea63c5acc01eca5fb780c7d7c8c9fe208ae8bd50cad1769693d92c6c8649d20d8", ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2x.go b/ms_mod/golang.org/x/crypto/blake2b/blake2x.go +new file mode 100644 +index 00000000000000..52c414db0e64d7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/blake2x.go +@@ -0,0 +1,177 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blake2b ++ ++import ( ++ "encoding/binary" ++ "errors" ++ "io" ++) ++ ++// XOF defines the interface to hash functions that ++// support arbitrary-length output. ++type XOF interface { ++ // Write absorbs more data into the hash's state. It panics if called ++ // after Read. ++ io.Writer ++ ++ // Read reads more output from the hash. It returns io.EOF if the limit ++ // has been reached. ++ io.Reader ++ ++ // Clone returns a copy of the XOF in its current state. ++ Clone() XOF ++ ++ // Reset resets the XOF to its initial state. ++ Reset() ++} ++ ++// OutputLengthUnknown can be used as the size argument to NewXOF to indicate ++// the length of the output is not known in advance. ++const OutputLengthUnknown = 0 ++ ++// magicUnknownOutputLength is a magic value for the output size that indicates ++// an unknown number of output bytes. ++const magicUnknownOutputLength = (1 << 32) - 1 ++ ++// maxOutputLength is the absolute maximum number of bytes to produce when the ++// number of output bytes is unknown. ++const maxOutputLength = (1 << 32) * 64 ++ ++// NewXOF creates a new variable-output-length hash. The hash either produce a ++// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes ++// (size == OutputLengthUnknown). In the latter case, an absolute limit of ++// 256GiB applies. ++// ++// A non-nil key turns the hash into a MAC. The key must between ++// zero and 32 bytes long. ++func NewXOF(size uint32, key []byte) (XOF, error) { ++ if len(key) > Size { ++ return nil, errKeySize ++ } ++ if size == magicUnknownOutputLength { ++ // 2^32-1 indicates an unknown number of bytes and thus isn't a ++ // valid length. ++ return nil, errors.New("blake2b: XOF length too large") ++ } ++ if size == OutputLengthUnknown { ++ size = magicUnknownOutputLength ++ } ++ x := &xof{ ++ d: digest{ ++ size: Size, ++ keyLen: len(key), ++ }, ++ length: size, ++ } ++ copy(x.d.key[:], key) ++ x.Reset() ++ return x, nil ++} ++ ++type xof struct { ++ d digest ++ length uint32 ++ remaining uint64 ++ cfg, root, block [Size]byte ++ offset int ++ nodeOffset uint32 ++ readMode bool ++} ++ ++func (x *xof) Write(p []byte) (n int, err error) { ++ if x.readMode { ++ panic("blake2b: write to XOF after read") ++ } ++ return x.d.Write(p) ++} ++ ++func (x *xof) Clone() XOF { ++ clone := *x ++ return &clone ++} ++ ++func (x *xof) Reset() { ++ x.cfg[0] = byte(Size) ++ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length ++ binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length ++ x.cfg[17] = byte(Size) // inner hash size ++ ++ x.d.Reset() ++ x.d.h[1] ^= uint64(x.length) << 32 ++ ++ x.remaining = uint64(x.length) ++ if x.remaining == magicUnknownOutputLength { ++ x.remaining = maxOutputLength ++ } ++ x.offset, x.nodeOffset = 0, 0 ++ x.readMode = false ++} ++ ++func (x *xof) Read(p []byte) (n int, err error) { ++ if !x.readMode { ++ x.d.finalize(&x.root) ++ x.readMode = true ++ } ++ ++ if x.remaining == 0 { ++ return 0, io.EOF ++ } ++ ++ n = len(p) ++ if uint64(n) > x.remaining { ++ n = int(x.remaining) ++ p = p[:n] ++ } ++ ++ if x.offset > 0 { ++ blockRemaining := Size - x.offset ++ if n < blockRemaining { ++ x.offset += copy(p, x.block[x.offset:]) ++ x.remaining -= uint64(n) ++ return ++ } ++ copy(p, x.block[x.offset:]) ++ p = p[blockRemaining:] ++ x.offset = 0 ++ x.remaining -= uint64(blockRemaining) ++ } ++ ++ for len(p) >= Size { ++ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) ++ x.nodeOffset++ ++ ++ x.d.initConfig(&x.cfg) ++ x.d.Write(x.root[:]) ++ x.d.finalize(&x.block) ++ ++ copy(p, x.block[:]) ++ p = p[Size:] ++ x.remaining -= uint64(Size) ++ } ++ ++ if todo := len(p); todo > 0 { ++ if x.remaining < uint64(Size) { ++ x.cfg[0] = byte(x.remaining) ++ } ++ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) ++ x.nodeOffset++ ++ ++ x.d.initConfig(&x.cfg) ++ x.d.Write(x.root[:]) ++ x.d.finalize(&x.block) ++ ++ x.offset = copy(p, x.block[:todo]) ++ x.remaining -= uint64(todo) ++ } ++ return ++} ++ ++func (d *digest) initConfig(cfg *[Size]byte) { ++ d.offset, d.c[0], d.c[1] = 0, 0, 0 ++ for i := range d.h { ++ d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2b/register.go b/ms_mod/golang.org/x/crypto/blake2b/register.go +new file mode 100644 +index 00000000000000..9d8633963cb6e1 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2b/register.go +@@ -0,0 +1,33 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.9 ++// +build go1.9 ++ ++package blake2b ++ ++import ( ++ "crypto" ++ "hash" ++) ++ ++func init() { ++ newHash256 := func() hash.Hash { ++ h, _ := New256(nil) ++ return h ++ } ++ newHash384 := func() hash.Hash { ++ h, _ := New384(nil) ++ return h ++ } ++ ++ newHash512 := func() hash.Hash { ++ h, _ := New512(nil) ++ return h ++ } ++ ++ crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) ++ crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) ++ crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s.go +new file mode 100644 +index 00000000000000..e3f46aab3a1aff +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s.go +@@ -0,0 +1,246 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 ++// and the extendable output function (XOF) BLAKE2Xs. ++// ++// BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any ++// size between 1 and 32 bytes. ++// For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf ++// and for BLAKE2Xs see https://blake2.net/blake2x.pdf ++// ++// If you aren't sure which function you need, use BLAKE2s (Sum256 or New256). ++// If you need a secret-key MAC (message authentication code), use the New256 ++// function with a non-nil key. ++// ++// BLAKE2X is a construction to compute hash values larger than 32 bytes. It ++// can produce hash values between 0 and 65535 bytes. ++package blake2s // import "golang.org/x/crypto/blake2s" ++ ++import ( ++ "encoding/binary" ++ "errors" ++ "hash" ++) ++ ++const ( ++ // The blocksize of BLAKE2s in bytes. ++ BlockSize = 64 ++ ++ // The hash size of BLAKE2s-256 in bytes. ++ Size = 32 ++ ++ // The hash size of BLAKE2s-128 in bytes. ++ Size128 = 16 ++) ++ ++var errKeySize = errors.New("blake2s: invalid key size") ++ ++var iv = [8]uint32{ ++ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, ++ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, ++} ++ ++// Sum256 returns the BLAKE2s-256 checksum of the data. ++func Sum256(data []byte) [Size]byte { ++ var sum [Size]byte ++ checkSum(&sum, Size, data) ++ return sum ++} ++ ++// New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil ++// key turns the hash into a MAC. The key must between zero and 32 bytes long. ++// When the key is nil, the returned hash.Hash implements BinaryMarshaler ++// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. ++func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } ++ ++// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a ++// non-empty key. Note that a 128-bit digest is too small to be secure as a ++// cryptographic hash and should only be used as a MAC, thus the key argument ++// is not optional. ++func New128(key []byte) (hash.Hash, error) { ++ if len(key) == 0 { ++ return nil, errors.New("blake2s: a key is required for a 128-bit hash") ++ } ++ return newDigest(Size128, key) ++} ++ ++func newDigest(hashSize int, key []byte) (*digest, error) { ++ if len(key) > Size { ++ return nil, errKeySize ++ } ++ d := &digest{ ++ size: hashSize, ++ keyLen: len(key), ++ } ++ copy(d.key[:], key) ++ d.Reset() ++ return d, nil ++} ++ ++func checkSum(sum *[Size]byte, hashSize int, data []byte) { ++ var ( ++ h [8]uint32 ++ c [2]uint32 ++ ) ++ ++ h = iv ++ h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24) ++ ++ if length := len(data); length > BlockSize { ++ n := length &^ (BlockSize - 1) ++ if length == n { ++ n -= BlockSize ++ } ++ hashBlocks(&h, &c, 0, data[:n]) ++ data = data[n:] ++ } ++ ++ var block [BlockSize]byte ++ offset := copy(block[:], data) ++ remaining := uint32(BlockSize - offset) ++ ++ if c[0] < remaining { ++ c[1]-- ++ } ++ c[0] -= remaining ++ ++ hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) ++ ++ for i, v := range h { ++ binary.LittleEndian.PutUint32(sum[4*i:], v) ++ } ++} ++ ++type digest struct { ++ h [8]uint32 ++ c [2]uint32 ++ size int ++ block [BlockSize]byte ++ offset int ++ ++ key [BlockSize]byte ++ keyLen int ++} ++ ++const ( ++ magic = "b2s" ++ marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1 ++) ++ ++func (d *digest) MarshalBinary() ([]byte, error) { ++ if d.keyLen != 0 { ++ return nil, errors.New("crypto/blake2s: cannot marshal MACs") ++ } ++ b := make([]byte, 0, marshaledSize) ++ b = append(b, magic...) ++ for i := 0; i < 8; i++ { ++ b = appendUint32(b, d.h[i]) ++ } ++ b = appendUint32(b, d.c[0]) ++ b = appendUint32(b, d.c[1]) ++ // Maximum value for size is 32 ++ b = append(b, byte(d.size)) ++ b = append(b, d.block[:]...) ++ b = append(b, byte(d.offset)) ++ return b, nil ++} ++ ++func (d *digest) UnmarshalBinary(b []byte) error { ++ if len(b) < len(magic) || string(b[:len(magic)]) != magic { ++ return errors.New("crypto/blake2s: invalid hash state identifier") ++ } ++ if len(b) != marshaledSize { ++ return errors.New("crypto/blake2s: invalid hash state size") ++ } ++ b = b[len(magic):] ++ for i := 0; i < 8; i++ { ++ b, d.h[i] = consumeUint32(b) ++ } ++ b, d.c[0] = consumeUint32(b) ++ b, d.c[1] = consumeUint32(b) ++ d.size = int(b[0]) ++ b = b[1:] ++ copy(d.block[:], b[:BlockSize]) ++ b = b[BlockSize:] ++ d.offset = int(b[0]) ++ return nil ++} ++ ++func (d *digest) BlockSize() int { return BlockSize } ++ ++func (d *digest) Size() int { return d.size } ++ ++func (d *digest) Reset() { ++ d.h = iv ++ d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24) ++ d.offset, d.c[0], d.c[1] = 0, 0, 0 ++ if d.keyLen > 0 { ++ d.block = d.key ++ d.offset = BlockSize ++ } ++} ++ ++func (d *digest) Write(p []byte) (n int, err error) { ++ n = len(p) ++ ++ if d.offset > 0 { ++ remaining := BlockSize - d.offset ++ if n <= remaining { ++ d.offset += copy(d.block[d.offset:], p) ++ return ++ } ++ copy(d.block[d.offset:], p[:remaining]) ++ hashBlocks(&d.h, &d.c, 0, d.block[:]) ++ d.offset = 0 ++ p = p[remaining:] ++ } ++ ++ if length := len(p); length > BlockSize { ++ nn := length &^ (BlockSize - 1) ++ if length == nn { ++ nn -= BlockSize ++ } ++ hashBlocks(&d.h, &d.c, 0, p[:nn]) ++ p = p[nn:] ++ } ++ ++ d.offset += copy(d.block[:], p) ++ return ++} ++ ++func (d *digest) Sum(sum []byte) []byte { ++ var hash [Size]byte ++ d.finalize(&hash) ++ return append(sum, hash[:d.size]...) ++} ++ ++func (d *digest) finalize(hash *[Size]byte) { ++ var block [BlockSize]byte ++ h := d.h ++ c := d.c ++ ++ copy(block[:], d.block[:d.offset]) ++ remaining := uint32(BlockSize - d.offset) ++ if c[0] < remaining { ++ c[1]-- ++ } ++ c[0] -= remaining ++ ++ hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) ++ for i, v := range h { ++ binary.LittleEndian.PutUint32(hash[4*i:], v) ++ } ++} ++ ++func appendUint32(b []byte, x uint32) []byte { ++ var a [4]byte ++ binary.BigEndian.PutUint32(a[:], x) ++ return append(b, a[:]...) ++} ++ ++func consumeUint32(b []byte) ([]byte, uint32) { ++ x := binary.BigEndian.Uint32(b) ++ return b[4:], x ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go +new file mode 100644 +index 00000000000000..b4463fb4dc0e2f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go +@@ -0,0 +1,33 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build 386 && gc && !purego ++// +build 386,gc,!purego ++ ++package blake2s ++ ++import "golang.org/x/sys/cpu" ++ ++var ( ++ useSSE4 = false ++ useSSSE3 = cpu.X86.HasSSSE3 ++ useSSE2 = cpu.X86.HasSSE2 ++) ++ ++//go:noescape ++func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++ ++//go:noescape ++func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++ ++func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { ++ switch { ++ case useSSSE3: ++ hashBlocksSSSE3(h, c, flag, blocks) ++ case useSSE2: ++ hashBlocksSSE2(h, c, flag, blocks) ++ default: ++ hashBlocksGeneric(h, c, flag, blocks) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s +new file mode 100644 +index 00000000000000..603d00ca3201dc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s +@@ -0,0 +1,430 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build 386 && gc && !purego ++// +build 386,gc,!purego ++ ++#include "textflag.h" ++ ++DATA iv0<>+0x00(SB)/4, $0x6a09e667 ++DATA iv0<>+0x04(SB)/4, $0xbb67ae85 ++DATA iv0<>+0x08(SB)/4, $0x3c6ef372 ++DATA iv0<>+0x0c(SB)/4, $0xa54ff53a ++GLOBL iv0<>(SB), (NOPTR+RODATA), $16 ++ ++DATA iv1<>+0x00(SB)/4, $0x510e527f ++DATA iv1<>+0x04(SB)/4, $0x9b05688c ++DATA iv1<>+0x08(SB)/4, $0x1f83d9ab ++DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 ++GLOBL iv1<>(SB), (NOPTR+RODATA), $16 ++ ++DATA rol16<>+0x00(SB)/8, $0x0504070601000302 ++DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A ++GLOBL rol16<>(SB), (NOPTR+RODATA), $16 ++ ++DATA rol8<>+0x00(SB)/8, $0x0407060500030201 ++DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 ++GLOBL rol8<>(SB), (NOPTR+RODATA), $16 ++ ++DATA counter<>+0x00(SB)/8, $0x40 ++DATA counter<>+0x08(SB)/8, $0x0 ++GLOBL counter<>(SB), (NOPTR+RODATA), $16 ++ ++#define ROTL_SSE2(n, t, v) \ ++ MOVO v, t; \ ++ PSLLL $n, t; \ ++ PSRLL $(32-n), v; \ ++ PXOR t, v ++ ++#define ROTL_SSSE3(c, v) \ ++ PSHUFB c, v ++ ++#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ ++ PADDL m0, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(16, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m1, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(24, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v1, v1; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v3, v3; \ ++ PADDL m2, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(16, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m3, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(24, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v3, v3; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v1, v1 ++ ++#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ ++ PADDL m0, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c16, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m1, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c8, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v1, v1; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v3, v3; \ ++ PADDL m2, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c16, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m3, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c8, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v3, v3; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v1, v1 ++ ++#define PRECOMPUTE(dst, off, src, t) \ ++ MOVL 0*4(src), t; \ ++ MOVL t, 0*4+off+0(dst); \ ++ MOVL t, 9*4+off+64(dst); \ ++ MOVL t, 5*4+off+128(dst); \ ++ MOVL t, 14*4+off+192(dst); \ ++ MOVL t, 4*4+off+256(dst); \ ++ MOVL t, 2*4+off+320(dst); \ ++ MOVL t, 8*4+off+384(dst); \ ++ MOVL t, 12*4+off+448(dst); \ ++ MOVL t, 3*4+off+512(dst); \ ++ MOVL t, 15*4+off+576(dst); \ ++ MOVL 1*4(src), t; \ ++ MOVL t, 4*4+off+0(dst); \ ++ MOVL t, 8*4+off+64(dst); \ ++ MOVL t, 14*4+off+128(dst); \ ++ MOVL t, 5*4+off+192(dst); \ ++ MOVL t, 12*4+off+256(dst); \ ++ MOVL t, 11*4+off+320(dst); \ ++ MOVL t, 1*4+off+384(dst); \ ++ MOVL t, 6*4+off+448(dst); \ ++ MOVL t, 10*4+off+512(dst); \ ++ MOVL t, 3*4+off+576(dst); \ ++ MOVL 2*4(src), t; \ ++ MOVL t, 1*4+off+0(dst); \ ++ MOVL t, 13*4+off+64(dst); \ ++ MOVL t, 6*4+off+128(dst); \ ++ MOVL t, 8*4+off+192(dst); \ ++ MOVL t, 2*4+off+256(dst); \ ++ MOVL t, 0*4+off+320(dst); \ ++ MOVL t, 14*4+off+384(dst); \ ++ MOVL t, 11*4+off+448(dst); \ ++ MOVL t, 12*4+off+512(dst); \ ++ MOVL t, 4*4+off+576(dst); \ ++ MOVL 3*4(src), t; \ ++ MOVL t, 5*4+off+0(dst); \ ++ MOVL t, 15*4+off+64(dst); \ ++ MOVL t, 9*4+off+128(dst); \ ++ MOVL t, 1*4+off+192(dst); \ ++ MOVL t, 11*4+off+256(dst); \ ++ MOVL t, 7*4+off+320(dst); \ ++ MOVL t, 13*4+off+384(dst); \ ++ MOVL t, 3*4+off+448(dst); \ ++ MOVL t, 6*4+off+512(dst); \ ++ MOVL t, 10*4+off+576(dst); \ ++ MOVL 4*4(src), t; \ ++ MOVL t, 2*4+off+0(dst); \ ++ MOVL t, 1*4+off+64(dst); \ ++ MOVL t, 15*4+off+128(dst); \ ++ MOVL t, 10*4+off+192(dst); \ ++ MOVL t, 6*4+off+256(dst); \ ++ MOVL t, 8*4+off+320(dst); \ ++ MOVL t, 3*4+off+384(dst); \ ++ MOVL t, 13*4+off+448(dst); \ ++ MOVL t, 14*4+off+512(dst); \ ++ MOVL t, 5*4+off+576(dst); \ ++ MOVL 5*4(src), t; \ ++ MOVL t, 6*4+off+0(dst); \ ++ MOVL t, 11*4+off+64(dst); \ ++ MOVL t, 2*4+off+128(dst); \ ++ MOVL t, 9*4+off+192(dst); \ ++ MOVL t, 1*4+off+256(dst); \ ++ MOVL t, 13*4+off+320(dst); \ ++ MOVL t, 4*4+off+384(dst); \ ++ MOVL t, 8*4+off+448(dst); \ ++ MOVL t, 15*4+off+512(dst); \ ++ MOVL t, 7*4+off+576(dst); \ ++ MOVL 6*4(src), t; \ ++ MOVL t, 3*4+off+0(dst); \ ++ MOVL t, 7*4+off+64(dst); \ ++ MOVL t, 13*4+off+128(dst); \ ++ MOVL t, 12*4+off+192(dst); \ ++ MOVL t, 10*4+off+256(dst); \ ++ MOVL t, 1*4+off+320(dst); \ ++ MOVL t, 9*4+off+384(dst); \ ++ MOVL t, 14*4+off+448(dst); \ ++ MOVL t, 0*4+off+512(dst); \ ++ MOVL t, 6*4+off+576(dst); \ ++ MOVL 7*4(src), t; \ ++ MOVL t, 7*4+off+0(dst); \ ++ MOVL t, 14*4+off+64(dst); \ ++ MOVL t, 10*4+off+128(dst); \ ++ MOVL t, 0*4+off+192(dst); \ ++ MOVL t, 5*4+off+256(dst); \ ++ MOVL t, 9*4+off+320(dst); \ ++ MOVL t, 12*4+off+384(dst); \ ++ MOVL t, 1*4+off+448(dst); \ ++ MOVL t, 13*4+off+512(dst); \ ++ MOVL t, 2*4+off+576(dst); \ ++ MOVL 8*4(src), t; \ ++ MOVL t, 8*4+off+0(dst); \ ++ MOVL t, 5*4+off+64(dst); \ ++ MOVL t, 4*4+off+128(dst); \ ++ MOVL t, 15*4+off+192(dst); \ ++ MOVL t, 14*4+off+256(dst); \ ++ MOVL t, 3*4+off+320(dst); \ ++ MOVL t, 11*4+off+384(dst); \ ++ MOVL t, 10*4+off+448(dst); \ ++ MOVL t, 7*4+off+512(dst); \ ++ MOVL t, 1*4+off+576(dst); \ ++ MOVL 9*4(src), t; \ ++ MOVL t, 12*4+off+0(dst); \ ++ MOVL t, 2*4+off+64(dst); \ ++ MOVL t, 11*4+off+128(dst); \ ++ MOVL t, 4*4+off+192(dst); \ ++ MOVL t, 0*4+off+256(dst); \ ++ MOVL t, 15*4+off+320(dst); \ ++ MOVL t, 10*4+off+384(dst); \ ++ MOVL t, 7*4+off+448(dst); \ ++ MOVL t, 5*4+off+512(dst); \ ++ MOVL t, 9*4+off+576(dst); \ ++ MOVL 10*4(src), t; \ ++ MOVL t, 9*4+off+0(dst); \ ++ MOVL t, 4*4+off+64(dst); \ ++ MOVL t, 8*4+off+128(dst); \ ++ MOVL t, 13*4+off+192(dst); \ ++ MOVL t, 3*4+off+256(dst); \ ++ MOVL t, 5*4+off+320(dst); \ ++ MOVL t, 7*4+off+384(dst); \ ++ MOVL t, 15*4+off+448(dst); \ ++ MOVL t, 11*4+off+512(dst); \ ++ MOVL t, 0*4+off+576(dst); \ ++ MOVL 11*4(src), t; \ ++ MOVL t, 13*4+off+0(dst); \ ++ MOVL t, 10*4+off+64(dst); \ ++ MOVL t, 0*4+off+128(dst); \ ++ MOVL t, 3*4+off+192(dst); \ ++ MOVL t, 9*4+off+256(dst); \ ++ MOVL t, 6*4+off+320(dst); \ ++ MOVL t, 15*4+off+384(dst); \ ++ MOVL t, 4*4+off+448(dst); \ ++ MOVL t, 2*4+off+512(dst); \ ++ MOVL t, 12*4+off+576(dst); \ ++ MOVL 12*4(src), t; \ ++ MOVL t, 10*4+off+0(dst); \ ++ MOVL t, 12*4+off+64(dst); \ ++ MOVL t, 1*4+off+128(dst); \ ++ MOVL t, 6*4+off+192(dst); \ ++ MOVL t, 13*4+off+256(dst); \ ++ MOVL t, 4*4+off+320(dst); \ ++ MOVL t, 0*4+off+384(dst); \ ++ MOVL t, 2*4+off+448(dst); \ ++ MOVL t, 8*4+off+512(dst); \ ++ MOVL t, 14*4+off+576(dst); \ ++ MOVL 13*4(src), t; \ ++ MOVL t, 14*4+off+0(dst); \ ++ MOVL t, 3*4+off+64(dst); \ ++ MOVL t, 7*4+off+128(dst); \ ++ MOVL t, 2*4+off+192(dst); \ ++ MOVL t, 15*4+off+256(dst); \ ++ MOVL t, 12*4+off+320(dst); \ ++ MOVL t, 6*4+off+384(dst); \ ++ MOVL t, 0*4+off+448(dst); \ ++ MOVL t, 9*4+off+512(dst); \ ++ MOVL t, 11*4+off+576(dst); \ ++ MOVL 14*4(src), t; \ ++ MOVL t, 11*4+off+0(dst); \ ++ MOVL t, 0*4+off+64(dst); \ ++ MOVL t, 12*4+off+128(dst); \ ++ MOVL t, 7*4+off+192(dst); \ ++ MOVL t, 8*4+off+256(dst); \ ++ MOVL t, 14*4+off+320(dst); \ ++ MOVL t, 2*4+off+384(dst); \ ++ MOVL t, 5*4+off+448(dst); \ ++ MOVL t, 1*4+off+512(dst); \ ++ MOVL t, 13*4+off+576(dst); \ ++ MOVL 15*4(src), t; \ ++ MOVL t, 15*4+off+0(dst); \ ++ MOVL t, 6*4+off+64(dst); \ ++ MOVL t, 3*4+off+128(dst); \ ++ MOVL t, 11*4+off+192(dst); \ ++ MOVL t, 7*4+off+256(dst); \ ++ MOVL t, 10*4+off+320(dst); \ ++ MOVL t, 5*4+off+384(dst); \ ++ MOVL t, 9*4+off+448(dst); \ ++ MOVL t, 4*4+off+512(dst); \ ++ MOVL t, 8*4+off+576(dst) ++ ++// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++TEXT Β·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment ++ MOVL h+0(FP), AX ++ MOVL c+4(FP), BX ++ MOVL flag+8(FP), CX ++ MOVL blocks_base+12(FP), SI ++ MOVL blocks_len+16(FP), DX ++ ++ MOVL SP, DI ++ ADDL $15, DI ++ ANDL $~15, DI ++ ++ MOVL CX, 8(DI) ++ MOVL 0(BX), CX ++ MOVL CX, 0(DI) ++ MOVL 4(BX), CX ++ MOVL CX, 4(DI) ++ XORL CX, CX ++ MOVL CX, 12(DI) ++ ++ MOVOU 0(AX), X0 ++ MOVOU 16(AX), X1 ++ MOVOU counter<>(SB), X2 ++ ++loop: ++ MOVO X0, X4 ++ MOVO X1, X5 ++ MOVOU iv0<>(SB), X6 ++ MOVOU iv1<>(SB), X7 ++ ++ MOVO 0(DI), X3 ++ PADDQ X2, X3 ++ PXOR X3, X7 ++ MOVO X3, 0(DI) ++ ++ PRECOMPUTE(DI, 16, SI, CX) ++ ROUND_SSE2(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3) ++ ROUND_SSE2(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3) ++ ++ PXOR X4, X0 ++ PXOR X5, X1 ++ PXOR X6, X0 ++ PXOR X7, X1 ++ ++ LEAL 64(SI), SI ++ SUBL $64, DX ++ JNE loop ++ ++ MOVL 0(DI), CX ++ MOVL CX, 0(BX) ++ MOVL 4(DI), CX ++ MOVL CX, 4(BX) ++ ++ MOVOU X0, 0(AX) ++ MOVOU X1, 16(AX) ++ ++ RET ++ ++// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++TEXT Β·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment ++ MOVL h+0(FP), AX ++ MOVL c+4(FP), BX ++ MOVL flag+8(FP), CX ++ MOVL blocks_base+12(FP), SI ++ MOVL blocks_len+16(FP), DX ++ ++ MOVL SP, DI ++ ADDL $15, DI ++ ANDL $~15, DI ++ ++ MOVL CX, 8(DI) ++ MOVL 0(BX), CX ++ MOVL CX, 0(DI) ++ MOVL 4(BX), CX ++ MOVL CX, 4(DI) ++ XORL CX, CX ++ MOVL CX, 12(DI) ++ ++ MOVOU 0(AX), X0 ++ MOVOU 16(AX), X1 ++ MOVOU counter<>(SB), X2 ++ ++loop: ++ MOVO X0, 656(DI) ++ MOVO X1, 672(DI) ++ MOVO X0, X4 ++ MOVO X1, X5 ++ MOVOU iv0<>(SB), X6 ++ MOVOU iv1<>(SB), X7 ++ ++ MOVO 0(DI), X3 ++ PADDQ X2, X3 ++ PXOR X3, X7 ++ MOVO X3, 0(DI) ++ ++ MOVOU rol16<>(SB), X0 ++ MOVOU rol8<>(SB), X1 ++ ++ PRECOMPUTE(DI, 16, SI, CX) ++ ROUND_SSSE3(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3, X0, X1) ++ ROUND_SSSE3(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3, X0, X1) ++ ++ MOVO 656(DI), X0 ++ MOVO 672(DI), X1 ++ PXOR X4, X0 ++ PXOR X5, X1 ++ PXOR X6, X0 ++ PXOR X7, X1 ++ ++ LEAL 64(SI), SI ++ SUBL $64, DX ++ JNE loop ++ ++ MOVL 0(DI), CX ++ MOVL CX, 0(BX) ++ MOVL 4(DI), CX ++ MOVL CX, 4(BX) ++ ++ MOVOU X0, 0(AX) ++ MOVOU X1, 16(AX) ++ ++ RET +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go +new file mode 100644 +index 00000000000000..becdaa120ff8db +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go +@@ -0,0 +1,38 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++package blake2s ++ ++import "golang.org/x/sys/cpu" ++ ++var ( ++ useSSE4 = cpu.X86.HasSSE41 ++ useSSSE3 = cpu.X86.HasSSSE3 ++ useSSE2 = cpu.X86.HasSSE2 ++) ++ ++//go:noescape ++func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++ ++//go:noescape ++func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++ ++//go:noescape ++func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++ ++func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { ++ switch { ++ case useSSE4: ++ hashBlocksSSE4(h, c, flag, blocks) ++ case useSSSE3: ++ hashBlocksSSSE3(h, c, flag, blocks) ++ case useSSE2: ++ hashBlocksSSE2(h, c, flag, blocks) ++ default: ++ hashBlocksGeneric(h, c, flag, blocks) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s +new file mode 100644 +index 00000000000000..e9df7a7c2199e8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s +@@ -0,0 +1,433 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++#include "textflag.h" ++ ++DATA iv0<>+0x00(SB)/4, $0x6a09e667 ++DATA iv0<>+0x04(SB)/4, $0xbb67ae85 ++DATA iv0<>+0x08(SB)/4, $0x3c6ef372 ++DATA iv0<>+0x0c(SB)/4, $0xa54ff53a ++GLOBL iv0<>(SB), (NOPTR+RODATA), $16 ++ ++DATA iv1<>+0x00(SB)/4, $0x510e527f ++DATA iv1<>+0x04(SB)/4, $0x9b05688c ++DATA iv1<>+0x08(SB)/4, $0x1f83d9ab ++DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 ++GLOBL iv1<>(SB), (NOPTR+RODATA), $16 ++ ++DATA rol16<>+0x00(SB)/8, $0x0504070601000302 ++DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A ++GLOBL rol16<>(SB), (NOPTR+RODATA), $16 ++ ++DATA rol8<>+0x00(SB)/8, $0x0407060500030201 ++DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 ++GLOBL rol8<>(SB), (NOPTR+RODATA), $16 ++ ++DATA counter<>+0x00(SB)/8, $0x40 ++DATA counter<>+0x08(SB)/8, $0x0 ++GLOBL counter<>(SB), (NOPTR+RODATA), $16 ++ ++#define ROTL_SSE2(n, t, v) \ ++ MOVO v, t; \ ++ PSLLL $n, t; \ ++ PSRLL $(32-n), v; \ ++ PXOR t, v ++ ++#define ROTL_SSSE3(c, v) \ ++ PSHUFB c, v ++ ++#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ ++ PADDL m0, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(16, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m1, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(24, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v1, v1; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v3, v3; \ ++ PADDL m2, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(16, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m3, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSE2(24, t, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v3, v3; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v1, v1 ++ ++#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ ++ PADDL m0, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c16, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m1, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c8, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v1, v1; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v3, v3; \ ++ PADDL m2, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c16, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(20, t, v1); \ ++ PADDL m3, v0; \ ++ PADDL v1, v0; \ ++ PXOR v0, v3; \ ++ ROTL_SSSE3(c8, v3); \ ++ PADDL v3, v2; \ ++ PXOR v2, v1; \ ++ ROTL_SSE2(25, t, v1); \ ++ PSHUFL $0x39, v3, v3; \ ++ PSHUFL $0x4E, v2, v2; \ ++ PSHUFL $0x93, v1, v1 ++ ++ ++#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \ ++ MOVL i0*4(src), m0; \ ++ PINSRD $1, i1*4(src), m0; \ ++ PINSRD $2, i2*4(src), m0; \ ++ PINSRD $3, i3*4(src), m0; \ ++ MOVL i4*4(src), m1; \ ++ PINSRD $1, i5*4(src), m1; \ ++ PINSRD $2, i6*4(src), m1; \ ++ PINSRD $3, i7*4(src), m1; \ ++ MOVL i8*4(src), m2; \ ++ PINSRD $1, i9*4(src), m2; \ ++ PINSRD $2, i10*4(src), m2; \ ++ PINSRD $3, i11*4(src), m2; \ ++ MOVL i12*4(src), m3; \ ++ PINSRD $1, i13*4(src), m3; \ ++ PINSRD $2, i14*4(src), m3; \ ++ PINSRD $3, i15*4(src), m3 ++ ++#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \ ++ MOVQ 0*4(src), R8; \ ++ MOVQ 2*4(src), R9; \ ++ MOVQ 4*4(src), R10; \ ++ MOVQ 6*4(src), R11; \ ++ MOVQ 8*4(src), R12; \ ++ MOVQ 10*4(src), R13; \ ++ MOVQ 12*4(src), R14; \ ++ MOVQ 14*4(src), R15; \ ++ \ ++ MOVL R8, 0*4+off+0(dst); \ ++ MOVL R8, 9*4+off+64(dst); \ ++ MOVL R8, 5*4+off+128(dst); \ ++ MOVL R8, 14*4+off+192(dst); \ ++ MOVL R8, 4*4+off+256(dst); \ ++ MOVL R8, 2*4+off+320(dst); \ ++ MOVL R8, 8*4+off+384(dst); \ ++ MOVL R8, 12*4+off+448(dst); \ ++ MOVL R8, 3*4+off+512(dst); \ ++ MOVL R8, 15*4+off+576(dst); \ ++ SHRQ $32, R8; \ ++ MOVL R8, 4*4+off+0(dst); \ ++ MOVL R8, 8*4+off+64(dst); \ ++ MOVL R8, 14*4+off+128(dst); \ ++ MOVL R8, 5*4+off+192(dst); \ ++ MOVL R8, 12*4+off+256(dst); \ ++ MOVL R8, 11*4+off+320(dst); \ ++ MOVL R8, 1*4+off+384(dst); \ ++ MOVL R8, 6*4+off+448(dst); \ ++ MOVL R8, 10*4+off+512(dst); \ ++ MOVL R8, 3*4+off+576(dst); \ ++ \ ++ MOVL R9, 1*4+off+0(dst); \ ++ MOVL R9, 13*4+off+64(dst); \ ++ MOVL R9, 6*4+off+128(dst); \ ++ MOVL R9, 8*4+off+192(dst); \ ++ MOVL R9, 2*4+off+256(dst); \ ++ MOVL R9, 0*4+off+320(dst); \ ++ MOVL R9, 14*4+off+384(dst); \ ++ MOVL R9, 11*4+off+448(dst); \ ++ MOVL R9, 12*4+off+512(dst); \ ++ MOVL R9, 4*4+off+576(dst); \ ++ SHRQ $32, R9; \ ++ MOVL R9, 5*4+off+0(dst); \ ++ MOVL R9, 15*4+off+64(dst); \ ++ MOVL R9, 9*4+off+128(dst); \ ++ MOVL R9, 1*4+off+192(dst); \ ++ MOVL R9, 11*4+off+256(dst); \ ++ MOVL R9, 7*4+off+320(dst); \ ++ MOVL R9, 13*4+off+384(dst); \ ++ MOVL R9, 3*4+off+448(dst); \ ++ MOVL R9, 6*4+off+512(dst); \ ++ MOVL R9, 10*4+off+576(dst); \ ++ \ ++ MOVL R10, 2*4+off+0(dst); \ ++ MOVL R10, 1*4+off+64(dst); \ ++ MOVL R10, 15*4+off+128(dst); \ ++ MOVL R10, 10*4+off+192(dst); \ ++ MOVL R10, 6*4+off+256(dst); \ ++ MOVL R10, 8*4+off+320(dst); \ ++ MOVL R10, 3*4+off+384(dst); \ ++ MOVL R10, 13*4+off+448(dst); \ ++ MOVL R10, 14*4+off+512(dst); \ ++ MOVL R10, 5*4+off+576(dst); \ ++ SHRQ $32, R10; \ ++ MOVL R10, 6*4+off+0(dst); \ ++ MOVL R10, 11*4+off+64(dst); \ ++ MOVL R10, 2*4+off+128(dst); \ ++ MOVL R10, 9*4+off+192(dst); \ ++ MOVL R10, 1*4+off+256(dst); \ ++ MOVL R10, 13*4+off+320(dst); \ ++ MOVL R10, 4*4+off+384(dst); \ ++ MOVL R10, 8*4+off+448(dst); \ ++ MOVL R10, 15*4+off+512(dst); \ ++ MOVL R10, 7*4+off+576(dst); \ ++ \ ++ MOVL R11, 3*4+off+0(dst); \ ++ MOVL R11, 7*4+off+64(dst); \ ++ MOVL R11, 13*4+off+128(dst); \ ++ MOVL R11, 12*4+off+192(dst); \ ++ MOVL R11, 10*4+off+256(dst); \ ++ MOVL R11, 1*4+off+320(dst); \ ++ MOVL R11, 9*4+off+384(dst); \ ++ MOVL R11, 14*4+off+448(dst); \ ++ MOVL R11, 0*4+off+512(dst); \ ++ MOVL R11, 6*4+off+576(dst); \ ++ SHRQ $32, R11; \ ++ MOVL R11, 7*4+off+0(dst); \ ++ MOVL R11, 14*4+off+64(dst); \ ++ MOVL R11, 10*4+off+128(dst); \ ++ MOVL R11, 0*4+off+192(dst); \ ++ MOVL R11, 5*4+off+256(dst); \ ++ MOVL R11, 9*4+off+320(dst); \ ++ MOVL R11, 12*4+off+384(dst); \ ++ MOVL R11, 1*4+off+448(dst); \ ++ MOVL R11, 13*4+off+512(dst); \ ++ MOVL R11, 2*4+off+576(dst); \ ++ \ ++ MOVL R12, 8*4+off+0(dst); \ ++ MOVL R12, 5*4+off+64(dst); \ ++ MOVL R12, 4*4+off+128(dst); \ ++ MOVL R12, 15*4+off+192(dst); \ ++ MOVL R12, 14*4+off+256(dst); \ ++ MOVL R12, 3*4+off+320(dst); \ ++ MOVL R12, 11*4+off+384(dst); \ ++ MOVL R12, 10*4+off+448(dst); \ ++ MOVL R12, 7*4+off+512(dst); \ ++ MOVL R12, 1*4+off+576(dst); \ ++ SHRQ $32, R12; \ ++ MOVL R12, 12*4+off+0(dst); \ ++ MOVL R12, 2*4+off+64(dst); \ ++ MOVL R12, 11*4+off+128(dst); \ ++ MOVL R12, 4*4+off+192(dst); \ ++ MOVL R12, 0*4+off+256(dst); \ ++ MOVL R12, 15*4+off+320(dst); \ ++ MOVL R12, 10*4+off+384(dst); \ ++ MOVL R12, 7*4+off+448(dst); \ ++ MOVL R12, 5*4+off+512(dst); \ ++ MOVL R12, 9*4+off+576(dst); \ ++ \ ++ MOVL R13, 9*4+off+0(dst); \ ++ MOVL R13, 4*4+off+64(dst); \ ++ MOVL R13, 8*4+off+128(dst); \ ++ MOVL R13, 13*4+off+192(dst); \ ++ MOVL R13, 3*4+off+256(dst); \ ++ MOVL R13, 5*4+off+320(dst); \ ++ MOVL R13, 7*4+off+384(dst); \ ++ MOVL R13, 15*4+off+448(dst); \ ++ MOVL R13, 11*4+off+512(dst); \ ++ MOVL R13, 0*4+off+576(dst); \ ++ SHRQ $32, R13; \ ++ MOVL R13, 13*4+off+0(dst); \ ++ MOVL R13, 10*4+off+64(dst); \ ++ MOVL R13, 0*4+off+128(dst); \ ++ MOVL R13, 3*4+off+192(dst); \ ++ MOVL R13, 9*4+off+256(dst); \ ++ MOVL R13, 6*4+off+320(dst); \ ++ MOVL R13, 15*4+off+384(dst); \ ++ MOVL R13, 4*4+off+448(dst); \ ++ MOVL R13, 2*4+off+512(dst); \ ++ MOVL R13, 12*4+off+576(dst); \ ++ \ ++ MOVL R14, 10*4+off+0(dst); \ ++ MOVL R14, 12*4+off+64(dst); \ ++ MOVL R14, 1*4+off+128(dst); \ ++ MOVL R14, 6*4+off+192(dst); \ ++ MOVL R14, 13*4+off+256(dst); \ ++ MOVL R14, 4*4+off+320(dst); \ ++ MOVL R14, 0*4+off+384(dst); \ ++ MOVL R14, 2*4+off+448(dst); \ ++ MOVL R14, 8*4+off+512(dst); \ ++ MOVL R14, 14*4+off+576(dst); \ ++ SHRQ $32, R14; \ ++ MOVL R14, 14*4+off+0(dst); \ ++ MOVL R14, 3*4+off+64(dst); \ ++ MOVL R14, 7*4+off+128(dst); \ ++ MOVL R14, 2*4+off+192(dst); \ ++ MOVL R14, 15*4+off+256(dst); \ ++ MOVL R14, 12*4+off+320(dst); \ ++ MOVL R14, 6*4+off+384(dst); \ ++ MOVL R14, 0*4+off+448(dst); \ ++ MOVL R14, 9*4+off+512(dst); \ ++ MOVL R14, 11*4+off+576(dst); \ ++ \ ++ MOVL R15, 11*4+off+0(dst); \ ++ MOVL R15, 0*4+off+64(dst); \ ++ MOVL R15, 12*4+off+128(dst); \ ++ MOVL R15, 7*4+off+192(dst); \ ++ MOVL R15, 8*4+off+256(dst); \ ++ MOVL R15, 14*4+off+320(dst); \ ++ MOVL R15, 2*4+off+384(dst); \ ++ MOVL R15, 5*4+off+448(dst); \ ++ MOVL R15, 1*4+off+512(dst); \ ++ MOVL R15, 13*4+off+576(dst); \ ++ SHRQ $32, R15; \ ++ MOVL R15, 15*4+off+0(dst); \ ++ MOVL R15, 6*4+off+64(dst); \ ++ MOVL R15, 3*4+off+128(dst); \ ++ MOVL R15, 11*4+off+192(dst); \ ++ MOVL R15, 7*4+off+256(dst); \ ++ MOVL R15, 10*4+off+320(dst); \ ++ MOVL R15, 5*4+off+384(dst); \ ++ MOVL R15, 9*4+off+448(dst); \ ++ MOVL R15, 4*4+off+512(dst); \ ++ MOVL R15, 8*4+off+576(dst) ++ ++#define BLAKE2s_SSE2() \ ++ PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8); \ ++ ROUND_SSE2(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8) ++ ++#define BLAKE2s_SSSE3() \ ++ PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8, X13, X14); \ ++ ROUND_SSSE3(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8, X13, X14) ++ ++#define BLAKE2s_SSE4() \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ ++ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \ ++ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) ++ ++#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \ ++ MOVQ h, AX; \ ++ MOVQ c, BX; \ ++ MOVL flag, CX; \ ++ MOVQ blocks_base, SI; \ ++ MOVQ blocks_len, DX; \ ++ \ ++ MOVQ SP, BP; \ ++ ADDQ $15, BP; \ ++ ANDQ $~15, BP; \ ++ \ ++ MOVQ 0(BX), R9; \ ++ MOVQ R9, 0(BP); \ ++ MOVQ CX, 8(BP); \ ++ \ ++ MOVOU 0(AX), X0; \ ++ MOVOU 16(AX), X1; \ ++ MOVOU iv0<>(SB), X2; \ ++ MOVOU iv1<>(SB), X3 \ ++ \ ++ MOVOU counter<>(SB), X12; \ ++ MOVOU rol16<>(SB), X13; \ ++ MOVOU rol8<>(SB), X14; \ ++ MOVO 0(BP), X15; \ ++ \ ++ loop: \ ++ MOVO X0, X4; \ ++ MOVO X1, X5; \ ++ MOVO X2, X6; \ ++ MOVO X3, X7; \ ++ \ ++ PADDQ X12, X15; \ ++ PXOR X15, X7; \ ++ \ ++ BLAKE2s_FUNC(); \ ++ \ ++ PXOR X4, X0; \ ++ PXOR X5, X1; \ ++ PXOR X6, X0; \ ++ PXOR X7, X1; \ ++ \ ++ LEAQ 64(SI), SI; \ ++ SUBQ $64, DX; \ ++ JNE loop; \ ++ \ ++ MOVO X15, 0(BP); \ ++ MOVQ 0(BP), R9; \ ++ MOVQ R9, 0(BX); \ ++ \ ++ MOVOU X0, 0(AX); \ ++ MOVOU X1, 16(AX) ++ ++// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++TEXT Β·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment ++ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2) ++ RET ++ ++// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++TEXT Β·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment ++ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3) ++ RET ++ ++// func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) ++TEXT Β·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment ++ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) ++ RET +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go +new file mode 100644 +index 00000000000000..24a1ff22adcff0 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go +@@ -0,0 +1,178 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blake2s ++ ++import ( ++ "math/bits" ++) ++ ++// the precomputed values for BLAKE2s ++// there are 10 16-byte arrays - one for each round ++// the entries are calculated from the sigma constants. ++var precomputed = [10][16]byte{ ++ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, ++ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, ++ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, ++ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, ++ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, ++ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, ++ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, ++ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, ++ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, ++ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, ++} ++ ++func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { ++ var m [16]uint32 ++ c0, c1 := c[0], c[1] ++ ++ for i := 0; i < len(blocks); { ++ c0 += BlockSize ++ if c0 < BlockSize { ++ c1++ ++ } ++ ++ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] ++ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] ++ v12 ^= c0 ++ v13 ^= c1 ++ v14 ^= flag ++ ++ for j := range m { ++ m[j] = uint32(blocks[i]) | uint32(blocks[i+1])<<8 | uint32(blocks[i+2])<<16 | uint32(blocks[i+3])<<24 ++ i += 4 ++ } ++ ++ for k := range precomputed { ++ s := &(precomputed[k]) ++ ++ v0 += m[s[0]] ++ v0 += v4 ++ v12 ^= v0 ++ v12 = bits.RotateLeft32(v12, -16) ++ v8 += v12 ++ v4 ^= v8 ++ v4 = bits.RotateLeft32(v4, -12) ++ v1 += m[s[1]] ++ v1 += v5 ++ v13 ^= v1 ++ v13 = bits.RotateLeft32(v13, -16) ++ v9 += v13 ++ v5 ^= v9 ++ v5 = bits.RotateLeft32(v5, -12) ++ v2 += m[s[2]] ++ v2 += v6 ++ v14 ^= v2 ++ v14 = bits.RotateLeft32(v14, -16) ++ v10 += v14 ++ v6 ^= v10 ++ v6 = bits.RotateLeft32(v6, -12) ++ v3 += m[s[3]] ++ v3 += v7 ++ v15 ^= v3 ++ v15 = bits.RotateLeft32(v15, -16) ++ v11 += v15 ++ v7 ^= v11 ++ v7 = bits.RotateLeft32(v7, -12) ++ ++ v0 += m[s[4]] ++ v0 += v4 ++ v12 ^= v0 ++ v12 = bits.RotateLeft32(v12, -8) ++ v8 += v12 ++ v4 ^= v8 ++ v4 = bits.RotateLeft32(v4, -7) ++ v1 += m[s[5]] ++ v1 += v5 ++ v13 ^= v1 ++ v13 = bits.RotateLeft32(v13, -8) ++ v9 += v13 ++ v5 ^= v9 ++ v5 = bits.RotateLeft32(v5, -7) ++ v2 += m[s[6]] ++ v2 += v6 ++ v14 ^= v2 ++ v14 = bits.RotateLeft32(v14, -8) ++ v10 += v14 ++ v6 ^= v10 ++ v6 = bits.RotateLeft32(v6, -7) ++ v3 += m[s[7]] ++ v3 += v7 ++ v15 ^= v3 ++ v15 = bits.RotateLeft32(v15, -8) ++ v11 += v15 ++ v7 ^= v11 ++ v7 = bits.RotateLeft32(v7, -7) ++ ++ v0 += m[s[8]] ++ v0 += v5 ++ v15 ^= v0 ++ v15 = bits.RotateLeft32(v15, -16) ++ v10 += v15 ++ v5 ^= v10 ++ v5 = bits.RotateLeft32(v5, -12) ++ v1 += m[s[9]] ++ v1 += v6 ++ v12 ^= v1 ++ v12 = bits.RotateLeft32(v12, -16) ++ v11 += v12 ++ v6 ^= v11 ++ v6 = bits.RotateLeft32(v6, -12) ++ v2 += m[s[10]] ++ v2 += v7 ++ v13 ^= v2 ++ v13 = bits.RotateLeft32(v13, -16) ++ v8 += v13 ++ v7 ^= v8 ++ v7 = bits.RotateLeft32(v7, -12) ++ v3 += m[s[11]] ++ v3 += v4 ++ v14 ^= v3 ++ v14 = bits.RotateLeft32(v14, -16) ++ v9 += v14 ++ v4 ^= v9 ++ v4 = bits.RotateLeft32(v4, -12) ++ ++ v0 += m[s[12]] ++ v0 += v5 ++ v15 ^= v0 ++ v15 = bits.RotateLeft32(v15, -8) ++ v10 += v15 ++ v5 ^= v10 ++ v5 = bits.RotateLeft32(v5, -7) ++ v1 += m[s[13]] ++ v1 += v6 ++ v12 ^= v1 ++ v12 = bits.RotateLeft32(v12, -8) ++ v11 += v12 ++ v6 ^= v11 ++ v6 = bits.RotateLeft32(v6, -7) ++ v2 += m[s[14]] ++ v2 += v7 ++ v13 ^= v2 ++ v13 = bits.RotateLeft32(v13, -8) ++ v8 += v13 ++ v7 ^= v8 ++ v7 = bits.RotateLeft32(v7, -7) ++ v3 += m[s[15]] ++ v3 += v4 ++ v14 ^= v3 ++ v14 = bits.RotateLeft32(v14, -8) ++ v9 += v14 ++ v4 ^= v9 ++ v4 = bits.RotateLeft32(v4, -7) ++ } ++ ++ h[0] ^= v0 ^ v8 ++ h[1] ^= v1 ^ v9 ++ h[2] ^= v2 ^ v10 ++ h[3] ^= v3 ^ v11 ++ h[4] ^= v4 ^ v12 ++ h[5] ^= v5 ^ v13 ++ h[6] ^= v6 ^ v14 ++ h[7] ^= v7 ^ v15 ++ } ++ c[0], c[1] = c0, c1 ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go +new file mode 100644 +index 00000000000000..799dba0c415853 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go +@@ -0,0 +1,18 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build (!amd64 && !386) || !gc || purego ++// +build !amd64,!386 !gc purego ++ ++package blake2s ++ ++var ( ++ useSSE4 = false ++ useSSSE3 = false ++ useSSE2 = false ++) ++ ++func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { ++ hashBlocksGeneric(h, c, flag, blocks) ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go +new file mode 100644 +index 00000000000000..cde79fb1cd0c87 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go +@@ -0,0 +1,1050 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blake2s ++ ++import ( ++ "bytes" ++ "encoding" ++ "encoding/hex" ++ "fmt" ++ "testing" ++) ++ ++func TestHashes(t *testing.T) { ++ defer func(sse2, ssse3, sse4 bool) { ++ useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4 ++ }(useSSE2, useSSSE3, useSSE4) ++ ++ if useSSE4 { ++ t.Log("SSE4 version") ++ testHashes(t) ++ testHashes128(t) ++ useSSE4 = false ++ } ++ if useSSSE3 { ++ t.Log("SSSE3 version") ++ testHashes(t) ++ testHashes128(t) ++ useSSSE3 = false ++ } ++ if useSSE2 { ++ t.Log("SSE2 version") ++ testHashes(t) ++ testHashes128(t) ++ useSSE2 = false ++ } ++ ++ t.Log("generic version") ++ testHashes(t) ++ testHashes128(t) ++} ++ ++func TestHashes2X(t *testing.T) { ++ defer func(sse2, ssse3, sse4 bool) { ++ useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4 ++ }(useSSE2, useSSSE3, useSSE4) ++ ++ if useSSE4 { ++ t.Log("SSE4 version") ++ testHashes2X(t) ++ useSSE4 = false ++ } ++ if useSSSE3 { ++ t.Log("SSSE3 version") ++ testHashes2X(t) ++ useSSSE3 = false ++ } ++ if useSSE2 { ++ t.Log("SSE2 version") ++ testHashes2X(t) ++ useSSE2 = false ++ } ++ ++ t.Log("generic version") ++ testHashes2X(t) ++} ++ ++func TestMarshal(t *testing.T) { ++ input := make([]byte, 255) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ for i := 0; i < 256; i++ { ++ h, err := New256(nil) ++ if err != nil { ++ t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) ++ } ++ h2, err := New256(nil) ++ if err != nil { ++ t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) ++ } ++ ++ h.Write(input[:i/2]) ++ halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() ++ if err != nil { ++ t.Fatalf("len(input)=%d: could not marshal: %v", i, err) ++ } ++ err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) ++ if err != nil { ++ t.Fatalf("len(input)=%d: could not unmarshal: %v", i, err) ++ } ++ ++ h.Write(input[i/2 : i]) ++ sum := h.Sum(nil) ++ h2.Write(input[i/2 : i]) ++ sum2 := h2.Sum(nil) ++ ++ if !bytes.Equal(sum, sum2) { ++ t.Fatalf("len(input)=%d: results do not match; sum = %v, sum2 = %v", i, sum, sum2) ++ } ++ ++ h3, err := New256(nil) ++ if err != nil { ++ t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) ++ } ++ h3.Write(input[:i]) ++ sum3 := h3.Sum(nil) ++ if !bytes.Equal(sum, sum3) { ++ t.Fatalf("len(input)=%d: sum = %v, want %v", i, sum, sum3) ++ } ++ } ++} ++ ++func testHashes(t *testing.T) { ++ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") ++ ++ input := make([]byte, 255) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ ++ for i, expectedHex := range hashes { ++ h, err := New256(key) ++ if err != nil { ++ t.Fatalf("#%d: error from New256: %v", i, err) ++ } ++ ++ h.Write(input[:i]) ++ sum := h.Sum(nil) ++ ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ ++ h.Reset() ++ for j := 0; j < i; j++ { ++ h.Write(input[j : j+1]) ++ } ++ ++ sum = h.Sum(sum[:0]) ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ } ++} ++ ++func testHashes128(t *testing.T) { ++ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") ++ ++ input := make([]byte, 255) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ ++ for i, expectedHex := range hashes128 { ++ h, err := New128(key) ++ if err != nil { ++ t.Fatalf("#%d: error from New128: %v", i, err) ++ } ++ ++ h.Write(input[:i]) ++ sum := h.Sum(nil) ++ ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ ++ h.Reset() ++ for j := 0; j < i; j++ { ++ h.Write(input[j : j+1]) ++ } ++ ++ sum = h.Sum(sum[:0]) ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ } ++} ++ ++func testHashes2X(t *testing.T) { ++ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") ++ ++ input := make([]byte, 256) ++ for i := range input { ++ input[i] = byte(i) ++ } ++ ++ for i, expectedHex := range hashes2X { ++ length := uint16(len(expectedHex) / 2) ++ sum := make([]byte, int(length)) ++ ++ h, err := NewXOF(length, key) ++ if err != nil { ++ t.Fatalf("#%d: error from NewXOF: %v", i, err) ++ } ++ ++ if _, err := h.Write(input); err != nil { ++ t.Fatalf("#%d (single write): error from Write: %v", i, err) ++ } ++ if _, err := h.Read(sum); err != nil { ++ t.Fatalf("#%d (single write): error from Read: %v", i, err) ++ } ++ ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ ++ h.Reset() ++ for j := 0; j < len(input); j++ { ++ h.Write(input[j : j+1]) ++ } ++ for j := 0; j < len(sum); j++ { ++ h = h.Clone() ++ if _, err := h.Read(sum[j : j+1]); err != nil { ++ t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) ++ } ++ } ++ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { ++ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) ++ } ++ } ++ ++ h, err := NewXOF(OutputLengthUnknown, key) ++ if err != nil { ++ t.Fatalf("#unknown length: error from NewXOF: %v", err) ++ } ++ if _, err := h.Write(input); err != nil { ++ t.Fatalf("#unknown length: error from Write: %v", err) ++ } ++ ++ var result [64]byte ++ if n, err := h.Read(result[:]); err != nil { ++ t.Fatalf("#unknown length: error from Read: %v", err) ++ } else if n != len(result) { ++ t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) ++ } ++ ++ const expected = "2a9a6977d915a2c4dd07dbcafe1918bf1682e56d9c8e567ecd19bfd7cd93528833c764d12b34a5e2a219c9fd463dab45e972c5574d73f45de5b2e23af72530d8" ++ if fmt.Sprintf("%x", result) != expected { ++ t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) ++ } ++} ++ ++// Benchmarks ++ ++func benchmarkSum(b *testing.B, size int) { ++ data := make([]byte, size) ++ b.SetBytes(int64(size)) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ Sum256(data) ++ } ++} ++ ++func benchmarkWrite(b *testing.B, size int) { ++ data := make([]byte, size) ++ h, _ := New256(nil) ++ b.SetBytes(int64(size)) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ h.Write(data) ++ } ++} ++ ++func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64) } ++func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } ++ ++func BenchmarkSum64(b *testing.B) { benchmarkSum(b, 64) } ++func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } ++ ++// hashes is taken from https://blake2.net/blake2s-test.txt ++var hashes = []string{ ++ "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49", ++ "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1", ++ "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803", ++ "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b", ++ "f6c3fbadb4cc687a0064a5be6e791bec63b868ad62fba61b3757ef9ca52e05b2", ++ "49c1f21188dfd769aea0e911dd6b41f14dab109d2b85977aa3088b5c707e8598", ++ "fdd8993dcd43f696d44f3cea0ff35345234ec8ee083eb3cada017c7f78c17143", ++ "e6c8125637438d0905b749f46560ac89fd471cf8692e28fab982f73f019b83a9", ++ "19fc8ca6979d60e6edd3b4541e2f967ced740df6ec1eaebbfe813832e96b2974", ++ "a6ad777ce881b52bb5a4421ab6cdd2dfba13e963652d4d6d122aee46548c14a7", ++ "f5c4b2ba1a00781b13aba0425242c69cb1552f3f71a9a3bb22b4a6b4277b46dd", ++ "e33c4c9bd0cc7e45c80e65c77fa5997fec7002738541509e68a9423891e822a3", ++ "fba16169b2c3ee105be6e1e650e5cbf40746b6753d036ab55179014ad7ef6651", ++ "f5c4bec6d62fc608bf41cc115f16d61c7efd3ff6c65692bbe0afffb1fede7475", ++ "a4862e76db847f05ba17ede5da4e7f91b5925cf1ad4ba12732c3995742a5cd6e", ++ "65f4b860cd15b38ef814a1a804314a55be953caa65fd758ad989ff34a41c1eea", ++ "19ba234f0a4f38637d1839f9d9f76ad91c8522307143c97d5f93f69274cec9a7", ++ "1a67186ca4a5cb8e65fca0e2ecbc5ddc14ae381bb8bffeb9e0a103449e3ef03c", ++ "afbea317b5a2e89c0bd90ccf5d7fd0ed57fe585e4be3271b0a6bf0f5786b0f26", ++ "f1b01558ce541262f5ec34299d6fb4090009e3434be2f49105cf46af4d2d4124", ++ "13a0a0c86335635eaa74ca2d5d488c797bbb4f47dc07105015ed6a1f3309efce", ++ "1580afeebebb346f94d59fe62da0b79237ead7b1491f5667a90e45edf6ca8b03", ++ "20be1a875b38c573dd7faaa0de489d655c11efb6a552698e07a2d331b5f655c3", ++ "be1fe3c4c04018c54c4a0f6b9a2ed3c53abe3a9f76b4d26de56fc9ae95059a99", ++ "e3e3ace537eb3edd8463d9ad3582e13cf86533ffde43d668dd2e93bbdbd7195a", ++ "110c50c0bf2c6e7aeb7e435d92d132ab6655168e78a2decdec3330777684d9c1", ++ "e9ba8f505c9c80c08666a701f3367e6cc665f34b22e73c3c0417eb1c2206082f", ++ "26cd66fca02379c76df12317052bcafd6cd8c3a7b890d805f36c49989782433a", ++ "213f3596d6e3a5d0e9932cd2159146015e2abc949f4729ee2632fe1edb78d337", ++ "1015d70108e03be1c702fe97253607d14aee591f2413ea6787427b6459ff219a", ++ "3ca989de10cfe609909472c8d35610805b2f977734cf652cc64b3bfc882d5d89", ++ "b6156f72d380ee9ea6acd190464f2307a5c179ef01fd71f99f2d0f7a57360aea", ++ "c03bc642b20959cbe133a0303e0c1abff3e31ec8e1a328ec8565c36decff5265", ++ "2c3e08176f760c6264c3a2cd66fec6c3d78de43fc192457b2a4a660a1e0eb22b", ++ "f738c02f3c1b190c512b1a32deabf353728e0e9ab034490e3c3409946a97aeec", ++ "8b1880df301cc963418811088964839287ff7fe31c49ea6ebd9e48bdeee497c5", ++ "1e75cb21c60989020375f1a7a242839f0b0b68973a4c2a05cf7555ed5aaec4c1", ++ "62bf8a9c32a5bccf290b6c474d75b2a2a4093f1a9e27139433a8f2b3bce7b8d7", ++ "166c8350d3173b5e702b783dfd33c66ee0432742e9b92b997fd23c60dc6756ca", ++ "044a14d822a90cacf2f5a101428adc8f4109386ccb158bf905c8618b8ee24ec3", ++ "387d397ea43a994be84d2d544afbe481a2000f55252696bba2c50c8ebd101347", ++ "56f8ccf1f86409b46ce36166ae9165138441577589db08cbc5f66ca29743b9fd", ++ "9706c092b04d91f53dff91fa37b7493d28b576b5d710469df79401662236fc03", ++ "877968686c068ce2f7e2adcff68bf8748edf3cf862cfb4d3947a3106958054e3", ++ "8817e5719879acf7024787eccdb271035566cfa333e049407c0178ccc57a5b9f", ++ "8938249e4b50cadaccdf5b18621326cbb15253e33a20f5636e995d72478de472", ++ "f164abba4963a44d107257e3232d90aca5e66a1408248c51741e991db5227756", ++ "d05563e2b1cba0c4a2a1e8bde3a1a0d9f5b40c85a070d6f5fb21066ead5d0601", ++ "03fbb16384f0a3866f4c3117877666efbf124597564b293d4aab0d269fabddfa", ++ "5fa8486ac0e52964d1881bbe338eb54be2f719549224892057b4da04ba8b3475", ++ "cdfabcee46911111236a31708b2539d71fc211d9b09c0d8530a11e1dbf6eed01", ++ "4f82de03b9504793b82a07a0bdcdff314d759e7b62d26b784946b0d36f916f52", ++ "259ec7f173bcc76a0994c967b4f5f024c56057fb79c965c4fae41875f06a0e4c", ++ "193cc8e7c3e08bb30f5437aa27ade1f142369b246a675b2383e6da9b49a9809e", ++ "5c10896f0e2856b2a2eee0fe4a2c1633565d18f0e93e1fab26c373e8f829654d", ++ "f16012d93f28851a1eb989f5d0b43f3f39ca73c9a62d5181bff237536bd348c3", ++ "2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806", ++ "ddb8782485e900bc60bcf4c33a6fd585680cc683d516efa03eb9985fad8715fb", ++ "4c4d6e71aea05786413148fc7a786b0ecaf582cff1209f5a809fba8504ce662c", ++ "fb4c5e86d7b2229b99b8ba6d94c247ef964aa3a2bae8edc77569f28dbbff2d4e", ++ "e94f526de9019633ecd54ac6120f23958d7718f1e7717bf329211a4faeed4e6d", ++ "cbd6660a10db3f23f7a03d4b9d4044c7932b2801ac89d60bc9eb92d65a46c2a0", ++ "8818bbd3db4dc123b25cbba5f54c2bc4b3fcf9bf7d7a7709f4ae588b267c4ece", ++ "c65382513f07460da39833cb666c5ed82e61b9e998f4b0c4287cee56c3cc9bcd", ++ "8975b0577fd35566d750b362b0897a26c399136df07bababbde6203ff2954ed4", ++ "21fe0ceb0052be7fb0f004187cacd7de67fa6eb0938d927677f2398c132317a8", ++ "2ef73f3c26f12d93889f3c78b6a66c1d52b649dc9e856e2c172ea7c58ac2b5e3", ++ "388a3cd56d73867abb5f8401492b6e2681eb69851e767fd84210a56076fb3dd3", ++ "af533e022fc9439e4e3cb838ecd18692232adf6fe9839526d3c3dd1b71910b1a", ++ "751c09d41a9343882a81cd13ee40818d12eb44c6c7f40df16e4aea8fab91972a", ++ "5b73ddb68d9d2b0aa265a07988d6b88ae9aac582af83032f8a9b21a2e1b7bf18", ++ "3da29126c7c5d7f43e64242a79feaa4ef3459cdeccc898ed59a97f6ec93b9dab", ++ "566dc920293da5cb4fe0aa8abda8bbf56f552313bff19046641e3615c1e3ed3f", ++ "4115bea02f73f97f629e5c5590720c01e7e449ae2a6697d4d2783321303692f9", ++ "4ce08f4762468a7670012164878d68340c52a35e66c1884d5c864889abc96677", ++ "81ea0b7804124e0c22ea5fc71104a2afcb52a1fa816f3ecb7dcb5d9dea1786d0", ++ "fe362733b05f6bedaf9379d7f7936ede209b1f8323c3922549d9e73681b5db7b", ++ "eff37d30dfd20359be4e73fdf40d27734b3df90a97a55ed745297294ca85d09f", ++ "172ffc67153d12e0ca76a8b6cd5d4731885b39ce0cac93a8972a18006c8b8baf", ++ "c47957f1cc88e83ef9445839709a480a036bed5f88ac0fcc8e1e703ffaac132c", ++ "30f3548370cfdceda5c37b569b6175e799eef1a62aaa943245ae7669c227a7b5", ++ "c95dcb3cf1f27d0eef2f25d2413870904a877c4a56c2de1e83e2bc2ae2e46821", ++ "d5d0b5d705434cd46b185749f66bfb5836dcdf6ee549a2b7a4aee7f58007caaf", ++ "bbc124a712f15d07c300e05b668389a439c91777f721f8320c1c9078066d2c7e", ++ "a451b48c35a6c7854cfaae60262e76990816382ac0667e5a5c9e1b46c4342ddf", ++ "b0d150fb55e778d01147f0b5d89d99ecb20ff07e5e6760d6b645eb5b654c622b", ++ "34f737c0ab219951eee89a9f8dac299c9d4c38f33fa494c5c6eefc92b6db08bc", ++ "1a62cc3a00800dcbd99891080c1e098458193a8cc9f970ea99fbeff00318c289", ++ "cfce55ebafc840d7ae48281c7fd57ec8b482d4b704437495495ac414cf4a374b", ++ "6746facf71146d999dabd05d093ae586648d1ee28e72617b99d0f0086e1e45bf", ++ "571ced283b3f23b4e750bf12a2caf1781847bd890e43603cdc5976102b7bb11b", ++ "cfcb765b048e35022c5d089d26e85a36b005a2b80493d03a144e09f409b6afd1", ++ "4050c7a27705bb27f42089b299f3cbe5054ead68727e8ef9318ce6f25cd6f31d", ++ "184070bd5d265fbdc142cd1c5cd0d7e414e70369a266d627c8fba84fa5e84c34", ++ "9edda9a4443902a9588c0d0ccc62b930218479a6841e6fe7d43003f04b1fd643", ++ "e412feef7908324a6da1841629f35d3d358642019310ec57c614836b63d30763", ++ "1a2b8edff3f9acc1554fcbae3cf1d6298c6462e22e5eb0259684f835012bd13f", ++ "288c4ad9b9409762ea07c24a41f04f69a7d74bee2d95435374bde946d7241c7b", ++ "805691bb286748cfb591d3aebe7e6f4e4dc6e2808c65143cc004e4eb6fd09d43", ++ "d4ac8d3a0afc6cfa7b460ae3001baeb36dadb37da07d2e8ac91822df348aed3d", ++ "c376617014d20158bced3d3ba552b6eccf84e62aa3eb650e90029c84d13eea69", ++ "c41f09f43cecae7293d6007ca0a357087d5ae59be500c1cd5b289ee810c7b082", ++ "03d1ced1fba5c39155c44b7765cb760c78708dcfc80b0bd8ade3a56da8830b29", ++ "09bde6f152218dc92c41d7f45387e63e5869d807ec70b821405dbd884b7fcf4b", ++ "71c9036e18179b90b37d39e9f05eb89cc5fc341fd7c477d0d7493285faca08a4", ++ "5916833ebb05cd919ca7fe83b692d3205bef72392b2cf6bb0a6d43f994f95f11", ++ "f63aab3ec641b3b024964c2b437c04f6043c4c7e0279239995401958f86bbe54", ++ "f172b180bfb09740493120b6326cbdc561e477def9bbcfd28cc8c1c5e3379a31", ++ "cb9b89cc18381dd9141ade588654d4e6a231d5bf49d4d59ac27d869cbe100cf3", ++ "7bd8815046fdd810a923e1984aaebdcdf84d87c8992d68b5eeb460f93eb3c8d7", ++ "607be66862fd08ee5b19facac09dfdbcd40c312101d66e6ebd2b841f1b9a9325", ++ "9fe03bbe69ab1834f5219b0da88a08b30a66c5913f0151963c360560db0387b3", ++ "90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c", ++ "336ea0530f4a7469126e0218587ebbde3358a0b31c29d200f7dc7eb15c6aadd8", ++ "a79e76dc0abca4396f0747cd7b748df913007626b1d659da0c1f78b9303d01a3", ++ "44e78a773756e0951519504d7038d28d0213a37e0ce375371757bc996311e3b8", ++ "77ac012a3f754dcfeab5eb996be9cd2d1f96111b6e49f3994df181f28569d825", ++ "ce5a10db6fccdaf140aaa4ded6250a9c06e9222bc9f9f3658a4aff935f2b9f3a", ++ "ecc203a7fe2be4abd55bb53e6e673572e0078da8cd375ef430cc97f9f80083af", ++ "14a5186de9d7a18b0412b8563e51cc5433840b4a129a8ff963b33a3c4afe8ebb", ++ "13f8ef95cb86e6a638931c8e107673eb76ba10d7c2cd70b9d9920bbeed929409", ++ "0b338f4ee12f2dfcb78713377941e0b0632152581d1332516e4a2cab1942cca4", ++ "eaab0ec37b3b8ab796e9f57238de14a264a076f3887d86e29bb5906db5a00e02", ++ "23cb68b8c0e6dc26dc27766ddc0a13a99438fd55617aa4095d8f969720c872df", ++ "091d8ee30d6f2968d46b687dd65292665742de0bb83dcc0004c72ce10007a549", ++ "7f507abc6d19ba00c065a876ec5657868882d18a221bc46c7a6912541f5bc7ba", ++ "a0607c24e14e8c223db0d70b4d30ee88014d603f437e9e02aa7dafa3cdfbad94", ++ "ddbfea75cc467882eb3483ce5e2e756a4f4701b76b445519e89f22d60fa86e06", ++ "0c311f38c35a4fb90d651c289d486856cd1413df9b0677f53ece2cd9e477c60a", ++ "46a73a8dd3e70f59d3942c01df599def783c9da82fd83222cd662b53dce7dbdf", ++ "ad038ff9b14de84a801e4e621ce5df029dd93520d0c2fa38bff176a8b1d1698c", ++ "ab70c5dfbd1ea817fed0cd067293abf319e5d7901c2141d5d99b23f03a38e748", ++ "1fffda67932b73c8ecaf009a3491a026953babfe1f663b0697c3c4ae8b2e7dcb", ++ "b0d2cc19472dd57f2b17efc03c8d58c2283dbb19da572f7755855aa9794317a0", ++ "a0d19a6ee33979c325510e276622df41f71583d07501b87071129a0ad94732a5", ++ "724642a7032d1062b89e52bea34b75df7d8fe772d9fe3c93ddf3c4545ab5a99b", ++ "ade5eaa7e61f672d587ea03dae7d7b55229c01d06bc0a5701436cbd18366a626", ++ "013b31ebd228fcdda51fabb03bb02d60ac20ca215aafa83bdd855e3755a35f0b", ++ "332ed40bb10dde3c954a75d7b8999d4b26a1c063c1dc6e32c1d91bab7bbb7d16", ++ "c7a197b3a05b566bcc9facd20e441d6f6c2860ac9651cd51d6b9d2cdeeea0390", ++ "bd9cf64ea8953c037108e6f654914f3958b68e29c16700dc184d94a21708ff60", ++ "8835b0ac021151df716474ce27ce4d3c15f0b2dab48003cf3f3efd0945106b9a", ++ "3bfefa3301aa55c080190cffda8eae51d9af488b4c1f24c3d9a75242fd8ea01d", ++ "08284d14993cd47d53ebaecf0df0478cc182c89c00e1859c84851686ddf2c1b7", ++ "1ed7ef9f04c2ac8db6a864db131087f27065098e69c3fe78718d9b947f4a39d0", ++ "c161f2dcd57e9c1439b31a9dd43d8f3d7dd8f0eb7cfac6fb25a0f28e306f0661", ++ "c01969ad34c52caf3dc4d80d19735c29731ac6e7a92085ab9250c48dea48a3fc", ++ "1720b3655619d2a52b3521ae0e49e345cb3389ebd6208acaf9f13fdacca8be49", ++ "756288361c83e24c617cf95c905b22d017cdc86f0bf1d658f4756c7379873b7f", ++ "e7d0eda3452693b752abcda1b55e276f82698f5f1605403eff830bea0071a394", ++ "2c82ecaa6b84803e044af63118afe544687cb6e6c7df49ed762dfd7c8693a1bc", ++ "6136cbf4b441056fa1e2722498125d6ded45e17b52143959c7f4d4e395218ac2", ++ "721d3245aafef27f6a624f47954b6c255079526ffa25e9ff77e5dcff473b1597", ++ "9dd2fbd8cef16c353c0ac21191d509eb28dd9e3e0d8cea5d26ca839393851c3a", ++ "b2394ceacdebf21bf9df2ced98e58f1c3a4bbbff660dd900f62202d6785cc46e", ++ "57089f222749ad7871765f062b114f43ba20ec56422a8b1e3f87192c0ea718c6", ++ "e49a9459961cd33cdf4aae1b1078a5dea7c040e0fea340c93a724872fc4af806", ++ "ede67f720effd2ca9c88994152d0201dee6b0a2d2c077aca6dae29f73f8b6309", ++ "e0f434bf22e3088039c21f719ffc67f0f2cb5e98a7a0194c76e96bf4e8e17e61", ++ "277c04e2853484a4eba910ad336d01b477b67cc200c59f3c8d77eef8494f29cd", ++ "156d5747d0c99c7f27097d7b7e002b2e185cb72d8dd7eb424a0321528161219f", ++ "20ddd1ed9b1ca803946d64a83ae4659da67fba7a1a3eddb1e103c0f5e03e3a2c", ++ "f0af604d3dabbf9a0f2a7d3dda6bd38bba72c6d09be494fcef713ff10189b6e6", ++ "9802bb87def4cc10c4a5fd49aa58dfe2f3fddb46b4708814ead81d23ba95139b", ++ "4f8ce1e51d2fe7f24043a904d898ebfc91975418753413aa099b795ecb35cedb", ++ "bddc6514d7ee6ace0a4ac1d0e068112288cbcf560454642705630177cba608bd", ++ "d635994f6291517b0281ffdd496afa862712e5b3c4e52e4cd5fdae8c0e72fb08", ++ "878d9ca600cf87e769cc305c1b35255186615a73a0da613b5f1c98dbf81283ea", ++ "a64ebe5dc185de9fdde7607b6998702eb23456184957307d2fa72e87a47702d6", ++ "ce50eab7b5eb52bdc9ad8e5a480ab780ca9320e44360b1fe37e03f2f7ad7de01", ++ "eeddb7c0db6e30abe66d79e327511e61fcebbc29f159b40a86b046ecf0513823", ++ "787fc93440c1ec96b5ad01c16cf77916a1405f9426356ec921d8dff3ea63b7e0", ++ "7f0d5eab47eefda696c0bf0fbf86ab216fce461e9303aba6ac374120e890e8df", ++ "b68004b42f14ad029f4c2e03b1d5eb76d57160e26476d21131bef20ada7d27f4", ++ "b0c4eb18ae250b51a41382ead92d0dc7455f9379fc9884428e4770608db0faec", ++ "f92b7a870c059f4d46464c824ec96355140bdce681322cc3a992ff103e3fea52", ++ "5364312614813398cc525d4c4e146edeb371265fba19133a2c3d2159298a1742", ++ "f6620e68d37fb2af5000fc28e23b832297ecd8bce99e8be4d04e85309e3d3374", ++ "5316a27969d7fe04ff27b283961bffc3bf5dfb32fb6a89d101c6c3b1937c2871", ++ "81d1664fdf3cb33c24eebac0bd64244b77c4abea90bbe8b5ee0b2aafcf2d6a53", ++ "345782f295b0880352e924a0467b5fbc3e8f3bfbc3c7e48b67091fb5e80a9442", ++ "794111ea6cd65e311f74ee41d476cb632ce1e4b051dc1d9e9d061a19e1d0bb49", ++ "2a85daf6138816b99bf8d08ba2114b7ab07975a78420c1a3b06a777c22dd8bcb", ++ "89b0d5f289ec16401a069a960d0b093e625da3cf41ee29b59b930c5820145455", ++ "d0fdcb543943fc27d20864f52181471b942cc77ca675bcb30df31d358ef7b1eb", ++ "b17ea8d77063c709d4dc6b879413c343e3790e9e62ca85b7900b086f6b75c672", ++ "e71a3e2c274db842d92114f217e2c0eac8b45093fdfd9df4ca7162394862d501", ++ "c0476759ab7aa333234f6b44f5fd858390ec23694c622cb986e769c78edd733e", ++ "9ab8eabb1416434d85391341d56993c55458167d4418b19a0f2ad8b79a83a75b", ++ "7992d0bbb15e23826f443e00505d68d3ed7372995a5c3e498654102fbcd0964e", ++ "c021b30085151435df33b007ccecc69df1269f39ba25092bed59d932ac0fdc28", ++ "91a25ec0ec0d9a567f89c4bfe1a65a0e432d07064b4190e27dfb81901fd3139b", ++ "5950d39a23e1545f301270aa1a12f2e6c453776e4d6355de425cc153f9818867", ++ "d79f14720c610af179a3765d4b7c0968f977962dbf655b521272b6f1e194488e", ++ "e9531bfc8b02995aeaa75ba27031fadbcbf4a0dab8961d9296cd7e84d25d6006", ++ "34e9c26a01d7f16181b454a9d1623c233cb99d31c694656e9413aca3e918692f", ++ "d9d7422f437bd439ddd4d883dae2a08350173414be78155133fff1964c3d7972", ++ "4aee0c7aaf075414ff1793ead7eaca601775c615dbd60b640b0a9f0ce505d435", ++ "6bfdd15459c83b99f096bfb49ee87b063d69c1974c6928acfcfb4099f8c4ef67", ++ "9fd1c408fd75c336193a2a14d94f6af5adf050b80387b4b010fb29f4cc72707c", ++ "13c88480a5d00d6c8c7ad2110d76a82d9b70f4fa6696d4e5dd42a066dcaf9920", ++ "820e725ee25fe8fd3a8d5abe4c46c3ba889de6fa9191aa22ba67d5705421542b", ++ "32d93a0eb02f42fbbcaf2bad0085b282e46046a4df7ad10657c9d6476375b93e", ++ "adc5187905b1669cd8ec9c721e1953786b9d89a9bae30780f1e1eab24a00523c", ++ "e90756ff7f9ad810b239a10ced2cf9b2284354c1f8c7e0accc2461dc796d6e89", ++ "1251f76e56978481875359801db589a0b22f86d8d634dc04506f322ed78f17e8", ++ "3afa899fd980e73ecb7f4d8b8f291dc9af796bc65d27f974c6f193c9191a09fd", ++ "aa305be26e5deddc3c1010cbc213f95f051c785c5b431e6a7cd048f161787528", ++ "8ea1884ff32e9d10f039b407d0d44e7e670abd884aeee0fb757ae94eaa97373d", ++ "d482b2155d4dec6b4736a1f1617b53aaa37310277d3fef0c37ad41768fc235b4", ++ "4d413971387e7a8898a8dc2a27500778539ea214a2dfe9b3d7e8ebdce5cf3db3", ++ "696e5d46e6c57e8796e4735d08916e0b7929b3cf298c296d22e9d3019653371c", ++ "1f5647c1d3b088228885865c8940908bf40d1a8272821973b160008e7a3ce2eb", ++ "b6e76c330f021a5bda65875010b0edf09126c0f510ea849048192003aef4c61c", ++ "3cd952a0beada41abb424ce47f94b42be64e1ffb0fd0782276807946d0d0bc55", ++ "98d92677439b41b7bb513312afb92bcc8ee968b2e3b238cecb9b0f34c9bb63d0", ++ "ecbca2cf08ae57d517ad16158a32bfa7dc0382eaeda128e91886734c24a0b29d", ++ "942cc7c0b52e2b16a4b89fa4fc7e0bf609e29a08c1a8543452b77c7bfd11bb28", ++ "8a065d8b61a0dffb170d5627735a76b0e9506037808cba16c345007c9f79cf8f", ++ "1b9fa19714659c78ff413871849215361029ac802b1cbcd54e408bd87287f81f", ++ "8dab071bcd6c7292a9ef727b4ae0d86713301da8618d9a48adce55f303a869a1", ++ "8253e3e7c7b684b9cb2beb014ce330ff3d99d17abbdbabe4f4d674ded53ffc6b", ++ "f195f321e9e3d6bd7d074504dd2ab0e6241f92e784b1aa271ff648b1cab6d7f6", ++ "27e4cc72090f241266476a7c09495f2db153d5bcbd761903ef79275ec56b2ed8", ++ "899c2405788e25b99a1846355e646d77cf400083415f7dc5afe69d6e17c00023", ++ "a59b78c4905744076bfee894de707d4f120b5c6893ea0400297d0bb834727632", ++ "59dc78b105649707a2bb4419c48f005400d3973de3736610230435b10424b24f", ++ "c0149d1d7e7a6353a6d906efe728f2f329fe14a4149a3ea77609bc42b975ddfa", ++ "a32f241474a6c16932e9243be0cf09bcdc7e0ca0e7a6a1b9b1a0f01e41502377", ++ "b239b2e4f81841361c1339f68e2c359f929af9ad9f34e01aab4631ad6d5500b0", ++ "85fb419c7002a3e0b4b6ea093b4c1ac6936645b65dac5ac15a8528b7b94c1754", ++ "9619720625f190b93a3fad186ab314189633c0d3a01e6f9bc8c4a8f82f383dbf", ++ "7d620d90fe69fa469a6538388970a1aa09bb48a2d59b347b97e8ce71f48c7f46", ++ "294383568596fb37c75bbacd979c5ff6f20a556bf8879cc72924855df9b8240e", ++ "16b18ab314359c2b833c1c6986d48c55a9fc97cde9a3c1f10a3177140f73f738", ++ "8cbbdd14bc33f04cf45813e4a153a273d36adad5ce71f499eeb87fb8ac63b729", ++ "69c9a498db174ecaefcc5a3ac9fdedf0f813a5bec727f1e775babdec7718816e", ++ "b462c3be40448f1d4f80626254e535b08bc9cdcff599a768578d4b2881a8e3f0", ++ "553e9d9c5f360ac0b74a7d44e5a391dad4ced03e0c24183b7e8ecabdf1715a64", ++ "7a7c55a56fa9ae51e655e01975d8a6ff4ae9e4b486fcbe4eac044588f245ebea", ++ "2afdf3c82abc4867f5de111286c2b3be7d6e48657ba923cfbf101a6dfcf9db9a", ++ "41037d2edcdce0c49b7fb4a6aa0999ca66976c7483afe631d4eda283144f6dfc", ++ "c4466f8497ca2eeb4583a0b08e9d9ac74395709fda109d24f2e4462196779c5d", ++ "75f609338aa67d969a2ae2a2362b2da9d77c695dfd1df7224a6901db932c3364", ++ "68606ceb989d5488fc7cf649f3d7c272ef055da1a93faecd55fe06f6967098ca", ++ "44346bdeb7e052f6255048f0d9b42c425bab9c3dd24168212c3ecf1ebf34e6ae", ++ "8e9cf6e1f366471f2ac7d2ee9b5e6266fda71f8f2e4109f2237ed5f8813fc718", ++ "84bbeb8406d250951f8c1b3e86a7c010082921833dfd9555a2f909b1086eb4b8", ++ "ee666f3eef0f7e2a9c222958c97eaf35f51ced393d714485ab09a069340fdf88", ++ "c153d34a65c47b4a62c5cacf24010975d0356b2f32c8f5da530d338816ad5de6", ++ "9fc5450109e1b779f6c7ae79d56c27635c8dd426c5a9d54e2578db989b8c3b4e", ++ "d12bf3732ef4af5c22fa90356af8fc50fcb40f8f2ea5c8594737a3b3d5abdbd7", ++ "11030b9289bba5af65260672ab6fee88b87420acef4a1789a2073b7ec2f2a09e", ++ "69cb192b8444005c8c0ceb12c846860768188cda0aec27a9c8a55cdee2123632", ++ "db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83", ++ "3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd", ++} ++ ++var hashes128 = []string{ ++ "9536f9b267655743dee97b8a670f9f53", ++ "13bacfb85b48a1223c595f8c1e7e82cb", ++ "d47a9b1645e2feae501cd5fe44ce6333", ++ "1e2a79436a7796a3e9826bfedf07659f", ++ "7640360ed3c4f3054dba79a21dda66b7", ++ "d1207ac2bf5ac84fc9ef016da5a46a86", ++ "3123987871e59305ece3125abfc0099a", ++ "cf9e072ad522f2cda2d825218086731c", ++ "95d22870392efe2846b12b6e8e84efbb", ++ "7d63c30e2d51333f245601b038c0b93b", ++ "ed608b98e13976bdf4bedc63fa35e443", ++ "ed704b5cd1abf8e0dd67a6ac667a3fa5", ++ "77dc70109827dc74c70fd26cba379ae5", ++ "d2bf34508b07825ee934f33958f4560e", ++ "a340baa7b8a93a6e658adef42e78eeb7", ++ "b85c5ceaecbe9a251eac76f6932ba395", ++ "246519722001f6e8e97a2183f5985e53", ++ "5bce5aa0b7c6cac2ecf6406183cd779a", ++ "13408f1647c02f6efd0047ad8344f695", ++ "a63970f196760aa36cb965ab62f0e0fa", ++ "bc26f48421dd99fd45e15e736d3e7dac", ++ "4c6f70f9e3237cde918afb52d26f1823", ++ "45ed610cfbc37db80c4bf0eef14ae8d6", ++ "87c4c150705ea5078209ec008200539c", ++ "54de21f5e0e6f2afe04daeb822b6931e", ++ "9732a04e505064e19de3d542e7e71631", ++ "d2bd27e95531d6957eef511c4ba64ad4", ++ "7a36c9f70dcc7c3063b547101a5f6c35", ++ "322007d1a44c4257bc7903b183305529", ++ "dbcc9a09f412290ca2e0d53dfd142ddb", ++ "df12ed43b8e53a56db20e0f83764002c", ++ "d114cc11e7d5b33a360c45f18d4c7c6e", ++ "c43b5e836af88620a8a71b1652cb8640", ++ "9491c653e8867ed73c1b4ac6b5a9bb4d", ++ "06d0e988df94ada6c6f9f36f588ab7c5", ++ "561efad2480e93262c8eeaa3677615c4", ++ "ba8ffc702e5adc93503045eca8702312", ++ "5782be6ccdc78c8425285e85de8ccdc6", ++ "aa1c4393e4c07b53ea6e2b5b1e970771", ++ "42a229dc50e52271c51e8666023ebc1e", ++ "53706110e919f84de7f8d6c7f0e7b831", ++ "fc5ac8ee39cc1dd1424391323e2901bd", ++ "bed27b62ff66cac2fbb68193c727106a", ++ "cd5e689b96d0b9ea7e08dac36f7b211e", ++ "0b4c7f604eba058d18e322c6e1baf173", ++ "eb838227fdfad09a27f0f8413120675d", ++ "3149cf9d19a7fd529e6154a8b4c3b3ad", ++ "ca1e20126df930fd5fb7afe4422191e5", ++ "b23398f910599f3c09b6549fa81bcb46", ++ "27fb17c11b34fa5d8b5afe5ee3321ead", ++ "0f665f5f04cf2d46b7fead1a1f328158", ++ "8f068be73b3681f99f3b282e3c02bba5", ++ "ba189bbd13808dcf4e002a4dd21660d5", ++ "2732dcd1b16668ae6ab6a61595d0d62a", ++ "d410ccdd059f0e02b472ec9ec54bdd3c", ++ "b2eaa07b055b3a03a399971327f7e8c2", ++ "2e8a225655e9f99b69c60dc8b4d8e566", ++ "4eb55416c853f2152e67f8a224133cec", ++ "49552403790d8de0505a8e317a443687", ++ "7f2747cd41f56942752e868212c7d5ac", ++ "02a28f10e193b430df7112d2d98cf759", ++ "d4213404a9f1cf759017747cf5958270", ++ "faa34884344f9c65e944882db8476d34", ++ "ece382a8bd5018f1de5da44b72cea75b", ++ "f1efa90d2547036841ecd3627fafbc36", ++ "811ff8686d23a435ecbd0bdafcd27b1b", ++ "b21beea9c7385f657a76558530438721", ++ "9cb969da4f1b4fc5b13bf78fe366f0c4", ++ "8850d16d7b614d3268ccfa009d33c7fc", ++ "aa98a2b6176ea86415b9aff3268c6f6d", ++ "ec3e1efa5ed195eff667e16b1af1e39e", ++ "e40787dca57411d2630db2de699beb08", ++ "554835890735babd06318de23d31e78a", ++ "493957feecddc302ee2bb2086b6ebfd3", ++ "f6069709ad5b0139163717e9ce1114ab", ++ "ba5ed386098da284484b211555505a01", ++ "9244c8dfad8cbb68c118fa51465b3ae4", ++ "51e309a5008eb1f5185e5cc007cfb36f", ++ "6ce9ff712121b4f6087955f4911eafd4", ++ "59b51d8dcda031218ccdd7c760828155", ++ "0012878767a3d4f1c8194458cf1f8832", ++ "82900708afd5b6582dc16f008c655edd", ++ "21302c7e39b5a4cdf1d6f86b4f00c9b4", ++ "e894c7431591eab8d1ce0fe2aa1f01df", ++ "b67e1c40ee9d988226d605621854d955", ++ "6237bdafa34137cbbec6be43ea9bd22c", ++ "4172a8e19b0dcb09b978bb9eff7af52b", ++ "5714abb55bd4448a5a6ad09fbd872fdf", ++ "7ce1700bef423e1f958a94a77a94d44a", ++ "3742ec50cded528527775833453e0b26", ++ "5d41b135724c7c9c689495324b162f18", ++ "85c523333c6442c202e9e6e0f1185f93", ++ "5c71f5222d40ff5d90e7570e71ab2d30", ++ "6e18912e83d012efb4c66250ced6f0d9", ++ "4add4448c2e35e0b138a0bac7b4b1775", ++ "c0376c6bc5e7b8b9d2108ec25d2aab53", ++ "f72261d5ed156765c977751c8a13fcc1", ++ "cff4156c48614b6ceed3dd6b9058f17e", ++ "36bfb513f76c15f514bcb593419835aa", ++ "166bf48c6bffaf8291e6fdf63854bef4", ++ "0b67d33f8b859c3157fbabd9e6e47ed0", ++ "e4da659ca76c88e73a9f9f10f3d51789", ++ "33c1ae2a86b3f51c0642e6ed5b5aa1f1", ++ "27469b56aca2334449c1cf4970dcd969", ++ "b7117b2e363378aa0901b0d6a9f6ddc0", ++ "a9578233b09e5cd5231943fdb12cd90d", ++ "486d7d75253598b716a068243c1c3e89", ++ "66f6b02d682b78ffdc85e9ec86852489", ++ "38a07b9a4b228fbcc305476e4d2e05d2", ++ "aedb61c7970e7d05bf9002dae3c6858c", ++ "c03ef441f7dd30fdb61ad2d4d8e4c7da", ++ "7f45cc1eea9a00cb6aeb2dd748361190", ++ "a59538b358459132e55160899e47bd65", ++ "137010fef72364411820c3fbed15c8df", ++ "d8362b93fc504500dbd33ac74e1b4d70", ++ "a7e49f12c8f47e3b29cf8c0889b0a9c8", ++ "072e94ffbfc684bd8ab2a1b9dade2fd5", ++ "5ab438584bd2229e452052e002631a5f", ++ "f233d14221097baef57d3ec205c9e086", ++ "3a95db000c4a8ff98dc5c89631a7f162", ++ "0544f18c2994ab4ddf1728f66041ff16", ++ "0bc02116c60a3cc331928d6c9d3ba37e", ++ "b189dca6cb5b813c74200834fba97f29", ++ "ac8aaab075b4a5bc24419da239212650", ++ "1e9f19323dc71c29ae99c479dc7e8df9", ++ "12d944c3fa7caa1b3d62adfc492274dd", ++ "b4c68f1fffe8f0030e9b18aad8c9dc96", ++ "25887fab1422700d7fa3edc0b20206e2", ++ "8c09f698d03eaf88abf69f8147865ef6", ++ "5c363ae42a5bec26fbc5e996428d9bd7", ++ "7fdfc2e854fbb3928150d5e3abcf56d6", ++ "f0c944023f714df115f9e4f25bcdb89b", ++ "6d19534b4c332741c8ddd79a9644de2d", ++ "32595eb23764fbfc2ee7822649f74a12", ++ "5a51391aab33c8d575019b6e76ae052a", ++ "98b861ce2c620f10f913af5d704a5afd", ++ "b7fe2fc8b77fb1ce434f8465c7ddf793", ++ "0e8406e0cf8e9cc840668ece2a0fc64e", ++ "b89922db99c58f6a128ccffe19b6ce60", ++ "e1be9af665f0932b77d7f5631a511db7", ++ "74b96f20f58de8dc9ff5e31f91828523", ++ "36a4cfef5a2a7d8548db6710e50b3009", ++ "007e95e8d3b91948a1dedb91f75de76b", ++ "a87a702ce08f5745edf765bfcd5fbe0d", ++ "847e69a388a749a9c507354d0dddfe09", ++ "07176eefbc107a78f058f3d424ca6a54", ++ "ad7e80682333b68296f6cb2b4a8e446d", ++ "53c4aba43896ae422e5de5b9edbd46bf", ++ "33bd6c20ca2a7ab916d6e98003c6c5f8", ++ "060d088ea94aa093f9981a79df1dfcc8", ++ "5617b214b9df08d4f11e58f5e76d9a56", ++ "ca3a60ee85bd971e1daf9f7db059d909", ++ "cd2b7754505d8c884eddf736f1ec613e", ++ "f496163b252f1439e7e113ba2ecabd8e", ++ "5719c7dcf9d9f756d6213354acb7d5cf", ++ "6f7dd40b245c54411e7a9be83ae5701c", ++ "c8994dd9fdeb077a45ea04a30358b637", ++ "4b1184f1e35458c1c747817d527a252f", ++ "fc7df674afeac7a3fd994183f4c67a74", ++ "4f68e05ce4dcc533acf9c7c01d95711e", ++ "d4ebc59e918400720035dfc88e0c486a", ++ "d3105dd6fa123e543b0b3a6e0eeaea9e", ++ "874196128ed443f5bdb2800ca048fcad", ++ "01645f134978dc8f9cf0abc93b53780e", ++ "5b8b64caa257873a0ffd47c981ef6c3f", ++ "4ee208fc50ba0a6e65c5b58cec44c923", ++ "53f409a52427b3b7ffabb057ca088428", ++ "c1d6cd616f5341a93d921e356e5887a9", ++ "e85c20fea67fa7320dc23379181183c8", ++ "7912b6409489df001b7372bc94aebde7", ++ "e559f761ec866a87f1f331767fafc60f", ++ "20a6f5a36bc37043d977ed7708465ef8", ++ "6a72f526965ab120826640dd784c6cc4", ++ "bf486d92ad68e87c613689dd370d001b", ++ "d339fd0eb35edf3abd6419c8d857acaf", ++ "9521cd7f32306d969ddabc4e6a617f52", ++ "a1cd9f3e81520842f3cf6cc301cb0021", ++ "18e879b6f154492d593edd3f4554e237", ++ "66e2329c1f5137589e051592587e521e", ++ "e899566dd6c3e82cbc83958e69feb590", ++ "8a4b41d7c47e4e80659d77b4e4bfc9ae", ++ "f1944f6fcfc17803405a1101998c57dd", ++ "f6bcec07567b4f72851b307139656b18", ++ "22e7bb256918fe9924dce9093e2d8a27", ++ "dd25b925815fe7b50b7079f5f65a3970", ++ "0457f10f299acf0c230dd4007612e58f", ++ "ecb420c19efd93814fae2964d69b54af", ++ "14eb47b06dff685d88751c6e32789db4", ++ "e8f072dbb50d1ab6654aa162604a892d", ++ "69cff9c62092332f03a166c7b0034469", ++ "d3619f98970b798ca32c6c14cd25af91", ++ "2246d423774ee9d51a551e89c0539d9e", ++ "75e5d1a1e374a04a699247dad827b6cf", ++ "6d087dd1d4cd15bf47db07c7a96b1db8", ++ "967e4c055ac51b4b2a3e506cebd5826f", ++ "7417aa79247e473401bfa92a25b62e2a", ++ "24f3f4956da34b5c533d9a551ccd7b16", ++ "0c40382de693a5304e2331eb951cc962", ++ "9436f949d51b347db5c8e6258dafaaac", ++ "d2084297fe84c4ba6e04e4fb73d734fe", ++ "42a6f8ff590af21b512e9e088257aa34", ++ "c484ad06b1cdb3a54f3f6464a7a2a6fd", ++ "1b8ac860f5ceb4365400a201ed2917aa", ++ "c43eadabbe7b7473f3f837fc52650f54", ++ "0e5d3205406126b1f838875deb150d6a", ++ "6bf4946f8ec8a9c417f50cd1e67565be", ++ "42f09a2522314799c95b3fc121a0e3e8", ++ "06b8f1487f691a3f7c3f74e133d55870", ++ "1a70a65fb4f314dcf6a31451a9d2704f", ++ "7d4acdd0823279fd28a1e48b49a04669", ++ "09545cc8822a5dfc93bbab708fd69174", ++ "efc063db625013a83c9a426d39a9bddb", ++ "213bbf89b3f5be0ffdb14854bbcb2588", ++ "b69624d89fe2774df9a6f43695d755d4", ++ "c0f9ff9ded82bd73c512e365a894774d", ++ "d1b68507ed89c17ead6f69012982db71", ++ "14cf16db04648978e35c44850855d1b0", ++ "9f254d4eccab74cd91d694df863650a8", ++ "8f8946e2967baa4a814d36ff01d20813", ++ "6b9dc4d24ecba166cb2915d7a6cba43b", ++ "eb35a80418a0042b850e294db7898d4d", ++ "f55f925d280c637d54055c9df088ef5f", ++ "f48427a04f67e33f3ba0a17f7c9704a7", ++ "4a9f5bfcc0321aea2eced896cee65894", ++ "8723a67d1a1df90f1cef96e6fe81e702", ++ "c166c343ee25998f80bad4067960d3fd", ++ "dab67288d16702e676a040fd42344d73", ++ "c8e9e0d80841eb2c116dd14c180e006c", ++ "92294f546bacf0dea9042c93ecba8b34", ++ "013705b1502b37369ad22fe8237d444e", ++ "9b97f8837d5f2ebab0768fc9a6446b93", ++ "7e7e5236b05ec35f89edf8bf655498e7", ++ "7be8f2362c174c776fb9432fe93bf259", ++ "2422e80420276d2df5702c6470879b01", ++ "df645795db778bcce23bbe819a76ba48", ++ "3f97a4ac87dfc58761cda1782d749074", ++ "50e3f45df21ebfa1b706b9c0a1c245a8", ++ "7879541c7ff612c7ddf17cb8f7260183", ++ "67f6542b903b7ba1945eba1a85ee6b1c", ++ "b34b73d36ab6234b8d3f5494d251138e", ++ "0aea139641fdba59ab1103479a96e05f", ++ "02776815a87b8ba878453666d42afe3c", ++ "5929ab0a90459ebac5a16e2fb37c847e", ++ "c244def5b20ce0468f2b5012d04ac7fd", ++ "12116add6fefce36ed8a0aeccce9b6d3", ++ "3cd743841e9d8b878f34d91b793b4fad", ++ "45e87510cf5705262185f46905fae35f", ++ "276047016b0bfb501b2d4fc748165793", ++ "ddd245df5a799417d350bd7f4e0b0b7e", ++ "d34d917a54a2983f3fdbc4b14caae382", ++ "7730fbc09d0c1fb1939a8fc436f6b995", ++ "eb4899ef257a1711cc9270a19702e5b5", ++ "8a30932014bce35bba620895d374df7a", ++ "1924aabf9c50aa00bee5e1f95b5d9e12", ++ "1758d6f8b982aec9fbe50f20e3082b46", ++ "cd075928ab7e6883e697fe7fd3ac43ee", ++} ++ ++// hashes2X is taken from ++// https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2-kat.json ++var hashes2X = []string{ ++ "0e", ++ "5196", ++ "ad6bad", ++ "d8e4b32f", ++ "8eb89056f3", ++ "410497c2ed72", ++ "f0de771b375c90", ++ "8662db8685033611", ++ "9ef9f1eed88a3f52ca", ++ "08225082df0d2b0a815e", ++ "0f6e84a17439f1bc97c299", ++ "895ec39c78d3556cefdbfabc", ++ "2b396b3fa90ab556079a79b44d", ++ "abae26501c4c1d6123c0f2289111", ++ "bca098df9099b3f785a37ba40fce5f", ++ "19b827f054b67a120f11efb0d690be70", ++ "b88d32a338fd60b58570fda228a121113b", ++ "3f30143af1cad33f9b794576e078cc79062e", ++ "ffddb58d9aa8d38086fcdae07e6653e8f31dfc", ++ "abb99c2e74a74556919040ca0cd857c95ec985e9", ++ "71f13f89af55ba936f8a7188ee93d2e8fb0cf2a720", ++ "99734fdf0eef4838a7515426f4c59b800854e2fcdc1c", ++ "579b1652aa1f5779d2b0e61868af856855020bdd44d7a7", ++ "1383d4ab4a6d8672b4075d421a159f69380ff47e4bb518d5", ++ "d3fa1412712dbbab71d4c6265dc1585c8dcc73380cf807f76a", ++ "1d57868a71e7245667780455d9aaa9e0683baf08fbaf946091c2", ++ "ef80418fe7049c6251ed7960a6b0e9def0da2749781994b24593a0", ++ "ef91cb81e4bfb50231e89475e251e2ef2fde59357551cd227588b63f", ++ "d7f398a5d21c3139cff0562a84f154b6953c7bc18a5f4b60491c196b6d", ++ "0a2abc6d38f30aef253579a4088c5b9aec64391f37d576eb06a300c193a5", ++ "02dd758fa23113a14fd94830e50e0f6b86faec4e551e808b0ca8d00fef2a15", ++ "a4fe2bd0f96a215fa7164ae1a405f4030a586c12b0c29806a099d7d7fdd8dd72", ++ "7dce710a20f42ab687ec6ea83b53faaa418229ce0d5a2ff2a5e66defb0b65c03c9", ++ "0320c40b5eea641d0bc25420b7545ac1d796b61563728a4dc451207f1addeedcf860", ++ "460539415f2baeb626fad748dee0eb3e9f27221661160e13edf39d1b5d476ee0672400", ++ "02de8ffa5b9c748164f99ed9d678b02e53f4ae88fb26c6d94a8cefc328725a692eae78c2", ++ "348a61a0136436136910262ad67ef20644b32c15456d5fad6b1679386d0bea87cc1a2e2b5e", ++ "24c32966c803434d48d2283482ee8f404f598cf7a17961748125d2ed1da987039b1ce00f2ba7", ++ "bd07cb16121d3b47adf03b96c41c947beadc01e40548e0d0773e61780d48d33a0e2a675ca681a6", ++ "a35844e34c20b4b9371b6c52fac412afe5d80a4c1e40aa3a0e5a729dc3d41c2c3719d096f616f0ba", ++ "6df1efbb4567747fe98d218935612f8835852dde2ce3dec767792d7f1d876cdae0056fef085245449d", ++ "48d6094af78bd38d8f4b39c54279b80ef617bc6ad21def0b2c62113b656c5d6a55aea2e3fde94a254b92", ++ "cd6e684759d2f19083164712c2aca0038442efb5b646594396b1fccdbd21203290f44cfdecca0373b3801b", ++ "155dfbf26103c8354362663677fa27d0e1ce3487a821a2a7171014c1bd5dd071f4974df272b1374765b8f2e1", ++ "15b11067f311efa4ee813dbca48d690dc92780656bc4d4c56510523190a240180867c829a8b8b9844175a8aa23", ++ "9bc27953a17fb84d5eabe95b4ea6bc03ea450274abccfb6f3938ded8560fb59662459a11a86b0e0f32fbea6bb1f8", ++ "03b78fb0b34fb8662accdf350a6be75ace9789653ee4375d351e871f6a98ac5e782ca4b4a717665d25e49a5ae25d81", ++ "687e9a6fda6e2ce0e40e4d30fef38c31e3513d2892bbe85c991fc3715947e42bc49bcd079a40ed061c2c3665efe555ab", ++ "f3886027d2049a8909e26545bd202d6a6fa2a6f815d31c7d520f705a81fa606dd695369c37aee4fa77dc645e9b05813ceb", ++ "e4a412ccd20b97797d91ccc286904fcd17c5afe8bed0618f1af333c052c473cd327637d951c32e4af047106036a3bc8c1c45", ++ "92f4b8c240a28b6238bc2eabadaf2ff3c4bfe0e6c61268ace6aebdeb0691450caea4287db8b329bde96af8cdb8a0fe2f57ef2d", ++ "e506834b3445e1a9a9b7bae844e91e0834512a06c0dc75fa4604e3b903c4e23616f2e0c78b5cc496660b4a13064bb1138edef4ff", ++ "27031955a40d8dbd1591f26e3c26e367a3c68f8204a396c6a4ba34b89672896d11276966a42bd516716f35ed63e442e116dbcf35da", ++ "646b1635c68d2328dddd5ac26eb9877c24c28390a45753a65044c3136ae2fe4fb40d09bf555271646d3dceb1ab1b7c8d8e421f553f94", ++ "f6171f8d833743bdee7cc8f8b29c38614e1d2d8d6a5fff68bec2c0f4dd463d7941ff5c368e2683d8f1dc97119bde2b73ca412718bc8cb1", ++ "45db1c478b040aa2e23fb4427017079810775c62abe737e82ec0ef8dcd0fc51f521f29fe6412fff7eac9beb7bcf75f483f3f8b971e42454b", ++ "500dab14687db3ca3dde9304af5f54194b37bdf475628af46b07bfbf6bc2b64ecef284b17f9d1d9be41794699bc0e76c2878b3a55730f7142d", ++ "31bba2efc7b3f415c3f031d4c06bb590ae40085ad157370af30238e03e25a359c9e133212ed34b7a006f839173b577e7015a87fdff2270fafddb", ++ "0600b3fb4b5e1ed0c8b2698ac1d9905e67e027390764821f963ad8d2b33cbc378b9c25c3ee422992d22b760222ed5697be0576d73938ae9d634ed7", ++ "4c0ca4f177d132594a4c613bad68da24c564efa3b4da0d0a903f26534a2e09f8d799d10e78f48ccdb0203954a36c5cf1bf24c076632c2b022b041200", ++ "97aacf2e1b013677b2e14084f097cb1e64d7b3fa36f097e189d86dc4a263bcc46817cd1ee6ff0c7ccd9acef63201cdc0e36254e19204a7388643bb571f", ++ "71fd6846ce7adb0843d6063546a16b79b54ad6c0f018a479a45817624fa221f63525084860559d1a0679c8d89a80701c62743ec2da8419d503f8f0cd7946", ++ "f73dfb046def3362d6de36077dae2cee2587fe95fe0800548bb7d99737897096ba59052e0dadcc1fb0ccb5535391875328637a0376a43a4d89366758dfe3e2", ++ "ec470d0aa932c78c5bcf86203ec0014314114765fa679c3daef214f883a17e1b4ca12f44433772a6e4ef685c904b2fc35586c6bd88f325b965968b06d808d73f", ++ "cf601753ffa09fe48a8a84c37769991e96290e200bbaf1910c57760f989bd0c72e6128e294528ee861ad7eee70d589de3cf4a0c35f7197e1925a64d0133628d87d", ++ "f15413f7d6fc54bb55829f698da92ee42fcf58dde1aa1bd07d438ecdc32ad6bf2bcdbecc99f18ed43e81b33065af5a4ca29960ae50553e610c0bbf4153d580e73dbb", ++ "84b1738adb9757fb9402ef7113581291136184d7ae35fe0b6a738da6acb0889d4d5bac7a957024e3709fa80c77d3859871ed1aa25cf488e438a2d24cfadce6008761dd", ++ "e02814bb81f250c1835a05108396b74c7878e737654bb83155e241774d04e639bbc571b413cd9349092f926c8a149a53cd33e9b63f370b6d460e504199d2e7d849db6cbe", ++ "aeee4a789956ec0913592c30ce4f9c544894da77ba447c84df3be2c869100e4df8f7e316445d844b31c3209abcc912f647735fd4a7136c2f35c6fda5b2e6708f5ca951b2b0", ++ "8cfd11ca385de3c843de84c830d59278fe79b70fb5ddbfbfc1ddefeb22c329ef2f607d1d1abbd1cd0d0cc7c5d3ed922add76aadca0d2f57b66cb16c582b6f18f60aee2f7509b", ++ "852e5ce2047d8d8b42b4c7e4987b95d23e8026a202d4567951bbbd23111e389fe33a736318546a914d2bddedfbf53846036ad9e35f29318b1f96e33eba08f071d6dc665149feb6", ++ "f225c23164979d0d13874a90ee291627e4f61a672a5578506fd3d65a12cb48a182f78350dc24c637b2f3950dc4882a5c1d5d5bad551c6f3e0093aa87e962bea51566af3791d52d65", ++ "5f33864d882455f8ef046aed64e2d1691e5c1555e333b0852750592e6f00d3b5ec941d0c00e99629612795d5870cf93c984b45e4464ba072a34903b400a42824ac13da28c7c1cb1959", ++ "7baaee7c3eb68c18c5ae1d45ba381803de34e36a52e2d7ccc9d48a297273c4d8644b473195bc23005f7a4f5ca790b1fa11f6a96e585e635513f11745dd97a69c1222204ab28d3c7735df", ++ "d0a2a3fc450ef9af7ae982041feb2842901026467d87839c33b4a9e081ea63d5be60ae99ca6e42393ded45255b8f42886f87ba0310572d9f0d8b5a07ff4b6bae1f30559a844983cc568560", ++ "3aa4164462b3e7044c35b08b047b924790f6d5c520b1df4305b5d41f4717e81f0cd4bccb9a5a6594773832b8707443adde4047caaed2293f92234df257df54ed275a9658fab483d0576d33a9", ++ "c8b4239fd7f1b893d978268f77f6505b5775d89090374322d40083b0f4c437423f670ca213f7fe05c61069725da2561646eefaea597ac48e293fbad44c2872046857e56d04a426a84008cefd71", ++ "f94839a7024c0a16971271b6727c081770110c957b1f2e03be03d2200b565cf8240f2873b0426042aaea996a1784fadb2b27f23bc1a521b4f7320dfbed86cd38d75141365ba9b443defc0a3b4078", ++ "8af934fdc8b3376ca09bdd89f9057ed38b656bff96a8f8a3038d456a265689ca32036670cb01469cc6e958cc4a46f1e80d700ae56659828a65c0456b8e55f28f255bc86ce48e44377bf1f9970b617d", ++ "ada572989e42f0e38c1f7c22b46bb52a84df8f7b3b773c9f17a5823e59a9725248d703efb4cb011abc9474e8e711666ed3cfa60db48480a8160615dfabad761bc0eb843d2e46299c59b61a15b4422fdf", ++ "b11f1ea52a7e4bd2a5cf1e234b7c9eb909fb45860080f0a6bdb5517a37b5b7cd90f3a9e2297f995e96c293189b807a7bf6e7633bebbc36674544db5f18dd33020aeaf50ee832efe4d3d053873fd31ce3b9", ++ "e54b006cd96c43d19787c1ab1e08ea0f8922bdb7142e748212e7912a1f2c0a4fad1b9f5209c30960b8b83ef4960e929b155a8a48c8fb7ce4326915950cede6b98a96b6f1ecb12715b713985dacd1c1180413", ++ "ee2c2f31a414ccd8f6a790f55e09155fd50aac2a878f9014f6c6035cae9186f90cdef0b7adf3e207c3d24ddfba8cd321b2e9228b02a1182b6973da6698071fce8cc0a23a7bf0d5aefd21ab1b8dc7818549bba3", ++ "6d6810793bad6c7efe8fd56cac04a0fb8717a44c09cbfaebce196a80ac318c79ca5c2db54fee8191ee2d305b690a92bd9e2c947a3c29342a93ac05796484638787a184e4525e82aeb9afa2f9480caebb91014c51", ++ "91e4694366cff84854872667fd168d2d42eca9070cdc92fca9936e8361e7266931f418450d098a42686241d08024dd72f0024d22ba644bd414245e78608942321ff61860ba1245f83c88592dc7995c49c0c53aa8a9", ++ "608aa620a5cf145f4477694407ccd8faa3182465b29ae98d96a42f7409434c21e4671bcae079f6871a09d8f2965e4926a9b08277d32f9dd6a474e3a9fb232f27fc4235df9c02abf67f7e540ca9ddc270ee91b23a5b57", ++ "c14f75e92f75f4356ab01c8792af13383e7fef2ffb3064de55e8da0a50511fea364ccd8140134872adccad197228319260a7b77b67a39677a0dcdcadfb750333ac8e032121e278bdcdbed5e452dae0416011186d9ebf29", ++ "03fcb9f6e1f058091b11351e775184ff2cd1f31ee846c6ea8efd49dd344f4af473f92eb44eba8a019776f77bb24e294aa9f962b39feecf7c59d46f1a606f89b1e81c2715ac9aa252e9ce941d091ffb99bb52404961794cf8", ++ "11e189b1d90fcfe8111c79c5351d826f5ec15a602af3b71d50bc7ed813f36c9a682520984ae911669d3c3036223a53176794c7e17929efab2b1c5b500f24f8c83d3db5d1029c5714c6fd34eb800a913985c218071677b9885c", ++ "69f8f5db3ab0321a708ab2f4234645dade6bfda495851dbe7257f2b72e3e8378b9fa8120bc836b737a675271e519b4712d2b56b359e0f2234ba7552dd4828b939e0542e729878ac1f81b6ce14cb573e76af3a6aa227f95b2350e", ++ "be734d78fae92cacb009cc400e023086bc3a3a10e8ca7cb4d553ea85314f51383660b8508e8477af60baf7e07c04cc9e094690ae12c73e5f089763201b4b48d664b94b4f5820bd1540f4a84100fdf8fce7f6466aa5d5c34fcbab45", ++ "d61b77032403f9b6ea5ad2b760eb0157545e37f1712ec44d7926ccf130e8fc0fe8e9b15570a6214c3899a074811486182b250dc97ebdd3b61403614d935cd0a61c0899f31b0e49b81c8a9a4fe8409822c470aacfde229d965dd62f51", ++ "c31bd548e36d5fae95ed8fa6e807642711c897f0fcc3b0d00bd317ed2bca73412064618c6a84a61c71bce3e963333b0266a5656571dcc4ba8a8c9d84af4bdb445c34a7aef445b15d77698e0b13c436c928cc7fa7acd5f68867e8132993", ++ "9903b8adab803d085b634bfae2e109dd247a7d6249f203403216d9f7410c36142df8fa56fb4d6f78136eef5817bad5ea3608439bb19336628c37d42db16ab2df8018b773baedafb77278a50926370b48bd81710203c7abc7b4043f9a1751", ++ "4dadaf0d6a96022c8ce40d48f460526d9956da33260e1770315ead420da75b122c762762aa3ddc1aef9070ff2298b2304cf90443318b17183b60778f3859b141053e5827decfff27ff106a48cfdb0371d0ef614fc7400e860b676df3176d1a", ++ "314dda800f2f494ca9c9678f178940d2284cb29c51cb01ca2019a9bede0cdc50f8ecf2a77e238b884867e78e691461a66100b38f374c4ccac80309641533a3217eca7e6b9a9af01c026201f0afaec5a61629a59eb530c3cb81934b0cb5b45eae", ++ "4658b7500951f75c84e4509d74047ca621009835c0152f03c9f96ca73beb29608c44390ba4473323e621284be872bdb72175628780113e470036265d11dfcb284ac04604e667f1e4c1d357a411d3100d4d9f84a14a6fabd1e3f4de0ac81af50179", ++ "491f877592837e7912f16b73ee1fb06f4633d854a5723e156978f48ec48fbd8b5e863c24d838ff95fa865155d07e5513df42c8bb7706f8e3806b705866475c0ac04bbe5aa4b91b7dc373e82153483b1b03304a1a791b058926c1becd069509cbf46e", ++ "231034720c719ab31f7c146a702a971f5943b70086b80a2a3eb928fa9380b7a1ad8773bfd0739142d2ad6e19819765ca54f92db5f16c1df5fa4b445c266215a92527bd4ef50ed277b9a21aee3fb7a8128c14ce084f53eac878a7a660b7c011eb1a33c5", ++ "3366860c77804fe0b4f368b02bb5b0d150821d957e3ba37842da9fc8d336e9d702c8446ecafbd19d79b868702f32405853bc17695873a7306e0ce4573cd9ac0b7fc7dd35534d7635198d152a1802f7d8d6a4bb07600fcdaacfaa1c3f40a09bc02e974c99", ++ "ccbbbe621f910a95835f5f8d74b21e13f8a4b03f72f91f37b5c7e995aa3cd5539508d5e234e77a4668a42c239b2d13ef0e55ecf85142055e3f8a7e46320e21324a6b88e6c823ac04b485125c2aa59b61476481208f92ea4dd330cb18777c1cf0df7cd07893", ++ "87faf0e49e7e5ab66ee3147921f8817867fe637d4ab694c33ee8009c759e7d707f44c69c1b9754e2b4f8f47b25f51cd01de7273f548f4952e8efc4d9044c6ea72d1d5857e0ffeb3f44b0c88cb67683401cfb2f1d17f0ca5696641bef28d7579f68d9d066d968", ++ "38c876a007ec727c92e2503990c4d9407cea2271026aee88cd7b16c4396f00cc4b760576adf2d683713a3f6063cc13ecd7e4f3b6148ad914ca89f34d1375aa4c8e2033f1315153189507bfd116b07fc4bc14f751bbbb0e752f621153ae8df4d68491a22430b309", ++ "87d636a33dbd9ad81ecd6f3569e418bf8a972f97c5644787b99c361195231a72455a121dd7b3254d6ff80101a0a1e2b1eb1ca4866bd23063fe007310c88c4a2ab3b49f14755cd0ee0e5ffa2fd0d2c0ea41d89e67a27a8f6c94b134ba8d361491b3c20bacac3d226b", ++ "b021af793badbb857f9a353e320450c44c1030fce3885e6b271bcc02e6af65fdc5be4dc483ff44bd5d539ed1e7eb7efe3001252e92a87df8227ace601047e101c871d29302b3cb6c6f4639078afc81c4c0f4c2e04688612ecf3f7be1d58ea92894a5dab49b949f2089", ++ "c5c1f2fbf2c8504a686b615278fc6221858d401b7fe790b75fb6bca6885cdd128e9142bf925471ee126f9e62d984de1c30c9c677eff5fdbd5eb0fa4ef3bff6a831056cea20fd61cf44d56ffc5bda0e8472ecdc67946d63c40db4ba882bc4dfa16d8ddac600570b9b6bf3", ++ "88f8cc0daeaeaea7ab0520a311dff91b1fd9a7a3ec778c333422c9f3eb0bc183acc80dfefb17a5ac5f95c490693c45666ec69234919b83244003191bad837aa2a237daeb427e07b9e7aa6ca94b1db03d54ee8f4fe8d0802cb14a6599005eb6326eefe5008d9098d40aa851", ++ "2eb6b1a58e7fe39ff915ac84c2f21a22432c4f0d260380a3f993310af048b11647f95d23adf8a746500833ee4e467fb52ea9f1039519fa58bcb0f1d0151558147b3c92b83730aba0e20eeeea2b75f3ff3ad79f2f8a46cbbadb114a52e32f018342aeeaf827e03ad6d583bbce", ++ "3ba7dcd16a98be1df6b904457709b906cbf8d39516ef107006c0bf363db79f91aaae033466624d30858e61c2c368599963e49f22446e4473aa0df06e9c734e183a941510d540536377072334910e9cef56bc66c12df310ecd4b9dc14207439c1da0ac08bdd9be9f2c840df207e", ++ "a34a7926324ea96867dac6f0dba51d753268e497b1c4f272918c7eb0e34120be65b7b5ba044d583141ec3ea16fcedae6197116b16562fb0706a89dc8efd3ba173ccd0fd7d84d480e0a3dda3b580c326aa1caca623879b0fb91e7d173998889da704eda6495023b5ad4c9ad406298", ++ "5ef97d80b90d5c716322d9ba645a0e1b7a403968258a7d43d310320f60f96235f50e9f22cac0ad239636521fa0607d2f471051b505b371d88778c46fe6787d47a91a5bec4e3900fe6ed22918226fc9fbb3f70ee733c369420612b76b5f55988d757c891d7005d17ee55783fe506202", ++ "140d2c08dae0553f6a49585fd5c217796279152b2e100ebde6812d6e5f6b862b2a3a484aed4d6226197e511be2d7f05f55a916e32534ddcb81bdcf499c3f44f526eb515cc3b6fa4c4039ad251253241f541558bba7413ca29318a414179048a054104e433c674ca2d4b3a4c181878727", ++ "29fdfc1e859b001ee104d107216b5299a792d26b2418e823e0381fa390380d654e4a0a0720ba5ff59b2ff22d8c4e013284f980911dcfec7f0dca2f89867f311ced1ac8a14d669ef1114504a5b7626f67b22ecd86469800f1575543b72ab1d4c5c10ee08f06159a4a3e1ae09937f12aa173", ++ "52dfb643832a598a10786a430fc484d6370a05356ee61c80a101dbbcfac75847fba78e27e537cc4eb918eb5ab40b968d0fb23506fee2ad37e12fb7534fb55a9e50902b69ceb78d51db449cbe2d1fc0a8c0022d8a82e2182b0a059035e5f6c4f4cc90278518e178becfbea814f317f9e7c051", ++ "d32f69c6a8ee00ca83b82eaf82e312fbb00d9b2f6202412a1ffc6890b4509bbbeda4c4a90e8f7bca37e7fd82bd23307e2342d27aa10039a83da55e84ce273822740510e4ec239d73c52b0cbc245ad523af961994f19db225212bf4cc160f68a84760233952a8e09f2c963be9bb1d71ca4bb265", ++ "d1e603a46aa49ee1a9ded63918f80feca5fc22fb45f659fd837ff79be5ad7faf0bbd9c4ba91628ee293b478a7e6a7bd433fa265c20e5941b9ea7edc906055ce9799cbb06d0b33ae7ed7f4b918cc082c3d4a1ac317a4acec175a73cc3eeb7cb97d96d24133a29c19375c57f3a4105519846dd14d4", ++ "b45ac88fac2e8d8f5a4a90930cd7523730733369af9e39bf1ffb833c01108952198301f4619f04b9c399fef04c214bad3358999967c474b67a7c06457a1d61f9466489ed5c0c64c6cdc83027386d6263491d18e81ae8d68ca4e396a71207adaaa60997d0dca867065e68852e6dba9669b62dc7672b", ++ "d5f2893edd67f8a4b5245a616039ffe459d50e3d103ad4675102028f2c497ea69bf52fa62cd9e84f30ae2ea40449302932bbb0a5e426a054f166fdbe92c744314cc0a0aa58bbc3a8739f7e099961219ec208a8d01c1ae8a2a2b06534bf822aaa00ca96218e430f0389c69c7f3fd195e128c38d484ff6", ++ "37279a76e79f33f8b52f29358841db9ec2e03cc86d09a335f5a35c0a31a1db3e9c4eb7b1d1b978332f47f8c3e5409d4e443e1d15342a316f442e3bfa151f6a0d216df2443d80cbcf12c101c51f2946d81161583218584640f4f9c10de3bb3f4772bd3a0f4a365f444777456b913592719818afb26472b6", ++ "a46d252a0addf504ad2541e7d992cbed58a22ea5679980fb0df072d37540a77dd0a1448bdb7f172da7da19d6e4180a29356ecb2a8b5199b59a24e7028bb4521f3281313d2c00da9e1d284972ab6527066e9d508d68094c6aa03537226ef19c28d47f91dddebfcc796ec4221642ddf9de5b80b3b90c22d9e7", ++ "060c18d8b57b5e6572dee194c69e265c2743a48d4185a802eaa8d4dbd4c66c9ff725c93667f1fb816418f18c5f9be55e38b7718a9250bc06284bd834c7bd6dfcd11a97c14779ac539629bcd6e15b5fca3466d14fe60d8671af0fb8b080218703bc1c21563b8f640fde0304a3f4aeb9ec0482f880b5be0daa74", ++ "8f2f42bc01acca20d36054ec81272da60580a9a5414697e0bdb4e44a4ab18b8e690c8056d32f6eaaf9ee08f3448f1f23b9844cf33fb4a93cba5e8157b00b2179d18b6aa7215ae4e9dc9ad52484ad4bfb3688fc80565ddb246dd6db8f0937e01b0d2f2e2a64ad87e03c2a4ad74af5ab97976379445b96404f1d71", ++ "ccb9e524051cca0578aa1cb437116a01c400338f371f9e57525214ad5143b9c3416897eae8e584ce79347297071f67041f921cbc381c2be0b310b8004d039c7cc08cb8ff30ef83c3db413f3fb9c799e31cd930f64da1592ec980cc19830b2a448594cb12a61fc7a229e9c59fe1d66179772865894afd068f0942e5", ++ "3eb5dc42172022ab7d0bc465a3c725b2d82ee8d9844b396913ceb8a885323dbbbf9ef4ed549724cc96d451ea1d1d44a8175a75f2a7d44bb8bfc2c2dffed00db0328cfde52bf9171f4025770abbe59b3aefd8151c480bafa09f613955fd571e5d8c0d4936c670d182cf119c068d420ded12af694d63cd5aef2f4f6f71", ++ "20ea77e58e41337ad63f149ed962a8210b6efa3747fe9bea317c4b48f9641f7145b7906ed020a7ae7d2ee59435392edc32aee7eff978a661375af723fbd440dd84e4a152f2e6ef66f4ab1046b22c77ac52717de721dfe39aa8ba8cd5da27baca00cc1fffe12c52382f0ee83ad1418f4c6a122effaf7471e1e125d7e7ba", ++ "95c662b835171fa23f948c3c3ed27bab9b3c367bbfe267fe65f8037a35b50cd7fc6030bfce4000425ef646c34793f0762635ae70487a0216ef7428da622be895d1b6040423246511c2370d6876a5c5d2df8bbd48fb14f787b632ad2c1f5a927fdf36bc493c1c8606accfa52de33258669f7d2d73c9c81119591c8ea2b0ef", ++ "f708a230675d83299cc43167a771602d52fa37cbc068ef9128ef60d186e5d98efb8c98798da619d2011bf4673214f4a4c82e4b11156f6292f6e676d5b84dc1b81e7cc811b0d37310ac58da1bfcb339f6ba689d80dd876b82d131e03f450c6c9f15c3a3b3d4db43c273c94ed1d1bd6d369c4d30256ff80ea626bda56a6b94ea", ++ "f8417766ce86b275f2b7fec49da832ab9bf9cb6fdfe1b916979ae5b69176d7e0293f8d34cb55cf2b4264a8d671370cb595c419c1a3ce5b8afa642208481333522005fbe48cdc700e47b29254b79f685e1e91e7e34121784f53bd6a7d9fb6369571bba992c54316a54e309bbc2d488e9f4233d51d72a0dd8845772377f2c0feb9", ++ "3479e04efa2318afc441931a7d0134abc2f04227239fa5a6ae40f25189da1f1f313732026631969d3761aea0c478528b129808955be429136eeff003779dd0b8757e3b802bdff0f5f957e19278eabad72764aa74d469231e935f4c80040462ab56094e4a69a82346b3aeb075e73a8e30318e46fdaec0a42f17ccf5b592fb800613", ++ "03df0e061fa2ae63b42f94a1ba387661760deaab3ec8ffabcaff20eeed8d0717d8d09a0eafd9bde04e97b9501ac0c6f4255331f787d16054873f0673a3b42ce23b75a3b38c1ebcc04306d086c57a79d6095d8ce78e082a66c9efca7c2650c1046c6e0bbce0b2cba27c3824333e50e046e2a7703d3328ab3b82c9d6a51bc99b9516ff", ++ "76b488b801932932beefffdd8c19cf5b4632306e69e37e6a837e9a20c8e073bcadd5640549faa4972ebd7ee55cb2425b74cb041a52dd401b1a531beb6dfb23c4cfe74bc84f034156c8f55050ca93236eb73c4e2595d9fbf93dc49e1ec9a31705359732dda73f737ec4274e5c82626dc4ec929e5e2c7a2f5f5fb666181922bd8be575e3", ++ "ff17f6ef13abc0426b03d309dc6e8eeb822300f7b87eff4f9c44140a424098fd2aef860e5646066d22f5e8ed1e82a459c9b9ad7b9d5978c29718e17bff4eeefd1a80ba48108b551e62cd8be919e29edea8fbd5a96dfc97d01058d226105cfcdec0fba5d70769039c77be10bd182bd67f431e4b48b3345f534f08a4beb49628515d3e0b67", ++ "95b9d7b5b88431445ec80df511d4d106db2da75a2ba201484f90699157e5954d31a19f34d8f11524c1dabd88b9c3adcdba0520b2bdc8485def670409d1cd3707ff5f3e9dffe1bca56a23f254bf24770e2e636755f215814c8e897a062fd84c9f3f3fd62d16c6672a2578db26f65851b2c9f50e0f42685733a12dd9828cee198eb7c835b066", ++ "010e2192db21f3d49f96ba542b9977588025d823fc941c1c02d982eae87fb58c200b70b88d41bbe8ab0b0e8d6e0f14f7da03fde25e10148887d698289d2f686fa1408501422e1250af6b63e8bb30aac23dcdec4bba9c517361dff6dff5e6c6d9adcf42e1606e451b0004de10d90f0aed30dd853a7143e9e3f9256a1e638793713013ebee79d5", ++ "02aaf6b569e8e5b703ff5f28ccb6b89bf879b7311ea7f1a25edd372db62de8e000219afc1ad67e7909cc2f7c714c6fc63ba341062cebf24780980899950afc35cef38086ee88991e3002ae17c07fd8a16a49a8a90fc5540be0956dff95390c3d37629949de99920d93096eb35cf0427f75a6561cf68326e129dbeffb8772bfdce245d320f922ae", ++ "70752b3f18713e2f533246a2a46e38a83cc36dfccec07c1030b5204cba4432700735a8cee538b078d281a2d0262110381c5815a112bb84404f55af91652bd17502dd75e4910e062943d8a736ae3eecdfdd8e3f83e0a5e2ddeeff0ccbdadaddc95391310fc657a59724f7e6560c37dc1d5bb5db40170190f04a274c864ade9687c0f6a2a48283177a", ++ "01f3c1333b44077c518cc594d0fb90c37651fb7b2442e71fc0a5611097f1cf7bcfaf11c8e0ac1b1cab54afba15bb9332df6bc64d8032368e3f686c8324b0114e0979dad78a5ccd3fff88bbe89eef89c4be586ca092addef552ed33224e85d8c2f4fba85ac7735f34b6aa5ae5299154f861a9fb83046b0e8fca4db32c1343e02676f283975f43c086cf", ++ "509283ebc99ff8d87902fa00e2d2a6fa239e335fb840dbd0fdbab6ed2d95e8275402523f7ce9a2fabd4b6c9b533288fbe914bde84365a204711d0977a7d698f4614385984dd4c137e4820035dd6737da364edff1bb62283e87a8c7ae8637314fe9b5777ec4ec21276dafedb2ad5ee1aa0ac99e34a6c01c055c8a239fd28681607f65143082cd4553c529", ++ "c17e417e876db4e123c631f7136b8a85bfd6ce66a69180d0cd5ecfd6f037bb1c7bd7908d51f2c485bf9e92c0e1799ee5f6ab834ee481f5eb1a8020205adb4d0f90126d4e7c2c859c5a5f644bdfa9c649ff4f168e834de6f9769429732099d46d0af506ab86c6fd92175159bbc05c75db8e1fa867e6030d64250008d64c857c47caec3dc8b2ffb384d0193e", ++ "950988fbe9d62a66f5f2c492bc8dc944a78eb3796ec37ba94b6a81a9d402ccad03cd8497fff74c5f4a03081c5fecec48574fecb21c1de261332c23108195d3f6a96ff8e433a1a30eda53dd5bb414973334f8cde5510ff759f7c17046cbb5acd8e8c4a6eecf2a9121ec3fc4b22c4daa72678194ce809024cd45c4ebb9ccdb6f854205cdb624f0787480d8034d", ++ "552a212c403b473741da8e9c7b916d5e5e9bcc9949021ae1ca1ed46b7d4a98addbb604d9fff56175b7e0367db26c9635fa7813653dc8d610befdd09ec41e99b192a716106f4299eec8b940863e5a59cf26cdc2cd0c3017f9b4f215812bed15f69e77edf672178e13c55580982f01fcc2fa131ec3d736a55d56504c545f4be50fee83f1263e4d3f3c877cc6242c", ++ "b00c4283dd3d9cd26e44bd97cede6c771cb14f2571b51cfdaae4309560ffd165da025a1bbd31096c3aa8286e2d6dcc3e681b8d01f2c5064ea26dfd0b5156b7a7f5d1e046c5bd1628f8fdae24b03bdf7cf7366900cc013a8cbed9d7f5937c914b08f8c27683b956e1279812d04288515333fc6aba3684dde2292951f0610649d90fe61606630fc6a4cd383649252c", ++ "f6e79457bb6d0884dd223be2cf5ae412a1ed425f1e4012f75951b096aea3b9f3581f9013bcae1aff2d3fc1e5c7e06f24af6d53c2c5c238b71c71cc670b05a7ee5204400026a5c4e5ddec3ad96771e49fae4b0f75ec58049ad9d972e5749a32d90f847f1ed2a1bab83db181e541cf5c8adb6b29ecc64dc25add491d408d3eb3ddcb013de7f5ffb6de9dd7ff300a5fc6", ++ "fe1d71e1d5efa3f712d23216ee8ee9139e66bd648b83efc02cdb4d45a28cf36759ff190a84d14d9471477abefb5aea4111110336143dd80cf81e02f268120cc07d746538f968e9876bff8358d390f5b8e7eafa61ecd236cedaf276bd61865fdd3424988201dcdeda2e3e0c33c9e3b3670125dd1049106cc6df5695fb2dca443233ff440f265bbff055483bac1e859b83", ++ "4c80163562872a965dedd8725652906156ada6e9d999027d96f49289edb92f9ef043e9d7c3377e091b27f85275499454af32317535997fb4aaeaf93565ad481ff7d45d2abddd4df4b60f71a6923ec30496c6ae534dc5427107ab4c5e656a322c7ab058d4c13ec0ebafa76576560697ac98f84aa4a554f98ec87134c0d7dca9184cf70412a324aac91823c0aca02537d197", ++ "fdd58c5ffe88665beb7073c8f4c22472f4bc9390cdd27a42622ca55978b000ab7579f795d4de0dfcaf521b8268980ef1d20277b07567985c0fd5030784ad6c32541ac24e99ab706105a2255fc32935c0fce6fdad9bb224d94ae4eae2a3ff08836618a3adf193630647bce1952b69da4de360f59da303519278bfd39b733cf66820a5e9e971b702f45998b69a0889f4bec8ec", ++ "ff38b15aba3794e2c81d88003e045ac6cbfc9f4833cdf896cefd8ac0c88674727ad9a9fcb9ef36574deea480e6f6e8691c8390ad73b8ea0eb3665c914b0d886546948e67d7987eea248b5feb52346ffdd965d5c835144c3bc63daf325e74b11267e32e58a914ae4521a668839d9445fececa49c5fba41f9e171698bbc7c6c97fa163a377a96456958d6e1d74f91ada56a30df8", ++ "f048c19328d60b4e59ed76940415b2c84c23883198bba5699efb0a1774ad5da6d15390c7b55d77d66f37448fe08107f42a5336408d5322f4b630e3275865fc66dccab39f6e13fabc133e5a441fe352d81c7cd9a25f145a6e2e2417d3b0bbc79eafcd7ad688c02011fd268dd44ac3f4f87b37a84a46fd9e9975962fba92c9a3486deb0c45f6a2e044df4bb79f0feeea432c5008b0", ++ "1b3e5fe6f113cce28a6f8d6f7809d3cec398cabffe9ff2ff10a7fec29a4ee4b54186063fd5307a2be393c9ecd75a37620bdb94c9c18da69b658579676ec90351d10dc33a7cb3b75798b1234f9f684d4a73a0fab2df3d5d6fdb1c1b1514d0935c1f2dd21486f91c2595b2f8f8a500ff443b9305270fb6f3da7961d9316d4ed6a135a31c4a3611d40e6585bbb34f498cd5b9a5d92676", ++ "740db337baa12b16897f17a85fa5685acc85e48338867f8ac9c0198dd650f5dfa7c17725c1262c72207e365c8aa45ffaab6470a0e5afefbfc3bb702a9766064f28cc8b796878dfdd3ca9d0216c14941438fc541fb5be0a13d29a996c5c985db4f630df067a5626db5dcd8df3a2bff17dc446e46e4079b8815da4318cb228c7722684e2a795a0ca56f500ea51951a6a385385d886f678", ++ "1465f2d578d167faa017fe8f763ce3cc8dc1e8371d774ed2a8803f12585296ee71a1f2253dd16b717a81f91f0f3641018a0111182b4e65d884b0a3d0292631ad807cdccc88bdeecb476e76f72b5246a630aff6e2401fa9570f85acb73ccb4e19ef04a932a03d7b7985dbe1e5bb410df517fe362321469e6f8b0e0cef6c31d7aa8ec06aa220620d66cc0e133fdee963589b12320fc9678e", ++ "80c051952fa6f3ef6af0f1759ec3e83c8eb91abee1de360bfa09e74b05af2475a0dbf8f9135aa25892919bbe0515898cfb6f88abc9e1891f2b2180bb97370f578973d55c13c35edb22ed80647c2a7e2884d1ccb2dc2f92d7b6ec5843ade13a608a31190ce965bde97161c4d4af1d91ca9962053f9aa51865bdf04fc23fa35a6fc3c8e888941263a26ed66c2dd0b29b2325dfbd1227c5091c", ++ "9c1e2a1aed6406052eed12b4495365f2f80e9c9645473f3549b607f20910bcd16dc3a4b173ac8d128129cdb7c76ebbc8e9a2a1ba0d822c66b367e790a69ac71f0a60ed4bff0e979148e3f3ee6607c76dbc572ee5ff17c27e4b52adebb4bedddff517f591a1977299c7cb01106f1453b098d29848ba3751c816215bb0d090c50f9e445b41b2c49d4eec83b92ce6c269ce835fd279e7cbbb5e47", ++ "466abda8944d0329d2975c0f2e2afc901f117887af301881f63b714f49a2f692fa63a8871fc0b301fe8573dc9b2689880cd8969e5072c57671e0633b041481dab25e65c9de404af033a11a8070c8ab70ca6d465318501afdd9940c7efbe1bb6d49581c222fad251dba4ee0a98efe22a3c4f74da05844523b30bbad6b080ac8df70a02da80bc9d477dfb869adb211e209a316d5dd1fd89a6b8f8e", ++ "0e89a873e07799ba9372fc95d483193bd91a1ee6cc186374b51c8e4d1f40dd3d30e08f7feecfffbea5395d480ee588a294b96304b04f1ee7bbf6200cc8876395d1db3ac813e1019bb68d27204e514fe4a61ad2cbd1782dca0e38b5538c5390bca626c5895b745cfca5dac636fd4f37fed9014ab46ae1156c7789bbcbb956ff7ee5ce9effa560731d26783dc6ae8bddd53a5d28133614d0ddeddd9c", ++ "fdde2b80bc7a577ef0a6c03e59512bd5b62c265d860b75416ef0ce374d544cbb4e3a5dbd31e3b43e82975090c28bc77d1bdec907aeceb5d1c8b71375b6d631b84a46153f5f1d195bfcb2af6f597a9cdc83782c5bbbb58c5188a87ebf375eee5212fa52523820a83106e8ecd52bedd60d95cd646159774389c07e1adcaa6b6f649408f33399ec6e507d61659696b3dd249996892d5986b654d94ff337", ++ "f5d7d66929afcdff04de30e83f248e69e89604daea782e1d82d8032e91a95c1d6fb2f5578f79b51be4397e4cd7cbc608ce143fdddbc6fb6c43ffdd394a7df0124353b919aeeac025f3eb11ff246c3b9657c1a947fc534ce48e18feffada8797037c6bc7e2d9a9e2e019fe65627b3feb28e446473e3bd413047a2587f0be6a103403cb3c33fdc212dca14d8e386aa511c22308e632f5f9528dbabaf2deb", ++ "332990a8dba55f977bc814436cf386ebbf10cb487a5f6ce83e13741bac670c6810284fbbe4e303547ef411e964fae82854e8c13cf56979b89ecfedd337aad78260060122d13dfbbf8497acb2066ed89e30a1d5c11008bd4d145b5ec353956310536304d8b8bba0793baec6d8f3ff49718a56e6694f8122078265cf5731d9ba61292c1219a1affb3679576d4998290aba3684a205c3469d40761a5c4e96b2", ++ "efbdff285027610f03182009c89b953f19721cfcdb8accd74bab6ec4bdf3f555ab902cb0dd91284269d140638aaabd211748aa4da3b18cddc653b57e461b9ad8491807c535c08fe97d89eb587c6af19ca152e72479626ab764e8b62da89fefc8354c75a44851f985746d78715a5a92798dac1a4222be27897b3f0aa63d596aa7378545f49b259aa8518c3def8a2ec8f7aa956c43668c8717052035a7c36b47", ++ "0eea9bb83bdc324fd21b03669aa922fbebc448e7d25e210294c07862cfa6e061731dfb67b4810633f4dbe2130d90fa1c65843af436e74219d213c4458dcac1c48ec4541fc6e3b7918ab2bc621aedda53658050900c3865ca57cd5dfa1d28576827401956d2dd8b861fa90ab11bb0b544ded9bd3d62e3278ed484e17db8f2d5dc5ea4d19a0e15134ba6986714c2b22c59c2f0e517b74eb92ce40d2f5b89e6d79f", ++ "25da9f90d2d3f81b420ea5b03be69df8ccf05f91cc46d9ace62c7f56ead9de4af576fbeee747b906aad69e59104523fe03e1a0a4d5d902352df18d18dc8225855c46fefeec9bd09c508c916995ed4161ee633f6e6291cb16e8cac7edcce213417d34a2c1edea84a0e613278b1e853e25fb4d66ff4c7ee4584e7f9b681c319c874d43502534e8c16a57b1ae7cc0723783807738a55b661e617ee285bdb8b845607f", ++ "a76b6f81372df09322098868d469fb3fb9beafc5edb32c674974ca7032966aaca5b5c9bffef87bfe626bd8e33d1c5f054f7d5acd3b91ff95324d1ae39eb905b9f2694fe5cb03486cee86d2f661a751b0e6c716a61d1d405494c2d4e32bf803803dc02dba2c06eecf6f97fb1f6c5fd10cfc4215c06d627c46b6a16da0854e4c7c873d50aa1bd396b35961b5fa31ac962575230c07c369f8fbc1ff2256b47383a3df2a", ++ "f9db613812f2259972d91b1598ffb166031b339913925ee385f03b3b35dc4b2f1ae78a3c3d99c6ff6a07be129ce1f4b8d994d24988d7fbd31f20535d36ab6bd0592cfb4f8c1ed9244c7fa8a3c46e91272a1a40c6cfcf261c5658476c59793bf1a3775086e41a0492f88a31e2d9d1ce75cf1c6b4b928b3545d838d1de6b61b735d921bcf72e4e0615e9ff969ef76b4b947026cb016e2660ba39b0c4c953369a52c210de", ++ "e601c7e75f80b10a2d15b06c521618ddc1836fe9b024458385c53cbfcedd79f3b4239598cd7b9f72c42dec0b29dda9d4fa842173558ed16c2c0969f7117157317b57266990855b9acbf510e76310ebe4b96c0de47d7f6b00bb88d06fad2c2f01610b9a686079f3ed84613ba477922502bc2305681cd8dd465e70e357534503b7cbc68070ad16d9c51de96ccf0aae1599299331c5655b801fd1dd48dddf6902d0e9579f0c", ++ "ee5ff4ca16d1bde59ffaf2d064eac9141c1d8f120ea2bda942b7956ba3effc5f1e725a3b40b0b9223a14d7a50df1681d14ca0e0eda7bb09c428fa3b2701f83a7a3e139485a118f6287d266dbc7fe68c87b35becabc7782537c79cb8165bdc40cc103d7b6d4b627fafa0e4113f92341ab90ceab594bfae20dadbfafd401684584598941f1ffb8e23dc8a04ecd15376cda6d849fe0dfd177538c62413622d172d9d46e05c450", ++ "1daca80db6ed9cb162ae24aae07c02f4126f07cd09ecee8e798fa1bc25c26c644333b63731b4ebc3f287f2318a820c32a3a55fc976576bc936f7384e2553d2891e3771ff24dd4c7f0256906460a8f12d30ed2b23583a0259cb00a9065a757d654d6e4603e7c7eb4a8426b527ae8a849d9350e9094b890367df3e8b23ad2df4d7dcce416bd8ea3badd037f53f7b07c02e5926515f196d62aeb9b8b14c863f067fc12c5dfc90db", ++ "27ff4e58a34ff1fcd66855d014ea17889a3cf0021a9fea3fabfd5b270ae770f40b5439e00c0d26bd9766f6fb0b4f23c5fcc195edf6d04bf708e5b0bced4f5c256e5ae47cc5651e51cd9fe9dc5d101439b9bc5cc24f76a8e8847c72686e2af1ce7098ad7bc104dad00c096a6d48b6453322e9cd6773fb91fb1eabd05dc5185a9aea07a2f64c6fea9897681b4428aaffe1fe5fd3e8ceb890b12169ec9d51eaabf0ca3d5ba415770d", ++ "75e2fb56327983b04f640717be8cba6fef3655b4d8e5539587d6478356ec397efaed818b8425d052778eb30ef0dee656c52c2aeab079ed496ae4441a365f2130432c87ba757e25b4511656ad15e2eff84d342331fd2814d1f1d11af65d98a424c115ba183437c0d0aa55f5c44b8685028a47d89d0d36a0f20aed510c366ab338f074a941b404fb349caaec821e0850a627777cc8f5abce6b509290027a2a28ff1db62a5ed2f95fc6", ++ "c6ae8b6a060917cd498aa7874ad44baff73efc89a023d9f3e9d12c03d0b7f5bcb5e24e1bc2ab2f2c67b9a9d36ff8beb51b5affd4a3510361001c80642955b22ea4bf28b81a5affe5ecdbabd8d17960a6af3825a4522fe76b3d720b5d06e66bff5379d7a8de1f5cc3e7bb75163a854d77d9b3949bf904b6c4e568682f0dab7f217f80da7303cfdc9a53c17b6b51d8ddff0ce49541e0c7d7b2eed82a9d6be4aec73274c30895f5f0f5fa", ++ "606c9a15a89cd66a00f26122e33ab0a08c4f73f073d843e0f6a4c1618271cfd64e52a055327deaaea8841bdd5b778ebbbd46fbc5f43362326208fdb0d0f93153c57072e2e84cecfe3b45accae7cf9dd1b3eaf9d8250d8174b3dade2256ecc8c3acc77f79d1bf9795a53c46c0f04196d8b492608a9f2a0f0b80294e2abe012dc01e60af94323c467f44c536bf375cddbb068c78432843703dd00544f4fff3eaa1a5a1467afaae7815f80d", ++ "88b383cb266937c4259fc65b9005a8c190ee6cc4b7d3575900e6f3f091d0a2cefa26e601259ffb3fd03083270eb63db1ffb8b4515ec454d12f0944f8f9f6869eedc2c5f1689766a748d74e79ad83ff6a1639aefdec6109342dead31e9cead50bcc00c5b2206e8aaa47fdd01397b141880490174141a1e6e19268378c1b54a84aba60ca711fd72f7df88e120dfea2caa140085a0cf73342f3c588b7edfb5b5e5ccabd68a32364746d92d536", ++ "dc0b293f1ba02a326743509f41efdfeeac1efc45137ac03e397a3273a1f586a0190cfb4ea96d6c13ca692a4de6de905c8338c3e29a04cbae76272f568b9d795cea5d758106b9d9cff6f80ef650d6b7c428ea3946c3acc594907fe4227ed68faf31f2f6775f1be5139dc0b4d73ed6308fa226b9077561c9e4c7a4df68cc6b819b0f463a11b9a09682ba99752c4db7aea9beac1d9279f2c2675d42b551d27aa2c1c34125e32f2f6f45c35bca45", ++ "5d801a7413311e1d1b19b3c321542b22e2a4ccbe340545d272abede9223741d9835a0fc80cc9da97a13f8bb4110eb4ad71093efba165b1edad0da01da89d86726e0d8e42ae003b4b50297d233c87da08406f0e7fc58ba6da5ee5ba3d2d7142cbe6632734eb2e7b7863c15cc82198ee8f9a0ae0b7f93bdbda1ed269b3824d5d3c8e78513815b17a4c0cc8c9706b9c77423a309ae3fd98e1e05cdbe9e2577834fd71f964301b10b66c316a2d8f2c", ++ "2fd32a2bc15a9e96a100624404fd0a4e54ba9f8c0543d8ccf7c5c2e35f5e8c3c11dfd497320aa903900a4ca55a2b323b3ac4a7cfcd01bf0b448db8829072bee6b77c3d7bec2e1d8b414d907288d4a804d2379546ef2e2dc628269589164b13fceb32dba6fd5d48a956ce0b5c3eb28d894a95af58bf52f0d6d6cbe51317152744b4ccfc918ed17fa6856478d580b389016b772e1d02e57d2217a204e25361d91d4845a3fa20fefe2c5004f1f89ff7", ++ "f537b437662759bef8bd64368536b9c64fffbddc5e2cbdad465c3966b7f2c4bc5b96767ef40a1c144a4f1cd49edc4cc5b57e7eb30d9b90108f6fd3c0dc8a8808b9e0bd13aa3d661c4863637c5e4ba286553694a60bef18801299ae349df53a355051dcc46a7d003c4aa613808f430e9db8ca7dfe0b3f0a4c5ab6eb306aeb53e11a01f910064fbe6ca78b2a94fac34a2602f73de3f275953e13ff5c6bb5c39b82321ead17ec0f8ecc479e6afbc926e1", ++ "1dd9fb7d5b5d5074971e69300720014deba6fbdb942bd29704cdfcd40fa5281d2a1b9f5b776183e03ff99c29587f10e8d325cb49c5c93e94f5132741b92c4086eec1374dea5c1e772cbb230c7b31f3e962eb572be810076bdb926b63732522cdf815c3ab99bbc164a1036aab103cac7b823dd21a911aec9bc794028f07b7f839bae0e68211286441f1c8d3a35b281fd321312577bbda04f643ecb2a74ec4527bb5148dbccbeba749f5ea19b6072366ba", ++ "5bd63737449de2d20ca63943953338ecf4cdd6cd0a726241adb04376385a809cc6ba0f3482a310746fbc2cd5eb214f03a14cdc548777fb0d048d659cd75a962e490c4fe47affc2430a34b10275e4c76752a115aae3a24d4fb4fad89ce4d79d65de10292f3490bfdaeabfae08ed51bda6ec8230e66cb07ddbeec26e3ef68dd71c852900659fcf0c963f4574ffe4626a33db9abf0873dde68b21138498b81e8cc44d354be4073615889a7ddff633b5447d38", ++ "a683ec8250506571f9c640fb1837e1ebb06f123e745f95e521e4ea7a0b2b08a514bbe5bdfd316903d1d6a05f5a143d94dab61d8a3a146ab40b2d6b72df2f0e945875a8aa7051ed115975f6f1567cfcbf04c5e11e3a7027b8e179ba00739181ba10b028e3df7259d0712f4a6cef96469ff737865b85fee2c2db02a6423e32505381e18a1e0b4ce3c7998b8d6b1b5e09c3a280b85486d0984c9e193b0ad2043c2bc4ad04f5b00a73956715937eebf6b3e27afc", ++ "4df9d160b8e81c42930c48956fcb46b20b6656ee30e5a51dd6317876dc33e0160d31280fc185e58479f994991d575a917073b4439919c9ac49b6a7c3f985211d084c82c9d5c5b9a2d29c5699a22e79de3958d7b0e856b9aa97493cd4563aaa04fa3977a9bb89e0bc06a82296bdc76d20c8d393770176d648712454305fdfcf4e117d05acb5a5b006a9f8d0dc66dca708c4e4103ca825d2331750685c44ce3d9b3e753455580f4d6ac4533edeeb02cebec7cc84", ++ "67bb59c3ef5ee8bc79b89a673e331e581215076cc36b68f517ca0a74f74efafe9dcc240e6d8ca4b21019c27d6c9289f4419b4f218eeb39eb741c5ebebfe0ed2f6faeec5e8c477acf71907990e8e288f4d4049111779b0635c7bbec16b76493f1c22f645745fdac2b383679fee573e4f47af45ee08d84f63a5ace4ee1c06fa41e2e6e14b7bc392e38426813087a3a461efc62ed1941dc8f1728a2bdc04fde72a0b786558783c84abd4bd100e4926979a0a5e707b1", ++ "d341147169d2937ff2373bd0a9aefa77968ec8f0d993c6f9881eb174a1911e05cdc45993cb86d149a754bbe321ae38363f9518c50dd3faf087ffeeeb6a058b226ccab7858c00ba6de0e8f4d034b1d27508da5cc473f3a413189ee6fd912d7750486912944d4dc34405ce5ccc3885fb0aabcb922bcfa9081d0ab84c288022bd501235a835eb2e1124ed1d48fd4f8682da8e7919321031326502273375625c4e3a7282b9f53452195e53c6b4b57cd5c66f621bed1814", ++ "27e7872a54dfff359ea7f0fca256983f7600236e716e111be15a1fe72eb66923ea60038ca2953b0286447dfe4fe853ca13c4d1ddc7a578f1fc5fc8598b05809ad0c64a4363c0228f8d15e28280837a16a5c4dadab681e28968ae17934639fbc124bc59212138e494eecad48f6546c38366f1b7b2a0f56f579f41fb3aef75dc5a0958b25deaa50cb7fd1c69816aa9a51874a98e57911a33daf773c6e6166cecfeec7a0cf54df01ab4b931984f54424e92e08cd92d5e43", ++ "13dcc9c2783b3fbf6711d02505b924e72ec6736131159017b966dda90986b97522bf52fd15fc0560ecb91e2175322334aaaa0097e1f3777c0be6d5d3de18ed6fa3444133486068a777443a8d0fa212ca46994944555c87ad1fb3a367db711c7ebd8f7a7a6dbb3a0207de85851d1b0ad2f4149bdd5a5ba0e1a81ff742df95edee850c0de20e90dd01753137cb8f2c64e5e4638ceb893a3879ae2c049aa5bce44d56bf3f325b6c5029b2b8e1b2da8de7d4e48ca7d8f6fbdc", ++ "9ca875115b109eab538d4ec7023600ad953cacdb49b5abe263e68b48eafac89a15e803e838d048d9625972f271cc8f36344bed7bab69abf0bf05979a4cfff273b82f9961626509765fcb4b4e7fa48212bcb3ab2b1f2dd5e2af768cba6300a813514dd13e4d269e3d36548af0cacdb18bb2439ec9459f6d847d39f5598304ec46a26d75de1f9f0c2a88db915bd26e45e1f1e68c5b5b50d1890e97a3803c36755f026863d14176b8b57f42e91d3ff37787f9b38e333e9f0433", ++ "ec006ac11e6d62b6d9b32ebe2e18c002353a9ffd5dfbc5161ab887770ddd9b8c0e19e5321e5bc105add22e473050b71f0399327c7eba1ef809f8667c1f4e2c7172e10e753705e9a083f5bce88d77521225ecd9e89f1e1caed367fb0275dc28f620fbd67e6b176c9ae5d2659e6ec662116c9f2bbca3a93043233a4861e0688db6dc1800f752c5d58aa5033c250c891d9126e534ed921a9026eb333333fa8292059b8b446f336ca6a0cb4c7946b6aea3831653122f154a4ea1d7", ++ "23deadc94481ce28188f3a0ca3e85431964cb31b60fabf381e6bd45ef0332bd4dde774b0281d317dc2e7d0c298fcf8625fa734126968df8b68ef8a35c325d84ba4fc53936ff3ffdd8838d2a8cabf8a9cac54aa444ed9875944e55994a22f7fa8538b1e983b57d9215fac5c0052029644044e790ce2f5044655608c1d7ad3bb862203ba3aba3b526606f273d342ed5721648e3f600942d3f7546f679161436389d879dd8094e1bd1b1e12cde15cd3cda4c30a40835665e4e5cf94", ++ "94701e06340114f9cf715a1fb659988d33db59e87bc4844b1500448960af757b5282f6d52967a6ae11aa4ecfc6818c962b084c811a57724f5d401191567f24ce917e4f8c3963474fdc9d2c8613c16f62446448b6da6eeae54d672825ed7606a90e4611d0e318ff00566862c955b636b5e81fec3362e8672ad2a6d222a515cf410482836deba092a51a4d464dfbbab35c50a33437ac16a88256e9e23ddd3c827cc58d3e5000ee90b12e4c5175c5733662d4848ae0d406c2f0a4f498", ++ "735b0758d5a331b2304f01081172eb95ae4115de651b1a6693c5b9543de33df25d9f421dbaeca033fc8bff57313b482778005aa9fdcbca65c643da2f3320e34197868eec3848ff3c70d7ac7d910fc332e9a359f892ae01641be253013b554a0d3f249b3586b1857e5a0f9482ebd91432a852b221f4287a6e81ed24e8064645d5b28ab9a13b26cc1420ce73dbc47b31acf8a871601022ce23bc443b1222ce9a037a2fe5226295feb4efd4fd671338f459ae146032697cf82fc55c8fbf", ++ "c48d94f14549352790079fee69e3e72ebaa380510e3581a0824066413e7044a36ad08affbf9b52b21963d2f8e092ff0ac1c973c423ade3ece5d3bca852b894675e8173290529226939c24109f50b8b0d5c9f762ff10388833d99bea99c5ef3ebb2a9d19d2231e67ca6c9056d8834730605897426cd069cbeb6a46b9f5332be73ab45c03fcc35c2d91f22bf3861b2b2549f9ec8798aeff83ceaf707325c77e7389b388de8dab7c7c63a4110ec156c5145e42203c4a8e3d071a7cb83b4cd", ++ "553e9e0de274167ecdd7b5fc85f9c0e665be7c22c93ddc6ec840ce171cf5d1d1a476743eb7ea0c9492eac5a4c9837c62a91dd1a6ea9e6fff1f1470b22cc62359474a6ba0b0334b2739528454470f4e14b9c4eeb6fd2cdd7e7c6f97668eebd1000bef4388015630a8332de7b17c2004060ecb11e58029b3f9575040a5dd4e294e7c78e4fc99e4390c56534a4e933d9a45460f62ffaaba25da293f7765cd7a4ce78c28a85013b893a0099c1c128b01ee66a76f051dc1409bf4176e5afec90e", ++ "dea8f97c66a3e375d0a3412105ed4f0784f3973ec8c57b4f553d3da40fd4cfd39761de563ec96a9178804641f7ebbee48caf9dec17a14bc8246618b22e683c0090259e3db19dc5b6175710df80cdc735a92a990a3cfb166461ae713adda7d9fa3c4cf9f409b1467f3cf85d2141ef3f119d1c53f23c0380b1ebd728d7e932c535965bca41a414b6ea5bf0f9a381e098d282a554a25ce41980d7c7be75ff5ce4b1e54cc61e683f1dd817b8e2c1a430d7f895e5e7af13912cc110f0bbb95372fb", ++ "9dfda2e2f732867e60ed2b5fa99ab88eb82dc7a54334d02031258beef75fa4bd6962a1083b9c29e4eeb3e5ab8065f3e2fc732675b8d7705c16cfb4ef7305eb58120f1af5ddc55872a2cbde3a48661a0598f48f63e2e9aadc603545e2b6001748e3af9e86e1830af7b84ffd3e8f16679213d37cac91f07af0af02b37f5ed946ef5c955b60d488acc6ae736b10459ca7dabeacd7dabcfd656511ac913174f6d99327be59befe3e463a49afbb5235f0ce2840588c6edfbaaba00a4211c0764dd638", ++ "ddcd23e8b9dc8889b8599c721e7f8ecc2cbdca03e5a8fd5105f7f2941daec4e2906c654210bdd478374ddee43ee749a920ee91872e057a1157d384dcd111266221b3c79774476b4862fe450704ff2c5353e9a936cac87c96515c28ed4c830335a55d084cb5873c5fd2dd907f3266d8eb7bf13b6dd7cd4966982a0949efd8e428dae13daee549e01cc3c226211d6307823f742c5ef2155601a4644c46eddd603d4abd959c6d242e427768df3b1e22d87971df58a1564b38311a897c85b497a72556", ++ "39016647acfbc63fe55a74598bc1956eaf4e0cb49d532c5d8323fc6a3f15a0231597f06eafd74ad245e672bf6b21e4da503cb5bf9d15e9038ef354b38807564d91f38b4258378ccd9b9420a1562d7136196822a1291c913d83c4cd99fd8d420990c72cdc47607124de21da8d9c7f472fdcc780379f186a04da93cd87628abf323c8dadcd7fb8fbade37d7d2b5c9f9fc524ff77494c98f42f2158a6f68c906105ca9e8bb2df463863cfc1e9008d8344f55c4e3203dde6699b59812d49ce1279fa1c86", ++ "02cff7567067cbca5911664c6bd7daaf484181edd2a771d0b64566c3ab08d382e83932cdd7b4dbf86c9cdd1a4c353a511e68afb6746a507a9cd385c198246f4543d606c6149a5384e4ff54c1b90d663dc7a4b91aeac3cf716db7ca6f9a1914e3a33efe82e7ccc4215999c0b012782402db4726db1d7d1c73571d45739aa6fcb5a20eeb54a84d5f99902a8d356cbf95f34c9c28c8f2badfbc08c69233514493c0c04963268c88bc54039ab2999c7b06cba405936dfc43b48cb53f62e18e7ff8ff3f6eb9", ++ "5764812ae6ab9491d8d295a0299228ec7146148ff373241a510faee7db7080706a8dada87938bf726c754e416c8c63c0ac617266a0a4863c2582412bf0f53b827e9a3465949a03dc2db3cb10b8c75e45cb9bf65410a0f6e6410b7f71f3a7e229e647cbbd5a54904bb96f8358adea1aaa0e845ac2838f6dd16936baa15a7c755af8029ef50aed3066d375d3265eaaa38822d11b173f4a1de39461d17d1629c8df7334d8da1b6401daaf7f34b2b48d6556ae99cd29ed1073926bcda867421832a4c36c7095", ++ "4df3043cf0f90462b37d9106e67366d112e4938c4f06abae97869531af89e9feebce0812dffe71a226de5dc36be652e26ef6a4be47d9b2db5cdd43809a565e4fc0988bfe82037c505dd276b757b785203249fd083fb474a25acccc9f38dc5164ff9097e05989aa6e280739a755231f93670e7226e22046914c155bf33d135b3f736ccca84cc47ae643215a054b54b7e13ffcd7ad73cced9279dc3210b80700fcc757acfb64c68e0bc4da05aac2b6a99d5582e79b303c88a7ac4dd8ed4289516bba0e243527", ++ "bf041a11622715426c3a755c637d5f478dd7da949e50f05377bf333f1c62c671ebdbf9467d37b780c25f7af9d453fc67fafb2f065a3f9f15d4c3561eeaa73fa6c813bf96dcf02430a2e6b65da8d174d2558110dc1208bdcb7898e2670894c0b9e2c894da3b130f57a90ec8ea1bffd27a37b4da4645c546b2b141db4e2c919154dac00e78dd3eb6e4445974e3bb07905982da35e4069ee8f8c5acd0efcfa5c981b4fd5d42da83c633e3e35ebdc959bd14c8bacb52212b4334f94aa64d2ee183861db35d2d8a94", ++ "a170ceda0613adc9c3a1e427f07beacf3b16ed69fb42b6bc09a38d803f632ad2929dba215b85683b74e2feb1d18fe17d0ea0db84d1be4e2e73476917a2a4cff51d6eca7c5e82232afde00dd2286a4c20eb09800b4d5d80e7ea35b6965b9792d99e399abda8cf32174ae2b7414b9bdb9d63e148f7357635a7310b130c939593cd3479164724011966c4232142df9966f09422f34f20b30af4b640a2c6d3dd985fe0ba3dfa9083cbb9b8dfe540ff9f6c608d18481213040768ef33300d773f9890c724ead320a1e7", ++ "929477e9c2d0bbad3429a0e0de776695255013108261dc6404cb09828770e274d8bb650a50e490dfe917fc2047b0f8ee72e105927d9fa70523c727778cbf6ae876d641ad562938c870d12f2e047bb78920739dba0c3f8ce1fb77589623a5f1625f5d6ab81940c7dfc3dc3a641d82b2813629bab8282999317d6b93842334f123fb4693a9c2c9d8ba9bfc746642dfbd045cd2021b272eab7358aa954d453da53fc5392dfa7eb881f6f53809b692d27f3366595ff403289efcc691e118b4744a1147071d8909bef1e8", ++ "3e98bb14fff5bdf7db38a3960dc55ca7d02333daed8712cca13dd5bffd114636559279db72554cc0a0ee1f7e15557d77cab0f2f1131f94fe698db81be38300a856a5eca85e5cf915fb7b6f38ccd2f27350e62cc30ce10ffe835118be3d435d2342ed3d06199b7e20c8e34d68902f0ab8745bd8b7d5b863d525c1f5906d2dca598db8a0f1e67736182cac15677579c58b8c670cae1be3e3c882153b2aa2988933e579ec2d6dbb00c671da64443dfc027dee6dfc3233c99758304570a982bf9b2eb59ccd70d0b54c4b54", ++ "aa12c7fa50ffdc2811c1872e4bee15f43e6909212385c872eb489f7e06dc1787043f56126f8373bdfa4b3f61405c73dd4dfd3f40aa5cd207e8520849c26f67716a46c0989a99efff42f24e0736e327af8e607c401a1bac77341e9a78c91e35d55b2457bdd5317a405a1fcf7a2a23de68ef92b65819e8aa3807c545361dfc9fe89125123492da958dc313cb5d03cb4b192c54ac6b27fcbc498652f5ed36b587bb74942b3ad453a8d79e5ddc06ebf806dad5046b73251064582ef5777dc530f8701701761884783fdf197f", ++ "83e615cf6e17a29e63945710b548a6d9935850eec69830841e26cb6071e908bf72c87cf079ffb34c5eb1a390def72d004a9488224a18e189aa1092a0f1135712834d257a53dc1d0e2c6417d8f472ff13b181910f4c93a307420d44beec8875d5219a3160b8e921434ddf3f71d68db1c1d5c39d68edb7a604792f8b4e31ecda7895c99fc7031a5b98a22009c1da005ac8fd2da0b5d742743f5712d12fd76d11a18e487776ce21ca0d6e5ab9ca6d8c394c321b91c14e291399a642721361811a73b7392e8603a3004e7060bf", ++ "ae1a8f7bfe4b1a0fa94708921dadb2c20b938239d7b9a2c7c598528f20f49764d322ebe85a5b2ea15563cf2f2304baf55d6607c52e2e1160859dcb7af6d7856899eada0e9128a180d3de6fed9334ba52b80c5c362d5591a0ec30f86d37a399927eb1c53076a12d26775522c511c83eb5b7abc2a00bd2dfd5627a8febba53d85f9b74c4b7f0c862ddb0d9298899b646b774d6cc23e4e23ab47174fccd34499253996d5e0917210e2f6daa1685f89f2f1fdfd5509ebc38191d539ecfb54ff0f5bbe6ef36ea35d425af6462f518", ++ "1d033e06be253ab800c8176d3a9650ab2a5bcaa03e11ea95fb9ab3834b41eb0d1b2bcecfe219364c3104ef65a8d692bd77c798548b7d9a8faf7f5172db24ec7c93006d6e9839368291b8277a82c034a3731f1b2e298d6e0282ec8a7902e4f844d132f1d261d171375c646065e201849f2df73e3748d853a3122c2206aac92fea448500c5418ecfb3d80e0e6c0d51f85831ce74f6c659cc291f5348a1ef8b949f1b2a753633e382f40c1bd1b2f44748ea61127b6f568255ae25e1da9f52c8c53cd62cd482788ae430388a92694c", ++ "104bc838b16a641749dcf73c57b207ea3bcc84381170e4ca362065a3d492e892b426a1f4fd82f69461d1ce1f3aaf8fc291ea30d6667e7e1aea4c44f7d52a5fa6d34709e6658483260ff5da76bfb74e7d194ad40dcac00daf0e45e74db4bc2248100a8b256b257278c3c98f1f2e3a80cdb812352aaf4155b3a4033999fb9fe7f506994fcf3a8db31e9e5ca8ef8c2e9c6326ca5b0803724ba641950eca877fe6ed6afc2e014651c56d0e6a61eaff7c5ed0b861d4bebe42904c0a568c26aa8abb2e97da2bfb40f14eafb6bf16cd208f", ++ "5b92e4a175437d0a53eb10de2c56401720b11715a034459ebf506c3fd6534b5e817a0f09deac4bcfd353301d8d031b1331582ac09189b48e6ccea444655866c4bbd123d45ebabb774f877cf12d33b84cfca4a6a94f3f98869fcf2bbb6cc1b964c2438c2f348bcdf9001dce60a4706d20c169a040baa61cbeb0b8e58d505e6e3739ab03e110ae7efdf91347474033defbd1e86af322ec6456d3394699ca7ca6a29a70d9b10a38fe666eab2858bfe12dacb31568549c826c15af5b6fddf779954351be1872f04e53db7b3b5fbf61fd18", ++ "401cc7bd9f8227efaed70dad83fc8db3bd38efc166f0f11ab142c565c68ba9db680423a3d698b6f3476ef440051fd20b93f6a2ed045825567df5a65e3f62e4442ec396ad260a16a13a1dee46c7e8d88bdd7edf223ab76a9a787c1f4fe9925c051a4ca0e77a0e78baa29f36d193c862fd3a60653f544ea9e3f75f2f553891be8c1fb882f6a6aad118f576f3c2793efc67221b37a45ab6137434f6228cb002fc137b91fb8572c757f00736879453d64a8a868c131810ffdad9e9d028d132157ecb1da675d54047d19b27d3258c9b1bca0a", ++ "c20cf0354982ca6a19d9a4dbf78f810934db2373941a12c263adefa61a5f385c859bc47028829c531dc25ccc0004c7510e707175a102ec3c4b4c933e3f52033e67476ff5f864c446c042a21e6037f7798363d20267891b965879fde80af6b59d77862e3a229af01b7ac78b578e94bd9f9b073c38a627c1864df0083aabb17024bdab6c3c0f0f73d31d59480523a2f23b78baa0385c15f290114305d7f98786b7dbc17a8c2aad97448e8ea389e68ef71091a6a9735ac12ca5497b9171da11a93c28d3273f58b74e2e46279d3ce9d0b20d19", ++ "e2365c2754073b511f16a1881ff8a537541ca7362ae7b84223d3c7d1d49d03a37d6d05dd2b819af9705c015dacc9dda83474eb14b7d5fce6e8a8f8c58e870149338d320e5ae476da6749af45e65ffed550d225a39dc74ffd93ba7da476985d6f44e90fc8e82454496260458431804d802fe804d825f611772f9710667377adfb1a11e4275bcecb42175c515f6a9439a359824f82cc9d480954364e6693099a821ace362e6c7ecbe68be8823bb5b49b4f23ad81b64139e3b63d9d4d298a842f013ef0d91ce7915ee8f816c70ba2aa3994216f", ++ "9c43944676fe859327096f82049cf69e48b98715878400fdf2805e0d5ee642e6cc9c43739f418b701348a033c5cb96bf8702fcd2fac9be58262a843c1e4155ed8a1724b6ebf7cce659d88a95a0c54deb2d7d9574a45219b6419ee173d1d8fad3ace47c962b349abe1048565df85bbd0eb9b11698258c23598023a00fdd26573e41951452027125c6e894a97736ecd63fd15b29a55d8dd9dab7e2e18f541a2e341890a61b7c896e7dc67aa82f3479dacd4a8ec7558d40c34d9ae4060e13718d676c2450258d83de8a86e012813693098c165b4e", ++ "1c707c29582d98a0e99639211102f3f041660ca03ad0939fe3855b8c1b22d6a9b8673c93e3eabc0ab231509b2b0d73c76a290a363943d12d2ff0ea30c6dd54eda753767effe04cabb4c3966388fa4c83a1906a0f48519a5fba9aeb585e0f8c45d6123a75ebe98fd1d0272f733a3925119481a321fe7509346c05128302851ba17a137f956f184e057a305e79a148727a5926de6854eb0314d5492fd735fa773d99ea34c95ca7546bd3a3aa8e66bcc6d860cec3d35d0e2165d5fbe8be99b6e7967df6693e5a6243e94c9c4a2528ae6305cbeca209", ++ "8f1e88103ffa378f062cade0ec509bec99a5c73fb273e79dbef24abf718ac26ac23dfd2b8932038ed3cb9637b71643c161142019f45b25b4fa4c52356737a27027e805ec635154327a66bfe64efc6285cca98c34edc7fb6c0766970a545342cf840aec0a5ba1dd3c6949be4fe97b0f8c8186de07536fd9074db34d09b2f08af9dcf9424d6edbf9cd044102c0e5dc35aff78c36d079dbd2c500e19c8c985ae2abaf6b2a20716bb719754a8840ce97632116c4d0b0e3c83ccca27f11c4204b76b5d6cfe6348a9615d8e4af53500dc4c2cabf12ec8c76", ++ "b9a0c28f1a6156992c103a84655fc6e654fa6e45e45819513afa797024717c00cc195994512fd53ecd1e12dac4d2448e0c40308382312084d2111f7db147b2e6589ce6d977f6115f629508167df8f45bac98abd49f6b272bcc4fd874dd5e29fb6daceb2d727a2a892194cfb9269eda00626ac89b4e74bd29b21e9f6ef18cb69889a02d4f0a06a2e5718899c1dc3b051c2cfa29653e782f87fefa478e6465bf5ff27f8b6abdb500077aac97100bd955ec535a587d66f23354be51cd8170289344bac9451f74e8aee3639f7c09981f4885e018912324d7", ++ "456844a34ae1074246f8f71eeef2010ec8733265bed7c1cc60043d770edfa320cbd4284a94be2574337e16d27f125074ebd7e99031f7abb4547b9540a7b0b5148ef501b550dd929f3dfe39ac65519f563e9254424aaafa05b1d37c16c771882e9e25d4906ac58603da749adf686932cd73d81e2658134fe69294c7a521d257eaf2110c667fc9d6f09b52d24b93910e532184eeb96eae9d9c9750ac3c39e79367431ac1af7011172d0a8be46a31010219a0310a733068c589bfc4748f3626aa4ff8d355cc893d05111c287c9992e95ad47481a6c42d6eca", ++ "c5c4b9900b9727bdc24baa544cad5faf8340be6b3759361f53889f71f5f4b224aa0090d875a00ea7116772117dbefc3a81c6950ca7ceeae71e4ba975c50d61fec82e6d9448d3a0dfd10bb087bdf0673e3e19fa2aaa7e97eebf71f11b86034fcf5a61240c71444ac3da15ef09b27b3523d37d309e8722380f835c1aee4a767bb027ec0674040853e5b53d6a31657f51acff6d2487860becd5ce695696cfe5937f4a0217b69e01cc6facc24dfe5f5230b8692a0b718e3b3c789d682db36101795a9a5f8bbb838c3679be72f7941a1db180135347d0a884ab7c", ++ "1781df2fedd2c39137854737d054cd3ed16b0ade411e41d97888ac900fdb46d9ae26b3d2dd07e118fd57eabd0dfd03a55793c76420666444865371adffc9b2f35068a0d70f9cfda1ac27ccb4beff4ffa5b8bb8bddac843386675c38a181fd0d935d6d51b25d78e7ff4ecef27a9853c0f0d2879c395ed1c4883987d123890d04f851c3e042e1164c68c0d503de16816f4b0e554236e5f4c339ea11d01ce652f6208f78f457a2417a97c0a6a240f443262def4b6763abf53e597bf1a28f907dc7cbdc751a234ea7d75710ad5ab0c37e8e9805102a375abd44011", ++ "8963552ad1e729ead07750df599d734157aaa4bcdcac17e8eb19b4f99cdb162686ff433137aa4e8a0cc8df0053999196262115aec326cf37567d9ba4760e0ad21d5763977f1ab9b35c0fc667890fa87fc946ceb776a811b5adc69446bfb8f5d9908029dc5aa38db816e4a4e8f98e5a48cf0a01627031c5bd1ced8bc1940dcafe4ae2f1199b186468eafc07e96a89d95dc18ef0fed3eda5b58ce58f221a47ba5311313cc680367eeb058fafc7bcadce5f520b6371489d9e529278ae6ee2650a85aed82896879038bbd9aa8d685fc9528943ccf2235cdf69a86464", ++ "23ceae3008085134433f5de4b47bafe0f443d443491e6cd47b216dd2dcc3da65239515a6e6b9beb9a939ae9f1f1f5e11f88326475e0962f319d9bf75ddfb4a46e7cc3f799d7547f3c0b2e089018b75787b82ea1a7295e7411f4852f94c94170e98bb0647923b8eb7d184038e56560da46085540cbfef82b6b577c445d038f6c93fbfdfc96ab3a0191d20a57b8610efb4cc45cd95198198e6f80ac46b0601511885f650eb00992605be903bcb46cd53c360c6f86e476c4c9ca4ad052eb572bbf26eb81dd9c73bcbec137aea6ee27aa97dadf7bef733fa1555019dab", ++ "c0fd31e82c996d7edef095cccfcf669accb85a483ea9c59f368cc980f73da7202a95c5156c34192ae4ebf773c1a683c079b17ac9d08b4265b4054fcddaf6666ca50f38f1a2ef2497459a68c06837363a526e850ecfbd223f55dba67db017eadb7a9139abb5bf3854834478b838aafa16c5ee90ea52fb2f7b8db2bcefb85b06fc455c2b6c27d0af9a49dbf2f313bf2599370637393e7972b31d8bf6759f3e6115c618e672831f84d76ba1879c754144e1df4d56b1e264b1797dcb8ab165040c8d20b931071081d7f74fbff590bdc8e888e71acc6a720270da8db7c821", ++ "936fdab91fba396e4a8754a97a04ba333daadc29885c9d0c8fea3387165278f4974e468fea57f2bfd8428c4d0f010833283db73735d39de0c0cb5898d0c06c0ecd05f61098935cb6130a8da60d1a6c2ecfe420f972263fff5a631b09e81c837183c5528bb1c740b36fc39cb082f3383c2b4afb25d04ad1d1f4af63dcf26a0bf5a647cd2e35a51cc119c4dc5031f5715b3bfa1f2b92de06bdac0d670fdd30980f32c51f3936b51e5db6b95a8d36279da5faa4c4e454f2b7e54e9f488071011c7f6f9b63da260a2e46d796d36c9a9dcae88085806a10a77bbb670d475778", ++ "a55fe162b287bd6eebd6cf7e7aeea8672322d924ae42c7404ff89aedb98943f3755d2889bca488cc7000e6e9b8e7a0ef289273cd29c44cc600e330d1775e3cb767f12150e1615dca8c3f67466463a3ca993a1b788cf67a7a35b95dfff954206eb5ea1e1bf7fb06482a551625b5c9fd9a86e8414c8cf79d3a14104a153cbe04aac5172aa4c4a89349f5856c4262dd1d7317a7544c9afbbed449e7dcc2b58d9df6c9c9ed3883e42e80f5c2433550f30e73c7bce0fccdd880adc19282a392dae26a0108e7faf168cfc15937aeb046d60712603286b8ddfb27916b79242d56f1", ++ "2bd6976592408cdbc4e41dcd3ecfbb786775ddedef914d9058e6753f839fdfe15b17d549dbc084aa6cdf3befa0158aa84c5d58c5876144fd7e6c41ab7d42419d0dd353732e0e6d3fafc4f5626c07433390a4fd467197e85b5de7e2cf1c26cc575356adedcc0740008523b503df12ff571387726c5ccb280376d19cbacb1d7ce7aab8b13292c6a8b8881e949cbf6d4610d16ebba1d46cdb8d0459596e0aa683d0307bd926e14de19b9bfeaefa29d91b82248604673a455520cbb64eef3f38cfad8e126a3b1cfa1aaba53a784c8ae0c50279c0ecdab54095d36f67ace9b8ebbb", ++ "71913ae2b1c8729ed6da003c24a1d4f96e28d7faf55ca14ee0b2865282b9b61103ce6ee0b00b00aacf2081adedea5616f9dfd22c6d6d4f5907bcc02eb33edf92de0bd479794f51246d9b612b4543f6ff633c4fc83bfa6144c9d26721cdc690a3d5a8db54d8bc7873bfd32924eeb502810732b5ac2f1852bb021c401d26c39aa3b7eb09083093a9e89bf889b53383b5af61110aca1b9fdf38908c7d5a184fc5f46b3423a66a2749feb8de2c541c563987278dbd0513d99b732411012b5b75e385510de5f6839c3797dc094c9501d5f0504b06b43efb6e746f2129ca189c1da424", ++ "9d048a83294de08d3063d2ee4b4f3106641d9b340a3785c076233686dd3382d9064a349c9eaa78028d35652078b583e3f708e036eb2ced3f7f0e936c0fd98f5d0f8aa91b8d9badef298bd0c06843831279e7c0c67ca7e572f552cfdd984c12e924c08c13aeec6f7e13d161785546ebfd794b5d6a92a4744e52c4cab1d0df93b9468be6e264e8cfcc488f9c3c1817cbe501f4b9cc5999483b7433aea777226b25273a6ef2331b5f3b6db8091591e8e276015da3ef78bb2ee0526ffe23def2d8d193cbe594e8ced1f3d216fcedae2a1eb288da82e34cf98aebc28def658ee0849ae7", ++ "3251c96cbf82ee2e5264528c0b6cdfc23d20e1eb2d6441b5d62f0fd24c692a0d45a8bc8aac32884b7141ac0f4f113ec9fc7f6b4db3d696374177f9a42d602ca471275b928f639105a55b846da9ac7274cc37de8c38541f6895f94d72a81e117844b46601c201f7189b935a96e42505f2098ac985d92dfe86349a706ef6325b3c2e4060ced3c453e68ed09e043bcc75846b80118dc53530248da250fb57922d0afa53a7b2c89161aa4fa372a46b2a8e1307741cecedf585d2f998a9d496763800b6965c38a5d8aa566c709f13699c8185ab4fd8fdc8b824f4dd6d1c255b4788f50574", ++ "2de31dbc8a012254586f3229d3524fc529554e98850d30acdfc11406bba6a142029126ac165ee90b2de7509fc3571a8ee12e16b05054eb8baea879d135b39627f0d8331be3e66bc720c2096ce74e437daebf3bc53d8f2ccc228c3256d3edb6e9ae7c354a0c9350e6d663a9a30630bf9da3d96b96608a2a171ae28105714058b6c4b38a36c56561c4612c32aad25c65b7fb6faa4e4ecd44ebf9b2fad42ff9a807cda2581614fd30d41a7436069399b8d4f062a37a5bd4066a93d541fa5797a7d3e7dc9c4c40f0bbf5256f71613240f9ef128b3423eacaf428ada06b6a531f835281e4f3", ++ "07dadee629a08223dcd7ec441287b4c5e26347451d9c003e3a8496b4ea313b51126283a6720d7851e24423d9c9c818b4601247178f38a61f45fd4c8596d79529d416834226666a2c8552bbc901cc5cc3406a18fc88077fea52e1b620748553052ab7788c0d025b095b736fbe714cb3a968ec16b5917652eba2d7cf32ef3140d6c27b25d053e9786d24cd09a5306a0ef55e46201faa6196a91084267d7a7b5ca57c2efdeb2cb97d682d2a191b915553c8933f1d1b7faf0b4a1d83ef611f1e44438bc1c3d860fbfd12b5f26e5a6889a31ce26ae6a55c7a563b5816d113423ef3f25fa9befc", ++ "1d94166bb387526d519c4ce150221954da8930f66765fe6a5504e30a69962d595cfdd07a82c003843598864261f053bdb6f5086d516c261e089caa89990f0967605768ae9200bdfe4dcd7b77a93265cb33d9851a2a1036113c732bf3f37534530641300f0620de5c16101e16f4baf39d9fcbfcb01c52afce0992c329d8dbb438c314eee995c5020611d6f889e06b8a032785cba9a415580dbf752b5e510523c89f478cc6f047bd926f51e4a965c9749d1e76379c0e7e5b56803893bafaa4d2892b4c52f143b2fa777cd1035ea418684b8019df084f9a3f1f768753096621f342895c510d01", ++ "fc0073f199ed8a1d6edc8e7bdf182670003108d82b283aba82326e856f8de378987a03d0fe8d2041440fd29d51c63796aab44090d2b14ee00859b3a08cbe88f724badcd3c401226c5db8b307b8deea5be305412b080e9f99cf79d6d08d3646f347a7afebb62912e3e246e2e726f9aec5c101d916e47f984507b1d65d313697256c77da7eca3bc5811c87bee02a2826cefff0d92bae989609aaf95d70561b40d98474c37277c884aed887a1606d206b11e8a8a71d1f1d19319557b57351228ff0404be700a6cc56c0a30f3d4b7a0a046463fdaf19e7d5f59e155f378e35baa33db1e881f2207f", ++ "f42a6a91278d6a076feba985b1cf4ce0af1fa9d6d039c136e8971e665ff088a10b6b9a379a6f5526fc5957773a0ccb8972a4a19be0745ac13937030a54b18dee4f4c5df47a58a33a7516b90e646e5da999166ab0e52f457f7c9b7e391836a687eaae37b377e59a4c995ab0c57162c307ab951a9ba6590f429cd27250e7010eb794ec1b1ec35f8aad189b2fd3e8aff24d93601d91a4884e6f84b02757ce7620a02901519fccfda52f68ad6df709d112a9c25d66bcbb9622806427ca8b8d346b6db05874bde800cde9cf17df4b05baab0f133febd1ebbb053b49c109a7f5b1f864a304d10288e2f0", ++ "bbcefaf4a0739509f8a2f831c954071aac52e60cfa882a867b8b910dcf7edf92e1c0692bb027bc378c460a01cb6ecc8f2a012dd84ee5a678cd497b1457b6d393421fbee98ff544fc7eba24cbc3aae506254d9a2d74dde74437ce4c8a69010718506bf4c5943342a942e5e2d3406a3016280b6e37954c5d5e763346251afb0b746cad68cac757f9df765e092518729cfb9a5e76300c124e708ca33591a369767ffb63933cb72fba67beb2223d98984d0b75eb5d1a38615913747b520b3d613c715c0c77d2987bb88f3c419bcc5d38573cf4a8a4f550b2d876f05ca252d88c70a561d869a5018b32f7", ++ "dc2437010cb05d9cab2af5c275e1d2acd627ce19fb86355df91fb8d059e60d591663c8eb077d48388c9a321057a98136f49f0098348d9f29d808936f98bb1787c7ac75fb14f6076dfd2de5b59b1fa4848cabaa9a99a091dc24b561911c392ecdbe53f4adae82b852d830adea3a10490c908e337ce0a6d12354ce05a37ad3a06696b66820af8a1f67e6287533fd6f38a5f6ad1c6b078c08baf2c37d2683af01e6a5b33796c8ae48935a888f9bd265f4f11a4e27c433b8b1c9afd140bcd21a07e24378ad6badde8e47c57e3340f49e2406e8d49afadd65eaaa4c3d078c27d7e42118cb86cd248100a356", ++ "6c290db326dd3152e6fa9b9c0cd7d49e50a0221b96e32f5f34a8cb7d0c2edd3e937a7d025d6999b7b468add4d6894d8f7aceaabc18f4d9c171f1fe95ea1ae8570382a8450fbc595d95b1f51d24e1abc2970b0e1d20ca40aa21bdfb3656adf2f19882eda606f5ef1c03174e1d94c8d12f0fee8dce6852f42a364eeafa27a7971d4379405db8e46baac4d685b969238e5df06292a6c790bf1994a051b038e1d8db91e1bc4804f32443781c34a552ed2e8100cea374e77af56ba0e11c45990d3ba68df9087b1f4968cbcbb1c42f99b7267c76af926ff3134e093df28fab039cad420c6b70f2d9b5e678c155", ++ "ac724a22ebabaedbbb052953e3c264a4b6440f313bad501cdc1484b64f33402a2230898776db5c818c28035ffae6ea24abd04b7159e42159833903a0c23a7c564f7645e49ddedb748fd9e51bd6cbf2eced98caaa35226970f003ce1fd260ac5795e096f1c04aebf8fd36e5e2adeea929b5e963a3cb71d6b55c85bb7d3a2b03a7e74b4416de8fa68950168d7c3ae8ed2e29bad1e8a182a7c5418e5d564373163778cd3c34e9d320eb1a60480a8f98b12e0026cbd7752e6079812e3767d9f55f3f10b8c214a6eceb2a58954091a06b33862af171a9b60bf2c6a44e8766e6c56e98092c56f2a8510f6d05c103", ++ "8c70114f7cffb375c2b9a06e27297a5c32418b2daf68af5bbedcc7106edbc070e764bf40c1f8eb15079e2ab77f898afff3490108ed9afb7ea9cb05df41d263be0e42d2321d3d2656622d7bd232bf68d37375fe7314b09cba66f19c8b59424198ee69e7a9f3de0ecce0685127807ce336fa479ccaf7aa1ebc4e406271ce6c4923ec36093516498cc227f9218869346c80ba5ae83e023aca0ae2bc86b5bf5d115a4616b6587cb869d92f8c780ab70d5766de07a204af5e1c8dbba622516d2e911b36c82e4687e4d258ea616c07f76ff0baa376c8d5975cffac0b25817f779ae3ce88b72eb47e378484ce999bf0", ++ "0733d59f041036398233fd47a84b93f6778ae5259ef5d62aa3b9faedec34c7edb570c18b2a5d2c4c55cf656d98a1ae396d45a3b746b7ad6f07312c3d05d1a50ffa90bcdcdba105e25b7b0c52664223f8c2476925d46dc6ea2406ded7d0b0b292f6656cebcc7616cfa4b82aec68b35d1da67f6ed2bf0171849d6bb65128d8a140ea5cf97f1003f8d7093bee077be78def4f7bd2caccbf0644f26b26285225142c40038484c3bb9ba9597744f4389e76dca3eb695c33ccc621cab1fb603cb3535a0ad318d220385d5e94f8674f3d55e97e097f8d5c049e911946afbfce783819951d65d6bff4567dc951390d1aaa", ++ "398ddbba3dcb5642c102efa841c1fcdaf067062e7eef8e2ee0cd73d7f77e57372d6ee1a9b7b6f86ad12d575001ae71f593449cb5a476c6bfeddaa2af0f9239c1d7effdedf66ceaf413707b5ab9661a7cc0ef8cfe4d1651579c4f0f64e2d12a52653c54f2dd60864e769eab8a627c89c56ee93365d031f0d2523cb95664b1575d51b122f33c9e94de75432a690658c977b68aa5b721a393f9b9b3b612c10e920a7d510c6d8460b35f8614c42f5d2c241a01b28105aa7c1b521ac63ebbedafac6d5a38c898e8590f918a1927bc53aecc2b1c8b18d7df9107c6997d9b3fa4b0bdb1c603da619d9e75670b97a5b40f06", ++ "ef07bbc7c4150dd47f8c69a7989948fe831dc798b0424dcd6551bfa8e88216095a7e5d720909bf3d23526b9ba464b66ff6b63a7337c31451ab9a15f04ead809a62bb52206237de77597a730106d02d227dd6099ea9ee2a92cdc446ac3b9d024e32255adb3e9b56b561c431e0b5a721f0336f19568a5335d0ebc6c73ed8ff2c15e219477d9e4b67f2928e251f8a61a2848857e037d010806c718ab062967fd8e85f3722252957923f5f9005aae47b4b1b3fa464e3ba9df573a56055f17e903126fbbcb6cb96de92fe617c97f84ef3ba0d8f2651dc4aa80c157f372ae1bc02e5067ad076f3fe48bb72c0f3c99273f82b", ++ "c7076986d2333f3a6752adf11f1a9e5c6bc4755f341073cc86a9c7519c8db029d5ae833fdf3fee826ff4692c57880c5074620ea97c00f1dde1e8a0f18501627984ded4d1b5c4af35be5cc1bcc868060a49a968dc0547acde490b4c68d79924a93a986aa0ad060c7de706e8a99ce8f84a4f8707b52a8ee122b763ba580d6b1f35f6af25094c69f49247da96c836991851ad36f60bf577863d7471608a012afa7a56656abeee7cd9b4f1f4d9d13a8526c0f33cd251caf7486639e787250390e7e488e9ec311fc3d847a7266cc59bcc2bc34192554aa57cf25db10ce04bdabef3fde6db85f55195ecc2ff892b2e268ebea6", ++ "01789f40d42d8d3e4a416fd9ae7de78c3a30507809eda200e1afaaf8d7020cd1fad18eba62d821946f220506cf105ff0e2069a771a2c233714afa6b2f695497e4b95c9693dbb93ec4c9a14720676aa87ee31dd34e4e081756477032b4a57b328285f2cdec1b269754c474936927e93acc26012aff1bb36f30c2402aca0a9b9ce9568f5000e2c934263933b436c94f8d6589c89db7edabc5d03a8fe795fe50c5166beab64ed7c22662b984ae2c66dbe4c090b0df603b27c759278f8d66859afea3f6a8f02c2c2a2202b9fc29132256f164b5050a803b43688dc4c9ba86374a3522afba5d1a19bb3820b883aebc267627095", ++ "2c61944bd6a50da00ebb951d2b67d79fc6b6fb5aca83b1de3dbd7690ab756bb1e1a21051ccf1e24136ac8ccb42a2ee10be94d2cb9289d5f52b6f90e9d07a3478f36a1eb7d08c3dec52ca154fd1427ba92a4ecbe73a71bceafbd26e9a39d50821e2876d3a0c0e6e373b9795dbf72ea29cc439ff42706be798c90d4617b39c90ec84bf9fb699dc8a9a34e25d81759d6c57df45efb1d0d68aa51278564b99633ed5dc464bb7d53c5c21f798f33bcd868657ecfe75a1ed8149d394b398969ef624831b30f1458465bfd2fdf3f284f2ffc54bf2817b5fab2e02056e864f78bb6fd870c64f3609dab218f25da8060f756e45121e79", ++ "942fa0c68cc72f69518a3a7aac0cde45bab0e928b5cb2bd24d049fc313f74b6afa87c4e34150484f3b5200163f8a6472d04777928ecc49319539fc17d71a38090f55a74f757fe45781a3c09f08dcd3dd4c73c8533a5e00cf8a86ebe77fe45be2848574f7c5d25e9a0632a60d2dd41febdbf987d2a0487e4a4ce6ed5f49f2d741a88ecac232b1498253fa4ee8147bbd0f600abdf295e81f7570015aac5fe6ca7bb4a99bb3fc54287106d7fc1132a574af49db82a7b9a5f33e193cde527ca2176c52cdab672165e0fe5720f71ada57ee90060aa069ae2a0bfe67c1b71b17c601c3c2224bf9891bc11ba216e3ebcb51fd95b8d7cb", ++ "0d68cfe9c087ec116fe7572042385159cc705960f842aabad1ed1387ec1697f4413a23c6090041328fedd4b626c6eeaac5b5a71acc1fd1bb8fbd228857ac5bd045c364be7a5a26338ff04c99c4c473cf445a891db6422d1bdef4533442df171643fc36a092fabb464298e4194c9e2950884de13d113ee24160a416404c16ddc5d2476cb3fb80da543e6ed9105f6003977acb34e1fdd2cbdf7a00d5ff84350b74ac231418c0d88269d02d824802791ff42a51cc835deb9869a6023f867f82ef6dc0bfb03e6dfa835646bb18a4074773486e308aa39e532aaea4e6fb35dcada7e060f8282c371ed26d22302323d4fd142a85534671", ++ "45e24b167a0bbef1bd8f79dd047763d0754f36a7b623f298059d177e8ac994945c37d2c4af06f01318960301595941124592f2995af1459d854339998d3ae17534df2d9793d6e203857d02c98a0cd88991e641b3e640090ba303f87b907dca8ca462fac19ad079b2c82ea5b521ab891b10138b083b3d9fa214a8fe60d1cb3599c5d199c61a2cfb7ee2f39e5a5abad5ac4998b707545f73e92128d21803420526d2598a53bb314adf29a0ef56b94bd2221601eb53ecb8540e8fffd38fba7bd827ef255e4ef55491475c0f383a241f81c72af4e1dbf2a65cd4d18a497615aa0de2791a3511a7977a8d4d41492bfa4085f2fd4e8f751d", ++ "1c1bb695ae90e6e33fc1e8b2a62ab98bf835ac7193440f2351c8cdd830472b637d2fd9c9013cb83caef506abc1c4f7567706db6046b1d184579c7a9223ab1b35e32898c70a3c27628123ffcfa518612f080a2c4a9f8e0a927a47dc98307d2b48de9d5dddcb5c82f0b0e4e610d44f1baa9bbbf7f5a727134680bb7d1327b73b52d8e5e36dbb53971e99e699d79f75a3fc01316bd7012947d119d6aeb7f75b8fbf0479c03002148553fa0da450fd59d4f1bebc252caa11ed9bec5b6ef54279b5f8382b61cffc67ec03f4baa7ea476c31364b86aa8ccad9fd0818717f0ced2dd49477874b4341c602d7a1beab860eb476c7e3ce597e6926", ++ "7a3cd9bb2277e2c7f1134fe7233f0f7883c2db9fba80aa5742b03041de0fe589d9e5ea84470dabf41bb66816f3e33ebf19a0ca5aba1004cf971249b258ff26a98dbd0c37ec6cd574854109433357720040bafed4531e0079186b1e853e0ced35d08d27f6d732ed6e2c6651b51cc15c420a24f2dc36c16ef4b3896df1bb03b3963f9aaeb02a48eac5772abd5948c2fd0db2bb74e3351e5eabd681c4f413655bd94dec96b1544c1d5d2d1df4bdc26020d25fe81d5238de824687a5505e1fbe08d11b3924b3ccc070fd225bf01eb79e3d21f7b62a836cd3bcc11c931669c37613470e356143df87c48848a829f5e018973a5db88eb6c60203", ++ "3f158afd0733fcc5dfe1efc2dd4eada732f942af734ee664955bb1ba613eafd0f349e7554a14d68200c62d8f2dca2ec8b81c8350735eaf437041f78b452598825b6899560963ade66a0fc74ad01f8343d1d19c7bb327a8dc14ffdb1c42fa72b2970d9155e2da6a2e6419d4117842d826ff38ffab9617307a0283d3ea28c8104ad9a6e087bb750ed1d10fd8f7100b1663682e979d80e43968c33d9eff66f4d1344e583ee521e78d0a2193c0577516b978339c143bfc689bc744bbc4a9163063de82c9706384b6b385e54666c86b34f23c1e25be293af06092ca31d857e11e5b2caf0d19dd3afbe85380878eda76d718b4bb869c67e044e242", ++ "a177af4387b9bfa3d59e97ee7b0ff5f4ae4a326fd9204c8d28831a67fcc385ee6c4828247b16d11aea9bb8cd9e6c4d2876c6b2fa6d5041ad39e1b04039071e29c4d86417e7eac4fc7d3823958a021823e2c880a757dfbcd0c8196371db5bbfac15e4d1a0596508b6d26f8c4a664924c95082d173f817995b44c4285d625d9b2f56c86632fe1295c5a8a7a3760028072bcb07bc245a705e7174d06b9d5c0c8ca495b9ac218f1921fa63f2db3fd148f07545366d008fb5aead7497d902b91fbaa39669929d4ae9d07df8557f1f0aed7b51252f10c6606e5ff3ede1327530ca356b4896ecf14bf7322d77fddfbe28d52f6de7f66eeb81704c87e2", ++ "01a15b9018e35cc342c926b01d03ad9db4993a6bf92e0555969fee90033f28f3ec234c1268b11b040dfa0770d4ceb39edfeb8ee6a589f4eebcc08d2d1b0a1a52953aa26eb44fdf4a2743c3dacb212a0c0f325572f645f53027b6f3c0c55abaeb1b0918c89bedcb5028f094d743ea354f8ff553c45f111a8fd5a14a4e5c835164747d302472e19a67da04b4c8e39756a9d248ce14d1ed43de75aca86850f2455eccd4639b2af035bb3f504cc9065d091c1c47e036083cb3fc50bf39292b11737c7ce0b49673ba93981de304dc65a671775b6ff927e3ff93850b214fffb5792105a4bdc81354d5b09e84afbdd1792b8fb4e9d0ae3dad2492b03282", ++ "24f07ae31279ceed18ec6d35990f21200934ad6b132c6c62e82fe92a40a0e60a5bed10720eff5a1f728971888682772b2d9060d4fee88f37d0824e7384dddcc549475f0e1a44eda4804778b62febe46e04657a20577ee70acb3425e334881eebd8ddf714ae8c527ea747e3367de384e595a43b299b6bb3f6b0a4716cf90038e0f75a47d5057d7fcc3c8a8f9224992c67f8ae0d3251ea09a24aed9ce57ab637f6b3cbb7083df62b6287f64d0877984c4249d113bdb2b07865082aa24cd7ec07061b17de320f51f29f25b82d7073d369cf2dbf96310c0c311997911b2cc02f606f9cd99663c57e78499192a2a78f9c9fa67013e0f9817287faa69b22", ++ "4aeb32bf9d050f10bea18d9f71b4afea7bd08550e574e7d50df234c7413668b297b6721d7a0f0bdcdcceb2f55adddea28cd59bd44be0c5ec067039e428706caae11f565d961ad6e7f4c51b0aed6d05cc5b8d826c4b9c39daefb6c7da46dce619a359dc9ce215a215218fa8d54ee0b4f301b6c201c7c2c5f7cb1c6e0cb76ba6c6e8f63ef7a5213d550b0d0857fa0ff9e3e38e497161617413ac066e2fa539520233193a5cb7baa0c2cb20b45e56bfed2c40a9544d1f230dd0cd6d4976e7cf51da8a13200c3957c0154c8237b2931ce19b824963ac576ea49b548cc6aa85c47796b470fb2c6308d88f390bb13607e294c84a838b2713b14ca6a5e8bcee", ++ "77e607478be5502432230c913d9ec82f967d87c0ee169a74076f989648853eca693277287f8a5b306bc94dfdbf64ca5cb5dfc0bc498589d51a691b8d57d4b0a9ee247d038fe1b5571183be3e75c37045bf1235863ff1b84b208c10e7f1a5ba54ff36af5b2870129867164d013e0a6d2cc067a3509bba2f46390302c80b651cf590ef69aad8effd94cab28a9b44be6a38b58cfc47c9c725d6fa467894163383b6873d10d263b1cbbad932ded59ab503920267ac026726f794a335a88f6ef564f8968c6fa6f5d3ea161eb6062ca349b9a0e4038273399cfa297a6b07ceda1ebaa99c9de2d935ee230a08c5a488ad46f3393243371d40916b8063cac9da63", ++ "50957c407519951bd32e45d21129d6b83436e520b0801ec8292d79a828106a41583a0d607f853dc4410e0a1427f7e873455a75df065cfc6eef970f7e49d123b346976460aadd91cf513c140c356442a84656904a8b1d708dc6089db371c36f4fe059c62302eaab3c06c0cb3b429961f899dcf99798464b8571a440cac7a52b495f32417af6bc8f58adc63647531f804b4e96273b29b42434c1236bde80ba3744fef7b1d11c2f9db332b35bc25123338ac9a0796aac213c9709b3c514ea7ecd80e22d3d8a74f28c8194418a6e1ff30714d0f5a61c068b73b2ba6cad14e05569b4a5a100da3f91429d6e3ffee10ceea057845ec6fc47a6c5125b22e598b2dc", ++ "f2273ec31e03cf42d9ca953f8b87e78c291cb538098e0f2436194b308ce30583f553fccb21ae6c2d58f3a5a2ca6037c1b8b7afb291009e4310a0c518e75314c5bb1e813bf521f56d0a4891d0772ad84f09a00634815029a3f9ad4e41eafb4a745e409ef3d4f0b1cf6232b70a5ce262b9432f096e834201a0992db5d09ffa5cbc5471460519a4bc7cdc33ae6dfe6ffc1e80ea5d29813136406499c3514186ced71854a340701519ef33b6c82ca67049ab58578ff49c4c4fbf7d97bfec2ecd8fbefec1b6d6467503fea9d26e134e8c35739a422647aaf4db29c9a32e3df36e5845791fdd75a70903e0ce808313a3327431b7772567f779bbaee2e134c109a387", ++ "5784e614d538f7f26c803191deb464a884817002988c36448dcbecfad1997fe51ab0b3853c51ed49ce9f4e477522fb3f32cc50515b753c18fb89a8d965afcf1ed5e099b22c4225732baeb986f5c5bc88e4582d27915e2a19126d3d4555fab4f6516a6a156dbfeed9e982fc589e33ce2b9e1ba2b416e11852ddeab93025974267ac82c84f071c3d07f215f47e3565fd1d962c76e0d635892ea71488273765887d31f250a26c4ddc377ed89b17326e259f6cc1de0e63158e83aebb7f5a7c08c63c767876c8203639958a407acca096d1f606c04b4f4b3fd771781a5901b1c3cee7c04c3b6870226eee309b74f51edbf70a3817cc8da87875301e04d0416a65dc5d", ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2x.go b/ms_mod/golang.org/x/crypto/blake2s/blake2x.go +new file mode 100644 +index 00000000000000..828749ff01d153 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/blake2x.go +@@ -0,0 +1,178 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blake2s ++ ++import ( ++ "encoding/binary" ++ "errors" ++ "io" ++) ++ ++// XOF defines the interface to hash functions that ++// support arbitrary-length output. ++type XOF interface { ++ // Write absorbs more data into the hash's state. It panics if called ++ // after Read. ++ io.Writer ++ ++ // Read reads more output from the hash. It returns io.EOF if the limit ++ // has been reached. ++ io.Reader ++ ++ // Clone returns a copy of the XOF in its current state. ++ Clone() XOF ++ ++ // Reset resets the XOF to its initial state. ++ Reset() ++} ++ ++// OutputLengthUnknown can be used as the size argument to NewXOF to indicate ++// the length of the output is not known in advance. ++const OutputLengthUnknown = 0 ++ ++// magicUnknownOutputLength is a magic value for the output size that indicates ++// an unknown number of output bytes. ++const magicUnknownOutputLength = 65535 ++ ++// maxOutputLength is the absolute maximum number of bytes to produce when the ++// number of output bytes is unknown. ++const maxOutputLength = (1 << 32) * 32 ++ ++// NewXOF creates a new variable-output-length hash. The hash either produce a ++// known number of bytes (1 <= size < 65535), or an unknown number of bytes ++// (size == OutputLengthUnknown). In the latter case, an absolute limit of ++// 128GiB applies. ++// ++// A non-nil key turns the hash into a MAC. The key must between ++// zero and 32 bytes long. ++func NewXOF(size uint16, key []byte) (XOF, error) { ++ if len(key) > Size { ++ return nil, errKeySize ++ } ++ if size == magicUnknownOutputLength { ++ // 2^16-1 indicates an unknown number of bytes and thus isn't a ++ // valid length. ++ return nil, errors.New("blake2s: XOF length too large") ++ } ++ if size == OutputLengthUnknown { ++ size = magicUnknownOutputLength ++ } ++ x := &xof{ ++ d: digest{ ++ size: Size, ++ keyLen: len(key), ++ }, ++ length: size, ++ } ++ copy(x.d.key[:], key) ++ x.Reset() ++ return x, nil ++} ++ ++type xof struct { ++ d digest ++ length uint16 ++ remaining uint64 ++ cfg, root, block [Size]byte ++ offset int ++ nodeOffset uint32 ++ readMode bool ++} ++ ++func (x *xof) Write(p []byte) (n int, err error) { ++ if x.readMode { ++ panic("blake2s: write to XOF after read") ++ } ++ return x.d.Write(p) ++} ++ ++func (x *xof) Clone() XOF { ++ clone := *x ++ return &clone ++} ++ ++func (x *xof) Reset() { ++ x.cfg[0] = byte(Size) ++ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length ++ binary.LittleEndian.PutUint16(x.cfg[12:], x.length) // XOF length ++ x.cfg[15] = byte(Size) // inner hash size ++ ++ x.d.Reset() ++ x.d.h[3] ^= uint32(x.length) ++ ++ x.remaining = uint64(x.length) ++ if x.remaining == magicUnknownOutputLength { ++ x.remaining = maxOutputLength ++ } ++ x.offset, x.nodeOffset = 0, 0 ++ x.readMode = false ++} ++ ++func (x *xof) Read(p []byte) (n int, err error) { ++ if !x.readMode { ++ x.d.finalize(&x.root) ++ x.readMode = true ++ } ++ ++ if x.remaining == 0 { ++ return 0, io.EOF ++ } ++ ++ n = len(p) ++ if uint64(n) > x.remaining { ++ n = int(x.remaining) ++ p = p[:n] ++ } ++ ++ if x.offset > 0 { ++ blockRemaining := Size - x.offset ++ if n < blockRemaining { ++ x.offset += copy(p, x.block[x.offset:]) ++ x.remaining -= uint64(n) ++ return ++ } ++ copy(p, x.block[x.offset:]) ++ p = p[blockRemaining:] ++ x.offset = 0 ++ x.remaining -= uint64(blockRemaining) ++ } ++ ++ for len(p) >= Size { ++ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) ++ x.nodeOffset++ ++ ++ x.d.initConfig(&x.cfg) ++ x.d.Write(x.root[:]) ++ x.d.finalize(&x.block) ++ ++ copy(p, x.block[:]) ++ p = p[Size:] ++ x.remaining -= uint64(Size) ++ } ++ ++ if todo := len(p); todo > 0 { ++ if x.remaining < uint64(Size) { ++ x.cfg[0] = byte(x.remaining) ++ } ++ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) ++ x.nodeOffset++ ++ ++ x.d.initConfig(&x.cfg) ++ x.d.Write(x.root[:]) ++ x.d.finalize(&x.block) ++ ++ x.offset = copy(p, x.block[:todo]) ++ x.remaining -= uint64(todo) ++ } ++ ++ return ++} ++ ++func (d *digest) initConfig(cfg *[Size]byte) { ++ d.offset, d.c[0], d.c[1] = 0, 0, 0 ++ for i := range d.h { ++ d.h[i] = iv[i] ^ binary.LittleEndian.Uint32(cfg[i*4:]) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blake2s/register.go b/ms_mod/golang.org/x/crypto/blake2s/register.go +new file mode 100644 +index 00000000000000..ef79ff3c67a18f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blake2s/register.go +@@ -0,0 +1,22 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.9 ++// +build go1.9 ++ ++package blake2s ++ ++import ( ++ "crypto" ++ "hash" ++) ++ ++func init() { ++ newHash256 := func() hash.Hash { ++ h, _ := New256(nil) ++ return h ++ } ++ ++ crypto.RegisterHash(crypto.BLAKE2s_256, newHash256) ++} +diff --git a/ms_mod/golang.org/x/crypto/blowfish/block.go b/ms_mod/golang.org/x/crypto/blowfish/block.go +new file mode 100644 +index 00000000000000..9d80f19521b461 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blowfish/block.go +@@ -0,0 +1,159 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blowfish ++ ++// getNextWord returns the next big-endian uint32 value from the byte slice ++// at the given position in a circular manner, updating the position. ++func getNextWord(b []byte, pos *int) uint32 { ++ var w uint32 ++ j := *pos ++ for i := 0; i < 4; i++ { ++ w = w<<8 | uint32(b[j]) ++ j++ ++ if j >= len(b) { ++ j = 0 ++ } ++ } ++ *pos = j ++ return w ++} ++ ++// ExpandKey performs a key expansion on the given *Cipher. Specifically, it ++// performs the Blowfish algorithm's key schedule which sets up the *Cipher's ++// pi and substitution tables for calls to Encrypt. This is used, primarily, ++// by the bcrypt package to reuse the Blowfish key schedule during its ++// set up. It's unlikely that you need to use this directly. ++func ExpandKey(key []byte, c *Cipher) { ++ j := 0 ++ for i := 0; i < 18; i++ { ++ // Using inlined getNextWord for performance. ++ var d uint32 ++ for k := 0; k < 4; k++ { ++ d = d<<8 | uint32(key[j]) ++ j++ ++ if j >= len(key) { ++ j = 0 ++ } ++ } ++ c.p[i] ^= d ++ } ++ ++ var l, r uint32 ++ for i := 0; i < 18; i += 2 { ++ l, r = encryptBlock(l, r, c) ++ c.p[i], c.p[i+1] = l, r ++ } ++ ++ for i := 0; i < 256; i += 2 { ++ l, r = encryptBlock(l, r, c) ++ c.s0[i], c.s0[i+1] = l, r ++ } ++ for i := 0; i < 256; i += 2 { ++ l, r = encryptBlock(l, r, c) ++ c.s1[i], c.s1[i+1] = l, r ++ } ++ for i := 0; i < 256; i += 2 { ++ l, r = encryptBlock(l, r, c) ++ c.s2[i], c.s2[i+1] = l, r ++ } ++ for i := 0; i < 256; i += 2 { ++ l, r = encryptBlock(l, r, c) ++ c.s3[i], c.s3[i+1] = l, r ++ } ++} ++ ++// This is similar to ExpandKey, but folds the salt during the key ++// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero ++// salt passed in, reusing ExpandKey turns out to be a place of inefficiency ++// and specializing it here is useful. ++func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { ++ j := 0 ++ for i := 0; i < 18; i++ { ++ c.p[i] ^= getNextWord(key, &j) ++ } ++ ++ j = 0 ++ var l, r uint32 ++ for i := 0; i < 18; i += 2 { ++ l ^= getNextWord(salt, &j) ++ r ^= getNextWord(salt, &j) ++ l, r = encryptBlock(l, r, c) ++ c.p[i], c.p[i+1] = l, r ++ } ++ ++ for i := 0; i < 256; i += 2 { ++ l ^= getNextWord(salt, &j) ++ r ^= getNextWord(salt, &j) ++ l, r = encryptBlock(l, r, c) ++ c.s0[i], c.s0[i+1] = l, r ++ } ++ ++ for i := 0; i < 256; i += 2 { ++ l ^= getNextWord(salt, &j) ++ r ^= getNextWord(salt, &j) ++ l, r = encryptBlock(l, r, c) ++ c.s1[i], c.s1[i+1] = l, r ++ } ++ ++ for i := 0; i < 256; i += 2 { ++ l ^= getNextWord(salt, &j) ++ r ^= getNextWord(salt, &j) ++ l, r = encryptBlock(l, r, c) ++ c.s2[i], c.s2[i+1] = l, r ++ } ++ ++ for i := 0; i < 256; i += 2 { ++ l ^= getNextWord(salt, &j) ++ r ^= getNextWord(salt, &j) ++ l, r = encryptBlock(l, r, c) ++ c.s3[i], c.s3[i+1] = l, r ++ } ++} ++ ++func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { ++ xl, xr := l, r ++ xl ^= c.p[0] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] ++ xr ^= c.p[17] ++ return xr, xl ++} ++ ++func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { ++ xl, xr := l, r ++ xl ^= c.p[17] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] ++ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] ++ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] ++ xr ^= c.p[0] ++ return xr, xl ++} +diff --git a/ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go b/ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go +new file mode 100644 +index 00000000000000..368ba872bfd5ef +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go +@@ -0,0 +1,274 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package blowfish ++ ++import "testing" ++ ++type CryptTest struct { ++ key []byte ++ in []byte ++ out []byte ++} ++ ++// Test vector values are from https://www.schneier.com/code/vectors.txt. ++var encryptTests = []CryptTest{ ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}}, ++ { ++ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, ++ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, ++ []byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}}, ++ { ++ []byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, ++ []byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}}, ++ { ++ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, ++ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, ++ []byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}}, ++ ++ { ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, ++ []byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}}, ++ { ++ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}}, ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}}, ++ { ++ []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}}, ++ { ++ []byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57}, ++ []byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42}, ++ []byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}}, ++ { ++ []byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E}, ++ []byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA}, ++ []byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}}, ++ { ++ []byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86}, ++ []byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72}, ++ []byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}}, ++ { ++ []byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E}, ++ []byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A}, ++ []byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}}, ++ { ++ []byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6}, ++ []byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2}, ++ []byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}}, ++ { ++ []byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE}, ++ []byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A}, ++ []byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}}, ++ { ++ []byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6}, ++ []byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2}, ++ []byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}}, ++ { ++ []byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE}, ++ []byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A}, ++ []byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}}, ++ { ++ []byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16}, ++ []byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02}, ++ []byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}}, ++ { ++ []byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F}, ++ []byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A}, ++ []byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}}, ++ { ++ []byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46}, ++ []byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32}, ++ []byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}}, ++ { ++ []byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E}, ++ []byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA}, ++ []byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}}, ++ { ++ []byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76}, ++ []byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62}, ++ []byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}}, ++ { ++ []byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07}, ++ []byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2}, ++ []byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}}, ++ { ++ []byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F}, ++ []byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA}, ++ []byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}}, ++ { ++ []byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7}, ++ []byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92}, ++ []byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}}, ++ { ++ []byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF}, ++ []byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A}, ++ []byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}}, ++ { ++ []byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6}, ++ []byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2}, ++ []byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}}, ++ { ++ []byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF}, ++ []byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A}, ++ []byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}}, ++ { ++ []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}}, ++ { ++ []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E}, ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}}, ++ { ++ []byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE}, ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}}, ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, ++ []byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}}, ++ { ++ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}}, ++ { ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}}, ++ { ++ []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, ++ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, ++ []byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}}, ++} ++ ++func TestCipherEncrypt(t *testing.T) { ++ for i, tt := range encryptTests { ++ c, err := NewCipher(tt.key) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) ++ continue ++ } ++ ct := make([]byte, len(tt.out)) ++ c.Encrypt(ct, tt.in) ++ for j, v := range ct { ++ if v != tt.out[j] { ++ t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j]) ++ break ++ } ++ } ++ } ++} ++ ++func TestCipherDecrypt(t *testing.T) { ++ for i, tt := range encryptTests { ++ c, err := NewCipher(tt.key) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) ++ continue ++ } ++ pt := make([]byte, len(tt.in)) ++ c.Decrypt(pt, tt.out) ++ for j, v := range pt { ++ if v != tt.in[j] { ++ t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j]) ++ break ++ } ++ } ++ } ++} ++ ++func TestSaltedCipherKeyLength(t *testing.T) { ++ if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) { ++ t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0)) ++ } ++ ++ // A 57-byte key. One over the typical blowfish restriction. ++ key := []byte("012345678901234567890123456789012345678901234567890123456") ++ if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil { ++ t.Errorf("NewSaltedCipher with long key, gave error %#v", err) ++ } ++} ++ ++// Test vectors generated with Blowfish from OpenSSH. ++var saltedVectors = [][8]byte{ ++ {0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e}, ++ {0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12}, ++ {0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad}, ++ {0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8}, ++ {0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8}, ++ {0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf}, ++ {0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9}, ++ {0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38}, ++ {0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4}, ++ {0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c}, ++ {0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5}, ++ {0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b}, ++ {0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47}, ++ {0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2}, ++ {0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19}, ++ {0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc}, ++ {0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93}, ++ {0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57}, ++ {0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08}, ++ {0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03}, ++ {0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f}, ++ {0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef}, ++ {0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71}, ++ {0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad}, ++ {0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe}, ++ {0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13}, ++ {0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe}, ++ {0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6}, ++ {0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6}, ++ {0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92}, ++ {0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56}, ++ {0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee}, ++} ++ ++func TestSaltedCipher(t *testing.T) { ++ var key, salt [32]byte ++ for i := range key { ++ key[i] = byte(i) ++ salt[i] = byte(i + 32) ++ } ++ for i, v := range saltedVectors { ++ c, err := NewSaltedCipher(key[:], salt[:i]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ var buf [8]byte ++ c.Encrypt(buf[:], buf[:]) ++ if v != buf { ++ t.Errorf("%d: expected %x, got %x", i, v, buf) ++ } ++ } ++} ++ ++func BenchmarkExpandKeyWithSalt(b *testing.B) { ++ key := make([]byte, 32) ++ salt := make([]byte, 16) ++ c, _ := NewCipher(key) ++ for i := 0; i < b.N; i++ { ++ expandKeyWithSalt(key, salt, c) ++ } ++} ++ ++func BenchmarkExpandKey(b *testing.B) { ++ key := make([]byte, 32) ++ c, _ := NewCipher(key) ++ for i := 0; i < b.N; i++ { ++ ExpandKey(key, c) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/blowfish/cipher.go b/ms_mod/golang.org/x/crypto/blowfish/cipher.go +new file mode 100644 +index 00000000000000..213bf204afea5b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blowfish/cipher.go +@@ -0,0 +1,99 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. ++// ++// Blowfish is a legacy cipher and its short block size makes it vulnerable to ++// birthday bound attacks (see https://sweet32.info). It should only be used ++// where compatibility with legacy systems, not security, is the goal. ++// ++// Deprecated: any new system should use AES (from crypto/aes, if necessary in ++// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from ++// golang.org/x/crypto/chacha20poly1305). ++package blowfish // import "golang.org/x/crypto/blowfish" ++ ++// The code is a port of Bruce Schneier's C implementation. ++// See https://www.schneier.com/blowfish.html. ++ ++import "strconv" ++ ++// The Blowfish block size in bytes. ++const BlockSize = 8 ++ ++// A Cipher is an instance of Blowfish encryption using a particular key. ++type Cipher struct { ++ p [18]uint32 ++ s0, s1, s2, s3 [256]uint32 ++} ++ ++type KeySizeError int ++ ++func (k KeySizeError) Error() string { ++ return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) ++} ++ ++// NewCipher creates and returns a Cipher. ++// The key argument should be the Blowfish key, from 1 to 56 bytes. ++func NewCipher(key []byte) (*Cipher, error) { ++ var result Cipher ++ if k := len(key); k < 1 || k > 56 { ++ return nil, KeySizeError(k) ++ } ++ initCipher(&result) ++ ExpandKey(key, &result) ++ return &result, nil ++} ++ ++// NewSaltedCipher creates a returns a Cipher that folds a salt into its key ++// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is ++// sufficient and desirable. For bcrypt compatibility, the key can be over 56 ++// bytes. ++func NewSaltedCipher(key, salt []byte) (*Cipher, error) { ++ if len(salt) == 0 { ++ return NewCipher(key) ++ } ++ var result Cipher ++ if k := len(key); k < 1 { ++ return nil, KeySizeError(k) ++ } ++ initCipher(&result) ++ expandKeyWithSalt(key, salt, &result) ++ return &result, nil ++} ++ ++// BlockSize returns the Blowfish block size, 8 bytes. ++// It is necessary to satisfy the Block interface in the ++// package "crypto/cipher". ++func (c *Cipher) BlockSize() int { return BlockSize } ++ ++// Encrypt encrypts the 8-byte buffer src using the key k ++// and stores the result in dst. ++// Note that for amounts of data larger than a block, ++// it is not safe to just call Encrypt on successive blocks; ++// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). ++func (c *Cipher) Encrypt(dst, src []byte) { ++ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) ++ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) ++ l, r = encryptBlock(l, r, c) ++ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) ++ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) ++} ++ ++// Decrypt decrypts the 8-byte buffer src using the key k ++// and stores the result in dst. ++func (c *Cipher) Decrypt(dst, src []byte) { ++ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) ++ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) ++ l, r = decryptBlock(l, r, c) ++ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) ++ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) ++} ++ ++func initCipher(c *Cipher) { ++ copy(c.p[0:], p[0:]) ++ copy(c.s0[0:], s0[0:]) ++ copy(c.s1[0:], s1[0:]) ++ copy(c.s2[0:], s2[0:]) ++ copy(c.s3[0:], s3[0:]) ++} +diff --git a/ms_mod/golang.org/x/crypto/blowfish/const.go b/ms_mod/golang.org/x/crypto/blowfish/const.go +new file mode 100644 +index 00000000000000..d04077595abc44 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/blowfish/const.go +@@ -0,0 +1,199 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// The startup permutation array and substitution boxes. ++// They are the hexadecimal digits of PI; see: ++// https://www.schneier.com/code/constants.txt. ++ ++package blowfish ++ ++var s0 = [256]uint32{ ++ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, ++ 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, ++ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, ++ 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, ++ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, ++ 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, ++ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, ++ 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, ++ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, ++ 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, ++ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, ++ 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, ++ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, ++ 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, ++ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, ++ 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, ++ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, ++ 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, ++ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, ++ 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, ++ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, ++ 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, ++ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, ++ 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, ++ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, ++ 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, ++ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, ++ 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, ++ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, ++ 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, ++ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, ++ 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, ++ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, ++ 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, ++ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, ++ 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, ++ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, ++ 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, ++ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, ++ 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, ++ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, ++ 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, ++ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, ++} ++ ++var s1 = [256]uint32{ ++ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, ++ 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, ++ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, ++ 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, ++ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, ++ 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, ++ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, ++ 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, ++ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, ++ 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, ++ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, ++ 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, ++ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, ++ 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, ++ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, ++ 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, ++ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, ++ 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, ++ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, ++ 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, ++ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, ++ 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, ++ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, ++ 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, ++ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, ++ 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, ++ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, ++ 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, ++ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, ++ 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, ++ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, ++ 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, ++ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, ++ 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, ++ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, ++ 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, ++ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, ++ 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, ++ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, ++ 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, ++ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, ++ 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, ++ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, ++} ++ ++var s2 = [256]uint32{ ++ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, ++ 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, ++ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, ++ 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, ++ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, ++ 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, ++ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, ++ 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, ++ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, ++ 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, ++ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, ++ 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, ++ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, ++ 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, ++ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, ++ 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, ++ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, ++ 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, ++ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, ++ 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, ++ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, ++ 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, ++ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, ++ 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, ++ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, ++ 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, ++ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, ++ 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, ++ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, ++ 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, ++ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, ++ 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, ++ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, ++ 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, ++ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, ++ 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, ++ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, ++ 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, ++ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, ++ 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, ++ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, ++ 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, ++ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, ++} ++ ++var s3 = [256]uint32{ ++ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, ++ 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, ++ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, ++ 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, ++ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, ++ 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, ++ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, ++ 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, ++ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, ++ 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, ++ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, ++ 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, ++ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, ++ 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, ++ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, ++ 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, ++ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, ++ 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, ++ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, ++ 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, ++ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, ++ 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, ++ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, ++ 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, ++ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, ++ 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, ++ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, ++ 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, ++ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, ++ 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, ++ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, ++ 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, ++ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, ++ 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, ++ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, ++ 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, ++ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, ++ 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, ++ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, ++ 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, ++ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, ++ 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, ++ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, ++} ++ ++var p = [18]uint32{ ++ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, ++ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, ++ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/bn256.go b/ms_mod/golang.org/x/crypto/bn256/bn256.go +new file mode 100644 +index 00000000000000..5d6d198bcb1c4c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/bn256.go +@@ -0,0 +1,429 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package bn256 implements a particular bilinear group. ++// ++// Bilinear groups are the basis of many of the new cryptographic protocols ++// that have been proposed over the past decade. They consist of a triplet of ++// groups (G₁, Gβ‚‚ and GT) such that there exists a function e(g₁ˣ,gβ‚‚ΚΈ)=gTΛ£ΚΈ ++// (where gβ‚“ is a generator of the respective group). That function is called ++// a pairing function. ++// ++// This package specifically implements the Optimal Ate pairing over a 256-bit ++// Barreto-Naehrig curve as described in ++// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible ++// with the implementation described in that paper. ++// ++// This package previously claimed to operate at a 128-bit security level. ++// However, recent improvements in attacks mean that is no longer true. See ++// https://moderncrypto.org/mail-archive/curves/2016/000740.html. ++// ++// Deprecated: due to its weakened security, new systems should not rely on this ++// elliptic curve. This package is frozen, and not implemented in constant time. ++// There is a more complete implementation at github.com/cloudflare/bn256, but ++// note that it suffers from the same security issues of the underlying curve. ++package bn256 // import "golang.org/x/crypto/bn256" ++ ++import ( ++ "crypto/rand" ++ "io" ++ "math/big" ++) ++ ++// G1 is an abstract cyclic group. The zero value is suitable for use as the ++// output of an operation, but cannot be used as an input. ++type G1 struct { ++ p *curvePoint ++} ++ ++// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. ++func RandomG1(r io.Reader) (*big.Int, *G1, error) { ++ var k *big.Int ++ var err error ++ ++ for { ++ k, err = rand.Int(r, Order) ++ if err != nil { ++ return nil, nil, err ++ } ++ if k.Sign() > 0 { ++ break ++ } ++ } ++ ++ return k, new(G1).ScalarBaseMult(k), nil ++} ++ ++func (e *G1) String() string { ++ if e.p == nil { ++ return "bn256.G1" + newCurvePoint(nil).String() ++ } ++ return "bn256.G1" + e.p.String() ++} ++ ++// ScalarBaseMult sets e to g*k where g is the generator of the group and ++// then returns e. ++func (e *G1) ScalarBaseMult(k *big.Int) *G1 { ++ if e.p == nil { ++ e.p = newCurvePoint(nil) ++ } ++ e.p.Mul(curveGen, k, new(bnPool)) ++ return e ++} ++ ++// ScalarMult sets e to a*k and then returns e. ++func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { ++ if e.p == nil { ++ e.p = newCurvePoint(nil) ++ } ++ e.p.Mul(a.p, k, new(bnPool)) ++ return e ++} ++ ++// Add sets e to a+b and then returns e. ++// ++// Warning: this function is not complete, it fails for a equal to b. ++func (e *G1) Add(a, b *G1) *G1 { ++ if e.p == nil { ++ e.p = newCurvePoint(nil) ++ } ++ e.p.Add(a.p, b.p, new(bnPool)) ++ return e ++} ++ ++// Neg sets e to -a and then returns e. ++func (e *G1) Neg(a *G1) *G1 { ++ if e.p == nil { ++ e.p = newCurvePoint(nil) ++ } ++ e.p.Negative(a.p) ++ return e ++} ++ ++// Marshal converts n to a byte slice. ++func (e *G1) Marshal() []byte { ++ // Each value is a 256-bit number. ++ const numBytes = 256 / 8 ++ ++ if e.p.IsInfinity() { ++ return make([]byte, numBytes*2) ++ } ++ ++ e.p.MakeAffine(nil) ++ ++ xBytes := new(big.Int).Mod(e.p.x, p).Bytes() ++ yBytes := new(big.Int).Mod(e.p.y, p).Bytes() ++ ++ ret := make([]byte, numBytes*2) ++ copy(ret[1*numBytes-len(xBytes):], xBytes) ++ copy(ret[2*numBytes-len(yBytes):], yBytes) ++ ++ return ret ++} ++ ++// Unmarshal sets e to the result of converting the output of Marshal back into ++// a group element and then returns e. ++func (e *G1) Unmarshal(m []byte) (*G1, bool) { ++ // Each value is a 256-bit number. ++ const numBytes = 256 / 8 ++ ++ if len(m) != 2*numBytes { ++ return nil, false ++ } ++ ++ if e.p == nil { ++ e.p = newCurvePoint(nil) ++ } ++ ++ e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) ++ e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) ++ ++ if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { ++ // This is the point at infinity. ++ e.p.y.SetInt64(1) ++ e.p.z.SetInt64(0) ++ e.p.t.SetInt64(0) ++ } else { ++ e.p.z.SetInt64(1) ++ e.p.t.SetInt64(1) ++ ++ if !e.p.IsOnCurve() { ++ return nil, false ++ } ++ } ++ ++ return e, true ++} ++ ++// G2 is an abstract cyclic group. The zero value is suitable for use as the ++// output of an operation, but cannot be used as an input. ++type G2 struct { ++ p *twistPoint ++} ++ ++// RandomG2 returns x and gβ‚‚Λ£ where x is a random, non-zero number read from r. ++func RandomG2(r io.Reader) (*big.Int, *G2, error) { ++ var k *big.Int ++ var err error ++ ++ for { ++ k, err = rand.Int(r, Order) ++ if err != nil { ++ return nil, nil, err ++ } ++ if k.Sign() > 0 { ++ break ++ } ++ } ++ ++ return k, new(G2).ScalarBaseMult(k), nil ++} ++ ++func (e *G2) String() string { ++ if e.p == nil { ++ return "bn256.G2" + newTwistPoint(nil).String() ++ } ++ return "bn256.G2" + e.p.String() ++} ++ ++// ScalarBaseMult sets e to g*k where g is the generator of the group and ++// then returns out. ++func (e *G2) ScalarBaseMult(k *big.Int) *G2 { ++ if e.p == nil { ++ e.p = newTwistPoint(nil) ++ } ++ e.p.Mul(twistGen, k, new(bnPool)) ++ return e ++} ++ ++// ScalarMult sets e to a*k and then returns e. ++func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { ++ if e.p == nil { ++ e.p = newTwistPoint(nil) ++ } ++ e.p.Mul(a.p, k, new(bnPool)) ++ return e ++} ++ ++// Add sets e to a+b and then returns e. ++// ++// Warning: this function is not complete, it fails for a equal to b. ++func (e *G2) Add(a, b *G2) *G2 { ++ if e.p == nil { ++ e.p = newTwistPoint(nil) ++ } ++ e.p.Add(a.p, b.p, new(bnPool)) ++ return e ++} ++ ++// Marshal converts n into a byte slice. ++func (n *G2) Marshal() []byte { ++ // Each value is a 256-bit number. ++ const numBytes = 256 / 8 ++ ++ if n.p.IsInfinity() { ++ return make([]byte, numBytes*4) ++ } ++ ++ n.p.MakeAffine(nil) ++ ++ xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes() ++ xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes() ++ yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes() ++ yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes() ++ ++ ret := make([]byte, numBytes*4) ++ copy(ret[1*numBytes-len(xxBytes):], xxBytes) ++ copy(ret[2*numBytes-len(xyBytes):], xyBytes) ++ copy(ret[3*numBytes-len(yxBytes):], yxBytes) ++ copy(ret[4*numBytes-len(yyBytes):], yyBytes) ++ ++ return ret ++} ++ ++// Unmarshal sets e to the result of converting the output of Marshal back into ++// a group element and then returns e. ++func (e *G2) Unmarshal(m []byte) (*G2, bool) { ++ // Each value is a 256-bit number. ++ const numBytes = 256 / 8 ++ ++ if len(m) != 4*numBytes { ++ return nil, false ++ } ++ ++ if e.p == nil { ++ e.p = newTwistPoint(nil) ++ } ++ ++ e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) ++ e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) ++ e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) ++ e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) ++ ++ if e.p.x.x.Sign() == 0 && ++ e.p.x.y.Sign() == 0 && ++ e.p.y.x.Sign() == 0 && ++ e.p.y.y.Sign() == 0 { ++ // This is the point at infinity. ++ e.p.y.SetOne() ++ e.p.z.SetZero() ++ e.p.t.SetZero() ++ } else { ++ e.p.z.SetOne() ++ e.p.t.SetOne() ++ ++ if !e.p.IsOnCurve() { ++ return nil, false ++ } ++ } ++ ++ return e, true ++} ++ ++// GT is an abstract cyclic group. The zero value is suitable for use as the ++// output of an operation, but cannot be used as an input. ++type GT struct { ++ p *gfP12 ++} ++ ++func (e *GT) String() string { ++ if e.p == nil { ++ return "bn256.GT" + newGFp12(nil).String() ++ } ++ return "bn256.GT" + e.p.String() ++} ++ ++// ScalarMult sets e to a*k and then returns e. ++func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { ++ if e.p == nil { ++ e.p = newGFp12(nil) ++ } ++ e.p.Exp(a.p, k, new(bnPool)) ++ return e ++} ++ ++// Add sets e to a+b and then returns e. ++func (e *GT) Add(a, b *GT) *GT { ++ if e.p == nil { ++ e.p = newGFp12(nil) ++ } ++ e.p.Mul(a.p, b.p, new(bnPool)) ++ return e ++} ++ ++// Neg sets e to -a and then returns e. ++func (e *GT) Neg(a *GT) *GT { ++ if e.p == nil { ++ e.p = newGFp12(nil) ++ } ++ e.p.Invert(a.p, new(bnPool)) ++ return e ++} ++ ++// Marshal converts n into a byte slice. ++func (n *GT) Marshal() []byte { ++ n.p.Minimal() ++ ++ xxxBytes := n.p.x.x.x.Bytes() ++ xxyBytes := n.p.x.x.y.Bytes() ++ xyxBytes := n.p.x.y.x.Bytes() ++ xyyBytes := n.p.x.y.y.Bytes() ++ xzxBytes := n.p.x.z.x.Bytes() ++ xzyBytes := n.p.x.z.y.Bytes() ++ yxxBytes := n.p.y.x.x.Bytes() ++ yxyBytes := n.p.y.x.y.Bytes() ++ yyxBytes := n.p.y.y.x.Bytes() ++ yyyBytes := n.p.y.y.y.Bytes() ++ yzxBytes := n.p.y.z.x.Bytes() ++ yzyBytes := n.p.y.z.y.Bytes() ++ ++ // Each value is a 256-bit number. ++ const numBytes = 256 / 8 ++ ++ ret := make([]byte, numBytes*12) ++ copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) ++ copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) ++ copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) ++ copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) ++ copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) ++ copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) ++ copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) ++ copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) ++ copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) ++ copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) ++ copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) ++ copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) ++ ++ return ret ++} ++ ++// Unmarshal sets e to the result of converting the output of Marshal back into ++// a group element and then returns e. ++func (e *GT) Unmarshal(m []byte) (*GT, bool) { ++ // Each value is a 256-bit number. ++ const numBytes = 256 / 8 ++ ++ if len(m) != 12*numBytes { ++ return nil, false ++ } ++ ++ if e.p == nil { ++ e.p = newGFp12(nil) ++ } ++ ++ e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) ++ e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) ++ e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) ++ e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) ++ e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) ++ e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) ++ e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) ++ e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) ++ e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) ++ e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) ++ e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) ++ e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) ++ ++ return e, true ++} ++ ++// Pair calculates an Optimal Ate pairing. ++func Pair(g1 *G1, g2 *G2) *GT { ++ return >{optimalAte(g2.p, g1.p, new(bnPool))} ++} ++ ++// bnPool implements a tiny cache of *big.Int objects that's used to reduce the ++// number of allocations made during processing. ++type bnPool struct { ++ bns []*big.Int ++ count int ++} ++ ++func (pool *bnPool) Get() *big.Int { ++ if pool == nil { ++ return new(big.Int) ++ } ++ ++ pool.count++ ++ l := len(pool.bns) ++ if l == 0 { ++ return new(big.Int) ++ } ++ ++ bn := pool.bns[l-1] ++ pool.bns = pool.bns[:l-1] ++ return bn ++} ++ ++func (pool *bnPool) Put(bn *big.Int) { ++ if pool == nil { ++ return ++ } ++ pool.bns = append(pool.bns, bn) ++ pool.count-- ++} ++ ++func (pool *bnPool) Count() int { ++ return pool.count ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/bn256_test.go b/ms_mod/golang.org/x/crypto/bn256/bn256_test.go +new file mode 100644 +index 00000000000000..1cec3884ecd4c9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/bn256_test.go +@@ -0,0 +1,304 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "math/big" ++ "testing" ++) ++ ++func TestGFp2Invert(t *testing.T) { ++ pool := new(bnPool) ++ ++ a := newGFp2(pool) ++ a.x.SetString("23423492374", 10) ++ a.y.SetString("12934872398472394827398470", 10) ++ ++ inv := newGFp2(pool) ++ inv.Invert(a, pool) ++ ++ b := newGFp2(pool).Mul(inv, a, pool) ++ if b.x.Int64() != 0 || b.y.Int64() != 1 { ++ t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y) ++ } ++ ++ a.Put(pool) ++ b.Put(pool) ++ inv.Put(pool) ++ ++ if c := pool.Count(); c > 0 { ++ t.Errorf("Pool count non-zero: %d\n", c) ++ } ++} ++ ++func isZero(n *big.Int) bool { ++ return new(big.Int).Mod(n, p).Int64() == 0 ++} ++ ++func isOne(n *big.Int) bool { ++ return new(big.Int).Mod(n, p).Int64() == 1 ++} ++ ++func TestGFp6Invert(t *testing.T) { ++ pool := new(bnPool) ++ ++ a := newGFp6(pool) ++ a.x.x.SetString("239487238491", 10) ++ a.x.y.SetString("2356249827341", 10) ++ a.y.x.SetString("082659782", 10) ++ a.y.y.SetString("182703523765", 10) ++ a.z.x.SetString("978236549263", 10) ++ a.z.y.SetString("64893242", 10) ++ ++ inv := newGFp6(pool) ++ inv.Invert(a, pool) ++ ++ b := newGFp6(pool).Mul(inv, a, pool) ++ if !isZero(b.x.x) || ++ !isZero(b.x.y) || ++ !isZero(b.y.x) || ++ !isZero(b.y.y) || ++ !isZero(b.z.x) || ++ !isOne(b.z.y) { ++ t.Fatalf("bad result for a^-1*a: %s", b) ++ } ++ ++ a.Put(pool) ++ b.Put(pool) ++ inv.Put(pool) ++ ++ if c := pool.Count(); c > 0 { ++ t.Errorf("Pool count non-zero: %d\n", c) ++ } ++} ++ ++func TestGFp12Invert(t *testing.T) { ++ pool := new(bnPool) ++ ++ a := newGFp12(pool) ++ a.x.x.x.SetString("239846234862342323958623", 10) ++ a.x.x.y.SetString("2359862352529835623", 10) ++ a.x.y.x.SetString("928836523", 10) ++ a.x.y.y.SetString("9856234", 10) ++ a.x.z.x.SetString("235635286", 10) ++ a.x.z.y.SetString("5628392833", 10) ++ a.y.x.x.SetString("252936598265329856238956532167968", 10) ++ a.y.x.y.SetString("23596239865236954178968", 10) ++ a.y.y.x.SetString("95421692834", 10) ++ a.y.y.y.SetString("236548", 10) ++ a.y.z.x.SetString("924523", 10) ++ a.y.z.y.SetString("12954623", 10) ++ ++ inv := newGFp12(pool) ++ inv.Invert(a, pool) ++ ++ b := newGFp12(pool).Mul(inv, a, pool) ++ if !isZero(b.x.x.x) || ++ !isZero(b.x.x.y) || ++ !isZero(b.x.y.x) || ++ !isZero(b.x.y.y) || ++ !isZero(b.x.z.x) || ++ !isZero(b.x.z.y) || ++ !isZero(b.y.x.x) || ++ !isZero(b.y.x.y) || ++ !isZero(b.y.y.x) || ++ !isZero(b.y.y.y) || ++ !isZero(b.y.z.x) || ++ !isOne(b.y.z.y) { ++ t.Fatalf("bad result for a^-1*a: %s", b) ++ } ++ ++ a.Put(pool) ++ b.Put(pool) ++ inv.Put(pool) ++ ++ if c := pool.Count(); c > 0 { ++ t.Errorf("Pool count non-zero: %d\n", c) ++ } ++} ++ ++func TestCurveImpl(t *testing.T) { ++ pool := new(bnPool) ++ ++ g := &curvePoint{ ++ pool.Get().SetInt64(1), ++ pool.Get().SetInt64(-2), ++ pool.Get().SetInt64(1), ++ pool.Get().SetInt64(0), ++ } ++ ++ x := pool.Get().SetInt64(32498273234) ++ X := newCurvePoint(pool).Mul(g, x, pool) ++ ++ y := pool.Get().SetInt64(98732423523) ++ Y := newCurvePoint(pool).Mul(g, y, pool) ++ ++ s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool) ++ s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool) ++ ++ if s1.x.Cmp(s2.x) != 0 || ++ s2.x.Cmp(s1.x) != 0 { ++ t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y) ++ } ++ ++ pool.Put(x) ++ X.Put(pool) ++ pool.Put(y) ++ Y.Put(pool) ++ s1.Put(pool) ++ s2.Put(pool) ++ g.Put(pool) ++ ++ if c := pool.Count(); c > 0 { ++ t.Errorf("Pool count non-zero: %d\n", c) ++ } ++} ++ ++func TestOrderG1(t *testing.T) { ++ g := new(G1).ScalarBaseMult(Order) ++ if !g.p.IsInfinity() { ++ t.Error("G1 has incorrect order") ++ } ++ ++ one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) ++ g.Add(g, one) ++ g.p.MakeAffine(nil) ++ if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 { ++ t.Errorf("1+0 != 1 in G1") ++ } ++} ++ ++func TestOrderG2(t *testing.T) { ++ g := new(G2).ScalarBaseMult(Order) ++ if !g.p.IsInfinity() { ++ t.Error("G2 has incorrect order") ++ } ++ ++ one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) ++ g.Add(g, one) ++ g.p.MakeAffine(nil) ++ if g.p.x.x.Cmp(one.p.x.x) != 0 || ++ g.p.x.y.Cmp(one.p.x.y) != 0 || ++ g.p.y.x.Cmp(one.p.y.x) != 0 || ++ g.p.y.y.Cmp(one.p.y.y) != 0 { ++ t.Errorf("1+0 != 1 in G2") ++ } ++} ++ ++func TestOrderGT(t *testing.T) { ++ gt := Pair(&G1{curveGen}, &G2{twistGen}) ++ g := new(GT).ScalarMult(gt, Order) ++ if !g.p.IsOne() { ++ t.Error("GT has incorrect order") ++ } ++} ++ ++func TestBilinearity(t *testing.T) { ++ for i := 0; i < 2; i++ { ++ a, p1, _ := RandomG1(rand.Reader) ++ b, p2, _ := RandomG2(rand.Reader) ++ e1 := Pair(p1, p2) ++ ++ e2 := Pair(&G1{curveGen}, &G2{twistGen}) ++ e2.ScalarMult(e2, a) ++ e2.ScalarMult(e2, b) ++ ++ minusE2 := new(GT).Neg(e2) ++ e1.Add(e1, minusE2) ++ ++ if !e1.p.IsOne() { ++ t.Fatalf("bad pairing result: %s", e1) ++ } ++ } ++} ++ ++func TestG1Marshal(t *testing.T) { ++ g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) ++ form := g.Marshal() ++ _, ok := new(G1).Unmarshal(form) ++ if !ok { ++ t.Fatalf("failed to unmarshal") ++ } ++ ++ g.ScalarBaseMult(Order) ++ form = g.Marshal() ++ g2, ok := new(G1).Unmarshal(form) ++ if !ok { ++ t.Fatalf("failed to unmarshal ∞") ++ } ++ if !g2.p.IsInfinity() { ++ t.Fatalf("∞ unmarshaled incorrectly") ++ } ++} ++ ++func TestG2Marshal(t *testing.T) { ++ g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) ++ form := g.Marshal() ++ _, ok := new(G2).Unmarshal(form) ++ if !ok { ++ t.Fatalf("failed to unmarshal") ++ } ++ ++ g.ScalarBaseMult(Order) ++ form = g.Marshal() ++ g2, ok := new(G2).Unmarshal(form) ++ if !ok { ++ t.Fatalf("failed to unmarshal ∞") ++ } ++ if !g2.p.IsInfinity() { ++ t.Fatalf("∞ unmarshaled incorrectly") ++ } ++} ++ ++func TestG1Identity(t *testing.T) { ++ g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0)) ++ if !g.p.IsInfinity() { ++ t.Error("failure") ++ } ++} ++ ++func TestG2Identity(t *testing.T) { ++ g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0)) ++ if !g.p.IsInfinity() { ++ t.Error("failure") ++ } ++} ++ ++func TestTripartiteDiffieHellman(t *testing.T) { ++ a, _ := rand.Int(rand.Reader, Order) ++ b, _ := rand.Int(rand.Reader, Order) ++ c, _ := rand.Int(rand.Reader, Order) ++ ++ pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) ++ qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) ++ pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) ++ qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) ++ pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) ++ qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) ++ ++ k1 := Pair(pb, qc) ++ k1.ScalarMult(k1, a) ++ k1Bytes := k1.Marshal() ++ ++ k2 := Pair(pc, qa) ++ k2.ScalarMult(k2, b) ++ k2Bytes := k2.Marshal() ++ ++ k3 := Pair(pa, qb) ++ k3.ScalarMult(k3, c) ++ k3Bytes := k3.Marshal() ++ ++ if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { ++ t.Errorf("keys didn't agree") ++ } ++} ++ ++func BenchmarkPairing(b *testing.B) { ++ for i := 0; i < b.N; i++ { ++ Pair(&G1{curveGen}, &G2{twistGen}) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/constants.go b/ms_mod/golang.org/x/crypto/bn256/constants.go +new file mode 100644 +index 00000000000000..1ccefc4982aa2a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/constants.go +@@ -0,0 +1,44 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++import ( ++ "math/big" ++) ++ ++func bigFromBase10(s string) *big.Int { ++ n, _ := new(big.Int).SetString(s, 10) ++ return n ++} ++ ++// u is the BN parameter that determines the prime: 1868033Β³. ++var u = bigFromBase10("6518589491078791937") ++ ++// p is a prime over which we form a basic field: 36u⁴+36uΒ³+24uΒ²+6u+1. ++var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783") ++ ++// Order is the number of elements in both G₁ and Gβ‚‚: 36u⁴+36uΒ³+18uΒ²+6u+1. ++var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969") ++ ++// xiToPMinus1Over6 is ΞΎ^((p-1)/6) where ΞΎ = i+3. ++var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")} ++ ++// xiToPMinus1Over3 is ΞΎ^((p-1)/3) where ΞΎ = i+3. ++var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")} ++ ++// xiToPMinus1Over2 is ΞΎ^((p-1)/2) where ΞΎ = i+3. ++var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")} ++ ++// xiToPSquaredMinus1Over3 is ΞΎ^((pΒ²-1)/3) where ΞΎ = i+3. ++var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752") ++ ++// xiTo2PSquaredMinus2Over3 is ΞΎ^((2pΒ²-2)/3) where ΞΎ = i+3 (a cubic root of unity, mod p). ++var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030") ++ ++// xiToPSquaredMinus1Over6 is ΞΎ^((1pΒ²-1)/6) where ΞΎ = i+3 (a cubic root of -1, mod p). ++var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753") ++ ++// xiTo2PMinus2Over3 is ΞΎ^((2p-2)/3) where ΞΎ = i+3. ++var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")} +diff --git a/ms_mod/golang.org/x/crypto/bn256/curve.go b/ms_mod/golang.org/x/crypto/bn256/curve.go +new file mode 100644 +index 00000000000000..63c052bc22f2bf +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/curve.go +@@ -0,0 +1,287 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++import ( ++ "math/big" ++) ++ ++// curvePoint implements the elliptic curve yΒ²=xΒ³+3. Points are kept in ++// Jacobian form and t=zΒ² when valid. G₁ is the set of points of this curve on ++// GF(p). ++type curvePoint struct { ++ x, y, z, t *big.Int ++} ++ ++var curveB = new(big.Int).SetInt64(3) ++ ++// curveGen is the generator of G₁. ++var curveGen = &curvePoint{ ++ new(big.Int).SetInt64(1), ++ new(big.Int).SetInt64(-2), ++ new(big.Int).SetInt64(1), ++ new(big.Int).SetInt64(1), ++} ++ ++func newCurvePoint(pool *bnPool) *curvePoint { ++ return &curvePoint{ ++ pool.Get(), ++ pool.Get(), ++ pool.Get(), ++ pool.Get(), ++ } ++} ++ ++func (c *curvePoint) String() string { ++ c.MakeAffine(new(bnPool)) ++ return "(" + c.x.String() + ", " + c.y.String() + ")" ++} ++ ++func (c *curvePoint) Put(pool *bnPool) { ++ pool.Put(c.x) ++ pool.Put(c.y) ++ pool.Put(c.z) ++ pool.Put(c.t) ++} ++ ++func (c *curvePoint) Set(a *curvePoint) { ++ c.x.Set(a.x) ++ c.y.Set(a.y) ++ c.z.Set(a.z) ++ c.t.Set(a.t) ++} ++ ++// IsOnCurve returns true iff c is on the curve where c must be in affine form. ++func (c *curvePoint) IsOnCurve() bool { ++ yy := new(big.Int).Mul(c.y, c.y) ++ xxx := new(big.Int).Mul(c.x, c.x) ++ xxx.Mul(xxx, c.x) ++ yy.Sub(yy, xxx) ++ yy.Sub(yy, curveB) ++ if yy.Sign() < 0 || yy.Cmp(p) >= 0 { ++ yy.Mod(yy, p) ++ } ++ return yy.Sign() == 0 ++} ++ ++func (c *curvePoint) SetInfinity() { ++ c.z.SetInt64(0) ++} ++ ++func (c *curvePoint) IsInfinity() bool { ++ return c.z.Sign() == 0 ++} ++ ++func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { ++ if a.IsInfinity() { ++ c.Set(b) ++ return ++ } ++ if b.IsInfinity() { ++ c.Set(a) ++ return ++ } ++ ++ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 ++ ++ // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] ++ // by [u1:s1:z1Β·z2] and [u2:s2:z1Β·z2] ++ // where u1 = x1Β·z2Β², s1 = y1Β·z2Β³ and u1 = x2Β·z1Β², s2 = y2Β·z1Β³ ++ z1z1 := pool.Get().Mul(a.z, a.z) ++ z1z1.Mod(z1z1, p) ++ z2z2 := pool.Get().Mul(b.z, b.z) ++ z2z2.Mod(z2z2, p) ++ u1 := pool.Get().Mul(a.x, z2z2) ++ u1.Mod(u1, p) ++ u2 := pool.Get().Mul(b.x, z1z1) ++ u2.Mod(u2, p) ++ ++ t := pool.Get().Mul(b.z, z2z2) ++ t.Mod(t, p) ++ s1 := pool.Get().Mul(a.y, t) ++ s1.Mod(s1, p) ++ ++ t.Mul(a.z, z1z1) ++ t.Mod(t, p) ++ s2 := pool.Get().Mul(b.y, t) ++ s2.Mod(s2, p) ++ ++ // Compute x = (2h)Β²(sΒ²-u1-u2) ++ // where s = (s2-s1)/(u2-u1) is the slope of the line through ++ // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. ++ // This is also: ++ // 4(s2-s1)Β² - 4hΒ²(u1+u2) = 4(s2-s1)Β² - 4hΒ³ - 4hΒ²(2u1) ++ // = rΒ² - j - 2v ++ // with the notations below. ++ h := pool.Get().Sub(u2, u1) ++ xEqual := h.Sign() == 0 ++ ++ t.Add(h, h) ++ // i = 4hΒ² ++ i := pool.Get().Mul(t, t) ++ i.Mod(i, p) ++ // j = 4hΒ³ ++ j := pool.Get().Mul(h, i) ++ j.Mod(j, p) ++ ++ t.Sub(s2, s1) ++ yEqual := t.Sign() == 0 ++ if xEqual && yEqual { ++ c.Double(a, pool) ++ return ++ } ++ r := pool.Get().Add(t, t) ++ ++ v := pool.Get().Mul(u1, i) ++ v.Mod(v, p) ++ ++ // t4 = 4(s2-s1)Β² ++ t4 := pool.Get().Mul(r, r) ++ t4.Mod(t4, p) ++ t.Add(v, v) ++ t6 := pool.Get().Sub(t4, j) ++ c.x.Sub(t6, t) ++ ++ // Set y = -(2h)Β³(s1 + s*(x/4hΒ²-u1)) ++ // This is also ++ // y = - 2Β·s1Β·j - (s2-s1)(2x - 2iΒ·u1) = r(v-x) - 2Β·s1Β·j ++ t.Sub(v, c.x) // t7 ++ t4.Mul(s1, j) // t8 ++ t4.Mod(t4, p) ++ t6.Add(t4, t4) // t9 ++ t4.Mul(r, t) // t10 ++ t4.Mod(t4, p) ++ c.y.Sub(t4, t6) ++ ++ // Set z = 2(u2-u1)Β·z1Β·z2 = 2hΒ·z1Β·z2 ++ t.Add(a.z, b.z) // t11 ++ t4.Mul(t, t) // t12 ++ t4.Mod(t4, p) ++ t.Sub(t4, z1z1) // t13 ++ t4.Sub(t, z2z2) // t14 ++ c.z.Mul(t4, h) ++ c.z.Mod(c.z, p) ++ ++ pool.Put(z1z1) ++ pool.Put(z2z2) ++ pool.Put(u1) ++ pool.Put(u2) ++ pool.Put(t) ++ pool.Put(s1) ++ pool.Put(s2) ++ pool.Put(h) ++ pool.Put(i) ++ pool.Put(j) ++ pool.Put(r) ++ pool.Put(v) ++ pool.Put(t4) ++ pool.Put(t6) ++} ++ ++func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { ++ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 ++ A := pool.Get().Mul(a.x, a.x) ++ A.Mod(A, p) ++ B := pool.Get().Mul(a.y, a.y) ++ B.Mod(B, p) ++ C := pool.Get().Mul(B, B) ++ C.Mod(C, p) ++ ++ t := pool.Get().Add(a.x, B) ++ t2 := pool.Get().Mul(t, t) ++ t2.Mod(t2, p) ++ t.Sub(t2, A) ++ t2.Sub(t, C) ++ d := pool.Get().Add(t2, t2) ++ t.Add(A, A) ++ e := pool.Get().Add(t, A) ++ f := pool.Get().Mul(e, e) ++ f.Mod(f, p) ++ ++ t.Add(d, d) ++ c.x.Sub(f, t) ++ ++ t.Add(C, C) ++ t2.Add(t, t) ++ t.Add(t2, t2) ++ c.y.Sub(d, c.x) ++ t2.Mul(e, c.y) ++ t2.Mod(t2, p) ++ c.y.Sub(t2, t) ++ ++ t.Mul(a.y, a.z) ++ t.Mod(t, p) ++ c.z.Add(t, t) ++ ++ pool.Put(A) ++ pool.Put(B) ++ pool.Put(C) ++ pool.Put(t) ++ pool.Put(t2) ++ pool.Put(d) ++ pool.Put(e) ++ pool.Put(f) ++} ++ ++func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { ++ sum := newCurvePoint(pool) ++ sum.SetInfinity() ++ t := newCurvePoint(pool) ++ ++ for i := scalar.BitLen(); i >= 0; i-- { ++ t.Double(sum, pool) ++ if scalar.Bit(i) != 0 { ++ sum.Add(t, a, pool) ++ } else { ++ sum.Set(t) ++ } ++ } ++ ++ c.Set(sum) ++ sum.Put(pool) ++ t.Put(pool) ++ return c ++} ++ ++// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets ++// c to 0 : 1 : 0. ++func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { ++ if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { ++ return c ++ } ++ if c.IsInfinity() { ++ c.x.SetInt64(0) ++ c.y.SetInt64(1) ++ c.z.SetInt64(0) ++ c.t.SetInt64(0) ++ return c ++ } ++ ++ zInv := pool.Get().ModInverse(c.z, p) ++ t := pool.Get().Mul(c.y, zInv) ++ t.Mod(t, p) ++ zInv2 := pool.Get().Mul(zInv, zInv) ++ zInv2.Mod(zInv2, p) ++ c.y.Mul(t, zInv2) ++ c.y.Mod(c.y, p) ++ t.Mul(c.x, zInv2) ++ t.Mod(t, p) ++ c.x.Set(t) ++ c.z.SetInt64(1) ++ c.t.SetInt64(1) ++ ++ pool.Put(zInv) ++ pool.Put(t) ++ pool.Put(zInv2) ++ ++ return c ++} ++ ++func (c *curvePoint) Negative(a *curvePoint) { ++ c.x.Set(a.x) ++ c.y.Neg(a.y) ++ c.z.Set(a.z) ++ c.t.SetInt64(0) ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/example_test.go b/ms_mod/golang.org/x/crypto/bn256/example_test.go +new file mode 100644 +index 00000000000000..b2d19807a25e6d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/example_test.go +@@ -0,0 +1,43 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++import ( ++ "crypto/rand" ++) ++ ++func ExamplePair() { ++ // This implements the tripartite Diffie-Hellman algorithm from "A One ++ // Round Protocol for Tripartite Diffie-Hellman", A. Joux. ++ // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf ++ ++ // Each of three parties, a, b and c, generate a private value. ++ a, _ := rand.Int(rand.Reader, Order) ++ b, _ := rand.Int(rand.Reader, Order) ++ c, _ := rand.Int(rand.Reader, Order) ++ ++ // Then each party calculates g₁ and gβ‚‚ times their private value. ++ pa := new(G1).ScalarBaseMult(a) ++ qa := new(G2).ScalarBaseMult(a) ++ ++ pb := new(G1).ScalarBaseMult(b) ++ qb := new(G2).ScalarBaseMult(b) ++ ++ pc := new(G1).ScalarBaseMult(c) ++ qc := new(G2).ScalarBaseMult(c) ++ ++ // Now each party exchanges its public values with the other two and ++ // all parties can calculate the shared key. ++ k1 := Pair(pb, qc) ++ k1.ScalarMult(k1, a) ++ ++ k2 := Pair(pc, qa) ++ k2.ScalarMult(k2, b) ++ ++ k3 := Pair(pa, qb) ++ k3.ScalarMult(k3, c) ++ ++ // k1, k2 and k3 will all be equal. ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/gfp12.go b/ms_mod/golang.org/x/crypto/bn256/gfp12.go +new file mode 100644 +index 00000000000000..2b0151ebcc4924 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/gfp12.go +@@ -0,0 +1,200 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++// For details of the algorithms used, see "Multiplication and Squaring on ++// Pairing-Friendly Fields, Devegili et al. ++// http://eprint.iacr.org/2006/471.pdf. ++ ++import ( ++ "math/big" ++) ++ ++// gfP12 implements the field of size pΒΉΒ² as a quadratic extension of gfP6 ++// where ω²=Ο„. ++type gfP12 struct { ++ x, y *gfP6 // value is xΟ‰ + y ++} ++ ++func newGFp12(pool *bnPool) *gfP12 { ++ return &gfP12{newGFp6(pool), newGFp6(pool)} ++} ++ ++func (e *gfP12) String() string { ++ return "(" + e.x.String() + "," + e.y.String() + ")" ++} ++ ++func (e *gfP12) Put(pool *bnPool) { ++ e.x.Put(pool) ++ e.y.Put(pool) ++} ++ ++func (e *gfP12) Set(a *gfP12) *gfP12 { ++ e.x.Set(a.x) ++ e.y.Set(a.y) ++ return e ++} ++ ++func (e *gfP12) SetZero() *gfP12 { ++ e.x.SetZero() ++ e.y.SetZero() ++ return e ++} ++ ++func (e *gfP12) SetOne() *gfP12 { ++ e.x.SetZero() ++ e.y.SetOne() ++ return e ++} ++ ++func (e *gfP12) Minimal() { ++ e.x.Minimal() ++ e.y.Minimal() ++} ++ ++func (e *gfP12) IsZero() bool { ++ e.Minimal() ++ return e.x.IsZero() && e.y.IsZero() ++} ++ ++func (e *gfP12) IsOne() bool { ++ e.Minimal() ++ return e.x.IsZero() && e.y.IsOne() ++} ++ ++func (e *gfP12) Conjugate(a *gfP12) *gfP12 { ++ e.x.Negative(a.x) ++ e.y.Set(a.y) ++ return a ++} ++ ++func (e *gfP12) Negative(a *gfP12) *gfP12 { ++ e.x.Negative(a.x) ++ e.y.Negative(a.y) ++ return e ++} ++ ++// Frobenius computes (xΟ‰+y)^p = x^p ω·ξ^((p-1)/6) + y^p ++func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { ++ e.x.Frobenius(a.x, pool) ++ e.y.Frobenius(a.y, pool) ++ e.x.MulScalar(e.x, xiToPMinus1Over6, pool) ++ return e ++} ++ ++// FrobeniusP2 computes (xΟ‰+y)^pΒ² = x^pΒ² ω·ξ^((pΒ²-1)/6) + y^pΒ² ++func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { ++ e.x.FrobeniusP2(a.x) ++ e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) ++ e.y.FrobeniusP2(a.y) ++ return e ++} ++ ++func (e *gfP12) Add(a, b *gfP12) *gfP12 { ++ e.x.Add(a.x, b.x) ++ e.y.Add(a.y, b.y) ++ return e ++} ++ ++func (e *gfP12) Sub(a, b *gfP12) *gfP12 { ++ e.x.Sub(a.x, b.x) ++ e.y.Sub(a.y, b.y) ++ return e ++} ++ ++func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { ++ tx := newGFp6(pool) ++ tx.Mul(a.x, b.y, pool) ++ t := newGFp6(pool) ++ t.Mul(b.x, a.y, pool) ++ tx.Add(tx, t) ++ ++ ty := newGFp6(pool) ++ ty.Mul(a.y, b.y, pool) ++ t.Mul(a.x, b.x, pool) ++ t.MulTau(t, pool) ++ e.y.Add(ty, t) ++ e.x.Set(tx) ++ ++ tx.Put(pool) ++ ty.Put(pool) ++ t.Put(pool) ++ return e ++} ++ ++func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { ++ e.x.Mul(a.x, b, pool) ++ e.y.Mul(a.y, b, pool) ++ return e ++} ++ ++func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { ++ sum := newGFp12(pool) ++ sum.SetOne() ++ t := newGFp12(pool) ++ ++ for i := power.BitLen() - 1; i >= 0; i-- { ++ t.Square(sum, pool) ++ if power.Bit(i) != 0 { ++ sum.Mul(t, a, pool) ++ } else { ++ sum.Set(t) ++ } ++ } ++ ++ c.Set(sum) ++ ++ sum.Put(pool) ++ t.Put(pool) ++ ++ return c ++} ++ ++func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { ++ // Complex squaring algorithm ++ v0 := newGFp6(pool) ++ v0.Mul(a.x, a.y, pool) ++ ++ t := newGFp6(pool) ++ t.MulTau(a.x, pool) ++ t.Add(a.y, t) ++ ty := newGFp6(pool) ++ ty.Add(a.x, a.y) ++ ty.Mul(ty, t, pool) ++ ty.Sub(ty, v0) ++ t.MulTau(v0, pool) ++ ty.Sub(ty, t) ++ ++ e.y.Set(ty) ++ e.x.Double(v0) ++ ++ v0.Put(pool) ++ t.Put(pool) ++ ty.Put(pool) ++ ++ return e ++} ++ ++func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { ++ // See "Implementing cryptographic pairings", M. Scott, section 3.2. ++ // ftp://136.206.11.249/pub/crypto/pairings.pdf ++ t1 := newGFp6(pool) ++ t2 := newGFp6(pool) ++ ++ t1.Square(a.x, pool) ++ t2.Square(a.y, pool) ++ t1.MulTau(t1, pool) ++ t1.Sub(t2, t1) ++ t2.Invert(t1, pool) ++ ++ e.x.Negative(a.x) ++ e.y.Set(a.y) ++ e.MulScalar(e, t2, pool) ++ ++ t1.Put(pool) ++ t2.Put(pool) ++ ++ return e ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/gfp2.go b/ms_mod/golang.org/x/crypto/bn256/gfp2.go +new file mode 100644 +index 00000000000000..97f3f1f3fa1a0e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/gfp2.go +@@ -0,0 +1,219 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++// For details of the algorithms used, see "Multiplication and Squaring on ++// Pairing-Friendly Fields, Devegili et al. ++// http://eprint.iacr.org/2006/471.pdf. ++ ++import ( ++ "math/big" ++) ++ ++// gfP2 implements a field of size pΒ² as a quadratic extension of the base ++// field where iΒ²=-1. ++type gfP2 struct { ++ x, y *big.Int // value is xi+y. ++} ++ ++func newGFp2(pool *bnPool) *gfP2 { ++ return &gfP2{pool.Get(), pool.Get()} ++} ++ ++func (e *gfP2) String() string { ++ x := new(big.Int).Mod(e.x, p) ++ y := new(big.Int).Mod(e.y, p) ++ return "(" + x.String() + "," + y.String() + ")" ++} ++ ++func (e *gfP2) Put(pool *bnPool) { ++ pool.Put(e.x) ++ pool.Put(e.y) ++} ++ ++func (e *gfP2) Set(a *gfP2) *gfP2 { ++ e.x.Set(a.x) ++ e.y.Set(a.y) ++ return e ++} ++ ++func (e *gfP2) SetZero() *gfP2 { ++ e.x.SetInt64(0) ++ e.y.SetInt64(0) ++ return e ++} ++ ++func (e *gfP2) SetOne() *gfP2 { ++ e.x.SetInt64(0) ++ e.y.SetInt64(1) ++ return e ++} ++ ++func (e *gfP2) Minimal() { ++ if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 { ++ e.x.Mod(e.x, p) ++ } ++ if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 { ++ e.y.Mod(e.y, p) ++ } ++} ++ ++func (e *gfP2) IsZero() bool { ++ return e.x.Sign() == 0 && e.y.Sign() == 0 ++} ++ ++func (e *gfP2) IsOne() bool { ++ if e.x.Sign() != 0 { ++ return false ++ } ++ words := e.y.Bits() ++ return len(words) == 1 && words[0] == 1 ++} ++ ++func (e *gfP2) Conjugate(a *gfP2) *gfP2 { ++ e.y.Set(a.y) ++ e.x.Neg(a.x) ++ return e ++} ++ ++func (e *gfP2) Negative(a *gfP2) *gfP2 { ++ e.x.Neg(a.x) ++ e.y.Neg(a.y) ++ return e ++} ++ ++func (e *gfP2) Add(a, b *gfP2) *gfP2 { ++ e.x.Add(a.x, b.x) ++ e.y.Add(a.y, b.y) ++ return e ++} ++ ++func (e *gfP2) Sub(a, b *gfP2) *gfP2 { ++ e.x.Sub(a.x, b.x) ++ e.y.Sub(a.y, b.y) ++ return e ++} ++ ++func (e *gfP2) Double(a *gfP2) *gfP2 { ++ e.x.Lsh(a.x, 1) ++ e.y.Lsh(a.y, 1) ++ return e ++} ++ ++func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { ++ sum := newGFp2(pool) ++ sum.SetOne() ++ t := newGFp2(pool) ++ ++ for i := power.BitLen() - 1; i >= 0; i-- { ++ t.Square(sum, pool) ++ if power.Bit(i) != 0 { ++ sum.Mul(t, a, pool) ++ } else { ++ sum.Set(t) ++ } ++ } ++ ++ c.Set(sum) ++ ++ sum.Put(pool) ++ t.Put(pool) ++ ++ return c ++} ++ ++// See "Multiplication and Squaring in Pairing-Friendly Fields", ++// http://eprint.iacr.org/2006/471.pdf ++func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { ++ tx := pool.Get().Mul(a.x, b.y) ++ t := pool.Get().Mul(b.x, a.y) ++ tx.Add(tx, t) ++ tx.Mod(tx, p) ++ ++ ty := pool.Get().Mul(a.y, b.y) ++ t.Mul(a.x, b.x) ++ ty.Sub(ty, t) ++ e.y.Mod(ty, p) ++ e.x.Set(tx) ++ ++ pool.Put(tx) ++ pool.Put(ty) ++ pool.Put(t) ++ ++ return e ++} ++ ++func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { ++ e.x.Mul(a.x, b) ++ e.y.Mul(a.y, b) ++ return e ++} ++ ++// MulXi sets e=ΞΎa where ΞΎ=i+3 and then returns e. ++func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { ++ // (xi+y)(i+3) = (3x+y)i+(3y-x) ++ tx := pool.Get().Lsh(a.x, 1) ++ tx.Add(tx, a.x) ++ tx.Add(tx, a.y) ++ ++ ty := pool.Get().Lsh(a.y, 1) ++ ty.Add(ty, a.y) ++ ty.Sub(ty, a.x) ++ ++ e.x.Set(tx) ++ e.y.Set(ty) ++ ++ pool.Put(tx) ++ pool.Put(ty) ++ ++ return e ++} ++ ++func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { ++ // Complex squaring algorithm: ++ // (xi+b)Β² = (x+y)(y-x) + 2*i*x*y ++ t1 := pool.Get().Sub(a.y, a.x) ++ t2 := pool.Get().Add(a.x, a.y) ++ ty := pool.Get().Mul(t1, t2) ++ ty.Mod(ty, p) ++ ++ t1.Mul(a.x, a.y) ++ t1.Lsh(t1, 1) ++ ++ e.x.Mod(t1, p) ++ e.y.Set(ty) ++ ++ pool.Put(t1) ++ pool.Put(t2) ++ pool.Put(ty) ++ ++ return e ++} ++ ++func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { ++ // See "Implementing cryptographic pairings", M. Scott, section 3.2. ++ // ftp://136.206.11.249/pub/crypto/pairings.pdf ++ t := pool.Get() ++ t.Mul(a.y, a.y) ++ t2 := pool.Get() ++ t2.Mul(a.x, a.x) ++ t.Add(t, t2) ++ ++ inv := pool.Get() ++ inv.ModInverse(t, p) ++ ++ e.x.Neg(a.x) ++ e.x.Mul(e.x, inv) ++ e.x.Mod(e.x, p) ++ ++ e.y.Mul(a.y, inv) ++ e.y.Mod(e.y, p) ++ ++ pool.Put(t) ++ pool.Put(t2) ++ pool.Put(inv) ++ ++ return e ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/gfp6.go b/ms_mod/golang.org/x/crypto/bn256/gfp6.go +new file mode 100644 +index 00000000000000..f98ae782cc154a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/gfp6.go +@@ -0,0 +1,296 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++// For details of the algorithms used, see "Multiplication and Squaring on ++// Pairing-Friendly Fields, Devegili et al. ++// http://eprint.iacr.org/2006/471.pdf. ++ ++import ( ++ "math/big" ++) ++ ++// gfP6 implements the field of size p⁢ as a cubic extension of gfP2 where τ³=ΞΎ ++// and ΞΎ=i+3. ++type gfP6 struct { ++ x, y, z *gfP2 // value is xτ² + yΟ„ + z ++} ++ ++func newGFp6(pool *bnPool) *gfP6 { ++ return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} ++} ++ ++func (e *gfP6) String() string { ++ return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" ++} ++ ++func (e *gfP6) Put(pool *bnPool) { ++ e.x.Put(pool) ++ e.y.Put(pool) ++ e.z.Put(pool) ++} ++ ++func (e *gfP6) Set(a *gfP6) *gfP6 { ++ e.x.Set(a.x) ++ e.y.Set(a.y) ++ e.z.Set(a.z) ++ return e ++} ++ ++func (e *gfP6) SetZero() *gfP6 { ++ e.x.SetZero() ++ e.y.SetZero() ++ e.z.SetZero() ++ return e ++} ++ ++func (e *gfP6) SetOne() *gfP6 { ++ e.x.SetZero() ++ e.y.SetZero() ++ e.z.SetOne() ++ return e ++} ++ ++func (e *gfP6) Minimal() { ++ e.x.Minimal() ++ e.y.Minimal() ++ e.z.Minimal() ++} ++ ++func (e *gfP6) IsZero() bool { ++ return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() ++} ++ ++func (e *gfP6) IsOne() bool { ++ return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() ++} ++ ++func (e *gfP6) Negative(a *gfP6) *gfP6 { ++ e.x.Negative(a.x) ++ e.y.Negative(a.y) ++ e.z.Negative(a.z) ++ return e ++} ++ ++func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { ++ e.x.Conjugate(a.x) ++ e.y.Conjugate(a.y) ++ e.z.Conjugate(a.z) ++ ++ e.x.Mul(e.x, xiTo2PMinus2Over3, pool) ++ e.y.Mul(e.y, xiToPMinus1Over3, pool) ++ return e ++} ++ ++// FrobeniusP2 computes (xτ²+yΟ„+z)^(pΒ²) = xΟ„^(2pΒ²) + yΟ„^(pΒ²) + z ++func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { ++ // Ο„^(2pΒ²) = τ²τ^(2pΒ²-2) = τ²ξ^((2pΒ²-2)/3) ++ e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) ++ // Ο„^(pΒ²) = ττ^(pΒ²-1) = τξ^((pΒ²-1)/3) ++ e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) ++ e.z.Set(a.z) ++ return e ++} ++ ++func (e *gfP6) Add(a, b *gfP6) *gfP6 { ++ e.x.Add(a.x, b.x) ++ e.y.Add(a.y, b.y) ++ e.z.Add(a.z, b.z) ++ return e ++} ++ ++func (e *gfP6) Sub(a, b *gfP6) *gfP6 { ++ e.x.Sub(a.x, b.x) ++ e.y.Sub(a.y, b.y) ++ e.z.Sub(a.z, b.z) ++ return e ++} ++ ++func (e *gfP6) Double(a *gfP6) *gfP6 { ++ e.x.Double(a.x) ++ e.y.Double(a.y) ++ e.z.Double(a.z) ++ return e ++} ++ ++func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { ++ // "Multiplication and Squaring on Pairing-Friendly Fields" ++ // Section 4, Karatsuba method. ++ // http://eprint.iacr.org/2006/471.pdf ++ ++ v0 := newGFp2(pool) ++ v0.Mul(a.z, b.z, pool) ++ v1 := newGFp2(pool) ++ v1.Mul(a.y, b.y, pool) ++ v2 := newGFp2(pool) ++ v2.Mul(a.x, b.x, pool) ++ ++ t0 := newGFp2(pool) ++ t0.Add(a.x, a.y) ++ t1 := newGFp2(pool) ++ t1.Add(b.x, b.y) ++ tz := newGFp2(pool) ++ tz.Mul(t0, t1, pool) ++ ++ tz.Sub(tz, v1) ++ tz.Sub(tz, v2) ++ tz.MulXi(tz, pool) ++ tz.Add(tz, v0) ++ ++ t0.Add(a.y, a.z) ++ t1.Add(b.y, b.z) ++ ty := newGFp2(pool) ++ ty.Mul(t0, t1, pool) ++ ty.Sub(ty, v0) ++ ty.Sub(ty, v1) ++ t0.MulXi(v2, pool) ++ ty.Add(ty, t0) ++ ++ t0.Add(a.x, a.z) ++ t1.Add(b.x, b.z) ++ tx := newGFp2(pool) ++ tx.Mul(t0, t1, pool) ++ tx.Sub(tx, v0) ++ tx.Add(tx, v1) ++ tx.Sub(tx, v2) ++ ++ e.x.Set(tx) ++ e.y.Set(ty) ++ e.z.Set(tz) ++ ++ t0.Put(pool) ++ t1.Put(pool) ++ tx.Put(pool) ++ ty.Put(pool) ++ tz.Put(pool) ++ v0.Put(pool) ++ v1.Put(pool) ++ v2.Put(pool) ++ return e ++} ++ ++func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { ++ e.x.Mul(a.x, b, pool) ++ e.y.Mul(a.y, b, pool) ++ e.z.Mul(a.z, b, pool) ++ return e ++} ++ ++func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { ++ e.x.MulScalar(a.x, b) ++ e.y.MulScalar(a.y, b) ++ e.z.MulScalar(a.z, b) ++ return e ++} ++ ++// MulTau computes τ·(aτ²+bΟ„+c) = bτ²+cΟ„+aΞΎ ++func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { ++ tz := newGFp2(pool) ++ tz.MulXi(a.x, pool) ++ ty := newGFp2(pool) ++ ty.Set(a.y) ++ e.y.Set(a.z) ++ e.x.Set(ty) ++ e.z.Set(tz) ++ tz.Put(pool) ++ ty.Put(pool) ++} ++ ++func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { ++ v0 := newGFp2(pool).Square(a.z, pool) ++ v1 := newGFp2(pool).Square(a.y, pool) ++ v2 := newGFp2(pool).Square(a.x, pool) ++ ++ c0 := newGFp2(pool).Add(a.x, a.y) ++ c0.Square(c0, pool) ++ c0.Sub(c0, v1) ++ c0.Sub(c0, v2) ++ c0.MulXi(c0, pool) ++ c0.Add(c0, v0) ++ ++ c1 := newGFp2(pool).Add(a.y, a.z) ++ c1.Square(c1, pool) ++ c1.Sub(c1, v0) ++ c1.Sub(c1, v1) ++ xiV2 := newGFp2(pool).MulXi(v2, pool) ++ c1.Add(c1, xiV2) ++ ++ c2 := newGFp2(pool).Add(a.x, a.z) ++ c2.Square(c2, pool) ++ c2.Sub(c2, v0) ++ c2.Add(c2, v1) ++ c2.Sub(c2, v2) ++ ++ e.x.Set(c2) ++ e.y.Set(c1) ++ e.z.Set(c0) ++ ++ v0.Put(pool) ++ v1.Put(pool) ++ v2.Put(pool) ++ c0.Put(pool) ++ c1.Put(pool) ++ c2.Put(pool) ++ xiV2.Put(pool) ++ ++ return e ++} ++ ++func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { ++ // See "Implementing cryptographic pairings", M. Scott, section 3.2. ++ // ftp://136.206.11.249/pub/crypto/pairings.pdf ++ ++ // Here we can give a short explanation of how it works: let j be a cubic root of ++ // unity in GF(pΒ²) so that 1+j+jΒ²=0. ++ // Then (xτ² + yΟ„ + z)(xj²τ² + yjΟ„ + z)(xjτ² + yjΒ²Ο„ + z) ++ // = (xτ² + yΟ„ + z)(Cτ²+BΟ„+A) ++ // = (xΒ³ΞΎΒ²+yΒ³ΞΎ+zΒ³-3ΞΎxyz) = F is an element of the base field (the norm). ++ // ++ // On the other hand (xj²τ² + yjΟ„ + z)(xjτ² + yjΒ²Ο„ + z) ++ // = τ²(yΒ²-ΞΎxz) + Ο„(ΞΎxΒ²-yz) + (zΒ²-ΞΎxy) ++ // ++ // So that's why A = (zΒ²-ΞΎxy), B = (ΞΎxΒ²-yz), C = (yΒ²-ΞΎxz) ++ t1 := newGFp2(pool) ++ ++ A := newGFp2(pool) ++ A.Square(a.z, pool) ++ t1.Mul(a.x, a.y, pool) ++ t1.MulXi(t1, pool) ++ A.Sub(A, t1) ++ ++ B := newGFp2(pool) ++ B.Square(a.x, pool) ++ B.MulXi(B, pool) ++ t1.Mul(a.y, a.z, pool) ++ B.Sub(B, t1) ++ ++ C := newGFp2(pool) ++ C.Square(a.y, pool) ++ t1.Mul(a.x, a.z, pool) ++ C.Sub(C, t1) ++ ++ F := newGFp2(pool) ++ F.Mul(C, a.y, pool) ++ F.MulXi(F, pool) ++ t1.Mul(A, a.z, pool) ++ F.Add(F, t1) ++ t1.Mul(B, a.x, pool) ++ t1.MulXi(t1, pool) ++ F.Add(F, t1) ++ ++ F.Invert(F, pool) ++ ++ e.x.Mul(C, F, pool) ++ e.y.Mul(B, F, pool) ++ e.z.Mul(A, F, pool) ++ ++ t1.Put(pool) ++ A.Put(pool) ++ B.Put(pool) ++ C.Put(pool) ++ F.Put(pool) ++ ++ return e ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/optate.go b/ms_mod/golang.org/x/crypto/bn256/optate.go +new file mode 100644 +index 00000000000000..7ae0746eb10b89 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/optate.go +@@ -0,0 +1,395 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { ++ // See the mixed addition algorithm from "Faster Computation of the ++ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf ++ ++ B := newGFp2(pool).Mul(p.x, r.t, pool) ++ ++ D := newGFp2(pool).Add(p.y, r.z) ++ D.Square(D, pool) ++ D.Sub(D, r2) ++ D.Sub(D, r.t) ++ D.Mul(D, r.t, pool) ++ ++ H := newGFp2(pool).Sub(B, r.x) ++ I := newGFp2(pool).Square(H, pool) ++ ++ E := newGFp2(pool).Add(I, I) ++ E.Add(E, E) ++ ++ J := newGFp2(pool).Mul(H, E, pool) ++ ++ L1 := newGFp2(pool).Sub(D, r.y) ++ L1.Sub(L1, r.y) ++ ++ V := newGFp2(pool).Mul(r.x, E, pool) ++ ++ rOut = newTwistPoint(pool) ++ rOut.x.Square(L1, pool) ++ rOut.x.Sub(rOut.x, J) ++ rOut.x.Sub(rOut.x, V) ++ rOut.x.Sub(rOut.x, V) ++ ++ rOut.z.Add(r.z, H) ++ rOut.z.Square(rOut.z, pool) ++ rOut.z.Sub(rOut.z, r.t) ++ rOut.z.Sub(rOut.z, I) ++ ++ t := newGFp2(pool).Sub(V, rOut.x) ++ t.Mul(t, L1, pool) ++ t2 := newGFp2(pool).Mul(r.y, J, pool) ++ t2.Add(t2, t2) ++ rOut.y.Sub(t, t2) ++ ++ rOut.t.Square(rOut.z, pool) ++ ++ t.Add(p.y, rOut.z) ++ t.Square(t, pool) ++ t.Sub(t, r2) ++ t.Sub(t, rOut.t) ++ ++ t2.Mul(L1, p.x, pool) ++ t2.Add(t2, t2) ++ a = newGFp2(pool) ++ a.Sub(t2, t) ++ ++ c = newGFp2(pool) ++ c.MulScalar(rOut.z, q.y) ++ c.Add(c, c) ++ ++ b = newGFp2(pool) ++ b.SetZero() ++ b.Sub(b, L1) ++ b.MulScalar(b, q.x) ++ b.Add(b, b) ++ ++ B.Put(pool) ++ D.Put(pool) ++ H.Put(pool) ++ I.Put(pool) ++ E.Put(pool) ++ J.Put(pool) ++ L1.Put(pool) ++ V.Put(pool) ++ t.Put(pool) ++ t2.Put(pool) ++ ++ return ++} ++ ++func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { ++ // See the doubling algorithm for a=0 from "Faster Computation of the ++ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf ++ ++ A := newGFp2(pool).Square(r.x, pool) ++ B := newGFp2(pool).Square(r.y, pool) ++ C := newGFp2(pool).Square(B, pool) ++ ++ D := newGFp2(pool).Add(r.x, B) ++ D.Square(D, pool) ++ D.Sub(D, A) ++ D.Sub(D, C) ++ D.Add(D, D) ++ ++ E := newGFp2(pool).Add(A, A) ++ E.Add(E, A) ++ ++ G := newGFp2(pool).Square(E, pool) ++ ++ rOut = newTwistPoint(pool) ++ rOut.x.Sub(G, D) ++ rOut.x.Sub(rOut.x, D) ++ ++ rOut.z.Add(r.y, r.z) ++ rOut.z.Square(rOut.z, pool) ++ rOut.z.Sub(rOut.z, B) ++ rOut.z.Sub(rOut.z, r.t) ++ ++ rOut.y.Sub(D, rOut.x) ++ rOut.y.Mul(rOut.y, E, pool) ++ t := newGFp2(pool).Add(C, C) ++ t.Add(t, t) ++ t.Add(t, t) ++ rOut.y.Sub(rOut.y, t) ++ ++ rOut.t.Square(rOut.z, pool) ++ ++ t.Mul(E, r.t, pool) ++ t.Add(t, t) ++ b = newGFp2(pool) ++ b.SetZero() ++ b.Sub(b, t) ++ b.MulScalar(b, q.x) ++ ++ a = newGFp2(pool) ++ a.Add(r.x, E) ++ a.Square(a, pool) ++ a.Sub(a, A) ++ a.Sub(a, G) ++ t.Add(B, B) ++ t.Add(t, t) ++ a.Sub(a, t) ++ ++ c = newGFp2(pool) ++ c.Mul(rOut.z, r.t, pool) ++ c.Add(c, c) ++ c.MulScalar(c, q.y) ++ ++ A.Put(pool) ++ B.Put(pool) ++ C.Put(pool) ++ D.Put(pool) ++ E.Put(pool) ++ G.Put(pool) ++ t.Put(pool) ++ ++ return ++} ++ ++func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { ++ a2 := newGFp6(pool) ++ a2.x.SetZero() ++ a2.y.Set(a) ++ a2.z.Set(b) ++ a2.Mul(a2, ret.x, pool) ++ t3 := newGFp6(pool).MulScalar(ret.y, c, pool) ++ ++ t := newGFp2(pool) ++ t.Add(b, c) ++ t2 := newGFp6(pool) ++ t2.x.SetZero() ++ t2.y.Set(a) ++ t2.z.Set(t) ++ ret.x.Add(ret.x, ret.y) ++ ++ ret.y.Set(t3) ++ ++ ret.x.Mul(ret.x, t2, pool) ++ ret.x.Sub(ret.x, a2) ++ ret.x.Sub(ret.x, ret.y) ++ a2.MulTau(a2, pool) ++ ret.y.Add(ret.y, a2) ++ ++ a2.Put(pool) ++ t3.Put(pool) ++ t2.Put(pool) ++ t.Put(pool) ++} ++ ++// sixuPlus2NAF is 6u+2 in non-adjacent form. ++var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1} ++ ++// miller implements the Miller loop for calculating the Optimal Ate pairing. ++// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf ++func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { ++ ret := newGFp12(pool) ++ ret.SetOne() ++ ++ aAffine := newTwistPoint(pool) ++ aAffine.Set(q) ++ aAffine.MakeAffine(pool) ++ ++ bAffine := newCurvePoint(pool) ++ bAffine.Set(p) ++ bAffine.MakeAffine(pool) ++ ++ minusA := newTwistPoint(pool) ++ minusA.Negative(aAffine, pool) ++ ++ r := newTwistPoint(pool) ++ r.Set(aAffine) ++ ++ r2 := newGFp2(pool) ++ r2.Square(aAffine.y, pool) ++ ++ for i := len(sixuPlus2NAF) - 1; i > 0; i-- { ++ a, b, c, newR := lineFunctionDouble(r, bAffine, pool) ++ if i != len(sixuPlus2NAF)-1 { ++ ret.Square(ret, pool) ++ } ++ ++ mulLine(ret, a, b, c, pool) ++ a.Put(pool) ++ b.Put(pool) ++ c.Put(pool) ++ r.Put(pool) ++ r = newR ++ ++ switch sixuPlus2NAF[i-1] { ++ case 1: ++ a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) ++ case -1: ++ a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) ++ default: ++ continue ++ } ++ ++ mulLine(ret, a, b, c, pool) ++ a.Put(pool) ++ b.Put(pool) ++ c.Put(pool) ++ r.Put(pool) ++ r = newR ++ } ++ ++ // In order to calculate Q1 we have to convert q from the sextic twist ++ // to the full GF(p^12) group, apply the Frobenius there, and convert ++ // back. ++ // ++ // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just ++ // x for a moment, then after applying the Frobenius, we have xΜ„Ο‰^(2p) ++ // where xΜ„ is the conjugate of x. If we are going to apply the inverse ++ // isomorphism we need a value with a single coefficient of ω² so we ++ // rewrite this as xΜ„Ο‰^(2p-2)ω². ξ⁢ = Ο‰ and, due to the construction of ++ // p, 2p-2 is a multiple of six. Therefore we can rewrite as ++ // xΜ„ΞΎ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the ++ // ω². ++ // ++ // A similar argument can be made for the y value. ++ ++ q1 := newTwistPoint(pool) ++ q1.x.Conjugate(aAffine.x) ++ q1.x.Mul(q1.x, xiToPMinus1Over3, pool) ++ q1.y.Conjugate(aAffine.y) ++ q1.y.Mul(q1.y, xiToPMinus1Over2, pool) ++ q1.z.SetOne() ++ q1.t.SetOne() ++ ++ // For Q2 we are applying the pΒ² Frobenius. The two conjugations cancel ++ // out and we are left only with the factors from the isomorphism. In ++ // the case of x, we end up with a pure number which is why ++ // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We ++ // ignore this to end up with -Q2. ++ ++ minusQ2 := newTwistPoint(pool) ++ minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) ++ minusQ2.y.Set(aAffine.y) ++ minusQ2.z.SetOne() ++ minusQ2.t.SetOne() ++ ++ r2.Square(q1.y, pool) ++ a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) ++ mulLine(ret, a, b, c, pool) ++ a.Put(pool) ++ b.Put(pool) ++ c.Put(pool) ++ r.Put(pool) ++ r = newR ++ ++ r2.Square(minusQ2.y, pool) ++ a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) ++ mulLine(ret, a, b, c, pool) ++ a.Put(pool) ++ b.Put(pool) ++ c.Put(pool) ++ r.Put(pool) ++ r = newR ++ ++ aAffine.Put(pool) ++ bAffine.Put(pool) ++ minusA.Put(pool) ++ r.Put(pool) ++ r2.Put(pool) ++ ++ return ret ++} ++ ++// finalExponentiation computes the (pΒΉΒ²-1)/Order-th power of an element of ++// GF(pΒΉΒ²) to obtain an element of GT (steps 13-15 of algorithm 1 from ++// http://cryptojedi.org/papers/dclxvi-20100714.pdf) ++func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { ++ t1 := newGFp12(pool) ++ ++ // This is the p^6-Frobenius ++ t1.x.Negative(in.x) ++ t1.y.Set(in.y) ++ ++ inv := newGFp12(pool) ++ inv.Invert(in, pool) ++ t1.Mul(t1, inv, pool) ++ ++ t2 := newGFp12(pool).FrobeniusP2(t1, pool) ++ t1.Mul(t1, t2, pool) ++ ++ fp := newGFp12(pool).Frobenius(t1, pool) ++ fp2 := newGFp12(pool).FrobeniusP2(t1, pool) ++ fp3 := newGFp12(pool).Frobenius(fp2, pool) ++ ++ fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) ++ fu.Exp(t1, u, pool) ++ fu2.Exp(fu, u, pool) ++ fu3.Exp(fu2, u, pool) ++ ++ y3 := newGFp12(pool).Frobenius(fu, pool) ++ fu2p := newGFp12(pool).Frobenius(fu2, pool) ++ fu3p := newGFp12(pool).Frobenius(fu3, pool) ++ y2 := newGFp12(pool).FrobeniusP2(fu2, pool) ++ ++ y0 := newGFp12(pool) ++ y0.Mul(fp, fp2, pool) ++ y0.Mul(y0, fp3, pool) ++ ++ y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) ++ y1.Conjugate(t1) ++ y5.Conjugate(fu2) ++ y3.Conjugate(y3) ++ y4.Mul(fu, fu2p, pool) ++ y4.Conjugate(y4) ++ ++ y6 := newGFp12(pool) ++ y6.Mul(fu3, fu3p, pool) ++ y6.Conjugate(y6) ++ ++ t0 := newGFp12(pool) ++ t0.Square(y6, pool) ++ t0.Mul(t0, y4, pool) ++ t0.Mul(t0, y5, pool) ++ t1.Mul(y3, y5, pool) ++ t1.Mul(t1, t0, pool) ++ t0.Mul(t0, y2, pool) ++ t1.Square(t1, pool) ++ t1.Mul(t1, t0, pool) ++ t1.Square(t1, pool) ++ t0.Mul(t1, y1, pool) ++ t1.Mul(t1, y0, pool) ++ t0.Square(t0, pool) ++ t0.Mul(t0, t1, pool) ++ ++ inv.Put(pool) ++ t1.Put(pool) ++ t2.Put(pool) ++ fp.Put(pool) ++ fp2.Put(pool) ++ fp3.Put(pool) ++ fu.Put(pool) ++ fu2.Put(pool) ++ fu3.Put(pool) ++ fu2p.Put(pool) ++ fu3p.Put(pool) ++ y0.Put(pool) ++ y1.Put(pool) ++ y2.Put(pool) ++ y3.Put(pool) ++ y4.Put(pool) ++ y5.Put(pool) ++ y6.Put(pool) ++ ++ return t0 ++} ++ ++func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { ++ e := miller(a, b, pool) ++ ret := finalExponentiation(e, pool) ++ e.Put(pool) ++ ++ if a.IsInfinity() || b.IsInfinity() { ++ ret.SetOne() ++ } ++ ++ return ret ++} +diff --git a/ms_mod/golang.org/x/crypto/bn256/twist.go b/ms_mod/golang.org/x/crypto/bn256/twist.go +new file mode 100644 +index 00000000000000..056d80f18f0881 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/bn256/twist.go +@@ -0,0 +1,258 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bn256 ++ ++import ( ++ "math/big" ++) ++ ++// twistPoint implements the elliptic curve yΒ²=xΒ³+3/ΞΎ over GF(pΒ²). Points are ++// kept in Jacobian form and t=zΒ² when valid. The group Gβ‚‚ is the set of ++// n-torsion points of this curve over GF(pΒ²) (where n = Order) ++type twistPoint struct { ++ x, y, z, t *gfP2 ++} ++ ++var twistB = &gfP2{ ++ bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"), ++ bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"), ++} ++ ++// twistGen is the generator of group Gβ‚‚. ++var twistGen = &twistPoint{ ++ &gfP2{ ++ bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"), ++ bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"), ++ }, ++ &gfP2{ ++ bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"), ++ bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"), ++ }, ++ &gfP2{ ++ bigFromBase10("0"), ++ bigFromBase10("1"), ++ }, ++ &gfP2{ ++ bigFromBase10("0"), ++ bigFromBase10("1"), ++ }, ++} ++ ++func newTwistPoint(pool *bnPool) *twistPoint { ++ return &twistPoint{ ++ newGFp2(pool), ++ newGFp2(pool), ++ newGFp2(pool), ++ newGFp2(pool), ++ } ++} ++ ++func (c *twistPoint) String() string { ++ return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" ++} ++ ++func (c *twistPoint) Put(pool *bnPool) { ++ c.x.Put(pool) ++ c.y.Put(pool) ++ c.z.Put(pool) ++ c.t.Put(pool) ++} ++ ++func (c *twistPoint) Set(a *twistPoint) { ++ c.x.Set(a.x) ++ c.y.Set(a.y) ++ c.z.Set(a.z) ++ c.t.Set(a.t) ++} ++ ++// IsOnCurve returns true iff c is on the curve where c must be in affine form. ++func (c *twistPoint) IsOnCurve() bool { ++ pool := new(bnPool) ++ yy := newGFp2(pool).Square(c.y, pool) ++ xxx := newGFp2(pool).Square(c.x, pool) ++ xxx.Mul(xxx, c.x, pool) ++ yy.Sub(yy, xxx) ++ yy.Sub(yy, twistB) ++ yy.Minimal() ++ return yy.x.Sign() == 0 && yy.y.Sign() == 0 ++} ++ ++func (c *twistPoint) SetInfinity() { ++ c.z.SetZero() ++} ++ ++func (c *twistPoint) IsInfinity() bool { ++ return c.z.IsZero() ++} ++ ++func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { ++ // For additional comments, see the same function in curve.go. ++ ++ if a.IsInfinity() { ++ c.Set(b) ++ return ++ } ++ if b.IsInfinity() { ++ c.Set(a) ++ return ++ } ++ ++ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 ++ z1z1 := newGFp2(pool).Square(a.z, pool) ++ z2z2 := newGFp2(pool).Square(b.z, pool) ++ u1 := newGFp2(pool).Mul(a.x, z2z2, pool) ++ u2 := newGFp2(pool).Mul(b.x, z1z1, pool) ++ ++ t := newGFp2(pool).Mul(b.z, z2z2, pool) ++ s1 := newGFp2(pool).Mul(a.y, t, pool) ++ ++ t.Mul(a.z, z1z1, pool) ++ s2 := newGFp2(pool).Mul(b.y, t, pool) ++ ++ h := newGFp2(pool).Sub(u2, u1) ++ xEqual := h.IsZero() ++ ++ t.Add(h, h) ++ i := newGFp2(pool).Square(t, pool) ++ j := newGFp2(pool).Mul(h, i, pool) ++ ++ t.Sub(s2, s1) ++ yEqual := t.IsZero() ++ if xEqual && yEqual { ++ c.Double(a, pool) ++ return ++ } ++ r := newGFp2(pool).Add(t, t) ++ ++ v := newGFp2(pool).Mul(u1, i, pool) ++ ++ t4 := newGFp2(pool).Square(r, pool) ++ t.Add(v, v) ++ t6 := newGFp2(pool).Sub(t4, j) ++ c.x.Sub(t6, t) ++ ++ t.Sub(v, c.x) // t7 ++ t4.Mul(s1, j, pool) // t8 ++ t6.Add(t4, t4) // t9 ++ t4.Mul(r, t, pool) // t10 ++ c.y.Sub(t4, t6) ++ ++ t.Add(a.z, b.z) // t11 ++ t4.Square(t, pool) // t12 ++ t.Sub(t4, z1z1) // t13 ++ t4.Sub(t, z2z2) // t14 ++ c.z.Mul(t4, h, pool) ++ ++ z1z1.Put(pool) ++ z2z2.Put(pool) ++ u1.Put(pool) ++ u2.Put(pool) ++ t.Put(pool) ++ s1.Put(pool) ++ s2.Put(pool) ++ h.Put(pool) ++ i.Put(pool) ++ j.Put(pool) ++ r.Put(pool) ++ v.Put(pool) ++ t4.Put(pool) ++ t6.Put(pool) ++} ++ ++func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { ++ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 ++ A := newGFp2(pool).Square(a.x, pool) ++ B := newGFp2(pool).Square(a.y, pool) ++ C := newGFp2(pool).Square(B, pool) ++ ++ t := newGFp2(pool).Add(a.x, B) ++ t2 := newGFp2(pool).Square(t, pool) ++ t.Sub(t2, A) ++ t2.Sub(t, C) ++ d := newGFp2(pool).Add(t2, t2) ++ t.Add(A, A) ++ e := newGFp2(pool).Add(t, A) ++ f := newGFp2(pool).Square(e, pool) ++ ++ t.Add(d, d) ++ c.x.Sub(f, t) ++ ++ t.Add(C, C) ++ t2.Add(t, t) ++ t.Add(t2, t2) ++ c.y.Sub(d, c.x) ++ t2.Mul(e, c.y, pool) ++ c.y.Sub(t2, t) ++ ++ t.Mul(a.y, a.z, pool) ++ c.z.Add(t, t) ++ ++ A.Put(pool) ++ B.Put(pool) ++ C.Put(pool) ++ t.Put(pool) ++ t2.Put(pool) ++ d.Put(pool) ++ e.Put(pool) ++ f.Put(pool) ++} ++ ++func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { ++ sum := newTwistPoint(pool) ++ sum.SetInfinity() ++ t := newTwistPoint(pool) ++ ++ for i := scalar.BitLen(); i >= 0; i-- { ++ t.Double(sum, pool) ++ if scalar.Bit(i) != 0 { ++ sum.Add(t, a, pool) ++ } else { ++ sum.Set(t) ++ } ++ } ++ ++ c.Set(sum) ++ sum.Put(pool) ++ t.Put(pool) ++ return c ++} ++ ++// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets ++// c to 0 : 1 : 0. ++func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { ++ if c.z.IsOne() { ++ return c ++ } ++ if c.IsInfinity() { ++ c.x.SetZero() ++ c.y.SetOne() ++ c.z.SetZero() ++ c.t.SetZero() ++ return c ++ } ++ ++ zInv := newGFp2(pool).Invert(c.z, pool) ++ t := newGFp2(pool).Mul(c.y, zInv, pool) ++ zInv2 := newGFp2(pool).Square(zInv, pool) ++ c.y.Mul(t, zInv2, pool) ++ t.Mul(c.x, zInv2, pool) ++ c.x.Set(t) ++ c.z.SetOne() ++ c.t.SetOne() ++ ++ zInv.Put(pool) ++ t.Put(pool) ++ zInv2.Put(pool) ++ ++ return c ++} ++ ++func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { ++ c.x.Set(a.x) ++ c.y.SetZero() ++ c.y.Sub(c.y, a.y) ++ c.z.Set(a.z) ++ c.t.SetZero() ++} +diff --git a/ms_mod/golang.org/x/crypto/cast5/cast5.go b/ms_mod/golang.org/x/crypto/cast5/cast5.go +new file mode 100644 +index 00000000000000..425e8eecb06beb +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cast5/cast5.go +@@ -0,0 +1,536 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package cast5 implements CAST5, as defined in RFC 2144. ++// ++// CAST5 is a legacy cipher and its short block size makes it vulnerable to ++// birthday bound attacks (see https://sweet32.info). It should only be used ++// where compatibility with legacy systems, not security, is the goal. ++// ++// Deprecated: any new system should use AES (from crypto/aes, if necessary in ++// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from ++// golang.org/x/crypto/chacha20poly1305). ++package cast5 // import "golang.org/x/crypto/cast5" ++ ++import ( ++ "errors" ++ "math/bits" ++) ++ ++const BlockSize = 8 ++const KeySize = 16 ++ ++type Cipher struct { ++ masking [16]uint32 ++ rotate [16]uint8 ++} ++ ++func NewCipher(key []byte) (c *Cipher, err error) { ++ if len(key) != KeySize { ++ return nil, errors.New("CAST5: keys must be 16 bytes") ++ } ++ ++ c = new(Cipher) ++ c.keySchedule(key) ++ return ++} ++ ++func (c *Cipher) BlockSize() int { ++ return BlockSize ++} ++ ++func (c *Cipher) Encrypt(dst, src []byte) { ++ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) ++ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) ++ ++ l, r = r, l^f1(r, c.masking[0], c.rotate[0]) ++ l, r = r, l^f2(r, c.masking[1], c.rotate[1]) ++ l, r = r, l^f3(r, c.masking[2], c.rotate[2]) ++ l, r = r, l^f1(r, c.masking[3], c.rotate[3]) ++ ++ l, r = r, l^f2(r, c.masking[4], c.rotate[4]) ++ l, r = r, l^f3(r, c.masking[5], c.rotate[5]) ++ l, r = r, l^f1(r, c.masking[6], c.rotate[6]) ++ l, r = r, l^f2(r, c.masking[7], c.rotate[7]) ++ ++ l, r = r, l^f3(r, c.masking[8], c.rotate[8]) ++ l, r = r, l^f1(r, c.masking[9], c.rotate[9]) ++ l, r = r, l^f2(r, c.masking[10], c.rotate[10]) ++ l, r = r, l^f3(r, c.masking[11], c.rotate[11]) ++ ++ l, r = r, l^f1(r, c.masking[12], c.rotate[12]) ++ l, r = r, l^f2(r, c.masking[13], c.rotate[13]) ++ l, r = r, l^f3(r, c.masking[14], c.rotate[14]) ++ l, r = r, l^f1(r, c.masking[15], c.rotate[15]) ++ ++ dst[0] = uint8(r >> 24) ++ dst[1] = uint8(r >> 16) ++ dst[2] = uint8(r >> 8) ++ dst[3] = uint8(r) ++ dst[4] = uint8(l >> 24) ++ dst[5] = uint8(l >> 16) ++ dst[6] = uint8(l >> 8) ++ dst[7] = uint8(l) ++} ++ ++func (c *Cipher) Decrypt(dst, src []byte) { ++ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) ++ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) ++ ++ l, r = r, l^f1(r, c.masking[15], c.rotate[15]) ++ l, r = r, l^f3(r, c.masking[14], c.rotate[14]) ++ l, r = r, l^f2(r, c.masking[13], c.rotate[13]) ++ l, r = r, l^f1(r, c.masking[12], c.rotate[12]) ++ ++ l, r = r, l^f3(r, c.masking[11], c.rotate[11]) ++ l, r = r, l^f2(r, c.masking[10], c.rotate[10]) ++ l, r = r, l^f1(r, c.masking[9], c.rotate[9]) ++ l, r = r, l^f3(r, c.masking[8], c.rotate[8]) ++ ++ l, r = r, l^f2(r, c.masking[7], c.rotate[7]) ++ l, r = r, l^f1(r, c.masking[6], c.rotate[6]) ++ l, r = r, l^f3(r, c.masking[5], c.rotate[5]) ++ l, r = r, l^f2(r, c.masking[4], c.rotate[4]) ++ ++ l, r = r, l^f1(r, c.masking[3], c.rotate[3]) ++ l, r = r, l^f3(r, c.masking[2], c.rotate[2]) ++ l, r = r, l^f2(r, c.masking[1], c.rotate[1]) ++ l, r = r, l^f1(r, c.masking[0], c.rotate[0]) ++ ++ dst[0] = uint8(r >> 24) ++ dst[1] = uint8(r >> 16) ++ dst[2] = uint8(r >> 8) ++ dst[3] = uint8(r) ++ dst[4] = uint8(l >> 24) ++ dst[5] = uint8(l >> 16) ++ dst[6] = uint8(l >> 8) ++ dst[7] = uint8(l) ++} ++ ++type keyScheduleA [4][7]uint8 ++type keyScheduleB [4][5]uint8 ++ ++// keyScheduleRound contains the magic values for a round of the key schedule. ++// The keyScheduleA deals with the lines like: ++// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] ++// Conceptually, both x and z are in the same array, x first. The first ++// element describes which word of this array gets written to and the ++// second, which word gets read. So, for the line above, it's "4, 0", because ++// it's writing to the first word of z, which, being after x, is word 4, and ++// reading from the first word of x: word 0. ++// ++// Next are the indexes into the S-boxes. Now the array is treated as bytes. So ++// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear ++// that it's z that we're indexing. ++// ++// keyScheduleB deals with lines like: ++// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] ++// "K1" is ignored because key words are always written in order. So the five ++// elements are the S-box indexes. They use the same form as in keyScheduleA, ++// above. ++ ++type keyScheduleRound struct{} ++type keySchedule []keyScheduleRound ++ ++var schedule = []struct { ++ a keyScheduleA ++ b keyScheduleB ++}{ ++ { ++ keyScheduleA{ ++ {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8}, ++ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, ++ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, ++ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, ++ }, ++ keyScheduleB{ ++ {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2}, ++ {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6}, ++ {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9}, ++ {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc}, ++ }, ++ }, ++ { ++ keyScheduleA{ ++ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, ++ {1, 4, 0, 2, 1, 3, 16 + 2}, ++ {2, 5, 7, 6, 5, 4, 16 + 1}, ++ {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, ++ }, ++ keyScheduleB{ ++ {3, 2, 0xc, 0xd, 8}, ++ {1, 0, 0xe, 0xf, 0xd}, ++ {7, 6, 8, 9, 3}, ++ {5, 4, 0xa, 0xb, 7}, ++ }, ++ }, ++ { ++ keyScheduleA{ ++ {4, 0, 0xd, 0xf, 0xc, 0xe, 8}, ++ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, ++ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, ++ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, ++ }, ++ keyScheduleB{ ++ {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9}, ++ {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc}, ++ {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2}, ++ {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6}, ++ }, ++ }, ++ { ++ keyScheduleA{ ++ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, ++ {1, 4, 0, 2, 1, 3, 16 + 2}, ++ {2, 5, 7, 6, 5, 4, 16 + 1}, ++ {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, ++ }, ++ keyScheduleB{ ++ {8, 9, 7, 6, 3}, ++ {0xa, 0xb, 5, 4, 7}, ++ {0xc, 0xd, 3, 2, 8}, ++ {0xe, 0xf, 1, 0, 0xd}, ++ }, ++ }, ++} ++ ++func (c *Cipher) keySchedule(in []byte) { ++ var t [8]uint32 ++ var k [32]uint32 ++ ++ for i := 0; i < 4; i++ { ++ j := i * 4 ++ t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3]) ++ } ++ ++ x := []byte{6, 7, 4, 5} ++ ki := 0 ++ ++ for half := 0; half < 2; half++ { ++ for _, round := range schedule { ++ for j := 0; j < 4; j++ { ++ var a [7]uint8 ++ copy(a[:], round.a[j][:]) ++ w := t[a[1]] ++ w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff] ++ w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff] ++ w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff] ++ w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff] ++ w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff] ++ t[a[0]] = w ++ } ++ ++ for j := 0; j < 4; j++ { ++ var b [5]uint8 ++ copy(b[:], round.b[j][:]) ++ w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff] ++ w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff] ++ w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff] ++ w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff] ++ w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff] ++ k[ki] = w ++ ki++ ++ } ++ } ++ } ++ ++ for i := 0; i < 16; i++ { ++ c.masking[i] = k[i] ++ c.rotate[i] = uint8(k[16+i] & 0x1f) ++ } ++} ++ ++// These are the three 'f' functions. See RFC 2144, section 2.2. ++func f1(d, m uint32, r uint8) uint32 { ++ t := m + d ++ I := bits.RotateLeft32(t, int(r)) ++ return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] ++} ++ ++func f2(d, m uint32, r uint8) uint32 { ++ t := m ^ d ++ I := bits.RotateLeft32(t, int(r)) ++ return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] ++} ++ ++func f3(d, m uint32, r uint8) uint32 { ++ t := m - d ++ I := bits.RotateLeft32(t, int(r)) ++ return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] ++} ++ ++var sBox = [8][256]uint32{ ++ { ++ 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, ++ 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, ++ 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, ++ 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, ++ 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, ++ 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, ++ 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, ++ 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, ++ 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, ++ 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, ++ 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, ++ 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, ++ 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, ++ 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, ++ 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, ++ 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, ++ 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, ++ 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, ++ 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, ++ 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, ++ 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, ++ 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, ++ 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, ++ 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, ++ 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, ++ 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, ++ 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, ++ 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, ++ 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, ++ 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, ++ 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, ++ 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, ++ }, ++ { ++ 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, ++ 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, ++ 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, ++ 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, ++ 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, ++ 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, ++ 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, ++ 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, ++ 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, ++ 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, ++ 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, ++ 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, ++ 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, ++ 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, ++ 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, ++ 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, ++ 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, ++ 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, ++ 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, ++ 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, ++ 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, ++ 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, ++ 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, ++ 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, ++ 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, ++ 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, ++ 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, ++ 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, ++ 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, ++ 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, ++ 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, ++ 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, ++ }, ++ { ++ 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, ++ 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, ++ 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, ++ 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, ++ 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, ++ 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, ++ 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, ++ 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, ++ 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, ++ 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, ++ 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, ++ 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, ++ 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, ++ 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, ++ 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, ++ 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, ++ 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, ++ 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, ++ 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, ++ 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, ++ 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, ++ 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, ++ 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, ++ 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, ++ 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, ++ 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, ++ 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, ++ 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, ++ 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, ++ 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, ++ 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, ++ 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, ++ }, ++ { ++ 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, ++ 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, ++ 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, ++ 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, ++ 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, ++ 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, ++ 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, ++ 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, ++ 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, ++ 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, ++ 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, ++ 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, ++ 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, ++ 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, ++ 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, ++ 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, ++ 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, ++ 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, ++ 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, ++ 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, ++ 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, ++ 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, ++ 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, ++ 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, ++ 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, ++ 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, ++ 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, ++ 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, ++ 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, ++ 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, ++ 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, ++ 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, ++ }, ++ { ++ 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, ++ 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, ++ 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, ++ 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, ++ 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, ++ 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, ++ 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, ++ 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, ++ 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, ++ 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, ++ 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, ++ 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, ++ 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, ++ 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, ++ 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, ++ 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, ++ 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, ++ 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, ++ 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, ++ 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, ++ 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, ++ 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, ++ 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, ++ 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, ++ 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, ++ 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, ++ 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, ++ 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, ++ 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, ++ 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, ++ 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, ++ 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, ++ }, ++ { ++ 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, ++ 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, ++ 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, ++ 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, ++ 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, ++ 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, ++ 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, ++ 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, ++ 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, ++ 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, ++ 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, ++ 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, ++ 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, ++ 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, ++ 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, ++ 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, ++ 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, ++ 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, ++ 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, ++ 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, ++ 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, ++ 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, ++ 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, ++ 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, ++ 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, ++ 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, ++ 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, ++ 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, ++ 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, ++ 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, ++ 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, ++ 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, ++ }, ++ { ++ 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, ++ 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, ++ 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, ++ 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, ++ 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, ++ 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, ++ 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, ++ 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, ++ 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, ++ 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, ++ 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, ++ 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, ++ 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, ++ 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, ++ 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, ++ 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, ++ 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, ++ 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, ++ 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, ++ 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, ++ 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, ++ 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, ++ 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, ++ 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, ++ 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, ++ 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, ++ 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, ++ 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, ++ 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, ++ 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, ++ 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, ++ 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, ++ }, ++ { ++ 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, ++ 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, ++ 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, ++ 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, ++ 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, ++ 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, ++ 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, ++ 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, ++ 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, ++ 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, ++ 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, ++ 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, ++ 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, ++ 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, ++ 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, ++ 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, ++ 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, ++ 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, ++ 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, ++ 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, ++ 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, ++ 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, ++ 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, ++ 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, ++ 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, ++ 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, ++ 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, ++ 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, ++ 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, ++ 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, ++ 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, ++ 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/cast5/cast5_test.go b/ms_mod/golang.org/x/crypto/cast5/cast5_test.go +new file mode 100644 +index 00000000000000..778b272a638885 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cast5/cast5_test.go +@@ -0,0 +1,106 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package cast5 ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++) ++ ++// This test vector is taken from RFC 2144, App B.1. ++// Since the other two test vectors are for reduced-round variants, we can't ++// use them. ++var basicTests = []struct { ++ key, plainText, cipherText string ++}{ ++ { ++ "0123456712345678234567893456789a", ++ "0123456789abcdef", ++ "238b4fe5847e44b2", ++ }, ++} ++ ++func TestBasic(t *testing.T) { ++ for i, test := range basicTests { ++ key, _ := hex.DecodeString(test.key) ++ plainText, _ := hex.DecodeString(test.plainText) ++ expected, _ := hex.DecodeString(test.cipherText) ++ ++ c, err := NewCipher(key) ++ if err != nil { ++ t.Errorf("#%d: failed to create Cipher: %s", i, err) ++ continue ++ } ++ var cipherText [BlockSize]byte ++ c.Encrypt(cipherText[:], plainText) ++ if !bytes.Equal(cipherText[:], expected) { ++ t.Errorf("#%d: got:%x want:%x", i, cipherText, expected) ++ } ++ ++ var plainTextAgain [BlockSize]byte ++ c.Decrypt(plainTextAgain[:], cipherText[:]) ++ if !bytes.Equal(plainTextAgain[:], plainText) { ++ t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText) ++ } ++ } ++} ++ ++// TestFull performs the test specified in RFC 2144, App B.2. ++// However, due to the length of time taken, it's disabled here and a more ++// limited version is included, below. ++func TestFull(t *testing.T) { ++ if testing.Short() { ++ // This is too slow for normal testing ++ return ++ } ++ ++ a, b := iterate(1000000) ++ ++ const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92" ++ const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e" ++ ++ if hex.EncodeToString(a) != expectedA { ++ t.Errorf("a: got:%x want:%s", a, expectedA) ++ } ++ if hex.EncodeToString(b) != expectedB { ++ t.Errorf("b: got:%x want:%s", b, expectedB) ++ } ++} ++ ++func iterate(iterations int) ([]byte, []byte) { ++ const initValueHex = "0123456712345678234567893456789a" ++ ++ initValue, _ := hex.DecodeString(initValueHex) ++ ++ var a, b [16]byte ++ copy(a[:], initValue) ++ copy(b[:], initValue) ++ ++ for i := 0; i < iterations; i++ { ++ c, _ := NewCipher(b[:]) ++ c.Encrypt(a[:8], a[:8]) ++ c.Encrypt(a[8:], a[8:]) ++ c, _ = NewCipher(a[:]) ++ c.Encrypt(b[:8], b[:8]) ++ c.Encrypt(b[8:], b[8:]) ++ } ++ ++ return a[:], b[:] ++} ++ ++func TestLimited(t *testing.T) { ++ a, b := iterate(1000) ++ ++ const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d" ++ const expectedB = "e5bf37eff14c456a40b21ce369370a9f" ++ ++ if hex.EncodeToString(a) != expectedA { ++ t.Errorf("a: got:%x want:%s", a, expectedA) ++ } ++ if hex.EncodeToString(b) != expectedB { ++ t.Errorf("b: got:%x want:%s", b, expectedB) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go +new file mode 100644 +index 00000000000000..94c71ac1ac863f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go +@@ -0,0 +1,17 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.11 && gc && !purego ++// +build go1.11,gc,!purego ++ ++package chacha20 ++ ++const bufSize = 256 ++ ++//go:noescape ++func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) ++ ++func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { ++ xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s +new file mode 100644 +index 00000000000000..63cae9e6f0b1ba +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s +@@ -0,0 +1,308 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.11 && gc && !purego ++// +build go1.11,gc,!purego ++ ++#include "textflag.h" ++ ++#define NUM_ROUNDS 10 ++ ++// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) ++TEXT Β·xorKeyStreamVX(SB), NOSPLIT, $0 ++ MOVD dst+0(FP), R1 ++ MOVD src+24(FP), R2 ++ MOVD src_len+32(FP), R3 ++ MOVD key+48(FP), R4 ++ MOVD nonce+56(FP), R6 ++ MOVD counter+64(FP), R7 ++ ++ MOVD $Β·constants(SB), R10 ++ MOVD $Β·incRotMatrix(SB), R11 ++ ++ MOVW (R7), R20 ++ ++ AND $~255, R3, R13 ++ ADD R2, R13, R12 // R12 for block end ++ AND $255, R3, R13 ++loop: ++ MOVD $NUM_ROUNDS, R21 ++ VLD1 (R11), [V30.S4, V31.S4] ++ ++ // load contants ++ // VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] ++ WORD $0x4D60E940 ++ ++ // load keys ++ // VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4] ++ WORD $0x4DFFE884 ++ // VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4] ++ WORD $0x4DFFE888 ++ SUB $32, R4 ++ ++ // load counter + nonce ++ // VLD1R (R7), [V12.S4] ++ WORD $0x4D40C8EC ++ ++ // VLD3R (R6), [V13.S4, V14.S4, V15.S4] ++ WORD $0x4D40E8CD ++ ++ // update counter ++ VADD V30.S4, V12.S4, V12.S4 ++ ++chacha: ++ // V0..V3 += V4..V7 ++ // V12..V15 <<<= ((V12..V15 XOR V0..V3), 16) ++ VADD V0.S4, V4.S4, V0.S4 ++ VADD V1.S4, V5.S4, V1.S4 ++ VADD V2.S4, V6.S4, V2.S4 ++ VADD V3.S4, V7.S4, V3.S4 ++ VEOR V12.B16, V0.B16, V12.B16 ++ VEOR V13.B16, V1.B16, V13.B16 ++ VEOR V14.B16, V2.B16, V14.B16 ++ VEOR V15.B16, V3.B16, V15.B16 ++ VREV32 V12.H8, V12.H8 ++ VREV32 V13.H8, V13.H8 ++ VREV32 V14.H8, V14.H8 ++ VREV32 V15.H8, V15.H8 ++ // V8..V11 += V12..V15 ++ // V4..V7 <<<= ((V4..V7 XOR V8..V11), 12) ++ VADD V8.S4, V12.S4, V8.S4 ++ VADD V9.S4, V13.S4, V9.S4 ++ VADD V10.S4, V14.S4, V10.S4 ++ VADD V11.S4, V15.S4, V11.S4 ++ VEOR V8.B16, V4.B16, V16.B16 ++ VEOR V9.B16, V5.B16, V17.B16 ++ VEOR V10.B16, V6.B16, V18.B16 ++ VEOR V11.B16, V7.B16, V19.B16 ++ VSHL $12, V16.S4, V4.S4 ++ VSHL $12, V17.S4, V5.S4 ++ VSHL $12, V18.S4, V6.S4 ++ VSHL $12, V19.S4, V7.S4 ++ VSRI $20, V16.S4, V4.S4 ++ VSRI $20, V17.S4, V5.S4 ++ VSRI $20, V18.S4, V6.S4 ++ VSRI $20, V19.S4, V7.S4 ++ ++ // V0..V3 += V4..V7 ++ // V12..V15 <<<= ((V12..V15 XOR V0..V3), 8) ++ VADD V0.S4, V4.S4, V0.S4 ++ VADD V1.S4, V5.S4, V1.S4 ++ VADD V2.S4, V6.S4, V2.S4 ++ VADD V3.S4, V7.S4, V3.S4 ++ VEOR V12.B16, V0.B16, V12.B16 ++ VEOR V13.B16, V1.B16, V13.B16 ++ VEOR V14.B16, V2.B16, V14.B16 ++ VEOR V15.B16, V3.B16, V15.B16 ++ VTBL V31.B16, [V12.B16], V12.B16 ++ VTBL V31.B16, [V13.B16], V13.B16 ++ VTBL V31.B16, [V14.B16], V14.B16 ++ VTBL V31.B16, [V15.B16], V15.B16 ++ ++ // V8..V11 += V12..V15 ++ // V4..V7 <<<= ((V4..V7 XOR V8..V11), 7) ++ VADD V12.S4, V8.S4, V8.S4 ++ VADD V13.S4, V9.S4, V9.S4 ++ VADD V14.S4, V10.S4, V10.S4 ++ VADD V15.S4, V11.S4, V11.S4 ++ VEOR V8.B16, V4.B16, V16.B16 ++ VEOR V9.B16, V5.B16, V17.B16 ++ VEOR V10.B16, V6.B16, V18.B16 ++ VEOR V11.B16, V7.B16, V19.B16 ++ VSHL $7, V16.S4, V4.S4 ++ VSHL $7, V17.S4, V5.S4 ++ VSHL $7, V18.S4, V6.S4 ++ VSHL $7, V19.S4, V7.S4 ++ VSRI $25, V16.S4, V4.S4 ++ VSRI $25, V17.S4, V5.S4 ++ VSRI $25, V18.S4, V6.S4 ++ VSRI $25, V19.S4, V7.S4 ++ ++ // V0..V3 += V5..V7, V4 ++ // V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16) ++ VADD V0.S4, V5.S4, V0.S4 ++ VADD V1.S4, V6.S4, V1.S4 ++ VADD V2.S4, V7.S4, V2.S4 ++ VADD V3.S4, V4.S4, V3.S4 ++ VEOR V15.B16, V0.B16, V15.B16 ++ VEOR V12.B16, V1.B16, V12.B16 ++ VEOR V13.B16, V2.B16, V13.B16 ++ VEOR V14.B16, V3.B16, V14.B16 ++ VREV32 V12.H8, V12.H8 ++ VREV32 V13.H8, V13.H8 ++ VREV32 V14.H8, V14.H8 ++ VREV32 V15.H8, V15.H8 ++ ++ // V10 += V15; V5 <<<= ((V10 XOR V5), 12) ++ // ... ++ VADD V15.S4, V10.S4, V10.S4 ++ VADD V12.S4, V11.S4, V11.S4 ++ VADD V13.S4, V8.S4, V8.S4 ++ VADD V14.S4, V9.S4, V9.S4 ++ VEOR V10.B16, V5.B16, V16.B16 ++ VEOR V11.B16, V6.B16, V17.B16 ++ VEOR V8.B16, V7.B16, V18.B16 ++ VEOR V9.B16, V4.B16, V19.B16 ++ VSHL $12, V16.S4, V5.S4 ++ VSHL $12, V17.S4, V6.S4 ++ VSHL $12, V18.S4, V7.S4 ++ VSHL $12, V19.S4, V4.S4 ++ VSRI $20, V16.S4, V5.S4 ++ VSRI $20, V17.S4, V6.S4 ++ VSRI $20, V18.S4, V7.S4 ++ VSRI $20, V19.S4, V4.S4 ++ ++ // V0 += V5; V15 <<<= ((V0 XOR V15), 8) ++ // ... ++ VADD V5.S4, V0.S4, V0.S4 ++ VADD V6.S4, V1.S4, V1.S4 ++ VADD V7.S4, V2.S4, V2.S4 ++ VADD V4.S4, V3.S4, V3.S4 ++ VEOR V0.B16, V15.B16, V15.B16 ++ VEOR V1.B16, V12.B16, V12.B16 ++ VEOR V2.B16, V13.B16, V13.B16 ++ VEOR V3.B16, V14.B16, V14.B16 ++ VTBL V31.B16, [V12.B16], V12.B16 ++ VTBL V31.B16, [V13.B16], V13.B16 ++ VTBL V31.B16, [V14.B16], V14.B16 ++ VTBL V31.B16, [V15.B16], V15.B16 ++ ++ // V10 += V15; V5 <<<= ((V10 XOR V5), 7) ++ // ... ++ VADD V15.S4, V10.S4, V10.S4 ++ VADD V12.S4, V11.S4, V11.S4 ++ VADD V13.S4, V8.S4, V8.S4 ++ VADD V14.S4, V9.S4, V9.S4 ++ VEOR V10.B16, V5.B16, V16.B16 ++ VEOR V11.B16, V6.B16, V17.B16 ++ VEOR V8.B16, V7.B16, V18.B16 ++ VEOR V9.B16, V4.B16, V19.B16 ++ VSHL $7, V16.S4, V5.S4 ++ VSHL $7, V17.S4, V6.S4 ++ VSHL $7, V18.S4, V7.S4 ++ VSHL $7, V19.S4, V4.S4 ++ VSRI $25, V16.S4, V5.S4 ++ VSRI $25, V17.S4, V6.S4 ++ VSRI $25, V18.S4, V7.S4 ++ VSRI $25, V19.S4, V4.S4 ++ ++ SUB $1, R21 ++ CBNZ R21, chacha ++ ++ // VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4] ++ WORD $0x4D60E950 ++ ++ // VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4] ++ WORD $0x4DFFE894 ++ VADD V30.S4, V12.S4, V12.S4 ++ VADD V16.S4, V0.S4, V0.S4 ++ VADD V17.S4, V1.S4, V1.S4 ++ VADD V18.S4, V2.S4, V2.S4 ++ VADD V19.S4, V3.S4, V3.S4 ++ // VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4] ++ WORD $0x4DFFE898 ++ // restore R4 ++ SUB $32, R4 ++ ++ // load counter + nonce ++ // VLD1R (R7), [V28.S4] ++ WORD $0x4D40C8FC ++ // VLD3R (R6), [V29.S4, V30.S4, V31.S4] ++ WORD $0x4D40E8DD ++ ++ VADD V20.S4, V4.S4, V4.S4 ++ VADD V21.S4, V5.S4, V5.S4 ++ VADD V22.S4, V6.S4, V6.S4 ++ VADD V23.S4, V7.S4, V7.S4 ++ VADD V24.S4, V8.S4, V8.S4 ++ VADD V25.S4, V9.S4, V9.S4 ++ VADD V26.S4, V10.S4, V10.S4 ++ VADD V27.S4, V11.S4, V11.S4 ++ VADD V28.S4, V12.S4, V12.S4 ++ VADD V29.S4, V13.S4, V13.S4 ++ VADD V30.S4, V14.S4, V14.S4 ++ VADD V31.S4, V15.S4, V15.S4 ++ ++ VZIP1 V1.S4, V0.S4, V16.S4 ++ VZIP2 V1.S4, V0.S4, V17.S4 ++ VZIP1 V3.S4, V2.S4, V18.S4 ++ VZIP2 V3.S4, V2.S4, V19.S4 ++ VZIP1 V5.S4, V4.S4, V20.S4 ++ VZIP2 V5.S4, V4.S4, V21.S4 ++ VZIP1 V7.S4, V6.S4, V22.S4 ++ VZIP2 V7.S4, V6.S4, V23.S4 ++ VZIP1 V9.S4, V8.S4, V24.S4 ++ VZIP2 V9.S4, V8.S4, V25.S4 ++ VZIP1 V11.S4, V10.S4, V26.S4 ++ VZIP2 V11.S4, V10.S4, V27.S4 ++ VZIP1 V13.S4, V12.S4, V28.S4 ++ VZIP2 V13.S4, V12.S4, V29.S4 ++ VZIP1 V15.S4, V14.S4, V30.S4 ++ VZIP2 V15.S4, V14.S4, V31.S4 ++ VZIP1 V18.D2, V16.D2, V0.D2 ++ VZIP2 V18.D2, V16.D2, V4.D2 ++ VZIP1 V19.D2, V17.D2, V8.D2 ++ VZIP2 V19.D2, V17.D2, V12.D2 ++ VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16] ++ ++ VZIP1 V22.D2, V20.D2, V1.D2 ++ VZIP2 V22.D2, V20.D2, V5.D2 ++ VZIP1 V23.D2, V21.D2, V9.D2 ++ VZIP2 V23.D2, V21.D2, V13.D2 ++ VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16] ++ VZIP1 V26.D2, V24.D2, V2.D2 ++ VZIP2 V26.D2, V24.D2, V6.D2 ++ VZIP1 V27.D2, V25.D2, V10.D2 ++ VZIP2 V27.D2, V25.D2, V14.D2 ++ VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16] ++ VZIP1 V30.D2, V28.D2, V3.D2 ++ VZIP2 V30.D2, V28.D2, V7.D2 ++ VZIP1 V31.D2, V29.D2, V11.D2 ++ VZIP2 V31.D2, V29.D2, V15.D2 ++ VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16] ++ VEOR V0.B16, V16.B16, V16.B16 ++ VEOR V1.B16, V17.B16, V17.B16 ++ VEOR V2.B16, V18.B16, V18.B16 ++ VEOR V3.B16, V19.B16, V19.B16 ++ VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1) ++ VEOR V4.B16, V20.B16, V20.B16 ++ VEOR V5.B16, V21.B16, V21.B16 ++ VEOR V6.B16, V22.B16, V22.B16 ++ VEOR V7.B16, V23.B16, V23.B16 ++ VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1) ++ VEOR V8.B16, V24.B16, V24.B16 ++ VEOR V9.B16, V25.B16, V25.B16 ++ VEOR V10.B16, V26.B16, V26.B16 ++ VEOR V11.B16, V27.B16, V27.B16 ++ VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1) ++ VEOR V12.B16, V28.B16, V28.B16 ++ VEOR V13.B16, V29.B16, V29.B16 ++ VEOR V14.B16, V30.B16, V30.B16 ++ VEOR V15.B16, V31.B16, V31.B16 ++ VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1) ++ ++ ADD $4, R20 ++ MOVW R20, (R7) // update counter ++ ++ CMP R2, R12 ++ BGT loop ++ ++ RET ++ ++ ++DATA Β·constants+0x00(SB)/4, $0x61707865 ++DATA Β·constants+0x04(SB)/4, $0x3320646e ++DATA Β·constants+0x08(SB)/4, $0x79622d32 ++DATA Β·constants+0x0c(SB)/4, $0x6b206574 ++GLOBL Β·constants(SB), NOPTR|RODATA, $32 ++ ++DATA Β·incRotMatrix+0x00(SB)/4, $0x00000000 ++DATA Β·incRotMatrix+0x04(SB)/4, $0x00000001 ++DATA Β·incRotMatrix+0x08(SB)/4, $0x00000002 ++DATA Β·incRotMatrix+0x0c(SB)/4, $0x00000003 ++DATA Β·incRotMatrix+0x10(SB)/4, $0x02010003 ++DATA Β·incRotMatrix+0x14(SB)/4, $0x06050407 ++DATA Β·incRotMatrix+0x18(SB)/4, $0x0A09080B ++DATA Β·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F ++GLOBL Β·incRotMatrix(SB), NOPTR|RODATA, $32 +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go +new file mode 100644 +index 00000000000000..93eb5ae6de6f33 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go +@@ -0,0 +1,398 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms ++// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01. ++package chacha20 ++ ++import ( ++ "crypto/cipher" ++ "encoding/binary" ++ "errors" ++ "math/bits" ++ ++ "golang.org/x/crypto/internal/alias" ++) ++ ++const ( ++ // KeySize is the size of the key used by this cipher, in bytes. ++ KeySize = 32 ++ ++ // NonceSize is the size of the nonce used with the standard variant of this ++ // cipher, in bytes. ++ // ++ // Note that this is too short to be safely generated at random if the same ++ // key is reused more than 2Β³Β² times. ++ NonceSize = 12 ++ ++ // NonceSizeX is the size of the nonce used with the XChaCha20 variant of ++ // this cipher, in bytes. ++ NonceSizeX = 24 ++) ++ ++// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key ++// and nonce. A *Cipher implements the cipher.Stream interface. ++type Cipher struct { ++ // The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter ++ // (incremented after each block), and 3 of nonce. ++ key [8]uint32 ++ counter uint32 ++ nonce [3]uint32 ++ ++ // The last len bytes of buf are leftover key stream bytes from the previous ++ // XORKeyStream invocation. The size of buf depends on how many blocks are ++ // computed at a time by xorKeyStreamBlocks. ++ buf [bufSize]byte ++ len int ++ ++ // overflow is set when the counter overflowed, no more blocks can be ++ // generated, and the next XORKeyStream call should panic. ++ overflow bool ++ ++ // The counter-independent results of the first round are cached after they ++ // are computed the first time. ++ precompDone bool ++ p1, p5, p9, p13 uint32 ++ p2, p6, p10, p14 uint32 ++ p3, p7, p11, p15 uint32 ++} ++ ++var _ cipher.Stream = (*Cipher)(nil) ++ ++// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given ++// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided, ++// the XChaCha20 construction will be used. It returns an error if key or nonce ++// have any other length. ++// ++// Note that ChaCha20, like all stream ciphers, is not authenticated and allows ++// attackers to silently tamper with the plaintext. For this reason, it is more ++// appropriate as a building block than as a standalone encryption mechanism. ++// Instead, consider using package golang.org/x/crypto/chacha20poly1305. ++func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) { ++ // This function is split into a wrapper so that the Cipher allocation will ++ // be inlined, and depending on how the caller uses the return value, won't ++ // escape to the heap. ++ c := &Cipher{} ++ return newUnauthenticatedCipher(c, key, nonce) ++} ++ ++func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) { ++ if len(key) != KeySize { ++ return nil, errors.New("chacha20: wrong key size") ++ } ++ if len(nonce) == NonceSizeX { ++ // XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a ++ // derived key, allowing it to operate on a nonce of 24 bytes. See ++ // draft-irtf-cfrg-xchacha-01, Section 2.3. ++ key, _ = HChaCha20(key, nonce[0:16]) ++ cNonce := make([]byte, NonceSize) ++ copy(cNonce[4:12], nonce[16:24]) ++ nonce = cNonce ++ } else if len(nonce) != NonceSize { ++ return nil, errors.New("chacha20: wrong nonce size") ++ } ++ ++ key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint ++ c.key = [8]uint32{ ++ binary.LittleEndian.Uint32(key[0:4]), ++ binary.LittleEndian.Uint32(key[4:8]), ++ binary.LittleEndian.Uint32(key[8:12]), ++ binary.LittleEndian.Uint32(key[12:16]), ++ binary.LittleEndian.Uint32(key[16:20]), ++ binary.LittleEndian.Uint32(key[20:24]), ++ binary.LittleEndian.Uint32(key[24:28]), ++ binary.LittleEndian.Uint32(key[28:32]), ++ } ++ c.nonce = [3]uint32{ ++ binary.LittleEndian.Uint32(nonce[0:4]), ++ binary.LittleEndian.Uint32(nonce[4:8]), ++ binary.LittleEndian.Uint32(nonce[8:12]), ++ } ++ return c, nil ++} ++ ++// The constant first 4 words of the ChaCha20 state. ++const ( ++ j0 uint32 = 0x61707865 // expa ++ j1 uint32 = 0x3320646e // nd 3 ++ j2 uint32 = 0x79622d32 // 2-by ++ j3 uint32 = 0x6b206574 // te k ++) ++ ++const blockSize = 64 ++ ++// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words. ++// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16 ++// words each round, in columnar or diagonal groups of 4 at a time. ++func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { ++ a += b ++ d ^= a ++ d = bits.RotateLeft32(d, 16) ++ c += d ++ b ^= c ++ b = bits.RotateLeft32(b, 12) ++ a += b ++ d ^= a ++ d = bits.RotateLeft32(d, 8) ++ c += d ++ b ^= c ++ b = bits.RotateLeft32(b, 7) ++ return a, b, c, d ++} ++ ++// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will ++// behave as if (64 * counter) bytes had been encrypted so far. ++// ++// To prevent accidental counter reuse, SetCounter panics if counter is less ++// than the current value. ++// ++// Note that the execution time of XORKeyStream is not independent of the ++// counter value. ++func (s *Cipher) SetCounter(counter uint32) { ++ // Internally, s may buffer multiple blocks, which complicates this ++ // implementation slightly. When checking whether the counter has rolled ++ // back, we must use both s.counter and s.len to determine how many blocks ++ // we have already output. ++ outputCounter := s.counter - uint32(s.len)/blockSize ++ if s.overflow || counter < outputCounter { ++ panic("chacha20: SetCounter attempted to rollback counter") ++ } ++ ++ // In the general case, we set the new counter value and reset s.len to 0, ++ // causing the next call to XORKeyStream to refill the buffer. However, if ++ // we're advancing within the existing buffer, we can save work by simply ++ // setting s.len. ++ if counter < s.counter { ++ s.len = int(s.counter-counter) * blockSize ++ } else { ++ s.counter = counter ++ s.len = 0 ++ } ++} ++ ++// XORKeyStream XORs each byte in the given slice with a byte from the ++// cipher's key stream. Dst and src must overlap entirely or not at all. ++// ++// If len(dst) < len(src), XORKeyStream will panic. It is acceptable ++// to pass a dst bigger than src, and in that case, XORKeyStream will ++// only update dst[:len(src)] and will not touch the rest of dst. ++// ++// Multiple calls to XORKeyStream behave as if the concatenation of ++// the src buffers was passed in a single run. That is, Cipher ++// maintains state and does not reset at each XORKeyStream call. ++func (s *Cipher) XORKeyStream(dst, src []byte) { ++ if len(src) == 0 { ++ return ++ } ++ if len(dst) < len(src) { ++ panic("chacha20: output smaller than input") ++ } ++ dst = dst[:len(src)] ++ if alias.InexactOverlap(dst, src) { ++ panic("chacha20: invalid buffer overlap") ++ } ++ ++ // First, drain any remaining key stream from a previous XORKeyStream. ++ if s.len != 0 { ++ keyStream := s.buf[bufSize-s.len:] ++ if len(src) < len(keyStream) { ++ keyStream = keyStream[:len(src)] ++ } ++ _ = src[len(keyStream)-1] // bounds check elimination hint ++ for i, b := range keyStream { ++ dst[i] = src[i] ^ b ++ } ++ s.len -= len(keyStream) ++ dst, src = dst[len(keyStream):], src[len(keyStream):] ++ } ++ if len(src) == 0 { ++ return ++ } ++ ++ // If we'd need to let the counter overflow and keep generating output, ++ // panic immediately. If instead we'd only reach the last block, remember ++ // not to generate any more output after the buffer is drained. ++ numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize ++ if s.overflow || uint64(s.counter)+numBlocks > 1<<32 { ++ panic("chacha20: counter overflow") ++ } else if uint64(s.counter)+numBlocks == 1<<32 { ++ s.overflow = true ++ } ++ ++ // xorKeyStreamBlocks implementations expect input lengths that are a ++ // multiple of bufSize. Platform-specific ones process multiple blocks at a ++ // time, so have bufSizes that are a multiple of blockSize. ++ ++ full := len(src) - len(src)%bufSize ++ if full > 0 { ++ s.xorKeyStreamBlocks(dst[:full], src[:full]) ++ } ++ dst, src = dst[full:], src[full:] ++ ++ // If using a multi-block xorKeyStreamBlocks would overflow, use the generic ++ // one that does one block at a time. ++ const blocksPerBuf = bufSize / blockSize ++ if uint64(s.counter)+blocksPerBuf > 1<<32 { ++ s.buf = [bufSize]byte{} ++ numBlocks := (len(src) + blockSize - 1) / blockSize ++ buf := s.buf[bufSize-numBlocks*blockSize:] ++ copy(buf, src) ++ s.xorKeyStreamBlocksGeneric(buf, buf) ++ s.len = len(buf) - copy(dst, buf) ++ return ++ } ++ ++ // If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and ++ // keep the leftover keystream for the next XORKeyStream invocation. ++ if len(src) > 0 { ++ s.buf = [bufSize]byte{} ++ copy(s.buf[:], src) ++ s.xorKeyStreamBlocks(s.buf[:], s.buf[:]) ++ s.len = bufSize - copy(dst, s.buf[:]) ++ } ++} ++ ++func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { ++ if len(dst) != len(src) || len(dst)%blockSize != 0 { ++ panic("chacha20: internal error: wrong dst and/or src length") ++ } ++ ++ // To generate each block of key stream, the initial cipher state ++ // (represented below) is passed through 20 rounds of shuffling, ++ // alternatively applying quarterRounds by columns (like 1, 5, 9, 13) ++ // or by diagonals (like 1, 6, 11, 12). ++ // ++ // 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc ++ // 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk ++ // 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk ++ // 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn ++ // ++ // c=constant k=key b=blockcount n=nonce ++ var ( ++ c0, c1, c2, c3 = j0, j1, j2, j3 ++ c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3] ++ c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7] ++ _, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2] ++ ) ++ ++ // Three quarters of the first round don't depend on the counter, so we can ++ // calculate them here, and reuse them for multiple blocks in the loop, and ++ // for future XORKeyStream invocations. ++ if !s.precompDone { ++ s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13) ++ s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14) ++ s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15) ++ s.precompDone = true ++ } ++ ++ // A condition of len(src) > 0 would be sufficient, but this also ++ // acts as a bounds check elimination hint. ++ for len(src) >= 64 && len(dst) >= 64 { ++ // The remainder of the first column round. ++ fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter) ++ ++ // The second diagonal round. ++ x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15) ++ x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12) ++ x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13) ++ x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14) ++ ++ // The remaining 18 rounds. ++ for i := 0; i < 9; i++ { ++ // Column round. ++ x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) ++ x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) ++ x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) ++ x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) ++ ++ // Diagonal round. ++ x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) ++ x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) ++ x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) ++ x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) ++ } ++ ++ // Add back the initial state to generate the key stream, then ++ // XOR the key stream with the source and write out the result. ++ addXor(dst[0:4], src[0:4], x0, c0) ++ addXor(dst[4:8], src[4:8], x1, c1) ++ addXor(dst[8:12], src[8:12], x2, c2) ++ addXor(dst[12:16], src[12:16], x3, c3) ++ addXor(dst[16:20], src[16:20], x4, c4) ++ addXor(dst[20:24], src[20:24], x5, c5) ++ addXor(dst[24:28], src[24:28], x6, c6) ++ addXor(dst[28:32], src[28:32], x7, c7) ++ addXor(dst[32:36], src[32:36], x8, c8) ++ addXor(dst[36:40], src[36:40], x9, c9) ++ addXor(dst[40:44], src[40:44], x10, c10) ++ addXor(dst[44:48], src[44:48], x11, c11) ++ addXor(dst[48:52], src[48:52], x12, s.counter) ++ addXor(dst[52:56], src[52:56], x13, c13) ++ addXor(dst[56:60], src[56:60], x14, c14) ++ addXor(dst[60:64], src[60:64], x15, c15) ++ ++ s.counter += 1 ++ ++ src, dst = src[blockSize:], dst[blockSize:] ++ } ++} ++ ++// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes ++// key and a 16 bytes nonce. It returns an error if key or nonce have any other ++// length. It is used as part of the XChaCha20 construction. ++func HChaCha20(key, nonce []byte) ([]byte, error) { ++ // This function is split into a wrapper so that the slice allocation will ++ // be inlined, and depending on how the caller uses the return value, won't ++ // escape to the heap. ++ out := make([]byte, 32) ++ return hChaCha20(out, key, nonce) ++} ++ ++func hChaCha20(out, key, nonce []byte) ([]byte, error) { ++ if len(key) != KeySize { ++ return nil, errors.New("chacha20: wrong HChaCha20 key size") ++ } ++ if len(nonce) != 16 { ++ return nil, errors.New("chacha20: wrong HChaCha20 nonce size") ++ } ++ ++ x0, x1, x2, x3 := j0, j1, j2, j3 ++ x4 := binary.LittleEndian.Uint32(key[0:4]) ++ x5 := binary.LittleEndian.Uint32(key[4:8]) ++ x6 := binary.LittleEndian.Uint32(key[8:12]) ++ x7 := binary.LittleEndian.Uint32(key[12:16]) ++ x8 := binary.LittleEndian.Uint32(key[16:20]) ++ x9 := binary.LittleEndian.Uint32(key[20:24]) ++ x10 := binary.LittleEndian.Uint32(key[24:28]) ++ x11 := binary.LittleEndian.Uint32(key[28:32]) ++ x12 := binary.LittleEndian.Uint32(nonce[0:4]) ++ x13 := binary.LittleEndian.Uint32(nonce[4:8]) ++ x14 := binary.LittleEndian.Uint32(nonce[8:12]) ++ x15 := binary.LittleEndian.Uint32(nonce[12:16]) ++ ++ for i := 0; i < 10; i++ { ++ // Diagonal round. ++ x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) ++ x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) ++ x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) ++ x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) ++ ++ // Column round. ++ x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) ++ x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) ++ x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) ++ x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) ++ } ++ ++ _ = out[31] // bounds check elimination hint ++ binary.LittleEndian.PutUint32(out[0:4], x0) ++ binary.LittleEndian.PutUint32(out[4:8], x1) ++ binary.LittleEndian.PutUint32(out[8:12], x2) ++ binary.LittleEndian.PutUint32(out[12:16], x3) ++ binary.LittleEndian.PutUint32(out[16:20], x12) ++ binary.LittleEndian.PutUint32(out[20:24], x13) ++ binary.LittleEndian.PutUint32(out[24:28], x14) ++ binary.LittleEndian.PutUint32(out[28:32], x15) ++ return out, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go +new file mode 100644 +index 00000000000000..025b49897e32b2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go +@@ -0,0 +1,14 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego ++// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego ++ ++package chacha20 ++ ++const bufSize = blockSize ++ ++func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) { ++ s.xorKeyStreamBlocksGeneric(dst, src) ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go +new file mode 100644 +index 00000000000000..da420b2e97b03c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go +@@ -0,0 +1,17 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package chacha20 ++ ++const bufSize = 256 ++ ++//go:noescape ++func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) ++ ++func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { ++ chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter) ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s +new file mode 100644 +index 00000000000000..5c0fed26f85027 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s +@@ -0,0 +1,450 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Based on CRYPTOGAMS code with the following comment: ++// # ==================================================================== ++// # Written by Andy Polyakov for the OpenSSL ++// # project. The module is, however, dual licensed under OpenSSL and ++// # CRYPTOGAMS licenses depending on where you obtain it. For further ++// # details see http://www.openssl.org/~appro/cryptogams/. ++// # ==================================================================== ++ ++// Code for the perl script that generates the ppc64 assembler ++// can be found in the cryptogams repository at the link below. It is based on ++// the original from openssl. ++ ++// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91 ++ ++// The differences in this and the original implementation are ++// due to the calling conventions and initialization of constants. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "textflag.h" ++ ++#define OUT R3 ++#define INP R4 ++#define LEN R5 ++#define KEY R6 ++#define CNT R7 ++#define TMP R15 ++ ++#define CONSTBASE R16 ++#define BLOCKS R17 ++ ++DATA consts<>+0x00(SB)/8, $0x3320646e61707865 ++DATA consts<>+0x08(SB)/8, $0x6b20657479622d32 ++DATA consts<>+0x10(SB)/8, $0x0000000000000001 ++DATA consts<>+0x18(SB)/8, $0x0000000000000000 ++DATA consts<>+0x20(SB)/8, $0x0000000000000004 ++DATA consts<>+0x28(SB)/8, $0x0000000000000000 ++DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d ++DATA consts<>+0x38(SB)/8, $0x0203000106070405 ++DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c ++DATA consts<>+0x48(SB)/8, $0x0102030005060704 ++DATA consts<>+0x50(SB)/8, $0x6170786561707865 ++DATA consts<>+0x58(SB)/8, $0x6170786561707865 ++DATA consts<>+0x60(SB)/8, $0x3320646e3320646e ++DATA consts<>+0x68(SB)/8, $0x3320646e3320646e ++DATA consts<>+0x70(SB)/8, $0x79622d3279622d32 ++DATA consts<>+0x78(SB)/8, $0x79622d3279622d32 ++DATA consts<>+0x80(SB)/8, $0x6b2065746b206574 ++DATA consts<>+0x88(SB)/8, $0x6b2065746b206574 ++DATA consts<>+0x90(SB)/8, $0x0000000100000000 ++DATA consts<>+0x98(SB)/8, $0x0000000300000002 ++GLOBL consts<>(SB), RODATA, $0xa0 ++ ++//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) ++TEXT Β·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 ++ MOVD out+0(FP), OUT ++ MOVD inp+8(FP), INP ++ MOVD len+16(FP), LEN ++ MOVD key+24(FP), KEY ++ MOVD counter+32(FP), CNT ++ ++ // Addressing for constants ++ MOVD $consts<>+0x00(SB), CONSTBASE ++ MOVD $16, R8 ++ MOVD $32, R9 ++ MOVD $48, R10 ++ MOVD $64, R11 ++ SRD $6, LEN, BLOCKS ++ // V16 ++ LXVW4X (CONSTBASE)(R0), VS48 ++ ADD $80,CONSTBASE ++ ++ // Load key into V17,V18 ++ LXVW4X (KEY)(R0), VS49 ++ LXVW4X (KEY)(R8), VS50 ++ ++ // Load CNT, NONCE into V19 ++ LXVW4X (CNT)(R0), VS51 ++ ++ // Clear V27 ++ VXOR V27, V27, V27 ++ ++ // V28 ++ LXVW4X (CONSTBASE)(R11), VS60 ++ ++ // splat slot from V19 -> V26 ++ VSPLTW $0, V19, V26 ++ ++ VSLDOI $4, V19, V27, V19 ++ VSLDOI $12, V27, V19, V19 ++ ++ VADDUWM V26, V28, V26 ++ ++ MOVD $10, R14 ++ MOVD R14, CTR ++ ++loop_outer_vsx: ++ // V0, V1, V2, V3 ++ LXVW4X (R0)(CONSTBASE), VS32 ++ LXVW4X (R8)(CONSTBASE), VS33 ++ LXVW4X (R9)(CONSTBASE), VS34 ++ LXVW4X (R10)(CONSTBASE), VS35 ++ ++ // splat values from V17, V18 into V4-V11 ++ VSPLTW $0, V17, V4 ++ VSPLTW $1, V17, V5 ++ VSPLTW $2, V17, V6 ++ VSPLTW $3, V17, V7 ++ VSPLTW $0, V18, V8 ++ VSPLTW $1, V18, V9 ++ VSPLTW $2, V18, V10 ++ VSPLTW $3, V18, V11 ++ ++ // VOR ++ VOR V26, V26, V12 ++ ++ // splat values from V19 -> V13, V14, V15 ++ VSPLTW $1, V19, V13 ++ VSPLTW $2, V19, V14 ++ VSPLTW $3, V19, V15 ++ ++ // splat const values ++ VSPLTISW $-16, V27 ++ VSPLTISW $12, V28 ++ VSPLTISW $8, V29 ++ VSPLTISW $7, V30 ++ ++loop_vsx: ++ VADDUWM V0, V4, V0 ++ VADDUWM V1, V5, V1 ++ VADDUWM V2, V6, V2 ++ VADDUWM V3, V7, V3 ++ ++ VXOR V12, V0, V12 ++ VXOR V13, V1, V13 ++ VXOR V14, V2, V14 ++ VXOR V15, V3, V15 ++ ++ VRLW V12, V27, V12 ++ VRLW V13, V27, V13 ++ VRLW V14, V27, V14 ++ VRLW V15, V27, V15 ++ ++ VADDUWM V8, V12, V8 ++ VADDUWM V9, V13, V9 ++ VADDUWM V10, V14, V10 ++ VADDUWM V11, V15, V11 ++ ++ VXOR V4, V8, V4 ++ VXOR V5, V9, V5 ++ VXOR V6, V10, V6 ++ VXOR V7, V11, V7 ++ ++ VRLW V4, V28, V4 ++ VRLW V5, V28, V5 ++ VRLW V6, V28, V6 ++ VRLW V7, V28, V7 ++ ++ VADDUWM V0, V4, V0 ++ VADDUWM V1, V5, V1 ++ VADDUWM V2, V6, V2 ++ VADDUWM V3, V7, V3 ++ ++ VXOR V12, V0, V12 ++ VXOR V13, V1, V13 ++ VXOR V14, V2, V14 ++ VXOR V15, V3, V15 ++ ++ VRLW V12, V29, V12 ++ VRLW V13, V29, V13 ++ VRLW V14, V29, V14 ++ VRLW V15, V29, V15 ++ ++ VADDUWM V8, V12, V8 ++ VADDUWM V9, V13, V9 ++ VADDUWM V10, V14, V10 ++ VADDUWM V11, V15, V11 ++ ++ VXOR V4, V8, V4 ++ VXOR V5, V9, V5 ++ VXOR V6, V10, V6 ++ VXOR V7, V11, V7 ++ ++ VRLW V4, V30, V4 ++ VRLW V5, V30, V5 ++ VRLW V6, V30, V6 ++ VRLW V7, V30, V7 ++ ++ VADDUWM V0, V5, V0 ++ VADDUWM V1, V6, V1 ++ VADDUWM V2, V7, V2 ++ VADDUWM V3, V4, V3 ++ ++ VXOR V15, V0, V15 ++ VXOR V12, V1, V12 ++ VXOR V13, V2, V13 ++ VXOR V14, V3, V14 ++ ++ VRLW V15, V27, V15 ++ VRLW V12, V27, V12 ++ VRLW V13, V27, V13 ++ VRLW V14, V27, V14 ++ ++ VADDUWM V10, V15, V10 ++ VADDUWM V11, V12, V11 ++ VADDUWM V8, V13, V8 ++ VADDUWM V9, V14, V9 ++ ++ VXOR V5, V10, V5 ++ VXOR V6, V11, V6 ++ VXOR V7, V8, V7 ++ VXOR V4, V9, V4 ++ ++ VRLW V5, V28, V5 ++ VRLW V6, V28, V6 ++ VRLW V7, V28, V7 ++ VRLW V4, V28, V4 ++ ++ VADDUWM V0, V5, V0 ++ VADDUWM V1, V6, V1 ++ VADDUWM V2, V7, V2 ++ VADDUWM V3, V4, V3 ++ ++ VXOR V15, V0, V15 ++ VXOR V12, V1, V12 ++ VXOR V13, V2, V13 ++ VXOR V14, V3, V14 ++ ++ VRLW V15, V29, V15 ++ VRLW V12, V29, V12 ++ VRLW V13, V29, V13 ++ VRLW V14, V29, V14 ++ ++ VADDUWM V10, V15, V10 ++ VADDUWM V11, V12, V11 ++ VADDUWM V8, V13, V8 ++ VADDUWM V9, V14, V9 ++ ++ VXOR V5, V10, V5 ++ VXOR V6, V11, V6 ++ VXOR V7, V8, V7 ++ VXOR V4, V9, V4 ++ ++ VRLW V5, V30, V5 ++ VRLW V6, V30, V6 ++ VRLW V7, V30, V7 ++ VRLW V4, V30, V4 ++ BC 16, LT, loop_vsx ++ ++ VADDUWM V12, V26, V12 ++ ++ WORD $0x13600F8C // VMRGEW V0, V1, V27 ++ WORD $0x13821F8C // VMRGEW V2, V3, V28 ++ ++ WORD $0x10000E8C // VMRGOW V0, V1, V0 ++ WORD $0x10421E8C // VMRGOW V2, V3, V2 ++ ++ WORD $0x13A42F8C // VMRGEW V4, V5, V29 ++ WORD $0x13C63F8C // VMRGEW V6, V7, V30 ++ ++ XXPERMDI VS32, VS34, $0, VS33 ++ XXPERMDI VS32, VS34, $3, VS35 ++ XXPERMDI VS59, VS60, $0, VS32 ++ XXPERMDI VS59, VS60, $3, VS34 ++ ++ WORD $0x10842E8C // VMRGOW V4, V5, V4 ++ WORD $0x10C63E8C // VMRGOW V6, V7, V6 ++ ++ WORD $0x13684F8C // VMRGEW V8, V9, V27 ++ WORD $0x138A5F8C // VMRGEW V10, V11, V28 ++ ++ XXPERMDI VS36, VS38, $0, VS37 ++ XXPERMDI VS36, VS38, $3, VS39 ++ XXPERMDI VS61, VS62, $0, VS36 ++ XXPERMDI VS61, VS62, $3, VS38 ++ ++ WORD $0x11084E8C // VMRGOW V8, V9, V8 ++ WORD $0x114A5E8C // VMRGOW V10, V11, V10 ++ ++ WORD $0x13AC6F8C // VMRGEW V12, V13, V29 ++ WORD $0x13CE7F8C // VMRGEW V14, V15, V30 ++ ++ XXPERMDI VS40, VS42, $0, VS41 ++ XXPERMDI VS40, VS42, $3, VS43 ++ XXPERMDI VS59, VS60, $0, VS40 ++ XXPERMDI VS59, VS60, $3, VS42 ++ ++ WORD $0x118C6E8C // VMRGOW V12, V13, V12 ++ WORD $0x11CE7E8C // VMRGOW V14, V15, V14 ++ ++ VSPLTISW $4, V27 ++ VADDUWM V26, V27, V26 ++ ++ XXPERMDI VS44, VS46, $0, VS45 ++ XXPERMDI VS44, VS46, $3, VS47 ++ XXPERMDI VS61, VS62, $0, VS44 ++ XXPERMDI VS61, VS62, $3, VS46 ++ ++ VADDUWM V0, V16, V0 ++ VADDUWM V4, V17, V4 ++ VADDUWM V8, V18, V8 ++ VADDUWM V12, V19, V12 ++ ++ CMPU LEN, $64 ++ BLT tail_vsx ++ ++ // Bottom of loop ++ LXVW4X (INP)(R0), VS59 ++ LXVW4X (INP)(R8), VS60 ++ LXVW4X (INP)(R9), VS61 ++ LXVW4X (INP)(R10), VS62 ++ ++ VXOR V27, V0, V27 ++ VXOR V28, V4, V28 ++ VXOR V29, V8, V29 ++ VXOR V30, V12, V30 ++ ++ STXVW4X VS59, (OUT)(R0) ++ STXVW4X VS60, (OUT)(R8) ++ ADD $64, INP ++ STXVW4X VS61, (OUT)(R9) ++ ADD $-64, LEN ++ STXVW4X VS62, (OUT)(R10) ++ ADD $64, OUT ++ BEQ done_vsx ++ ++ VADDUWM V1, V16, V0 ++ VADDUWM V5, V17, V4 ++ VADDUWM V9, V18, V8 ++ VADDUWM V13, V19, V12 ++ ++ CMPU LEN, $64 ++ BLT tail_vsx ++ ++ LXVW4X (INP)(R0), VS59 ++ LXVW4X (INP)(R8), VS60 ++ LXVW4X (INP)(R9), VS61 ++ LXVW4X (INP)(R10), VS62 ++ VXOR V27, V0, V27 ++ ++ VXOR V28, V4, V28 ++ VXOR V29, V8, V29 ++ VXOR V30, V12, V30 ++ ++ STXVW4X VS59, (OUT)(R0) ++ STXVW4X VS60, (OUT)(R8) ++ ADD $64, INP ++ STXVW4X VS61, (OUT)(R9) ++ ADD $-64, LEN ++ STXVW4X VS62, (OUT)(V10) ++ ADD $64, OUT ++ BEQ done_vsx ++ ++ VADDUWM V2, V16, V0 ++ VADDUWM V6, V17, V4 ++ VADDUWM V10, V18, V8 ++ VADDUWM V14, V19, V12 ++ ++ CMPU LEN, $64 ++ BLT tail_vsx ++ ++ LXVW4X (INP)(R0), VS59 ++ LXVW4X (INP)(R8), VS60 ++ LXVW4X (INP)(R9), VS61 ++ LXVW4X (INP)(R10), VS62 ++ ++ VXOR V27, V0, V27 ++ VXOR V28, V4, V28 ++ VXOR V29, V8, V29 ++ VXOR V30, V12, V30 ++ ++ STXVW4X VS59, (OUT)(R0) ++ STXVW4X VS60, (OUT)(R8) ++ ADD $64, INP ++ STXVW4X VS61, (OUT)(R9) ++ ADD $-64, LEN ++ STXVW4X VS62, (OUT)(R10) ++ ADD $64, OUT ++ BEQ done_vsx ++ ++ VADDUWM V3, V16, V0 ++ VADDUWM V7, V17, V4 ++ VADDUWM V11, V18, V8 ++ VADDUWM V15, V19, V12 ++ ++ CMPU LEN, $64 ++ BLT tail_vsx ++ ++ LXVW4X (INP)(R0), VS59 ++ LXVW4X (INP)(R8), VS60 ++ LXVW4X (INP)(R9), VS61 ++ LXVW4X (INP)(R10), VS62 ++ ++ VXOR V27, V0, V27 ++ VXOR V28, V4, V28 ++ VXOR V29, V8, V29 ++ VXOR V30, V12, V30 ++ ++ STXVW4X VS59, (OUT)(R0) ++ STXVW4X VS60, (OUT)(R8) ++ ADD $64, INP ++ STXVW4X VS61, (OUT)(R9) ++ ADD $-64, LEN ++ STXVW4X VS62, (OUT)(R10) ++ ADD $64, OUT ++ ++ MOVD $10, R14 ++ MOVD R14, CTR ++ BNE loop_outer_vsx ++ ++done_vsx: ++ // Increment counter by number of 64 byte blocks ++ MOVD (CNT), R14 ++ ADD BLOCKS, R14 ++ MOVD R14, (CNT) ++ RET ++ ++tail_vsx: ++ ADD $32, R1, R11 ++ MOVD LEN, CTR ++ ++ // Save values on stack to copy from ++ STXVW4X VS32, (R11)(R0) ++ STXVW4X VS36, (R11)(R8) ++ STXVW4X VS40, (R11)(R9) ++ STXVW4X VS44, (R11)(R10) ++ ADD $-1, R11, R12 ++ ADD $-1, INP ++ ADD $-1, OUT ++ ++looptail_vsx: ++ // Copying the result to OUT ++ // in bytes. ++ MOVBZU 1(R12), KEY ++ MOVBZU 1(INP), TMP ++ XOR KEY, TMP, KEY ++ MOVBU KEY, 1(OUT) ++ BC 16, LT, looptail_vsx ++ ++ // Clear the stack values ++ STXVW4X VS48, (R11)(R0) ++ STXVW4X VS48, (R11)(R8) ++ STXVW4X VS48, (R11)(R9) ++ STXVW4X VS48, (R11)(R10) ++ BR done_vsx +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go +new file mode 100644 +index 00000000000000..4652247b8a637e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go +@@ -0,0 +1,28 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package chacha20 ++ ++import "golang.org/x/sys/cpu" ++ ++var haveAsm = cpu.S390X.HasVX ++ ++const bufSize = 256 ++ ++// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only ++// be called when the vector facility is available. Implementation in asm_s390x.s. ++// ++//go:noescape ++func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) ++ ++func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { ++ if cpu.S390X.HasVX { ++ xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) ++ } else { ++ c.xorKeyStreamBlocksGeneric(dst, src) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s +new file mode 100644 +index 00000000000000..f3ef5a019d9593 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s +@@ -0,0 +1,225 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "go_asm.h" ++#include "textflag.h" ++ ++// This is an implementation of the ChaCha20 encryption algorithm as ++// specified in RFC 7539. It uses vector instructions to compute ++// 4 keystream blocks in parallel (256 bytes) which are then XORed ++// with the bytes in the input slice. ++ ++GLOBL Β·constants<>(SB), RODATA|NOPTR, $32 ++// BSWAP: swap bytes in each 4-byte element ++DATA Β·constants<>+0x00(SB)/4, $0x03020100 ++DATA Β·constants<>+0x04(SB)/4, $0x07060504 ++DATA Β·constants<>+0x08(SB)/4, $0x0b0a0908 ++DATA Β·constants<>+0x0c(SB)/4, $0x0f0e0d0c ++// J0: [j0, j1, j2, j3] ++DATA Β·constants<>+0x10(SB)/4, $0x61707865 ++DATA Β·constants<>+0x14(SB)/4, $0x3320646e ++DATA Β·constants<>+0x18(SB)/4, $0x79622d32 ++DATA Β·constants<>+0x1c(SB)/4, $0x6b206574 ++ ++#define BSWAP V5 ++#define J0 V6 ++#define KEY0 V7 ++#define KEY1 V8 ++#define NONCE V9 ++#define CTR V10 ++#define M0 V11 ++#define M1 V12 ++#define M2 V13 ++#define M3 V14 ++#define INC V15 ++#define X0 V16 ++#define X1 V17 ++#define X2 V18 ++#define X3 V19 ++#define X4 V20 ++#define X5 V21 ++#define X6 V22 ++#define X7 V23 ++#define X8 V24 ++#define X9 V25 ++#define X10 V26 ++#define X11 V27 ++#define X12 V28 ++#define X13 V29 ++#define X14 V30 ++#define X15 V31 ++ ++#define NUM_ROUNDS 20 ++ ++#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \ ++ VAF a1, a0, a0 \ ++ VAF b1, b0, b0 \ ++ VAF c1, c0, c0 \ ++ VAF d1, d0, d0 \ ++ VX a0, a2, a2 \ ++ VX b0, b2, b2 \ ++ VX c0, c2, c2 \ ++ VX d0, d2, d2 \ ++ VERLLF $16, a2, a2 \ ++ VERLLF $16, b2, b2 \ ++ VERLLF $16, c2, c2 \ ++ VERLLF $16, d2, d2 \ ++ VAF a2, a3, a3 \ ++ VAF b2, b3, b3 \ ++ VAF c2, c3, c3 \ ++ VAF d2, d3, d3 \ ++ VX a3, a1, a1 \ ++ VX b3, b1, b1 \ ++ VX c3, c1, c1 \ ++ VX d3, d1, d1 \ ++ VERLLF $12, a1, a1 \ ++ VERLLF $12, b1, b1 \ ++ VERLLF $12, c1, c1 \ ++ VERLLF $12, d1, d1 \ ++ VAF a1, a0, a0 \ ++ VAF b1, b0, b0 \ ++ VAF c1, c0, c0 \ ++ VAF d1, d0, d0 \ ++ VX a0, a2, a2 \ ++ VX b0, b2, b2 \ ++ VX c0, c2, c2 \ ++ VX d0, d2, d2 \ ++ VERLLF $8, a2, a2 \ ++ VERLLF $8, b2, b2 \ ++ VERLLF $8, c2, c2 \ ++ VERLLF $8, d2, d2 \ ++ VAF a2, a3, a3 \ ++ VAF b2, b3, b3 \ ++ VAF c2, c3, c3 \ ++ VAF d2, d3, d3 \ ++ VX a3, a1, a1 \ ++ VX b3, b1, b1 \ ++ VX c3, c1, c1 \ ++ VX d3, d1, d1 \ ++ VERLLF $7, a1, a1 \ ++ VERLLF $7, b1, b1 \ ++ VERLLF $7, c1, c1 \ ++ VERLLF $7, d1, d1 ++ ++#define PERMUTE(mask, v0, v1, v2, v3) \ ++ VPERM v0, v0, mask, v0 \ ++ VPERM v1, v1, mask, v1 \ ++ VPERM v2, v2, mask, v2 \ ++ VPERM v3, v3, mask, v3 ++ ++#define ADDV(x, v0, v1, v2, v3) \ ++ VAF x, v0, v0 \ ++ VAF x, v1, v1 \ ++ VAF x, v2, v2 \ ++ VAF x, v3, v3 ++ ++#define XORV(off, dst, src, v0, v1, v2, v3) \ ++ VLM off(src), M0, M3 \ ++ PERMUTE(BSWAP, v0, v1, v2, v3) \ ++ VX v0, M0, M0 \ ++ VX v1, M1, M1 \ ++ VX v2, M2, M2 \ ++ VX v3, M3, M3 \ ++ VSTM M0, M3, off(dst) ++ ++#define SHUFFLE(a, b, c, d, t, u, v, w) \ ++ VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]} ++ VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]} ++ VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]} ++ VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]} ++ VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]} ++ VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]} ++ VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} ++ VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} ++ ++// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) ++TEXT Β·xorKeyStreamVX(SB), NOSPLIT, $0 ++ MOVD $Β·constants<>(SB), R1 ++ MOVD dst+0(FP), R2 // R2=&dst[0] ++ LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src) ++ MOVD key+48(FP), R5 // R5=key ++ MOVD nonce+56(FP), R6 // R6=nonce ++ MOVD counter+64(FP), R7 // R7=counter ++ ++ // load BSWAP and J0 ++ VLM (R1), BSWAP, J0 ++ ++ // setup ++ MOVD $95, R0 ++ VLM (R5), KEY0, KEY1 ++ VLL R0, (R6), NONCE ++ VZERO M0 ++ VLEIB $7, $32, M0 ++ VSRLB M0, NONCE, NONCE ++ ++ // initialize counter values ++ VLREPF (R7), CTR ++ VZERO INC ++ VLEIF $1, $1, INC ++ VLEIF $2, $2, INC ++ VLEIF $3, $3, INC ++ VAF INC, CTR, CTR ++ VREPIF $4, INC ++ ++chacha: ++ VREPF $0, J0, X0 ++ VREPF $1, J0, X1 ++ VREPF $2, J0, X2 ++ VREPF $3, J0, X3 ++ VREPF $0, KEY0, X4 ++ VREPF $1, KEY0, X5 ++ VREPF $2, KEY0, X6 ++ VREPF $3, KEY0, X7 ++ VREPF $0, KEY1, X8 ++ VREPF $1, KEY1, X9 ++ VREPF $2, KEY1, X10 ++ VREPF $3, KEY1, X11 ++ VLR CTR, X12 ++ VREPF $1, NONCE, X13 ++ VREPF $2, NONCE, X14 ++ VREPF $3, NONCE, X15 ++ ++ MOVD $(NUM_ROUNDS/2), R1 ++ ++loop: ++ ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11) ++ ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9) ++ ++ ADD $-1, R1 ++ BNE loop ++ ++ // decrement length ++ ADD $-256, R4 ++ ++ // rearrange vectors ++ SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) ++ ADDV(J0, X0, X1, X2, X3) ++ SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3) ++ ADDV(KEY0, X4, X5, X6, X7) ++ SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3) ++ ADDV(KEY1, X8, X9, X10, X11) ++ VAF CTR, X12, X12 ++ SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3) ++ ADDV(NONCE, X12, X13, X14, X15) ++ ++ // increment counters ++ VAF INC, CTR, CTR ++ ++ // xor keystream with plaintext ++ XORV(0*64, R2, R3, X0, X4, X8, X12) ++ XORV(1*64, R2, R3, X1, X5, X9, X13) ++ XORV(2*64, R2, R3, X2, X6, X10, X14) ++ XORV(3*64, R2, R3, X3, X7, X11, X15) ++ ++ // increment pointers ++ MOVD $256(R2), R2 ++ MOVD $256(R3), R3 ++ ++ CMPBNE R4, $0, chacha ++ ++ VSTEF $0, CTR, (R7) ++ RET +diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_test.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_test.go +new file mode 100644 +index 00000000000000..60b11d92f6f582 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_test.go +@@ -0,0 +1,274 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package chacha20 ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "fmt" ++ "math/rand" ++ "testing" ++) ++ ++func _() { ++ // Assert that bufSize is a multiple of blockSize. ++ var b [1]byte ++ _ = b[bufSize%blockSize] ++} ++ ++func hexDecode(s string) []byte { ++ ss, err := hex.DecodeString(s) ++ if err != nil { ++ panic(fmt.Sprintf("cannot decode input %#v: %v", s, err)) ++ } ++ return ss ++} ++ ++// Run the test cases with the input and output in different buffers. ++func TestNoOverlap(t *testing.T) { ++ for _, c := range testVectors { ++ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) ++ input := hexDecode(c.input) ++ output := make([]byte, len(input)) ++ s.XORKeyStream(output, input) ++ got := hex.EncodeToString(output) ++ if got != c.output { ++ t.Errorf("length=%v: got %#v, want %#v", len(input), got, c.output) ++ } ++ } ++} ++ ++// Run the test cases with the input and output overlapping entirely. ++func TestOverlap(t *testing.T) { ++ for _, c := range testVectors { ++ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) ++ data := hexDecode(c.input) ++ s.XORKeyStream(data, data) ++ got := hex.EncodeToString(data) ++ if got != c.output { ++ t.Errorf("length=%v: got %#v, want %#v", len(data), got, c.output) ++ } ++ } ++} ++ ++// Run the test cases with various source and destination offsets. ++func TestUnaligned(t *testing.T) { ++ const max = 8 // max offset (+1) to test ++ for _, c := range testVectors { ++ data := hexDecode(c.input) ++ input := make([]byte, len(data)+max) ++ output := make([]byte, len(data)+max) ++ for i := 0; i < max; i++ { // input offsets ++ for j := 0; j < max; j++ { // output offsets ++ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) ++ ++ input := input[i : i+len(data)] ++ output := output[j : j+len(data)] ++ ++ copy(input, data) ++ s.XORKeyStream(output, input) ++ got := hex.EncodeToString(output) ++ if got != c.output { ++ t.Errorf("length=%v: got %#v, want %#v", len(data), got, c.output) ++ } ++ } ++ } ++ } ++} ++ ++// Run the test cases by calling XORKeyStream multiple times. ++func TestStep(t *testing.T) { ++ // wide range of step sizes to try and hit edge cases ++ steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256} ++ rnd := rand.New(rand.NewSource(123)) ++ for _, c := range testVectors { ++ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) ++ input := hexDecode(c.input) ++ output := make([]byte, len(input)) ++ ++ // step through the buffers ++ i, step := 0, steps[rnd.Intn(len(steps))] ++ for i+step < len(input) { ++ s.XORKeyStream(output[i:i+step], input[i:i+step]) ++ if i+step < len(input) && output[i+step] != 0 { ++ t.Errorf("length=%v, i=%v, step=%v: output overwritten", len(input), i, step) ++ } ++ i += step ++ step = steps[rnd.Intn(len(steps))] ++ } ++ // finish the encryption ++ s.XORKeyStream(output[i:], input[i:]) ++ // ensure we tolerate a call with an empty input ++ s.XORKeyStream(output[len(output):], input[len(input):]) ++ ++ got := hex.EncodeToString(output) ++ if got != c.output { ++ t.Errorf("length=%v: got %#v, want %#v", len(input), got, c.output) ++ } ++ } ++} ++ ++func TestSetCounter(t *testing.T) { ++ newCipher := func() *Cipher { ++ s, _ := NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) ++ return s ++ } ++ s := newCipher() ++ src := bytes.Repeat([]byte("test"), 32) // two 64-byte blocks ++ dst1 := make([]byte, len(src)) ++ s.XORKeyStream(dst1, src) ++ // advance counter to 1 and xor second block ++ s = newCipher() ++ s.SetCounter(1) ++ dst2 := make([]byte, len(src)) ++ s.XORKeyStream(dst2[64:], src[64:]) ++ if !bytes.Equal(dst1[64:], dst2[64:]) { ++ t.Error("failed to produce identical output using SetCounter") ++ } ++ ++ // test again with unaligned blocks; SetCounter should reset the buffer ++ s = newCipher() ++ s.XORKeyStream(dst1[:70], src[:70]) ++ s = newCipher() ++ s.XORKeyStream([]byte{0}, []byte{0}) ++ s.SetCounter(1) ++ s.XORKeyStream(dst2[64:70], src[64:70]) ++ if !bytes.Equal(dst1[64:70], dst2[64:70]) { ++ t.Error("SetCounter did not reset buffer") ++ } ++ ++ // advancing to a lower counter value should cause a panic ++ panics := func(fn func()) (p bool) { ++ defer func() { p = recover() != nil }() ++ fn() ++ return ++ } ++ if !panics(func() { s.SetCounter(0) }) { ++ t.Error("counter decreasing should trigger a panic") ++ } ++} ++ ++func TestLastBlock(t *testing.T) { ++ panics := func(fn func()) (p bool) { ++ defer func() { p = recover() != nil }() ++ fn() ++ return ++ } ++ ++ checkLastBlock := func(b []byte) { ++ t.Helper() ++ // Hardcoded result to check all implementations generate the same output. ++ lastBlock := "ace4cd09e294d1912d4ad205d06f95d9c2f2bfcf453e8753f128765b62215f4d" + ++ "92c74f2f626c6a640c0b1284d839ec81f1696281dafc3e684593937023b58b1d" ++ if got := hex.EncodeToString(b); got != lastBlock { ++ t.Errorf("wrong output for the last block, got %q, want %q", got, lastBlock) ++ } ++ } ++ ++ // setting the counter to 0xffffffff and crypting multiple blocks should ++ // trigger a panic ++ s, _ := NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) ++ s.SetCounter(0xffffffff) ++ blocks := make([]byte, blockSize*2) ++ if !panics(func() { s.XORKeyStream(blocks, blocks) }) { ++ t.Error("crypting multiple blocks should trigger a panic") ++ } ++ ++ // setting the counter to 0xffffffff - 1 and crypting two blocks should not ++ // trigger a panic ++ s, _ = NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) ++ s.SetCounter(0xffffffff - 1) ++ if panics(func() { s.XORKeyStream(blocks, blocks) }) { ++ t.Error("crypting the last blocks should not trigger a panic") ++ } ++ checkLastBlock(blocks[blockSize:]) ++ // once all the keystream is spent, setting the counter should panic ++ if !panics(func() { s.SetCounter(0xffffffff) }) { ++ t.Error("setting the counter after overflow should trigger a panic") ++ } ++ // crypting a subsequent block *should* panic ++ block := make([]byte, blockSize) ++ if !panics(func() { s.XORKeyStream(block, block) }) { ++ t.Error("crypting after overflow should trigger a panic") ++ } ++ ++ // if we crypt less than a full block, we should be able to crypt the rest ++ // in a subsequent call without panicking ++ s, _ = NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) ++ s.SetCounter(0xffffffff) ++ if panics(func() { s.XORKeyStream(block[:7], block[:7]) }) { ++ t.Error("crypting part of the last block should not trigger a panic") ++ } ++ if panics(func() { s.XORKeyStream(block[7:], block[7:]) }) { ++ t.Error("crypting part of the last block should not trigger a panic") ++ } ++ checkLastBlock(block) ++ // as before, a third call should trigger a panic because all keystream is spent ++ if !panics(func() { s.XORKeyStream(block[:1], block[:1]) }) { ++ t.Error("crypting after overflow should trigger a panic") ++ } ++} ++ ++func benchmarkChaCha20(b *testing.B, step, count int) { ++ tot := step * count ++ src := make([]byte, tot) ++ dst := make([]byte, tot) ++ key := make([]byte, KeySize) ++ nonce := make([]byte, NonceSize) ++ b.SetBytes(int64(tot)) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ c, _ := NewUnauthenticatedCipher(key, nonce) ++ for i := 0; i < tot; i += step { ++ c.XORKeyStream(dst[i:], src[i:i+step]) ++ } ++ } ++} ++ ++func BenchmarkChaCha20(b *testing.B) { ++ b.Run("64", func(b *testing.B) { ++ benchmarkChaCha20(b, 64, 1) ++ }) ++ b.Run("256", func(b *testing.B) { ++ benchmarkChaCha20(b, 256, 1) ++ }) ++ b.Run("10x25", func(b *testing.B) { ++ benchmarkChaCha20(b, 10, 25) ++ }) ++ b.Run("4096", func(b *testing.B) { ++ benchmarkChaCha20(b, 4096, 1) ++ }) ++ b.Run("100x40", func(b *testing.B) { ++ benchmarkChaCha20(b, 100, 40) ++ }) ++ b.Run("65536", func(b *testing.B) { ++ benchmarkChaCha20(b, 65536, 1) ++ }) ++ b.Run("1000x65", func(b *testing.B) { ++ benchmarkChaCha20(b, 1000, 65) ++ }) ++} ++ ++func TestHChaCha20(t *testing.T) { ++ // See draft-irtf-cfrg-xchacha-00, Section 2.2.1. ++ key := []byte{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} ++ nonce := []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, ++ 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27} ++ expected := []byte{0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, ++ 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, ++ 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, ++ 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, ++ } ++ result, err := HChaCha20(key[:], nonce[:]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if !bytes.Equal(expected, result) { ++ t.Errorf("want %x, got %x", expected, result) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/vectors_test.go b/ms_mod/golang.org/x/crypto/chacha20/vectors_test.go +new file mode 100644 +index 00000000000000..3d3bbcdc51d8a8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/vectors_test.go +@@ -0,0 +1,511 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package chacha20 ++ ++// Test vectors for ChaCha20 implementations. ++ ++type testCase struct { ++ nonce string ++ key string ++ input string ++ output string ++} ++ ++var testVectors = [...]testCase{ ++ { ++ // From libsodium/test/default/xchacha20.c ++ nonce: "c047548266b7c370d33566a2425cbf30d82d1eaf5294109e", ++ key: "9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232", ++ input: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", ++ output: "a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc", ++ }, ++ { ++ // From draft-irtf-cfrg-xchacha-01 ++ nonce: "404142434445464748494a4b4c4d4e4f5051525354555658", ++ key: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", ++ input: "5468652064686f6c65202870726f6e6f756e6365642022646f6c65222920697320616c736f206b6e6f776e2061732074686520417369617469632077696c6420646f672c2072656420646f672c20616e642077686973746c696e6720646f672e2049742069732061626f7574207468652073697a65206f662061204765726d616e20736865706865726420627574206c6f6f6b73206d6f7265206c696b652061206c6f6e672d6c656767656420666f782e205468697320686967686c7920656c757369766520616e6420736b696c6c6564206a756d70657220697320636c6173736966696564207769746820776f6c7665732c20636f796f7465732c206a61636b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d69632066616d696c792043616e696461652e", ++ output: "4559abba4e48c16102e8bb2c05e6947f50a786de162f9b0b7e592a9b53d0d4e98d8d6410d540a1a6375b26d80dace4fab52384c731acbf16a5923c0c48d3575d4d0d2c673b666faa731061277701093a6bf7a158a8864292a41c48e3a9b4c0daece0f8d98d0d7e05b37a307bbb66333164ec9e1b24ea0d6c3ffddcec4f68e7443056193a03c810e11344ca06d8ed8a2bfb1e8d48cfa6bc0eb4e2464b748142407c9f431aee769960e15ba8b96890466ef2457599852385c661f752ce20f9da0c09ab6b19df74e76a95967446f8d0fd415e7bee2a12a114c20eb5292ae7a349ae577820d5520a1f3fb62a17ce6a7e68fa7c79111d8860920bc048ef43fe84486ccb87c25f0ae045f0cce1e7989a9aa220a28bdd4827e751a24a6d5c62d790a66393b93111c1a55dd7421a10184974c7c5", ++ }, ++ { ++ nonce: "1733d194b3a2b6063600fe3f", ++ key: "b6a3a89de64abf3aae9cf1a207c768101e80e472925d16ce8f02e761573dac82", ++ input: "", ++ output: "", ++ }, ++ { ++ nonce: "ddfa69041ecc3feeb077cf45", ++ key: "2be077349f80bf45faa1f427e81d90dbdc90a1d8d4212c1dacf2bd870000bfdf", ++ input: "23dbad0780", ++ output: "415a3e498d", ++ }, ++ { ++ nonce: "496b2a516daff98da5a23653", ++ key: "254c12e973a3d14fbbf7457964f0d5ee5d18c42913cf9a3c67a3944c532c2c7c", ++ input: "f518831fab69c054a6", ++ output: "cfe40f63f81391484b", ++ }, ++ { ++ nonce: "9e7a69ca17672f6b209285b7", ++ key: "205082fc0b41a45cd085527d9d1c0a16410b47152a743436faa74ae67ae60bca", ++ input: "805fad1d62951537aeed9859", ++ output: "47bd303f93c3ce04bce44710", ++ }, ++ { ++ nonce: "b33dedcd7f0a77359bdeae06", ++ key: "ef2d6344a720e4a58f2ac10f159ab76314e37d3316bf2fb857bc043127927c67", ++ input: "f4e8a7577affb841cf48392cf5df", ++ output: "f445c0fb7e3d5bfdab47090ddee6", ++ }, ++ { ++ nonce: "b1508a348092cc4ace14608d", ++ key: "a831bd347ef40828f9198b9d8396f54d48435831454aa734a274e10ddcc7d429", ++ input: "1179b71ec4dc34bd812f742b5a0b27", ++ output: "cc7f80f333c647d6e592e4f7ecc834", ++ }, ++ { ++ nonce: "034775c821c58891a6e88cac", ++ key: "ed793ce92b1689ce66836a117f65dcec981dc85b522f5dffbb3e1f172f3f7750", ++ input: "7bd94943d55392d0311c413ac755ce0347872ba3", ++ output: "c43665de15136af232675d9d5dbbeca77f3c542a", ++ }, ++ { ++ nonce: "cb55869aa56e9d6e5e70ad5d", ++ key: "b3d542358ffd7b1ff8ab3810ece814729356d0edbd63e66006d5e5e8a223a9ee", ++ input: "1505f669acc5ad9aaa0e993ba8c24e744d13655e1f", ++ output: "26cad1ccf4cf4c49b267ab7be10bc2ffa3ba66bc86", ++ }, ++ { ++ nonce: "a42c203f86fc63000ea16072", ++ key: "d6b18ae2473d3be8ca711267ffbc77b97644f6a2b4791d31d0910d180c6e1aec", ++ input: "20070523ddb4ebf0d5f20fd95aacf47fb269ebadda6879638a", ++ output: "5ce972624cb2b7e7c28f5b865ba08c887911b4f5e361830a4b", ++ }, ++ { ++ nonce: "ea7186cf2fdf728d8a535a8b", ++ key: "bba26ce4efb56ad06b96e2b02d0cdd549ad81588a9306c421e0f5b0175ae4b25", ++ input: "d10f8050c1186f92e26f351db36490d82ea677498562d8d4f487a0a4058adf", ++ output: "f30c11bc553b2baf6870760d735680897c9fee168f976b2a33ef395fdbd4fc", ++ }, ++ { ++ nonce: "3a98bed189a35a0fe1c726fa", ++ key: "a76d5c79dcaab18c9a3542a0272eea95c45382122f59bcaa10e8910371d941f6", ++ input: "e88dc380b7d45a4a762c34f310199587867516fac4a2634022b96a9f862e17714d17", ++ output: "aac98ba3821399e55a5eab5862f7f1bfc63637d700125878c2b17151f306c9aec80e", ++ }, ++ { ++ nonce: "b8f4f598731d183f2e57f45b", ++ key: "f78c6fa82b1ab48d5631e0e0598aad3dbad1e4b338fbf6759d7094dbf334dbc3", ++ input: "b0fcf0a731e2902787309697db2384e1cda07b60002c95355a4e261fb601f034b2b3", ++ output: "b6c8c40ddda029a70a21c25f724cc90c43f6edc407055683572a9f5e9690a1d571bb", ++ }, ++ { ++ nonce: "18ae8972507ebe7e7691817d", ++ key: "a0076c332ba22e4a462f87a8285e7ba43f5e64be91651c377a23dcd28095c592", ++ input: "cf9ec6fa3f0a67488adb5598a48ed916729a1e416d206f9675dfa9fd6585793f274f363bbca348b3", ++ output: "bb7ed8a199aa329dcd18736ce705804ffae8c3e2ba341ae907f94f4672d57175df25d28e16962fd6", ++ }, ++ { ++ nonce: "de8131fd263e198b99c7eb0b", ++ key: "2e4c1a78e255ab2743af4a8101ab0b0ae02ce69dd2032b47e818eedf935b858b", ++ input: "be9a8211d68642310724eda3dd02f63fcc03a101d9564b0ecee6f4ecececcb0099bb26aabee46b1a2c0416b4ac269e", ++ output: "3152f317cf3626e26d02cff9392619ea02e22115b6d43d6dd2e1177c6bb3cb71c4a90c3d13b63c43e03605ec98d9a1", ++ }, ++ { ++ nonce: "f62fb0273e6110a5d8228b21", ++ key: "3277fc62f46cf0ced55ef4a44f65962f6e952b9ff472b542869cb55b4f78e435", ++ input: "495343a257250f8970f791f493b89d10edba89806b88aaaeb3b5aefd078ba7b765746164bce653f5e6c096dd8499fb76d97d77", ++ output: "62c01f426581551b5b16e8b1a3a23c86bcdd189ab695dbea4bf811a14741e6ebbb0261ef8ae47778a6be7e0ef11697b891412c", ++ }, ++ { ++ nonce: "637ab99d4802f50f56dfb6f2", ++ key: "8f7a652b5d5767fe61d256aa979a1730f1fffcae98b68e9b5637fe1e0c45eab4", ++ input: "e37fbbd3fe37ce5a99d18e5dcb0dafe7adf8b596528708f7d310569ab44c251377f7363a390c653965e0cb8dd217464b3d8f79c1", ++ output: "b07d4c56fb83a49e8d9fc992e1230bb5086fecbd828cdbc7353f61b1a3cec0baf9c5bf67c9da06b49469a999ba3b37916ec125be", ++ }, ++ { ++ nonce: "38ecdfc1d303757d663c3e9a", ++ key: "e7d8148613049bdefab4482a44e7bdcb5edc5dad3ed8449117d6d97445db0b23", ++ input: "9efab614388a7d99102bcc901e3623d31fd9dd9d3c3338d086f69c13e7aa8653f9ce76e722e5a6a8cbbbee067a6cb9c59aa9b4b4c518bbed", ++ output: "829d9fe74b7a4b3aeb04580b41d38a156ffbebba5d49ad55d1b0370f25abcd41221304941ad8e0d5095e15fbd839295bf1e7a509a807c005", ++ }, ++ { ++ nonce: "1c52e2c7b4995479d76c94c7", ++ key: "74e7fc53bf534b9a3441615f1494c3a3727ca0a81123249399ecae435aeb6d21", ++ input: "03b5d7ab4bd8c9a4f47ec122cbeb595bd1a0d58de3bb3dcc66c4e288f29622d6863e846fdfb27a90740feb03a4761c6017250bc0f129cc65d19680ab9d6970", ++ output: "83db55d9eb441a909268311da67d432c732ad6bda0a0dae710d1bce040b91269deb558a68ced4aa5760ca0b9c5efc84e725f297bdbdadbc368bea4e20261c5", ++ }, ++ { ++ nonce: "a1f0411d78773b7ca5ee9169", ++ key: "393e211f141d26562c7cfc15c5ccfe21c58456a9060560266bc0dcdab010c8f2", ++ input: "2f4da518578a2a82c8c855155645838ca431cdf35d9f8562f256746150580ca1c74f79b3e9ae78224573da8b47a4b3cc63fbed8d4e831a6b4d796c124d87c78a66e5", ++ output: "6fc086ded3d1d5566577ccd9971e713c1126ec52d3894f09ab701116c7b5abda959cbb207f4468eb7b6a6b7e1b6d2bc6047f337499d63522f256ee751b91f84f70b6", ++ }, ++ { ++ nonce: "2c029f74b0da21a052228c64", ++ key: "b0e7aca1a10e7a56b913af52080ca3cb746d7ae039ca3b5c07acb285c0afb503", ++ input: "55739a1738b4a4028021b21549e2661b050e3d830ad9a56f57bfcaca3e0f72051b9ca92411840061083e5e45124d8425061ab26c632ac7852118411ac80026da946357c630f27225", ++ output: "8051bf98f8f2617e159ba205a9342ab700973dd045e09321805eed89e419f37f3211c5aa82666b9a097270babc26d3bfe0c990fe245ae982a31f23cfbf6156b5c8cfb77f340e2bf5", ++ }, ++ { ++ nonce: "a86bc1234ecdd19fcb4e22cb", ++ key: "4a4094b698f1b586ff1bfd10544ea81309e521ab64d74374f1b33109f2876e68", ++ input: "7ffd8d5970fdee613eeae531d1c673fd379d64b0b6bfedd010433b080b561038f7f266fa7e15d7d8e10d23f21b9d7724bb200b0f58b9250483e784f4a6555d09c234e8d1c549ebb76a8e", ++ output: "c173617e36ea20ce04c490803b2098bd4f1ff4b31fdca1c51c6475ade83892c5f12731652d5774631d55ae2938617a5e9462bb6083328a23a4fba52de50ca9075586f2efc22aae56e3a8", ++ }, ++ { ++ nonce: "296f5fd61962f7f39e3c039a", ++ key: "c417a0eb1a42e06917239e44118a85293a52c8d0a2c9b0a884cab20a451a01af", ++ input: "7a5766097562361cfaeac5b8a6175e1ceeeda30aec5e354df4302e7700ea48c505da9fdc57874da879480ecfea9c6c8904f330cbac5e27f296b33b667fea483348f031bef761d0b8e318a8132caa7a5943", ++ output: "5e9fbf427c4f0fcf44db3180ea47d923f52bee933a985543622eff70e2b3f5c673be8e05cd7acbcadd8593da454c60d5f19131e61730a73b9c0f87e3921ee5a591a086446b2a0fadd8a4bc7b49a8e83764", ++ }, ++ { ++ nonce: "6ee50ec741ec580e616fd9af", ++ key: "bbf22a177cd285904dc4a28cda48a18ab0880c29397418888147d518ce2c3f63", ++ input: "0777c02a2900052d9b79f38387d2c234108a2ad066cbf7df6ea6acc5a3f86b3d6156abb5b18ad4ecf79e171383a1897e64a95ecdbba6aa3f1c7c12fe31283629ff547cb113a826cb348a7c10507cc645fa2eb97b5f22e44d", ++ output: "368c90db3464ba488340b1960e9f75d2c3b5b392bdd5622ff70e85e6d00b1e6a996ba3978ce64f8f2b5a9a90576c8f32b908233e15d2f443cccc98af87745c93c8056603407a3fb37ce0c1f8ab6384cc37c69c98bfecf337", ++ }, ++ { ++ nonce: "79da06301d054827dc7cc172", ++ key: "e8b7cd6028e9cbceb97a9be13715d63099c1fba0bf387789a90577dd63175c3e", ++ input: "cf2dccbcfd781c030376f9019d841ca701cb54a1791f50f50bee0c2bf178182603a4712b5916eebd5001595c3f48283f1ba097ce2e7bf94f2b7fa957ce776e14a7a570093be2de386ececbd6525e72c5970c3e7d35974b8f0b831fbc", ++ output: "7c92b8c75e6eb8675229660cedcb10334965a7737cde7336512d9eff846c670d1fa8f8a427ea4f43e66be609466711fd241ccff7d3f049bda3a2394e5aa2108abc80e859611dbd3c7ba2d044a3ececa4980dd65e823dd110fea7a548", ++ }, ++ { ++ nonce: "eeb10ffc0ac64c4167bd4441", ++ key: "c6913210b6032b8248b59ad2fe3e8fc86a0536691fa6aa285878dfa01935a2da", ++ input: "e08a8949a1bfd6a8c1186b431b6ad59b106ae5552821db69b66dc03fbc4a2b970dcf9c7da4f5082572bc978f8ee27c554c8884b5a450b36d70453348cd6cac9b80c9900cf98a4088803f564bb1281d24507b2f61ba737c8145c71b50eb0f6dfc", ++ output: "73d043acf9dcd758c7299bd1fd1f4100d61ff77d339e279bfbe6f9233b0d9afa24992a9c1c7a19545d469fdfb369c201322f6fe8c633fcdcffef31032bfb41b9fb55506e301d049fd447d61f974a713debeaed886f486a98efd3d6c3f25fbb30", ++ }, ++ { ++ nonce: "570c03c2e1593b1e1ade7e60", ++ key: "b5c2bad18345a9569b478b621ea556308f8fbf693de0f12dd2489d4b79c3f57d", ++ input: "a0c302120111f00c99cff7d839cdf43207a7e2f73d5dd888daa00d84254db0e621a72493480420c9c61ce1cfc54188ff525bb7a0e6c1cd298f598973a1de9fd2d79a21401588775b0adbe261ba4e4f79a894d1bd5835b5924d09ba32ef03cb4bc0bd6eb4ee4274", ++ output: "bc714bd7d8399beedc238f7ddeb0b99d94ad6bf8bf54548a3e4b90a76aa5673c91db6482591e8ff9126e1412bce56d52a4c2d89f22c29858e24482f177abacef428d0ae1779f0ae0778c44f9f02fe474da93c35c615b5fad29eca697978891f426714441317f2b", ++ }, ++ { ++ nonce: "1fc84df4e7036ecf966796f4", ++ key: "f4127b0d89473f68b48f82c7a0c60f82eb3112c5d71667e493ef36406cb9af26", ++ input: "ebce290c03c7cb65d053918ba2da0256dc700b337b8c124c43d5da4746888ca78387feea1a3a72c5e249d3d93a1907977dd4009699a15be5da2ca89c60e971c8df5d4553b61b710d92d3453dea595a0e45ae1e093f02ea70608b7b32f9c6aadc661a052f9b14c03ea0117a3192", ++ output: "cbb8c4ec827a1123c1141327c594d4a8b0b4a74b0008115bb9ec4275db3a8e5529a4f145551af29c473764cbaa0794b2d1eb1066f32a07fd39f5f3fe51498c46fba5310ae7c3664571d6a851e673ded3badc25e426f9c6038724779aa6d2d8ec3f54865f7df612e25575635ab5", ++ }, ++ { ++ nonce: "1b463e8d60c3057eddafbb3b", ++ key: "c917b9f9f79bf89ac9bbec7d7beae5e755ab4a9bbef6ef90906d9ba11a9bf6b9", ++ input: "275c97de985aa265332065ccce437770b110737a77dea62137a5d6cb62e9cb8b504d34334a58a71aba153d9b86f21377467b2fafaf54829331bf2ce0009acb37842b7a4b5f152aab650a393153f1ed479abc21f7a6fe205b9852ff2f7f3a0e3bfe76ca9770efada4e29e06db0569a99d08648e", ++ output: "b225aa01d5c438d572deaea51ac12c0c694e0f9dc0ed2884a98e5e2943d52bb4692d7d8f12486de12d0559087e8c09e4f2d5b74e350838aa2bd36023032ccbcae56be75c6a17c59583d81a1fd60e305af5053ac89f753c9347f3040e48405232dc8428c49dcb3d9b899145f5b3bc955f34dbbe", ++ }, ++ { ++ nonce: "f5331f87bae3fee4931e8ccb", ++ key: "03491233e587027e8f98d6e95f406219b5c1215fe695c62ac900b246ba98da9f", ++ input: "ceda15cfffd53ccebe31b5886facd863f6166e02ec65f46f54148860a5c2702e34fd204d881af6055952690cd1ffa8ba4d0e297cc165d981b371932adb935398c987baff335108c5e77f2e5dd5e1ca9a017bc376cbdbe3c0f45e079c212e8986b438444e79cd37927c1479f45c9e75b0076cc9f8679011", ++ output: "a3f1c3f885583b999c85cd118e2ababfa5a2de0c8eb28aacc161b1efee89d8de36ddeb584174c0e92011b8d667cb64009049976082072e6262933dbf7b14839805e1face375b7cbb54f9828ba1ed8aa55634ec5d72b6351feff4d77a3a22b34203b02e096f5e5f9ae9ad6a9dd16c57ce6d94dcc8873d18", ++ }, ++ { ++ nonce: "e83c55efea20e1df3a7e049a", ++ key: "c179f4be8b4f555989f097bf1e6f315228e4410104dc26ff578f0ce1598a56a7", ++ input: "799bb2d634406753416b3a2b67513293a0b3496ef5b2d019758dedaaac2edd72502fc4a375b3f0d4237bc16b0e3d47e7ddc315c6aef3a23fcae2eb3a6083bc7ac4fd1b5bf0025cc1cb266b40234b77db762c747d3a7b27956cf3a4cf72320fb60c0d0713fa60b37a6cb5b21a599e79d0f06a5b7201aeb5d2", ++ output: "e84dfb3dbaac364085497aeabd197db852d3140c0c07f5f10e5c144c1fe26a50a9877649e88c6fe04283f4b7590a8d0d042ef577693f76f706e31c4979437590fe0ab03d89afb089d1be50ae173ea5458810372838eceac53bf4bac792735d8149e548efb432e236da92bf3168bbcf36f644c23efb478a4e", ++ }, ++ { ++ nonce: "a02481d9aa80cd78fc5cc53d", ++ key: "416e2802e3383ef16b4735f7fc4bc433978797d795459c4a13040806d8fd9912", ++ input: "b2d060bd173955f44ee01b8bfcf0a6fad017c3517e4e8c8da728379f6d54471c955615e2b1effe4ce3d0139df225223c361be1cac416ade10a749c5da324563696dae8272577e44e8588cd5306bff0bfbdb32af3ac7cbc78be24b51baf4d5e47cf8f1d6b0a63ed9359da45c3e7297b2314028848f5816feab885e2", ++ output: "ffa4aa66dd5d39694ae64696bfa96f771accef68f195456ad815751e25c47ed4f27b436f1b3e3fcaa3e0d04133b53559c100cd633ced3d4321fc56225c85d2443727bce40434455aa4c1f3e6768c0fe58ad88b3a928313d41a7629f1ce874d2c8bcf822ebdaebfd9d95a31bb62daab5385eb8eefe026e8cbf1ff7a", ++ }, ++ { ++ nonce: "0f6b105381fd11dff3b6d169", ++ key: "38b1360794e1cd55c173820fe668c2f7d52b366155b43cbbfcc9d344fdd3567d", ++ input: "4f0171d7309493a349530940feece3c6200693f9cff38924114d53f723d090fffa3c80731b5ca989d3e924d1fa14266632cb9ab879e1a36df22dc9f8d1dadea229db72fded0c42187c38b9fa263c20e5fb5b4aa80eb90e8616e36d9b8c613b371c402343823184ecad3532058a46cf9e7ea5a9ecad043ac3028cbcc3f36d32", ++ output: "88c773ff34b23e691e14018ba1b2bd48a4a6979b377eb0d68336ce6192dcd5177e6b4f1c4bea2df90af56b35fe2a1d6279d253c0194dcbca9bf136f92d69165b216e4c9d1ce6b3fbe40c71e32c3f4088de352732d0e2bad9c16fd0bb9bde3d6c30257ce063432d09f19da79d49aa7641124a6c9e3f09449e911edbae11a053", ++ }, ++ { ++ nonce: "bdff905e73f198a8889a9f26", ++ key: "5fe044529bbeadf9ac549f9e46004623eacd8267962c98ba6b5021c7e3f710ed", ++ input: "8f8d9e18d3212bd20b96d75c06d1a63622fd83d13f79d542e45996135368772ea81511302a0d87e246dd346314cfe019bae8a5c97f567f12d82aca98dfea397c6a47dd0c419f1c609d9c52dcfcbe7eee68b2635954206ed592b7081442ce9ce3187d10ccd41cc856fb924b011f817c676c9419f52a2938c7af5f76755a75eb065411", ++ output: "4e130c5df384b9c3c84aa38a744260735e93783da0337ade99f777e692c5ea276ac4cc65880b4ae9c3b96888760fdddb74bc2e2694bedf1ee6f14619c8015f951ba81b274b466e318d09defe80bdbed57bc213ac4631d2eb14c8e348181d60f6295ceee1e9231ae047830ef4778ff66146621b76974773b5d11c8e17a476450f46ef", ++ }, ++ { ++ nonce: "e8398e304ff1a49a96db11f5", ++ key: "19523b8388e5824b2c652d4bd76e8f7c63e84bfee5503a9d9b0988b868198d9f", ++ input: "30d2379dd3ceae612182576f9acf6de505ab5a9445fe1a86ae75c5c29429e11c50fd9ec657b29b173a3763b1e171b5a7da1803ba5d64fccb2d32cb7788be194dbca00c3c91774c4c4c8ede48c1027d7cc8b387101a4fe5e44a1d9693b2f627626025072806083aadbced91c9711a0171f52ffb8ed5596cf34130022398c8a1da99c7", ++ output: "b1e8da34ad0189038ee24673979b405ef73fdbdd6f376f800031d64005a4ebed51a37f2180571223848decbea6dd22b198ab9560d7edc047c5d69183dc69b5fca346911d25cb2a1a9f830dc6382ad0024e8c3eef3aa2d155abcfe43bff01956a5e20a862fbed5c5e8df8eed0601a120caac634b068314e221f175baa11ae29002bb9", ++ }, ++ { ++ nonce: "5acafea5b4c13a750966a4c5", ++ key: "5948bfabf69b8d826daaf7f7a28c2025adc0a4d78232dd2fc2b8fc2b4bd88983", ++ input: "d9404ccdcc8ef128a1b1ace4f9f1669d274ec82aa914cac34b83ac00b236478fd6167e96ec658850c6c139eb0f6fc0dd7191ba9a39828032008f7f37eb9a8df9d6cdd54240e600efe7fc49a674000c5030d825b2c5c96d0f19b8ecdbf4eeb86d3e569c5e3131abc7d6359dd4255284ccacf150d42e7a899536d51ee6db329654a4581c5ac6e419", ++ output: "c5534b5fb40b4834300e9577a9d87440c5272263d06e6aee84aa92cdf5d1b033145d336f26e5fe55c09a7e75753af93d0786dfc1cb435e86c67bd3ec8e766d0801b99e68691e2c3c3ffec539cf62e68285ea9027daa2716cd6f97e8eb7b9e266357a25eb2d4839a829508a6b7228f2832b3cd998f77597ae530430e6e4ecb53eb9efe456863a04", ++ }, ++ { ++ nonce: "4658aa126c4f608885950dc1", ++ key: "d6cc91149d552f60060c08d4bdfa0202f8f4d3ff174c14bf3c3fbf8875330808", ++ input: "231765f832927461f338aceb0f4cf51fd8469348c69c549c1dec7333d4aa4968c1ed58b65ab3fe3d0562600a2b076d56fd9ef91f589752e0455dd1d2e614cacfc0d757a11a4a2264bd38f23d3cca108632201b4f6c3b06477467726dde0c2f3aee01d66d788247663f1d0e66b044da9393ede27b9905b44115b067914961bdade85a2eca2844e1", ++ output: "1dd35f3f774f66d88cb7c2b23820ee078a093d0d85f86c4f103d869f93e2dbdd8a7cb8f101084fe1d7281a71754ec9aac5eb4fca8c365b24ed80e695caace1a8781a5a225938b50b8be96d0499752fdabd4f50d0b6ce396c6e2ca45308d1f2cc5a2a2361a8ca7a334e6ee62d466d74a1b0bf5b352f4ef6d8f8c589b733748bd3d7cda593243fab", ++ }, ++ { ++ nonce: "f0709d1c67a388a02b4dc24e", ++ key: "75974e4952a8070d4af28aaf5c825bc68067e0c5cebafb17b5711d65efd848f5", ++ input: "e46841f12d98aeb7710b9162d342895a971b0e3a499886bbb6aa74dc744a28d89a54542b628acdc2f693cb7c03f73fc3b74069bc3f2d000a145fb8a806cdc7d6fa971da09a33b92851cc3d1f6f5646d7fa2b1d564876feefeb63b6e66dba1c0b86ca345235bb822e0f93132346840d2a3d6eb1b541178ea51affc7b31f8da02732cc4e5bcb5d8683ae0a91c9", ++ output: "1dcbfd0bb2b905656c52bd7b1bcdad9b4d434ae9ac221a0d3a316115cdd4a463fa9b3444d2612a4e277d0dcd881fa6e80e59e5a54e35e1a14747aed31edf4ac24214f9d9c329ebe2157620b64efaded9976549bc4aa100d5c15be3f85f700f8a21dfe77590dfee2de9a23cc1ed1e44f32ebf68ca289b097bc13b42802dc7c75309c4afc25b5741839f7db3d5", ++ }, ++ { ++ nonce: "8b7b06236d6c275b606ccaae", ++ key: "8844d62973293a89efb4e332d4d5f32a1bc05e094cb605c87d8b4e8862708d79", ++ input: "e98e4a9550bdd29e4106f0cc8669dcc646a69438408e9a72c7cdb9b9d437b5f7a13fcb197629541c55bca1f8972a80cd1c1f591a0e24f977cdeb84763eab2648e42286e6473ea95e3a6a43b07a32b6a6cd80fe007ba0cf7f5ac7e651431f5e72690ec52a7134f9757daf0d8eff6b831a229db4ab8288f6bbf81e16fedebe621fd1737c8792cfd15fb3040f4f6a4cbc1e", ++ output: "5c69cf522c058790a3bc38979e172b60e71f7896d362d754edc1668d4f388b3fc0acdf40786d2f34886e107a142b1e724b9b9b171cb0e38fd78b35f8ac5269d74296c39c9f8628d848f57af9d8525a33f19021db2b9c64ba113171ebb3882075019ec7e77b51ce80b063ed41d48dad481d9536c030002a75d15c1c10ce0ec3ff17bc483f8416055a99b53035f4b6ea60", ++ }, ++ { ++ nonce: "5896072b85daf5bd0d45758a", ++ key: "a3eac94919880462a5cfaa9bdcad7038e182c605f3fff9f44b8e84a3c1ebc10a", ++ input: "ce0f0d900dd0d31749d08631ec59f216a1391f66a73bae81d3b0e2919a461bc9a14d6a01b827e3bcb55bbccf27c1ed574157e6becd5cf47181a73c9d3e865ab48a20551027e560e965876b0e1a256bfa5cb5179bf54bd8ec65e5570e374b853b37bf4b3ef1ec612d288ebc19275fa88da9419e012f957f9b6a7e375b3377db0eb3619c731aebfeb0930772b4020d3a3e90723e72", ++ output: "b06981b57fe184091ef9f8ccf522a5bcdb59bf9a68a3ddb817fdd999a6ecf81053a602141cf1b17017bae592b6b6e64756631a2b29a9e1b4f877c8b2ae30f71bc921e4f34b6f9cd8e587c57a30245f80e95005d0f18f5114400785140e6743da352d921fb4a74632a9c40115ad7706263ac9b41a11609fa0c42fc00f8d60931976162598df63ebad9496dd8943d25a03fa47475c", ++ }, ++ { ++ nonce: "b88a8e097be7d884415830bb", ++ key: "3cf9b5468d77b2c88f27c52c4c90a3d24f5dce06e859440c305ca30402dcea2f", ++ input: "eccfd66bdc691478f354b8423d6a3f20932a1f591d8e6cefa734975fb8ee6881b6dc92c0d1d5ed54fd1999efd7f11ac697a1f130587dd895eb498c9a8fc7d1714c385ec156ecae3bdea2a3462834245e724531d0fedda2b77693a53ed7354b758e875b23cfc83219a091fb2076e7a88cd77f779ed96f8d81ffa3fe5059303ac706086494b9f2982f4f88a0c6fadc3748625004db", ++ output: "925529047d4177b72bf50905ba77e47608815522c1829b24046e439d5451901257903a5409fb910373167e8b7f4fdfa543a477608ddfc11bbd1efc138366961463b9915b302a346b795dd593f6fcf4fa73529b6fe83079552aabbe99474a72806f59688d826675fa7f6649b9f5307e5028853c9821b8c4a1a0fc4bfdc7c8c78b25aeaba2b5821d17b36317381a3bd578917d2504", ++ }, ++ { ++ nonce: "4a6e2a2e8a486d9ab66c96f9", ++ key: "ff3b90583f17bec2b52861e253afb6b6eb8e2f093633cf38fb90df7f374be27a", ++ input: "f0c7139c69413869bca980d7f192b2bc3f57e34ca4f26164e1a54a234e84e1aa285cc02cfbaef3dfba2dbb52a555ec1f6ef0e89d0b2f0bd1846e65b74444b5f003a7308965e67bed558689be2668ca10ca368fac072e0e4535a031af23b3c37c561e185872b86c9bceddb5c1199e43fb5f735384766d33710460b541b52d3f5b6c108c08e76724bcac7ad2d866a8bbeeea92a3d867660d2e", ++ output: "d2c16c7a242b493038203daec65960de384c030eb698ef6a53c36eabb7556cbfa4770eaa8bc0a2b385ad97495eeb1c03ff4e6efcb804aefa81c177dc62700a9eefe6e8dd10cff5d43a2f47463cab5eb1ee260c3826cac9bfa070f1e0435541a89ebd224d13cc43f8fff12f38091c2b3f2102d5c20d8b1c3ae4f129364bbe9f9ce2147dcf0639668ddb90dffe6a50f939f53fa7ba358e913f", ++ }, ++ { ++ nonce: "98013e248c44840860e7319a", ++ key: "bc17e037902e1e9baa9d6715ee234af9fe6da80d4ca8eec3999719dd92fbef6e", ++ input: "7024974ebf3f66e25631c0699bcc057be0af06bc60d81a7131acaa620a998e15f385c4eaf51ff1e0a81ae5c6a7442d28a3cdc8aeb9701055e75d39ecac35f1e0ac9f9affb6f9197c0066bf39338a2286316e9d1bb7464398e411da1507c470d64f88d11d86d09e6958fa856583ace697f4ee4edc82618662cb3c5380cb4ce7f01c770aab3467d6367c409a83e447c36768a92fc78f9cbe5698c11e", ++ output: "ff56a3a6e3867588c753260b320c301ce80de8c406545fdd69025abc21ce7430cba6b4f4a08ad3d95dc09be50e67beeff20d1983a98b9cb544b91165f9a0a5b803a66c4e21bd3a10b463b7c1f565e66064f7019362290c77238d72b0ea1e264c0939d76799843439b9f09e220982eb1dc075d449412f838709428a6b8975db25163c58f40bf320514abf7a685150d37a98bac8b34ccb5245edb551", ++ }, ++ { ++ nonce: "6d864ed2d8259dc5f123f6fc", ++ key: "a0cc325fc5ca6741ee4349c0eca17f50c0df8fad2dfa66624153f0223e147480", ++ input: "8d79329cf647e966fde65a57fc959223c745801c55312046b791671773cca0af4cd48ead1f316eba0da44aa5d18025eced0c9ed97abaabb24570d89b5b00c179dca15dbae89c0b12bb9e67028e3ae4d6065041b76e508706bec36517a135554d8e6ef7cf3b613cbf894bec65d4dc4e8cb5ca8734ad397238e1e5f528fa11181a57dc71cc3d8c29f3aba45f746b1e8c7faace119c9ba23a05fffd9022c6c85260", ++ output: "60aea840869f7be6fcc5584b87f43d7ba91ed2d246a8f0a58e82c5153772a9561bdf08e31a0a974f8a057b04a238feb014403cd5ffe9cf231db292199198271f9793c9202387f0835a1e1dc24f85dd86cb34608923783fd38226244a2dd745071b27d49cbffebea80d9dacad1578c09852406aa15250de58d6d09cf50c3fcfff3313fac92c8dad5cb0a61ccc02c91cecee3f628e30c666698edecf81831e55ec", ++ }, ++ { ++ nonce: "4710b63001f90c812415684d", ++ key: "d07614e58d0098df9ee6df596691b30d4a4a1e6c5e1676fb85f1805135fb5973", ++ input: "85484293a843d2d80b72924b7972dfa97cbe5b8c6bcc096f4d5b38956eb3f13f47b02b0f759ea37014ecdecfb55f2707ef6d7e81fd4973c92b0043eac160aaf90a4f32b83067b708a08b48db7c5900d87e4f2f62b932cf0981de72b4feea50a5eb00e39429c374698cbe5b86cf3e1fc313a6156a1559f73c5bac146ceaaaf3ccf81917c3fdd0b639d57cf19ab5bc98295fff3c779242f8be486ba348bd757ba920ca6579be2156", ++ output: "bb1650260ef2e86d96d39170f355411b6561082dcc763df0e018fdea8f10e9dc48489fb7a075f7f84260aecc10abcfadbc6e1cd26924b25dedb1cc887ada49bb4e3e02006bdd39098ef404c1c320fb3b294ded3e82b3920c8798727badfb0d63853138c29cf1ebf1759423a1457b3d2c252acf0d1cde8165f01c0b2266297e688ff03756d1b06cb79a2cc3ba649d161b8d9ef1f8fb792bd823c4eabb7fb799393f4106ab324d98", ++ }, ++ { ++ nonce: "be0c024290af62adcd539e02", ++ key: "9520adab77c41e60a123c93b1adede1e5523613358485b281467fdd3c3bcf4e0", ++ input: "a2fc6e1b5281a4e0330eecd1ab4c41670570423173255979953142b78733b2910fa5540e8294208df6ae4f18672d5ac65acf851bcd394e1932db13c81b21e6f165e5538aff862e46126c650bbe055e54b31c78f2f0221d2631d66ef6d3f4c5ae25eada043b74d8770e2c29799c0954d8ccbd17766b79e6e94e88f478db3566a20cb890846917591a07738328d5c05f7ed4695a82607660f1239661faa9af0368aeb89726f13c2aaecf0deaf7", ++ output: "d8fe402a641c388522842385de98be60f87d922c318215947d4b7562d4ca1e2dbc7ee86494e65fb0bfddfdebdb2ae6469312f95b32c722b2720d64bb8d7cc3dd82f9055b1d89f05b77984f91f94ba4ac79c5129cd7c91cc751b0defc3f2799518e372d27aa683f1e7bbd4f55414c48fe8a3a37ac1f179a1a329cda775aec0d31d75a5a38addb1de67c06bddbedf4c8d87abc18c9f9dd072d457ea29ad4dfb109ce7e99a4a82fbe330b0afbb5", ++ }, ++ { ++ nonce: "8f1c02a8c4027a6693b6687a", ++ key: "c801e4ec475a80faca2f576d0c781c9ce5457564114cefd7461edc914e692aba", ++ input: "480387bc6d2bbc9e4ced2448d9ec39a4f27abe8cfb46752d773552ad7808a794058962b49e005fef4e403e6a391d1d3f59025eeb5fb8fbbe920f5361862c205d430eac613cd66108f2f2f0bd4d95a8f6ca7bd1f917eaeb388be87d8b7084a2eb98c575034578edf1b3dafff051a59313873a7be78908599e7e1c442d883d3fd3d26787eb7467eed3a3fb2d40046a4460d5d14215565606bcf8b6270af8500e3504d6d27dacf45bace32214472d525fdc", ++ output: "ab81a9c28358dfe12e35a21e96f5f4190afb59214f3cf310c092ab273c63cd73a783d080c7d4db2faccd70d1180b954cd700c0a56b086691e2c2cd735c88e765e2266cd9ebe1830d63df4b34e2611a8abeeca9c8c4fac71135dafb1cb3569540ed1362ddeb744ed62f6fd21de87b836ec2980f165c02506e0c316ae3cf3d18a862954d9781f726ecc1723af4a730ccc6d6de82553450a52499acb58fb2008969401c45b2f20e12b58f308db1d199b4ff", ++ }, ++ { ++ nonce: "7c684e41c269fcc6d312cad3", ++ key: "ca1cb501af5584bc4248903f52b4426064d14dcdf0f383da72b904ff0edd72f9", ++ input: "b274e61059f3215173ae226e30a92ee4b4f8a3da95f2e768e3fac2e54ddac92c200c525f190403a6ef9d13c0661c6a7e52ed14c73b821c9680f1f29711f28a6f3163cf762742ed9474dbea51ff94503a5a404adbbdfbf4c6041e57cb14ea90945dc6cb095a52a1c57c69c5f62ac1a91cd8784b925666335bbfee331820b5f7470bc566f8bbb303366aafe75d77c4df5de2649ed55b2e5e514c3cb9f632b567594a0cf02ec6089a950dbe00554ee4dfb9", ++ output: "a0969730d48ee881792a3927b2f5d279aba9f2ed01e6b31b92d0e1fb8ba7f35a236d838e0ce5f8654957167de864f324c870864b4e7450a6050cd4950aa35e5a1a34a595e88dd6f6396300aff285de369691b6e0e894106dc5b31525e4539c1e56df3ceedbbab1e85da8c0914e816270a4bae3af294b04a3ea6e9ef7e2aab4da5f5370df2706b5e3f000d88179ac756deaa652a1cc85e80ad9622f1bf91a2776262eb7289846d44f7f8192e763cb37aa", ++ }, ++ { ++ nonce: "1d5c31dd98da35230fdaa0e0", ++ key: "d6c71964420f340db8f4f27a42cf3635fbc6682f5f859dac90d4c407b1b11197", ++ input: "ee849039c6cd972dc943d2a4468844d130c0150276f4e0889047e2300c3ecc6792c4527bfe9437dad877eb986e6b1aa9b867d1798c9d314243f0a87ec9ee5b601c2554876c87cbf50df3334a077c4152f8b8fef4a2d301ddbfa90c887ece757c3eb6c4fc1e0212d6b5a8bb038acaec28cba064c9b34f5364cb7f0fc2ac4ef2c7ddde0f5ba17014459eaa78f08a46a01882ebf7c6e409dadda250bb899dc8b3b70e160bbcb4412a9963b174d0fc6bc16383a46ffaacb6e0", ++ output: "3e272ded9c0a5cebe7cf17ac03f69eb20f62996e047501b6cc3c8691ddb2780ea72c21a81888bfea96e4373a412c55ca95648390de740102d661143043baec3976230e024477d134b8504a223c36a215b34164c9e9e1fa99a49fdc56f2f04ea525a6b82997d9bbc95c4b5baeab4dec50061efb7c1a757887acb8b47b142e0a2e61885a2c14c4642d83d718a0546b90699adc545a48129603862a1c89d8e665cde54b3ba487754db6d6f5acf6a4b95693cc569577a2dc48", ++ }, ++ { ++ nonce: "7c4fb4ebddc714af7acd4345", ++ key: "7719e70c860e7999dcd61065e78a96379afb17295ff29e0185d082d243d02861", ++ input: "0992396a6f29b861dd0bc256e1d1b7dce88435733506a6aa20c62e43afa542d1c46e28b2e6d8e2eacb7c08db05e356fe404684b0e3a9849596db82eb788aa09258c28eb19e9838f757425b4edef12deeca56e30cf030272e325d4246d6e083219b2f965124963ca91f066d47bf5a8282a011a78b0155aa70038259a4a59135f241fd2f88c908b9f4eef7b7df0f3a1c16a52c009b522f89dabd52601bbf6e3ce68732e1a6d444469480f06da218786cf6c9666362e7a7f7be12", ++ output: "545c05a84b5a4fffd1dd623c8f2b11443818560bdb0c26dadd3b694d4790d294b99059f4127b7cca122c4000954d745af96094ff4623f60db33e994bb6903263d775f48d7047427b3a498c2ecde65bd37bcb8ee7e240a1e08c884c0079cab518f4e1c38ba5ea547f4da83b7c6036e4259bee91c42e8fae895df07781cc166f1d50e1550a88ee0244bb2950070714dd80a891aa8a9f0580a67a35cb44609b82a5cc7235f16deea2c4f3667f2c2b33e8eeef944e1abdc25e48fa", ++ }, ++ { ++ nonce: "9071cb35869a2e21e43c42bc", ++ key: "dece19faf2e86a57ab5d05585d35b3911a50d269c223637385136c2657454f13", ++ input: "3b9efcbbb607fad5e9f1263dad014cc5c2617d439fcd980408f4f9a93acb1a33d1c3a22f38c037e4603dfbbfb5571bc08c4a1958cbbf510e3e4dd19007fe15fad7808369149a9c4db7ca0496f7a600a6f2454ee1cffd5a68d45c270e4b53ac9b77f33a1ffbb1804244f57d2b05b8036fe2cda9efead3d4eff074ea5c07128e0b354a4a11ffa179163933bc6bd10d200804cc93b64575746e94e975f990bddcc8a4335e99e2459fbe9bc0e004ffcd6cac52f48ef55cc0637a75c1dc", ++ output: "631ba7301e33236da2477506ea98d3b732447389e849b68e1f09bd5fd814f40dc3247a1012fa654f08e3dda0c104ee2dff12ecf5cb018644de50d70dfb6c8cc1f5f552e5f1e50466bbb538ad6b98fd37f33fe615c326efc9cc97899b829b007f91569fa9b28ce0076c53daedf9cc0f838e22cf1125b86a6a2c2eb4a45dadea45ad00fb4f054e7d6b09c13ab1dd5328debfbf4f1b70af2b8a5b1d02df8a87d7661473e0c180ba4c815f14db87c5bdc15f11a29d8e0ce3d747d5dcd4", ++ }, ++ { ++ nonce: "ac41c9cc025ba4dbd67a0dab", ++ key: "5207759b0a0927a6f0957c963f2cfff87eb9be69c1990ba383dcdd0aaf9b3f44", ++ input: "f28a71efd95e963e5e0bc0fcf04d8768ce93cb55dc73c32e6496022e214596314b7f843f5c7b136a371c2776a0bfbdd534dccbe7f55e9d3d3b5e938f2d7e74393e4caf6c38fa4b05c948e31dc6a9126817fa3d7892c478f75ab9f6ab85c0e12091bd06e89c7d3ca8d9dcdd4c21fead3d769a253919c2c72dd068474ea322b7e71cafa31684e05a63e179e6432fb70661792cc626a5060cec9e506b35d9286f15dc53cc220b1826314eec337dd8e7af688e5950b2316c30516620569ea65aab", ++ output: "1bcea54b1bf4e6e17f87e0d16388abe49b988b9c785b31f67f49f2ca4011ecd2ad5283d52ef707dd3b803e73a17663b5bfa9027710e045a0da4237f77a725cf92792b178575456de731b2971718937dd0e9ea12558c3fa06e80bbf769e9799f7470db5b91476d6175f1a6d8e974fd505854c1230b252bb892a318e6d0c24dcc9ecb4861769cd746abab58805bc41c6086a6d22b951fba57b00c5b78f6dcb2831715b9d4d788b11c06086f1d6e6279cd130bc752218d7836abc77d255a9e7a1", ++ }, ++ { ++ nonce: "587c7e98949a83cc602e9530", ++ key: "6f284ae396d9dc4a12871697e8dd820ae54942010b81825ee845a4b4b0ad7995", ++ input: "c1d1ede73bd89b7c3d4ea43b7d49c065a99f789c57452670d1f92f04f2e26f4f5325c825f545016c854f2db2b3448f3dc00afe37c547d0740223515de57fd7a0861b00acfb39931dc9b1681035d69702183e4b9c6559fb8196acbf80b45e8cc5348b638c6d12cea11f6ef3cc370073c5467d0e077d2fb75e6bf89cea9e93e5cf9612862219ca743ef1696783140d833cd2147d8821a33310e3a49360cb26e393b3fee6dba08fcda38d1b7e2310ec1f715e3d8fa0c6b5e291eea07c25afd5c82759a834a89cc5", ++ output: "11a8493cdc495c179f0d29c2b4672997205a9080f596ee3c80d79b55162b1c875ac18eb94bf2a9e05b08024f524a1e9665912394a330c593d23260e6bdf87620c10a48f678693196fb744c49054182fba667c601e7b7ebf0f068e8d69ba004b804fda616a4a0d5350e1a3bd424b8266462be282308219c578569aefc1ccd09ecdf5da283356c9e524e14e69d25b0e19643dab26f54373a7272b43755c3f1ddaee6c5fb9e8e093110c41697e95f73a68c75454e050239197c9fbd8cec76698bd11894ebf6e2b2", ++ }, ++ { ++ nonce: "5a021f8500c8f3e63075ae85", ++ key: "47be0d2d65e405dab2b3f6429ee726708066449e76f91d69a23db2f7fa2134bb", ++ input: "37b2dc4b6a5203d3a753d2aeffcdaed5a7c1741ed04d755dd6325902128f63b6981f93c8cc540f678987f0ddb13aae6965abb975a565f0769528e2bc8c6c19d66b8934f2a39f1234f5a5e16f8f0e47789cd3042ca24d7e1d4ddb9f69d6a96e4fd648673a3a7e988a0730229512382caaded327b6bbbbd00a35df681aca21b186bc7ac3356d50889bbf891839a22bb85db4c00bfa43717b26699c485892eb5e16d1034b08d3afa61f3b5f798af502bba33d7281f2f1942b18fb733ca983244e57963615a43b64184f00a5e220", ++ output: "b68c7a2a1c8d8c8a03fc33495199c432726b9a1500bc5b0f8034ce32c3e3a78c42c1078e087665bd93c72a41df6bfa4e5beb63e3d3226aeeba686128229a584fab0c8c074a65cef417ad06ab1565675a41cf06bb0fb38f51204eccccb75edd724cdd16b1d65a272f939c01508f0385ca55ac68a0e145806317cc12e6848b1124943a6b2d99a8c92083fc5f31ab2e7354db3f8f2d783dbf1cfec9c54f8bfcb93d6f28ef66f18f19b0fab8836458e9b09bee742ba936cb2b747dd9dcf97ca7f6c82bf0af6f1b433592d65143fe", ++ }, ++ { ++ nonce: "7fd9bfae2d4483f51f2fab15", ++ key: "9bcfd1d3e68731e457a77150b4832a416f71273f88c4fd17ed771f2756b04b6c", ++ input: "68c2c5612912b5f994172720130dff092ee85a2c1395111efa64d5a281ca864d3db9600e685854d81c6de7e8747b92fb7c4c2efa829d3d4c0c9fc9d689e2e5c84c9eae8ba4ab536fb6c7523124b9e9f2997f0b36e05fb16163d6952eee066dd22fb7585925ffded0204cc76818bcead0d1f8095ca2cf9cd1ddcd0361b9c9451940e14332dac4e870e8b2af57f8c55996447e2a8c9d548255fe3ed6c08aedaf05bb599743ecb0df8655152bbb162a52e3f21bea51cb8bf29f6df8525eb1aa9f2dd73cd3d99f4cca31f90c05316a146aab2b5b", ++ output: "d0ae327fa3c4d6270a2750b1125145bdeef8ab5d0a11662c25372e56f368c82c6f5fc99115a06a5968f22ffe1e4c3034c231614dd6304e6853090c5940b4d1f7905ef4588356d16d903199186167fec57e3d5ce72c900fe1330a389200ed61eec0bdc3672554f1588ec342961bf4be874139b95df66431178d1d10b178e11fcbd26963ff589d5d5faf301b7774a56bbfa836112a6ea9c3026ebdd051085f9131132c2700674bef6e6c2c5b96aace94eb2ba6c0e0aef0eefa88995e742ca51ac50af83683b801b7c2c5af4880e2b344cc5564", ++ }, ++ { ++ nonce: "b873e9f9a7a68524e6dea72e", ++ key: "11efed96267ff58c3ca8e3b6c634f49e48ea07464d7ee8ac7574d8a058949c3a", ++ input: "fed3d1efa309c8b50cb9da02b95167f3b77c76e0f213490a404f049270a9c105158160357b7922e6be78bc014053360534add61c2052265d9d1985022af6c2327cf2d565e9cef25a13202577948c01edc22337dc4c45defe6adbfb36385b2766e4fa7e9059b23754b1bad52e42fce76c87782918c5911f57a9394a565620d4b2d46716aa6b2ba73e9c4001298c77bfdca6e9f7df8c20807fa71278bd11d6c318ed323584978ad345c9d383b9186db3bd9cec6d128f43ff89998f315dd07fa56e2230c89d803c1c000a1b749107a3159a54398dac37487d9a", ++ output: "6a95fba06be8147a269599bccda0ce8f5c693398a83738512e972808ec2f25bc72402d4bcd1bc808cc7772b6e863b0e49d1d70c58fcf4fcaa442215eeb3a4648ade085177b4e7a0b0e2198f0acf5465c97bd63f93781db3f0b9a0a184c3e06a76c4793a13923f83b2242b62511c2edff00b5304584cbe317c538de23785d2504fae8faabee81c5315298186ce3dcbf63370d1ccd9efec718cbc90b3d2e0b0b6aefb3a9b31e4311f8f518be22fdc2b0f00e79a283701c53f6936dd63734ecb24480d5365d1a81392498faf9a1ddee577007acc5f8c87895be", ++ }, ++ { ++ nonce: "444cbde3315ab7a30f0192fe", ++ key: "8bab05ddd17cac05203711b806475253a1ee0c8ee723eb520b73851cd51439b3", ++ input: "d776bee5625d29a2ebf6fec4df94d2b9ac62e8e7c56704fd38a87ee932b787cbc555621535e76ea30183cb0ee30604f485b541f45feb8c01b9750d37fded5cdffbbc34fb90fdc9c7c7ddf949a1d50b796f1ea5db437238c7fb83c4b22c9e491f75b33d84746f1cd10bfda56851b8514ff0ded0adfd5092a66a85202d06bd967485d06a2c56011110da74bf40b6e59f61b0273164744da02ce2b285d5c3f03aee79eea4d4503e517177692ed3bb035071d77fc1b95c97a4d6cc0d41462ae4a357edf478d457c4805fa586515614697e647e19271091d5734d90", ++ output: "60e9b2dd15da511770162345251edfb15cea929fb79285a42f6c616dfde6befc77f252e653b2d7902a403032fc4ce4934620931a2ec952a8d0f14bf1c0b65cc287b23c2300999ed993446eb416749bf0c9c7dfe60181903e5d78a92d85e7a46b5e1f824c6004d851810b0875ec7b4083e7d861aabdd251b255b3f1fd1ee64619a17d97fde45c5704ab1ef28242d607d9501709a3ac28ee7d91a3aac00cd7f27eb9e7feaf7279962b9d3468bb4367e8e725ecf168a2e1af0b0dc5ca3f5a205b8a7a2aae6534edd224efa2cf1a9cd113b372577decaaf83c1afd", ++ }, ++ { ++ nonce: "50fdabcd995b0dd1850a169e", ++ key: "e9a431828b3cf3891bb1960f9dae3c85334a62f6ee2395ee5378bb28f8c68a68", ++ input: "4f57848ff5398e61bcafd4d4609bcd616ef109c0f5aa826c84f0e5055d475c6a3a90f978a38d0bd773df153179465ab6402b2c03a4bf43de1f7516eb8626d057ae1ab455316dd87f7636b15762a9e46a332645648b707b139e609b377165207bb501b8bccfa05f1bf0084631c648279afdf51c26798899777812de520f6a6f0d3c7f3ef866982f5d57f9c8d81c9a4eabb036651e8055a43c23a7f558b893dd66d8534bf8d179d8aa7d9e8987cfdaaa7b5a9381ba9c79d5c1161b1bdbd30defdd304ee07f19b7ba829a0d5b40a04b42edd6407b68399caac69069", ++ output: "e096cc68956ed16d2dea1154a259e01647913eeea488be0b54bd1816c781a35e161772ae1f7a26b82e864ade297a51cc9be518641b2e5f195b557ec6fc183e4e5c1fc01d84fe6ca75e5b073af8339427569b1b8ee7fcff0ffa5e7e6237987c40deec0abf091c06a3b28469c8f955fc72e4f3727557f78e8606123e0639dff782e954d55e236448f4223ff6301accda9f8fa6cd43a8d6381e5dde61851a5aec0f23aeca7262659bc793ce71fa7992f80e44611ae080b7d36066e5c75c30851306f0af514591d4d5034ecdf0d6c704bfdf85473f86141c9eb59377", ++ }, ++ { ++ nonce: "3f32de67c92a44a0d9b1779d", ++ key: "d4338dcad949438381d5685e0ec3a79938607fdc638b7e69ce2e4c28fa3b3eee", ++ input: "046a61c0f09dcbf3e3af52fab8bbcded365092fad817b66ed8ca6603b649780ed812af0150adbc8b988c43a6ada564a70df677661aff7b9f380d62977d8180d2506c63637c0585dcef6fe3f7a2cf3bbb7b3d0df7769f04bf0f2e3af9439ab7615c304b32055aea0fc060890beb34fa9f90084814b6ed7363b400dfc52ee87925c5b4a14a98e3b50c7f65adc48c89ddd6414626c5e0bdefabab85c4a0e012243e682d4931be413af62fd7123ab7e7774fcae7e423bf1d3a31d036195437e9ea8f38aa40182daa9aacf3c9f3d90cc0050977c6065c9a46bcca6ba745", ++ output: "cd5a6a263e3ee50dda0e34c614b94c3ec1b14b99a2f4095a6b5715fdfc3449fcdf8a09d1ae02d4c52e5e638f1ee87a4a629f99f15a23dd06718792f24285f5a415e40f698752c697ee81f2f9248da1506ce04a7f489f8e2b02e6834671a2da79acc1cdfb78ea01822d09a1c4a87ffa44e56c4f85f97507044cf946ccb6a2e06e2917bac013f608d75ee78fa422a5efc9c569226bf7068d4705fde3a9fad2030256db0acf9a1d12666e0acf9f5346ad62e5af4c01a008d67ab1224b3e98278d073116ff966cdc779fb3aff985ec9411a3eefa042d71dd4ae5b15d5e", ++ }, ++ { ++ nonce: "5a3d6aa35fa04717b40e4405", ++ key: "e61e702d1a5a3d14abb967bbcc8cc8ab8fadba208be40765391b1edb801d529e", ++ input: "af516216f74a6344cbe458cbba820f7e25c0b10aa84b790da2ee6317e059171076d7246c2878be83fc00c200d546c007f849e4c163d52c7b0da31beff4abff481be3266b92e668cf4dd1c84d9d7b3e5191dcd6ddb51d17d337621046e83e9ac035fccfb239648bc3c6fd340fbb50707e5a33b3ef439d292192d0e4bc727690c61450e5a28789e5ea50e746bc66d039493e080fb70e9ae06d89004cb71de8178941c422f1e9862492fc9149a4864ff52b1277b9f5a63c2f16e9adb5263cf65a034a62ebb0f1a385d2681c87a35f1c45670b4edef1c68fe9544fcf411d95", ++ output: "b22ffd8f0e549bd3e0206d7f01ff222f92d39b41cf995a331d5ef0cf5c24bcc3ddb36e64d351b5755400246fe4989b5f912e18daa46cdd33e52dafbd2872f16e94220b56315d72c1dbb1525fd34831d7202970c11711ff36de3fc479407c34fef0aea86e172f9beb0f393194355b9dd59625639f4a6bf72ba571c229f2fb053c1114e82793deb2dfe8232f1a327949689d2fb2820662dcd2a39a2546c7df12b3ff7e87e58c74badf568cddebd3c558f0f7874c834c4b8aa988653f138ec79620f5e3ed737690928a30f981dca9f2920ac7307607063b40f87c204de47c", ++ }, ++ { ++ nonce: "22e02bb9c757121e1ec0d70a", ++ key: "9cbb1dca0495dbaa5ca9b8775eeb0dc5b80fbc2dc24b659e5a92d89466fb9cfe", ++ input: "a3d70bdb509f10bb28a8caab96db61652467cf4d8e608ee365699d6148d4e84d5d93bdabe29aa4f0bc8ee155f0b1fb73293c5293929eaacdd070e770c7cccfb2de120b0c3811abeeddaf77b7214a375ca67d618a5d169bb274a477421d71a651cfb9370bcf7e0d38f913754c11002089cf6cd6a8de1c8a937fb216591d57b37efdf3797f280773950f7eddeb9c3385c8315ff5ff581c64610a86ada7ff6a1657e262df94892dff9fdfb6e958d101f4c26296470c138dc4e1ca4bb565b3ff877a7f78b3d11d64b7c24e27ba6f6b06f6e368f5ac218cd5d11b815ab0987678eb", ++ output: "646314264896a6e25601e536f6e783d465b2ead1e0be4422bc9cc8eacabae4a749ad533eb28091be8397328dcfb34c92006bbda930ab070ed7b806095bb1c8f476350e7b08ffbd4d7d6055c8defaa8deff9d54f5215c2d7db27ce09e08f5d87a859145ea3126e2a01882921c3fddef3985bd451bca44063258390aec8ec725b07d064314fe43a9c83e9287b47616dfefbf539b82da209aa08a6d3176b7e3b4be4a17d44e581280a684e4a64414649bfcea82b541729f8178b580e8b972a89f5b8c4f9b68205e9396d8ae5e81873b61da074080fd44c52d50fb0880ee9c35da", ++ }, ++ { ++ nonce: "27190905ba751c66ad3dc200", ++ key: "9d49002edb63dcaffb2ec6c3197a15b4138bce84796232859d1ee72ee4218731", ++ input: "f48b5ae62f9968baa9ba0754276cd8e9dcfa8a88e4571856d483ee857b1e7bc98b4732e81f1b4421a3bf05ab9020d56c573474b2a2ac4a2daf0a7e0c3a692a097e746d12507ba6c47bec1d91d4c7cfc8993c6700c65a0e5f11b1ccd07a04eac41f59b15b085c1e2a38b7d3be9eb7d08984782753ae23acdafbd01ae0065ab9c6d2a2d157c1fc9c49c2444f2e5f9b0f0bbfb055cc04e29b2658b85d414b448a5b62d32af9a1e115d3d396387d4bb97ba656a9202f868b32353cc05f15ae46cbe983d47b78ba73d2578a94d149e2c64a48d0c1a04fc68baf34c24b641ea0b7a800", ++ output: "b9af1016275eaff9905356292944168c3fe5fdffd9e4494eb33d539b34546680936c664420769204e91ead32c2bb33a8b4868b563174d1a46108b9dfe6d9ac6cc1e975f9662c8473b14950cbc9bc2c08de19d5d0653bb460bea37b4c20a9ab118a9550bfeb1b4892a3ff774e8efe3656adcdf48239f96e844d242525ee9f9559f6a469e920dcb3eaa283a0f31f5dfac3c4fac7befa586ac31bd17f8406f5c4379ba8c3e03a6992a1915afa526d5ed8cc7d5a2605423ece9f4a44f0c41d6dc35a5d2085916ca8cabd85ac257421eb78d73451f69aaedeb4ec57840231436654ce", ++ }, ++ { ++ nonce: "7c996d5d8739629d36de4257", ++ key: "eaa5b2578bd6bdc5c6b0c79960a9ae26f1755cba6bcf04a9de315068990e0f0a", ++ input: "b39101601efa2ecdf41878b0fd920a3005ce709e4ec2970abb76e32c232ea21069f81b246eda75aace7555ce8ae203455d3723e684bd671389300e353eec0d2f499d10654fafda2e7a69bfca7198eb172249167ca8864b5d5f58d28723090ec86e251a1bac0346d52fd81f06e0c05429e0b2b895588290b7d00878a4da3378eb6c7e61487de2b318fedf68fa7ad7c88ee746827c1f60d98c7716f3f9695c5ffd4670f71a0fa78a1fb554ba482c5de83feaed7c65fc71acc9f541342eb8f7622b12bb2cfa222fa2ddd8b3ed210ce442275afa3132c8a0e17dd504ecbc92525c118952be", ++ output: "50eb5b21c179a03b9a822f0075906a3ce4acc32486139f92635c7d834f69071d5a6dc0e15ed06a5cee37147071d59641d140a82ad5815b954e7f28e080c3dbbeaf13943d7b7c66d49d51ba1132eeadd4cb7a7e7d726d08d95f1578d55519f267f753f3e16ff39504a87b2286d8bfba0fe6bc28887b466bf276453a82cdd0abbbbf08db0e1c26c317d50ad9b8dc09cd621bc566d362024e8404739df6468869d2125c58b25d70e392f5e75924c4341be81c263915bb514ad436fb24c2c67450e84f6d1b72d1a02a3310c07a7814d930264fdbbf5ddca7067e18e8a44faa87169b7f2e35", ++ }, ++ { ++ nonce: "07a7bc75f4d1f6897a656f2a", ++ key: "cc429f94483c5d2b73e40bfeaa92ac17ddd9c9bd26dff97408754826a2417b7c", ++ input: "0a42f63b975ad0e12a1e32615813dfd6f79e53ce011e2a2f0534dd054689f8df73a8326fecfd517ff7fe530d78081af66c3a8c7c189eb9d9efed1e5577b5512d42ef1fe273f670ce380c64bc62e217a7e410a8ed89998344e29301e4e053a3a3cf7e71587fd056a6bd976f16e157476a06997dfaaff32172dd84190570621f2221420c0a0ea607ea756e9792c8c0e7157c95b89c9490e20b750ee85e4c27c9b8f409e848ec90afcad33342010bb9808358afbcb3d9b094127c38c243a204e76899677079758e7cbada9a5c18363449eebc07bab516a16372722403a046df85c7dd2ffc804c54d38aab", ++ output: "87a47bcaa1c1eb8e55151011c4f39af4b9e108a55a7124cdcf66d0dee727306e6971f783b038bd6b215f530cdbb53e17975742ec304fdb3792a88b674504396978c6a5e4a9c87a7c3ca430d61165c1a3f6162eeaf38c93e18b6ccb6a595ad428cdc98efef8f84463eed757a72ffd827b71c0579fcc1f4baa11812be2bc5a2a95df8e41d04b33343df09ce628c367d1f88488f7a2787f013c8e76f0b9257cee777ec4adc6df8c5790e41ea02da85142b777a0d4e7c7157a48118046935f8888b5352d1750bf00b92843027a349cf5685e8a2a2efde16dcf5e1c1ed8c779bb38cabfb42ec4dd87d58273", ++ }, ++ { ++ nonce: "f7a40350de8cbd4025fb35fe", ++ key: "d9496e57dfe9840ea327f209e09d7c43dec86ac42b2d6a1a8476ab42b6fb5342", ++ input: "abeff48fa082dfe78cac33636c421991b0d94c3bc9e5bd6d22763601a55201fa47b09ce60cb959ba107020213c28ae31d54923d1e74ab1d9ddc2762b2d23d8c6961d81068230884a39682fa4b30676ffec19319362c075df0b879a0f083a67b23597bf95c4bb997fae4736479cb8a9c00520ba2f6e5962d54c313c576180d17779ff239ad60f1f1373627770d50a1c49718b2b2e536846299e052f8c1a5d3079e91cb1b8eac4661daac32d73b3b99e2051f8f694a61d1e9d3935f802921a4d979b6ade453cf30d73a4a498a6a2c5395c60fcf271d50b4967ac12b0d7bf818c2679d552e9b3b963f9f789", ++ output: "a0d11e732984ad575570ed51031b8ac2d7b4c536f7e85f6fce9ef5d2b946cefe2ee009227d6747c7d133ba69609f4a1e2253d0eb59d1f930611e0c26a7c0cf2d2ce7ccea6e079eadf2eb1acf0463d90fb4b3269faae3febfc88cb9fb0873d8b74894506199394c8e44a96e6b479bd3e045749cce1c3f57243abdb37e67084eb573cd820c6cee424227019592a027e9da8f7b8997bfb292627a986f83c8fb8d156a91a12a8b52659cf9272924631745ed3a2453a4c2d87a167faa9104e799c715ed597bcb66949ab15dae29a86ba147507e8d8af66e96c09c53caa053ad3b79d9ed3c0c6c00169eaec3a3", ++ }, ++ { ++ nonce: "ce48aec66f90f026bfb88afd", ++ key: "502cb8420d9e517f9850b9cb32e5756f1bf6c9e242f94a5a7b7779269c1c8e6a", ++ input: "a77b7a5870335b9145fd2e08ec898ba2f158fda16e8a2661a7a416857b6ba6937b4843ecaa79d3635d28383af80290842de9ca0bb621ee22b7fd6bf379922741e812b1739c33dd6923d0607826fc84d46bbdbd1fe9d1255f56a167779a560a6eed1b9c9579b8f771147df467e67a070d9e9ce8ad92dc0543d1c28216c1dec82614ac5e853ed49b6abac7eb3426ef0c749febce2ca4e589d06ccfc8f9f622ede388282d69ceb2fd5122ba024b7a194da9dffc7acb481eabfcd127e9b854be1da727483452a83d1ca14238a496db89958afd7140dd057773ea9a1eee412875b552d464ba0fab31239c752d7dd3d9", ++ output: "b330c33a511d9809436ab0c4b84253eeda63b095d5e8dc74803de5f070444a0256d21d6c1cf82054a231b43648c3547aa37919b32cfd9893e265b55545be6d7cd11d3f238ef66c3c278fcccb7dd0dc59f57750562cb28da05d86ee30265ff6a3991a466ba7e6208c56fc8862e19ac332e5fb3cbcc84e83a6205dee61a71acd363a3c9de96d54070a69860c152d4ceb9c4b4cc3b878547b6116699885654b11f888dc3c23483a4b24fbe27c52545c06dd80ab7223d4578ab89bff5f9cbf5d55b19611a5251031df5da5060a1f198226c638ab5e8ec5db459e9cd8210f64b2521a2329d79228cc484c5065ef8a1d", ++ }, ++ { ++ nonce: "8b6738eadaea410c7b148133", ++ key: "acc28f26867e2921cff89edf3452b4d4f2c4952ae36cc3cec938fad59037c47d", ++ input: "322d634bc180458123e10d0509870b54e0f0a3a72a2bd9e9cf44324c7a1ca37dd6adf9db1fcc8dadabd881f91d47d93b58382802b42ee936802fac8612ea4dd9eca5f215935ea9ba6233b9c8bddba3385861de669d95c888c8977851cb305db577a4eb2360f362fa459d61ffc8fcaa1502905b073bd8e9567ac7cff8e5fb1002c55641a3af5fc47ac0131fae372f073e19721ffcce9821e0241d7fa67bfc499c8f100e050d39bd4d7cae4557d208629603ec4a007852762ec1905d0e81b873510fd334dedcd9c288eb8415db505913af06bea94d197ab627d58f6a9944f6c56247595fc54ae3f8604aa37c3466f74561131e11dc", ++ output: "edbfb1090987762f75eba2439d746cdbefe8605b8ebad59e075d28b54edfe48813ccae891f6ed655c5ab5211ba896fff0c8e09bd1554aad987dc53f355d0822e9b0f524a99a79c68a9f3b4e30506cd725b07be135e4540078be88dac64fc545c433837b96a924452f6b844291c4c3fb5f8cc94f06d9f19dad7fc945f093020e82ed19f9eb3ddff68b813629991d1a460e5455e1cb41cf23bb3d96fdb6b96581c3bf9ef72814406329bbbba5b835e7724c728cebe88efcd996dea71d0fd5c53e081c21ce8b3764738d693e390fbf8e0137a716760fc9cd2014cd9bf3fd706bc3464d1f15803606976e96b1077cda0a62921ff7c32", ++ }, ++ { ++ nonce: "84c53a88d5e7b88f66de07df", ++ key: "477e74c7c6883d8531a69abf8064f1788080247c3b97ff15408a5231e5869662", ++ input: "e6b8a9012cdfd2041ab2b65b4e4f1442794fdf1c3685e6622ce70f80b9c2252ba6d9e6384d474a7622053d35df946a3b19408b3e1712da00525070279ce381359b542a9ad7c07750e393e0834593777352c1f7dbc84cc1a2b1eba787377d2cb1d08a7d20e1393d44022107acac5d765be37f9075af02e4bbf8e60ceb262aa34e2b870cc7adcf54329a667249cb4958393bff4f4333338cae45cbca419d59e605aa0cecb1241080339198b9b283e4201afc07360b8ae2a57b0b9b97167c315f03fd7a87a00ae73f91ca560a1505f3cdf04576b9aee5ea775f719916f1e1942ad5311c7f87153f8e62855ace3f34afb08d4d7c7f4fd2bf83e42f76", ++ output: "fc2673c80812d101bca7a2e0e105fa449550e695a016596f5c3cde11fb7dc518b94fdb74058e634546a726c37896110e1d1f9cdeccba1c89958041061ded8e8bc2751ec6dad76a305e70c57f9c81a5a65b5116390af4f7bf7053a03ec13f5d60a58cc5ba61f8c46ef6d2d291de490082dcfdf294aeb3a9414d64e4bd6497d4625acfa591627bfd98f0aec7e7def71515c09942db6911d73b96b4bd2d6df03bb729e945d71549d40e4bc401e1f73baf263a74280537692240638619f92645a5ade1eb8151191c7ff8bd715b3c1cd667e69745b806e16d46d9aa680a7367b8fb45a1598631cf3d44c1f5cfcd95bc8dafdb65a2083905a6937fcf21", ++ }, ++ { ++ nonce: "627acd79be19e60a36d2967d", ++ key: "648eec7d142bf1092adf706c0daae0ea14acb12733d8007aca0a3ce6e2389418", ++ input: "0cfd93b195e37dd15dfae83132c24ed5bfce7fe6fad4064b213b2c31a39e39ddad2f977e904c9c5b055ed03db46fcdd845bbb6ff0ab5a8c92e89295b6801f36ae63eba61fba24a3858aeb36f2da226b23b24d7b2c7d2670f23a9a1b60db85c0ecee584bef1b00e42d10ca17432a74bbb220d88356d82c850da4c09dd5baf413caf8f9479e02a330065fb865489c0f59605d56146ec8434182345de2d15e2a1dceeeee2fe94871d41913f6788738947ed9849ca0ae985e3e19a97bee82b96feeddceb196c9b6012264661945981c279f43db9599a4ef01116f592478619690daa64387290484d21e8d2444751194e1f361fb37f04014a3c7e4b409e5c828d8990", ++ output: "0502848571d1472ff10bec06c1299fad23a2cb824d88bf91b5447c5139500bd837a2fddc629e4a964e84907c1e6740263f1fef4f5ed41062982c150d9e77a1047b7d86c0e191945e8db00ca3845a39560857fc9e0e4a394eea4ba80a689cb5714c4bab7124ffdbfa8bbb91c3eb3caa1621f49dba1eea3ebf1d547ee337f9085638a12317b86c11aa1525813445107038942fc519eebdc1b98d313ad822bf0b94a054259aa8cf1be4b3a68f974269729941747f9a23fa5d83453071b431dac62274c24f6a32248b0785ff90aad5840fadc89af0aef7553d9352cfb00d3999ffbe28cd9fde7854e95710f4532b8bf5011e518c93361e58d22a2302182e00e8bccd", ++ }, ++ { ++ nonce: "001e58b792ba1b9a74663564", ++ key: "cd9f2cdc1ade505e6b464685219bb4c1cd70a63667f387280043bf2f74030af9", ++ input: "0d8d864010ce8df1c0179cf0236dce1c100f9c115eaa5294c24a2e1afa27f9d57ebc18f00482be0218d44262bd4db73002ff53c6388f5e333470aced2a42a73b376686c8d02e05ece27cdd8b1e3f675c715981f8b656d68d0e16227b529cf881d2433e4371fbcd933eaa72346e77e688ac80ee95324512c66a4c16338cf38c941b72c21c3d01e005a07c0eb436014fb1ee61806de7e96842ca3217ab8c7607d609dd2f637f9fda8a85cb0549f262c9e4a955c384319a6ad2b696e2593d7d174f5ddb98e2a8d5d12558c18ab67571e9a0202e91ce26d720cbe41a3a6a4f309296ca4d9d9a59a9043dd2e5a707ed7d5034023d5ea06ab14b39b7852e5c984848d5670c6f2f0b189c2a8a4a4bca", ++ output: "d2a5693c9d503a8821751d085a0837579233e65b691366e4a7464481d22800e786939349f721a815f28b4e47c8889f0814fb95d592d1185e45d6dbcac14ffa4f1d6c79194f2f7eb7323439d9607edf80f01e3a968b483eb93c01d9cb9d3625d21d66927e7aeedc1d9bd589560ed2b61cbed5ad0e0310c8ebe140c64c67d4909c010902d5386efa359ab60a9573493d3e5d8761cfd4023eba23de48372032d4673b5f6ad66cd0dfab02a73aa81f269ae88fcabb3ae9cb09f6bf60fd3575a3046bc6843f444e1e9fb9ff9b991620344fb99da68df09496b40f8b9dfc34e830a87f65710940603ebab554d36e8b4c9228bc9c26c07b828f34cdfdd40b161717236ba325e8c20bd018b324345e09", ++ }, ++ { ++ nonce: "cb1f642ce2c770518836a262", ++ key: "1559ed5a18ccc4c57415e5f0c694d875d182701bdba12e5d24fd09079898f6f5", ++ input: "07c50a69e168e388caf6f91471cf436886a3de58ef2c44795d94fba6538add8d414d84f3ef0ac9377fd5bed6aa6805a695f3a711025550bb6f014893c664e09bd05f4d3b850771991fc02f41c7353cd062156243b67fce9c1f0c21eb73087a5de0db0578923eb49bf87a583351e8441c7b121645bcb64ef5960fdca85af863dca7ebb56662e9707d541513bc91bf9b301431423b552e2c148e66ecfd48045ecb3a940dd65694d7fc8bf511e691b9cfd7547fe7bca6465b72ff9f1748723c4eb14f8bc1efb2fbc6726115c597a3881e0d5019335daf2e5ea8796c2a8b893ca798c4ef2639465505c4bd492bf7e934bb35be9b66c9f35730736c65fa4c1a2485378b9d71912cb924634a8e0db2802b75728818dc00fc28effdf1d8a05e4de4608bb6a78bb19c377d5ec77dca1b5ad38fded7", ++ output: "3dff5fde2ca24bf419e13cb7d12368e70449d41f2aa22e4b567f5cbdbcf3257975e44097deb180f2621ec36acf375dad3b7a19234b9856dc6c7842a7f86be00304b41a8c1662a02e8390346cbd0ff6be7bc1ceb821dbd805ab5c93c9c6ea5093249b5dc52081cbbbe1b326e831ef3c6c42fb791790086d1586f7daf031e70a71b54e9134f942e9ce229fc77980eb80c985ee0c5965eaba375d156f9b423b0615f4ca6fd77de28e28f35aba327e4f1b75725730155b7b4d6c5c264bf3d9dc9a16e7ededcc261add8c666278bac5cf0b3275d6d6678060eae30bbf2ce5f63e6a53a450b65aa0adbd1c90cf045f5ddd9700c2a99c80586c5244cf4c08035b6ff630c82cec3a4fcc83860e987898b42fe746939f8b37c814f8dab65de276e9784fb90f0751d3ba0826889e1e7e4fdbf8a90942", ++ }, ++ { ++ nonce: "cc72b199d056100933750548", ++ key: "8e39cfe66660c5c34c19ffc5c4d8d2f608891d6d6520e663cb85a4ccd63db01e", ++ input: "3ddcd3c00014747903c95e49f64258615455a0b26c5070a9532382a9bbd18eeb19c9fe1a902f5c6baf544c5938fc256d310a9332223dc3c54a6eb79a4b4091c3b01c798d2800418863f2865c1cd8add760e445588576d4a6c945e1d6d50dc913674daa4737ac94d84eb0ff57cda95df915989c75adc97c4e3c1c837c798a432ba4803a246bb274b032db77e5c1bb554a5342ef2e5d3ff7f102adb5d4e282ad800ccae83f68c4bfd3b6046786a8cfaa2b63c62d64c938189b1039ae1a81ce5c91530772cca0f4a3470ba68e4e0548a221eb4addf91554e603155a4592dc5c338aa0f75a8cc2822b318fbfba4a8f73fa08512132705dae792eed6b809c251d35cca60c476406d964187b63cd59333771e37367671d0ccb393f5b8bde77bebc133485ec5c66bdd631d98cdbee78a3cf435d2f824fa2f9e91e89af28b2e155df4fb04bbe4ce0b6162dcd8e81ee8d5922ebf9c957b26c343a0396d91f6287a4af9e11b7fbb5a5a5c1fcdb186365a20617d4ff5037b0bfa97b6213a6ebcf0b78b81c65737378787b255cba03d715fed4addc2c70c1fb4d3ab16f2bff287186c26a164dae2fe9dbe3c4a2e1617f01cae79f", ++ output: "ecea5fc18dc4aed23359cacb8f79a457512e0a27d9816f353e315519d2b2faf74d14ae8ae5e227b203823998a47a050c363a807f45f610942fed4518b8091b88dff8b2af8fb6552eb654c85d2b6a918bcf56fb898392941d983b1afd867ef840e12313059ed3e4d217498dd511563a939c3c536fbbf8e019deed29262f0a655fc680b15939475e0cee0ce2e8bab5834f7354b93e2e0958a5bc608fab369b6aee3c9d73a6898e402484eac7300150517bbd137bf55762897696a3dc4be74b0c141755ac8f2f6e59f707b1690c451a774c46bbe195d826a6784f8d807b78f8ebc343ecacf37cb9b1b2fdbff6a1237b5098853d783e77515c419894c2628f8b5117042294ee2ed58a33746f9e79b13fdfaa25a75fc95340a89076e786e0ecad7de437a9a3fb3092146d255005b22895310b1252a3e34572cf74665b97f4adc30dd0f34e3216c7757953a4b618a775bbe68f9e0922d75afc80a1379aaf1745f2263afb6f0b37553d9c984f1ef781ea75b1980c559c77565c83f3e0bd7a3cd7cdb594658beb7e5eb940633dbc6ae2f50383beea676cb6c814b17b1d73dd133f544da88ab371415889ead21803c1ffe3f2", ++ }, ++ { ++ nonce: "6d4adb2a1c0cd0333c19a010", ++ key: "df07d78b19202170815568dba3d1db9c1affb97dee19f11affc0d8b1cb224a3c", ++ input: "93ce72a518ae892e00c271a08ead720cc4a32b676016612b5bf2b45d9ae9a27da52e664dbbdf709d9a69ba0506e2c988bb5a587400bca8ae4773bf1f315a8f383826741bfd36afeae5219796f5ce34b229cac71c066988dbcae2cbcfcdbb49efcf335380519669aaf3058e9df7f364bfd66c84703d3faaf8747442bdd35ac98acdc719011d27beba39f62eab8656060df02fab7039223f2a96caac8649bc34da45f6f224f928d69c18b281a9b3065f376858c9fd10f26658ae21f5166a50fe9a0d20739402eec84f5240ee05e61268f34408089e264e7006a59bb63eeaa629ba72603e65718d48e94e244e7b39d21d85848d5f6f417631f3876f51b76b6c264356d7d7b1b27bbac78316c5167b689eff236078cf9e2e4626a4ae8bedeecbcaf6883e2e6e9304969b4fc7a4280dcdc5196267e9bb980e225fcbf7a9b2f7098f7f5c9edd06f50c8791edaf387ff3e85ff7bee1f61e4660fddd4eaf5ab0320508e3ccaa9823ae5a71faa86bd76e16d862d83ed57bf6a13de046a3095a74a10c4da952b3c9b8fbde36048537f76eef631a83d55d3a13096e48f02b96a5a8da74c287a9164ce03ddf2f868e9ca3119ec41f0233792e64086c903eb9247dbae80e923eae", ++ output: "bcf49d62dcd1cff9dc37d7096df0c39031e64ccaeea3830fa485edb71b7fcf2ec709a4b327ef9c7d4ea2b35f113a8485d4c236e06b3baccee30e79c6c08739fe5fbed59db30479b56dfbe584a5d79b169b200430ed27072137e940a34170606b31f22095f2151b4d9b901f6337f991a23e4c8997a1ebf5105361fdade1c889b8dc9565e3b33e0bd608c39d725becbb60da8a797186fe0986736112da3d09906442364d6e253e5b27fd5ad72e877c120ea7a11d42b19948f0df5ddabf9cf661c5ce14b81adc2a95b6b0009ece48922b6a2b6efffdf961be8f8ec1b51ad7cfc5c1bca371f42cdac2389cbddcdc5373b6507cdf3ffc7bfb7e81487a778fcf380b934f7326b131cb568bbaa14c8f427920aa78cc0b323d6ea65260022113e2febfb93dcfce791ab6a18489e9b38de281169f1cd3b35eee0a57ed30533d7411a7e50641a78d2e80db1f872398e4ae49938b8d5aa930c0c0da2182bd176e3df56ab90af3e46cdb862cfc12070bc3bd62d6b0387e4eee66d90c50972427b34acaf2baff9d8a76002a20f43c22ac93686defc68b98b7b707d78d0e7265aabadde32507a67f425cbd16c22a426d56b9892bac3a73dd2d2c03efdb22ecc6483f8d1ca67fc7d5", ++ }, ++ { ++ nonce: "1552f1ecdd1ae345319d4956", ++ key: "968498f5dfc2bc49c3a34b7bbe38515d6b46cbd6f8828ce9273f7d14f08923c8", ++ input: "f72bec13b0f0b6f2317118f14c2a0d8e963b1bd49ae7584e710dbde75bb1e30c79281847cb822a5f3ae4fa56825e511212f17f0d293cfe80f872e6992d304e9283d08ce65ceeacb003b36a862c91282a22536e0b9c19953512a1bf9e20d3e7a8f1a2dff45dec0b9b04c592e88a7814540cf636a024d10008463d0b3aafbc4c9359889149433ef173124866aa6f53526ef3b3f2c630860ecdd08ffd9fc050e95da512cc87f812f9391085cdec5cc87258b8560806a52336d612da7ab05e0f60566b950904aa27c975a48c7d78455728c87f9b53aa4978374ab9592e12c22d9a760e26eb527133534ac5bbf969596b71cde8b4ef3587fa7ffa7116834348c275ad4dce68ab3397521ddc8e54380129cc81b981f9b32db20dddb0ecaa0f1ff7b06495a42b4a800a207b8e9ca38794e2fa9f40546e0e3aef7b5236d7fdadd72b1158714a5ad8d6264df1e75120088e449b9e911eddac59f1f19a795205ab7532783a93159876133b3fe3a518475a545fbe8dd2ac143f33c35d98e3ee13b63606b1e671917ac3ff9412773a3ac47b8c6627b8ba9dde6820f4f16c2ed9cb7d7086cfbb0cf2d7533eff253d14f634ab2aad3fb4289b9a0bb667a6fdd0acd5949185d53f1dd2b96ff060bb44f872a67259100669e6eaf1a7e2b11dd5fc35792db0c44a1127765934a068bf", ++ output: "bb618ae6b7739a4dedde1dbacf864b0892b93dea3007237d2f6f23be0718bdd29321e6b0fcb6a44dacf0f5c53d91e16165997e2302ae7ebc2dbd02c0fd8e8606a4ad13e409a4e807f331cf4174171c5fff23ca232192906b4eefdf2ffb4c65af78be01b0ba7d15b4341dd5a2edd49b17db2812358c8af0a4a9724e0169f50d1d331936bc2400012a60849876c3ead52cc9fe60173c9992f83f3e41ebd24fe3961835109612994c7620280539d483f91ef9a64c16032a35612a119589efe6357fa35b19531274576e304be75bc7e91d58015792095bb00ce4de251a52b946554366ea7ed9ce9317020ec155ae0071e022af36ad10eda5d671e5090c136e381cecdb8bc179474fabc7dab2d8a134772976cf0791b6cebe2333d34b4b8e2b6b2eab2b5dc7c6a08a583d091df64328cbcde36bc1b81095d82c741a1503c55d833d551a855e098166c5efffb8e4146e32e54abcaa85076ca6660abdfca9e82824217b5d3f23f7ff3455872bc76751480c1a8e3e725365c82fc135cd3713cc0f1ea733754142f8c37716a2a4fa8a6b898215c287565325774c2510df6b49e78cb986853ac5ca532c9a7e2bceb7c0157f60433f29fe29009343d6035d7b5892c77f821b644590615dc505604501dd218dcab789e6f0525387919cf25c7c6d62a8979e39d346decbed2657", ++ }, ++ { ++ nonce: "478ca60b970002bca7147dbf", ++ key: "deedbe3b6c4d8f6e72cd276e60f30f14a0ef91c87f22aa4af2fe3c73f3f1512b", ++ input: "96eb94e1adbcc0646440c8824a2fc0f2c4b17d9cbddbb8ba8d9dbd6482fbf7201c74eb923153e0138b2f6f182f9c3d5656ee40bb7c26a01740b5c7d125261d4e4197614800aa152b402ba581bfbf4288e73c9ef7e7e37491212b921420eaaff880eeb458e3d0aa108b01b53492c97e328e9d10e3220b924351d583c00e76aee9325d6b89b1f162ffa30b386b37b5eaf4dfc25d22987dde4496158818c4d8f19ea300fe140be921d3f1abdaf9ab8946833a57cda5f41f995ff80e98b0f10f7afd736dd33438dfd395547f11563056078ff8f7c202aac262955f0ca5dae2365472de40f069028104ac552ea5a45ff2773335e5d3242f1e62e0e98003333dc51a3c8abbaf368f284536672e55d005b24b7aeba8e4cef23289adc12db2213aa037c797e7e753ae985568199cfe14cf1704fbca443e6036bdd05859e3583897cbefe7a0cf268b75d554b2da6e503ee04b126fbf74eaac0ebca37e84ab9c726973af780fe2bc9869fe67b7d9e4a04062ee535b2c1740d1347224e211b5cd37ee14c3325f40abee930eb6a1634986e756b3a1f86a3d7ee7184d95ea948506d8ab8b23f92ecf3eb0586f7a8b1bc227e08a0e32ca75ca4eeffc5c0a2a623547788bca66f3dc2c48671e462544d52a87d34307a7f111aeacb7da50262deab33d9f29dd6b47c3bb555be598d619cc66be8c4b74b01772725268a43d467f39bc565e5efcd0", ++ output: "590965d18ebdf1a89689662cfae1b8c8a73db8b26941313006b9b9bd6afa6a57149d09a27390b8883069e4fc2dfcf75035def1f8b865e24c21b1a1ed3e9f220d7b48046577b661bc92d9888a912984ad415ea2fc92c9e37da0bef5c7dab11495c612c27b5babe6eee28fd26482272fce69ca7f11bac95251735ad808365ac587830ec04105304f8e440a4da47d30e788718da4282941c9c76f18de4f954b8be750b54cb1145489edf273625a0df9a694a23fe7bfea12579b53c3b2a3de85705568cd7e603f3b8beba9a14cad9979ea283a8a291d3e1105b7f890e2a569804d9b7dd4c7e50bd0dcd11223fd7247af77f04212ece1b98c238d2fa0386a994bc502f83dcdd2e5a0d45b185155e1a395d91726d383c2c198fff1590e983c65ee041638510787c8c59c2e96f31678226a033e027bb40c416b73c3dbef31affc93a659c8ec7ffeca313fd5283a80533b2d63941c8f245d22b160c5fe57c5fa4b759c407b9acd6d9c4f80f244360b9acd11e2b43d4af757e16a6ef9d6756df39ca3a8a235e74351f50b2ebf54df633c8c400fd80b41b07117676d486377095660f2f20f62c034563b4560b473a8f4d6a740306d2a822fd8bd98012a840ba9b1709df9a0d61ecc305f7180fd764e334045d9a8ca23cb8036c05616a8b21fc488429ba4168c59dfa231f0ffa668a3be7b16583df1a55bb9c15d51660ddeca730d66f7a9", ++ }, ++ { ++ nonce: "54df19942a3f5904d66dc071", ++ key: "4077517b5363e841089462edea2ce35fdfc56bb050b3c9ae6f2a0cc04ff4aab3", ++ input: "be3f309c6e7b89e1ec4a855cf161156d09f8a04d5630534ee19e9e071e3f4603f23f0c59a7b7f8a32c4c203ec8c129a268faba09abde7b61135c6c37fd091e2d695f0e242488098ebed30c7d321f4dcef0bdd23fa85a53569868cf2008bf4d2ee7a12a6673298c7e797321b9f4559748223b590e6fcf17aa72251586b01181cefcd32c6a1a20a0fc27143426f6572b1aab0e7301e390cb857f912d78d5153906c698ee140b36cdc72693cc019cb7add747ca3a07b2b82a2332bfa76c962b186ad94209fcf590ed0f6a73b08a771a58eb9649f2f1da4f7c385da83d50c939231f745514d14b0920deedd9c4dc6d2e547f83643d13541870875e52c610372b14b602e7a47f0b3721cfca60ec68e2eee91f40ceba2d0fdb4ebe19cb1d1ab170726c9e600030454ef355f9a40033672be520e528937f38e7a862a5ae50cd94f667cd015a72ee3f91b1a09031bf4c207e0c516b2e7a4baedf373f1ee71843e560741ed3a3094d2b513e2248caf27ce135716f6887d9f1fe5b11e02c12c989d29054ab183a3f55d9b40d78e12ff56edf936ab966c7c3130bea472b71fd69e70165a76afbf720e2c1587a77943b35acfd81b2ab6f39476623edf3663024fb84da8057ed3a361e9533caf9fc58a5e4897e4bf84f58ed063b5c353bdca3792952eec0a1404149ebeb5b17cd6350ab3e27e44e40fbcb00780d001a48d0365d534ff830553409919608881e665f83bb5cf0736d728c41cc4e985c377f89ee1186303d0d76bc634875ab3ebd87059969f24b0464ae11967bcc47f300a34e3b917b1affceea716c5ad9abf1aa3a1106e2f4d006514dc62cfd2a52426968f2f3991c9f9d8fcd", ++ output: "e4032c01bcece73fde73961ed216820dcb44ce20134678c98afb674bb03afec2f4aacbade7f87a32fff57ae9213eaf0509e9d9db1313b06fd1df53561f85896ba627cccd2d0e2ae4f24f5579bf02f6599f5e63412ba084cf53a5bc9a8061b5c029b755329fcd73f629fadd3bcf6cb4c572fea86466cb5159d19eaaf0f44c3471d0323bc7206bb514ed8117a61c6d98d44faff6a83716657531d965ba3efbcf067c452e0d2807db3423958d9a4421886fe132d7c47e82086db9507616b67f0051dffc1a49ecce3ca8e4d5f5af15684cd8837a471430ddd333ea0b6ee603b7d9e702692f857fab060ccf26f2a8e61dfd3b12923acca78b83a6004e4ff09113becf6bdd0bec3a449a195559dfeafd4e2a79ead5ae3c993a15ad9b1a2ce818e18edb010b7fece9aa437d85ba9841d89026d6aac1a3a6ab6dad932a26d7db6f3664b06d51584cf4d22a75c06e2840db7292798306e4d39379af85a6bc8dcaebb5246e07fadd5e336f122de0ecb99ca24a971701a1f43bd69933beef6e52d299b132e7510caf27b99739e32bd272afc36755ea80cc7ed3957d91325584b338d15b19fe554ee70bee903babe21d0cbecd49235c70a3a4f516ce16761d1cfcd70bb4b9c7c73c359f3fdd0753d6c1ac1a1463142f18266b6a9c84675f247d56563646fb2c8c3b6b81944c2ba2b76b685ba5ea40cf539bcf3850a8af3e0a69c0b38164de520a3bea82b91f67d36bbd87877b5be7f06c2d26b2dc747a26a51f51fe293197db0e91e6ac617c71ddc6edfeb7db8f067ac2012268deb7e5f00a640c1bbec5c4c71f10f921071308cadededad5c90e72d744d0bf790b043fd35729570889ebe5", ++ }, ++ { ++ nonce: "90bece179b25feefcad4f9bd", ++ key: "e8512d17c6f5805b38e4c9b9c01961a523232162896538f5a37970de43e66906", ++ input: "0aa4fbce7e1774f0607e7ea01fc0e6d210bb283964ae75e180a9f6ff3d2c4d50914bfc32bca6d243eb33551521d54d66f377fdc1d31974ece79b157905ff7e7a9b064f349727ce37c83c15ae13df635c3e6b4baf994d9aa0bb90b06c6cda51deefda72c97a2993448e654b746b216d2b949bff1af5238558205cfc3162f1d7a020a919db4d4eb44bcf7b269d4df57e24133d1e540694b9148444cee16e64035ef006a6079dff449949c1b342991f2a27f21c8bd74ccf4bc944284a46e9fd9f9bfd4b95f80c05553950fabbf5e5aed6babb8427832266aa4d175114de9127ff6ee848534d6dd5aa6d2dc361319863cdf32cfb1b074faed17d368964393352df01fe8d86af0e994bc9dac315f7d9efa7bef47a16676cdf17a535ae71d399c4c11a3a3ba0491e8d41f419685258a4ec7d1ae588b3ca341719c0827ce5f5a653959a8671844f2d0293c09bc7d35497ed18c160fc7b6d073a311b621a7a37f7ded1df3d73dcba1821278c9e17a191997fa4dab0802e1ee1b468e91e4272c4569a17dc0b2805b980bde798640aa328a3605abea1865083d7446e960c27f69d32882a2a2295efc9c440dc203872373411925f8839715e9441d31dd9cc14bab09a3e03b4a63e14db3039d58725796326ea6327f189beecd63955f1409467c81f4691ecfe9f0ac5234f23dfb84e3199e415ee7b4f67189e8857ff6cb3f64c2ac1b554bfbd679a6ea8491cfd69d96d08ee2744d9103e0b044212560ff707974b1a9043e1f2c3592828fde8ab5e993652c00e2b3fdb19082611b67866ece6c4a2635f87e04d2136d679f632416b03ece4d7e9406f3437163f4fe0c8cc7b87d487f6de3b3022665bcafa847c2b9199e1ba9af7deb0e29b66ad41688d03a8369416dfbee6d03526adb3ebc4b4f8531d73589499a3010b5309e9d9d2f5a9cf347983a92722dbf6c4f0bae8aba57b37d322", ++ output: "a31f9a532f35f20ba604a9ab9989260e5a4ed04e6ecfa1cb9e0e1d16943906acbbb4e761a2bebc86cad0ce8b3f26d98b455e4b0835eb8b43791cea29fe8fa6e5187b60198142059bbce98917aa2957ae2555bee70e6e9e21ff6197a51ac2ca2952c413efec4d9903a2f6883e88aebe7ca8316831f6a8f2cd0e486319b58dc8db862779adff98b7f35c33faa53d56acd7a81e0feffc286b728f3a11afab7cace4c30b1a45780276b1f0ab89242410d07cb1191c7b9da5d09db7c9a729d91ac3ed82f4350f2871a12d125ba672861d1b0af7219c360a0e023a8b7c23fb9d72631c72e032c097118d90e5db0576586d8224165a8376fe8d04de93516848e7c2653cb4f7d24a971ccf4f16c527ea5b4153fad5fd5bf473b15806671854507bf1a6d9e5fe4a6f6ec977197d21d69a041dd955e199031f895adefd850c8b0ae327ba0c18ca1783560e1ff0feb2f659137e34a91e9e9ff04fe3375b7db6e4326986e6265e5fef00297f6ae627c7563846e531762748fe8d0b6baff17acf1e6c5cfefa35a95ef634ff96f83f16342a6c62311fc653d314f8a6de109356ab7801316e69a48834cb6325816b1f66d5c67d6e9c9cbc8e1a0521fd6e4bf77a7d2609f99c9579e143f530677b99d198a97620d087f058edf35eb7271701ecebb8bfde5671641ed21aeee9e7db06b932e0def91be93cf2955159e9666c770cdffa03886eb6e98dfca8f91ff5cef1927c0f82b9226d65c68d011416cbef802c264e34244ead7a6ebbe28a510a37e1276f4f3cf27a3944a08aaa23bd321092761627dae20dc269b6150545c75e995cfee0a9bcedb1ad8b364beb8839fd5c9f7984fa0a08a1a354aebe18f62acf6d6664978fcfda2ce6fc16eaa2cda5b835339001b3b98d3a407a3e18e0ec2da6ee3d1448c1ece2ed67c3f51f01e76ed59f0e61102b103a3c65aea94275e8d1f0d331538efe", ++ }, ++ { ++ nonce: "09bdc9b17d49e6db953bc716", ++ key: "e5d9f90b68e6ed2e95ca1d636de3334244e63fd8891fb199175705ef5f69e91a", ++ input: "e097b1e8dea40f63714e63ab3ad9bdd518ac3e188926d1086a9850a5580affb592f6e421abc617c103479ba39a3924eea1c0bbbb051614c4b5003bbd5fcbb8093864fc1c130748194d6b560e203b889b98b574a98ec3e0e07cb2d9f271ba7794e5419123b4f2ebc7e0d65cd404104868905ff2c38d30c967fe9d77ebdd4b8fa836c3b0ad15e3e70e9a28236d5593e761e694b047f63bc62c7b0d493c3e2528c8af78f56725172ac9416ec2bdc54de92b92a63f9ccb61e686f9249c7cc337d99b2160400bb5535eb8f8eb1e3cafcbceaa821c1088edbacb3b01b5bed977e702de747ad00268ffe72e3d877dd75816db65b5459607cd1b963fe43bf2405ec223ddc0de514d59cde74f7522dc72285caa3eeb7eae527a7723b33d21ce91c91c8d26bf36eeb1dcdfc1e9e475c1565ed9c7e64ef601874a4f277280a5ceec26717e9385aee8b159379e3feed7952b87240c942970d63351259aa7a286ddb4a2620fa67565c92f592902e49422f1eecea2f44d1c0bbbf54a9e5612b86a9549aa3e6639a924c7bbe2d3c1b5669da73c0e2c6f6f6084f54a912ad2635d0141c2f5ac925414dce0da09ab8f86eae2a7b7e48741253189e5fd554d5c04d9807ac6ffd8a4f8229a3e8ab75ca5c778bd7ec5a5c02085faba9792cbc47f9e9311f3444e6544359769e1b3eb4d42ac8923ec94536e1a44497766b5da523f5763749dbc2738dfa8e13c191dfeac56c7614a96bd3ae23e4e6e5ac00be851ac9831108989b491eaade62113c531385ef3e964ce817c8ed0857adca946467682c2f4387fab2f31ce71b58370853171720268459588d5d216faca58d0bebbd7cd83a78445d9b49e83ec2cdb59b5d760880bf60532178d60372752b47d52562b316c7de5c74af9cd588643002d66bc6260595a540d2f82cf2c07fa64e0cdd1f79877b6a25b0608c735a7d35ca10852da441fcfb31061fd7e482a0989866f9eea8b0b39c3d519715c1c2766c3ad99f041143cdb36557ed647403458155dccbb80c3a365f0a85b1135695648ab67ac76b3d219c7b77e49d735c72ac947b1d7eeb279beb9d2602aba7b36ca", ++ output: "7b6e07e6415660affba56047b988f4548b308e7a642c76791f5c3742cc4cb744cde48fc30e50d458084e06c6dd29a52cb4c306a69a493a17c0838d14b107d07b81c983a2dbad09b80f087ba48465a8beaae5b16e8093e17cfb9e84ea3bdb9af00889268a5c01ddf25af434de56f65882322432aa275fac8519e317ef4d89478f29182143f97350983050f5d37c4b518611da6fa2aed7bb73e614231a194fe17c9073e377fc6ea0aa491e15ca54808e0536c8c3f1bf657283f807ebfc89b55049ac8fb86f89f17974fcf0afc1a2c690c0442842d0f4af9ee29dd960e499d1077bfdad4c0c9189a6e83799bb585acdb853c1e99da7ce9c7eeb9bf431f8d364d0ea80b0a95a7807f196c6ee69fe90e6d1f5d23e5cb256e37e65826d7a111f2272884d6319f968580b3164b2697ea6556816cea3ca316651fe2fd68dfa905d080c28622606f7d24da216289fa2c54c6f42dc244ecb047512ace62f0801f2dfad8f0218f45e2b3bbac97c2176c842398b16dfa1fdfc9a68b7b5a1e785d2a0cc592bc491f5a69c81127b758ee02c66b81674d3135c5882d1dc89dadcffa06f4b0644df5c7fd65c72611d79be7ad637edd6fc38b39946aa2a2c6d08ca9d3ff9a8ffe2e7989546489539b1a623fa937c468e59e0978602526b4367de277526895aa222fbaeae2084f418c5745d8ee844da0baa47f592970c14cf710f49539c12104a62baddb3382f5773dd18c83ecb238ae2e749a51584a38e394ebadd175bf5c3cec787907abb1d94af70ae63d3b7d8d5ff254da90b78ec8fe2ea95dfbc6e3e69ecad856c9e54906df8fe39859f2014b74dc3ca0ee2a957001939d37a6c0b489bd3f1658b835a57b24aa282c23e875c9e67e6eb8b32fe44e7d7d8e285d85da0ce1b53990f9fdb5e2e74728e433ed2c1044df9e89cb9bb316c39fc6fc8bcc74a382093926a288170e857d6b7f47858a4c2d05c74263dc9e8199332d0179687f4a4cdfc80ee6737300cefba75905b22d21e897f887b67aa3051877fff11d98bf96ca5091bb225bddd5eae697f3dfb0efcdb788ebf6694b5b39dbb0d4bf9427382a3a58f0b", ++ }, ++ { ++ nonce: "3e507e0cdf0d11f88c6c3183", ++ key: "cdd1a20f05f9e74f1b4c9e2b81c85b11c5bc222925aa603f316dc21363af9620", ++ input: "0a1064714f20d9e47fe53250ecfec759f4137e60afaf65755f4709a483504c3855833b6dcaf7aa0180fd735fa9a73d46697f6c45004adf12452ea4c04a720fd7c20b9783b74b8b3ea0c8b1563d5a85f44af8afd7d91ca6298ca22642a684f66e365edd6f6bdb2dd32dfa13c62dc497fb341b86f65d40655931171416e23e3b2623c0b4a67d448877b6e3d4e0fe284034a10162b2b5e21639047036874f4bcde22b145b5f18aa8ff32dec81e6a5ac68b3c30c24bd8fd3b8e098a1cf202e2ab2a3bb66a9393222b9f7384653cda7707f00bc3c81e9591fd040a07d3629410c2db78781a4c9db3df5f9d648162f1b087974f56a89db07aa21ba827e3864a1618945b2fba06853a13c35da2909f5013feb313bae09870b8eab904024adab0d6ac46c1a1499791b47413139dee59db676949b9e9ab8d3d6abaa954ec2a9fc83953c91b483c3b6bd6700b96484850734e72e3710a1b379c0d0698aeaf68f13a0d317bfd689471e3299288e7a383a58522f0daaff210cc4917fa05f0b8ceefc2afc46148a05a100d30787accfb4da094e61ea6b58f132692aedcabae928e53c2594b01507b8fc2d0a85a1d111d1f4de0b95258281ae01873a72606753b6f878ecd8c4f613fb3477710d260f0bca0d4c06f675ab7113eded395f88755a98a0ad22b4a002cfe9447c4e39eda13738f4eccb9c13367ebc2878257c4647d31b67e5e32b6a77f23e9593658d19c0a40e8a7228767afba1cf23072b013b2d76ee66e42b57bec2797ce3619c695a661004c8129cb5c5d6a2836be22483f3b7e40bf8ac5535bf6cd065c4821a87829948c88163cfe3c0f60cea4e7ff59df4cdbf80064b2d664b39487413039999b5e86f1d467b12682d0cd355e9f7cd980e87d584ddbda89f68632d3b8fd6bc3b80205d7feb97a46842b093f74aa14bb21accda7474247b5e39ac76ef75e9b5b52b6a829a7e2297ab88fb0eb690d54ab1af2d7437149a6202035ce15f1e6c6267458d62677c263d83d3f8119af191b7d766582620e0f08b411c996c25ba6a32c2d73f592e789ed662e94103329bfa5e6573f1116ec04438997f3e4ad91b4123b570743455020d914bde2d8417fb24671e6db261732fb89dda1a36614b095529e4f97374c9bc0e55aa577bfffa663c816ca9fae3472e0a", ++ output: "b00a7caf5359c5bcebe590e6bab9aa03370050c55cbd45a257f4869937e922a15f2d38121b1493d6b5dd4a8a47d7b4e5cb049d396ad84ed421df774b0408b6939f18ebf5cf83f48c540affcc2a885967bf4bd222c42904b8a73c4185bde3f97e874fad25b46714235e60c9ff53ed2975c9c85ebad0752249e4b627ffa41555eb9074f63a5f7d61d207d2ce11b2a9fa23a13a0832eccb91efa2afd8d9acfee94ac78a733fa156bfea5006da1d0127c32aadbb75c015b68c627903e1c85bf3a1a9f99c6cfbdbb5c871f7f9661b78cf5e16d819f53e9930e201d4f58e69bcdce77ec5b9b1d2cf206a71f744342273c26b9abc71303c20df3d51f52222893d803fc8e0e0afcd99ee1c7f95b48680403566f7f9e296d7ccc0ec348b6ad515af58d11fd82c628ea29ee6a5d67aaeabd8823addc01a078b04313af73105d4ce4abef8e6ee8ce649640a19678292d4f1017d121549fd2c19ba6cdc0b613e512bc9551d759c6d38aea7e35c0847a142e273a16bb1495e652f9668b97801ba3f6d9931c0a1efaa4452e15732dca1ca9cb45ed289e0fd08d1cee1cdcc9dfba8d0b2562b0b1a180f4ee69d63573222c8d4789bf0d63d2a201a70c7b27c84e620e33e8a863cf49b784269a51ead3d4ad26f044d5859988d5485a11533ea805f5a8f6313caa6b421071a34f57170fdd8e4663e9a4cdcdcc1ddaa9f6e651fb365cf827667b018ae7d028c7f96295b2b4f9eeb4b361b48af86463a79f50b107ab0935e3cec3f4f203cea801ff95fb870d2c2f0e315dc8a6a547dd3c390a1f5403917315164bd2d40362489b389a54e8dc0ddb83e6a43a26c65923e6f76ee0ee0e3a33b0a9066620a01f0319e20b9f1beb3910ad962a3000e6aacb0ae57f3f6c5e0315be5de93edcf0e45e0e47332f9daf7f33e6e8bf1929910b78b8f88ca12bf5519a3217b7554c8c8350cc314561d580bf67a3878e3979430d070121a5e070a3458742e8549bda972f603222e2b30eb8a49a955805307e6e02f8c60a08188f69340e116422458d4a8841f46a78c833b1a822e3f6c9c97422c918f17c36175ca4b3d1c081ee4b175b4b07bf101c3836eb5b9e3cbd08a89b4a1c50edcb41ea8ea6ceb1532f5b842715d50dc21e2499e08c373d3dedb96bb477c8802ab7aa957e0b5810f38", ++ }, ++ { ++ nonce: "c9da02eb6ca0cba74c76240c", ++ key: "574a41e94695e2d54c2f5e1a464c6e801f8d09481aca51437cd93e05ca95a4a6", ++ input: "00fa3b13b5cfa9b5d65a41cc2d3c420518802c22c4582873f1ad52a22032d2cef7c975078b199787e852fb1f914529f60d1cc854e5d6d547216dce043e0fc94866bb2193343c3a07fde60e668266d1cee3067c6f2ce0f9f63456ad08094b6c7f515f7ca90caa96494e2a6835ba1f3f166012ad1ff6af6b5f8455d5c26e72402966af9066ca70ad027eed23b0eb02c751195064a62283975efeb29bc5993f83360d012a2f5275ac758a9e8fe458fc7cc0673e6b9e338678f0faff60a67fff3784c3054dcbd95d1b00ed4c6156b3831cc42a2ccdeee55541f228b88e6c318e2d797c6fc035ae12868c4a4e3843b5b25a530b1477dec3f5ac27644476b5766e0ee132d833f9a63200eb0980bf72c3666150e567e01e3e1f469cf36beea65946fce714a3f354983e54ca4315b57ea35c5f48bd5eada05f49db1004cbb39888ebab3afad62f6509abad77ca8c4ff28731c7ae545e6876c8f4a80b6cc26928ee05001a9764694b52edd605e182d5a3a5fd192bff58aba90f57e4debe612d02cf6f08af33a78ebf8823bb3eb46d4da25b7dfa15ad436c380633d3db3d0dc4dfec6c2324d105e7090e65342b554854e777b40b5dab8125a58e8b212364ff88459a8466ff5ae661034abc8286a78ad5aa582e2dabbcd7a0b0cedcb9fd5f0bb8c3bef9117f2ca6520a72b94e528c1a4a464398e654995d5f4c77cbabf2b204b96a058cf1b38284b34e41ac37b05a003ed51be9602050f21c6b9326714bc425c1e22833da95a6e77571691d4dcab4ef9056c4c7f85d5b445b902eb375b5164c6bdf629ccfd4127a6c024bb6c4da0b6b08350432e58f8229e04e2e76f704be17d36e0c04fcc7a98f721d4572aa7f66ae8e9664300a189bc3862da47b60c8b33424f6d577cc10f4755f36c2a6decc30ba81bf48f96616ccfcfb74965d6bdcab82728bb224c560d1cfd7a175413ad1c14c734746be3b062b4e7514e9075c688103515e32e3335dbd272a315024d56f4ecd354264da9bc712080657b2b51b06dc7c4c441d9858935a4c3e6b207bde38ea83bba4c6854b2bcf914d758e0a174c0528e0e385c7cff355c38db1c22440369141e91266824c59f1ed23e7d4b99d31b0baa7bed4526e24259dbef5c9ae275e97267b756645f804c274d65ac7ab0f7683435bc2e4f24075cd1b790aa2b53fbf044e8f2092bdf0dbe88a582ff8f8de291e8220", ++ output: "bea32587095caac661c3ac49e65654b282192b2addf5b9a403aea6c8bd0096291a0a66ca4062acf1da91fb5749952096ec63ab652ecf94c29807f0aaac939b6896edcd6f0cd8dd8d208b906ef4d7a8766831fecd6ce98f4ea0c34fa9a5114dbeb23c2cd6d3aa962e39b18cb343c24e65d49fad0a0fb50736f8d2b24b011108932484399f4c4510ac9a5e6bc78ff0b450e67f87b49f253b99d95d6294e15a9934fc8b89a5913c08f75d3516766fb0f60f82e2b2647b4619991c78adbcf548c07c0dda30c629349d84f298313c3e629e03760b1cf860264205a950d6fd86732a6513827f72c0dff5aff96f7203464f60849c1065beb70f282cca1334f6f6c767dfff94f063361f592e85597de5d313eaed17bd533db24818d9ba9aea2afa797721fbd19eea7b8d46bbc4b9dc0164636d2e754f5e9e8c04e2a381096331731c645ea1f613a37bfa9a6fb2c6307e9bacacbeab7f5672163ff9742a8115049bce0269d7d5f6f35787be031dbee1535b0516ec0b46d12f5833cde5f2cc569edcdd20993e9776aacf48ace7bfadf79065f2803fba6b2b27aa622abb7ae023ff2b27b727f509f313f92026392485a5ed4fd53b2e22b2d2dc1538ce158d34921214638be30ae054a0f5f1d4f9c590a2d215ac2a5b23ed33871ab26c8bb6db7fe9d6f51e527c9547248a4e9734c64658b22893f4f6867a35f18e2bbfd7d62142025955cb51af8e40b6fcb91c7e959cea2c92022c87c29dae107a306f41b00e73c7bceef8cb070e8f9e830caeee463170e919cba6eee63092a5a7ee33b74db09cdd022fdafbcd5d524253a29a103ba6f4d668d31d18f867557871c0e0258221c3050d57c18bdae4cc4ff8da0daddb5c08619be127ee76a317b59a9d8e67808603a1bfce6b4e0d070082b283bf9c0e6ef8256208e482f3e2d1a40d30807f60a868e2279dfbc3586d44ee25fdca3505cd39fd469c2cd03bc2f921d22a8346750f346c919e7247301c1c8a4a3ddb8eabc6e80d85cd2459afe1cbb4851ea2c86b8075e0fef3177cb074894410ecf681242fac62b5fa4ed3a10ddaa595427851d376cf69e350207b667f7aa26d003f1ec739a8792532ebd93f3cafb1fea40d227bcadda2fb6da794cea3371240f257f80b1b8a857ea453b46938397c1f4b303a46257750003a60666a11d03bf2afb5c71e059933d617288891733b63784bd9c662234f", ++ }, ++ { ++ nonce: "a4472b3c13c814f614706fa2", ++ key: "183dbd3967cdaac9b58554cb226a532087ac22bb80a59d1c2e6b997d61e46f45", ++ input: "01847d8a97d56e55e12f89adb13c8c0f9dea5555e8dc61171fbb8e181f6cf846a4dd68b2c75335c0896fa215bf7f9eb7e398e4520aaaf33461ecfb61051f43d43569fb75fabd79d319bf39469f951e4da7932a74624c46d8d26a9499c701c00d3dea57a6f65b4c0f33b568d13989340294d17cd005b26d89cf6fa1c88e7b6ef4d074291fa8c117ae05d7c785459ef4561c45af63a811e9aa1c31b69a5bdac2356d955a0f579791247a757a691b3de447a53619878397cd82a74053f06da3574045bc856500ec01fd2afbc64d8dd283ac876a50e9396f78c424ab157f481316fd9c90cd899f5aca46dad32c68f1d64ea7f1c4bdb994ad847072609bd89adc2fa8382a5d573b680533640b8321b6adf27926274660b2cbaf04fbc9a4fb17ce8957c38c7bab1aafd5bf7263171e47d2e1ae5cf0494815642209d303dba561754479c24ea01a573c9083b68acc49907b1748924d3c6a82feb9417ca932578c123f9db35521c0d992565f7396f0c23e436289c1720e4e7c6e285c04a8159f93e06801334e523b18fe188355cc6a155febe64ba053e6b5d1cc87787fd5ae68fa86d8c51868b9f6a9664cf0d56aa6cb8463362bb671e6b8423bcbefe2a1a0acba3f135496736b5cec5e329494af46aba322bf5d1cc108c98298459558773a316e09b0bb960a26f4b0bfbaa493b5f98a0e522b6203c471b10e662abe9b9e60de2a1517843933add02017fadd62608383ad53796159f3d21b2c8ed7295802ca79ea65d550114ca2bcc7f7c3b4c6709fffc3c2de00da06e83d8f0cf04b8c8edd21c0fc11a0b2aa7f6adad255fef25e5c0a9d59546e97446e1fbf6a51a8ea6cad54cabfdd19cd10d7d33ff0549b710557e3931821dd8809ab0a9d3aaa761a01ae0f2e378906672924d6a1b12fb1cca7bed41f31974b9917a05de60c32796f502e7035a2c01cb49bc8e1734b9fa138b81b4dfe19d37f5942dd1b42f03e1e5a6a046ecd457174150e17dd148e4bfea44b72da35ef42a7251244700e59e702033677d42611168fd246e1b18b9a464b6c20fc7fcf6360cd00466ece059a69d7d54a4f5565d08799f85dd3c849a08ba43415077c1c0e5dbdba52bb3167ee99a11db551f0260493be1dde58d2072e8c02251f4f574b6e115cbb6136dc2c3fbce75fdcefe812d9c07a91a89088985a52cb1fb9f6cef80fa30364706414175e42c75e8e37f6e7cd028c99f59caa88c49db5b46e8d6301bc39034013718a9eeef5506415016fb21d70e46a03b4c5ba72f91dd9321ff5e210e5e5f7b0723a3bc4bb02b5a74c1f4a63aa5a993a31f79a768fe8033c9abfeb4deb536af1054be02d8d1c4a6a0fa75f3eb787d57a03b7ae994fb1b54b2c43b230ce32e6245d944b3cea4fa6", ++ output: "785dbea5d1e50af4743ed5fd2209e441fc7c50bc7f6fd9cc7f24654c619e2606178dcbbd81a1f94c1b3176837024098bd31326145be326b32fd9277a55a6fb38780c8dc8b471a3184379d90da4aa87d80b889b1f4d8d0755c1704a526b99ac829b8ad157ca54b2b05ff8b2917e27b0c147ab54add9a89fdcad7b93ba1fe2d5be9de88b68a5324f1b42943e45ee31c4ef783ec9e2337b3f2834b10cf452b313fafdf0c03719140f64060da0a565e185cb8e544e1c185ca230ff2321739a285abe8be4be0ce76678a7b0902a77a645194de49fef8ff64cc464ea25e1f1d72c775e450f08ddd7680d27a4142879787b198583d93b84cd87fd5b4063d92d13d9c9cb580c01fac0174686a18f64e6fa0b3589624cfae04aad74950559bdf92b2b199c60cb04013aa0ef56d1f9ec5b7e968f6a83756ecc9cee7dd8b433f64649f948df5474a64549e71e46fd8bb16568d21f5fb67f5ed555f2b8aec4709383e8cbc45b9fe47c0434178ad4c6d0d42606d6eef0e21d0370898d1d5d646830a88d5f024094fe9c7a2003ca13d20ab7cd748dc11a22f578ddab416f3500eff3d89fc177b46436108e2e2c7973910cb8454a01c9e9b98f966848325444b2ac205b1ed6919fa76aaf63717574761b7f62b10649357df49f85a845a30b6acd57fa202fe58673930ec59399f537e9682b1f5f6f409988789a8e0c1f803478dded14b40d3b6eb3109758efeb6a7fe21f41c4dcc8027258da27ad74010839dbfdf8fe55050511f85c321e653f76e55f22248f46da529a380c6b1a16a19ce73af9715545c2cae098dc42dd61248dbcf7b295f4dc6b8930b41baeef677156c534869be65e723e1aa0336e8be8a3b138f840c9cd63bab6d9d61f239a47d8cf56258544e6ef65edca27069f7a57f087a7cc021fa1294b75c0c0f1093c025e426e4f041ed5187f358402676d5da5fb6ceba76a178f65c8c3046f258531c165b8808bdd221c59ff56e3e06247576e144aac01ea96a07f1be15d7a2b0b3b6c259a9133f8a50b56154ecf9f61022f470027247e6e70e6eaf7ece5e324ec8f95667ffed10337652b119e7cb8d197e306e81ea251340b9fb2c33aa230c0a16e1ca783f9344b3acbf413acd96616e6d477dba90e39326089934bc5ca6620855cdc442e25bf8b8debf335e16e7e25cceb68659cc81b13a507fbd9f30b347126beeb57016bd348fe3df592d4778011664a218227e70d7360d139480500b7f6f84153e61ca4dea105875e19ce3d11a3dfd0ad0074035ff6a9fac0ece91afd8be74c168da20c8baafcc14632eb0e774db758a3d90709cddf0266c27963788c35a842beea8ba2d916234431efde4bb32fd7e1cef51dcf580f4697206bbc3f991f4046360aea6e88ec", ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20/xor.go b/ms_mod/golang.org/x/crypto/chacha20/xor.go +new file mode 100644 +index 00000000000000..c2d04851e0d132 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20/xor.go +@@ -0,0 +1,42 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found src the LICENSE file. ++ ++package chacha20 ++ ++import "runtime" ++ ++// Platforms that have fast unaligned 32-bit little endian accesses. ++const unaligned = runtime.GOARCH == "386" || ++ runtime.GOARCH == "amd64" || ++ runtime.GOARCH == "arm64" || ++ runtime.GOARCH == "ppc64le" || ++ runtime.GOARCH == "s390x" ++ ++// addXor reads a little endian uint32 from src, XORs it with (a + b) and ++// places the result in little endian byte order in dst. ++func addXor(dst, src []byte, a, b uint32) { ++ _, _ = src[3], dst[3] // bounds check elimination hint ++ if unaligned { ++ // The compiler should optimize this code into ++ // 32-bit unaligned little endian loads and stores. ++ // TODO: delete once the compiler does a reliably ++ // good job with the generic code below. ++ // See issue #25111 for more details. ++ v := uint32(src[0]) ++ v |= uint32(src[1]) << 8 ++ v |= uint32(src[2]) << 16 ++ v |= uint32(src[3]) << 24 ++ v ^= a + b ++ dst[0] = byte(v) ++ dst[1] = byte(v >> 8) ++ dst[2] = byte(v >> 16) ++ dst[3] = byte(v >> 24) ++ } else { ++ a += b ++ dst[0] = src[0] ^ byte(a) ++ dst[1] = src[1] ^ byte(a>>8) ++ dst[2] = src[2] ^ byte(a>>16) ++ dst[3] = src[3] ^ byte(a>>24) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +new file mode 100644 +index 00000000000000..93da7322bc48c2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +@@ -0,0 +1,98 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its ++// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and ++// draft-irtf-cfrg-xchacha-01. ++package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" ++ ++import ( ++ "crypto/cipher" ++ "errors" ++) ++ ++const ( ++ // KeySize is the size of the key used by this AEAD, in bytes. ++ KeySize = 32 ++ ++ // NonceSize is the size of the nonce used with the standard variant of this ++ // AEAD, in bytes. ++ // ++ // Note that this is too short to be safely generated at random if the same ++ // key is reused more than 2Β³Β² times. ++ NonceSize = 12 ++ ++ // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 ++ // variant of this AEAD, in bytes. ++ NonceSizeX = 24 ++ ++ // Overhead is the size of the Poly1305 authentication tag, and the ++ // difference between a ciphertext length and its plaintext. ++ Overhead = 16 ++) ++ ++type chacha20poly1305 struct { ++ key [KeySize]byte ++} ++ ++// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. ++func New(key []byte) (cipher.AEAD, error) { ++ if len(key) != KeySize { ++ return nil, errors.New("chacha20poly1305: bad key length") ++ } ++ ret := new(chacha20poly1305) ++ copy(ret.key[:], key) ++ return ret, nil ++} ++ ++func (c *chacha20poly1305) NonceSize() int { ++ return NonceSize ++} ++ ++func (c *chacha20poly1305) Overhead() int { ++ return Overhead ++} ++ ++func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { ++ if len(nonce) != NonceSize { ++ panic("chacha20poly1305: bad nonce length passed to Seal") ++ } ++ ++ if uint64(len(plaintext)) > (1<<38)-64 { ++ panic("chacha20poly1305: plaintext too large") ++ } ++ ++ return c.seal(dst, nonce, plaintext, additionalData) ++} ++ ++var errOpen = errors.New("chacha20poly1305: message authentication failed") ++ ++func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { ++ if len(nonce) != NonceSize { ++ panic("chacha20poly1305: bad nonce length passed to Open") ++ } ++ if len(ciphertext) < 16 { ++ return nil, errOpen ++ } ++ if uint64(len(ciphertext)) > (1<<38)-48 { ++ panic("chacha20poly1305: ciphertext too large") ++ } ++ ++ return c.open(dst, nonce, ciphertext, additionalData) ++} ++ ++// sliceForAppend takes a slice and a requested number of bytes. It returns a ++// slice with the contents of the given slice followed by that many bytes and a ++// second slice that aliases into it and contains only the extra bytes. If the ++// original slice has sufficient capacity then no allocation is performed. ++func sliceForAppend(in []byte, n int) (head, tail []byte) { ++ if total := len(in) + n; cap(in) >= total { ++ head = in[:total] ++ } else { ++ head = make([]byte, total) ++ copy(head, in) ++ } ++ tail = head[len(in):] ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go +new file mode 100644 +index 00000000000000..0c408c57094ccb +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go +@@ -0,0 +1,87 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package chacha20poly1305 ++ ++import ( ++ "encoding/binary" ++ ++ "golang.org/x/crypto/internal/alias" ++ "golang.org/x/sys/cpu" ++) ++ ++//go:noescape ++func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool ++ ++//go:noescape ++func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) ++ ++var ( ++ useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 ++) ++ ++// setupState writes a ChaCha20 input matrix to state. See ++// https://tools.ietf.org/html/rfc7539#section-2.3. ++func setupState(state *[16]uint32, key *[32]byte, nonce []byte) { ++ state[0] = 0x61707865 ++ state[1] = 0x3320646e ++ state[2] = 0x79622d32 ++ state[3] = 0x6b206574 ++ ++ state[4] = binary.LittleEndian.Uint32(key[0:4]) ++ state[5] = binary.LittleEndian.Uint32(key[4:8]) ++ state[6] = binary.LittleEndian.Uint32(key[8:12]) ++ state[7] = binary.LittleEndian.Uint32(key[12:16]) ++ state[8] = binary.LittleEndian.Uint32(key[16:20]) ++ state[9] = binary.LittleEndian.Uint32(key[20:24]) ++ state[10] = binary.LittleEndian.Uint32(key[24:28]) ++ state[11] = binary.LittleEndian.Uint32(key[28:32]) ++ ++ state[12] = 0 ++ state[13] = binary.LittleEndian.Uint32(nonce[0:4]) ++ state[14] = binary.LittleEndian.Uint32(nonce[4:8]) ++ state[15] = binary.LittleEndian.Uint32(nonce[8:12]) ++} ++ ++func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { ++ if !cpu.X86.HasSSSE3 { ++ return c.sealGeneric(dst, nonce, plaintext, additionalData) ++ } ++ ++ var state [16]uint32 ++ setupState(&state, &c.key, nonce) ++ ++ ret, out := sliceForAppend(dst, len(plaintext)+16) ++ if alias.InexactOverlap(out, plaintext) { ++ panic("chacha20poly1305: invalid buffer overlap") ++ } ++ chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData) ++ return ret ++} ++ ++func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { ++ if !cpu.X86.HasSSSE3 { ++ return c.openGeneric(dst, nonce, ciphertext, additionalData) ++ } ++ ++ var state [16]uint32 ++ setupState(&state, &c.key, nonce) ++ ++ ciphertext = ciphertext[:len(ciphertext)-16] ++ ret, out := sliceForAppend(dst, len(ciphertext)) ++ if alias.InexactOverlap(out, ciphertext) { ++ panic("chacha20poly1305: invalid buffer overlap") ++ } ++ if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) { ++ for i := range out { ++ out[i] = 0 ++ } ++ return nil, errOpen ++ } ++ ++ return ret, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s +new file mode 100644 +index 00000000000000..867c181a14c074 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s +@@ -0,0 +1,2696 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "textflag.h" ++// General register allocation ++#define oup DI ++#define inp SI ++#define inl BX ++#define adp CX // free to reuse, after we hash the additional data ++#define keyp R8 // free to reuse, when we copy the key to stack ++#define itr2 R9 // general iterator ++#define itr1 CX // general iterator ++#define acc0 R10 ++#define acc1 R11 ++#define acc2 R12 ++#define t0 R13 ++#define t1 R14 ++#define t2 R15 ++#define t3 R8 ++// Register and stack allocation for the SSE code ++#define rStore (0*16)(BP) ++#define sStore (1*16)(BP) ++#define state1Store (2*16)(BP) ++#define state2Store (3*16)(BP) ++#define tmpStore (4*16)(BP) ++#define ctr0Store (5*16)(BP) ++#define ctr1Store (6*16)(BP) ++#define ctr2Store (7*16)(BP) ++#define ctr3Store (8*16)(BP) ++#define A0 X0 ++#define A1 X1 ++#define A2 X2 ++#define B0 X3 ++#define B1 X4 ++#define B2 X5 ++#define C0 X6 ++#define C1 X7 ++#define C2 X8 ++#define D0 X9 ++#define D1 X10 ++#define D2 X11 ++#define T0 X12 ++#define T1 X13 ++#define T2 X14 ++#define T3 X15 ++#define A3 T0 ++#define B3 T1 ++#define C3 T2 ++#define D3 T3 ++// Register and stack allocation for the AVX2 code ++#define rsStoreAVX2 (0*32)(BP) ++#define state1StoreAVX2 (1*32)(BP) ++#define state2StoreAVX2 (2*32)(BP) ++#define ctr0StoreAVX2 (3*32)(BP) ++#define ctr1StoreAVX2 (4*32)(BP) ++#define ctr2StoreAVX2 (5*32)(BP) ++#define ctr3StoreAVX2 (6*32)(BP) ++#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack ++#define AA0 Y0 ++#define AA1 Y5 ++#define AA2 Y6 ++#define AA3 Y7 ++#define BB0 Y14 ++#define BB1 Y9 ++#define BB2 Y10 ++#define BB3 Y11 ++#define CC0 Y12 ++#define CC1 Y13 ++#define CC2 Y8 ++#define CC3 Y15 ++#define DD0 Y4 ++#define DD1 Y1 ++#define DD2 Y2 ++#define DD3 Y3 ++#define TT0 DD3 ++#define TT1 AA3 ++#define TT2 BB3 ++#define TT3 CC3 ++// ChaCha20 constants ++DATA Β·chacha20Constants<>+0x00(SB)/4, $0x61707865 ++DATA Β·chacha20Constants<>+0x04(SB)/4, $0x3320646e ++DATA Β·chacha20Constants<>+0x08(SB)/4, $0x79622d32 ++DATA Β·chacha20Constants<>+0x0c(SB)/4, $0x6b206574 ++DATA Β·chacha20Constants<>+0x10(SB)/4, $0x61707865 ++DATA Β·chacha20Constants<>+0x14(SB)/4, $0x3320646e ++DATA Β·chacha20Constants<>+0x18(SB)/4, $0x79622d32 ++DATA Β·chacha20Constants<>+0x1c(SB)/4, $0x6b206574 ++// <<< 16 with PSHUFB ++DATA Β·rol16<>+0x00(SB)/8, $0x0504070601000302 ++DATA Β·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A ++DATA Β·rol16<>+0x10(SB)/8, $0x0504070601000302 ++DATA Β·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A ++// <<< 8 with PSHUFB ++DATA Β·rol8<>+0x00(SB)/8, $0x0605040702010003 ++DATA Β·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B ++DATA Β·rol8<>+0x10(SB)/8, $0x0605040702010003 ++DATA Β·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B ++ ++DATA Β·avx2InitMask<>+0x00(SB)/8, $0x0 ++DATA Β·avx2InitMask<>+0x08(SB)/8, $0x0 ++DATA Β·avx2InitMask<>+0x10(SB)/8, $0x1 ++DATA Β·avx2InitMask<>+0x18(SB)/8, $0x0 ++ ++DATA Β·avx2IncMask<>+0x00(SB)/8, $0x2 ++DATA Β·avx2IncMask<>+0x08(SB)/8, $0x0 ++DATA Β·avx2IncMask<>+0x10(SB)/8, $0x2 ++DATA Β·avx2IncMask<>+0x18(SB)/8, $0x0 ++// Poly1305 key clamp ++DATA Β·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF ++DATA Β·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC ++DATA Β·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF ++DATA Β·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF ++ ++DATA Β·sseIncMask<>+0x00(SB)/8, $0x1 ++DATA Β·sseIncMask<>+0x08(SB)/8, $0x0 ++// To load/store the last < 16 bytes in a buffer ++DATA Β·andMask<>+0x00(SB)/8, $0x00000000000000ff ++DATA Β·andMask<>+0x08(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x10(SB)/8, $0x000000000000ffff ++DATA Β·andMask<>+0x18(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x20(SB)/8, $0x0000000000ffffff ++DATA Β·andMask<>+0x28(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x30(SB)/8, $0x00000000ffffffff ++DATA Β·andMask<>+0x38(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x40(SB)/8, $0x000000ffffffffff ++DATA Β·andMask<>+0x48(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x50(SB)/8, $0x0000ffffffffffff ++DATA Β·andMask<>+0x58(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x60(SB)/8, $0x00ffffffffffffff ++DATA Β·andMask<>+0x68(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x70(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0x78(SB)/8, $0x0000000000000000 ++DATA Β·andMask<>+0x80(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0x88(SB)/8, $0x00000000000000ff ++DATA Β·andMask<>+0x90(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0x98(SB)/8, $0x000000000000ffff ++DATA Β·andMask<>+0xa0(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0xa8(SB)/8, $0x0000000000ffffff ++DATA Β·andMask<>+0xb0(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0xb8(SB)/8, $0x00000000ffffffff ++DATA Β·andMask<>+0xc0(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0xc8(SB)/8, $0x000000ffffffffff ++DATA Β·andMask<>+0xd0(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff ++DATA Β·andMask<>+0xe0(SB)/8, $0xffffffffffffffff ++DATA Β·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff ++ ++GLOBL Β·chacha20Constants<>(SB), (NOPTR+RODATA), $32 ++GLOBL Β·rol16<>(SB), (NOPTR+RODATA), $32 ++GLOBL Β·rol8<>(SB), (NOPTR+RODATA), $32 ++GLOBL Β·sseIncMask<>(SB), (NOPTR+RODATA), $16 ++GLOBL Β·avx2IncMask<>(SB), (NOPTR+RODATA), $32 ++GLOBL Β·avx2InitMask<>(SB), (NOPTR+RODATA), $32 ++GLOBL Β·polyClampMask<>(SB), (NOPTR+RODATA), $32 ++GLOBL Β·andMask<>(SB), (NOPTR+RODATA), $240 ++// No PALIGNR in Go ASM yet (but VPALIGNR is present). ++#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3 ++#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4 ++#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5 ++#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13 ++#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6 ++#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7 ++#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8 ++#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14 ++#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9 ++#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10 ++#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11 ++#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15 ++#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3 ++#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4 ++#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5 ++#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13 ++#define shiftC0Right shiftC0Left ++#define shiftC1Right shiftC1Left ++#define shiftC2Right shiftC2Left ++#define shiftC3Right shiftC3Left ++#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9 ++#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10 ++#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11 ++#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15 ++// Some macros ++#define chachaQR(A, B, C, D, T) \ ++ PADDD B, A; PXOR A, D; PSHUFB Β·rol16<>(SB), D \ ++ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \ ++ PADDD B, A; PXOR A, D; PSHUFB Β·rol8<>(SB), D \ ++ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B ++ ++#define chachaQR_AVX2(A, B, C, D, T) \ ++ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB Β·rol16<>(SB), D, D \ ++ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \ ++ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB Β·rol8<>(SB), D, D \ ++ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B ++ ++#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2 ++#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2 ++#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX ++#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3 ++#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t3, t2; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2 ++ ++#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2 ++#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3 ++#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3 ++ ++#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage ++#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage ++// ---------------------------------------------------------------------------- ++TEXT polyHashADInternal<>(SB), NOSPLIT, $0 ++ // adp points to beginning of additional data ++ // itr2 holds ad length ++ XORQ acc0, acc0 ++ XORQ acc1, acc1 ++ XORQ acc2, acc2 ++ CMPQ itr2, $13 ++ JNE hashADLoop ++ ++openFastTLSAD: ++ // Special treatment for the TLS case of 13 bytes ++ MOVQ (adp), acc0 ++ MOVQ 5(adp), acc1 ++ SHRQ $24, acc1 ++ MOVQ $1, acc2 ++ polyMul ++ RET ++ ++hashADLoop: ++ // Hash in 16 byte chunks ++ CMPQ itr2, $16 ++ JB hashADTail ++ polyAdd(0(adp)) ++ LEAQ (1*16)(adp), adp ++ SUBQ $16, itr2 ++ polyMul ++ JMP hashADLoop ++ ++hashADTail: ++ CMPQ itr2, $0 ++ JE hashADDone ++ ++ // Hash last < 16 byte tail ++ XORQ t0, t0 ++ XORQ t1, t1 ++ XORQ t2, t2 ++ ADDQ itr2, adp ++ ++hashADTailLoop: ++ SHLQ $8, t0, t1 ++ SHLQ $8, t0 ++ MOVB -1(adp), t2 ++ XORQ t2, t0 ++ DECQ adp ++ DECQ itr2 ++ JNE hashADTailLoop ++ ++hashADTailFinish: ++ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 ++ polyMul ++ ++ // Finished AD ++hashADDone: ++ RET ++ ++// ---------------------------------------------------------------------------- ++// func chacha20Poly1305Open(dst, key, src, ad []byte) bool ++TEXT Β·chacha20Poly1305Open(SB), 0, $288-97 ++ // For aligned stack access ++ MOVQ SP, BP ++ ADDQ $32, BP ++ ANDQ $-32, BP ++ MOVQ dst+0(FP), oup ++ MOVQ key+24(FP), keyp ++ MOVQ src+48(FP), inp ++ MOVQ src_len+56(FP), inl ++ MOVQ ad+72(FP), adp ++ ++ // Check for AVX2 support ++ CMPB Β·useAVX2(SB), $1 ++ JE chacha20Poly1305Open_AVX2 ++ ++ // Special optimization, for very short buffers ++ CMPQ inl, $128 ++ JBE openSSE128 // About 16% faster ++ ++ // For long buffers, prepare the poly key first ++ MOVOU Β·chacha20Constants<>(SB), A0 ++ MOVOU (1*16)(keyp), B0 ++ MOVOU (2*16)(keyp), C0 ++ MOVOU (3*16)(keyp), D0 ++ MOVO D0, T1 ++ ++ // Store state on stack for future use ++ MOVO B0, state1Store ++ MOVO C0, state2Store ++ MOVO D0, ctr3Store ++ MOVQ $10, itr2 ++ ++openSSEPreparePolyKey: ++ chachaQR(A0, B0, C0, D0, T0) ++ shiftB0Left; shiftC0Left; shiftD0Left ++ chachaQR(A0, B0, C0, D0, T0) ++ shiftB0Right; shiftC0Right; shiftD0Right ++ DECQ itr2 ++ JNE openSSEPreparePolyKey ++ ++ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL state1Store, B0 ++ ++ // Clamp and store the key ++ PAND Β·polyClampMask<>(SB), A0 ++ MOVO A0, rStore; MOVO B0, sStore ++ ++ // Hash AAD ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ ++openSSEMainLoop: ++ CMPQ inl, $256 ++ JB openSSEMainLoopDone ++ ++ // Load state, increment counter blocks ++ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0 ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 ++ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 ++ ++ // Store counters ++ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store ++ ++ // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16 ++ MOVQ $4, itr1 ++ MOVQ inp, itr2 ++ ++openSSEInternalLoop: ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ polyAdd(0(itr2)) ++ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left ++ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left ++ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left ++ polyMulStage1 ++ polyMulStage2 ++ LEAQ (2*8)(itr2), itr2 ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ polyMulStage3 ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ polyMulReduceStage ++ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right ++ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right ++ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right ++ DECQ itr1 ++ JGE openSSEInternalLoop ++ ++ polyAdd(0(itr2)) ++ polyMul ++ LEAQ (2*8)(itr2), itr2 ++ ++ CMPQ itr1, $-6 ++ JG openSSEInternalLoop ++ ++ // Add in the state ++ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 ++ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 ++ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 ++ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 ++ ++ // Load - xor - store ++ MOVO D3, tmpStore ++ MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup) ++ MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup) ++ MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup) ++ MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup) ++ MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup) ++ MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup) ++ MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup) ++ MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup) ++ MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup) ++ MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup) ++ MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup) ++ MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup) ++ MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup) ++ MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup) ++ MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup) ++ MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup) ++ LEAQ 256(inp), inp ++ LEAQ 256(oup), oup ++ SUBQ $256, inl ++ JMP openSSEMainLoop ++ ++openSSEMainLoopDone: ++ // Handle the various tail sizes efficiently ++ TESTQ inl, inl ++ JE openSSEFinalize ++ CMPQ inl, $64 ++ JBE openSSETail64 ++ CMPQ inl, $128 ++ JBE openSSETail128 ++ CMPQ inl, $192 ++ JBE openSSETail192 ++ JMP openSSETail256 ++ ++openSSEFinalize: ++ // Hash in the PT, AAD lengths ++ ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2 ++ polyMul ++ ++ // Final reduce ++ MOVQ acc0, t0 ++ MOVQ acc1, t1 ++ MOVQ acc2, t2 ++ SUBQ $-5, acc0 ++ SBBQ $-1, acc1 ++ SBBQ $3, acc2 ++ CMOVQCS t0, acc0 ++ CMOVQCS t1, acc1 ++ CMOVQCS t2, acc2 ++ ++ // Add in the "s" part of the key ++ ADDQ 0+sStore, acc0 ++ ADCQ 8+sStore, acc1 ++ ++ // Finally, constant time compare to the tag at the end of the message ++ XORQ AX, AX ++ MOVQ $1, DX ++ XORQ (0*8)(inp), acc0 ++ XORQ (1*8)(inp), acc1 ++ ORQ acc1, acc0 ++ CMOVQEQ DX, AX ++ ++ // Return true iff tags are equal ++ MOVB AX, ret+96(FP) ++ RET ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for buffers smaller than 129 bytes ++openSSE128: ++ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks ++ MOVOU Β·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 ++ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 ++ MOVQ $10, itr2 ++ ++openSSE128InnerCipherLoop: ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Left; shiftB1Left; shiftB2Left ++ shiftC0Left; shiftC1Left; shiftC2Left ++ shiftD0Left; shiftD1Left; shiftD2Left ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Right; shiftB1Right; shiftB2Right ++ shiftC0Right; shiftC1Right; shiftC2Right ++ shiftD0Right; shiftD1Right; shiftD2Right ++ DECQ itr2 ++ JNE openSSE128InnerCipherLoop ++ ++ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 ++ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 ++ PADDL T2, C1; PADDL T2, C2 ++ PADDL T3, D1; PADDL Β·sseIncMask<>(SB), T3; PADDL T3, D2 ++ ++ // Clamp and store the key ++ PAND Β·polyClampMask<>(SB), A0 ++ MOVOU A0, rStore; MOVOU B0, sStore ++ ++ // Hash ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ ++openSSE128Open: ++ CMPQ inl, $16 ++ JB openSSETail16 ++ SUBQ $16, inl ++ ++ // Load for hashing ++ polyAdd(0(inp)) ++ ++ // Load for decryption ++ MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup) ++ LEAQ (1*16)(inp), inp ++ LEAQ (1*16)(oup), oup ++ polyMul ++ ++ // Shift the stream "left" ++ MOVO B1, A1 ++ MOVO C1, B1 ++ MOVO D1, C1 ++ MOVO A2, D1 ++ MOVO B2, A2 ++ MOVO C2, B2 ++ MOVO D2, C2 ++ JMP openSSE128Open ++ ++openSSETail16: ++ TESTQ inl, inl ++ JE openSSEFinalize ++ ++ // We can safely load the CT from the end, because it is padded with the MAC ++ MOVQ inl, itr2 ++ SHLQ $4, itr2 ++ LEAQ Β·andMask<>(SB), t0 ++ MOVOU (inp), T0 ++ ADDQ inl, inp ++ PAND -16(t0)(itr2*1), T0 ++ MOVO T0, 0+tmpStore ++ MOVQ T0, t0 ++ MOVQ 8+tmpStore, t1 ++ PXOR A1, T0 ++ ++ // We can only store one byte at a time, since plaintext can be shorter than 16 bytes ++openSSETail16Store: ++ MOVQ T0, t3 ++ MOVB t3, (oup) ++ PSRLDQ $1, T0 ++ INCQ oup ++ DECQ inl ++ JNE openSSETail16Store ++ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 ++ polyMul ++ JMP openSSEFinalize ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 64 bytes of ciphertext ++openSSETail64: ++ // Need to decrypt up to 64 bytes - prepare single block ++ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr0Store ++ XORQ itr2, itr2 ++ MOVQ inl, itr1 ++ CMPQ itr1, $16 ++ JB openSSETail64LoopB ++ ++openSSETail64LoopA: ++ // Perform ChaCha rounds, while hashing the remaining input ++ polyAdd(0(inp)(itr2*1)) ++ polyMul ++ SUBQ $16, itr1 ++ ++openSSETail64LoopB: ++ ADDQ $16, itr2 ++ chachaQR(A0, B0, C0, D0, T0) ++ shiftB0Left; shiftC0Left; shiftD0Left ++ chachaQR(A0, B0, C0, D0, T0) ++ shiftB0Right; shiftC0Right; shiftD0Right ++ ++ CMPQ itr1, $16 ++ JAE openSSETail64LoopA ++ ++ CMPQ itr2, $160 ++ JNE openSSETail64LoopB ++ ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0 ++ ++openSSETail64DecLoop: ++ CMPQ inl, $16 ++ JB openSSETail64DecLoopDone ++ SUBQ $16, inl ++ MOVOU (inp), T0 ++ PXOR T0, A0 ++ MOVOU A0, (oup) ++ LEAQ 16(inp), inp ++ LEAQ 16(oup), oup ++ MOVO B0, A0 ++ MOVO C0, B0 ++ MOVO D0, C0 ++ JMP openSSETail64DecLoop ++ ++openSSETail64DecLoopDone: ++ MOVO A0, A1 ++ JMP openSSETail16 ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 128 bytes of ciphertext ++openSSETail128: ++ // Need to decrypt up to 128 bytes - prepare two blocks ++ MOVO Β·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr0Store ++ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr1Store ++ XORQ itr2, itr2 ++ MOVQ inl, itr1 ++ ANDQ $-16, itr1 ++ ++openSSETail128LoopA: ++ // Perform ChaCha rounds, while hashing the remaining input ++ polyAdd(0(inp)(itr2*1)) ++ polyMul ++ ++openSSETail128LoopB: ++ ADDQ $16, itr2 ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) ++ shiftB0Left; shiftC0Left; shiftD0Left ++ shiftB1Left; shiftC1Left; shiftD1Left ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) ++ shiftB0Right; shiftC0Right; shiftD0Right ++ shiftB1Right; shiftC1Right; shiftD1Right ++ ++ CMPQ itr2, itr1 ++ JB openSSETail128LoopA ++ ++ CMPQ itr2, $160 ++ JNE openSSETail128LoopB ++ ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1 ++ PADDL state1Store, B0; PADDL state1Store, B1 ++ PADDL state2Store, C0; PADDL state2Store, C1 ++ PADDL ctr1Store, D0; PADDL ctr0Store, D1 ++ ++ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 ++ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 ++ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) ++ ++ SUBQ $64, inl ++ LEAQ 64(inp), inp ++ LEAQ 64(oup), oup ++ JMP openSSETail64DecLoop ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 192 bytes of ciphertext ++openSSETail192: ++ // Need to decrypt up to 192 bytes - prepare three blocks ++ MOVO Β·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL Β·sseIncMask<>(SB), D2; MOVO D2, ctr0Store ++ MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr1Store ++ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr2Store ++ ++ MOVQ inl, itr1 ++ MOVQ $160, itr2 ++ CMPQ itr1, $160 ++ CMOVQGT itr2, itr1 ++ ANDQ $-16, itr1 ++ XORQ itr2, itr2 ++ ++openSSLTail192LoopA: ++ // Perform ChaCha rounds, while hashing the remaining input ++ polyAdd(0(inp)(itr2*1)) ++ polyMul ++ ++openSSLTail192LoopB: ++ ADDQ $16, itr2 ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Left; shiftC0Left; shiftD0Left ++ shiftB1Left; shiftC1Left; shiftD1Left ++ shiftB2Left; shiftC2Left; shiftD2Left ++ ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Right; shiftC0Right; shiftD0Right ++ shiftB1Right; shiftC1Right; shiftD1Right ++ shiftB2Right; shiftC2Right; shiftD2Right ++ ++ CMPQ itr2, itr1 ++ JB openSSLTail192LoopA ++ ++ CMPQ itr2, $160 ++ JNE openSSLTail192LoopB ++ ++ CMPQ inl, $176 ++ JB openSSLTail192Store ++ ++ polyAdd(160(inp)) ++ polyMul ++ ++ CMPQ inl, $192 ++ JB openSSLTail192Store ++ ++ polyAdd(176(inp)) ++ polyMul ++ ++openSSLTail192Store: ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 ++ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 ++ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 ++ PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2 ++ ++ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 ++ PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2 ++ MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup) ++ ++ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 ++ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 ++ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) ++ ++ SUBQ $128, inl ++ LEAQ 128(inp), inp ++ LEAQ 128(oup), oup ++ JMP openSSETail64DecLoop ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 256 bytes of ciphertext ++openSSETail256: ++ // Need to decrypt up to 256 bytes - prepare four blocks ++ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0 ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 ++ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 ++ ++ // Store counters ++ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store ++ XORQ itr2, itr2 ++ ++openSSETail256Loop: ++ // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication ++ polyAdd(0(inp)(itr2*1)) ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left ++ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left ++ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left ++ polyMulStage1 ++ polyMulStage2 ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ polyMulStage3 ++ polyMulReduceStage ++ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right ++ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right ++ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right ++ ADDQ $2*8, itr2 ++ CMPQ itr2, $160 ++ JB openSSETail256Loop ++ MOVQ inl, itr1 ++ ANDQ $-16, itr1 ++ ++openSSETail256HashLoop: ++ polyAdd(0(inp)(itr2*1)) ++ polyMul ++ ADDQ $2*8, itr2 ++ CMPQ itr2, itr1 ++ JB openSSETail256HashLoop ++ ++ // Add in the state ++ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 ++ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 ++ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 ++ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 ++ MOVO D3, tmpStore ++ ++ // Load - xor - store ++ MOVOU (0*16)(inp), D3; PXOR D3, A0 ++ MOVOU (1*16)(inp), D3; PXOR D3, B0 ++ MOVOU (2*16)(inp), D3; PXOR D3, C0 ++ MOVOU (3*16)(inp), D3; PXOR D3, D0 ++ MOVOU A0, (0*16)(oup) ++ MOVOU B0, (1*16)(oup) ++ MOVOU C0, (2*16)(oup) ++ MOVOU D0, (3*16)(oup) ++ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 ++ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 ++ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) ++ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 ++ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 ++ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) ++ LEAQ 192(inp), inp ++ LEAQ 192(oup), oup ++ SUBQ $192, inl ++ MOVO A3, A0 ++ MOVO B3, B0 ++ MOVO C3, C0 ++ MOVO tmpStore, D0 ++ ++ JMP openSSETail64DecLoop ++ ++// ---------------------------------------------------------------------------- ++// ------------------------- AVX2 Code ---------------------------------------- ++chacha20Poly1305Open_AVX2: ++ VZEROUPPER ++ VMOVDQU Β·chacha20Constants<>(SB), AA0 ++ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 ++ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 ++ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 ++ VPADDD Β·avx2InitMask<>(SB), DD0, DD0 ++ ++ // Special optimization, for very short buffers ++ CMPQ inl, $192 ++ JBE openAVX2192 ++ CMPQ inl, $320 ++ JBE openAVX2320 ++ ++ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream ++ VMOVDQA BB0, state1StoreAVX2 ++ VMOVDQA CC0, state2StoreAVX2 ++ VMOVDQA DD0, ctr3StoreAVX2 ++ MOVQ $10, itr2 ++ ++openAVX2PreparePolyKey: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 ++ DECQ itr2 ++ JNE openAVX2PreparePolyKey ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0 ++ VPADDD state1StoreAVX2, BB0, BB0 ++ VPADDD state2StoreAVX2, CC0, CC0 ++ VPADDD ctr3StoreAVX2, DD0, DD0 ++ ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ ++ // Clamp and store poly key ++ VPAND Β·polyClampMask<>(SB), TT0, TT0 ++ VMOVDQA TT0, rsStoreAVX2 ++ ++ // Stream for the first 64 bytes ++ VPERM2I128 $0x13, AA0, BB0, AA0 ++ VPERM2I128 $0x13, CC0, DD0, BB0 ++ ++ // Hash AD + first 64 bytes ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ XORQ itr1, itr1 ++ ++openAVX2InitialHash64: ++ polyAdd(0(inp)(itr1*1)) ++ polyMulAVX2 ++ ADDQ $16, itr1 ++ CMPQ itr1, $64 ++ JNE openAVX2InitialHash64 ++ ++ // Decrypt the first 64 bytes ++ VPXOR (0*32)(inp), AA0, AA0 ++ VPXOR (1*32)(inp), BB0, BB0 ++ VMOVDQU AA0, (0*32)(oup) ++ VMOVDQU BB0, (1*32)(oup) ++ LEAQ (2*32)(inp), inp ++ LEAQ (2*32)(oup), oup ++ SUBQ $64, inl ++ ++openAVX2MainLoop: ++ CMPQ inl, $512 ++ JB openAVX2MainLoopDone ++ ++ // Load state, increment counter blocks, store the incremented counters ++ VMOVDQU Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 ++ VMOVDQA ctr3StoreAVX2, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 ++ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 ++ XORQ itr1, itr1 ++ ++openAVX2InternalLoop: ++ // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications ++ // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext ++ polyAdd(0*8(inp)(itr1*1)) ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ polyMulStage1_AVX2 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ polyMulStage2_AVX2 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ polyMulStage3_AVX2 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulReduceStage ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ polyAdd(2*8(inp)(itr1*1)) ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ polyMulStage1_AVX2 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulStage2_AVX2 ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ polyMulStage3_AVX2 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ polyMulReduceStage ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ polyAdd(4*8(inp)(itr1*1)) ++ LEAQ (6*8)(itr1), itr1 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulStage1_AVX2 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ polyMulStage2_AVX2 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ polyMulStage3_AVX2 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulReduceStage ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 ++ CMPQ itr1, $480 ++ JNE openAVX2InternalLoop ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 ++ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ ++ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here ++ polyAdd(480(inp)) ++ polyMulAVX2 ++ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 ++ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 ++ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) ++ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 ++ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) ++ ++ // and here ++ polyAdd(496(inp)) ++ polyMulAVX2 ++ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 ++ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) ++ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 ++ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) ++ LEAQ (32*16)(inp), inp ++ LEAQ (32*16)(oup), oup ++ SUBQ $(32*16), inl ++ JMP openAVX2MainLoop ++ ++openAVX2MainLoopDone: ++ // Handle the various tail sizes efficiently ++ TESTQ inl, inl ++ JE openSSEFinalize ++ CMPQ inl, $128 ++ JBE openAVX2Tail128 ++ CMPQ inl, $256 ++ JBE openAVX2Tail256 ++ CMPQ inl, $384 ++ JBE openAVX2Tail384 ++ JMP openAVX2Tail512 ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for buffers smaller than 193 bytes ++openAVX2192: ++ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks ++ VMOVDQA AA0, AA1 ++ VMOVDQA BB0, BB1 ++ VMOVDQA CC0, CC1 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VMOVDQA AA0, AA2 ++ VMOVDQA BB0, BB2 ++ VMOVDQA CC0, CC2 ++ VMOVDQA DD0, DD2 ++ VMOVDQA DD1, TT3 ++ MOVQ $10, itr2 ++ ++openAVX2192InnerCipherLoop: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 ++ DECQ itr2 ++ JNE openAVX2192InnerCipherLoop ++ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 ++ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 ++ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 ++ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ ++ // Clamp and store poly key ++ VPAND Β·polyClampMask<>(SB), TT0, TT0 ++ VMOVDQA TT0, rsStoreAVX2 ++ ++ // Stream for up to 192 bytes ++ VPERM2I128 $0x13, AA0, BB0, AA0 ++ VPERM2I128 $0x13, CC0, DD0, BB0 ++ VPERM2I128 $0x02, AA1, BB1, CC0 ++ VPERM2I128 $0x02, CC1, DD1, DD0 ++ VPERM2I128 $0x13, AA1, BB1, AA1 ++ VPERM2I128 $0x13, CC1, DD1, BB1 ++ ++openAVX2ShortOpen: ++ // Hash ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ ++openAVX2ShortOpenLoop: ++ CMPQ inl, $32 ++ JB openAVX2ShortTail32 ++ SUBQ $32, inl ++ ++ // Load for hashing ++ polyAdd(0*8(inp)) ++ polyMulAVX2 ++ polyAdd(2*8(inp)) ++ polyMulAVX2 ++ ++ // Load for decryption ++ VPXOR (inp), AA0, AA0 ++ VMOVDQU AA0, (oup) ++ LEAQ (1*32)(inp), inp ++ LEAQ (1*32)(oup), oup ++ ++ // Shift stream left ++ VMOVDQA BB0, AA0 ++ VMOVDQA CC0, BB0 ++ VMOVDQA DD0, CC0 ++ VMOVDQA AA1, DD0 ++ VMOVDQA BB1, AA1 ++ VMOVDQA CC1, BB1 ++ VMOVDQA DD1, CC1 ++ VMOVDQA AA2, DD1 ++ VMOVDQA BB2, AA2 ++ JMP openAVX2ShortOpenLoop ++ ++openAVX2ShortTail32: ++ CMPQ inl, $16 ++ VMOVDQA A0, A1 ++ JB openAVX2ShortDone ++ ++ SUBQ $16, inl ++ ++ // Load for hashing ++ polyAdd(0*8(inp)) ++ polyMulAVX2 ++ ++ // Load for decryption ++ VPXOR (inp), A0, T0 ++ VMOVDQU T0, (oup) ++ LEAQ (1*16)(inp), inp ++ LEAQ (1*16)(oup), oup ++ VPERM2I128 $0x11, AA0, AA0, AA0 ++ VMOVDQA A0, A1 ++ ++openAVX2ShortDone: ++ VZEROUPPER ++ JMP openSSETail16 ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for buffers smaller than 321 bytes ++openAVX2320: ++ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks ++ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD Β·avx2IncMask<>(SB), DD1, DD2 ++ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 ++ MOVQ $10, itr2 ++ ++openAVX2320InnerCipherLoop: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 ++ DECQ itr2 ++ JNE openAVX2320InnerCipherLoop ++ ++ VMOVDQA Β·chacha20Constants<>(SB), TT0 ++ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 ++ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 ++ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 ++ VMOVDQA Β·avx2IncMask<>(SB), TT0 ++ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 ++ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 ++ VPADDD TT3, DD2, DD2 ++ ++ // Clamp and store poly key ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ VPAND Β·polyClampMask<>(SB), TT0, TT0 ++ VMOVDQA TT0, rsStoreAVX2 ++ ++ // Stream for up to 320 bytes ++ VPERM2I128 $0x13, AA0, BB0, AA0 ++ VPERM2I128 $0x13, CC0, DD0, BB0 ++ VPERM2I128 $0x02, AA1, BB1, CC0 ++ VPERM2I128 $0x02, CC1, DD1, DD0 ++ VPERM2I128 $0x13, AA1, BB1, AA1 ++ VPERM2I128 $0x13, CC1, DD1, BB1 ++ VPERM2I128 $0x02, AA2, BB2, CC1 ++ VPERM2I128 $0x02, CC2, DD2, DD1 ++ VPERM2I128 $0x13, AA2, BB2, AA2 ++ VPERM2I128 $0x13, CC2, DD2, BB2 ++ JMP openAVX2ShortOpen ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 128 bytes of ciphertext ++openAVX2Tail128: ++ // Need to decrypt up to 128 bytes - prepare two blocks ++ VMOVDQA Β·chacha20Constants<>(SB), AA1 ++ VMOVDQA state1StoreAVX2, BB1 ++ VMOVDQA state2StoreAVX2, CC1 ++ VMOVDQA ctr3StoreAVX2, DD1 ++ VPADDD Β·avx2IncMask<>(SB), DD1, DD1 ++ VMOVDQA DD1, DD0 ++ ++ XORQ itr2, itr2 ++ MOVQ inl, itr1 ++ ANDQ $-16, itr1 ++ TESTQ itr1, itr1 ++ JE openAVX2Tail128LoopB ++ ++openAVX2Tail128LoopA: ++ // Perform ChaCha rounds, while hashing the remaining input ++ polyAdd(0(inp)(itr2*1)) ++ polyMulAVX2 ++ ++openAVX2Tail128LoopB: ++ ADDQ $16, itr2 ++ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $4, BB1, BB1, BB1 ++ VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $12, DD1, DD1, DD1 ++ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $12, BB1, BB1, BB1 ++ VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $4, DD1, DD1, DD1 ++ CMPQ itr2, itr1 ++ JB openAVX2Tail128LoopA ++ CMPQ itr2, $160 ++ JNE openAVX2Tail128LoopB ++ ++ VPADDD Β·chacha20Constants<>(SB), AA1, AA1 ++ VPADDD state1StoreAVX2, BB1, BB1 ++ VPADDD state2StoreAVX2, CC1, CC1 ++ VPADDD DD0, DD1, DD1 ++ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 ++ ++openAVX2TailLoop: ++ CMPQ inl, $32 ++ JB openAVX2Tail ++ SUBQ $32, inl ++ ++ // Load for decryption ++ VPXOR (inp), AA0, AA0 ++ VMOVDQU AA0, (oup) ++ LEAQ (1*32)(inp), inp ++ LEAQ (1*32)(oup), oup ++ VMOVDQA BB0, AA0 ++ VMOVDQA CC0, BB0 ++ VMOVDQA DD0, CC0 ++ JMP openAVX2TailLoop ++ ++openAVX2Tail: ++ CMPQ inl, $16 ++ VMOVDQA A0, A1 ++ JB openAVX2TailDone ++ SUBQ $16, inl ++ ++ // Load for decryption ++ VPXOR (inp), A0, T0 ++ VMOVDQU T0, (oup) ++ LEAQ (1*16)(inp), inp ++ LEAQ (1*16)(oup), oup ++ VPERM2I128 $0x11, AA0, AA0, AA0 ++ VMOVDQA A0, A1 ++ ++openAVX2TailDone: ++ VZEROUPPER ++ JMP openSSETail16 ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 256 bytes of ciphertext ++openAVX2Tail256: ++ // Need to decrypt up to 256 bytes - prepare four blocks ++ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VMOVDQA DD0, TT1 ++ VMOVDQA DD1, TT2 ++ ++ // Compute the number of iterations that will hash data ++ MOVQ inl, tmpStoreAVX2 ++ MOVQ inl, itr1 ++ SUBQ $128, itr1 ++ SHRQ $4, itr1 ++ MOVQ $10, itr2 ++ CMPQ itr1, $10 ++ CMOVQGT itr2, itr1 ++ MOVQ inp, inl ++ XORQ itr2, itr2 ++ ++openAVX2Tail256LoopA: ++ polyAdd(0(inl)) ++ polyMulAVX2 ++ LEAQ 16(inl), inl ++ ++ // Perform ChaCha rounds, while hashing the remaining input ++openAVX2Tail256LoopB: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 ++ INCQ itr2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 ++ CMPQ itr2, itr1 ++ JB openAVX2Tail256LoopA ++ ++ CMPQ itr2, $10 ++ JNE openAVX2Tail256LoopB ++ ++ MOVQ inl, itr2 ++ SUBQ inp, inl ++ MOVQ inl, itr1 ++ MOVQ tmpStoreAVX2, inl ++ ++ // Hash the remainder of data (if any) ++openAVX2Tail256Hash: ++ ADDQ $16, itr1 ++ CMPQ itr1, inl ++ JGT openAVX2Tail256HashEnd ++ polyAdd (0(itr2)) ++ polyMulAVX2 ++ LEAQ 16(itr2), itr2 ++ JMP openAVX2Tail256Hash ++ ++// Store 128 bytes safely, then go to store loop ++openAVX2Tail256HashEnd: ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 ++ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 ++ VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2 ++ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 ++ ++ VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2 ++ VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup) ++ LEAQ (4*32)(inp), inp ++ LEAQ (4*32)(oup), oup ++ SUBQ $4*32, inl ++ ++ JMP openAVX2TailLoop ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 384 bytes of ciphertext ++openAVX2Tail384: ++ // Need to decrypt up to 384 bytes - prepare six blocks ++ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VPADDD Β·avx2IncMask<>(SB), DD1, DD2 ++ VMOVDQA DD0, ctr0StoreAVX2 ++ VMOVDQA DD1, ctr1StoreAVX2 ++ VMOVDQA DD2, ctr2StoreAVX2 ++ ++ // Compute the number of iterations that will hash two blocks of data ++ MOVQ inl, tmpStoreAVX2 ++ MOVQ inl, itr1 ++ SUBQ $256, itr1 ++ SHRQ $4, itr1 ++ ADDQ $6, itr1 ++ MOVQ $10, itr2 ++ CMPQ itr1, $10 ++ CMOVQGT itr2, itr1 ++ MOVQ inp, inl ++ XORQ itr2, itr2 ++ ++ // Perform ChaCha rounds, while hashing the remaining input ++openAVX2Tail384LoopB: ++ polyAdd(0(inl)) ++ polyMulAVX2 ++ LEAQ 16(inl), inl ++ ++openAVX2Tail384LoopA: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 ++ polyAdd(0(inl)) ++ polyMulAVX2 ++ LEAQ 16(inl), inl ++ INCQ itr2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 ++ ++ CMPQ itr2, itr1 ++ JB openAVX2Tail384LoopB ++ ++ CMPQ itr2, $10 ++ JNE openAVX2Tail384LoopA ++ ++ MOVQ inl, itr2 ++ SUBQ inp, inl ++ MOVQ inl, itr1 ++ MOVQ tmpStoreAVX2, inl ++ ++openAVX2Tail384Hash: ++ ADDQ $16, itr1 ++ CMPQ itr1, inl ++ JGT openAVX2Tail384HashEnd ++ polyAdd(0(itr2)) ++ polyMulAVX2 ++ LEAQ 16(itr2), itr2 ++ JMP openAVX2Tail384Hash ++ ++// Store 256 bytes safely, then go to store loop ++openAVX2Tail384HashEnd: ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 ++ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2 ++ VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3 ++ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 ++ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) ++ VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3 ++ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 ++ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) ++ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 ++ LEAQ (8*32)(inp), inp ++ LEAQ (8*32)(oup), oup ++ SUBQ $8*32, inl ++ JMP openAVX2TailLoop ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 512 bytes of ciphertext ++openAVX2Tail512: ++ VMOVDQU Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 ++ VMOVDQA ctr3StoreAVX2, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 ++ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 ++ XORQ itr1, itr1 ++ MOVQ inp, itr2 ++ ++openAVX2Tail512LoopB: ++ polyAdd(0(itr2)) ++ polyMulAVX2 ++ LEAQ (2*8)(itr2), itr2 ++ ++openAVX2Tail512LoopA: ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyAdd(0*8(itr2)) ++ polyMulAVX2 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ polyAdd(2*8(itr2)) ++ polyMulAVX2 ++ LEAQ (4*8)(itr2), itr2 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 ++ INCQ itr1 ++ CMPQ itr1, $4 ++ JLT openAVX2Tail512LoopB ++ ++ CMPQ itr1, $10 ++ JNE openAVX2Tail512LoopA ++ ++ MOVQ inl, itr1 ++ SUBQ $384, itr1 ++ ANDQ $-16, itr1 ++ ++openAVX2Tail512HashLoop: ++ TESTQ itr1, itr1 ++ JE openAVX2Tail512HashEnd ++ polyAdd(0(itr2)) ++ polyMulAVX2 ++ LEAQ 16(itr2), itr2 ++ SUBQ $16, itr1 ++ JMP openAVX2Tail512HashLoop ++ ++openAVX2Tail512HashEnd: ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 ++ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 ++ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 ++ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) ++ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 ++ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) ++ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 ++ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) ++ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 ++ ++ LEAQ (12*32)(inp), inp ++ LEAQ (12*32)(oup), oup ++ SUBQ $12*32, inl ++ ++ JMP openAVX2TailLoop ++ ++// ---------------------------------------------------------------------------- ++// ---------------------------------------------------------------------------- ++// func chacha20Poly1305Seal(dst, key, src, ad []byte) ++TEXT Β·chacha20Poly1305Seal(SB), 0, $288-96 ++ // For aligned stack access ++ MOVQ SP, BP ++ ADDQ $32, BP ++ ANDQ $-32, BP ++ MOVQ dst+0(FP), oup ++ MOVQ key+24(FP), keyp ++ MOVQ src+48(FP), inp ++ MOVQ src_len+56(FP), inl ++ MOVQ ad+72(FP), adp ++ ++ CMPB Β·useAVX2(SB), $1 ++ JE chacha20Poly1305Seal_AVX2 ++ ++ // Special optimization, for very short buffers ++ CMPQ inl, $128 ++ JBE sealSSE128 // About 15% faster ++ ++ // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration ++ MOVOU Β·chacha20Constants<>(SB), A0 ++ MOVOU (1*16)(keyp), B0 ++ MOVOU (2*16)(keyp), C0 ++ MOVOU (3*16)(keyp), D0 ++ ++ // Store state on stack for future use ++ MOVO B0, state1Store ++ MOVO C0, state2Store ++ ++ // Load state, increment counter blocks ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 ++ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 ++ ++ // Store counters ++ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store ++ MOVQ $10, itr2 ++ ++sealSSEIntroLoop: ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left ++ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left ++ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left ++ ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right ++ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right ++ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right ++ DECQ itr2 ++ JNE sealSSEIntroLoop ++ ++ // Add in the state ++ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 ++ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 ++ PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 ++ PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 ++ ++ // Clamp and store the key ++ PAND Β·polyClampMask<>(SB), A0 ++ MOVO A0, rStore ++ MOVO B0, sStore ++ ++ // Hash AAD ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ ++ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 ++ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 ++ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) ++ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 ++ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 ++ MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup) ++ ++ MOVQ $128, itr1 ++ SUBQ $128, inl ++ LEAQ 128(inp), inp ++ ++ MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1 ++ ++ CMPQ inl, $64 ++ JBE sealSSE128SealHash ++ ++ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 ++ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 ++ MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup) ++ ++ ADDQ $64, itr1 ++ SUBQ $64, inl ++ LEAQ 64(inp), inp ++ ++ MOVQ $2, itr1 ++ MOVQ $8, itr2 ++ ++ CMPQ inl, $64 ++ JBE sealSSETail64 ++ CMPQ inl, $128 ++ JBE sealSSETail128 ++ CMPQ inl, $192 ++ JBE sealSSETail192 ++ ++sealSSEMainLoop: ++ // Load state, increment counter blocks ++ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0 ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 ++ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 ++ ++ // Store counters ++ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store ++ ++sealSSEInnerLoop: ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ polyAdd(0(oup)) ++ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left ++ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left ++ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left ++ polyMulStage1 ++ polyMulStage2 ++ LEAQ (2*8)(oup), oup ++ MOVO C3, tmpStore ++ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) ++ MOVO tmpStore, C3 ++ MOVO C1, tmpStore ++ polyMulStage3 ++ chachaQR(A3, B3, C3, D3, C1) ++ MOVO tmpStore, C1 ++ polyMulReduceStage ++ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right ++ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right ++ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right ++ DECQ itr2 ++ JGE sealSSEInnerLoop ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ (2*8)(oup), oup ++ DECQ itr1 ++ JG sealSSEInnerLoop ++ ++ // Add in the state ++ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 ++ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 ++ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 ++ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 ++ MOVO D3, tmpStore ++ ++ // Load - xor - store ++ MOVOU (0*16)(inp), D3; PXOR D3, A0 ++ MOVOU (1*16)(inp), D3; PXOR D3, B0 ++ MOVOU (2*16)(inp), D3; PXOR D3, C0 ++ MOVOU (3*16)(inp), D3; PXOR D3, D0 ++ MOVOU A0, (0*16)(oup) ++ MOVOU B0, (1*16)(oup) ++ MOVOU C0, (2*16)(oup) ++ MOVOU D0, (3*16)(oup) ++ MOVO tmpStore, D3 ++ ++ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 ++ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 ++ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) ++ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 ++ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 ++ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) ++ ADDQ $192, inp ++ MOVQ $192, itr1 ++ SUBQ $192, inl ++ MOVO A3, A1 ++ MOVO B3, B1 ++ MOVO C3, C1 ++ MOVO D3, D1 ++ CMPQ inl, $64 ++ JBE sealSSE128SealHash ++ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 ++ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 ++ MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup) ++ LEAQ 64(inp), inp ++ SUBQ $64, inl ++ MOVQ $6, itr1 ++ MOVQ $4, itr2 ++ CMPQ inl, $192 ++ JG sealSSEMainLoop ++ ++ MOVQ inl, itr1 ++ TESTQ inl, inl ++ JE sealSSE128SealHash ++ MOVQ $6, itr1 ++ CMPQ inl, $64 ++ JBE sealSSETail64 ++ CMPQ inl, $128 ++ JBE sealSSETail128 ++ JMP sealSSETail192 ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 64 bytes of plaintext ++sealSSETail64: ++ // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes ++ MOVO Β·chacha20Constants<>(SB), A1 ++ MOVO state1Store, B1 ++ MOVO state2Store, C1 ++ MOVO ctr3Store, D1 ++ PADDL Β·sseIncMask<>(SB), D1 ++ MOVO D1, ctr0Store ++ ++sealSSETail64LoopA: ++ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealSSETail64LoopB: ++ chachaQR(A1, B1, C1, D1, T1) ++ shiftB1Left; shiftC1Left; shiftD1Left ++ chachaQR(A1, B1, C1, D1, T1) ++ shiftB1Right; shiftC1Right; shiftD1Right ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++ DECQ itr1 ++ JG sealSSETail64LoopA ++ ++ DECQ itr2 ++ JGE sealSSETail64LoopB ++ PADDL Β·chacha20Constants<>(SB), A1 ++ PADDL state1Store, B1 ++ PADDL state2Store, C1 ++ PADDL ctr0Store, D1 ++ ++ JMP sealSSE128Seal ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 128 bytes of plaintext ++sealSSETail128: ++ // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes ++ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr0Store ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr1Store ++ ++sealSSETail128LoopA: ++ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealSSETail128LoopB: ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) ++ shiftB0Left; shiftC0Left; shiftD0Left ++ shiftB1Left; shiftC1Left; shiftD1Left ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) ++ shiftB0Right; shiftC0Right; shiftD0Right ++ shiftB1Right; shiftC1Right; shiftD1Right ++ ++ DECQ itr1 ++ JG sealSSETail128LoopA ++ ++ DECQ itr2 ++ JGE sealSSETail128LoopB ++ ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1 ++ PADDL state1Store, B0; PADDL state1Store, B1 ++ PADDL state2Store, C0; PADDL state2Store, C1 ++ PADDL ctr0Store, D0; PADDL ctr1Store, D1 ++ ++ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 ++ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 ++ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) ++ ++ MOVQ $64, itr1 ++ LEAQ 64(inp), inp ++ SUBQ $64, inl ++ ++ JMP sealSSE128SealHash ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 192 bytes of plaintext ++sealSSETail192: ++ // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes ++ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr0Store ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr1Store ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2; MOVO D2, ctr2Store ++ ++sealSSETail192LoopA: ++ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealSSETail192LoopB: ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Left; shiftC0Left; shiftD0Left ++ shiftB1Left; shiftC1Left; shiftD1Left ++ shiftB2Left; shiftC2Left; shiftD2Left ++ ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Right; shiftC0Right; shiftD0Right ++ shiftB1Right; shiftC1Right; shiftD1Right ++ shiftB2Right; shiftC2Right; shiftD2Right ++ ++ DECQ itr1 ++ JG sealSSETail192LoopA ++ ++ DECQ itr2 ++ JGE sealSSETail192LoopB ++ ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 ++ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 ++ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 ++ PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2 ++ ++ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 ++ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 ++ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) ++ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 ++ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 ++ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) ++ ++ MOVO A2, A1 ++ MOVO B2, B1 ++ MOVO C2, C1 ++ MOVO D2, D1 ++ MOVQ $128, itr1 ++ LEAQ 128(inp), inp ++ SUBQ $128, inl ++ ++ JMP sealSSE128SealHash ++ ++// ---------------------------------------------------------------------------- ++// Special seal optimization for buffers smaller than 129 bytes ++sealSSE128: ++ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks ++ MOVOU Β·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 ++ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 ++ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 ++ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 ++ MOVQ $10, itr2 ++ ++sealSSE128InnerCipherLoop: ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Left; shiftB1Left; shiftB2Left ++ shiftC0Left; shiftC1Left; shiftC2Left ++ shiftD0Left; shiftD1Left; shiftD2Left ++ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) ++ shiftB0Right; shiftB1Right; shiftB2Right ++ shiftC0Right; shiftC1Right; shiftC2Right ++ shiftD0Right; shiftD1Right; shiftD2Right ++ DECQ itr2 ++ JNE sealSSE128InnerCipherLoop ++ ++ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded ++ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 ++ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 ++ PADDL T2, C1; PADDL T2, C2 ++ PADDL T3, D1; PADDL Β·sseIncMask<>(SB), T3; PADDL T3, D2 ++ PAND Β·polyClampMask<>(SB), A0 ++ MOVOU A0, rStore ++ MOVOU B0, sStore ++ ++ // Hash ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ XORQ itr1, itr1 ++ ++sealSSE128SealHash: ++ // itr1 holds the number of bytes encrypted but not yet hashed ++ CMPQ itr1, $16 ++ JB sealSSE128Seal ++ polyAdd(0(oup)) ++ polyMul ++ ++ SUBQ $16, itr1 ++ ADDQ $16, oup ++ ++ JMP sealSSE128SealHash ++ ++sealSSE128Seal: ++ CMPQ inl, $16 ++ JB sealSSETail ++ SUBQ $16, inl ++ ++ // Load for decryption ++ MOVOU (inp), T0 ++ PXOR T0, A1 ++ MOVOU A1, (oup) ++ LEAQ (1*16)(inp), inp ++ LEAQ (1*16)(oup), oup ++ ++ // Extract for hashing ++ MOVQ A1, t0 ++ PSRLDQ $8, A1 ++ MOVQ A1, t1 ++ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 ++ polyMul ++ ++ // Shift the stream "left" ++ MOVO B1, A1 ++ MOVO C1, B1 ++ MOVO D1, C1 ++ MOVO A2, D1 ++ MOVO B2, A2 ++ MOVO C2, B2 ++ MOVO D2, C2 ++ JMP sealSSE128Seal ++ ++sealSSETail: ++ TESTQ inl, inl ++ JE sealSSEFinalize ++ ++ // We can only load the PT one byte at a time to avoid read after end of buffer ++ MOVQ inl, itr2 ++ SHLQ $4, itr2 ++ LEAQ Β·andMask<>(SB), t0 ++ MOVQ inl, itr1 ++ LEAQ -1(inp)(inl*1), inp ++ XORQ t2, t2 ++ XORQ t3, t3 ++ XORQ AX, AX ++ ++sealSSETailLoadLoop: ++ SHLQ $8, t2, t3 ++ SHLQ $8, t2 ++ MOVB (inp), AX ++ XORQ AX, t2 ++ LEAQ -1(inp), inp ++ DECQ itr1 ++ JNE sealSSETailLoadLoop ++ MOVQ t2, 0+tmpStore ++ MOVQ t3, 8+tmpStore ++ PXOR 0+tmpStore, A1 ++ MOVOU A1, (oup) ++ MOVOU -16(t0)(itr2*1), T0 ++ PAND T0, A1 ++ MOVQ A1, t0 ++ PSRLDQ $8, A1 ++ MOVQ A1, t1 ++ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 ++ polyMul ++ ++ ADDQ inl, oup ++ ++sealSSEFinalize: ++ // Hash in the buffer lengths ++ ADDQ ad_len+80(FP), acc0 ++ ADCQ src_len+56(FP), acc1 ++ ADCQ $1, acc2 ++ polyMul ++ ++ // Final reduce ++ MOVQ acc0, t0 ++ MOVQ acc1, t1 ++ MOVQ acc2, t2 ++ SUBQ $-5, acc0 ++ SBBQ $-1, acc1 ++ SBBQ $3, acc2 ++ CMOVQCS t0, acc0 ++ CMOVQCS t1, acc1 ++ CMOVQCS t2, acc2 ++ ++ // Add in the "s" part of the key ++ ADDQ 0+sStore, acc0 ++ ADCQ 8+sStore, acc1 ++ ++ // Finally store the tag at the end of the message ++ MOVQ acc0, (0*8)(oup) ++ MOVQ acc1, (1*8)(oup) ++ RET ++ ++// ---------------------------------------------------------------------------- ++// ------------------------- AVX2 Code ---------------------------------------- ++chacha20Poly1305Seal_AVX2: ++ VZEROUPPER ++ VMOVDQU Β·chacha20Constants<>(SB), AA0 ++ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 ++ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 ++ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 ++ VPADDD Β·avx2InitMask<>(SB), DD0, DD0 ++ ++ // Special optimizations, for very short buffers ++ CMPQ inl, $192 ++ JBE seal192AVX2 // 33% faster ++ CMPQ inl, $320 ++ JBE seal320AVX2 // 17% faster ++ ++ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream ++ VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 ++ VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2 ++ VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2 ++ VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2 ++ VPADDD Β·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2 ++ VMOVDQA DD3, ctr3StoreAVX2 ++ MOVQ $10, itr2 ++ ++sealAVX2IntroLoop: ++ VMOVDQA CC3, tmpStoreAVX2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) ++ VMOVDQA tmpStoreAVX2, CC3 ++ VMOVDQA CC1, tmpStoreAVX2 ++ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) ++ VMOVDQA tmpStoreAVX2, CC1 ++ ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 ++ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 ++ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 ++ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 ++ ++ VMOVDQA CC3, tmpStoreAVX2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) ++ VMOVDQA tmpStoreAVX2, CC3 ++ VMOVDQA CC1, tmpStoreAVX2 ++ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) ++ VMOVDQA tmpStoreAVX2, CC1 ++ ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 ++ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 ++ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 ++ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 ++ DECQ itr2 ++ JNE sealAVX2IntroLoop ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 ++ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 ++ ++ VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127 ++ VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key ++ VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95 ++ ++ // Clamp and store poly key ++ VPAND Β·polyClampMask<>(SB), DD0, DD0 ++ VMOVDQA DD0, rsStoreAVX2 ++ ++ // Hash AD ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ ++ // Can store at least 320 bytes ++ VPXOR (0*32)(inp), AA0, AA0 ++ VPXOR (1*32)(inp), CC0, CC0 ++ VMOVDQU AA0, (0*32)(oup) ++ VMOVDQU CC0, (1*32)(oup) ++ ++ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 ++ VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup) ++ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 ++ VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup) ++ ++ MOVQ $320, itr1 ++ SUBQ $320, inl ++ LEAQ 320(inp), inp ++ ++ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0 ++ CMPQ inl, $128 ++ JBE sealAVX2SealHash ++ ++ VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup) ++ SUBQ $128, inl ++ LEAQ 128(inp), inp ++ ++ MOVQ $8, itr1 ++ MOVQ $2, itr2 ++ ++ CMPQ inl, $128 ++ JBE sealAVX2Tail128 ++ CMPQ inl, $256 ++ JBE sealAVX2Tail256 ++ CMPQ inl, $384 ++ JBE sealAVX2Tail384 ++ CMPQ inl, $512 ++ JBE sealAVX2Tail512 ++ ++ // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop ++ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 ++ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 ++ ++ VMOVDQA CC3, tmpStoreAVX2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) ++ VMOVDQA tmpStoreAVX2, CC3 ++ VMOVDQA CC1, tmpStoreAVX2 ++ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) ++ VMOVDQA tmpStoreAVX2, CC1 ++ ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 ++ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 ++ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 ++ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 ++ ++ VMOVDQA CC3, tmpStoreAVX2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) ++ VMOVDQA tmpStoreAVX2, CC3 ++ VMOVDQA CC1, tmpStoreAVX2 ++ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) ++ VMOVDQA tmpStoreAVX2, CC1 ++ ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 ++ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 ++ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 ++ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ ++ SUBQ $16, oup // Adjust the pointer ++ MOVQ $9, itr1 ++ JMP sealAVX2InternalLoopStart ++ ++sealAVX2MainLoop: ++ // Load state, increment counter blocks, store the incremented counters ++ VMOVDQU Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 ++ VMOVDQA ctr3StoreAVX2, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 ++ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 ++ MOVQ $10, itr1 ++ ++sealAVX2InternalLoop: ++ polyAdd(0*8(oup)) ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ polyMulStage1_AVX2 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ polyMulStage2_AVX2 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ polyMulStage3_AVX2 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulReduceStage ++ ++sealAVX2InternalLoopStart: ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ polyAdd(2*8(oup)) ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ polyMulStage1_AVX2 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulStage2_AVX2 ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ polyMulStage3_AVX2 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ polyMulReduceStage ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ polyAdd(4*8(oup)) ++ LEAQ (6*8)(oup), oup ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulStage1_AVX2 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ polyMulStage2_AVX2 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ polyMulStage3_AVX2 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyMulReduceStage ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 ++ DECQ itr1 ++ JNE sealAVX2InternalLoop ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 ++ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ ++ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here ++ polyAdd(0*8(oup)) ++ polyMulAVX2 ++ LEAQ (4*8)(oup), oup ++ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 ++ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 ++ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) ++ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 ++ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) ++ ++ // and here ++ polyAdd(-2*8(oup)) ++ polyMulAVX2 ++ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 ++ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) ++ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 ++ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) ++ LEAQ (32*16)(inp), inp ++ SUBQ $(32*16), inl ++ CMPQ inl, $512 ++ JG sealAVX2MainLoop ++ ++ // Tail can only hash 480 bytes ++ polyAdd(0*8(oup)) ++ polyMulAVX2 ++ polyAdd(2*8(oup)) ++ polyMulAVX2 ++ LEAQ 32(oup), oup ++ ++ MOVQ $10, itr1 ++ MOVQ $0, itr2 ++ CMPQ inl, $128 ++ JBE sealAVX2Tail128 ++ CMPQ inl, $256 ++ JBE sealAVX2Tail256 ++ CMPQ inl, $384 ++ JBE sealAVX2Tail384 ++ JMP sealAVX2Tail512 ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for buffers smaller than 193 bytes ++seal192AVX2: ++ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks ++ VMOVDQA AA0, AA1 ++ VMOVDQA BB0, BB1 ++ VMOVDQA CC0, CC1 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VMOVDQA AA0, AA2 ++ VMOVDQA BB0, BB2 ++ VMOVDQA CC0, CC2 ++ VMOVDQA DD0, DD2 ++ VMOVDQA DD1, TT3 ++ MOVQ $10, itr2 ++ ++sealAVX2192InnerCipherLoop: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 ++ DECQ itr2 ++ JNE sealAVX2192InnerCipherLoop ++ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 ++ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 ++ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 ++ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ ++ // Clamp and store poly key ++ VPAND Β·polyClampMask<>(SB), TT0, TT0 ++ VMOVDQA TT0, rsStoreAVX2 ++ ++ // Stream for up to 192 bytes ++ VPERM2I128 $0x13, AA0, BB0, AA0 ++ VPERM2I128 $0x13, CC0, DD0, BB0 ++ VPERM2I128 $0x02, AA1, BB1, CC0 ++ VPERM2I128 $0x02, CC1, DD1, DD0 ++ VPERM2I128 $0x13, AA1, BB1, AA1 ++ VPERM2I128 $0x13, CC1, DD1, BB1 ++ ++sealAVX2ShortSeal: ++ // Hash aad ++ MOVQ ad_len+80(FP), itr2 ++ CALL polyHashADInternal<>(SB) ++ XORQ itr1, itr1 ++ ++sealAVX2SealHash: ++ // itr1 holds the number of bytes encrypted but not yet hashed ++ CMPQ itr1, $16 ++ JB sealAVX2ShortSealLoop ++ polyAdd(0(oup)) ++ polyMul ++ SUBQ $16, itr1 ++ ADDQ $16, oup ++ JMP sealAVX2SealHash ++ ++sealAVX2ShortSealLoop: ++ CMPQ inl, $32 ++ JB sealAVX2ShortTail32 ++ SUBQ $32, inl ++ ++ // Load for encryption ++ VPXOR (inp), AA0, AA0 ++ VMOVDQU AA0, (oup) ++ LEAQ (1*32)(inp), inp ++ ++ // Now can hash ++ polyAdd(0*8(oup)) ++ polyMulAVX2 ++ polyAdd(2*8(oup)) ++ polyMulAVX2 ++ LEAQ (1*32)(oup), oup ++ ++ // Shift stream left ++ VMOVDQA BB0, AA0 ++ VMOVDQA CC0, BB0 ++ VMOVDQA DD0, CC0 ++ VMOVDQA AA1, DD0 ++ VMOVDQA BB1, AA1 ++ VMOVDQA CC1, BB1 ++ VMOVDQA DD1, CC1 ++ VMOVDQA AA2, DD1 ++ VMOVDQA BB2, AA2 ++ JMP sealAVX2ShortSealLoop ++ ++sealAVX2ShortTail32: ++ CMPQ inl, $16 ++ VMOVDQA A0, A1 ++ JB sealAVX2ShortDone ++ ++ SUBQ $16, inl ++ ++ // Load for encryption ++ VPXOR (inp), A0, T0 ++ VMOVDQU T0, (oup) ++ LEAQ (1*16)(inp), inp ++ ++ // Hash ++ polyAdd(0*8(oup)) ++ polyMulAVX2 ++ LEAQ (1*16)(oup), oup ++ VPERM2I128 $0x11, AA0, AA0, AA0 ++ VMOVDQA A0, A1 ++ ++sealAVX2ShortDone: ++ VZEROUPPER ++ JMP sealSSETail ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for buffers smaller than 321 bytes ++seal320AVX2: ++ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks ++ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD Β·avx2IncMask<>(SB), DD1, DD2 ++ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 ++ MOVQ $10, itr2 ++ ++sealAVX2320InnerCipherLoop: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 ++ DECQ itr2 ++ JNE sealAVX2320InnerCipherLoop ++ ++ VMOVDQA Β·chacha20Constants<>(SB), TT0 ++ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 ++ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 ++ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 ++ VMOVDQA Β·avx2IncMask<>(SB), TT0 ++ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 ++ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 ++ VPADDD TT3, DD2, DD2 ++ ++ // Clamp and store poly key ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ VPAND Β·polyClampMask<>(SB), TT0, TT0 ++ VMOVDQA TT0, rsStoreAVX2 ++ ++ // Stream for up to 320 bytes ++ VPERM2I128 $0x13, AA0, BB0, AA0 ++ VPERM2I128 $0x13, CC0, DD0, BB0 ++ VPERM2I128 $0x02, AA1, BB1, CC0 ++ VPERM2I128 $0x02, CC1, DD1, DD0 ++ VPERM2I128 $0x13, AA1, BB1, AA1 ++ VPERM2I128 $0x13, CC1, DD1, BB1 ++ VPERM2I128 $0x02, AA2, BB2, CC1 ++ VPERM2I128 $0x02, CC2, DD2, DD1 ++ VPERM2I128 $0x13, AA2, BB2, AA2 ++ VPERM2I128 $0x13, CC2, DD2, BB2 ++ JMP sealAVX2ShortSeal ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 128 bytes of ciphertext ++sealAVX2Tail128: ++ // Need to decrypt up to 128 bytes - prepare two blocks ++ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed ++ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed ++ VMOVDQA Β·chacha20Constants<>(SB), AA0 ++ VMOVDQA state1StoreAVX2, BB0 ++ VMOVDQA state2StoreAVX2, CC0 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 ++ VMOVDQA DD0, DD1 ++ ++sealAVX2Tail128LoopA: ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealAVX2Tail128LoopB: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) ++ polyAdd(0(oup)) ++ polyMul ++ VPALIGNR $4, BB0, BB0, BB0 ++ VPALIGNR $8, CC0, CC0, CC0 ++ VPALIGNR $12, DD0, DD0, DD0 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) ++ polyAdd(16(oup)) ++ polyMul ++ LEAQ 32(oup), oup ++ VPALIGNR $12, BB0, BB0, BB0 ++ VPALIGNR $8, CC0, CC0, CC0 ++ VPALIGNR $4, DD0, DD0, DD0 ++ DECQ itr1 ++ JG sealAVX2Tail128LoopA ++ DECQ itr2 ++ JGE sealAVX2Tail128LoopB ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA1 ++ VPADDD state1StoreAVX2, BB0, BB1 ++ VPADDD state2StoreAVX2, CC0, CC1 ++ VPADDD DD1, DD0, DD1 ++ ++ VPERM2I128 $0x02, AA1, BB1, AA0 ++ VPERM2I128 $0x02, CC1, DD1, BB0 ++ VPERM2I128 $0x13, AA1, BB1, CC0 ++ VPERM2I128 $0x13, CC1, DD1, DD0 ++ JMP sealAVX2ShortSealLoop ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 256 bytes of ciphertext ++sealAVX2Tail256: ++ // Need to decrypt up to 256 bytes - prepare two blocks ++ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed ++ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed ++ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA Β·chacha20Constants<>(SB), AA1 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 ++ VMOVDQA DD0, TT1 ++ VMOVDQA DD1, TT2 ++ ++sealAVX2Tail256LoopA: ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealAVX2Tail256LoopB: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ polyAdd(0(oup)) ++ polyMul ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) ++ polyAdd(16(oup)) ++ polyMul ++ LEAQ 32(oup), oup ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 ++ DECQ itr1 ++ JG sealAVX2Tail256LoopA ++ DECQ itr2 ++ JGE sealAVX2Tail256LoopB ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 ++ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ VPERM2I128 $0x02, CC0, DD0, TT1 ++ VPERM2I128 $0x13, AA0, BB0, TT2 ++ VPERM2I128 $0x13, CC0, DD0, TT3 ++ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 ++ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) ++ MOVQ $128, itr1 ++ LEAQ 128(inp), inp ++ SUBQ $128, inl ++ VPERM2I128 $0x02, AA1, BB1, AA0 ++ VPERM2I128 $0x02, CC1, DD1, BB0 ++ VPERM2I128 $0x13, AA1, BB1, CC0 ++ VPERM2I128 $0x13, CC1, DD1, DD0 ++ ++ JMP sealAVX2SealHash ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 384 bytes of ciphertext ++sealAVX2Tail384: ++ // Need to decrypt up to 384 bytes - prepare two blocks ++ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed ++ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed ++ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2 ++ VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3 ++ ++sealAVX2Tail384LoopA: ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealAVX2Tail384LoopB: ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ polyAdd(0(oup)) ++ polyMul ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 ++ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) ++ polyAdd(16(oup)) ++ polyMul ++ LEAQ 32(oup), oup ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 ++ DECQ itr1 ++ JG sealAVX2Tail384LoopA ++ DECQ itr2 ++ JGE sealAVX2Tail384LoopB ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 ++ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2 ++ VPERM2I128 $0x02, AA0, BB0, TT0 ++ VPERM2I128 $0x02, CC0, DD0, TT1 ++ VPERM2I128 $0x13, AA0, BB0, TT2 ++ VPERM2I128 $0x13, CC0, DD0, TT3 ++ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 ++ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) ++ VPERM2I128 $0x02, AA1, BB1, TT0 ++ VPERM2I128 $0x02, CC1, DD1, TT1 ++ VPERM2I128 $0x13, AA1, BB1, TT2 ++ VPERM2I128 $0x13, CC1, DD1, TT3 ++ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 ++ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) ++ MOVQ $256, itr1 ++ LEAQ 256(inp), inp ++ SUBQ $256, inl ++ VPERM2I128 $0x02, AA2, BB2, AA0 ++ VPERM2I128 $0x02, CC2, DD2, BB0 ++ VPERM2I128 $0x13, AA2, BB2, CC0 ++ VPERM2I128 $0x13, CC2, DD2, DD0 ++ ++ JMP sealAVX2SealHash ++ ++// ---------------------------------------------------------------------------- ++// Special optimization for the last 512 bytes of ciphertext ++sealAVX2Tail512: ++ // Need to decrypt up to 512 bytes - prepare two blocks ++ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed ++ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed ++ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 ++ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 ++ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 ++ VMOVDQA ctr3StoreAVX2, DD0 ++ VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 ++ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 ++ ++sealAVX2Tail512LoopA: ++ polyAdd(0(oup)) ++ polyMul ++ LEAQ 16(oup), oup ++ ++sealAVX2Tail512LoopB: ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ polyAdd(0*8(oup)) ++ polyMulAVX2 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ polyAdd(2*8(oup)) ++ polyMulAVX2 ++ LEAQ (4*8)(oup), oup ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 ++ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 ++ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 ++ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 ++ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 ++ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 ++ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 ++ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 ++ VMOVDQA tmpStoreAVX2, CC3 ++ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 ++ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 ++ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 ++ ++ DECQ itr1 ++ JG sealAVX2Tail512LoopA ++ DECQ itr2 ++ JGE sealAVX2Tail512LoopB ++ ++ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 ++ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 ++ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 ++ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 ++ VMOVDQA CC3, tmpStoreAVX2 ++ VPERM2I128 $0x02, AA0, BB0, CC3 ++ VPXOR (0*32)(inp), CC3, CC3 ++ VMOVDQU CC3, (0*32)(oup) ++ VPERM2I128 $0x02, CC0, DD0, CC3 ++ VPXOR (1*32)(inp), CC3, CC3 ++ VMOVDQU CC3, (1*32)(oup) ++ VPERM2I128 $0x13, AA0, BB0, CC3 ++ VPXOR (2*32)(inp), CC3, CC3 ++ VMOVDQU CC3, (2*32)(oup) ++ VPERM2I128 $0x13, CC0, DD0, CC3 ++ VPXOR (3*32)(inp), CC3, CC3 ++ VMOVDQU CC3, (3*32)(oup) ++ ++ VPERM2I128 $0x02, AA1, BB1, AA0 ++ VPERM2I128 $0x02, CC1, DD1, BB0 ++ VPERM2I128 $0x13, AA1, BB1, CC0 ++ VPERM2I128 $0x13, CC1, DD1, DD0 ++ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) ++ ++ VPERM2I128 $0x02, AA2, BB2, AA0 ++ VPERM2I128 $0x02, CC2, DD2, BB0 ++ VPERM2I128 $0x13, AA2, BB2, CC0 ++ VPERM2I128 $0x13, CC2, DD2, DD0 ++ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 ++ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) ++ ++ MOVQ $384, itr1 ++ LEAQ 384(inp), inp ++ SUBQ $384, inl ++ VPERM2I128 $0x02, AA3, BB3, AA0 ++ VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0 ++ VPERM2I128 $0x13, AA3, BB3, CC0 ++ VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 ++ ++ JMP sealAVX2SealHash +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go +new file mode 100644 +index 00000000000000..6313898f0a75d9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go +@@ -0,0 +1,81 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package chacha20poly1305 ++ ++import ( ++ "encoding/binary" ++ ++ "golang.org/x/crypto/chacha20" ++ "golang.org/x/crypto/internal/alias" ++ "golang.org/x/crypto/internal/poly1305" ++) ++ ++func writeWithPadding(p *poly1305.MAC, b []byte) { ++ p.Write(b) ++ if rem := len(b) % 16; rem != 0 { ++ var buf [16]byte ++ padLen := 16 - rem ++ p.Write(buf[:padLen]) ++ } ++} ++ ++func writeUint64(p *poly1305.MAC, n int) { ++ var buf [8]byte ++ binary.LittleEndian.PutUint64(buf[:], uint64(n)) ++ p.Write(buf[:]) ++} ++ ++func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { ++ ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) ++ ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] ++ if alias.InexactOverlap(out, plaintext) { ++ panic("chacha20poly1305: invalid buffer overlap") ++ } ++ ++ var polyKey [32]byte ++ s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) ++ s.XORKeyStream(polyKey[:], polyKey[:]) ++ s.SetCounter(1) // set the counter to 1, skipping 32 bytes ++ s.XORKeyStream(ciphertext, plaintext) ++ ++ p := poly1305.New(&polyKey) ++ writeWithPadding(p, additionalData) ++ writeWithPadding(p, ciphertext) ++ writeUint64(p, len(additionalData)) ++ writeUint64(p, len(plaintext)) ++ p.Sum(tag[:0]) ++ ++ return ret ++} ++ ++func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { ++ tag := ciphertext[len(ciphertext)-16:] ++ ciphertext = ciphertext[:len(ciphertext)-16] ++ ++ var polyKey [32]byte ++ s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) ++ s.XORKeyStream(polyKey[:], polyKey[:]) ++ s.SetCounter(1) // set the counter to 1, skipping 32 bytes ++ ++ p := poly1305.New(&polyKey) ++ writeWithPadding(p, additionalData) ++ writeWithPadding(p, ciphertext) ++ writeUint64(p, len(additionalData)) ++ writeUint64(p, len(ciphertext)) ++ ++ ret, out := sliceForAppend(dst, len(ciphertext)) ++ if alias.InexactOverlap(out, ciphertext) { ++ panic("chacha20poly1305: invalid buffer overlap") ++ } ++ if !p.Verify(tag) { ++ for i := range out { ++ out[i] = 0 ++ } ++ return nil, errOpen ++ } ++ ++ s.XORKeyStream(out, ciphertext) ++ return ret, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go +new file mode 100644 +index 00000000000000..f832b33d45f208 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go +@@ -0,0 +1,16 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !amd64 || !gc || purego ++// +build !amd64 !gc purego ++ ++package chacha20poly1305 ++ ++func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { ++ return c.sealGeneric(dst, nonce, plaintext, additionalData) ++} ++ ++func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { ++ return c.openGeneric(dst, nonce, ciphertext, additionalData) ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go +new file mode 100644 +index 00000000000000..82a4a36102d6d6 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go +@@ -0,0 +1,268 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package chacha20poly1305 ++ ++import ( ++ "bytes" ++ "crypto/cipher" ++ cryptorand "crypto/rand" ++ "encoding/hex" ++ "fmt" ++ mathrand "math/rand" ++ "strconv" ++ "testing" ++) ++ ++func TestVectors(t *testing.T) { ++ for i, test := range chacha20Poly1305Tests { ++ key, _ := hex.DecodeString(test.key) ++ nonce, _ := hex.DecodeString(test.nonce) ++ ad, _ := hex.DecodeString(test.aad) ++ plaintext, _ := hex.DecodeString(test.plaintext) ++ ++ var ( ++ aead cipher.AEAD ++ err error ++ ) ++ switch len(nonce) { ++ case NonceSize: ++ aead, err = New(key) ++ case NonceSizeX: ++ aead, err = NewX(key) ++ default: ++ t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce)) ++ } ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ ct := aead.Seal(nil, nonce, plaintext, ad) ++ if ctHex := hex.EncodeToString(ct); ctHex != test.out { ++ t.Errorf("#%d: got %s, want %s", i, ctHex, test.out) ++ continue ++ } ++ ++ plaintext2, err := aead.Open(nil, nonce, ct, ad) ++ if err != nil { ++ t.Errorf("#%d: Open failed", i) ++ continue ++ } ++ ++ if !bytes.Equal(plaintext, plaintext2) { ++ t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) ++ continue ++ } ++ ++ if len(ad) > 0 { ++ alterAdIdx := mathrand.Intn(len(ad)) ++ ad[alterAdIdx] ^= 0x80 ++ if _, err := aead.Open(nil, nonce, ct, ad); err == nil { ++ t.Errorf("#%d: Open was successful after altering additional data", i) ++ } ++ ad[alterAdIdx] ^= 0x80 ++ } ++ ++ alterNonceIdx := mathrand.Intn(aead.NonceSize()) ++ nonce[alterNonceIdx] ^= 0x80 ++ if _, err := aead.Open(nil, nonce, ct, ad); err == nil { ++ t.Errorf("#%d: Open was successful after altering nonce", i) ++ } ++ nonce[alterNonceIdx] ^= 0x80 ++ ++ alterCtIdx := mathrand.Intn(len(ct)) ++ ct[alterCtIdx] ^= 0x80 ++ if _, err := aead.Open(nil, nonce, ct, ad); err == nil { ++ t.Errorf("#%d: Open was successful after altering ciphertext", i) ++ } ++ ct[alterCtIdx] ^= 0x80 ++ } ++} ++ ++func TestRandom(t *testing.T) { ++ // Some random tests to verify Open(Seal) == Plaintext ++ f := func(t *testing.T, nonceSize int) { ++ for i := 0; i < 256; i++ { ++ var nonce = make([]byte, nonceSize) ++ var key [32]byte ++ ++ al := mathrand.Intn(128) ++ pl := mathrand.Intn(16384) ++ ad := make([]byte, al) ++ plaintext := make([]byte, pl) ++ cryptorand.Read(key[:]) ++ cryptorand.Read(nonce[:]) ++ cryptorand.Read(ad) ++ cryptorand.Read(plaintext) ++ ++ var ( ++ aead cipher.AEAD ++ err error ++ ) ++ switch len(nonce) { ++ case NonceSize: ++ aead, err = New(key[:]) ++ case NonceSizeX: ++ aead, err = NewX(key[:]) ++ default: ++ t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce)) ++ } ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ ct := aead.Seal(nil, nonce[:], plaintext, ad) ++ ++ plaintext2, err := aead.Open(nil, nonce[:], ct, ad) ++ if err != nil { ++ t.Errorf("Random #%d: Open failed", i) ++ continue ++ } ++ ++ if !bytes.Equal(plaintext, plaintext2) { ++ t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) ++ continue ++ } ++ ++ if len(ad) > 0 { ++ alterAdIdx := mathrand.Intn(len(ad)) ++ ad[alterAdIdx] ^= 0x80 ++ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { ++ t.Errorf("Random #%d: Open was successful after altering additional data", i) ++ } ++ ad[alterAdIdx] ^= 0x80 ++ } ++ ++ alterNonceIdx := mathrand.Intn(aead.NonceSize()) ++ nonce[alterNonceIdx] ^= 0x80 ++ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { ++ t.Errorf("Random #%d: Open was successful after altering nonce", i) ++ } ++ nonce[alterNonceIdx] ^= 0x80 ++ ++ alterCtIdx := mathrand.Intn(len(ct)) ++ ct[alterCtIdx] ^= 0x80 ++ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { ++ t.Errorf("Random #%d: Open was successful after altering ciphertext", i) ++ } ++ ct[alterCtIdx] ^= 0x80 ++ } ++ } ++ t.Run("Standard", func(t *testing.T) { f(t, NonceSize) }) ++ t.Run("X", func(t *testing.T) { f(t, NonceSizeX) }) ++} ++ ++func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) { ++ b.ReportAllocs() ++ b.SetBytes(int64(len(buf))) ++ ++ var key [32]byte ++ var nonce = make([]byte, nonceSize) ++ var ad [13]byte ++ var out []byte ++ ++ var aead cipher.AEAD ++ switch len(nonce) { ++ case NonceSize: ++ aead, _ = New(key[:]) ++ case NonceSizeX: ++ aead, _ = NewX(key[:]) ++ } ++ ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ out = aead.Seal(out[:0], nonce[:], buf[:], ad[:]) ++ } ++} ++ ++func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) { ++ b.ReportAllocs() ++ b.SetBytes(int64(len(buf))) ++ ++ var key [32]byte ++ var nonce = make([]byte, nonceSize) ++ var ad [13]byte ++ var ct []byte ++ var out []byte ++ ++ var aead cipher.AEAD ++ switch len(nonce) { ++ case NonceSize: ++ aead, _ = New(key[:]) ++ case NonceSizeX: ++ aead, _ = NewX(key[:]) ++ } ++ ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:]) ++ ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:]) ++ } ++} ++ ++func BenchmarkChacha20Poly1305(b *testing.B) { ++ for _, length := range []int{64, 1350, 8 * 1024} { ++ b.Run("Open-"+strconv.Itoa(length), func(b *testing.B) { ++ benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSize) ++ }) ++ b.Run("Seal-"+strconv.Itoa(length), func(b *testing.B) { ++ benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSize) ++ }) ++ ++ b.Run("Open-"+strconv.Itoa(length)+"-X", func(b *testing.B) { ++ benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSizeX) ++ }) ++ b.Run("Seal-"+strconv.Itoa(length)+"-X", func(b *testing.B) { ++ benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSizeX) ++ }) ++ } ++} ++ ++func ExampleNewX() { ++ // key should be randomly generated or derived from a function like Argon2. ++ key := make([]byte, KeySize) ++ if _, err := cryptorand.Read(key); err != nil { ++ panic(err) ++ } ++ ++ aead, err := NewX(key) ++ if err != nil { ++ panic(err) ++ } ++ ++ // Encryption. ++ var encryptedMsg []byte ++ { ++ msg := []byte("Gophers, gophers, gophers everywhere!") ++ ++ // Select a random nonce, and leave capacity for the ciphertext. ++ nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead()) ++ if _, err := cryptorand.Read(nonce); err != nil { ++ panic(err) ++ } ++ ++ // Encrypt the message and append the ciphertext to the nonce. ++ encryptedMsg = aead.Seal(nonce, nonce, msg, nil) ++ } ++ ++ // Decryption. ++ { ++ if len(encryptedMsg) < aead.NonceSize() { ++ panic("ciphertext too short") ++ } ++ ++ // Split nonce and ciphertext. ++ nonce, ciphertext := encryptedMsg[:aead.NonceSize()], encryptedMsg[aead.NonceSize():] ++ ++ // Decrypt the message and check it wasn't tampered with. ++ plaintext, err := aead.Open(nil, nonce, ciphertext, nil) ++ if err != nil { ++ panic(err) ++ } ++ ++ fmt.Printf("%s\n", plaintext) ++ } ++ ++ // Output: Gophers, gophers, gophers everywhere! ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go +new file mode 100644 +index 00000000000000..76823d13e6cbce +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go +@@ -0,0 +1,727 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package chacha20poly1305 ++ ++var chacha20Poly1305Tests = []struct { ++ plaintext, aad, key, nonce, out string ++}{ ++ { ++ "", ++ "", ++ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", ++ "070000004041424344454647", ++ "a0784d7a4716f3feb4f64e7f4b39bf04", ++ }, ++ { ++ // https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-01#appendix-A.3.1 ++ "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", ++ "50515253c0c1c2c3c4c5c6c7", ++ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", ++ "404142434445464748494a4b4c4d4e4f5051525354555657", ++ "bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52ec0875924c1c7987947deafd8780acf49", ++ }, ++ { ++ "1400000cebccee3bf561b292340fec60", ++ "00000000000000001603030010", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163", ++ }, ++ { ++ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", ++ "00000000000000000000000000", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa", ++ }, ++ { ++ "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87", ++ "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1", ++ "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f", ++ "4349e2131d44dc711148dfe3", ++ "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb", ++ }, ++ { ++ "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad", ++ "85deea3dc4", ++ "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7", ++ "b34710f65aed442e4a40866b", ++ "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0", ++ }, ++ { ++ "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5", ++ "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5", ++ "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e", ++ "2bbca0910cc47ca0b8517391", ++ "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f", ++ }, ++ { ++ "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337", ++ "74ba3372d308910b5c9c3885f41252d57556", ++ "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3", ++ "b928935c4c966c60fd6583c0", ++ "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d", ++ }, ++ { ++ "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b", ++ "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4", ++ "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093", ++ "8998e043d2961afa51ea262a", ++ "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7", ++ }, ++ { ++ "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e", ++ "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7", ++ "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975", ++ "aeb6159fa88bb1ffd51d036d", ++ "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e", ++ }, ++ { ++ "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296", ++ "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14", ++ "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c", ++ "4c46854e9e101090b1436f90", ++ "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb", ++ }, ++ { ++ "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9", ++ "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521", ++ "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87", ++ "eaa4d916d261676d632455be", ++ "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd", ++ }, ++ { ++ "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90", ++ "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a", ++ "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089", ++ "2403fe689e239c2ed261b381", ++ "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91", ++ }, ++ { ++ "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae", ++ "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974", ++ "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be", ++ "231b5780fedfb06d724450b3", ++ "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7", ++ }, ++ { ++ "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91", ++ "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3", ++ "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97", ++ "1e46a7486c5a03fd6758d938", ++ "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf", ++ }, ++ { ++ "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf", ++ "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae", ++ "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369", ++ "e14de73c4b17581a7e0d0649", ++ "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d", ++ }, ++ { ++ "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5", ++ "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81", ++ "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6", ++ "bb2d033de71d570ddf824e85", ++ "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2", ++ }, ++ { ++ "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65", ++ "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497", ++ "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d", ++ "350287a6bed5709dfba3d35c", ++ "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95", ++ }, ++ { ++ "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5", ++ "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68", ++ "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c", ++ "c0494bb7249f864f69beab46", ++ "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081", ++ }, ++ { ++ "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c", ++ "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5", ++ "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7", ++ "674a516f8f59f9067e0485e3", ++ "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc", ++ }, ++ { ++ "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c", ++ "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85", ++ "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b", ++ "8726dc5cae9497936658f603", ++ "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465", ++ }, ++ { ++ "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c", ++ "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94", ++ "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea", ++ "b633c1a0e1ddf4727b149b3d", ++ "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527", ++ }, ++ { ++ "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c", ++ "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655", ++ "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9", ++ "9f1d08be539f1244f0f69ad2", ++ "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a", ++ }, ++ { ++ "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271", ++ "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442", ++ "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1", ++ "952f492fe00b26028c560fc6", ++ "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053", ++ }, ++ { ++ "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34", ++ "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f", ++ "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769", ++ "7d3981073f90c6648c5e9c74", ++ "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7", ++ }, ++ { ++ "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf", ++ "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062", ++ "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc", ++ "5f6267f6b3b21423267310e6", ++ "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5", ++ }, ++ { ++ "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607", ++ "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd", ++ "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f", ++ "240cb25aaae4d085bbb747a5", ++ "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500", ++ }, ++ { ++ "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e", ++ "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597", ++ "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31", ++ "d9ce7d249af9496e99c93b36", ++ "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb", ++ }, ++ { ++ "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1", ++ "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555", ++ "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd", ++ "7df9824e774c5f86d83cb5d8", ++ "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f", ++ }, ++ { ++ "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092", ++ "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5", ++ "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a", ++ "588d9bc1d98210d9700ef488", ++ "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3", ++ }, ++ { ++ "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831", ++ "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f", ++ "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34", ++ "34a04df283c45655a52bdd84", ++ "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784", ++ }, ++ { ++ "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154", ++ "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9", ++ "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6", ++ "bb21211f342379370f2642d3", ++ "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8", ++ }, ++ { ++ "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459", ++ "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a", ++ "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb", ++ "47cc9eea11f9f3f9aafa23bd", ++ "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964", ++ }, ++ { ++ "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768", ++ "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33", ++ "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b", ++ "e88c14ef96c7768f5dba9de9", ++ "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc", ++ }, ++ { ++ "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64", ++ "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d", ++ "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81", ++ "36c79f9f14d431cc8c077439", ++ "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d", ++ }, ++ { ++ "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30", ++ "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083", ++ "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55", ++ "7812a320691ca8442767a51a", ++ "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb", ++ }, ++ { ++ "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e", ++ "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837", ++ "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c", ++ "e4709d225a552e90fb357413", ++ "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75", ++ }, ++ { ++ "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718", ++ "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9", ++ "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257", ++ "8bf183347ec1ca4bceff3374", ++ "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c", ++ }, ++ { ++ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b", ++ "0942e506c433afcda3847f2dad", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d", ++ }, ++ { ++ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", ++ "d3d934f75ea0f210a8f6059401", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925", ++ }, ++ { ++ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", ++ "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91", ++ }, ++ { ++ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b", ++ "bc", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170", ++ }, ++ { ++ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0", ++ "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d", ++ }, ++ { ++ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525", ++ "", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5", ++ }, ++ { ++ "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a", ++ "026866d46aa940309fdcabf92a324fbc", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00", ++ }, ++ { ++ "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9", ++ "56", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b", ++ }, ++ { ++ "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2", ++ "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6", ++ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", ++ "129039b5572e8a7a8131f76a", ++ "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54", ++ }, ++ ++ // XChaCha20-Poly1305 vectors ++ { ++ "000000000000000000000000000000", ++ "", ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ "000000000000000000000000000000000000000000000000", ++ "789e9689e5208d7fd9e1f3c5b5341fb2f7033812ac9ebd3745e2c99c7bbfeb", ++ }, ++ { ++ "02dc819b71875e49f5e1e5a768141cfd3f14307ae61a34d81decd9a3367c00c7", ++ "", ++ "b7bbfe61b8041658ddc95d5cbdc01bbe7626d24f3a043b70ddee87541234cff7", ++ "e293239d4c0a07840c5f83cb515be7fd59c333933027e99c", ++ "7a51f271bd2e547943c7be3316c05519a5d16803712289aa2369950b1504dd8267222e47b13280077ecada7b8795d535", ++ }, ++ { ++ "7afc5f3f24155002e17dc176a8f1f3a097ff5a991b02ff4640f70b90db0c15c328b696d6998ea7988edfe3b960e47824e4ae002fbe589be57896a9b7bf5578599c6ba0153c7c", ++ "d499bb9758debe59a93783c61974b7", ++ "4ea8fab44a07f7ffc0329b2c2f8f994efdb6d505aec32113ae324def5d929ba1", ++ "404d5086271c58bf27b0352a205d21ce4367d7b6a7628961", ++ "26d2b46ad58b6988e2dcf1d09ba8ab6f532dc7e0847cdbc0ed00284225c02bbdb278ee8381ebd127a06926107d1b731cfb1521b267168926492e8f77219ad922257a5be2c5e52e6183ca4dfd0ad3912d7bd1ec968065", ++ }, ++ { ++ "", ++ "", ++ "48d8bd02c2e9947eae58327114d35e055407b5519c8019535efcb4fc875b5e2b", ++ "cc0a587a475caba06f8dbc09afec1462af081fe1908c2cba", ++ "fc3322d0a9d6fac3eb4a9e09b00b361e", ++ }, ++ { ++ "e0862731e5", ++ "", ++ "6579e7ee96151131a1fcd06fe0d52802c0021f214960ecceec14b2b8591f62cd", ++ "e2230748649bc22e2b71e46a7814ecabe3a7005e949bd491", ++ "e991efb85d8b1cfa3f92cb72b8d3c882e88f4529d9", ++ }, ++ { ++ "00c7dd8f440af1530b44", ++ "", ++ "ffb733657c849d50ab4ab40c4ae18f8ee2f0acf7c907afefdc04dff3537fdff3", ++ "02c6fd8032a8d89edbedcd1db024c09d29f08b1e74325085", ++ "13dbcdb8c60c3ed28449a57688edfaea89e309ab4faa6d51e532", ++ }, ++ { ++ "7422f311ea476cf819cb8b3c77369f", ++ "", ++ "ef0d05d028d6abdd5e99d1761d2028de75ee6eb376ff0dc8036e9a8e10743876", ++ "f772745200b0f92e38f1d8dae79bf8138e84b301f0be74df", ++ "d5f992f9834df1be86b580ac59c7eae063a68072829c51bc8a26970dd3d310", ++ }, ++ { ++ "ba09ca69450e6c7bece31a7a3f216e3b9ed0e536", ++ "", ++ "8d93e31abfe22a63faf45cbea91877050718f13fef6e2664a1892d7f23007ccf", ++ "260b7b3554a7e6ff8aae7dd6234077ca539689a20c1610a8", ++ "c99e9a768eb2ec8569bdff8a37295069552faebcafb1a76e98bc7c5b6b778b3d1b6291f0", ++ }, ++ { ++ "424ec5f98a0fdc5a7388532d11ab0edb26733505627b7f2d1f", ++ "", ++ "b68d5e6c46cdbb0060445522bdc5c562ae803b6aaaf1e103c146e93527a59299", ++ "80bb5dc1dd44a35ec4f91307f1a95b4ca31183a1a596fb7c", ++ "29d4eed0fff0050d4bb40de3b055d836206e7cbd62de1a63904f0cf731129ba3f9c2b9d46251a6de89", ++ }, ++ { ++ "e7e4515cc0a6ef0491af983eaac4f862d6e726758a3c657f4ec444841e42", ++ "", ++ "e31a1d3af650e8e2848bd78432d89ecd1fdece9842dc2792e7bda080f537b17b", ++ "f3f09905e9a871e757348834f483ed71be9c0f437c8d74b0", ++ "f5c69528963e17db725a28885d30a45194f12848b8b7644c7bded47a2ee83e6d4ef34006305cfdf82effdced461d", ++ }, ++ { ++ "0f5ca45a54875d1d19e952e53caeaa19389342f776dab11723535503338d6f77202a37", ++ "", ++ "1031bc920d4fcb4434553b1bf2d25ab375200643bf523ff037bf8914297e8dca", ++ "4cc77e2ef5445e07b5f44de2dc5bf62d35b8c6f69502d2bf", ++ "7aa8669e1bfe8b0688899cdddbb8cee31265928c66a69a5090478da7397573b1cc0f64121e7d8bff8db0ddd3c17460d7f29a12", ++ }, ++ { ++ "c45578c04c194994e89025c7ffb015e5f138be3cd1a93640af167706aee2ad25ad38696df41ad805", ++ "", ++ "ac8648b7c94328419c668ce1c57c71893adf73abbb98892a4fc8da17400e3a5e", ++ "4ad637facf97af5fc03207ae56219da9972858b7430b3611", ++ "49e093fcd074fb67a755669119b8bd430d98d9232ca988882deeb3508bde7c00160c35cea89092db864dcb6d440aefa5aacb8aa7b9c04cf0", ++ }, ++ { ++ "b877bfa192ea7e4c7569b9ee973f89924d45f9d8ed03c7098ad0cad6e7880906befedcaf6417bb43efabca7a2f", ++ "", ++ "125e331d5da423ecabc8adf693cdbc2fc3d3589740d40a3894f914db86c02492", ++ "913f8b2f08006e6260de41ec3ee01d938a3e68fb12dc44c4", ++ "1be334253423c90fc8ea885ee5cd3a54268c035ba8a2119e5bd4f7822cd7bf9cb4cec568d5b6d6292606d32979e044df3504e6eb8c0b2fc7e2a0e17d62", ++ }, ++ { ++ "d946484a1df5f85ff72c92ff9e192660cde5074bd0ddd5de900c35eb10ed991113b1b19884631bc8ceb386bcd83908061ce9", ++ "", ++ "b7e83276373dcf8929b6a6ea80314c9de871f5f241c9144189ee4caf62726332", ++ "f59f9d6e3e6c00720dc20dc21586e8330431ebf42cf9180e", ++ "a38a662b18c2d15e1b7b14443cc23267a10bee23556b084b6254226389c414069b694159a4d0b5abbe34de381a0e2c88b947b4cfaaebf50c7a1ad6c656e386280ad7", ++ }, ++ { ++ "d266927ca40b2261d5a4722f3b4da0dd5bec74e103fab431702309fd0d0f1a259c767b956aa7348ca923d64c04f0a2e898b0670988b15e", ++ "", ++ "a60e09cd0bea16f26e54b62b2908687aa89722c298e69a3a22cf6cf1c46b7f8a", ++ "92da9d67854c53597fc099b68d955be32df2f0d9efe93614", ++ "9dd6d05832f6b4d7f555a5a83930d6aed5423461d85f363efb6c474b6c4c8261b680dea393e24c2a3c8d1cc9db6df517423085833aa21f9ab5b42445b914f2313bcd205d179430", ++ }, ++ { ++ "f7e11b4d372ed7cb0c0e157f2f9488d8efea0f9bbe089a345f51bdc77e30d1392813c5d22ca7e2c7dfc2e2d0da67efb2a559058d4de7a11bd2a2915e", ++ "", ++ "194b1190fa31d483c222ec475d2d6117710dd1ac19a6f1a1e8e894885b7fa631", ++ "6b07ea26bb1f2d92e04207b447f2fd1dd2086b442a7b6852", ++ "25ae14585790d71d39a6e88632228a70b1f6a041839dc89a74701c06bfa7c4de3288b7772cb2919818d95777ab58fe5480d6e49958f5d2481431014a8f88dab8f7e08d2a9aebbe691430011d", ++ }, ++ { ++ "", ++ "1e2b11e3", ++ "70cd96817da85ede0efdf03a358103a84561b25453dee73735e5fb0161b0d493", ++ "5ddeba49f7266d11827a43931d1c300dd47a3c33f9f8bf9b", ++ "592fc4c19f3cddec517b2a00f9df9665", ++ }, ++ { ++ "81b3cb7eb3", ++ "efcfd0cf", ++ "a977412f889281a6d75c24186f1bfaa00dcc5132f0929f20ef15bbf9e63c4c91", ++ "3f26ca997fb9166d9c615babe3e543ca43ab7cab20634ac5", ++ "8e4ade3e254cf52e93eace5c46667f150832725594", ++ }, ++ { ++ "556f97f2ebdb4e949923", ++ "f7cee2e0", ++ "787b3e86546a51028501c801dadf8d5b996fd6f6f2363d5d0f900c44f6a2f4c2", ++ "7fa6af59a779657d1cada847439ea5b92a1337cfbebbc3b1", ++ "608ec22dae5f48b89d6f0d2a940d5a7661e0a8e68aaee4ad2d96", ++ }, ++ { ++ "c06847a36ad031595b60edd44dc245", ++ "d4175e1f", ++ "16de31e534dd5af32801b1acd0ec541d1f8d82bcbc3af25ec815f3575b7aca73", ++ "29f6656972838f56c1684f6a278f9e4e207b51d68706fc25", ++ "836082cc51303e500fceade0b1a18f1d97d64ff41cc81754c07d6231b9fd1b", ++ }, ++ { ++ "0d03c22ced7b29c6741e72166cd61792028dfc80", ++ "e505dad0", ++ "ac2b426e5c5c8e00666180a3410e8a2f6e52247a43aecea9622163e8433c93b2", ++ "c1123430468228625967bbc0fbd0f963e674372259ff2deb", ++ "bf09979bf4fed2eec6c97f6e1bcfac35eeffc6d54a55cc1d83d8767ae74db2d7cdfbc371", ++ }, ++ { ++ "05bf00e1707cffe7ccbd06a9f846d0fd471a700ed43b4facb8", ++ "d863bebe", ++ "66c121f0f84b95ba1e6d29e7d81900bc96a642421b9b6105ae5eb5f2e7b07577", ++ "8ed6ae211a661e967995b71f7316ba88f44322bb62b4187b", ++ "b2c5c85d087e0305e9058fba52b661fb3d7f21cb4d4915ae048bc9e5d66a2f921dd4a1c1b030f442c9", ++ }, ++ { ++ "5f2b91a9be8bfaa21451ddc6c5cf28d1cc00b046b76270b95cda3c280c83", ++ "a8750275", ++ "39592eb276877fca9dd11e2181c0b23127328407e3cc11e315e5d748f43529cc", ++ "1084bebd756f193d9eea608b3a0193a5028f8ced19684821", ++ "eaee1f49ac8468154c601a5dd8b84d597602e5a73534b5fad5664f97d0f017dd114752be969679cf610340c6a312", ++ }, ++ { ++ "01e8e269b5376943f3b2d245483a76461dc8b7634868b559165f5dbb20839029fae9bb", ++ "a1e96da0", ++ "b8386123b87e50d9d046242cf1bf141fce7f65aff0fba76861a2bc72582d6ff0", ++ "0fbe2a13a89bea031de96d78f9f11358ba7b6a5e724b4392", ++ "705ec3f910ec85c6005baa99641de6ca43332ff52b5466df6af4ffbe4ef2a376a8f871d1eae503b5896601fee005cdc1f4c1c6", ++ }, ++ { ++ "706daba66e2edb1f828f3c0051e3cc214b12210bde0587bba02580f741a4c83e84d4e9fe961120cd", ++ "87663c5a", ++ "d519d82ba8a3f0c3af9efe36682b62e285167be101a526c1d73000f169c2a486", ++ "ad651aac536978e2bc1a54816345ac5e9a9b43b3d9cc0bfc", ++ "07051b5e72da9c4811beb07ff9f95aece67eae18420eb3f0e8bb8a5e26d4b483fa40eb063a2354842d0c8a41d981cc2b77c530b496db01c8", ++ }, ++ { ++ "1f6b24f2f0d9eb460d726bed953d66fcc4ecc29da6ed2fd711358eac3b2609d74ba3e21885156cde3cbe6d9b6f", ++ "f5efbc4e", ++ "86068a00544f749ad4ad15bb8e427ae78577ae22f4ca9778efff828ba10f6b20", ++ "c8420412c9626dcd34ece14593730f6aa2d01ec51cacd59f", ++ "a99f6c88eac35bb34439e34b292fe9db8192446dcdc81e2192060ec36d98b47de2bee12bf0f67cb24fb0949c07733a6781cd9455cdc61123f506886b04", ++ }, ++ { ++ "d69389d83362be8c0ddb738659a6cc4bd65d88cb5b525232f4d59a7d4751a7203c254923ecb6873e803220aab19664789a63", ++ "bc35fb1c", ++ "835855b326a98682b3075b4d7f1b89059c3cdfc547d4296c80ce7a77ba6434e3", ++ "c27cb75fc319ba431cbaeb120341d0c4745d883eb47e92bc", ++ "db6dc3f9a0f4f1a6df2495a88910550c2c6205478bfc1e81282e34b5b36d984c72c0509c522c987c61d2e640ced69402a6d33aa10d3d0b81e680b3c19bc142e81923", ++ }, ++ { ++ "a66a7f089115ed9e2d5bb5d33d7282a7afe401269b00f2a233a59c04b794a42901d862140b61d18d7c7f0ad5da040613e557f8abc74219", ++ "2c060aaf", ++ "99758aa7714fd707931f71803eefe04a06955041308a0b2a1104313b270ccf34", ++ "63f690d8926408c7a34fe8ddd505a8dc58769dc74e8d5da6", ++ "92b21ee85afcd8996ac28f3aed1047ad814d6e4ffbca3159af16f26eded83e4abda9e4275eb3ff0ad90dffe09f2d443b628f824f680b46527ce0128e8de1920f7c44350ebe7913", ++ }, ++ { ++ "f955183b1f762d4536d3f6885ea7f5ac27414caf46c2e24a2fd3bd56b91c53d840fb657224565e0a6f686f8ba320e04a401057399d9a3d995ab17c13", ++ "c372ddc5", ++ "a188be3795b2ca2e69b6aa263244f0963c492d694cf6c9b705a1d7045f3f2a26", ++ "51bb484ea094ee140474681e1c838e4442fd148de2cc345a", ++ "48759a5ddfdd829d11de8e0c538ce4a9c475faab6912039b568ad92d737d172fc1eb0c00c3793de6dddbfacfdbbc7f44aeba33684e18005aa982b6fc6c556e63bb90ff7a1dde8153a63eabe0", ++ }, ++ { ++ "", ++ "e013cd0bfafd486d", ++ "af3d3ba094d38299ecb91c17bfe3d085da5bd42e11acf8acb5bc26a4be9a7583", ++ "7dd63c14173831f109761b1c1abe18f6ba937d825957011b", ++ "8bc685a7d9d501952295cd25d8c92517", ++ }, ++ { ++ "284b64597e", ++ "31d013e53aa3ea79", ++ "93c77409d7f805f97fe683b2dd6ee06152a5e918b3eed5b731acccffdcb2cc04", ++ "3d331e90c4597cf0c30d1b7cfbd07bcb6ab927eda056873c", ++ "3538a449d6c18d148a8c6cb76f1bc288657ac7036a", ++ }, ++ { ++ "9fe67f5c78180ede8274", ++ "188608d230d75860", ++ "b7cca89a82640aea6f80b458c9e633d88594fb498959d39787be87030892d48f", ++ "ef891d50e8c08958f814590fdb7a9f16c61cc2aae1682109", ++ "bbb40c30f3d1391a5b38df480cbbf964b71e763e8140751f4e28", ++ }, ++ { ++ "3a2826b6f7e3d542e4ded8f23c9aa4", ++ "260033e789c4676a", ++ "7fe2731214f2b4b42f93217d43f1776498413725e4f6cfe62b756e5a52df10ea", ++ "888728219ebf761547f5e2218532714403020e5a8b7a49d0", ++ "fe0328f883fcd88930ae017c0f54ed90f883041efc020e959125af370c1d47", ++ }, ++ { ++ "91858bf7b969005d7164acbd5678052b651c53e0", ++ "f3cc53ecafcbadb3", ++ "d69c04e9726b22d51f97bc9da0f0fda86736e6b78e8ef9f6f0000f79890d6d43", ++ "6de3c45161b434e05445cf6bf69eef7bddf595fc6d8836bd", ++ "a8869dd578c0835e120c843bb7dedc7a1e9eae24ffd742be6bf5b74088a8a2c550976fcb", ++ }, ++ { ++ "b3b1a4d6b2a2b9c5a1ca6c1efaec34dcfa1acbe7074d5e10cc", ++ "d0f72bd16cda3bae", ++ "2b317857b089c9305c49b83019f6e158bc4ecc3339b39ade02ee10c37c268da0", ++ "cb5fa6d1e14a0b4bdf350cd10c8a7bd638102911ec74be09", ++ "e6372f77c14343650074e07a2b7223c37b29242224b722b24d63b5956f27aa64ce7ce4e39cd14a2787", ++ }, ++ { ++ "057d3e9f865be7dff774938cab6d080e50cf9a1593f53c0063201e0bb7ae", ++ "fd3881e505c8b12d", ++ "36e42b1ef1ee8d068f09b5fad3ee43d98d34aa3e3f994f2055aee139da71de9d", ++ "24124da36473d01bdca30297c9eef4fe61955525a453da17", ++ "a8b28139524c98c1f8776f442eac4c22766fe6aac83224641c58bf021fc9cb709ec4706f49c2d0c1828acf2bfe8d", ++ }, ++ { ++ "bd8f13e928c34d67a6c70c3c7efdf2982ecc31d8cee68f9cbddc75912cd828ac93d28b", ++ "193206c8fcc5b19b", ++ "6e47c40c9d7b757c2efca4d73890e4c73f3c859aab4fdc64b564b8480dd84e72", ++ "ca31340ae20d30fe488be355cb36652c5db7c9d6265a3e95", ++ "a121efc5e1843deade4b8adbfef1808de4eda222f176630ad34fb476fca19e0299e4a13668e53cf13882035ba4f04f47c8b4e3", ++ }, ++ { ++ "23067a196e977d10039c14ff358061c918d2148d31961bb3e12c27c5122383cb25c4d1d79c775720", ++ "62338d02fff78a00", ++ "2c5c79c92d91fb40ef7d0a77e8033f7b265e3bab998b8116d17b2e62bb4f8a09", ++ "024736adb1d5c01006dffd8158b57936d158d5b42054336d", ++ "46d0905473a995d38c7cdbb8ef3da96ecc82a22c5b3c6c9d1c4a61ae7a17db53cb88c5f7eccf2da1d0c417c300f989b4273470e36f03542f", ++ }, ++ { ++ "252e966c680329eb687bff813b78fea3bfd3505333f106c6f9f45ba69896723c41bb763793d9b266e897d05557", ++ "1e93e0cfe6523380", ++ "9ec6fd1baa13ee16aec3fac16718a2baccf18a403cec467c25b7448e9b321110", ++ "e7120b1018ab363a36e61102eedbcbe9847a6cbacaa9c328", ++ "2934f034587d4144bb11182679cd2cd1c99c8088d18e233379e9bc9c41107a1f57a2723ecc7b9ba4e6ee198adf0fd766738e828827dc73136fc5b996e9", ++ }, ++ { ++ "6744aefcb318f12bc6eeb59d4d62f7eb95f347cea14bd5158415f07f84e4e3baa3de07512d9b76095ac1312cfcb1bb77f499", ++ "608d2a33ce5d0b04", ++ "0f665cbdaaa40f4f5a00c53d951b0a98aac2342be259a52670f650a783be7aab", ++ "378bdb57e957b8c2e1500c9513052a3b02ff5b7edbd4a3a7", ++ "341c60fcb374b394f1b01a4a80aedef49ab0b67ec963675e6eec43ef106f7003be87dbf4a8976709583dccc55abc7f979c4721837e8664a69804ea31736aa2af615a", ++ }, ++ { ++ "bcf1004f988220b7ce063ef2ec4e276ffd074f0a90aa807de1532679d2a1505568eaa4192d9a6ea52cc500322343ce9f8e68cc2c606d83", ++ "e64bd00126c8792c", ++ "58e65150d6a15dcefbc14a171998987ad0d709fb06a17d68d6a778759681c308", ++ "106d2bd120b06e4eb10bc674fe55c77a3742225268319303", ++ "a28052a6686a1e9435fee8702f7da563a7b3d7b5d3e9e27f11abf73db309cd1f39a34756258c1c5c7f2fb12cf15eb20175c2a08fc93dd19c5e482ef3fbef3d8404a3cfd54a7baf", ++ }, ++ { ++ "acd08d4938a224b4cb2d723bf75420f3ea27b698fadd815bb7db9548a05651398644354334e69f8e4e5503bf1a6f92b38e860044a7edca6874038ce1", ++ "28a137808d0225b8", ++ "a031203b963a395b08be55844d81af39d19b23b7cc24b21afa31edc1eea6edd6", ++ "e8b31c52b6690f10f4ae62ba9d50ba39fb5edcfb78400e35", ++ "35cf39ba31da95ac9b661cdbd5e9c9655d13b8ff065c4ec10c810833a47a87d8057dd1948a7801bfe6904b49fed0aabfb3cd755a1a262d372786908ddcf64cae9f71cb9ed199c3ddacc50116", ++ }, ++ { ++ "", ++ "cda7ee2857e09e9054ef6806", ++ "d91dffb18132d8dd3d144a2f10ba28bc5df36cb60369f3b19893ec91db3cf904", ++ "ee56f19c62b0438da6a0d9e01844313902be44f84a6a4ce7", ++ "ccd48b61a5683c195d4424009eb1d147", ++ }, ++ { ++ "350f4c7ac2", ++ "7c104b539c1d2ae022434cd6", ++ "cbb61e369117f9250f68fa707240c554359262a4d66c757f80e3aeb6920894fb", ++ "fbb14c9943444eac5413c6f5c8095451eddece02c9461043", ++ "b5c6a35865ed8e5216ff6c77339ee1ab570de50e51", ++ }, ++ { ++ "4f0d61d3ea03a44a8df0", ++ "51c20a8ae9e9794da931fe23", ++ "ba6ced943aa62f9261d7513b822e02054e099acafb5360f0d850064da48b5a4f", ++ "04c68cb50cdbb0ec03f8381cf59b886e64c40548bf8e3f82", ++ "ea45a73957e2a853655623f2a3bb58791f7ea36dd2957ed66ffa", ++ }, ++ { ++ "4fbdd4d4293a8f34fdbc8f3ad44cf6", ++ "8212f315e3759c3253c588bb", ++ "5354791bc2370415811818e913e310dd12e6a0cf5dcab2b6424816eecccf4b65", ++ "7ee6353c2fbc73c9ebc652270bc86e4008e09583e623e679", ++ "50a354811a918e1801fb567621a8924baf8dd79da6d36702855d3753f1319c", ++ }, ++ { ++ "5a6f68b5a9a9920ca9c6edf5be7c0af150a063c4", ++ "9a524aa62938fb7a1e50ed06", ++ "fd91605a6ad85d8ba7a71b08dce1032aa9992bf4f28d407a53ddda04c043cada", ++ "46791d99d6de33e79025bf9e97c198e7cf409614c6284b4d", ++ "648033c1eb615467e90b7d3ac24202d8b849549141f9bab03e9e910c29b8eab3d4fb3f2c", ++ }, ++ { ++ "d9318c2c0d9ed89e35d242a6b1d496e7e0c5bbdf77eba14c56", ++ "a16053c35fbe8dc93c14a81f", ++ "f21406aec83134ebf7bc48c6d0f45acb5f341fbc7d3b5a9bff3ea1333c916af7", ++ "de6b977be450d5efa7777e006802ddbb10814a22da1c3cd9", ++ "8d3dad487d5161663da830b71c3e24ec5cdb74d858cbb73b084ed0902198532aad3a18416966bff223", ++ }, ++ { ++ "68d0ee08d38cb4bcc9268fee3030666e70e41fcabf6fe06536eeec43eec5", ++ "11e09447d40b22dc98070eec", ++ "da5ee1ec02eab13220fcb94f16efec848a8dd57c0f4d67955423f5d17fde5aa3", ++ "8f13e61d773a250810f75d46bf163a3f9205be5751f6049a", ++ "92a103b03764c1ad1f88500d22eeae5c0fe1044c872987c0b97affc5e8c3d783f8cc28a11dc91990ea22dd1bad74", ++ }, ++ { ++ "a1d960bda08efcf19e136dc1e8b05b6b381c820eda5f9a8047e1a2dd1803a1e4d11a7f", ++ "aa73d8d4aaa0cfd9d80a9ae8", ++ "08028833d617c28ba75b48f177cb5da87189189abb68dcb8974eca9230c25945", ++ "f7b6f34a910fd11588f567de8555932291f7df05f6e2b193", ++ "99cfc4cca193998bae153b744e6c94a82a2867780aa0f43acddb7c433fcb297311313ec2199f00d7ca7da0646b40113c60e935", ++ }, ++ { ++ "3b4ae39a745b6247ce5baf675ec36c5065b1bf76c8379eab4b769961d43a753896d068938017777e", ++ "128c017a985052f8cdbc6b28", ++ "4683d5caff613187a9b16af897253848e9c54fc0ec319de62452a86961d3cbb2", ++ "5612a13c2da003b91188921cbac3fa093eba99d8cbbb51ff", ++ "91a98b93b2174257175f7c882b45cc252e0db8667612bd270c1c12fe28b6bf209760bf8f370318f92ae3f88a5d4773b05714132cc28dddb8", ++ }, ++ { ++ "22ccf680d2995ef6563de281cff76882a036a59ad73f250e710b3040590d69bccde8a8411abe8b0d3cb728ca82", ++ "13a97d0a167a61aa21e531ec", ++ "9e140762eed274948b66de25e6e8f36ab65dc730b0cb096ef15aaba900a5588c", ++ "d0e9594cfd42ab72553bf34062a263f588bb8f1fc86a19f5", ++ "f194fc866dfba30e42c4508b7d90b3fa3f8983831ede713334563e36aa861f2f885b40be1dbe20ba2d10958a12823588d4bbbefb81a87d87315204f5e3", ++ }, ++ { ++ "a65f5d10c482b3381af296e631eb605eba6a11ccec6ceab021460d0bd35feb676ec6dbba5d4ad6c9f4d683ea541035bc80fa", ++ "f15ae71ffed50a8fcc4996b0", ++ "f535d60e8b75ac7e526041eed86eb4d65ae7e315eff15dba6c0133acc2a6a4bf", ++ "01ba61691ebb3c66d2f94c1b1c597ecd7b5ff7d2a30be405", ++ "d79e7c3893df5a5879c2f0a3f7ca619f08e4540f3ac7db35790b4211b9d47ae735adadf35fd47252a4763e3fd2b2cd8157f6ea7986108a53437962670a97d68ee281", ++ }, ++ { ++ "8c014655b97f6da76b0b168b565fd62de874c164fd7e227346a0ec22c908bed1e2a0b429620e6f3a68dd518f13a2c0250608a1cb08a7c3", ++ "10a7eff999029c5040c1b3bd", ++ "bf11af23e88c350a443493f6fa0eb34f234f4daa2676e26f0701bce5642d13f4", ++ "f14c97392afd2e32e2c625910ca029f9b6e81676c79cc42f", ++ "78d5226f372d5d60681dbfc749d12df74249f196b0cbf14fa65a3a59dc65ae458455ec39baa1df3397afe752bb06f6f13bf03c99abda7a95c1d0b73fd92d5f888a5f6f889a9aea", ++ }, ++ { ++ "66234d7a5b71eef134d60eccf7d5096ee879a33983d6f7a575e3a5e3a4022edccffe7865dde20b5b0a37252e31cb9a3650c63e35b057a1bc200a5b5b", ++ "ccc2406f997bcae737ddd0f5", ++ "d009eeb5b9b029577b14d200b7687b655eedb7d74add488f092681787999d66d", ++ "99319712626b400f9458dbb7a9abc9f5810f25b47fc90b39", ++ "543a2bbf52fd999027ae7c297353f3ce986f810bc2382583d0a81fda5939e4c87b6e8d262790cd614d6f753d8035b32adf43acc7f6d4c2c44289538928564b6587c2fcb99de1d8e34ffff323", ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go +new file mode 100644 +index 00000000000000..1cebfe946f4440 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go +@@ -0,0 +1,86 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package chacha20poly1305 ++ ++import ( ++ "crypto/cipher" ++ "errors" ++ ++ "golang.org/x/crypto/chacha20" ++) ++ ++type xchacha20poly1305 struct { ++ key [KeySize]byte ++} ++ ++// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. ++// ++// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce, ++// suitable to be generated randomly without risk of collisions. It should be ++// preferred when nonce uniqueness cannot be trivially ensured, or whenever ++// nonces are randomly generated. ++func NewX(key []byte) (cipher.AEAD, error) { ++ if len(key) != KeySize { ++ return nil, errors.New("chacha20poly1305: bad key length") ++ } ++ ret := new(xchacha20poly1305) ++ copy(ret.key[:], key) ++ return ret, nil ++} ++ ++func (*xchacha20poly1305) NonceSize() int { ++ return NonceSizeX ++} ++ ++func (*xchacha20poly1305) Overhead() int { ++ return Overhead ++} ++ ++func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { ++ if len(nonce) != NonceSizeX { ++ panic("chacha20poly1305: bad nonce length passed to Seal") ++ } ++ ++ // XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no ++ // size limit. However, since we reuse the ChaCha20-Poly1305 implementation, ++ // the second half of the counter is not available. This is unlikely to be ++ // an issue because the cipher.AEAD API requires the entire message to be in ++ // memory, and the counter overflows at 256 GB. ++ if uint64(len(plaintext)) > (1<<38)-64 { ++ panic("chacha20poly1305: plaintext too large") ++ } ++ ++ c := new(chacha20poly1305) ++ hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) ++ copy(c.key[:], hKey) ++ ++ // The first 4 bytes of the final nonce are unused counter space. ++ cNonce := make([]byte, NonceSize) ++ copy(cNonce[4:12], nonce[16:24]) ++ ++ return c.seal(dst, cNonce[:], plaintext, additionalData) ++} ++ ++func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { ++ if len(nonce) != NonceSizeX { ++ panic("chacha20poly1305: bad nonce length passed to Open") ++ } ++ if len(ciphertext) < 16 { ++ return nil, errOpen ++ } ++ if uint64(len(ciphertext)) > (1<<38)-48 { ++ panic("chacha20poly1305: ciphertext too large") ++ } ++ ++ c := new(chacha20poly1305) ++ hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) ++ copy(c.key[:], hKey) ++ ++ // The first 4 bytes of the final nonce are unused counter space. ++ cNonce := make([]byte, NonceSize) ++ copy(cNonce[4:12], nonce[16:24]) ++ ++ return c.open(dst, cNonce[:], ciphertext, additionalData) ++} +diff --git a/ms_mod/golang.org/x/crypto/codereview.cfg b/ms_mod/golang.org/x/crypto/codereview.cfg +new file mode 100644 +index 00000000000000..3f8b14b64e83f9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/codereview.cfg +@@ -0,0 +1 @@ ++issuerepo: golang/go +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/asn1.go b/ms_mod/golang.org/x/crypto/cryptobyte/asn1.go +new file mode 100644 +index 00000000000000..6fc2838a3fb853 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/asn1.go +@@ -0,0 +1,824 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package cryptobyte ++ ++import ( ++ encoding_asn1 "encoding/asn1" ++ "fmt" ++ "math/big" ++ "reflect" ++ "time" ++ ++ "golang.org/x/crypto/cryptobyte/asn1" ++) ++ ++// This file contains ASN.1-related methods for String and Builder. ++ ++// Builder ++ ++// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER. ++func (b *Builder) AddASN1Int64(v int64) { ++ b.addASN1Signed(asn1.INTEGER, v) ++} ++ ++// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the ++// given tag. ++func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { ++ b.addASN1Signed(tag, v) ++} ++ ++// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. ++func (b *Builder) AddASN1Enum(v int64) { ++ b.addASN1Signed(asn1.ENUM, v) ++} ++ ++func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) { ++ b.AddASN1(tag, func(c *Builder) { ++ length := 1 ++ for i := v; i >= 0x80 || i < -0x80; i >>= 8 { ++ length++ ++ } ++ ++ for ; length > 0; length-- { ++ i := v >> uint((length-1)*8) & 0xff ++ c.AddUint8(uint8(i)) ++ } ++ }) ++} ++ ++// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER. ++func (b *Builder) AddASN1Uint64(v uint64) { ++ b.AddASN1(asn1.INTEGER, func(c *Builder) { ++ length := 1 ++ for i := v; i >= 0x80; i >>= 8 { ++ length++ ++ } ++ ++ for ; length > 0; length-- { ++ i := v >> uint((length-1)*8) & 0xff ++ c.AddUint8(uint8(i)) ++ } ++ }) ++} ++ ++// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER. ++func (b *Builder) AddASN1BigInt(n *big.Int) { ++ if b.err != nil { ++ return ++ } ++ ++ b.AddASN1(asn1.INTEGER, func(c *Builder) { ++ if n.Sign() < 0 { ++ // A negative number has to be converted to two's-complement form. So we ++ // invert and subtract 1. If the most-significant-bit isn't set then ++ // we'll need to pad the beginning with 0xff in order to keep the number ++ // negative. ++ nMinus1 := new(big.Int).Neg(n) ++ nMinus1.Sub(nMinus1, bigOne) ++ bytes := nMinus1.Bytes() ++ for i := range bytes { ++ bytes[i] ^= 0xff ++ } ++ if len(bytes) == 0 || bytes[0]&0x80 == 0 { ++ c.add(0xff) ++ } ++ c.add(bytes...) ++ } else if n.Sign() == 0 { ++ c.add(0) ++ } else { ++ bytes := n.Bytes() ++ if bytes[0]&0x80 != 0 { ++ c.add(0) ++ } ++ c.add(bytes...) ++ } ++ }) ++} ++ ++// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING. ++func (b *Builder) AddASN1OctetString(bytes []byte) { ++ b.AddASN1(asn1.OCTET_STRING, func(c *Builder) { ++ c.AddBytes(bytes) ++ }) ++} ++ ++const generalizedTimeFormatStr = "20060102150405Z0700" ++ ++// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME. ++func (b *Builder) AddASN1GeneralizedTime(t time.Time) { ++ if t.Year() < 0 || t.Year() > 9999 { ++ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t) ++ return ++ } ++ b.AddASN1(asn1.GeneralizedTime, func(c *Builder) { ++ c.AddBytes([]byte(t.Format(generalizedTimeFormatStr))) ++ }) ++} ++ ++// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. ++func (b *Builder) AddASN1UTCTime(t time.Time) { ++ b.AddASN1(asn1.UTCTime, func(c *Builder) { ++ // As utilized by the X.509 profile, UTCTime can only ++ // represent the years 1950 through 2049. ++ if t.Year() < 1950 || t.Year() >= 2050 { ++ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) ++ return ++ } ++ c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) ++ }) ++} ++ ++// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not ++// support BIT STRINGs that are not a whole number of bytes. ++func (b *Builder) AddASN1BitString(data []byte) { ++ b.AddASN1(asn1.BIT_STRING, func(b *Builder) { ++ b.AddUint8(0) ++ b.AddBytes(data) ++ }) ++} ++ ++func (b *Builder) addBase128Int(n int64) { ++ var length int ++ if n == 0 { ++ length = 1 ++ } else { ++ for i := n; i > 0; i >>= 7 { ++ length++ ++ } ++ } ++ ++ for i := length - 1; i >= 0; i-- { ++ o := byte(n >> uint(i*7)) ++ o &= 0x7f ++ if i != 0 { ++ o |= 0x80 ++ } ++ ++ b.add(o) ++ } ++} ++ ++func isValidOID(oid encoding_asn1.ObjectIdentifier) bool { ++ if len(oid) < 2 { ++ return false ++ } ++ ++ if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) { ++ return false ++ } ++ ++ for _, v := range oid { ++ if v < 0 { ++ return false ++ } ++ } ++ ++ return true ++} ++ ++func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) { ++ b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) { ++ if !isValidOID(oid) { ++ b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid) ++ return ++ } ++ ++ b.addBase128Int(int64(oid[0])*40 + int64(oid[1])) ++ for _, v := range oid[2:] { ++ b.addBase128Int(int64(v)) ++ } ++ }) ++} ++ ++func (b *Builder) AddASN1Boolean(v bool) { ++ b.AddASN1(asn1.BOOLEAN, func(b *Builder) { ++ if v { ++ b.AddUint8(0xff) ++ } else { ++ b.AddUint8(0) ++ } ++ }) ++} ++ ++func (b *Builder) AddASN1NULL() { ++ b.add(uint8(asn1.NULL), 0) ++} ++ ++// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if ++// successful or records an error if one occurred. ++func (b *Builder) MarshalASN1(v interface{}) { ++ // NOTE(martinkr): This is somewhat of a hack to allow propagation of ++ // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a ++ // value embedded into a struct, its tag information is lost. ++ if b.err != nil { ++ return ++ } ++ bytes, err := encoding_asn1.Marshal(v) ++ if err != nil { ++ b.err = err ++ return ++ } ++ b.AddBytes(bytes) ++} ++ ++// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. ++// Tags greater than 30 are not supported and result in an error (i.e. ++// low-tag-number form only). The child builder passed to the ++// BuilderContinuation can be used to build the content of the ASN.1 object. ++func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { ++ if b.err != nil { ++ return ++ } ++ // Identifiers with the low five bits set indicate high-tag-number format ++ // (two or more octets), which we don't support. ++ if tag&0x1f == 0x1f { ++ b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) ++ return ++ } ++ b.AddUint8(uint8(tag)) ++ b.addLengthPrefixed(1, true, f) ++} ++ ++// String ++ ++// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean ++// representation into out and advances. It reports whether the read ++// was successful. ++func (s *String) ReadASN1Boolean(out *bool) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { ++ return false ++ } ++ ++ switch bytes[0] { ++ case 0: ++ *out = false ++ case 0xff: ++ *out = true ++ default: ++ return false ++ } ++ ++ return true ++} ++ ++// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does ++// not point to an integer, to a big.Int, or to a []byte it panics. Only ++// positive and zero values can be decoded into []byte, and they are returned as ++// big-endian binary values that share memory with s. Positive values will have ++// no leading zeroes, and zero will be returned as a single zero byte. ++// ReadASN1Integer reports whether the read was successful. ++func (s *String) ReadASN1Integer(out interface{}) bool { ++ switch out := out.(type) { ++ case *int, *int8, *int16, *int32, *int64: ++ var i int64 ++ if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { ++ return false ++ } ++ reflect.ValueOf(out).Elem().SetInt(i) ++ return true ++ case *uint, *uint8, *uint16, *uint32, *uint64: ++ var u uint64 ++ if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { ++ return false ++ } ++ reflect.ValueOf(out).Elem().SetUint(u) ++ return true ++ case *big.Int: ++ return s.readASN1BigInt(out) ++ case *[]byte: ++ return s.readASN1Bytes(out) ++ default: ++ panic("out does not point to an integer type") ++ } ++} ++ ++func checkASN1Integer(bytes []byte) bool { ++ if len(bytes) == 0 { ++ // An INTEGER is encoded with at least one octet. ++ return false ++ } ++ if len(bytes) == 1 { ++ return true ++ } ++ if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 { ++ // Value is not minimally encoded. ++ return false ++ } ++ return true ++} ++ ++var bigOne = big.NewInt(1) ++ ++func (s *String) readASN1BigInt(out *big.Int) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { ++ return false ++ } ++ if bytes[0]&0x80 == 0x80 { ++ // Negative number. ++ neg := make([]byte, len(bytes)) ++ for i, b := range bytes { ++ neg[i] = ^b ++ } ++ out.SetBytes(neg) ++ out.Add(out, bigOne) ++ out.Neg(out) ++ } else { ++ out.SetBytes(bytes) ++ } ++ return true ++} ++ ++func (s *String) readASN1Bytes(out *[]byte) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { ++ return false ++ } ++ if bytes[0]&0x80 == 0x80 { ++ return false ++ } ++ for len(bytes) > 1 && bytes[0] == 0 { ++ bytes = bytes[1:] ++ } ++ *out = bytes ++ return true ++} ++ ++func (s *String) readASN1Int64(out *int64) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { ++ return false ++ } ++ return true ++} ++ ++func asn1Signed(out *int64, n []byte) bool { ++ length := len(n) ++ if length > 8 { ++ return false ++ } ++ for i := 0; i < length; i++ { ++ *out <<= 8 ++ *out |= int64(n[i]) ++ } ++ // Shift up and down in order to sign extend the result. ++ *out <<= 64 - uint8(length)*8 ++ *out >>= 64 - uint8(length)*8 ++ return true ++} ++ ++func (s *String) readASN1Uint64(out *uint64) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) { ++ return false ++ } ++ return true ++} ++ ++func asn1Unsigned(out *uint64, n []byte) bool { ++ length := len(n) ++ if length > 9 || length == 9 && n[0] != 0 { ++ // Too large for uint64. ++ return false ++ } ++ if n[0]&0x80 != 0 { ++ // Negative number. ++ return false ++ } ++ for i := 0; i < length; i++ { ++ *out <<= 8 ++ *out |= uint64(n[i]) ++ } ++ return true ++} ++ ++// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out ++// and advances. It reports whether the read was successful and resulted in a ++// value that can be represented in an int64. ++func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { ++ var bytes String ++ return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) ++} ++ ++// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports ++// whether the read was successful. ++func (s *String) ReadASN1Enum(out *int) bool { ++ var bytes String ++ var i int64 ++ if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) { ++ return false ++ } ++ if int64(int(i)) != i { ++ return false ++ } ++ *out = int(i) ++ return true ++} ++ ++func (s *String) readBase128Int(out *int) bool { ++ ret := 0 ++ for i := 0; len(*s) > 0; i++ { ++ if i == 5 { ++ return false ++ } ++ // Avoid overflowing int on a 32-bit platform. ++ // We don't want different behavior based on the architecture. ++ if ret >= 1<<(31-7) { ++ return false ++ } ++ ret <<= 7 ++ b := s.read(1)[0] ++ ++ // ITU-T X.690, section 8.19.2: ++ // The subidentifier shall be encoded in the fewest possible octets, ++ // that is, the leading octet of the subidentifier shall not have the value 0x80. ++ if i == 0 && b == 0x80 { ++ return false ++ } ++ ++ ret |= int(b & 0x7f) ++ if b&0x80 == 0 { ++ *out = ret ++ return true ++ } ++ } ++ return false // truncated ++} ++ ++// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and ++// advances. It reports whether the read was successful. ++func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { ++ return false ++ } ++ ++ // In the worst case, we get two elements from the first byte (which is ++ // encoded differently) and then every varint is a single byte long. ++ components := make([]int, len(bytes)+1) ++ ++ // The first varint is 40*value1 + value2: ++ // According to this packing, value1 can take the values 0, 1 and 2 only. ++ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, ++ // then there are no restrictions on value2. ++ var v int ++ if !bytes.readBase128Int(&v) { ++ return false ++ } ++ if v < 80 { ++ components[0] = v / 40 ++ components[1] = v % 40 ++ } else { ++ components[0] = 2 ++ components[1] = v - 80 ++ } ++ ++ i := 2 ++ for ; len(bytes) > 0; i++ { ++ if !bytes.readBase128Int(&v) { ++ return false ++ } ++ components[i] = v ++ } ++ *out = components[:i] ++ return true ++} ++ ++// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and ++// advances. It reports whether the read was successful. ++func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { ++ return false ++ } ++ t := string(bytes) ++ res, err := time.Parse(generalizedTimeFormatStr, t) ++ if err != nil { ++ return false ++ } ++ if serialized := res.Format(generalizedTimeFormatStr); serialized != t { ++ return false ++ } ++ *out = res ++ return true ++} ++ ++const defaultUTCTimeFormatStr = "060102150405Z0700" ++ ++// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. ++// It reports whether the read was successful. ++func (s *String) ReadASN1UTCTime(out *time.Time) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.UTCTime) { ++ return false ++ } ++ t := string(bytes) ++ ++ formatStr := defaultUTCTimeFormatStr ++ var err error ++ res, err := time.Parse(formatStr, t) ++ if err != nil { ++ // Fallback to minute precision if we can't parse second ++ // precision. If we are following X.509 or X.690 we shouldn't ++ // support this, but we do. ++ formatStr = "0601021504Z0700" ++ res, err = time.Parse(formatStr, t) ++ } ++ if err != nil { ++ return false ++ } ++ ++ if serialized := res.Format(formatStr); serialized != t { ++ return false ++ } ++ ++ if res.Year() >= 2050 { ++ // UTCTime interprets the low order digits 50-99 as 1950-99. ++ // This only applies to its use in the X.509 profile. ++ // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 ++ res = res.AddDate(-100, 0, 0) ++ } ++ *out = res ++ return true ++} ++ ++// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. ++// It reports whether the read was successful. ++func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { ++ var bytes String ++ if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || ++ len(bytes)*8/8 != len(bytes) { ++ return false ++ } ++ ++ paddingBits := bytes[0] ++ bytes = bytes[1:] ++ if paddingBits > 7 || ++ len(bytes) == 0 && paddingBits != 0 || ++ len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) { ++ return false ++ } ++ ++ lenBytes := String((*s)[2 : 2+lenLen]) ++ if !lenBytes.readUnsigned(&len32, int(lenLen)) { ++ return false ++ } ++ ++ // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length ++ // with the minimum number of octets. ++ if len32 < 128 { ++ // Length should have used short-form encoding. ++ return false ++ } ++ if len32>>((lenLen-1)*8) == 0 { ++ // Leading octet is 0. Length should have been at least one byte shorter. ++ return false ++ } ++ ++ headerLen = 2 + uint32(lenLen) ++ if headerLen+len32 < len32 { ++ // Overflow. ++ return false ++ } ++ length = headerLen + len32 ++ } ++ ++ if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { ++ return false ++ } ++ if skipHeader && !out.Skip(int(headerLen)) { ++ panic("cryptobyte: internal error") ++ } ++ ++ return true ++} +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go +new file mode 100644 +index 00000000000000..cda8e3edfd5ea4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go +@@ -0,0 +1,46 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package asn1 contains supporting types for parsing and building ASN.1 ++// messages with the cryptobyte package. ++package asn1 // import "golang.org/x/crypto/cryptobyte/asn1" ++ ++// Tag represents an ASN.1 identifier octet, consisting of a tag number ++// (indicating a type) and class (such as context-specific or constructed). ++// ++// Methods in the cryptobyte package only support the low-tag-number form, i.e. ++// a single identifier octet with bits 7-8 encoding the class and bits 1-6 ++// encoding the tag number. ++type Tag uint8 ++ ++const ( ++ classConstructed = 0x20 ++ classContextSpecific = 0x80 ++) ++ ++// Constructed returns t with the constructed class bit set. ++func (t Tag) Constructed() Tag { return t | classConstructed } ++ ++// ContextSpecific returns t with the context-specific class bit set. ++func (t Tag) ContextSpecific() Tag { return t | classContextSpecific } ++ ++// The following is a list of standard tag and class combinations. ++const ( ++ BOOLEAN = Tag(1) ++ INTEGER = Tag(2) ++ BIT_STRING = Tag(3) ++ OCTET_STRING = Tag(4) ++ NULL = Tag(5) ++ OBJECT_IDENTIFIER = Tag(6) ++ ENUM = Tag(10) ++ UTF8String = Tag(12) ++ SEQUENCE = Tag(16 | classConstructed) ++ SET = Tag(17 | classConstructed) ++ PrintableString = Tag(19) ++ T61String = Tag(20) ++ IA5String = Tag(22) ++ UTCTime = Tag(23) ++ GeneralizedTime = Tag(24) ++ GeneralString = Tag(27) ++) +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go b/ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go +new file mode 100644 +index 00000000000000..e3f53a932ee847 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go +@@ -0,0 +1,435 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package cryptobyte ++ ++import ( ++ "bytes" ++ encoding_asn1 "encoding/asn1" ++ "math/big" ++ "reflect" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/cryptobyte/asn1" ++) ++ ++type readASN1Test struct { ++ name string ++ in []byte ++ tag asn1.Tag ++ ok bool ++ out interface{} ++} ++ ++var readASN1TestData = []readASN1Test{ ++ {"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}}, ++ {"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil}, ++ {"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil}, ++ {"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil}, ++ {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil}, ++ {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil}, ++ {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil}, ++ {"2**31 - 1 length", []byte{0x30, 0x84, 0x7f, 0xff, 0xff, 0xff}, 0x30, false, nil}, ++ {"2**32 - 1 length", []byte{0x30, 0x84, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, ++ {"2**63 - 1 length", []byte{0x30, 0x88, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, ++ {"2**64 - 1 length", []byte{0x30, 0x88, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, ++} ++ ++func TestReadASN1(t *testing.T) { ++ for _, test := range readASN1TestData { ++ t.Run(test.name, func(t *testing.T) { ++ var in, out String = test.in, nil ++ ok := in.ReadASN1(&out, test.tag) ++ if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) { ++ t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) ++ } ++ }) ++ } ++} ++ ++func TestReadASN1Optional(t *testing.T) { ++ var empty String ++ var present bool ++ ok := empty.ReadOptionalASN1(nil, &present, 0xa0) ++ if !ok || present { ++ t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present) ++ } ++ ++ var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil ++ ok = in.ReadOptionalASN1(&out, &present, 0xa0) ++ if !ok || present { ++ t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present) ++ } ++ ok = in.ReadOptionalASN1(&out, &present, 0xa1) ++ wantBytes := []byte{4, 1, 1} ++ if !ok || !present || !bytes.Equal(out, wantBytes) { ++ t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes) ++ } ++} ++ ++var optionalOctetStringTestData = []struct { ++ readASN1Test ++ present bool ++}{ ++ {readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false}, ++ {readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true}, ++ {readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false}, ++ {readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true}, ++} ++ ++func TestReadASN1OptionalOctetString(t *testing.T) { ++ for _, test := range optionalOctetStringTestData { ++ t.Run(test.name, func(t *testing.T) { ++ in := String(test.in) ++ var out []byte ++ var present bool ++ ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag) ++ if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) { ++ t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out) ++ } ++ }) ++ } ++} ++ ++const defaultInt = -1 ++ ++var optionalIntTestData = []readASN1Test{ ++ {"empty", []byte{}, 0xa0, true, defaultInt}, ++ {"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0}, ++ {"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt}, ++ {"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42}, ++} ++ ++func TestReadASN1OptionalInteger(t *testing.T) { ++ for _, test := range optionalIntTestData { ++ t.Run(test.name, func(t *testing.T) { ++ in := String(test.in) ++ var out int ++ ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt) ++ if ok != test.ok || ok && out != test.out.(int) { ++ t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) ++ } ++ }) ++ } ++} ++ ++func TestReadASN1IntegerSigned(t *testing.T) { ++ testData64 := []struct { ++ in []byte ++ out int64 ++ }{ ++ {[]byte{2, 3, 128, 0, 0}, -0x800000}, ++ {[]byte{2, 2, 255, 0}, -256}, ++ {[]byte{2, 2, 255, 127}, -129}, ++ {[]byte{2, 1, 128}, -128}, ++ {[]byte{2, 1, 255}, -1}, ++ {[]byte{2, 1, 0}, 0}, ++ {[]byte{2, 1, 1}, 1}, ++ {[]byte{2, 1, 2}, 2}, ++ {[]byte{2, 1, 127}, 127}, ++ {[]byte{2, 2, 0, 128}, 128}, ++ {[]byte{2, 2, 1, 0}, 256}, ++ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000}, ++ } ++ for i, test := range testData64 { ++ in := String(test.in) ++ var out int64 ++ ok := in.ReadASN1Integer(&out) ++ if !ok || out != test.out { ++ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out) ++ } ++ } ++ ++ // Repeat the same cases, reading into a big.Int. ++ t.Run("big.Int", func(t *testing.T) { ++ for i, test := range testData64 { ++ in := String(test.in) ++ var out big.Int ++ ok := in.ReadASN1Integer(&out) ++ if !ok || out.Int64() != test.out { ++ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out) ++ } ++ } ++ }) ++ ++ // Repeat the same cases, reading into a []byte. ++ t.Run("bytes", func(t *testing.T) { ++ for i, test := range testData64 { ++ in := String(test.in) ++ var out []byte ++ ok := in.ReadASN1Integer(&out) ++ if test.out < 0 { ++ if ok { ++ t.Errorf("#%d: in.ReadASN1Integer(%d) = %v, want false", i, test.out, ok) ++ } ++ continue ++ } ++ if !ok { ++ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true", i, ok) ++ continue ++ } ++ n := new(big.Int).SetBytes(out).Int64() ++ if n != test.out { ++ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %x, want %d", i, ok, out, test.out) ++ } ++ if out[0] == 0 && len(out) > 1 { ++ t.Errorf("#%d: in.ReadASN1Integer() = %v; out = %x, has leading zeroes", i, ok, out) ++ } ++ } ++ }) ++ ++ // Repeat with the implicit-tagging functions ++ t.Run("WithTag", func(t *testing.T) { ++ for i, test := range testData64 { ++ tag := asn1.Tag((i * 3) % 32).ContextSpecific() ++ ++ testData := make([]byte, len(test.in)) ++ copy(testData, test.in) ++ ++ // Alter the tag of the test case. ++ testData[0] = uint8(tag) ++ ++ in := String(testData) ++ var out int64 ++ ok := in.ReadASN1Int64WithTag(&out, tag) ++ if !ok || out != test.out { ++ t.Errorf("#%d: in.ReadASN1Int64WithTag() = %v, want true; out = %d, want %d", i, ok, out, test.out) ++ } ++ ++ var b Builder ++ b.AddASN1Int64WithTag(test.out, tag) ++ result, err := b.Bytes() ++ ++ if err != nil { ++ t.Errorf("#%d: AddASN1Int64WithTag failed: %s", i, err) ++ continue ++ } ++ ++ if !bytes.Equal(result, testData) { ++ t.Errorf("#%d: AddASN1Int64WithTag: got %x, want %x", i, result, testData) ++ } ++ } ++ }) ++} ++ ++func TestReadASN1IntegerUnsigned(t *testing.T) { ++ testData := []struct { ++ in []byte ++ out uint64 ++ }{ ++ {[]byte{2, 1, 0}, 0}, ++ {[]byte{2, 1, 1}, 1}, ++ {[]byte{2, 1, 2}, 2}, ++ {[]byte{2, 1, 127}, 127}, ++ {[]byte{2, 2, 0, 128}, 128}, ++ {[]byte{2, 2, 1, 0}, 256}, ++ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000}, ++ {[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff}, ++ {[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000}, ++ {[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff}, ++ } ++ for i, test := range testData { ++ in := String(test.in) ++ var out uint64 ++ ok := in.ReadASN1Integer(&out) ++ if !ok || out != test.out { ++ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out) ++ } ++ } ++} ++ ++func TestReadASN1IntegerInvalid(t *testing.T) { ++ testData := []String{ ++ []byte{3, 1, 0}, // invalid tag ++ // truncated ++ []byte{2, 1}, ++ []byte{2, 2, 0}, ++ // not minimally encoded ++ []byte{2, 2, 0, 1}, ++ []byte{2, 2, 0xff, 0xff}, ++ } ++ ++ for i, test := range testData { ++ var out int64 ++ if test.ReadASN1Integer(&out) { ++ t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out) ++ } ++ } ++} ++ ++func TestASN1ObjectIdentifier(t *testing.T) { ++ testData := []struct { ++ in []byte ++ ok bool ++ out []int ++ }{ ++ {[]byte{}, false, []int{}}, ++ {[]byte{6, 0}, false, []int{}}, ++ {[]byte{5, 1, 85}, false, []int{2, 5}}, ++ {[]byte{6, 1, 85}, true, []int{2, 5}}, ++ {[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}}, ++ {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, ++ {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}}, ++ {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, ++ {[]byte{6, 7, 85, 0x02, 0x85, 0xc7, 0xcc, 0xfb, 0x01}, true, []int{2, 5, 2, 1492336001}}, ++ {[]byte{6, 7, 0x55, 0x02, 0x87, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 2147483647}}, // 2**31-1 ++ {[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**31 ++ {[]byte{6, 3, 85, 0x80, 0x02}, false, []int{}}, // leading 0x80 octet ++ } ++ ++ for i, test := range testData { ++ in := String(test.in) ++ var out encoding_asn1.ObjectIdentifier ++ ok := in.ReadASN1ObjectIdentifier(&out) ++ if ok != test.ok || ok && !out.Equal(test.out) { ++ t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) ++ continue ++ } ++ ++ var b Builder ++ b.AddASN1ObjectIdentifier(out) ++ result, err := b.Bytes() ++ if builderOk := err == nil; test.ok != builderOk { ++ t.Errorf("#%d: error from Builder.Bytes: %s", i, err) ++ continue ++ } ++ if test.ok && !bytes.Equal(result, test.in) { ++ t.Errorf("#%d: reserialisation didn't match, got %x, want %x", i, result, test.in) ++ continue ++ } ++ } ++} ++ ++func TestReadASN1GeneralizedTime(t *testing.T) { ++ testData := []struct { ++ in string ++ ok bool ++ out time.Time ++ }{ ++ {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"20100102030405", false, time.Time{}}, ++ {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}, ++ {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))}, ++ /* These are invalid times. However, the time package normalises times ++ * and they were accepted in some versions. See #11134. */ ++ {"00000100000000Z", false, time.Time{}}, ++ {"20101302030405Z", false, time.Time{}}, ++ {"20100002030405Z", false, time.Time{}}, ++ {"20100100030405Z", false, time.Time{}}, ++ {"20100132030405Z", false, time.Time{}}, ++ {"20100231030405Z", false, time.Time{}}, ++ {"20100102240405Z", false, time.Time{}}, ++ {"20100102036005Z", false, time.Time{}}, ++ {"20100102030460Z", false, time.Time{}}, ++ {"-20100102030410Z", false, time.Time{}}, ++ {"2010-0102030410Z", false, time.Time{}}, ++ {"2010-0002030410Z", false, time.Time{}}, ++ {"201001-02030410Z", false, time.Time{}}, ++ {"20100102-030410Z", false, time.Time{}}, ++ {"2010010203-0410Z", false, time.Time{}}, ++ {"201001020304-10Z", false, time.Time{}}, ++ } ++ for i, test := range testData { ++ in := String(append([]byte{byte(asn1.GeneralizedTime), byte(len(test.in))}, test.in...)) ++ var out time.Time ++ ok := in.ReadASN1GeneralizedTime(&out) ++ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) { ++ t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out) ++ } ++ } ++} ++ ++func TestReadASN1UTCTime(t *testing.T) { ++ testData := []struct { ++ in string ++ ok bool ++ out time.Time ++ }{ ++ {"000102030405Z", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"500102030405Z", true, time.Date(1950, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"490102030405Z", true, time.Date(2049, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"990102030405Z", true, time.Date(1999, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"250102030405Z", true, time.Date(2025, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"750102030405Z", true, time.Date(1975, 01, 02, 03, 04, 05, 0, time.UTC)}, ++ {"000102030405+0905", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.FixedZone("", 9*60*60+5*60))}, ++ {"000102030405-0905", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.FixedZone("", -9*60*60-5*60))}, ++ {"0001020304Z", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.UTC)}, ++ {"5001020304Z", true, time.Date(1950, 01, 02, 03, 04, 00, 0, time.UTC)}, ++ {"0001020304+0905", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.FixedZone("", 9*60*60+5*60))}, ++ {"0001020304-0905", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.FixedZone("", -9*60*60-5*60))}, ++ {"000102030405Z0700", false, time.Time{}}, ++ {"000102030405", false, time.Time{}}, ++ } ++ for i, test := range testData { ++ in := String(append([]byte{byte(asn1.UTCTime), byte(len(test.in))}, test.in...)) ++ var out time.Time ++ ok := in.ReadASN1UTCTime(&out) ++ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) { ++ t.Errorf("#%d: in.ReadASN1UTCTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out) ++ } ++ } ++} ++ ++func TestReadASN1BitString(t *testing.T) { ++ testData := []struct { ++ in []byte ++ ok bool ++ out encoding_asn1.BitString ++ }{ ++ {[]byte{}, false, encoding_asn1.BitString{}}, ++ {[]byte{0x00}, true, encoding_asn1.BitString{}}, ++ {[]byte{0x07, 0x00}, true, encoding_asn1.BitString{Bytes: []byte{0}, BitLength: 1}}, ++ {[]byte{0x07, 0x01}, false, encoding_asn1.BitString{}}, ++ {[]byte{0x07, 0x40}, false, encoding_asn1.BitString{}}, ++ {[]byte{0x08, 0x00}, false, encoding_asn1.BitString{}}, ++ {[]byte{0xff}, false, encoding_asn1.BitString{}}, ++ {[]byte{0xfe, 0x00}, false, encoding_asn1.BitString{}}, ++ } ++ for i, test := range testData { ++ in := String(append([]byte{3, byte(len(test.in))}, test.in...)) ++ var out encoding_asn1.BitString ++ ok := in.ReadASN1BitString(&out) ++ if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) { ++ t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) ++ } ++ } ++} ++ ++func TestAddASN1BigInt(t *testing.T) { ++ x := big.NewInt(-1) ++ var b Builder ++ b.AddASN1BigInt(x) ++ got, err := b.Bytes() ++ if err != nil { ++ t.Fatalf("unexpected error adding -1: %v", err) ++ } ++ s := String(got) ++ var y big.Int ++ ok := s.ReadASN1Integer(&y) ++ if !ok || x.Cmp(&y) != 0 { ++ t.Errorf("unexpected bytes %v, want %v", &y, x) ++ } ++} ++ ++func TestReadASN1Boolean(t *testing.T) { ++ testData := []struct { ++ in []byte ++ ok bool ++ out bool ++ }{ ++ {[]byte{}, false, false}, ++ {[]byte{0x01, 0x01, 0x00}, true, false}, ++ {[]byte{0x01, 0x01, 0xff}, true, true}, ++ {[]byte{0x01, 0x01, 0x01}, false, false}, ++ } ++ for i, test := range testData { ++ in := String(test.in) ++ var out bool ++ ok := in.ReadASN1Boolean(&out) ++ if ok != test.ok || ok && (out != test.out) { ++ t.Errorf("#%d: in.ReadASN1Boolean() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/builder.go b/ms_mod/golang.org/x/crypto/cryptobyte/builder.go +new file mode 100644 +index 00000000000000..c05ac7d16da71e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/builder.go +@@ -0,0 +1,345 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package cryptobyte ++ ++import ( ++ "errors" ++ "fmt" ++) ++ ++// A Builder builds byte strings from fixed-length and length-prefixed values. ++// Builders either allocate space as needed, or are β€˜fixed’, which means that ++// they write into a given buffer and produce an error if it's exhausted. ++// ++// The zero value is a usable Builder that allocates space as needed. ++// ++// Simple values are marshaled and appended to a Builder using methods on the ++// Builder. Length-prefixed values are marshaled by providing a ++// BuilderContinuation, which is a function that writes the inner contents of ++// the value to a given Builder. See the documentation for BuilderContinuation ++// for details. ++type Builder struct { ++ err error ++ result []byte ++ fixedSize bool ++ child *Builder ++ offset int ++ pendingLenLen int ++ pendingIsASN1 bool ++ inContinuation *bool ++} ++ ++// NewBuilder creates a Builder that appends its output to the given buffer. ++// Like append(), the slice will be reallocated if its capacity is exceeded. ++// Use Bytes to get the final buffer. ++func NewBuilder(buffer []byte) *Builder { ++ return &Builder{ ++ result: buffer, ++ } ++} ++ ++// NewFixedBuilder creates a Builder that appends its output into the given ++// buffer. This builder does not reallocate the output buffer. Writes that ++// would exceed the buffer's capacity are treated as an error. ++func NewFixedBuilder(buffer []byte) *Builder { ++ return &Builder{ ++ result: buffer, ++ fixedSize: true, ++ } ++} ++ ++// SetError sets the value to be returned as the error from Bytes. Writes ++// performed after calling SetError are ignored. ++func (b *Builder) SetError(err error) { ++ b.err = err ++} ++ ++// Bytes returns the bytes written by the builder or an error if one has ++// occurred during building. ++func (b *Builder) Bytes() ([]byte, error) { ++ if b.err != nil { ++ return nil, b.err ++ } ++ return b.result[b.offset:], nil ++} ++ ++// BytesOrPanic returns the bytes written by the builder or panics if an error ++// has occurred during building. ++func (b *Builder) BytesOrPanic() []byte { ++ if b.err != nil { ++ panic(b.err) ++ } ++ return b.result[b.offset:] ++} ++ ++// AddUint8 appends an 8-bit value to the byte string. ++func (b *Builder) AddUint8(v uint8) { ++ b.add(byte(v)) ++} ++ ++// AddUint16 appends a big-endian, 16-bit value to the byte string. ++func (b *Builder) AddUint16(v uint16) { ++ b.add(byte(v>>8), byte(v)) ++} ++ ++// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest ++// byte of the 32-bit input value is silently truncated. ++func (b *Builder) AddUint24(v uint32) { ++ b.add(byte(v>>16), byte(v>>8), byte(v)) ++} ++ ++// AddUint32 appends a big-endian, 32-bit value to the byte string. ++func (b *Builder) AddUint32(v uint32) { ++ b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) ++} ++ ++// AddUint64 appends a big-endian, 64-bit value to the byte string. ++func (b *Builder) AddUint64(v uint64) { ++ b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) ++} ++ ++// AddBytes appends a sequence of bytes to the byte string. ++func (b *Builder) AddBytes(v []byte) { ++ b.add(v...) ++} ++ ++// BuilderContinuation is a continuation-passing interface for building ++// length-prefixed byte sequences. Builder methods for length-prefixed ++// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation ++// supplied to them. The child builder passed to the continuation can be used ++// to build the content of the length-prefixed sequence. For example: ++// ++// parent := cryptobyte.NewBuilder() ++// parent.AddUint8LengthPrefixed(func (child *Builder) { ++// child.AddUint8(42) ++// child.AddUint8LengthPrefixed(func (grandchild *Builder) { ++// grandchild.AddUint8(5) ++// }) ++// }) ++// ++// It is an error to write more bytes to the child than allowed by the reserved ++// length prefix. After the continuation returns, the child must be considered ++// invalid, i.e. users must not store any copies or references of the child ++// that outlive the continuation. ++// ++// If the continuation panics with a value of type BuildError then the inner ++// error will be returned as the error from Bytes. If the child panics ++// otherwise then Bytes will repanic with the same value. ++type BuilderContinuation func(child *Builder) ++ ++// BuildError wraps an error. If a BuilderContinuation panics with this value, ++// the panic will be recovered and the inner error will be returned from ++// Builder.Bytes. ++type BuildError struct { ++ Err error ++} ++ ++// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence. ++func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) { ++ b.addLengthPrefixed(1, false, f) ++} ++ ++// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence. ++func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) { ++ b.addLengthPrefixed(2, false, f) ++} ++ ++// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence. ++func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) { ++ b.addLengthPrefixed(3, false, f) ++} ++ ++// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence. ++func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) { ++ b.addLengthPrefixed(4, false, f) ++} ++ ++func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) { ++ if !*b.inContinuation { ++ *b.inContinuation = true ++ ++ defer func() { ++ *b.inContinuation = false ++ ++ r := recover() ++ if r == nil { ++ return ++ } ++ ++ if buildError, ok := r.(BuildError); ok { ++ b.err = buildError.Err ++ } else { ++ panic(r) ++ } ++ }() ++ } ++ ++ f(arg) ++} ++ ++func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) { ++ // Subsequent writes can be ignored if the builder has encountered an error. ++ if b.err != nil { ++ return ++ } ++ ++ offset := len(b.result) ++ b.add(make([]byte, lenLen)...) ++ ++ if b.inContinuation == nil { ++ b.inContinuation = new(bool) ++ } ++ ++ b.child = &Builder{ ++ result: b.result, ++ fixedSize: b.fixedSize, ++ offset: offset, ++ pendingLenLen: lenLen, ++ pendingIsASN1: isASN1, ++ inContinuation: b.inContinuation, ++ } ++ ++ b.callContinuation(f, b.child) ++ b.flushChild() ++ if b.child != nil { ++ panic("cryptobyte: internal error") ++ } ++} ++ ++func (b *Builder) flushChild() { ++ if b.child == nil { ++ return ++ } ++ b.child.flushChild() ++ child := b.child ++ b.child = nil ++ ++ if child.err != nil { ++ b.err = child.err ++ return ++ } ++ ++ length := len(child.result) - child.pendingLenLen - child.offset ++ ++ if length < 0 { ++ panic("cryptobyte: internal error") // result unexpectedly shrunk ++ } ++ ++ if child.pendingIsASN1 { ++ // For ASN.1, we reserved a single byte for the length. If that turned out ++ // to be incorrect, we have to move the contents along in order to make ++ // space. ++ if child.pendingLenLen != 1 { ++ panic("cryptobyte: internal error") ++ } ++ var lenLen, lenByte uint8 ++ if int64(length) > 0xfffffffe { ++ b.err = errors.New("pending ASN.1 child too long") ++ return ++ } else if length > 0xffffff { ++ lenLen = 5 ++ lenByte = 0x80 | 4 ++ } else if length > 0xffff { ++ lenLen = 4 ++ lenByte = 0x80 | 3 ++ } else if length > 0xff { ++ lenLen = 3 ++ lenByte = 0x80 | 2 ++ } else if length > 0x7f { ++ lenLen = 2 ++ lenByte = 0x80 | 1 ++ } else { ++ lenLen = 1 ++ lenByte = uint8(length) ++ length = 0 ++ } ++ ++ // Insert the initial length byte, make space for successive length bytes, ++ // and adjust the offset. ++ child.result[child.offset] = lenByte ++ extraBytes := int(lenLen - 1) ++ if extraBytes != 0 { ++ child.add(make([]byte, extraBytes)...) ++ childStart := child.offset + child.pendingLenLen ++ copy(child.result[childStart+extraBytes:], child.result[childStart:]) ++ } ++ child.offset++ ++ child.pendingLenLen = extraBytes ++ } ++ ++ l := length ++ for i := child.pendingLenLen - 1; i >= 0; i-- { ++ child.result[child.offset+i] = uint8(l) ++ l >>= 8 ++ } ++ if l != 0 { ++ b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen) ++ return ++ } ++ ++ if b.fixedSize && &b.result[0] != &child.result[0] { ++ panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer") ++ } ++ ++ b.result = child.result ++} ++ ++func (b *Builder) add(bytes ...byte) { ++ if b.err != nil { ++ return ++ } ++ if b.child != nil { ++ panic("cryptobyte: attempted write while child is pending") ++ } ++ if len(b.result)+len(bytes) < len(bytes) { ++ b.err = errors.New("cryptobyte: length overflow") ++ } ++ if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) { ++ b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer") ++ return ++ } ++ b.result = append(b.result, bytes...) ++} ++ ++// Unwrite rolls back non-negative n bytes written directly to the Builder. ++// An attempt by a child builder passed to a continuation to unwrite bytes ++// from its parent will panic. ++func (b *Builder) Unwrite(n int) { ++ if b.err != nil { ++ return ++ } ++ if b.child != nil { ++ panic("cryptobyte: attempted unwrite while child is pending") ++ } ++ length := len(b.result) - b.pendingLenLen - b.offset ++ if length < 0 { ++ panic("cryptobyte: internal error") ++ } ++ if n < 0 { ++ panic("cryptobyte: attempted to unwrite negative number of bytes") ++ } ++ if n > length { ++ panic("cryptobyte: attempted to unwrite more than was written") ++ } ++ b.result = b.result[:len(b.result)-n] ++} ++ ++// A MarshalingValue marshals itself into a Builder. ++type MarshalingValue interface { ++ // Marshal is called by Builder.AddValue. It receives a pointer to a builder ++ // to marshal itself into. It may return an error that occurred during ++ // marshaling, such as unset or invalid values. ++ Marshal(b *Builder) error ++} ++ ++// AddValue calls Marshal on v, passing a pointer to the builder to append to. ++// If Marshal returns an error, it is set on the Builder so that subsequent ++// appends don't have an effect. ++func (b *Builder) AddValue(v MarshalingValue) { ++ err := v.Marshal(b) ++ if err != nil { ++ b.err = err ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go b/ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go +new file mode 100644 +index 00000000000000..dc90e81fa93e4c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go +@@ -0,0 +1,536 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package cryptobyte ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "testing" ++) ++ ++func builderBytesEq(b *Builder, want ...byte) error { ++ got := b.BytesOrPanic() ++ if !bytes.Equal(got, want) { ++ return fmt.Errorf("Bytes() = %v, want %v", got, want) ++ } ++ return nil ++} ++ ++func TestContinuationError(t *testing.T) { ++ const errorStr = "TestContinuationError" ++ var b Builder ++ b.AddUint8LengthPrefixed(func(b *Builder) { ++ b.AddUint8(1) ++ panic(BuildError{Err: errors.New(errorStr)}) ++ }) ++ ++ ret, err := b.Bytes() ++ if ret != nil { ++ t.Error("expected nil result") ++ } ++ if err == nil { ++ t.Fatal("unexpected nil error") ++ } ++ if s := err.Error(); s != errorStr { ++ t.Errorf("expected error %q, got %v", errorStr, s) ++ } ++} ++ ++func TestContinuationNonError(t *testing.T) { ++ defer func() { ++ recover() ++ }() ++ ++ var b Builder ++ b.AddUint8LengthPrefixed(func(b *Builder) { ++ b.AddUint8(1) ++ panic(1) ++ }) ++ ++ t.Error("Builder did not panic") ++} ++ ++func TestGeneratedPanic(t *testing.T) { ++ defer func() { ++ recover() ++ }() ++ ++ var b Builder ++ b.AddUint8LengthPrefixed(func(b *Builder) { ++ var p *byte ++ *p = 0 ++ }) ++ ++ t.Error("Builder did not panic") ++} ++ ++func TestBytes(t *testing.T) { ++ var b Builder ++ v := []byte("foobarbaz") ++ b.AddBytes(v[0:3]) ++ b.AddBytes(v[3:4]) ++ b.AddBytes(v[4:9]) ++ if err := builderBytesEq(&b, v...); err != nil { ++ t.Error(err) ++ } ++ s := String(b.BytesOrPanic()) ++ for _, w := range []string{"foo", "bar", "baz"} { ++ var got []byte ++ if !s.ReadBytes(&got, 3) { ++ t.Errorf("ReadBytes() = false, want true (w = %v)", w) ++ } ++ want := []byte(w) ++ if !bytes.Equal(got, want) { ++ t.Errorf("ReadBytes(): got = %v, want %v", got, want) ++ } ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUint8(t *testing.T) { ++ var b Builder ++ b.AddUint8(42) ++ if err := builderBytesEq(&b, 42); err != nil { ++ t.Error(err) ++ } ++ ++ var s String = b.BytesOrPanic() ++ var v uint8 ++ if !s.ReadUint8(&v) { ++ t.Error("ReadUint8() = false, want true") ++ } ++ if v != 42 { ++ t.Errorf("v = %d, want 42", v) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUint16(t *testing.T) { ++ var b Builder ++ b.AddUint16(65534) ++ if err := builderBytesEq(&b, 255, 254); err != nil { ++ t.Error(err) ++ } ++ var s String = b.BytesOrPanic() ++ var v uint16 ++ if !s.ReadUint16(&v) { ++ t.Error("ReadUint16() == false, want true") ++ } ++ if v != 65534 { ++ t.Errorf("v = %d, want 65534", v) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUint24(t *testing.T) { ++ var b Builder ++ b.AddUint24(0xfffefd) ++ if err := builderBytesEq(&b, 255, 254, 253); err != nil { ++ t.Error(err) ++ } ++ ++ var s String = b.BytesOrPanic() ++ var v uint32 ++ if !s.ReadUint24(&v) { ++ t.Error("ReadUint24() = false, want true") ++ } ++ if v != 0xfffefd { ++ t.Errorf("v = %d, want fffefd", v) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUint24Truncation(t *testing.T) { ++ var b Builder ++ b.AddUint24(0x10111213) ++ if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestUint32(t *testing.T) { ++ var b Builder ++ b.AddUint32(0xfffefdfc) ++ if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil { ++ t.Error(err) ++ } ++ ++ var s String = b.BytesOrPanic() ++ var v uint32 ++ if !s.ReadUint32(&v) { ++ t.Error("ReadUint32() = false, want true") ++ } ++ if v != 0xfffefdfc { ++ t.Errorf("v = %x, want fffefdfc", v) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUint64(t *testing.T) { ++ var b Builder ++ b.AddUint64(0xf2fefefcff3cfdfc) ++ if err := builderBytesEq(&b, 242, 254, 254, 252, 255, 60, 253, 252); err != nil { ++ t.Error(err) ++ } ++ ++ var s String = b.BytesOrPanic() ++ var v uint64 ++ if !s.ReadUint64(&v) { ++ t.Error("ReadUint64() = false, want true") ++ } ++ if v != 0xf2fefefcff3cfdfc { ++ t.Errorf("v = %x, want f2fefefcff3cfdfc", v) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUMultiple(t *testing.T) { ++ var b Builder ++ b.AddUint8(23) ++ b.AddUint32(0xfffefdfc) ++ b.AddUint16(42) ++ if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil { ++ t.Error(err) ++ } ++ ++ var s String = b.BytesOrPanic() ++ var ( ++ x uint8 ++ y uint32 ++ z uint16 ++ ) ++ if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) { ++ t.Error("ReadUint8() = false, want true") ++ } ++ if x != 23 || y != 0xfffefdfc || z != 42 { ++ t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++} ++ ++func TestUint8LengthPrefixedSimple(t *testing.T) { ++ var b Builder ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ c.AddUint8(23) ++ c.AddUint8(42) ++ }) ++ if err := builderBytesEq(&b, 2, 23, 42); err != nil { ++ t.Error(err) ++ } ++ ++ var base, child String = b.BytesOrPanic(), nil ++ var x, y uint8 ++ if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || ++ !child.ReadUint8(&y) { ++ t.Error("parsing failed") ++ } ++ if x != 23 || y != 42 { ++ t.Errorf("want x, y == 23, 42; got %d, %d", x, y) ++ } ++ if len(base) != 0 { ++ t.Errorf("len(base) = %d, want 0", len(base)) ++ } ++ if len(child) != 0 { ++ t.Errorf("len(child) = %d, want 0", len(child)) ++ } ++} ++ ++func TestUint8LengthPrefixedMulti(t *testing.T) { ++ var b Builder ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ c.AddUint8(23) ++ c.AddUint8(42) ++ }) ++ b.AddUint8(5) ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ c.AddUint8(123) ++ c.AddUint8(234) ++ }) ++ if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil { ++ t.Error(err) ++ } ++ ++ var s, child String = b.BytesOrPanic(), nil ++ var u, v, w, x, y uint8 ++ if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) || ++ !s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) { ++ t.Error("parsing failed") ++ } ++ if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 { ++ t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234", ++ u, v, w, x, y) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++ if len(child) != 0 { ++ t.Errorf("len(child) = %d, want 0", len(child)) ++ } ++} ++ ++func TestUint8LengthPrefixedNested(t *testing.T) { ++ var b Builder ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ c.AddUint8(5) ++ c.AddUint8LengthPrefixed(func(d *Builder) { ++ d.AddUint8(23) ++ d.AddUint8(42) ++ }) ++ c.AddUint8(123) ++ }) ++ if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil { ++ t.Error(err) ++ } ++ ++ var base, child1, child2 String = b.BytesOrPanic(), nil, nil ++ var u, v, w, x uint8 ++ if !base.ReadUint8LengthPrefixed(&child1) { ++ t.Error("parsing base failed") ++ } ++ if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) { ++ t.Error("parsing child1 failed") ++ } ++ if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) { ++ t.Error("parsing child2 failed") ++ } ++ if u != 5 || v != 23 || w != 42 || x != 123 { ++ t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123", ++ u, v, w, x) ++ } ++ if len(base) != 0 { ++ t.Errorf("len(base) = %d, want 0", len(base)) ++ } ++ if len(child1) != 0 { ++ t.Errorf("len(child1) = %d, want 0", len(child1)) ++ } ++ if len(base) != 0 { ++ t.Errorf("len(child2) = %d, want 0", len(child2)) ++ } ++} ++ ++func TestPreallocatedBuffer(t *testing.T) { ++ var buf [5]byte ++ b := NewBuilder(buf[0:0]) ++ b.AddUint8(1) ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ c.AddUint8(3) ++ c.AddUint8(4) ++ }) ++ b.AddUint16(1286) // Outgrow buf by one byte. ++ want := []byte{1, 2, 3, 4, 0} ++ if !bytes.Equal(buf[:], want) { ++ t.Errorf("buf = %v want %v", buf, want) ++ } ++ if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestWriteWithPendingChild(t *testing.T) { ++ var b Builder ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ c.AddUint8LengthPrefixed(func(d *Builder) { ++ func() { ++ defer func() { ++ if recover() == nil { ++ t.Errorf("recover() = nil, want error; c.AddUint8() did not panic") ++ } ++ }() ++ c.AddUint8(2) // panics ++ }() ++ ++ defer func() { ++ if recover() == nil { ++ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic") ++ } ++ }() ++ b.AddUint8(2) // panics ++ }) ++ ++ defer func() { ++ if recover() == nil { ++ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic") ++ } ++ }() ++ b.AddUint8(2) // panics ++ }) ++} ++ ++func TestSetError(t *testing.T) { ++ const errorStr = "TestSetError" ++ var b Builder ++ b.SetError(errors.New(errorStr)) ++ ++ ret, err := b.Bytes() ++ if ret != nil { ++ t.Error("expected nil result") ++ } ++ if err == nil { ++ t.Fatal("unexpected nil error") ++ } ++ if s := err.Error(); s != errorStr { ++ t.Errorf("expected error %q, got %v", errorStr, s) ++ } ++} ++ ++func TestUnwrite(t *testing.T) { ++ var b Builder ++ b.AddBytes([]byte{1, 2, 3, 4, 5}) ++ b.Unwrite(2) ++ if err := builderBytesEq(&b, 1, 2, 3); err != nil { ++ t.Error(err) ++ } ++ ++ func() { ++ defer func() { ++ if recover() == nil { ++ t.Errorf("recover() = nil, want error; b.Unwrite() did not panic") ++ } ++ }() ++ b.Unwrite(4) // panics ++ }() ++ ++ b = Builder{} ++ b.AddBytes([]byte{1, 2, 3, 4, 5}) ++ b.AddUint8LengthPrefixed(func(b *Builder) { ++ b.AddBytes([]byte{1, 2, 3, 4, 5}) ++ ++ defer func() { ++ if recover() == nil { ++ t.Errorf("recover() = nil, want error; b.Unwrite() did not panic") ++ } ++ }() ++ b.Unwrite(6) // panics ++ }) ++ ++ b = Builder{} ++ b.AddBytes([]byte{1, 2, 3, 4, 5}) ++ b.AddUint8LengthPrefixed(func(c *Builder) { ++ defer func() { ++ if recover() == nil { ++ t.Errorf("recover() = nil, want error; b.Unwrite() did not panic") ++ } ++ }() ++ b.Unwrite(2) // panics (attempted unwrite while child is pending) ++ }) ++} ++ ++func TestFixedBuilderLengthPrefixed(t *testing.T) { ++ bufCap := 10 ++ inner := bytes.Repeat([]byte{0xff}, bufCap-2) ++ buf := make([]byte, 0, bufCap) ++ b := NewFixedBuilder(buf) ++ b.AddUint16LengthPrefixed(func(b *Builder) { ++ b.AddBytes(inner) ++ }) ++ if got := b.BytesOrPanic(); len(got) != bufCap { ++ t.Errorf("Expected output length to be %d, got %d", bufCap, len(got)) ++ } ++} ++ ++func TestFixedBuilderPanicReallocate(t *testing.T) { ++ defer func() { ++ recover() ++ }() ++ ++ b := NewFixedBuilder(make([]byte, 0, 10)) ++ b1 := NewFixedBuilder(make([]byte, 0, 10)) ++ b.AddUint16LengthPrefixed(func(b *Builder) { ++ *b = *b1 ++ }) ++ ++ t.Error("Builder did not panic") ++} ++ ++// ASN.1 ++ ++func TestASN1Int64(t *testing.T) { ++ tests := []struct { ++ in int64 ++ want []byte ++ }{ ++ {-0x800000, []byte{2, 3, 128, 0, 0}}, ++ {-256, []byte{2, 2, 255, 0}}, ++ {-129, []byte{2, 2, 255, 127}}, ++ {-128, []byte{2, 1, 128}}, ++ {-1, []byte{2, 1, 255}}, ++ {0, []byte{2, 1, 0}}, ++ {1, []byte{2, 1, 1}}, ++ {2, []byte{2, 1, 2}}, ++ {127, []byte{2, 1, 127}}, ++ {128, []byte{2, 2, 0, 128}}, ++ {256, []byte{2, 2, 1, 0}}, ++ {0x800000, []byte{2, 4, 0, 128, 0, 0}}, ++ } ++ for i, tt := range tests { ++ var b Builder ++ b.AddASN1Int64(tt.in) ++ if err := builderBytesEq(&b, tt.want...); err != nil { ++ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in) ++ } ++ ++ var n int64 ++ s := String(b.BytesOrPanic()) ++ ok := s.ReadASN1Integer(&n) ++ if !ok || n != tt.in { ++ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)", ++ ok, n, tt.in, i) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++ } ++} ++ ++func TestASN1Uint64(t *testing.T) { ++ tests := []struct { ++ in uint64 ++ want []byte ++ }{ ++ {0, []byte{2, 1, 0}}, ++ {1, []byte{2, 1, 1}}, ++ {2, []byte{2, 1, 2}}, ++ {127, []byte{2, 1, 127}}, ++ {128, []byte{2, 2, 0, 128}}, ++ {256, []byte{2, 2, 1, 0}}, ++ {0x800000, []byte{2, 4, 0, 128, 0, 0}}, ++ {0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}}, ++ {0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}}, ++ {0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}}, ++ } ++ for i, tt := range tests { ++ var b Builder ++ b.AddASN1Uint64(tt.in) ++ if err := builderBytesEq(&b, tt.want...); err != nil { ++ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in) ++ } ++ ++ var n uint64 ++ s := String(b.BytesOrPanic()) ++ ok := s.ReadASN1Integer(&n) ++ if !ok || n != tt.in { ++ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)", ++ ok, n, tt.in, i) ++ } ++ if len(s) != 0 { ++ t.Errorf("len(s) = %d, want 0", len(s)) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/example_test.go b/ms_mod/golang.org/x/crypto/cryptobyte/example_test.go +new file mode 100644 +index 00000000000000..86c098adf6141e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/example_test.go +@@ -0,0 +1,154 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package cryptobyte_test ++ ++import ( ++ "errors" ++ "fmt" ++ ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" ++) ++ ++func ExampleString_lengthPrefixed() { ++ // This is an example of parsing length-prefixed data (as found in, for ++ // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed ++ // strings. ++ ++ input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'}) ++ var result []string ++ ++ var values cryptobyte.String ++ if !input.ReadUint16LengthPrefixed(&values) || ++ !input.Empty() { ++ panic("bad format") ++ } ++ ++ for !values.Empty() { ++ var value cryptobyte.String ++ if !values.ReadUint8LengthPrefixed(&value) { ++ panic("bad format") ++ } ++ ++ result = append(result, string(value)) ++ } ++ ++ // Output: []string{"hello", "world"} ++ fmt.Printf("%#v\n", result) ++} ++ ++func ExampleString_aSN1() { ++ // This is an example of parsing ASN.1 data that looks like: ++ // Foo ::= SEQUENCE { ++ // version [6] INTEGER DEFAULT 0 ++ // data OCTET STRING ++ // } ++ ++ input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'}) ++ ++ var ( ++ version int64 ++ data, inner, versionBytes cryptobyte.String ++ haveVersion bool ++ ) ++ if !input.ReadASN1(&inner, asn1.SEQUENCE) || ++ !input.Empty() || ++ !inner.ReadOptionalASN1(&versionBytes, &haveVersion, asn1.Tag(6).Constructed().ContextSpecific()) || ++ (haveVersion && !versionBytes.ReadASN1Integer(&version)) || ++ (haveVersion && !versionBytes.Empty()) || ++ !inner.ReadASN1(&data, asn1.OCTET_STRING) || ++ !inner.Empty() { ++ panic("bad format") ++ } ++ ++ // Output: haveVersion: true, version: 2, data: hello ++ fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data)) ++} ++ ++func ExampleBuilder_aSN1() { ++ // This is an example of building ASN.1 data that looks like: ++ // Foo ::= SEQUENCE { ++ // version [6] INTEGER DEFAULT 0 ++ // data OCTET STRING ++ // } ++ ++ version := int64(2) ++ data := []byte("hello") ++ const defaultVersion = 0 ++ ++ var b cryptobyte.Builder ++ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { ++ if version != defaultVersion { ++ b.AddASN1(asn1.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) { ++ b.AddASN1Int64(version) ++ }) ++ } ++ b.AddASN1OctetString(data) ++ }) ++ ++ result, err := b.Bytes() ++ if err != nil { ++ panic(err) ++ } ++ ++ // Output: 300ca603020102040568656c6c6f ++ fmt.Printf("%x\n", result) ++} ++ ++func ExampleBuilder_lengthPrefixed() { ++ // This is an example of building length-prefixed data (as found in, ++ // for example, TLS). Imagine a 16-bit prefixed series of 8-bit ++ // prefixed strings. ++ input := []string{"hello", "world"} ++ ++ var b cryptobyte.Builder ++ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { ++ for _, value := range input { ++ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { ++ b.AddBytes([]byte(value)) ++ }) ++ } ++ }) ++ ++ result, err := b.Bytes() ++ if err != nil { ++ panic(err) ++ } ++ ++ // Output: 000c0568656c6c6f05776f726c64 ++ fmt.Printf("%x\n", result) ++} ++ ++func ExampleBuilder_lengthPrefixOverflow() { ++ // Writing more data that can be expressed by the length prefix results ++ // in an error from Bytes(). ++ ++ tooLarge := make([]byte, 256) ++ ++ var b cryptobyte.Builder ++ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { ++ b.AddBytes(tooLarge) ++ }) ++ ++ result, err := b.Bytes() ++ fmt.Printf("len=%d err=%s\n", len(result), err) ++ ++ // Output: len=0 err=cryptobyte: pending child length 256 exceeds 1-byte length prefix ++} ++ ++func ExampleBuilderContinuation_errorHandling() { ++ var b cryptobyte.Builder ++ // Continuations that panic with a BuildError will cause Bytes to ++ // return the inner error. ++ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { ++ b.AddUint32(0) ++ panic(cryptobyte.BuildError{Err: errors.New("example error")}) ++ }) ++ ++ result, err := b.Bytes() ++ fmt.Printf("len=%d err=%s\n", len(result), err) ++ ++ // Output: len=0 err=example error ++} +diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/string.go b/ms_mod/golang.org/x/crypto/cryptobyte/string.go +new file mode 100644 +index 00000000000000..0531a3d6f1aa9e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/cryptobyte/string.go +@@ -0,0 +1,172 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package cryptobyte contains types that help with parsing and constructing ++// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage ++// contains useful ASN.1 constants.) ++// ++// The String type is for parsing. It wraps a []byte slice and provides helper ++// functions for consuming structures, value by value. ++// ++// The Builder type is for constructing messages. It providers helper functions ++// for appending values and also for appending length-prefixed submessages – ++// without having to worry about calculating the length prefix ahead of time. ++// ++// See the documentation and examples for the Builder and String types to get ++// started. ++package cryptobyte // import "golang.org/x/crypto/cryptobyte" ++ ++// String represents a string of bytes. It provides methods for parsing ++// fixed-length and length-prefixed values from it. ++type String []byte ++ ++// read advances a String by n bytes and returns them. If less than n bytes ++// remain, it returns nil. ++func (s *String) read(n int) []byte { ++ if len(*s) < n || n < 0 { ++ return nil ++ } ++ v := (*s)[:n] ++ *s = (*s)[n:] ++ return v ++} ++ ++// Skip advances the String by n byte and reports whether it was successful. ++func (s *String) Skip(n int) bool { ++ return s.read(n) != nil ++} ++ ++// ReadUint8 decodes an 8-bit value into out and advances over it. ++// It reports whether the read was successful. ++func (s *String) ReadUint8(out *uint8) bool { ++ v := s.read(1) ++ if v == nil { ++ return false ++ } ++ *out = uint8(v[0]) ++ return true ++} ++ ++// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. ++// It reports whether the read was successful. ++func (s *String) ReadUint16(out *uint16) bool { ++ v := s.read(2) ++ if v == nil { ++ return false ++ } ++ *out = uint16(v[0])<<8 | uint16(v[1]) ++ return true ++} ++ ++// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. ++// It reports whether the read was successful. ++func (s *String) ReadUint24(out *uint32) bool { ++ v := s.read(3) ++ if v == nil { ++ return false ++ } ++ *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2]) ++ return true ++} ++ ++// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. ++// It reports whether the read was successful. ++func (s *String) ReadUint32(out *uint32) bool { ++ v := s.read(4) ++ if v == nil { ++ return false ++ } ++ *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) ++ return true ++} ++ ++// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it. ++// It reports whether the read was successful. ++func (s *String) ReadUint64(out *uint64) bool { ++ v := s.read(8) ++ if v == nil { ++ return false ++ } ++ *out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7]) ++ return true ++} ++ ++func (s *String) readUnsigned(out *uint32, length int) bool { ++ v := s.read(length) ++ if v == nil { ++ return false ++ } ++ var result uint32 ++ for i := 0; i < length; i++ { ++ result <<= 8 ++ result |= uint32(v[i]) ++ } ++ *out = result ++ return true ++} ++ ++func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { ++ lenBytes := s.read(lenLen) ++ if lenBytes == nil { ++ return false ++ } ++ var length uint32 ++ for _, b := range lenBytes { ++ length = length << 8 ++ length = length | uint32(b) ++ } ++ v := s.read(int(length)) ++ if v == nil { ++ return false ++ } ++ *outChild = v ++ return true ++} ++ ++// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value ++// into out and advances over it. It reports whether the read was successful. ++func (s *String) ReadUint8LengthPrefixed(out *String) bool { ++ return s.readLengthPrefixed(1, out) ++} ++ ++// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit ++// length-prefixed value into out and advances over it. It reports whether the ++// read was successful. ++func (s *String) ReadUint16LengthPrefixed(out *String) bool { ++ return s.readLengthPrefixed(2, out) ++} ++ ++// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit ++// length-prefixed value into out and advances over it. It reports whether ++// the read was successful. ++func (s *String) ReadUint24LengthPrefixed(out *String) bool { ++ return s.readLengthPrefixed(3, out) ++} ++ ++// ReadBytes reads n bytes into out and advances over them. It reports ++// whether the read was successful. ++func (s *String) ReadBytes(out *[]byte, n int) bool { ++ v := s.read(n) ++ if v == nil { ++ return false ++ } ++ *out = v ++ return true ++} ++ ++// CopyBytes copies len(out) bytes into out and advances over them. It reports ++// whether the copy operation was successful ++func (s *String) CopyBytes(out []byte) bool { ++ n := len(out) ++ v := s.read(n) ++ if v == nil { ++ return false ++ } ++ return copy(out, v) == n ++} ++ ++// Empty reports whether the string does not contain any bytes. ++func (s String) Empty() bool { ++ return len(s) == 0 ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519.go +new file mode 100644 +index 00000000000000..00f963ea20a35e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519.go +@@ -0,0 +1,59 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package curve25519 provides an implementation of the X25519 function, which ++// performs scalar multiplication on the elliptic curve known as Curve25519. ++// See RFC 7748. ++// ++// Starting in Go 1.20, this package is a wrapper for the X25519 implementation ++// in the crypto/ecdh package. ++package curve25519 // import "golang.org/x/crypto/curve25519" ++ ++// ScalarMult sets dst to the product scalar * point. ++// ++// Deprecated: when provided a low-order point, ScalarMult will set dst to all ++// zeroes, irrespective of the scalar. Instead, use the X25519 function, which ++// will return an error. ++func ScalarMult(dst, scalar, point *[32]byte) { ++ scalarMult(dst, scalar, point) ++} ++ ++// ScalarBaseMult sets dst to the product scalar * base where base is the ++// standard generator. ++// ++// It is recommended to use the X25519 function with Basepoint instead, as ++// copying into fixed size arrays can lead to unexpected bugs. ++func ScalarBaseMult(dst, scalar *[32]byte) { ++ scalarBaseMult(dst, scalar) ++} ++ ++const ( ++ // ScalarSize is the size of the scalar input to X25519. ++ ScalarSize = 32 ++ // PointSize is the size of the point input to X25519. ++ PointSize = 32 ++) ++ ++// Basepoint is the canonical Curve25519 generator. ++var Basepoint []byte ++ ++var basePoint = [32]byte{9} ++ ++func init() { Basepoint = basePoint[:] } ++ ++// X25519 returns the result of the scalar multiplication (scalar * point), ++// according to RFC 7748, Section 5. scalar, point and the return value are ++// slices of 32 bytes. ++// ++// scalar can be generated at random, for example with crypto/rand. point should ++// be either Basepoint or the output of another X25519 call. ++// ++// If point is Basepoint (but not if it's a different slice with the same ++// contents) a precomputed implementation might be used for performance. ++func X25519(scalar, point []byte) ([]byte, error) { ++ // Outline the body of function, to let the allocation be inlined in the ++ // caller, and possibly avoid escaping to the heap. ++ var dst [32]byte ++ return x25519(&dst, scalar, point) ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go +new file mode 100644 +index 00000000000000..ba647e8d77d985 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go +@@ -0,0 +1,105 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !go1.20 ++ ++package curve25519 ++ ++import ( ++ "crypto/subtle" ++ "errors" ++ "strconv" ++ ++ "golang.org/x/crypto/curve25519/internal/field" ++) ++ ++func scalarMult(dst, scalar, point *[32]byte) { ++ var e [32]byte ++ ++ copy(e[:], scalar[:]) ++ e[0] &= 248 ++ e[31] &= 127 ++ e[31] |= 64 ++ ++ var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element ++ x1.SetBytes(point[:]) ++ x2.One() ++ x3.Set(&x1) ++ z3.One() ++ ++ swap := 0 ++ for pos := 254; pos >= 0; pos-- { ++ b := e[pos/8] >> uint(pos&7) ++ b &= 1 ++ swap ^= int(b) ++ x2.Swap(&x3, swap) ++ z2.Swap(&z3, swap) ++ swap = int(b) ++ ++ tmp0.Subtract(&x3, &z3) ++ tmp1.Subtract(&x2, &z2) ++ x2.Add(&x2, &z2) ++ z2.Add(&x3, &z3) ++ z3.Multiply(&tmp0, &x2) ++ z2.Multiply(&z2, &tmp1) ++ tmp0.Square(&tmp1) ++ tmp1.Square(&x2) ++ x3.Add(&z3, &z2) ++ z2.Subtract(&z3, &z2) ++ x2.Multiply(&tmp1, &tmp0) ++ tmp1.Subtract(&tmp1, &tmp0) ++ z2.Square(&z2) ++ ++ z3.Mult32(&tmp1, 121666) ++ x3.Square(&x3) ++ tmp0.Add(&tmp0, &z3) ++ z3.Multiply(&x1, &z2) ++ z2.Multiply(&tmp1, &tmp0) ++ } ++ ++ x2.Swap(&x3, swap) ++ z2.Swap(&z3, swap) ++ ++ z2.Invert(&z2) ++ x2.Multiply(&x2, &z2) ++ copy(dst[:], x2.Bytes()) ++} ++ ++func scalarBaseMult(dst, scalar *[32]byte) { ++ checkBasepoint() ++ scalarMult(dst, scalar, &basePoint) ++} ++ ++func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { ++ var in [32]byte ++ if l := len(scalar); l != 32 { ++ return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32") ++ } ++ if l := len(point); l != 32 { ++ return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32") ++ } ++ copy(in[:], scalar) ++ if &point[0] == &Basepoint[0] { ++ scalarBaseMult(dst, &in) ++ } else { ++ var base, zero [32]byte ++ copy(base[:], point) ++ scalarMult(dst, &in, &base) ++ if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 { ++ return nil, errors.New("bad input point: low order point") ++ } ++ } ++ return dst[:], nil ++} ++ ++func checkBasepoint() { ++ if subtle.ConstantTimeCompare(Basepoint, []byte{ ++ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ }) != 1 { ++ panic("curve25519: global Basepoint value was modified") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go +new file mode 100644 +index 00000000000000..627df497270f9c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go +@@ -0,0 +1,46 @@ ++// Copyright 2022 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.20 ++ ++package curve25519 ++ ++import "crypto/ecdh" ++ ++func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { ++ curve := ecdh.X25519() ++ pub, err := curve.NewPublicKey(point) ++ if err != nil { ++ return nil, err ++ } ++ priv, err := curve.NewPrivateKey(scalar) ++ if err != nil { ++ return nil, err ++ } ++ out, err := priv.ECDH(pub) ++ if err != nil { ++ return nil, err ++ } ++ copy(dst[:], out) ++ return dst[:], nil ++} ++ ++func scalarMult(dst, scalar, point *[32]byte) { ++ if _, err := x25519(dst, scalar[:], point[:]); err != nil { ++ // The only error condition for x25519 when the inputs are 32 bytes long ++ // is if the output would have been the all-zero value. ++ for i := range dst { ++ dst[i] = 0 ++ } ++ } ++} ++ ++func scalarBaseMult(dst, scalar *[32]byte) { ++ curve := ecdh.X25519() ++ priv, err := curve.NewPrivateKey(scalar[:]) ++ if err != nil { ++ panic("curve25519: internal error: scalarBaseMult was not 32 bytes") ++ } ++ copy(dst[:], priv.PublicKey().Bytes()) ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go +new file mode 100644 +index 00000000000000..e2b338b5ecf23d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go +@@ -0,0 +1,142 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package curve25519_test ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/hex" ++ "testing" ++ ++ "golang.org/x/crypto/curve25519" ++) ++ ++const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" ++ ++func TestX25519Basepoint(t *testing.T) { ++ x := make([]byte, 32) ++ x[0] = 1 ++ ++ for i := 0; i < 200; i++ { ++ var err error ++ x, err = curve25519.X25519(x, curve25519.Basepoint) ++ if err != nil { ++ t.Fatal(err) ++ } ++ } ++ ++ result := hex.EncodeToString(x) ++ if result != expectedHex { ++ t.Errorf("incorrect result: got %s, want %s", result, expectedHex) ++ } ++} ++ ++func TestLowOrderPoints(t *testing.T) { ++ scalar := make([]byte, curve25519.ScalarSize) ++ if _, err := rand.Read(scalar); err != nil { ++ t.Fatal(err) ++ } ++ for i, p := range lowOrderPoints { ++ out, err := curve25519.X25519(scalar, p) ++ if err == nil { ++ t.Errorf("%d: expected error, got nil", i) ++ } ++ if out != nil { ++ t.Errorf("%d: expected nil output, got %x", i, out) ++ } ++ } ++} ++ ++func TestTestVectors(t *testing.T) { ++ t.Run("Legacy", func(t *testing.T) { testTestVectors(t, curve25519.ScalarMult) }) ++ t.Run("X25519", func(t *testing.T) { ++ testTestVectors(t, func(dst, scalar, point *[32]byte) { ++ out, err := curve25519.X25519(scalar[:], point[:]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ copy(dst[:], out) ++ }) ++ }) ++} ++ ++func testTestVectors(t *testing.T, scalarMult func(dst, scalar, point *[32]byte)) { ++ for _, tv := range testVectors { ++ var got [32]byte ++ scalarMult(&got, &tv.In, &tv.Base) ++ if !bytes.Equal(got[:], tv.Expect[:]) { ++ t.Logf(" in = %x", tv.In) ++ t.Logf(" base = %x", tv.Base) ++ t.Logf(" got = %x", got) ++ t.Logf("expect = %x", tv.Expect) ++ t.Fail() ++ } ++ } ++} ++ ++// TestHighBitIgnored tests the following requirement in RFC 7748: ++// ++// When receiving such an array, implementations of X25519 (but not X448) MUST ++// mask the most significant bit in the final byte. ++// ++// Regression test for issue #30095. ++func TestHighBitIgnored(t *testing.T) { ++ var s, u [32]byte ++ rand.Read(s[:]) ++ rand.Read(u[:]) ++ ++ var hi0, hi1 [32]byte ++ ++ u[31] &= 0x7f ++ curve25519.ScalarMult(&hi0, &s, &u) ++ ++ u[31] |= 0x80 ++ curve25519.ScalarMult(&hi1, &s, &u) ++ ++ if !bytes.Equal(hi0[:], hi1[:]) { ++ t.Errorf("high bit of group point should not affect result") ++ } ++} ++ ++var benchmarkSink byte ++ ++func BenchmarkX25519Basepoint(b *testing.B) { ++ scalar := make([]byte, curve25519.ScalarSize) ++ if _, err := rand.Read(scalar); err != nil { ++ b.Fatal(err) ++ } ++ ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ out, err := curve25519.X25519(scalar, curve25519.Basepoint) ++ if err != nil { ++ b.Fatal(err) ++ } ++ benchmarkSink ^= out[0] ++ } ++} ++ ++func BenchmarkX25519(b *testing.B) { ++ scalar := make([]byte, curve25519.ScalarSize) ++ if _, err := rand.Read(scalar); err != nil { ++ b.Fatal(err) ++ } ++ point, err := curve25519.X25519(scalar, curve25519.Basepoint) ++ if err != nil { ++ b.Fatal(err) ++ } ++ if _, err := rand.Read(scalar); err != nil { ++ b.Fatal(err) ++ } ++ ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ out, err := curve25519.X25519(scalar, point) ++ if err != nil { ++ b.Fatal(err) ++ } ++ benchmarkSink ^= out[0] ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/README b/ms_mod/golang.org/x/crypto/curve25519/internal/field/README +new file mode 100644 +index 00000000000000..e25bca7dc806b3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/README +@@ -0,0 +1,7 @@ ++This package is kept in sync with crypto/ed25519/internal/edwards25519/field in ++the standard library. ++ ++If there are any changes in the standard library that need to be synced to this ++package, run sync.sh. It will not overwrite any local changes made since the ++previous sync, so it's ok to land changes in this package first, and then sync ++to the standard library later. +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go +new file mode 100644 +index 00000000000000..1f3652987e84f8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go +@@ -0,0 +1,298 @@ ++// Copyright (c) 2021 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package main ++ ++import ( ++ "fmt" ++ ++ . "github.com/mmcloughlin/avo/build" ++ . "github.com/mmcloughlin/avo/gotypes" ++ . "github.com/mmcloughlin/avo/operand" ++ . "github.com/mmcloughlin/avo/reg" ++ ++ // Ensure "go mod tidy" doesn't remove the golang.org/x/crypto module ++ // dependency, which is necessary to access the field.Element type. ++ _ "golang.org/x/crypto/curve25519" ++) ++ ++//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field ++ ++func main() { ++ Package("golang.org/x/crypto/curve25519/internal/field") ++ ConstraintExpr("amd64,gc,!purego") ++ feMul() ++ feSquare() ++ Generate() ++} ++ ++type namedComponent struct { ++ Component ++ name string ++} ++ ++func (c namedComponent) String() string { return c.name } ++ ++type uint128 struct { ++ name string ++ hi, lo GPVirtual ++} ++ ++func (c uint128) String() string { return c.name } ++ ++func feSquare() { ++ TEXT("feSquare", NOSPLIT, "func(out, a *Element)") ++ Doc("feSquare sets out = a * a. It works like feSquareGeneric.") ++ Pragma("noescape") ++ ++ a := Dereference(Param("a")) ++ l0 := namedComponent{a.Field("l0"), "l0"} ++ l1 := namedComponent{a.Field("l1"), "l1"} ++ l2 := namedComponent{a.Field("l2"), "l2"} ++ l3 := namedComponent{a.Field("l3"), "l3"} ++ l4 := namedComponent{a.Field("l4"), "l4"} ++ ++ // r0 = l0Γ—l0 + 19Γ—2Γ—(l1Γ—l4 + l2Γ—l3) ++ r0 := uint128{"r0", GP64(), GP64()} ++ mul64(r0, 1, l0, l0) ++ addMul64(r0, 38, l1, l4) ++ addMul64(r0, 38, l2, l3) ++ ++ // r1 = 2Γ—l0Γ—l1 + 19Γ—2Γ—l2Γ—l4 + 19Γ—l3Γ—l3 ++ r1 := uint128{"r1", GP64(), GP64()} ++ mul64(r1, 2, l0, l1) ++ addMul64(r1, 38, l2, l4) ++ addMul64(r1, 19, l3, l3) ++ ++ // r2 = = 2Γ—l0Γ—l2 + l1Γ—l1 + 19Γ—2Γ—l3Γ—l4 ++ r2 := uint128{"r2", GP64(), GP64()} ++ mul64(r2, 2, l0, l2) ++ addMul64(r2, 1, l1, l1) ++ addMul64(r2, 38, l3, l4) ++ ++ // r3 = = 2Γ—l0Γ—l3 + 2Γ—l1Γ—l2 + 19Γ—l4Γ—l4 ++ r3 := uint128{"r3", GP64(), GP64()} ++ mul64(r3, 2, l0, l3) ++ addMul64(r3, 2, l1, l2) ++ addMul64(r3, 19, l4, l4) ++ ++ // r4 = = 2Γ—l0Γ—l4 + 2Γ—l1Γ—l3 + l2Γ—l2 ++ r4 := uint128{"r4", GP64(), GP64()} ++ mul64(r4, 2, l0, l4) ++ addMul64(r4, 2, l1, l3) ++ addMul64(r4, 1, l2, l2) ++ ++ Comment("First reduction chain") ++ maskLow51Bits := GP64() ++ MOVQ(Imm((1<<51)-1), maskLow51Bits) ++ c0, r0lo := shiftRightBy51(&r0) ++ c1, r1lo := shiftRightBy51(&r1) ++ c2, r2lo := shiftRightBy51(&r2) ++ c3, r3lo := shiftRightBy51(&r3) ++ c4, r4lo := shiftRightBy51(&r4) ++ maskAndAdd(r0lo, maskLow51Bits, c4, 19) ++ maskAndAdd(r1lo, maskLow51Bits, c0, 1) ++ maskAndAdd(r2lo, maskLow51Bits, c1, 1) ++ maskAndAdd(r3lo, maskLow51Bits, c2, 1) ++ maskAndAdd(r4lo, maskLow51Bits, c3, 1) ++ ++ Comment("Second reduction chain (carryPropagate)") ++ // c0 = r0 >> 51 ++ MOVQ(r0lo, c0) ++ SHRQ(Imm(51), c0) ++ // c1 = r1 >> 51 ++ MOVQ(r1lo, c1) ++ SHRQ(Imm(51), c1) ++ // c2 = r2 >> 51 ++ MOVQ(r2lo, c2) ++ SHRQ(Imm(51), c2) ++ // c3 = r3 >> 51 ++ MOVQ(r3lo, c3) ++ SHRQ(Imm(51), c3) ++ // c4 = r4 >> 51 ++ MOVQ(r4lo, c4) ++ SHRQ(Imm(51), c4) ++ maskAndAdd(r0lo, maskLow51Bits, c4, 19) ++ maskAndAdd(r1lo, maskLow51Bits, c0, 1) ++ maskAndAdd(r2lo, maskLow51Bits, c1, 1) ++ maskAndAdd(r3lo, maskLow51Bits, c2, 1) ++ maskAndAdd(r4lo, maskLow51Bits, c3, 1) ++ ++ Comment("Store output") ++ out := Dereference(Param("out")) ++ Store(r0lo, out.Field("l0")) ++ Store(r1lo, out.Field("l1")) ++ Store(r2lo, out.Field("l2")) ++ Store(r3lo, out.Field("l3")) ++ Store(r4lo, out.Field("l4")) ++ ++ RET() ++} ++ ++func feMul() { ++ TEXT("feMul", NOSPLIT, "func(out, a, b *Element)") ++ Doc("feMul sets out = a * b. It works like feMulGeneric.") ++ Pragma("noescape") ++ ++ a := Dereference(Param("a")) ++ a0 := namedComponent{a.Field("l0"), "a0"} ++ a1 := namedComponent{a.Field("l1"), "a1"} ++ a2 := namedComponent{a.Field("l2"), "a2"} ++ a3 := namedComponent{a.Field("l3"), "a3"} ++ a4 := namedComponent{a.Field("l4"), "a4"} ++ ++ b := Dereference(Param("b")) ++ b0 := namedComponent{b.Field("l0"), "b0"} ++ b1 := namedComponent{b.Field("l1"), "b1"} ++ b2 := namedComponent{b.Field("l2"), "b2"} ++ b3 := namedComponent{b.Field("l3"), "b3"} ++ b4 := namedComponent{b.Field("l4"), "b4"} ++ ++ // r0 = a0Γ—b0 + 19Γ—(a1Γ—b4 + a2Γ—b3 + a3Γ—b2 + a4Γ—b1) ++ r0 := uint128{"r0", GP64(), GP64()} ++ mul64(r0, 1, a0, b0) ++ addMul64(r0, 19, a1, b4) ++ addMul64(r0, 19, a2, b3) ++ addMul64(r0, 19, a3, b2) ++ addMul64(r0, 19, a4, b1) ++ ++ // r1 = a0Γ—b1 + a1Γ—b0 + 19Γ—(a2Γ—b4 + a3Γ—b3 + a4Γ—b2) ++ r1 := uint128{"r1", GP64(), GP64()} ++ mul64(r1, 1, a0, b1) ++ addMul64(r1, 1, a1, b0) ++ addMul64(r1, 19, a2, b4) ++ addMul64(r1, 19, a3, b3) ++ addMul64(r1, 19, a4, b2) ++ ++ // r2 = a0Γ—b2 + a1Γ—b1 + a2Γ—b0 + 19Γ—(a3Γ—b4 + a4Γ—b3) ++ r2 := uint128{"r2", GP64(), GP64()} ++ mul64(r2, 1, a0, b2) ++ addMul64(r2, 1, a1, b1) ++ addMul64(r2, 1, a2, b0) ++ addMul64(r2, 19, a3, b4) ++ addMul64(r2, 19, a4, b3) ++ ++ // r3 = a0Γ—b3 + a1Γ—b2 + a2Γ—b1 + a3Γ—b0 + 19Γ—a4Γ—b4 ++ r3 := uint128{"r3", GP64(), GP64()} ++ mul64(r3, 1, a0, b3) ++ addMul64(r3, 1, a1, b2) ++ addMul64(r3, 1, a2, b1) ++ addMul64(r3, 1, a3, b0) ++ addMul64(r3, 19, a4, b4) ++ ++ // r4 = a0Γ—b4 + a1Γ—b3 + a2Γ—b2 + a3Γ—b1 + a4Γ—b0 ++ r4 := uint128{"r4", GP64(), GP64()} ++ mul64(r4, 1, a0, b4) ++ addMul64(r4, 1, a1, b3) ++ addMul64(r4, 1, a2, b2) ++ addMul64(r4, 1, a3, b1) ++ addMul64(r4, 1, a4, b0) ++ ++ Comment("First reduction chain") ++ maskLow51Bits := GP64() ++ MOVQ(Imm((1<<51)-1), maskLow51Bits) ++ c0, r0lo := shiftRightBy51(&r0) ++ c1, r1lo := shiftRightBy51(&r1) ++ c2, r2lo := shiftRightBy51(&r2) ++ c3, r3lo := shiftRightBy51(&r3) ++ c4, r4lo := shiftRightBy51(&r4) ++ maskAndAdd(r0lo, maskLow51Bits, c4, 19) ++ maskAndAdd(r1lo, maskLow51Bits, c0, 1) ++ maskAndAdd(r2lo, maskLow51Bits, c1, 1) ++ maskAndAdd(r3lo, maskLow51Bits, c2, 1) ++ maskAndAdd(r4lo, maskLow51Bits, c3, 1) ++ ++ Comment("Second reduction chain (carryPropagate)") ++ // c0 = r0 >> 51 ++ MOVQ(r0lo, c0) ++ SHRQ(Imm(51), c0) ++ // c1 = r1 >> 51 ++ MOVQ(r1lo, c1) ++ SHRQ(Imm(51), c1) ++ // c2 = r2 >> 51 ++ MOVQ(r2lo, c2) ++ SHRQ(Imm(51), c2) ++ // c3 = r3 >> 51 ++ MOVQ(r3lo, c3) ++ SHRQ(Imm(51), c3) ++ // c4 = r4 >> 51 ++ MOVQ(r4lo, c4) ++ SHRQ(Imm(51), c4) ++ maskAndAdd(r0lo, maskLow51Bits, c4, 19) ++ maskAndAdd(r1lo, maskLow51Bits, c0, 1) ++ maskAndAdd(r2lo, maskLow51Bits, c1, 1) ++ maskAndAdd(r3lo, maskLow51Bits, c2, 1) ++ maskAndAdd(r4lo, maskLow51Bits, c3, 1) ++ ++ Comment("Store output") ++ out := Dereference(Param("out")) ++ Store(r0lo, out.Field("l0")) ++ Store(r1lo, out.Field("l1")) ++ Store(r2lo, out.Field("l2")) ++ Store(r3lo, out.Field("l3")) ++ Store(r4lo, out.Field("l4")) ++ ++ RET() ++} ++ ++// mul64 sets r to i * aX * bX. ++func mul64(r uint128, i int, aX, bX namedComponent) { ++ switch i { ++ case 1: ++ Comment(fmt.Sprintf("%s = %sΓ—%s", r, aX, bX)) ++ Load(aX, RAX) ++ case 2: ++ Comment(fmt.Sprintf("%s = 2Γ—%sΓ—%s", r, aX, bX)) ++ Load(aX, RAX) ++ SHLQ(Imm(1), RAX) ++ default: ++ panic("unsupported i value") ++ } ++ MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX ++ MOVQ(RAX, r.lo) ++ MOVQ(RDX, r.hi) ++} ++ ++// addMul64 sets r to r + i * aX * bX. ++func addMul64(r uint128, i uint64, aX, bX namedComponent) { ++ switch i { ++ case 1: ++ Comment(fmt.Sprintf("%s += %sΓ—%s", r, aX, bX)) ++ Load(aX, RAX) ++ default: ++ Comment(fmt.Sprintf("%s += %dΓ—%sΓ—%s", r, i, aX, bX)) ++ IMUL3Q(Imm(i), Load(aX, GP64()), RAX) ++ } ++ MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX ++ ADDQ(RAX, r.lo) ++ ADCQ(RDX, r.hi) ++} ++ ++// shiftRightBy51 returns r >> 51 and r.lo. ++// ++// After this function is called, the uint128 may not be used anymore. ++func shiftRightBy51(r *uint128) (out, lo GPVirtual) { ++ out = r.hi ++ lo = r.lo ++ SHLQ(Imm(64-51), r.lo, r.hi) ++ r.lo, r.hi = nil, nil // make sure the uint128 is unusable ++ return ++} ++ ++// maskAndAdd sets r = r&mask + c*i. ++func maskAndAdd(r, mask, c GPVirtual, i uint64) { ++ ANDQ(mask, r) ++ if i != 1 { ++ IMUL3Q(Imm(i), c, c) ++ } ++ ADDQ(c, r) ++} ++ ++func mustAddr(c Component) Op { ++ b, err := c.Resolve() ++ if err != nil { ++ panic(err) ++ } ++ return b.Addr ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod +new file mode 100644 +index 00000000000000..5b3dba315e7f90 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod +@@ -0,0 +1,10 @@ ++module asm ++ ++go 1.16 ++ ++require ( ++ github.com/mmcloughlin/avo v0.4.0 ++ golang.org/x/crypto v0.0.0 ++) ++ ++replace golang.org/x/crypto v0.0.0 => ../../../.. +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum +new file mode 100644 +index 00000000000000..4c9bbf675bc033 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum +@@ -0,0 +1,34 @@ ++github.com/mmcloughlin/avo v0.4.0 h1:jeHDRktVD+578ULxWpQHkilor6pkdLF7u7EiTzDbfcU= ++github.com/mmcloughlin/avo v0.4.0/go.mod h1:RW9BfYA3TgO9uCdNrKU2h6J8cPD8ZLznvfgHAeszb1s= ++github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= ++golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= ++golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= ++golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= ++golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= ++golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= ++golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= ++golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= ++golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ++golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ++golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= ++golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ++golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ++golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ++golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 h1:giLT+HuUP/gXYrG2Plg9WTjj4qhfgaW424ZIFog3rlk= ++golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= ++golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= ++golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= ++golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= ++golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= ++golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= ++golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= ++golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ++golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ++golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= ++golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ++rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go +new file mode 100644 +index 00000000000000..ca841ad99e3ab7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go +@@ -0,0 +1,416 @@ ++// Copyright (c) 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package field implements fast arithmetic modulo 2^255-19. ++package field ++ ++import ( ++ "crypto/subtle" ++ "encoding/binary" ++ "math/bits" ++) ++ ++// Element represents an element of the field GF(2^255-19). Note that this ++// is not a cryptographically secure group, and should only be used to interact ++// with edwards25519.Point coordinates. ++// ++// This type works similarly to math/big.Int, and all arguments and receivers ++// are allowed to alias. ++// ++// The zero value is a valid zero element. ++type Element struct { ++ // An element t represents the integer ++ // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 ++ // ++ // Between operations, all limbs are expected to be lower than 2^52. ++ l0 uint64 ++ l1 uint64 ++ l2 uint64 ++ l3 uint64 ++ l4 uint64 ++} ++ ++const maskLow51Bits uint64 = (1 << 51) - 1 ++ ++var feZero = &Element{0, 0, 0, 0, 0} ++ ++// Zero sets v = 0, and returns v. ++func (v *Element) Zero() *Element { ++ *v = *feZero ++ return v ++} ++ ++var feOne = &Element{1, 0, 0, 0, 0} ++ ++// One sets v = 1, and returns v. ++func (v *Element) One() *Element { ++ *v = *feOne ++ return v ++} ++ ++// reduce reduces v modulo 2^255 - 19 and returns it. ++func (v *Element) reduce() *Element { ++ v.carryPropagate() ++ ++ // After the light reduction we now have a field element representation ++ // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. ++ ++ // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, ++ // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. ++ c := (v.l0 + 19) >> 51 ++ c = (v.l1 + c) >> 51 ++ c = (v.l2 + c) >> 51 ++ c = (v.l3 + c) >> 51 ++ c = (v.l4 + c) >> 51 ++ ++ // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's ++ // effectively applying the reduction identity to the carry. ++ v.l0 += 19 * c ++ ++ v.l1 += v.l0 >> 51 ++ v.l0 = v.l0 & maskLow51Bits ++ v.l2 += v.l1 >> 51 ++ v.l1 = v.l1 & maskLow51Bits ++ v.l3 += v.l2 >> 51 ++ v.l2 = v.l2 & maskLow51Bits ++ v.l4 += v.l3 >> 51 ++ v.l3 = v.l3 & maskLow51Bits ++ // no additional carry ++ v.l4 = v.l4 & maskLow51Bits ++ ++ return v ++} ++ ++// Add sets v = a + b, and returns v. ++func (v *Element) Add(a, b *Element) *Element { ++ v.l0 = a.l0 + b.l0 ++ v.l1 = a.l1 + b.l1 ++ v.l2 = a.l2 + b.l2 ++ v.l3 = a.l3 + b.l3 ++ v.l4 = a.l4 + b.l4 ++ // Using the generic implementation here is actually faster than the ++ // assembly. Probably because the body of this function is so simple that ++ // the compiler can figure out better optimizations by inlining the carry ++ // propagation. TODO ++ return v.carryPropagateGeneric() ++} ++ ++// Subtract sets v = a - b, and returns v. ++func (v *Element) Subtract(a, b *Element) *Element { ++ // We first add 2 * p, to guarantee the subtraction won't underflow, and ++ // then subtract b (which can be up to 2^255 + 2^13 * 19). ++ v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 ++ v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 ++ v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 ++ v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 ++ v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 ++ return v.carryPropagate() ++} ++ ++// Negate sets v = -a, and returns v. ++func (v *Element) Negate(a *Element) *Element { ++ return v.Subtract(feZero, a) ++} ++ ++// Invert sets v = 1/z mod p, and returns v. ++// ++// If z == 0, Invert returns v = 0. ++func (v *Element) Invert(z *Element) *Element { ++ // Inversion is implemented as exponentiation with exponent p βˆ’ 2. It uses the ++ // same sequence of 255 squarings and 11 multiplications as [Curve25519]. ++ var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element ++ ++ z2.Square(z) // 2 ++ t.Square(&z2) // 4 ++ t.Square(&t) // 8 ++ z9.Multiply(&t, z) // 9 ++ z11.Multiply(&z9, &z2) // 11 ++ t.Square(&z11) // 22 ++ z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 ++ ++ t.Square(&z2_5_0) // 2^6 - 2^1 ++ for i := 0; i < 4; i++ { ++ t.Square(&t) // 2^10 - 2^5 ++ } ++ z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 ++ ++ t.Square(&z2_10_0) // 2^11 - 2^1 ++ for i := 0; i < 9; i++ { ++ t.Square(&t) // 2^20 - 2^10 ++ } ++ z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 ++ ++ t.Square(&z2_20_0) // 2^21 - 2^1 ++ for i := 0; i < 19; i++ { ++ t.Square(&t) // 2^40 - 2^20 ++ } ++ t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 ++ ++ t.Square(&t) // 2^41 - 2^1 ++ for i := 0; i < 9; i++ { ++ t.Square(&t) // 2^50 - 2^10 ++ } ++ z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 ++ ++ t.Square(&z2_50_0) // 2^51 - 2^1 ++ for i := 0; i < 49; i++ { ++ t.Square(&t) // 2^100 - 2^50 ++ } ++ z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 ++ ++ t.Square(&z2_100_0) // 2^101 - 2^1 ++ for i := 0; i < 99; i++ { ++ t.Square(&t) // 2^200 - 2^100 ++ } ++ t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 ++ ++ t.Square(&t) // 2^201 - 2^1 ++ for i := 0; i < 49; i++ { ++ t.Square(&t) // 2^250 - 2^50 ++ } ++ t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 ++ ++ t.Square(&t) // 2^251 - 2^1 ++ t.Square(&t) // 2^252 - 2^2 ++ t.Square(&t) // 2^253 - 2^3 ++ t.Square(&t) // 2^254 - 2^4 ++ t.Square(&t) // 2^255 - 2^5 ++ ++ return v.Multiply(&t, &z11) // 2^255 - 21 ++} ++ ++// Set sets v = a, and returns v. ++func (v *Element) Set(a *Element) *Element { ++ *v = *a ++ return v ++} ++ ++// SetBytes sets v to x, which must be a 32-byte little-endian encoding. ++// ++// Consistent with RFC 7748, the most significant bit (the high bit of the ++// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) ++// are accepted. Note that this is laxer than specified by RFC 8032. ++func (v *Element) SetBytes(x []byte) *Element { ++ if len(x) != 32 { ++ panic("edwards25519: invalid field element input size") ++ } ++ ++ // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). ++ v.l0 = binary.LittleEndian.Uint64(x[0:8]) ++ v.l0 &= maskLow51Bits ++ // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). ++ v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 ++ v.l1 &= maskLow51Bits ++ // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). ++ v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 ++ v.l2 &= maskLow51Bits ++ // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). ++ v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 ++ v.l3 &= maskLow51Bits ++ // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). ++ // Note: not bytes 25:33, shift 4, to avoid overread. ++ v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 ++ v.l4 &= maskLow51Bits ++ ++ return v ++} ++ ++// Bytes returns the canonical 32-byte little-endian encoding of v. ++func (v *Element) Bytes() []byte { ++ // This function is outlined to make the allocations inline in the caller ++ // rather than happen on the heap. ++ var out [32]byte ++ return v.bytes(&out) ++} ++ ++func (v *Element) bytes(out *[32]byte) []byte { ++ t := *v ++ t.reduce() ++ ++ var buf [8]byte ++ for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { ++ bitsOffset := i * 51 ++ binary.LittleEndian.PutUint64(buf[:], l<= len(out) { ++ break ++ } ++ out[off] |= bb ++ } ++ } ++ ++ return out[:] ++} ++ ++// Equal returns 1 if v and u are equal, and 0 otherwise. ++func (v *Element) Equal(u *Element) int { ++ sa, sv := u.Bytes(), v.Bytes() ++ return subtle.ConstantTimeCompare(sa, sv) ++} ++ ++// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. ++func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } ++ ++// Select sets v to a if cond == 1, and to b if cond == 0. ++func (v *Element) Select(a, b *Element, cond int) *Element { ++ m := mask64Bits(cond) ++ v.l0 = (m & a.l0) | (^m & b.l0) ++ v.l1 = (m & a.l1) | (^m & b.l1) ++ v.l2 = (m & a.l2) | (^m & b.l2) ++ v.l3 = (m & a.l3) | (^m & b.l3) ++ v.l4 = (m & a.l4) | (^m & b.l4) ++ return v ++} ++ ++// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. ++func (v *Element) Swap(u *Element, cond int) { ++ m := mask64Bits(cond) ++ t := m & (v.l0 ^ u.l0) ++ v.l0 ^= t ++ u.l0 ^= t ++ t = m & (v.l1 ^ u.l1) ++ v.l1 ^= t ++ u.l1 ^= t ++ t = m & (v.l2 ^ u.l2) ++ v.l2 ^= t ++ u.l2 ^= t ++ t = m & (v.l3 ^ u.l3) ++ v.l3 ^= t ++ u.l3 ^= t ++ t = m & (v.l4 ^ u.l4) ++ v.l4 ^= t ++ u.l4 ^= t ++} ++ ++// IsNegative returns 1 if v is negative, and 0 otherwise. ++func (v *Element) IsNegative() int { ++ return int(v.Bytes()[0] & 1) ++} ++ ++// Absolute sets v to |u|, and returns v. ++func (v *Element) Absolute(u *Element) *Element { ++ return v.Select(new(Element).Negate(u), u, u.IsNegative()) ++} ++ ++// Multiply sets v = x * y, and returns v. ++func (v *Element) Multiply(x, y *Element) *Element { ++ feMul(v, x, y) ++ return v ++} ++ ++// Square sets v = x * x, and returns v. ++func (v *Element) Square(x *Element) *Element { ++ feSquare(v, x) ++ return v ++} ++ ++// Mult32 sets v = x * y, and returns v. ++func (v *Element) Mult32(x *Element, y uint32) *Element { ++ x0lo, x0hi := mul51(x.l0, y) ++ x1lo, x1hi := mul51(x.l1, y) ++ x2lo, x2hi := mul51(x.l2, y) ++ x3lo, x3hi := mul51(x.l3, y) ++ x4lo, x4hi := mul51(x.l4, y) ++ v.l0 = x0lo + 19*x4hi // carried over per the reduction identity ++ v.l1 = x1lo + x0hi ++ v.l2 = x2lo + x1hi ++ v.l3 = x3lo + x2hi ++ v.l4 = x4lo + x3hi ++ // The hi portions are going to be only 32 bits, plus any previous excess, ++ // so we can skip the carry propagation. ++ return v ++} ++ ++// mul51 returns lo + hi * 2⁡¹ = a * b. ++func mul51(a uint64, b uint32) (lo uint64, hi uint64) { ++ mh, ml := bits.Mul64(a, uint64(b)) ++ lo = ml & maskLow51Bits ++ hi = (mh << 13) | (ml >> 51) ++ return ++} ++ ++// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. ++func (v *Element) Pow22523(x *Element) *Element { ++ var t0, t1, t2 Element ++ ++ t0.Square(x) // x^2 ++ t1.Square(&t0) // x^4 ++ t1.Square(&t1) // x^8 ++ t1.Multiply(x, &t1) // x^9 ++ t0.Multiply(&t0, &t1) // x^11 ++ t0.Square(&t0) // x^22 ++ t0.Multiply(&t1, &t0) // x^31 ++ t1.Square(&t0) // x^62 ++ for i := 1; i < 5; i++ { // x^992 ++ t1.Square(&t1) ++ } ++ t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 ++ t1.Square(&t0) // 2^11 - 2 ++ for i := 1; i < 10; i++ { // 2^20 - 2^10 ++ t1.Square(&t1) ++ } ++ t1.Multiply(&t1, &t0) // 2^20 - 1 ++ t2.Square(&t1) // 2^21 - 2 ++ for i := 1; i < 20; i++ { // 2^40 - 2^20 ++ t2.Square(&t2) ++ } ++ t1.Multiply(&t2, &t1) // 2^40 - 1 ++ t1.Square(&t1) // 2^41 - 2 ++ for i := 1; i < 10; i++ { // 2^50 - 2^10 ++ t1.Square(&t1) ++ } ++ t0.Multiply(&t1, &t0) // 2^50 - 1 ++ t1.Square(&t0) // 2^51 - 2 ++ for i := 1; i < 50; i++ { // 2^100 - 2^50 ++ t1.Square(&t1) ++ } ++ t1.Multiply(&t1, &t0) // 2^100 - 1 ++ t2.Square(&t1) // 2^101 - 2 ++ for i := 1; i < 100; i++ { // 2^200 - 2^100 ++ t2.Square(&t2) ++ } ++ t1.Multiply(&t2, &t1) // 2^200 - 1 ++ t1.Square(&t1) // 2^201 - 2 ++ for i := 1; i < 50; i++ { // 2^250 - 2^50 ++ t1.Square(&t1) ++ } ++ t0.Multiply(&t1, &t0) // 2^250 - 1 ++ t0.Square(&t0) // 2^251 - 2 ++ t0.Square(&t0) // 2^252 - 4 ++ return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) ++} ++ ++// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. ++var sqrtM1 = &Element{1718705420411056, 234908883556509, ++ 2233514472574048, 2117202627021982, 765476049583133} ++ ++// SqrtRatio sets r to the non-negative square root of the ratio of u and v. ++// ++// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio ++// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, ++// and returns r and 0. ++func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { ++ var a, b Element ++ ++ // r = (u * v3) * (u * v7)^((p-5)/8) ++ v2 := a.Square(v) ++ uv3 := b.Multiply(u, b.Multiply(v2, v)) ++ uv7 := a.Multiply(uv3, a.Square(v2)) ++ r.Multiply(uv3, r.Pow22523(uv7)) ++ ++ check := a.Multiply(v, a.Square(r)) // check = v * r^2 ++ ++ uNeg := b.Negate(u) ++ correctSignSqrt := check.Equal(u) ++ flippedSignSqrt := check.Equal(uNeg) ++ flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) ++ ++ rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r ++ // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) ++ r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) ++ ++ r.Absolute(r) // Choose the nonnegative square root. ++ return r, correctSignSqrt | flippedSignSqrt ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go +new file mode 100644 +index 00000000000000..64e57c4f359d5d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go +@@ -0,0 +1,126 @@ ++// Copyright (c) 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package field ++ ++import ( ++ "testing" ++ "testing/quick" ++) ++ ++func checkAliasingOneArg(f func(v, x *Element) *Element) func(v, x Element) bool { ++ return func(v, x Element) bool { ++ x1, v1 := x, x ++ ++ // Calculate a reference f(x) without aliasing. ++ if out := f(&v, &x); out != &v && isInBounds(out) { ++ return false ++ } ++ ++ // Test aliasing the argument and the receiver. ++ if out := f(&v1, &v1); out != &v1 || v1 != v { ++ return false ++ } ++ ++ // Ensure the arguments was not modified. ++ return x == x1 ++ } ++} ++ ++func checkAliasingTwoArgs(f func(v, x, y *Element) *Element) func(v, x, y Element) bool { ++ return func(v, x, y Element) bool { ++ x1, y1, v1 := x, y, Element{} ++ ++ // Calculate a reference f(x, y) without aliasing. ++ if out := f(&v, &x, &y); out != &v && isInBounds(out) { ++ return false ++ } ++ ++ // Test aliasing the first argument and the receiver. ++ v1 = x ++ if out := f(&v1, &v1, &y); out != &v1 || v1 != v { ++ return false ++ } ++ // Test aliasing the second argument and the receiver. ++ v1 = y ++ if out := f(&v1, &x, &v1); out != &v1 || v1 != v { ++ return false ++ } ++ ++ // Calculate a reference f(x, x) without aliasing. ++ if out := f(&v, &x, &x); out != &v { ++ return false ++ } ++ ++ // Test aliasing the first argument and the receiver. ++ v1 = x ++ if out := f(&v1, &v1, &x); out != &v1 || v1 != v { ++ return false ++ } ++ // Test aliasing the second argument and the receiver. ++ v1 = x ++ if out := f(&v1, &x, &v1); out != &v1 || v1 != v { ++ return false ++ } ++ // Test aliasing both arguments and the receiver. ++ v1 = x ++ if out := f(&v1, &v1, &v1); out != &v1 || v1 != v { ++ return false ++ } ++ ++ // Ensure the arguments were not modified. ++ return x == x1 && y == y1 ++ } ++} ++ ++// TestAliasing checks that receivers and arguments can alias each other without ++// leading to incorrect results. That is, it ensures that it's safe to write ++// ++// v.Invert(v) ++// ++// or ++// ++// v.Add(v, v) ++// ++// without any of the inputs getting clobbered by the output being written. ++func TestAliasing(t *testing.T) { ++ type target struct { ++ name string ++ oneArgF func(v, x *Element) *Element ++ twoArgsF func(v, x, y *Element) *Element ++ } ++ for _, tt := range []target{ ++ {name: "Absolute", oneArgF: (*Element).Absolute}, ++ {name: "Invert", oneArgF: (*Element).Invert}, ++ {name: "Negate", oneArgF: (*Element).Negate}, ++ {name: "Set", oneArgF: (*Element).Set}, ++ {name: "Square", oneArgF: (*Element).Square}, ++ {name: "Multiply", twoArgsF: (*Element).Multiply}, ++ {name: "Add", twoArgsF: (*Element).Add}, ++ {name: "Subtract", twoArgsF: (*Element).Subtract}, ++ { ++ name: "Select0", ++ twoArgsF: func(v, x, y *Element) *Element { ++ return (*Element).Select(v, x, y, 0) ++ }, ++ }, ++ { ++ name: "Select1", ++ twoArgsF: func(v, x, y *Element) *Element { ++ return (*Element).Select(v, x, y, 1) ++ }, ++ }, ++ } { ++ var err error ++ switch { ++ case tt.oneArgF != nil: ++ err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8}) ++ case tt.twoArgsF != nil: ++ err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8}) ++ } ++ if err != nil { ++ t.Errorf("%v: %v", tt.name, err) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go +new file mode 100644 +index 00000000000000..edcf163c4ed433 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go +@@ -0,0 +1,16 @@ ++// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++package field ++ ++// feMul sets out = a * b. It works like feMulGeneric. ++// ++//go:noescape ++func feMul(out *Element, a *Element, b *Element) ++ ++// feSquare sets out = a * a. It works like feSquareGeneric. ++// ++//go:noescape ++func feSquare(out *Element, a *Element) +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s +new file mode 100644 +index 00000000000000..293f013c94a66c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s +@@ -0,0 +1,379 @@ ++// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. ++ ++//go:build amd64 && gc && !purego ++// +build amd64,gc,!purego ++ ++#include "textflag.h" ++ ++// func feMul(out *Element, a *Element, b *Element) ++TEXT Β·feMul(SB), NOSPLIT, $0-24 ++ MOVQ a+8(FP), CX ++ MOVQ b+16(FP), BX ++ ++ // r0 = a0Γ—b0 ++ MOVQ (CX), AX ++ MULQ (BX) ++ MOVQ AX, DI ++ MOVQ DX, SI ++ ++ // r0 += 19Γ—a1Γ—b4 ++ MOVQ 8(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 32(BX) ++ ADDQ AX, DI ++ ADCQ DX, SI ++ ++ // r0 += 19Γ—a2Γ—b3 ++ MOVQ 16(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 24(BX) ++ ADDQ AX, DI ++ ADCQ DX, SI ++ ++ // r0 += 19Γ—a3Γ—b2 ++ MOVQ 24(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 16(BX) ++ ADDQ AX, DI ++ ADCQ DX, SI ++ ++ // r0 += 19Γ—a4Γ—b1 ++ MOVQ 32(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 8(BX) ++ ADDQ AX, DI ++ ADCQ DX, SI ++ ++ // r1 = a0Γ—b1 ++ MOVQ (CX), AX ++ MULQ 8(BX) ++ MOVQ AX, R9 ++ MOVQ DX, R8 ++ ++ // r1 += a1Γ—b0 ++ MOVQ 8(CX), AX ++ MULQ (BX) ++ ADDQ AX, R9 ++ ADCQ DX, R8 ++ ++ // r1 += 19Γ—a2Γ—b4 ++ MOVQ 16(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 32(BX) ++ ADDQ AX, R9 ++ ADCQ DX, R8 ++ ++ // r1 += 19Γ—a3Γ—b3 ++ MOVQ 24(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 24(BX) ++ ADDQ AX, R9 ++ ADCQ DX, R8 ++ ++ // r1 += 19Γ—a4Γ—b2 ++ MOVQ 32(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 16(BX) ++ ADDQ AX, R9 ++ ADCQ DX, R8 ++ ++ // r2 = a0Γ—b2 ++ MOVQ (CX), AX ++ MULQ 16(BX) ++ MOVQ AX, R11 ++ MOVQ DX, R10 ++ ++ // r2 += a1Γ—b1 ++ MOVQ 8(CX), AX ++ MULQ 8(BX) ++ ADDQ AX, R11 ++ ADCQ DX, R10 ++ ++ // r2 += a2Γ—b0 ++ MOVQ 16(CX), AX ++ MULQ (BX) ++ ADDQ AX, R11 ++ ADCQ DX, R10 ++ ++ // r2 += 19Γ—a3Γ—b4 ++ MOVQ 24(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 32(BX) ++ ADDQ AX, R11 ++ ADCQ DX, R10 ++ ++ // r2 += 19Γ—a4Γ—b3 ++ MOVQ 32(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 24(BX) ++ ADDQ AX, R11 ++ ADCQ DX, R10 ++ ++ // r3 = a0Γ—b3 ++ MOVQ (CX), AX ++ MULQ 24(BX) ++ MOVQ AX, R13 ++ MOVQ DX, R12 ++ ++ // r3 += a1Γ—b2 ++ MOVQ 8(CX), AX ++ MULQ 16(BX) ++ ADDQ AX, R13 ++ ADCQ DX, R12 ++ ++ // r3 += a2Γ—b1 ++ MOVQ 16(CX), AX ++ MULQ 8(BX) ++ ADDQ AX, R13 ++ ADCQ DX, R12 ++ ++ // r3 += a3Γ—b0 ++ MOVQ 24(CX), AX ++ MULQ (BX) ++ ADDQ AX, R13 ++ ADCQ DX, R12 ++ ++ // r3 += 19Γ—a4Γ—b4 ++ MOVQ 32(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 32(BX) ++ ADDQ AX, R13 ++ ADCQ DX, R12 ++ ++ // r4 = a0Γ—b4 ++ MOVQ (CX), AX ++ MULQ 32(BX) ++ MOVQ AX, R15 ++ MOVQ DX, R14 ++ ++ // r4 += a1Γ—b3 ++ MOVQ 8(CX), AX ++ MULQ 24(BX) ++ ADDQ AX, R15 ++ ADCQ DX, R14 ++ ++ // r4 += a2Γ—b2 ++ MOVQ 16(CX), AX ++ MULQ 16(BX) ++ ADDQ AX, R15 ++ ADCQ DX, R14 ++ ++ // r4 += a3Γ—b1 ++ MOVQ 24(CX), AX ++ MULQ 8(BX) ++ ADDQ AX, R15 ++ ADCQ DX, R14 ++ ++ // r4 += a4Γ—b0 ++ MOVQ 32(CX), AX ++ MULQ (BX) ++ ADDQ AX, R15 ++ ADCQ DX, R14 ++ ++ // First reduction chain ++ MOVQ $0x0007ffffffffffff, AX ++ SHLQ $0x0d, DI, SI ++ SHLQ $0x0d, R9, R8 ++ SHLQ $0x0d, R11, R10 ++ SHLQ $0x0d, R13, R12 ++ SHLQ $0x0d, R15, R14 ++ ANDQ AX, DI ++ IMUL3Q $0x13, R14, R14 ++ ADDQ R14, DI ++ ANDQ AX, R9 ++ ADDQ SI, R9 ++ ANDQ AX, R11 ++ ADDQ R8, R11 ++ ANDQ AX, R13 ++ ADDQ R10, R13 ++ ANDQ AX, R15 ++ ADDQ R12, R15 ++ ++ // Second reduction chain (carryPropagate) ++ MOVQ DI, SI ++ SHRQ $0x33, SI ++ MOVQ R9, R8 ++ SHRQ $0x33, R8 ++ MOVQ R11, R10 ++ SHRQ $0x33, R10 ++ MOVQ R13, R12 ++ SHRQ $0x33, R12 ++ MOVQ R15, R14 ++ SHRQ $0x33, R14 ++ ANDQ AX, DI ++ IMUL3Q $0x13, R14, R14 ++ ADDQ R14, DI ++ ANDQ AX, R9 ++ ADDQ SI, R9 ++ ANDQ AX, R11 ++ ADDQ R8, R11 ++ ANDQ AX, R13 ++ ADDQ R10, R13 ++ ANDQ AX, R15 ++ ADDQ R12, R15 ++ ++ // Store output ++ MOVQ out+0(FP), AX ++ MOVQ DI, (AX) ++ MOVQ R9, 8(AX) ++ MOVQ R11, 16(AX) ++ MOVQ R13, 24(AX) ++ MOVQ R15, 32(AX) ++ RET ++ ++// func feSquare(out *Element, a *Element) ++TEXT Β·feSquare(SB), NOSPLIT, $0-16 ++ MOVQ a+8(FP), CX ++ ++ // r0 = l0Γ—l0 ++ MOVQ (CX), AX ++ MULQ (CX) ++ MOVQ AX, SI ++ MOVQ DX, BX ++ ++ // r0 += 38Γ—l1Γ—l4 ++ MOVQ 8(CX), AX ++ IMUL3Q $0x26, AX, AX ++ MULQ 32(CX) ++ ADDQ AX, SI ++ ADCQ DX, BX ++ ++ // r0 += 38Γ—l2Γ—l3 ++ MOVQ 16(CX), AX ++ IMUL3Q $0x26, AX, AX ++ MULQ 24(CX) ++ ADDQ AX, SI ++ ADCQ DX, BX ++ ++ // r1 = 2Γ—l0Γ—l1 ++ MOVQ (CX), AX ++ SHLQ $0x01, AX ++ MULQ 8(CX) ++ MOVQ AX, R8 ++ MOVQ DX, DI ++ ++ // r1 += 38Γ—l2Γ—l4 ++ MOVQ 16(CX), AX ++ IMUL3Q $0x26, AX, AX ++ MULQ 32(CX) ++ ADDQ AX, R8 ++ ADCQ DX, DI ++ ++ // r1 += 19Γ—l3Γ—l3 ++ MOVQ 24(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 24(CX) ++ ADDQ AX, R8 ++ ADCQ DX, DI ++ ++ // r2 = 2Γ—l0Γ—l2 ++ MOVQ (CX), AX ++ SHLQ $0x01, AX ++ MULQ 16(CX) ++ MOVQ AX, R10 ++ MOVQ DX, R9 ++ ++ // r2 += l1Γ—l1 ++ MOVQ 8(CX), AX ++ MULQ 8(CX) ++ ADDQ AX, R10 ++ ADCQ DX, R9 ++ ++ // r2 += 38Γ—l3Γ—l4 ++ MOVQ 24(CX), AX ++ IMUL3Q $0x26, AX, AX ++ MULQ 32(CX) ++ ADDQ AX, R10 ++ ADCQ DX, R9 ++ ++ // r3 = 2Γ—l0Γ—l3 ++ MOVQ (CX), AX ++ SHLQ $0x01, AX ++ MULQ 24(CX) ++ MOVQ AX, R12 ++ MOVQ DX, R11 ++ ++ // r3 += 2Γ—l1Γ—l2 ++ MOVQ 8(CX), AX ++ IMUL3Q $0x02, AX, AX ++ MULQ 16(CX) ++ ADDQ AX, R12 ++ ADCQ DX, R11 ++ ++ // r3 += 19Γ—l4Γ—l4 ++ MOVQ 32(CX), AX ++ IMUL3Q $0x13, AX, AX ++ MULQ 32(CX) ++ ADDQ AX, R12 ++ ADCQ DX, R11 ++ ++ // r4 = 2Γ—l0Γ—l4 ++ MOVQ (CX), AX ++ SHLQ $0x01, AX ++ MULQ 32(CX) ++ MOVQ AX, R14 ++ MOVQ DX, R13 ++ ++ // r4 += 2Γ—l1Γ—l3 ++ MOVQ 8(CX), AX ++ IMUL3Q $0x02, AX, AX ++ MULQ 24(CX) ++ ADDQ AX, R14 ++ ADCQ DX, R13 ++ ++ // r4 += l2Γ—l2 ++ MOVQ 16(CX), AX ++ MULQ 16(CX) ++ ADDQ AX, R14 ++ ADCQ DX, R13 ++ ++ // First reduction chain ++ MOVQ $0x0007ffffffffffff, AX ++ SHLQ $0x0d, SI, BX ++ SHLQ $0x0d, R8, DI ++ SHLQ $0x0d, R10, R9 ++ SHLQ $0x0d, R12, R11 ++ SHLQ $0x0d, R14, R13 ++ ANDQ AX, SI ++ IMUL3Q $0x13, R13, R13 ++ ADDQ R13, SI ++ ANDQ AX, R8 ++ ADDQ BX, R8 ++ ANDQ AX, R10 ++ ADDQ DI, R10 ++ ANDQ AX, R12 ++ ADDQ R9, R12 ++ ANDQ AX, R14 ++ ADDQ R11, R14 ++ ++ // Second reduction chain (carryPropagate) ++ MOVQ SI, BX ++ SHRQ $0x33, BX ++ MOVQ R8, DI ++ SHRQ $0x33, DI ++ MOVQ R10, R9 ++ SHRQ $0x33, R9 ++ MOVQ R12, R11 ++ SHRQ $0x33, R11 ++ MOVQ R14, R13 ++ SHRQ $0x33, R13 ++ ANDQ AX, SI ++ IMUL3Q $0x13, R13, R13 ++ ADDQ R13, SI ++ ANDQ AX, R8 ++ ADDQ BX, R8 ++ ANDQ AX, R10 ++ ADDQ DI, R10 ++ ANDQ AX, R12 ++ ADDQ R9, R12 ++ ANDQ AX, R14 ++ ADDQ R11, R14 ++ ++ // Store output ++ MOVQ out+0(FP), AX ++ MOVQ SI, (AX) ++ MOVQ R8, 8(AX) ++ MOVQ R10, 16(AX) ++ MOVQ R12, 24(AX) ++ MOVQ R14, 32(AX) ++ RET +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go +new file mode 100644 +index 00000000000000..ddb6c9b8f7f245 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go +@@ -0,0 +1,12 @@ ++// Copyright (c) 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !amd64 || !gc || purego ++// +build !amd64 !gc purego ++ ++package field ++ ++func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } ++ ++func feSquare(v, x *Element) { feSquareGeneric(v, x) } +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go +new file mode 100644 +index 00000000000000..af459ef51549e7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go +@@ -0,0 +1,16 @@ ++// Copyright (c) 2020 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build arm64 && gc && !purego ++// +build arm64,gc,!purego ++ ++package field ++ ++//go:noescape ++func carryPropagate(v *Element) ++ ++func (v *Element) carryPropagate() *Element { ++ carryPropagate(v) ++ return v ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s +new file mode 100644 +index 00000000000000..5c91e458923e32 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s +@@ -0,0 +1,43 @@ ++// Copyright (c) 2020 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build arm64 && gc && !purego ++// +build arm64,gc,!purego ++ ++#include "textflag.h" ++ ++// carryPropagate works exactly like carryPropagateGeneric and uses the ++// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but ++// avoids loading R0-R4 twice and uses LDP and STP. ++// ++// See https://golang.org/issues/43145 for the main compiler issue. ++// ++// func carryPropagate(v *Element) ++TEXT Β·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 ++ MOVD v+0(FP), R20 ++ ++ LDP 0(R20), (R0, R1) ++ LDP 16(R20), (R2, R3) ++ MOVD 32(R20), R4 ++ ++ AND $0x7ffffffffffff, R0, R10 ++ AND $0x7ffffffffffff, R1, R11 ++ AND $0x7ffffffffffff, R2, R12 ++ AND $0x7ffffffffffff, R3, R13 ++ AND $0x7ffffffffffff, R4, R14 ++ ++ ADD R0>>51, R11, R11 ++ ADD R1>>51, R12, R12 ++ ADD R2>>51, R13, R13 ++ ADD R3>>51, R14, R14 ++ // R4>>51 * 19 + R10 -> R10 ++ LSR $51, R4, R21 ++ MOVD $19, R22 ++ MADD R22, R10, R21, R10 ++ ++ STP (R10, R11), 0(R20) ++ STP (R12, R13), 16(R20) ++ MOVD R14, 32(R20) ++ ++ RET +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go +new file mode 100644 +index 00000000000000..234a5b2e5d18ab +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go +@@ -0,0 +1,12 @@ ++// Copyright (c) 2021 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !arm64 || !gc || purego ++// +build !arm64 !gc purego ++ ++package field ++ ++func (v *Element) carryPropagate() *Element { ++ return v.carryPropagateGeneric() ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go +new file mode 100644 +index 00000000000000..77dc06cf9861cb +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go +@@ -0,0 +1,36 @@ ++// Copyright (c) 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package field ++ ++import "testing" ++ ++func BenchmarkAdd(b *testing.B) { ++ var x, y Element ++ x.One() ++ y.Add(feOne, feOne) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ x.Add(&x, &y) ++ } ++} ++ ++func BenchmarkMultiply(b *testing.B) { ++ var x, y Element ++ x.One() ++ y.Add(feOne, feOne) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ x.Multiply(&x, &y) ++ } ++} ++ ++func BenchmarkMult32(b *testing.B) { ++ var x Element ++ x.One() ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ x.Mult32(&x, 0xaa42aa42) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go +new file mode 100644 +index 00000000000000..2671217da597cc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go +@@ -0,0 +1,264 @@ ++// Copyright (c) 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package field ++ ++import "math/bits" ++ ++// uint128 holds a 128-bit number as two 64-bit limbs, for use with the ++// bits.Mul64 and bits.Add64 intrinsics. ++type uint128 struct { ++ lo, hi uint64 ++} ++ ++// mul64 returns a * b. ++func mul64(a, b uint64) uint128 { ++ hi, lo := bits.Mul64(a, b) ++ return uint128{lo, hi} ++} ++ ++// addMul64 returns v + a * b. ++func addMul64(v uint128, a, b uint64) uint128 { ++ hi, lo := bits.Mul64(a, b) ++ lo, c := bits.Add64(lo, v.lo, 0) ++ hi, _ = bits.Add64(hi, v.hi, c) ++ return uint128{lo, hi} ++} ++ ++// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. ++func shiftRightBy51(a uint128) uint64 { ++ return (a.hi << (64 - 51)) | (a.lo >> 51) ++} ++ ++func feMulGeneric(v, a, b *Element) { ++ a0 := a.l0 ++ a1 := a.l1 ++ a2 := a.l2 ++ a3 := a.l3 ++ a4 := a.l4 ++ ++ b0 := b.l0 ++ b1 := b.l1 ++ b2 := b.l2 ++ b3 := b.l3 ++ b4 := b.l4 ++ ++ // Limb multiplication works like pen-and-paper columnar multiplication, but ++ // with 51-bit limbs instead of digits. ++ // ++ // a4 a3 a2 a1 a0 x ++ // b4 b3 b2 b1 b0 = ++ // ------------------------ ++ // a4b0 a3b0 a2b0 a1b0 a0b0 + ++ // a4b1 a3b1 a2b1 a1b1 a0b1 + ++ // a4b2 a3b2 a2b2 a1b2 a0b2 + ++ // a4b3 a3b3 a2b3 a1b3 a0b3 + ++ // a4b4 a3b4 a2b4 a1b4 a0b4 = ++ // ---------------------------------------------- ++ // r8 r7 r6 r5 r4 r3 r2 r1 r0 ++ // ++ // We can then use the reduction identity (a * 2²⁡⁡ + b = a * 19 + b) to ++ // reduce the limbs that would overflow 255 bits. r5 * 2²⁡⁡ becomes 19 * r5, ++ // r6 * 2³⁰⁢ becomes 19 * r6 * 2⁡¹, etc. ++ // ++ // Reduction can be carried out simultaneously to multiplication. For ++ // example, we do not compute r5: whenever the result of a multiplication ++ // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. ++ // ++ // a4b0 a3b0 a2b0 a1b0 a0b0 + ++ // a3b1 a2b1 a1b1 a0b1 19Γ—a4b1 + ++ // a2b2 a1b2 a0b2 19Γ—a4b2 19Γ—a3b2 + ++ // a1b3 a0b3 19Γ—a4b3 19Γ—a3b3 19Γ—a2b3 + ++ // a0b4 19Γ—a4b4 19Γ—a3b4 19Γ—a2b4 19Γ—a1b4 = ++ // -------------------------------------- ++ // r4 r3 r2 r1 r0 ++ // ++ // Finally we add up the columns into wide, overlapping limbs. ++ ++ a1_19 := a1 * 19 ++ a2_19 := a2 * 19 ++ a3_19 := a3 * 19 ++ a4_19 := a4 * 19 ++ ++ // r0 = a0Γ—b0 + 19Γ—(a1Γ—b4 + a2Γ—b3 + a3Γ—b2 + a4Γ—b1) ++ r0 := mul64(a0, b0) ++ r0 = addMul64(r0, a1_19, b4) ++ r0 = addMul64(r0, a2_19, b3) ++ r0 = addMul64(r0, a3_19, b2) ++ r0 = addMul64(r0, a4_19, b1) ++ ++ // r1 = a0Γ—b1 + a1Γ—b0 + 19Γ—(a2Γ—b4 + a3Γ—b3 + a4Γ—b2) ++ r1 := mul64(a0, b1) ++ r1 = addMul64(r1, a1, b0) ++ r1 = addMul64(r1, a2_19, b4) ++ r1 = addMul64(r1, a3_19, b3) ++ r1 = addMul64(r1, a4_19, b2) ++ ++ // r2 = a0Γ—b2 + a1Γ—b1 + a2Γ—b0 + 19Γ—(a3Γ—b4 + a4Γ—b3) ++ r2 := mul64(a0, b2) ++ r2 = addMul64(r2, a1, b1) ++ r2 = addMul64(r2, a2, b0) ++ r2 = addMul64(r2, a3_19, b4) ++ r2 = addMul64(r2, a4_19, b3) ++ ++ // r3 = a0Γ—b3 + a1Γ—b2 + a2Γ—b1 + a3Γ—b0 + 19Γ—a4Γ—b4 ++ r3 := mul64(a0, b3) ++ r3 = addMul64(r3, a1, b2) ++ r3 = addMul64(r3, a2, b1) ++ r3 = addMul64(r3, a3, b0) ++ r3 = addMul64(r3, a4_19, b4) ++ ++ // r4 = a0Γ—b4 + a1Γ—b3 + a2Γ—b2 + a3Γ—b1 + a4Γ—b0 ++ r4 := mul64(a0, b4) ++ r4 = addMul64(r4, a1, b3) ++ r4 = addMul64(r4, a2, b2) ++ r4 = addMul64(r4, a3, b1) ++ r4 = addMul64(r4, a4, b0) ++ ++ // After the multiplication, we need to reduce (carry) the five coefficients ++ // to obtain a result with limbs that are at most slightly larger than 2⁡¹, ++ // to respect the Element invariant. ++ // ++ // Overall, the reduction works the same as carryPropagate, except with ++ // wider inputs: we take the carry for each coefficient by shifting it right ++ // by 51, and add it to the limb above it. The top carry is multiplied by 19 ++ // according to the reduction identity and added to the lowest limb. ++ // ++ // The largest coefficient (r0) will be at most 111 bits, which guarantees ++ // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. ++ // ++ // r0 = a0Γ—b0 + 19Γ—(a1Γ—b4 + a2Γ—b3 + a3Γ—b2 + a4Γ—b1) ++ // r0 < 2⁡²×2⁡² + 19Γ—(2⁡²×2⁡² + 2⁡²×2⁡² + 2⁡²×2⁡² + 2⁡²×2⁡²) ++ // r0 < (1 + 19 Γ— 4) Γ— 2⁡² Γ— 2⁡² ++ // r0 < 2⁷ Γ— 2⁡² Γ— 2⁡² ++ // r0 < 2ΒΉΒΉΒΉ ++ // ++ // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most ++ // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and ++ // allows us to easily apply the reduction identity. ++ // ++ // r4 = a0Γ—b4 + a1Γ—b3 + a2Γ—b2 + a3Γ—b1 + a4Γ—b0 ++ // r4 < 5 Γ— 2⁡² Γ— 2⁡² ++ // r4 < 2¹⁰⁷ ++ // ++ ++ c0 := shiftRightBy51(r0) ++ c1 := shiftRightBy51(r1) ++ c2 := shiftRightBy51(r2) ++ c3 := shiftRightBy51(r3) ++ c4 := shiftRightBy51(r4) ++ ++ rr0 := r0.lo&maskLow51Bits + c4*19 ++ rr1 := r1.lo&maskLow51Bits + c0 ++ rr2 := r2.lo&maskLow51Bits + c1 ++ rr3 := r3.lo&maskLow51Bits + c2 ++ rr4 := r4.lo&maskLow51Bits + c3 ++ ++ // Now all coefficients fit into 64-bit registers but are still too large to ++ // be passed around as a Element. We therefore do one last carry chain, ++ // where the carries will be small enough to fit in the wiggle room above 2⁡¹. ++ *v = Element{rr0, rr1, rr2, rr3, rr4} ++ v.carryPropagate() ++} ++ ++func feSquareGeneric(v, a *Element) { ++ l0 := a.l0 ++ l1 := a.l1 ++ l2 := a.l2 ++ l3 := a.l3 ++ l4 := a.l4 ++ ++ // Squaring works precisely like multiplication above, but thanks to its ++ // symmetry we get to group a few terms together. ++ // ++ // l4 l3 l2 l1 l0 x ++ // l4 l3 l2 l1 l0 = ++ // ------------------------ ++ // l4l0 l3l0 l2l0 l1l0 l0l0 + ++ // l4l1 l3l1 l2l1 l1l1 l0l1 + ++ // l4l2 l3l2 l2l2 l1l2 l0l2 + ++ // l4l3 l3l3 l2l3 l1l3 l0l3 + ++ // l4l4 l3l4 l2l4 l1l4 l0l4 = ++ // ---------------------------------------------- ++ // r8 r7 r6 r5 r4 r3 r2 r1 r0 ++ // ++ // l4l0 l3l0 l2l0 l1l0 l0l0 + ++ // l3l1 l2l1 l1l1 l0l1 19Γ—l4l1 + ++ // l2l2 l1l2 l0l2 19Γ—l4l2 19Γ—l3l2 + ++ // l1l3 l0l3 19Γ—l4l3 19Γ—l3l3 19Γ—l2l3 + ++ // l0l4 19Γ—l4l4 19Γ—l3l4 19Γ—l2l4 19Γ—l1l4 = ++ // -------------------------------------- ++ // r4 r3 r2 r1 r0 ++ // ++ // With precomputed 2Γ—, 19Γ—, and 2Γ—19Γ— terms, we can compute each limb with ++ // only three Mul64 and four Add64, instead of five and eight. ++ ++ l0_2 := l0 * 2 ++ l1_2 := l1 * 2 ++ ++ l1_38 := l1 * 38 ++ l2_38 := l2 * 38 ++ l3_38 := l3 * 38 ++ ++ l3_19 := l3 * 19 ++ l4_19 := l4 * 19 ++ ++ // r0 = l0Γ—l0 + 19Γ—(l1Γ—l4 + l2Γ—l3 + l3Γ—l2 + l4Γ—l1) = l0Γ—l0 + 19Γ—2Γ—(l1Γ—l4 + l2Γ—l3) ++ r0 := mul64(l0, l0) ++ r0 = addMul64(r0, l1_38, l4) ++ r0 = addMul64(r0, l2_38, l3) ++ ++ // r1 = l0Γ—l1 + l1Γ—l0 + 19Γ—(l2Γ—l4 + l3Γ—l3 + l4Γ—l2) = 2Γ—l0Γ—l1 + 19Γ—2Γ—l2Γ—l4 + 19Γ—l3Γ—l3 ++ r1 := mul64(l0_2, l1) ++ r1 = addMul64(r1, l2_38, l4) ++ r1 = addMul64(r1, l3_19, l3) ++ ++ // r2 = l0Γ—l2 + l1Γ—l1 + l2Γ—l0 + 19Γ—(l3Γ—l4 + l4Γ—l3) = 2Γ—l0Γ—l2 + l1Γ—l1 + 19Γ—2Γ—l3Γ—l4 ++ r2 := mul64(l0_2, l2) ++ r2 = addMul64(r2, l1, l1) ++ r2 = addMul64(r2, l3_38, l4) ++ ++ // r3 = l0Γ—l3 + l1Γ—l2 + l2Γ—l1 + l3Γ—l0 + 19Γ—l4Γ—l4 = 2Γ—l0Γ—l3 + 2Γ—l1Γ—l2 + 19Γ—l4Γ—l4 ++ r3 := mul64(l0_2, l3) ++ r3 = addMul64(r3, l1_2, l2) ++ r3 = addMul64(r3, l4_19, l4) ++ ++ // r4 = l0Γ—l4 + l1Γ—l3 + l2Γ—l2 + l3Γ—l1 + l4Γ—l0 = 2Γ—l0Γ—l4 + 2Γ—l1Γ—l3 + l2Γ—l2 ++ r4 := mul64(l0_2, l4) ++ r4 = addMul64(r4, l1_2, l3) ++ r4 = addMul64(r4, l2, l2) ++ ++ c0 := shiftRightBy51(r0) ++ c1 := shiftRightBy51(r1) ++ c2 := shiftRightBy51(r2) ++ c3 := shiftRightBy51(r3) ++ c4 := shiftRightBy51(r4) ++ ++ rr0 := r0.lo&maskLow51Bits + c4*19 ++ rr1 := r1.lo&maskLow51Bits + c0 ++ rr2 := r2.lo&maskLow51Bits + c1 ++ rr3 := r3.lo&maskLow51Bits + c2 ++ rr4 := r4.lo&maskLow51Bits + c3 ++ ++ *v = Element{rr0, rr1, rr2, rr3, rr4} ++ v.carryPropagate() ++} ++ ++// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction ++// identity (a * 2²⁡⁡ + b = a * 19 + b) to the l4 carry. TODO inline ++func (v *Element) carryPropagateGeneric() *Element { ++ c0 := v.l0 >> 51 ++ c1 := v.l1 >> 51 ++ c2 := v.l2 >> 51 ++ c3 := v.l3 >> 51 ++ c4 := v.l4 >> 51 ++ ++ v.l0 = v.l0&maskLow51Bits + c4*19 ++ v.l1 = v.l1&maskLow51Bits + c0 ++ v.l2 = v.l2&maskLow51Bits + c1 ++ v.l3 = v.l3&maskLow51Bits + c2 ++ v.l4 = v.l4&maskLow51Bits + c3 ++ ++ return v ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go +new file mode 100644 +index 00000000000000..b484459ff251f2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go +@@ -0,0 +1,558 @@ ++// Copyright (c) 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package field ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/hex" ++ "io" ++ "math/big" ++ "math/bits" ++ mathrand "math/rand" ++ "reflect" ++ "testing" ++ "testing/quick" ++) ++ ++func (v Element) String() string { ++ return hex.EncodeToString(v.Bytes()) ++} ++ ++// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks) ++// times. The default value of -quickchecks is 100. ++var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10} ++ ++func generateFieldElement(rand *mathrand.Rand) Element { ++ const maskLow52Bits = (1 << 52) - 1 ++ return Element{ ++ rand.Uint64() & maskLow52Bits, ++ rand.Uint64() & maskLow52Bits, ++ rand.Uint64() & maskLow52Bits, ++ rand.Uint64() & maskLow52Bits, ++ rand.Uint64() & maskLow52Bits, ++ } ++} ++ ++// weirdLimbs can be combined to generate a range of edge-case field elements. ++// 0 and -1 are intentionally more weighted, as they combine well. ++var ( ++ weirdLimbs51 = []uint64{ ++ 0, 0, 0, 0, ++ 1, ++ 19 - 1, ++ 19, ++ 0x2aaaaaaaaaaaa, ++ 0x5555555555555, ++ (1 << 51) - 20, ++ (1 << 51) - 19, ++ (1 << 51) - 1, (1 << 51) - 1, ++ (1 << 51) - 1, (1 << 51) - 1, ++ } ++ weirdLimbs52 = []uint64{ ++ 0, 0, 0, 0, 0, 0, ++ 1, ++ 19 - 1, ++ 19, ++ 0x2aaaaaaaaaaaa, ++ 0x5555555555555, ++ (1 << 51) - 20, ++ (1 << 51) - 19, ++ (1 << 51) - 1, (1 << 51) - 1, ++ (1 << 51) - 1, (1 << 51) - 1, ++ (1 << 51) - 1, (1 << 51) - 1, ++ 1 << 51, ++ (1 << 51) + 1, ++ (1 << 52) - 19, ++ (1 << 52) - 1, ++ } ++) ++ ++func generateWeirdFieldElement(rand *mathrand.Rand) Element { ++ return Element{ ++ weirdLimbs52[rand.Intn(len(weirdLimbs52))], ++ weirdLimbs51[rand.Intn(len(weirdLimbs51))], ++ weirdLimbs51[rand.Intn(len(weirdLimbs51))], ++ weirdLimbs51[rand.Intn(len(weirdLimbs51))], ++ weirdLimbs51[rand.Intn(len(weirdLimbs51))], ++ } ++} ++ ++func (Element) Generate(rand *mathrand.Rand, size int) reflect.Value { ++ if rand.Intn(2) == 0 { ++ return reflect.ValueOf(generateWeirdFieldElement(rand)) ++ } ++ return reflect.ValueOf(generateFieldElement(rand)) ++} ++ ++// isInBounds returns whether the element is within the expected bit size bounds ++// after a light reduction. ++func isInBounds(x *Element) bool { ++ return bits.Len64(x.l0) <= 52 && ++ bits.Len64(x.l1) <= 52 && ++ bits.Len64(x.l2) <= 52 && ++ bits.Len64(x.l3) <= 52 && ++ bits.Len64(x.l4) <= 52 ++} ++ ++func TestMultiplyDistributesOverAdd(t *testing.T) { ++ multiplyDistributesOverAdd := func(x, y, z Element) bool { ++ // Compute t1 = (x+y)*z ++ t1 := new(Element) ++ t1.Add(&x, &y) ++ t1.Multiply(t1, &z) ++ ++ // Compute t2 = x*z + y*z ++ t2 := new(Element) ++ t3 := new(Element) ++ t2.Multiply(&x, &z) ++ t3.Multiply(&y, &z) ++ t2.Add(t2, t3) ++ ++ return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) ++ } ++ ++ if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestMul64to128(t *testing.T) { ++ a := uint64(5) ++ b := uint64(5) ++ r := mul64(a, b) ++ if r.lo != 0x19 || r.hi != 0 { ++ t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) ++ } ++ ++ a = uint64(18014398509481983) // 2^54 - 1 ++ b = uint64(18014398509481983) // 2^54 - 1 ++ r = mul64(a, b) ++ if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff { ++ t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) ++ } ++ ++ a = uint64(1125899906842661) ++ b = uint64(2097155) ++ r = mul64(a, b) ++ r = addMul64(r, a, b) ++ r = addMul64(r, a, b) ++ r = addMul64(r, a, b) ++ r = addMul64(r, a, b) ++ if r.lo != 16888498990613035 || r.hi != 640 { ++ t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi) ++ } ++} ++ ++func TestSetBytesRoundTrip(t *testing.T) { ++ f1 := func(in [32]byte, fe Element) bool { ++ fe.SetBytes(in[:]) ++ ++ // Mask the most significant bit as it's ignored by SetBytes. (Now ++ // instead of earlier so we check the masking in SetBytes is working.) ++ in[len(in)-1] &= (1 << 7) - 1 ++ ++ return bytes.Equal(in[:], fe.Bytes()) && isInBounds(&fe) ++ } ++ if err := quick.Check(f1, nil); err != nil { ++ t.Errorf("failed bytes->FE->bytes round-trip: %v", err) ++ } ++ ++ f2 := func(fe, r Element) bool { ++ r.SetBytes(fe.Bytes()) ++ ++ // Intentionally not using Equal not to go through Bytes again. ++ // Calling reduce because both Generate and SetBytes can produce ++ // non-canonical representations. ++ fe.reduce() ++ r.reduce() ++ return fe == r ++ } ++ if err := quick.Check(f2, nil); err != nil { ++ t.Errorf("failed FE->bytes->FE round-trip: %v", err) ++ } ++ ++ // Check some fixed vectors from dalek ++ type feRTTest struct { ++ fe Element ++ b []byte ++ } ++ var tests = []feRTTest{ ++ { ++ fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}, ++ b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31}, ++ }, ++ { ++ fe: Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}, ++ b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122}, ++ }, ++ } ++ ++ for _, tt := range tests { ++ b := tt.fe.Bytes() ++ if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 { ++ t.Errorf("Failed fixed roundtrip: %v", tt) ++ } ++ } ++} ++ ++func swapEndianness(buf []byte) []byte { ++ for i := 0; i < len(buf)/2; i++ { ++ buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i] ++ } ++ return buf ++} ++ ++func TestBytesBigEquivalence(t *testing.T) { ++ f1 := func(in [32]byte, fe, fe1 Element) bool { ++ fe.SetBytes(in[:]) ++ ++ in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit ++ b := new(big.Int).SetBytes(swapEndianness(in[:])) ++ fe1.fromBig(b) ++ ++ if fe != fe1 { ++ return false ++ } ++ ++ buf := make([]byte, 32) // pad with zeroes ++ copy(buf, swapEndianness(fe1.toBig().Bytes())) ++ ++ return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1) ++ } ++ if err := quick.Check(f1, nil); err != nil { ++ t.Error(err) ++ } ++} ++ ++// fromBig sets v = n, and returns v. The bit length of n must not exceed 256. ++func (v *Element) fromBig(n *big.Int) *Element { ++ if n.BitLen() > 32*8 { ++ panic("edwards25519: invalid field element input size") ++ } ++ ++ buf := make([]byte, 0, 32) ++ for _, word := range n.Bits() { ++ for i := 0; i < bits.UintSize; i += 8 { ++ if len(buf) >= cap(buf) { ++ break ++ } ++ buf = append(buf, byte(word)) ++ word >>= 8 ++ } ++ } ++ ++ return v.SetBytes(buf[:32]) ++} ++ ++func (v *Element) fromDecimal(s string) *Element { ++ n, ok := new(big.Int).SetString(s, 10) ++ if !ok { ++ panic("not a valid decimal: " + s) ++ } ++ return v.fromBig(n) ++} ++ ++// toBig returns v as a big.Int. ++func (v *Element) toBig() *big.Int { ++ buf := v.Bytes() ++ ++ words := make([]big.Word, 32*8/bits.UintSize) ++ for n := range words { ++ for i := 0; i < bits.UintSize; i += 8 { ++ if len(buf) == 0 { ++ break ++ } ++ words[n] |= big.Word(buf[0]) << big.Word(i) ++ buf = buf[1:] ++ } ++ } ++ ++ return new(big.Int).SetBits(words) ++} ++ ++func TestDecimalConstants(t *testing.T) { ++ sqrtM1String := "19681161376707505956807079304988542015446066515923890162744021073123829784752" ++ if exp := new(Element).fromDecimal(sqrtM1String); sqrtM1.Equal(exp) != 1 { ++ t.Errorf("sqrtM1 is %v, expected %v", sqrtM1, exp) ++ } ++ // d is in the parent package, and we don't want to expose d or fromDecimal. ++ // dString := "37095705934669439343138083508754565189542113879843219016388785533085940283555" ++ // if exp := new(Element).fromDecimal(dString); d.Equal(exp) != 1 { ++ // t.Errorf("d is %v, expected %v", d, exp) ++ // } ++} ++ ++func TestSetBytesRoundTripEdgeCases(t *testing.T) { ++ // TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1, ++ // and between 2^255 and 2^256-1. Test both the documented SetBytes ++ // behavior, and that Bytes reduces them. ++} ++ ++// Tests self-consistency between Multiply and Square. ++func TestConsistency(t *testing.T) { ++ var x Element ++ var x2, x2sq Element ++ ++ x = Element{1, 1, 1, 1, 1} ++ x2.Multiply(&x, &x) ++ x2sq.Square(&x) ++ ++ if x2 != x2sq { ++ t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) ++ } ++ ++ var bytes [32]byte ++ ++ _, err := io.ReadFull(rand.Reader, bytes[:]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ x.SetBytes(bytes[:]) ++ ++ x2.Multiply(&x, &x) ++ x2sq.Square(&x) ++ ++ if x2 != x2sq { ++ t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) ++ } ++} ++ ++func TestEqual(t *testing.T) { ++ x := Element{1, 1, 1, 1, 1} ++ y := Element{5, 4, 3, 2, 1} ++ ++ eq := x.Equal(&x) ++ if eq != 1 { ++ t.Errorf("wrong about equality") ++ } ++ ++ eq = x.Equal(&y) ++ if eq != 0 { ++ t.Errorf("wrong about inequality") ++ } ++} ++ ++func TestInvert(t *testing.T) { ++ x := Element{1, 1, 1, 1, 1} ++ one := Element{1, 0, 0, 0, 0} ++ var xinv, r Element ++ ++ xinv.Invert(&x) ++ r.Multiply(&x, &xinv) ++ r.reduce() ++ ++ if one != r { ++ t.Errorf("inversion identity failed, got: %x", r) ++ } ++ ++ var bytes [32]byte ++ ++ _, err := io.ReadFull(rand.Reader, bytes[:]) ++ if err != nil { ++ t.Fatal(err) ++ } ++ x.SetBytes(bytes[:]) ++ ++ xinv.Invert(&x) ++ r.Multiply(&x, &xinv) ++ r.reduce() ++ ++ if one != r { ++ t.Errorf("random inversion identity failed, got: %x for field element %x", r, x) ++ } ++ ++ zero := Element{} ++ x.Set(&zero) ++ if xx := xinv.Invert(&x); xx != &xinv { ++ t.Errorf("inverting zero did not return the receiver") ++ } else if xinv.Equal(&zero) != 1 { ++ t.Errorf("inverting zero did not return zero") ++ } ++} ++ ++func TestSelectSwap(t *testing.T) { ++ a := Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676} ++ b := Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972} ++ ++ var c, d Element ++ ++ c.Select(&a, &b, 1) ++ d.Select(&a, &b, 0) ++ ++ if c.Equal(&a) != 1 || d.Equal(&b) != 1 { ++ t.Errorf("Select failed") ++ } ++ ++ c.Swap(&d, 0) ++ ++ if c.Equal(&a) != 1 || d.Equal(&b) != 1 { ++ t.Errorf("Swap failed") ++ } ++ ++ c.Swap(&d, 1) ++ ++ if c.Equal(&b) != 1 || d.Equal(&a) != 1 { ++ t.Errorf("Swap failed") ++ } ++} ++ ++func TestMult32(t *testing.T) { ++ mult32EquivalentToMul := func(x Element, y uint32) bool { ++ t1 := new(Element) ++ for i := 0; i < 100; i++ { ++ t1.Mult32(&x, y) ++ } ++ ++ ty := new(Element) ++ ty.l0 = uint64(y) ++ ++ t2 := new(Element) ++ for i := 0; i < 100; i++ { ++ t2.Multiply(&x, ty) ++ } ++ ++ return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) ++ } ++ ++ if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestSqrtRatio(t *testing.T) { ++ // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4. ++ type test struct { ++ u, v string ++ wasSquare int ++ r string ++ } ++ var tests = []test{ ++ // If u is 0, the function is defined to return (0, TRUE), even if v ++ // is zero. Note that where used in this package, the denominator v ++ // is never zero. ++ { ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ 1, "0000000000000000000000000000000000000000000000000000000000000000", ++ }, ++ // 0/1 == 0Β² ++ { ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ "0100000000000000000000000000000000000000000000000000000000000000", ++ 1, "0000000000000000000000000000000000000000000000000000000000000000", ++ }, ++ // If u is non-zero and v is zero, defined to return (0, FALSE). ++ { ++ "0100000000000000000000000000000000000000000000000000000000000000", ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ 0, "0000000000000000000000000000000000000000000000000000000000000000", ++ }, ++ // 2/1 is not square in this field. ++ { ++ "0200000000000000000000000000000000000000000000000000000000000000", ++ "0100000000000000000000000000000000000000000000000000000000000000", ++ 0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54", ++ }, ++ // 4/1 == 2Β² ++ { ++ "0400000000000000000000000000000000000000000000000000000000000000", ++ "0100000000000000000000000000000000000000000000000000000000000000", ++ 1, "0200000000000000000000000000000000000000000000000000000000000000", ++ }, ++ // 1/4 == (2⁻¹)Β² == (2^(p-2))Β² per Euler's theorem ++ { ++ "0100000000000000000000000000000000000000000000000000000000000000", ++ "0400000000000000000000000000000000000000000000000000000000000000", ++ 1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f", ++ }, ++ } ++ ++ for i, tt := range tests { ++ u := new(Element).SetBytes(decodeHex(tt.u)) ++ v := new(Element).SetBytes(decodeHex(tt.v)) ++ want := new(Element).SetBytes(decodeHex(tt.r)) ++ got, wasSquare := new(Element).SqrtRatio(u, v) ++ if got.Equal(want) == 0 || wasSquare != tt.wasSquare { ++ t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare) ++ } ++ } ++} ++ ++func TestCarryPropagate(t *testing.T) { ++ asmLikeGeneric := func(a [5]uint64) bool { ++ t1 := &Element{a[0], a[1], a[2], a[3], a[4]} ++ t2 := &Element{a[0], a[1], a[2], a[3], a[4]} ++ ++ t1.carryPropagate() ++ t2.carryPropagateGeneric() ++ ++ if *t1 != *t2 { ++ t.Logf("got: %#v,\nexpected: %#v", t1, t2) ++ } ++ ++ return *t1 == *t2 && isInBounds(t2) ++ } ++ ++ if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { ++ t.Error(err) ++ } ++ ++ if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) { ++ t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}") ++ } ++} ++ ++func TestFeSquare(t *testing.T) { ++ asmLikeGeneric := func(a Element) bool { ++ t1 := a ++ t2 := a ++ ++ feSquareGeneric(&t1, &t1) ++ feSquare(&t2, &t2) ++ ++ if t1 != t2 { ++ t.Logf("got: %#v,\nexpected: %#v", t1, t2) ++ } ++ ++ return t1 == t2 && isInBounds(&t2) ++ } ++ ++ if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestFeMul(t *testing.T) { ++ asmLikeGeneric := func(a, b Element) bool { ++ a1 := a ++ a2 := a ++ b1 := b ++ b2 := b ++ ++ feMulGeneric(&a1, &a1, &b1) ++ feMul(&a2, &a2, &b2) ++ ++ if a1 != a2 || b1 != b2 { ++ t.Logf("got: %#v,\nexpected: %#v", a1, a2) ++ t.Logf("got: %#v,\nexpected: %#v", b1, b2) ++ } ++ ++ return a1 == a2 && isInBounds(&a2) && ++ b1 == b2 && isInBounds(&b2) ++ } ++ ++ if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { ++ t.Error(err) ++ } ++} ++ ++func decodeHex(s string) []byte { ++ b, err := hex.DecodeString(s) ++ if err != nil { ++ panic(err) ++ } ++ return b ++} +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint +new file mode 100644 +index 00000000000000..e3685f95cab22f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint +@@ -0,0 +1 @@ ++b0c49ae9f59d233526f8934262c5bbbe14d4358d +diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh +new file mode 100644 +index 00000000000000..1ba22a8b4c9a28 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh +@@ -0,0 +1,19 @@ ++#! /bin/bash ++set -euo pipefail ++ ++cd "$(git rev-parse --show-toplevel)" ++ ++STD_PATH=src/crypto/ed25519/internal/edwards25519/field ++LOCAL_PATH=curve25519/internal/field ++LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint) ++ ++git fetch https://go.googlesource.com/go master ++ ++if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then ++ echo "No changes." ++else ++ NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint) ++ echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..." ++ git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \ ++ git apply -3 --directory=$LOCAL_PATH ++fi +diff --git a/ms_mod/golang.org/x/crypto/curve25519/vectors_test.go b/ms_mod/golang.org/x/crypto/curve25519/vectors_test.go +new file mode 100644 +index 00000000000000..f4c0a1414f0cea +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/curve25519/vectors_test.go +@@ -0,0 +1,105 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package curve25519_test ++ ++// lowOrderPoints from libsodium. ++// https://github.com/jedisct1/libsodium/blob/65621a1059a37d/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L11-L70 ++var lowOrderPoints = [][]byte{ ++ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ {0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00}, ++ {0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57}, ++ {0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, ++ {0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, ++ {0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, ++} ++ ++// testVectors generated with BoringSSL. ++var testVectors = []struct { ++ In [32]byte ++ Base [32]byte ++ Expect [32]byte ++}{ ++ { ++ In: [32]byte{0x66, 0x8f, 0xb9, 0xf7, 0x6a, 0xd9, 0x71, 0xc8, 0x1a, 0xc9, 0x0, 0x7, 0x1a, 0x15, 0x60, 0xbc, 0xe2, 0xca, 0x0, 0xca, 0xc7, 0xe6, 0x7a, 0xf9, 0x93, 0x48, 0x91, 0x37, 0x61, 0x43, 0x40, 0x14}, ++ Base: [32]byte{0xdb, 0x5f, 0x32, 0xb7, 0xf8, 0x41, 0xe7, 0xa1, 0xa0, 0x9, 0x68, 0xef, 0xfd, 0xed, 0x12, 0x73, 0x5f, 0xc4, 0x7a, 0x3e, 0xb1, 0x3b, 0x57, 0x9a, 0xac, 0xad, 0xea, 0xe8, 0x9, 0x39, 0xa7, 0xdd}, ++ Expect: [32]byte{0x9, 0xd, 0x85, 0xe5, 0x99, 0xea, 0x8e, 0x2b, 0xee, 0xb6, 0x13, 0x4, 0xd3, 0x7b, 0xe1, 0xe, 0xc5, 0xc9, 0x5, 0xf9, 0x92, 0x7d, 0x32, 0xf4, 0x2a, 0x9a, 0xa, 0xfb, 0x3e, 0xb, 0x40, 0x74}, ++ }, ++ { ++ In: [32]byte{0x63, 0x66, 0x95, 0xe3, 0x4f, 0x75, 0xb9, 0xa2, 0x79, 0xc8, 0x70, 0x6f, 0xad, 0x12, 0x89, 0xf2, 0xc0, 0xb1, 0xe2, 0x2e, 0x16, 0xf8, 0xb8, 0x86, 0x17, 0x29, 0xc1, 0xa, 0x58, 0x29, 0x58, 0xaf}, ++ Base: [32]byte{0x9, 0xd, 0x7, 0x1, 0xf8, 0xfd, 0xe2, 0x8f, 0x70, 0x4, 0x3b, 0x83, 0xf2, 0x34, 0x62, 0x25, 0x41, 0x9b, 0x18, 0xa7, 0xf2, 0x7e, 0x9e, 0x3d, 0x2b, 0xfd, 0x4, 0xe1, 0xf, 0x3d, 0x21, 0x3e}, ++ Expect: [32]byte{0xbf, 0x26, 0xec, 0x7e, 0xc4, 0x13, 0x6, 0x17, 0x33, 0xd4, 0x40, 0x70, 0xea, 0x67, 0xca, 0xb0, 0x2a, 0x85, 0xdc, 0x1b, 0xe8, 0xcf, 0xe1, 0xff, 0x73, 0xd5, 0x41, 0xcc, 0x8, 0x32, 0x55, 0x6}, ++ }, ++ { ++ In: [32]byte{0x73, 0x41, 0x81, 0xcd, 0x1a, 0x94, 0x6, 0x52, 0x2a, 0x56, 0xfe, 0x25, 0xe4, 0x3e, 0xcb, 0xf0, 0x29, 0x5d, 0xb5, 0xdd, 0xd0, 0x60, 0x9b, 0x3c, 0x2b, 0x4e, 0x79, 0xc0, 0x6f, 0x8b, 0xd4, 0x6d}, ++ Base: [32]byte{0xf8, 0xa8, 0x42, 0x1c, 0x7d, 0x21, 0xa9, 0x2d, 0xb3, 0xed, 0xe9, 0x79, 0xe1, 0xfa, 0x6a, 0xcb, 0x6, 0x2b, 0x56, 0xb1, 0x88, 0x5c, 0x71, 0xc5, 0x11, 0x53, 0xcc, 0xb8, 0x80, 0xac, 0x73, 0x15}, ++ Expect: [32]byte{0x11, 0x76, 0xd0, 0x16, 0x81, 0xf2, 0xcf, 0x92, 0x9d, 0xa2, 0xc7, 0xa3, 0xdf, 0x66, 0xb5, 0xd7, 0x72, 0x9f, 0xd4, 0x22, 0x22, 0x6f, 0xd6, 0x37, 0x42, 0x16, 0xbf, 0x7e, 0x2, 0xfd, 0xf, 0x62}, ++ }, ++ { ++ In: [32]byte{0x1f, 0x70, 0x39, 0x1f, 0x6b, 0xa8, 0x58, 0x12, 0x94, 0x13, 0xbd, 0x80, 0x1b, 0x12, 0xac, 0xbf, 0x66, 0x23, 0x62, 0x82, 0x5c, 0xa2, 0x50, 0x9c, 0x81, 0x87, 0x59, 0xa, 0x2b, 0xe, 0x61, 0x72}, ++ Base: [32]byte{0xd3, 0xea, 0xd0, 0x7a, 0x0, 0x8, 0xf4, 0x45, 0x2, 0xd5, 0x80, 0x8b, 0xff, 0xc8, 0x97, 0x9f, 0x25, 0xa8, 0x59, 0xd5, 0xad, 0xf4, 0x31, 0x2e, 0xa4, 0x87, 0x48, 0x9c, 0x30, 0xe0, 0x1b, 0x3b}, ++ Expect: [32]byte{0xf8, 0x48, 0x2f, 0x2e, 0x9e, 0x58, 0xbb, 0x6, 0x7e, 0x86, 0xb2, 0x87, 0x24, 0xb3, 0xc0, 0xa3, 0xbb, 0xb5, 0x7, 0x3e, 0x4c, 0x6a, 0xcd, 0x93, 0xdf, 0x54, 0x5e, 0xff, 0xdb, 0xba, 0x50, 0x5f}, ++ }, ++ { ++ In: [32]byte{0x3a, 0x7a, 0xe6, 0xcf, 0x8b, 0x88, 0x9d, 0x2b, 0x7a, 0x60, 0xa4, 0x70, 0xad, 0x6a, 0xd9, 0x99, 0x20, 0x6b, 0xf5, 0x7d, 0x90, 0x30, 0xdd, 0xf7, 0xf8, 0x68, 0xc, 0x8b, 0x1a, 0x64, 0x5d, 0xaa}, ++ Base: [32]byte{0x4d, 0x25, 0x4c, 0x80, 0x83, 0xd8, 0x7f, 0x1a, 0x9b, 0x3e, 0xa7, 0x31, 0xef, 0xcf, 0xf8, 0xa6, 0xf2, 0x31, 0x2d, 0x6f, 0xed, 0x68, 0xe, 0xf8, 0x29, 0x18, 0x51, 0x61, 0xc8, 0xfc, 0x50, 0x60}, ++ Expect: [32]byte{0x47, 0xb3, 0x56, 0xd5, 0x81, 0x8d, 0xe8, 0xef, 0xac, 0x77, 0x4b, 0x71, 0x4c, 0x42, 0xc4, 0x4b, 0xe6, 0x85, 0x23, 0xdd, 0x57, 0xdb, 0xd7, 0x39, 0x62, 0xd5, 0xa5, 0x26, 0x31, 0x87, 0x62, 0x37}, ++ }, ++ { ++ In: [32]byte{0x20, 0x31, 0x61, 0xc3, 0x15, 0x9a, 0x87, 0x6a, 0x2b, 0xea, 0xec, 0x29, 0xd2, 0x42, 0x7f, 0xb0, 0xc7, 0xc3, 0xd, 0x38, 0x2c, 0xd0, 0x13, 0xd2, 0x7c, 0xc3, 0xd3, 0x93, 0xdb, 0xd, 0xaf, 0x6f}, ++ Base: [32]byte{0x6a, 0xb9, 0x5d, 0x1a, 0xbe, 0x68, 0xc0, 0x9b, 0x0, 0x5c, 0x3d, 0xb9, 0x4, 0x2c, 0xc9, 0x1a, 0xc8, 0x49, 0xf7, 0xe9, 0x4a, 0x2a, 0x4a, 0x9b, 0x89, 0x36, 0x78, 0x97, 0xb, 0x7b, 0x95, 0xbf}, ++ Expect: [32]byte{0x11, 0xed, 0xae, 0xdc, 0x95, 0xff, 0x78, 0xf5, 0x63, 0xa1, 0xc8, 0xf1, 0x55, 0x91, 0xc0, 0x71, 0xde, 0xa0, 0x92, 0xb4, 0xd7, 0xec, 0xaa, 0xc8, 0xe0, 0x38, 0x7b, 0x5a, 0x16, 0xc, 0x4e, 0x5d}, ++ }, ++ { ++ In: [32]byte{0x13, 0xd6, 0x54, 0x91, 0xfe, 0x75, 0xf2, 0x3, 0xa0, 0x8, 0xb4, 0x41, 0x5a, 0xbc, 0x60, 0xd5, 0x32, 0xe6, 0x95, 0xdb, 0xd2, 0xf1, 0xe8, 0x3, 0xac, 0xcb, 0x34, 0xb2, 0xb7, 0x2c, 0x3d, 0x70}, ++ Base: [32]byte{0x2e, 0x78, 0x4e, 0x4, 0xca, 0x0, 0x73, 0x33, 0x62, 0x56, 0xa8, 0x39, 0x25, 0x5e, 0xd2, 0xf7, 0xd4, 0x79, 0x6a, 0x64, 0xcd, 0xc3, 0x7f, 0x1e, 0xb0, 0xe5, 0xc4, 0xc8, 0xd1, 0xd1, 0xe0, 0xf5}, ++ Expect: [32]byte{0x56, 0x3e, 0x8c, 0x9a, 0xda, 0xa7, 0xd7, 0x31, 0x1, 0xb0, 0xf2, 0xea, 0xd3, 0xca, 0xe1, 0xea, 0x5d, 0x8f, 0xcd, 0x5c, 0xd3, 0x60, 0x80, 0xbb, 0x8e, 0x6e, 0xc0, 0x3d, 0x61, 0x45, 0x9, 0x17}, ++ }, ++ { ++ In: [32]byte{0x68, 0x6f, 0x7d, 0xa9, 0x3b, 0xf2, 0x68, 0xe5, 0x88, 0x6, 0x98, 0x31, 0xf0, 0x47, 0x16, 0x3f, 0x33, 0x58, 0x99, 0x89, 0xd0, 0x82, 0x6e, 0x98, 0x8, 0xfb, 0x67, 0x8e, 0xd5, 0x7e, 0x67, 0x49}, ++ Base: [32]byte{0x8b, 0x54, 0x9b, 0x2d, 0xf6, 0x42, 0xd3, 0xb2, 0x5f, 0xe8, 0x38, 0xf, 0x8c, 0xc4, 0x37, 0x5f, 0x99, 0xb7, 0xbb, 0x4d, 0x27, 0x5f, 0x77, 0x9f, 0x3b, 0x7c, 0x81, 0xb8, 0xa2, 0xbb, 0xc1, 0x29}, ++ Expect: [32]byte{0x1, 0x47, 0x69, 0x65, 0x42, 0x6b, 0x61, 0x71, 0x74, 0x9a, 0x8a, 0xdd, 0x92, 0x35, 0x2, 0x5c, 0xe5, 0xf5, 0x57, 0xfe, 0x40, 0x9, 0xf7, 0x39, 0x30, 0x44, 0xeb, 0xbb, 0x8a, 0xe9, 0x52, 0x79}, ++ }, ++ { ++ In: [32]byte{0x82, 0xd6, 0x1c, 0xce, 0xdc, 0x80, 0x6a, 0x60, 0x60, 0xa3, 0x34, 0x9a, 0x5e, 0x87, 0xcb, 0xc7, 0xac, 0x11, 0x5e, 0x4f, 0x87, 0x77, 0x62, 0x50, 0xae, 0x25, 0x60, 0x98, 0xa7, 0xc4, 0x49, 0x59}, ++ Base: [32]byte{0x8b, 0x6b, 0x9d, 0x8, 0xf6, 0x1f, 0xc9, 0x1f, 0xe8, 0xb3, 0x29, 0x53, 0xc4, 0x23, 0x40, 0xf0, 0x7, 0xb5, 0x71, 0xdc, 0xb0, 0xa5, 0x6d, 0x10, 0x72, 0x4e, 0xce, 0xf9, 0x95, 0xc, 0xfb, 0x25}, ++ Expect: [32]byte{0x9c, 0x49, 0x94, 0x1f, 0x9c, 0x4f, 0x18, 0x71, 0xfa, 0x40, 0x91, 0xfe, 0xd7, 0x16, 0xd3, 0x49, 0x99, 0xc9, 0x52, 0x34, 0xed, 0xf2, 0xfd, 0xfb, 0xa6, 0xd1, 0x4a, 0x5a, 0xfe, 0x9e, 0x5, 0x58}, ++ }, ++ { ++ In: [32]byte{0x7d, 0xc7, 0x64, 0x4, 0x83, 0x13, 0x97, 0xd5, 0x88, 0x4f, 0xdf, 0x6f, 0x97, 0xe1, 0x74, 0x4c, 0x9e, 0xb1, 0x18, 0xa3, 0x1a, 0x7b, 0x23, 0xf8, 0xd7, 0x9f, 0x48, 0xce, 0x9c, 0xad, 0x15, 0x4b}, ++ Base: [32]byte{0x1a, 0xcd, 0x29, 0x27, 0x84, 0xf4, 0x79, 0x19, 0xd4, 0x55, 0xf8, 0x87, 0x44, 0x83, 0x58, 0x61, 0xb, 0xb9, 0x45, 0x96, 0x70, 0xeb, 0x99, 0xde, 0xe4, 0x60, 0x5, 0xf6, 0x89, 0xca, 0x5f, 0xb6}, ++ Expect: [32]byte{0x0, 0xf4, 0x3c, 0x2, 0x2e, 0x94, 0xea, 0x38, 0x19, 0xb0, 0x36, 0xae, 0x2b, 0x36, 0xb2, 0xa7, 0x61, 0x36, 0xaf, 0x62, 0x8a, 0x75, 0x1f, 0xe5, 0xd0, 0x1e, 0x3, 0xd, 0x44, 0x25, 0x88, 0x59}, ++ }, ++ { ++ In: [32]byte{0xfb, 0xc4, 0x51, 0x1d, 0x23, 0xa6, 0x82, 0xae, 0x4e, 0xfd, 0x8, 0xc8, 0x17, 0x9c, 0x1c, 0x6, 0x7f, 0x9c, 0x8b, 0xe7, 0x9b, 0xbc, 0x4e, 0xff, 0x5c, 0xe2, 0x96, 0xc6, 0xbc, 0x1f, 0xf4, 0x45}, ++ Base: [32]byte{0x55, 0xca, 0xff, 0x21, 0x81, 0xf2, 0x13, 0x6b, 0xe, 0xd0, 0xe1, 0xe2, 0x99, 0x44, 0x48, 0xe1, 0x6c, 0xc9, 0x70, 0x64, 0x6a, 0x98, 0x3d, 0x14, 0xd, 0xc4, 0xea, 0xb3, 0xd9, 0x4c, 0x28, 0x4e}, ++ Expect: [32]byte{0xae, 0x39, 0xd8, 0x16, 0x53, 0x23, 0x45, 0x79, 0x4d, 0x26, 0x91, 0xe0, 0x80, 0x1c, 0xaa, 0x52, 0x5f, 0xc3, 0x63, 0x4d, 0x40, 0x2c, 0xe9, 0x58, 0xb, 0x33, 0x38, 0xb4, 0x6f, 0x8b, 0xb9, 0x72}, ++ }, ++ { ++ In: [32]byte{0x4e, 0x6, 0xc, 0xe1, 0xc, 0xeb, 0xf0, 0x95, 0x9, 0x87, 0x16, 0xc8, 0x66, 0x19, 0xeb, 0x9f, 0x7d, 0xf6, 0x65, 0x24, 0x69, 0x8b, 0xa7, 0x98, 0x8c, 0x3b, 0x90, 0x95, 0xd9, 0xf5, 0x1, 0x34}, ++ Base: [32]byte{0x57, 0x73, 0x3f, 0x2d, 0x86, 0x96, 0x90, 0xd0, 0xd2, 0xed, 0xae, 0xc9, 0x52, 0x3d, 0xaa, 0x2d, 0xa9, 0x54, 0x45, 0xf4, 0x4f, 0x57, 0x83, 0xc1, 0xfa, 0xec, 0x6c, 0x3a, 0x98, 0x28, 0x18, 0xf3}, ++ Expect: [32]byte{0xa6, 0x1e, 0x74, 0x55, 0x2c, 0xce, 0x75, 0xf5, 0xe9, 0x72, 0xe4, 0x24, 0xf2, 0xcc, 0xb0, 0x9c, 0x83, 0xbc, 0x1b, 0x67, 0x1, 0x47, 0x48, 0xf0, 0x2c, 0x37, 0x1a, 0x20, 0x9e, 0xf2, 0xfb, 0x2c}, ++ }, ++ { ++ In: [32]byte{0x5c, 0x49, 0x2c, 0xba, 0x2c, 0xc8, 0x92, 0x48, 0x8a, 0x9c, 0xeb, 0x91, 0x86, 0xc2, 0xaa, 0xc2, 0x2f, 0x1, 0x5b, 0xf3, 0xef, 0x8d, 0x3e, 0xcc, 0x9c, 0x41, 0x76, 0x97, 0x62, 0x61, 0xaa, 0xb1}, ++ Base: [32]byte{0x67, 0x97, 0xc2, 0xe7, 0xdc, 0x92, 0xcc, 0xbe, 0x7c, 0x5, 0x6b, 0xec, 0x35, 0xa, 0xb6, 0xd3, 0xbd, 0x2a, 0x2c, 0x6b, 0xc5, 0xa8, 0x7, 0xbb, 0xca, 0xe1, 0xf6, 0xc2, 0xaf, 0x80, 0x36, 0x44}, ++ Expect: [32]byte{0xfc, 0xf3, 0x7, 0xdf, 0xbc, 0x19, 0x2, 0xb, 0x28, 0xa6, 0x61, 0x8c, 0x6c, 0x62, 0x2f, 0x31, 0x7e, 0x45, 0x96, 0x7d, 0xac, 0xf4, 0xae, 0x4a, 0xa, 0x69, 0x9a, 0x10, 0x76, 0x9f, 0xde, 0x14}, ++ }, ++ { ++ In: [32]byte{0xea, 0x33, 0x34, 0x92, 0x96, 0x5, 0x5a, 0x4e, 0x8b, 0x19, 0x2e, 0x3c, 0x23, 0xc5, 0xf4, 0xc8, 0x44, 0x28, 0x2a, 0x3b, 0xfc, 0x19, 0xec, 0xc9, 0xdc, 0x64, 0x6a, 0x42, 0xc3, 0x8d, 0xc2, 0x48}, ++ Base: [32]byte{0x2c, 0x75, 0xd8, 0x51, 0x42, 0xec, 0xad, 0x3e, 0x69, 0x44, 0x70, 0x4, 0x54, 0xc, 0x1c, 0x23, 0x54, 0x8f, 0xc8, 0xf4, 0x86, 0x25, 0x1b, 0x8a, 0x19, 0x46, 0x3f, 0x3d, 0xf6, 0xf8, 0xac, 0x61}, ++ Expect: [32]byte{0x5d, 0xca, 0xb6, 0x89, 0x73, 0xf9, 0x5b, 0xd3, 0xae, 0x4b, 0x34, 0xfa, 0xb9, 0x49, 0xfb, 0x7f, 0xb1, 0x5a, 0xf1, 0xd8, 0xca, 0xe2, 0x8c, 0xd6, 0x99, 0xf9, 0xc1, 0xaa, 0x33, 0x37, 0x34, 0x2f}, ++ }, ++ { ++ In: [32]byte{0x4f, 0x29, 0x79, 0xb1, 0xec, 0x86, 0x19, 0xe4, 0x5c, 0xa, 0xb, 0x2b, 0x52, 0x9, 0x34, 0x54, 0x1a, 0xb9, 0x44, 0x7, 0xb6, 0x4d, 0x19, 0xa, 0x76, 0xf3, 0x23, 0x14, 0xef, 0xe1, 0x84, 0xe7}, ++ Base: [32]byte{0xf7, 0xca, 0xe1, 0x8d, 0x8d, 0x36, 0xa7, 0xf5, 0x61, 0x17, 0xb8, 0xb7, 0xe, 0x25, 0x52, 0x27, 0x7f, 0xfc, 0x99, 0xdf, 0x87, 0x56, 0xb5, 0xe1, 0x38, 0xbf, 0x63, 0x68, 0xbc, 0x87, 0xf7, 0x4c}, ++ Expect: [32]byte{0xe4, 0xe6, 0x34, 0xeb, 0xb4, 0xfb, 0x66, 0x4f, 0xe8, 0xb2, 0xcf, 0xa1, 0x61, 0x5f, 0x0, 0xe6, 0x46, 0x6f, 0xff, 0x73, 0x2c, 0xe1, 0xf8, 0xa0, 0xc8, 0xd2, 0x72, 0x74, 0x31, 0xd1, 0x6f, 0x14}, ++ }, ++ { ++ In: [32]byte{0xf5, 0xd8, 0xa9, 0x27, 0x90, 0x1d, 0x4f, 0xa4, 0x24, 0x90, 0x86, 0xb7, 0xff, 0xec, 0x24, 0xf5, 0x29, 0x7d, 0x80, 0x11, 0x8e, 0x4a, 0xc9, 0xd3, 0xfc, 0x9a, 0x82, 0x37, 0x95, 0x1e, 0x3b, 0x7f}, ++ Base: [32]byte{0x3c, 0x23, 0x5e, 0xdc, 0x2, 0xf9, 0x11, 0x56, 0x41, 0xdb, 0xf5, 0x16, 0xd5, 0xde, 0x8a, 0x73, 0x5d, 0x6e, 0x53, 0xe2, 0x2a, 0xa2, 0xac, 0x14, 0x36, 0x56, 0x4, 0x5f, 0xf2, 0xe9, 0x52, 0x49}, ++ Expect: [32]byte{0xab, 0x95, 0x15, 0xab, 0x14, 0xaf, 0x9d, 0x27, 0xe, 0x1d, 0xae, 0xc, 0x56, 0x80, 0xcb, 0xc8, 0x88, 0xb, 0xd8, 0xa8, 0xe7, 0xeb, 0x67, 0xb4, 0xda, 0x42, 0xa6, 0x61, 0x96, 0x1e, 0xfc, 0xb}, ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/ed25519/ed25519.go b/ms_mod/golang.org/x/crypto/ed25519/ed25519.go +new file mode 100644 +index 00000000000000..a7828345fcc431 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ed25519/ed25519.go +@@ -0,0 +1,71 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package ed25519 implements the Ed25519 signature algorithm. See ++// https://ed25519.cr.yp.to/. ++// ++// These functions are also compatible with the β€œEd25519” function defined in ++// RFC 8032. However, unlike RFC 8032's formulation, this package's private key ++// representation includes a public key suffix to make multiple signing ++// operations with the same key more efficient. This package refers to the RFC ++// 8032 private key as the β€œseed”. ++// ++// Beginning with Go 1.13, the functionality of this package was moved to the ++// standard library as crypto/ed25519. This package only acts as a compatibility ++// wrapper. ++package ed25519 ++ ++import ( ++ "crypto/ed25519" ++ "io" ++) ++ ++const ( ++ // PublicKeySize is the size, in bytes, of public keys as used in this package. ++ PublicKeySize = 32 ++ // PrivateKeySize is the size, in bytes, of private keys as used in this package. ++ PrivateKeySize = 64 ++ // SignatureSize is the size, in bytes, of signatures generated and verified by this package. ++ SignatureSize = 64 ++ // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. ++ SeedSize = 32 ++) ++ ++// PublicKey is the type of Ed25519 public keys. ++// ++// This type is an alias for crypto/ed25519's PublicKey type. ++// See the crypto/ed25519 package for the methods on this type. ++type PublicKey = ed25519.PublicKey ++ ++// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. ++// ++// This type is an alias for crypto/ed25519's PrivateKey type. ++// See the crypto/ed25519 package for the methods on this type. ++type PrivateKey = ed25519.PrivateKey ++ ++// GenerateKey generates a public/private key pair using entropy from rand. ++// If rand is nil, crypto/rand.Reader will be used. ++func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { ++ return ed25519.GenerateKey(rand) ++} ++ ++// NewKeyFromSeed calculates a private key from a seed. It will panic if ++// len(seed) is not SeedSize. This function is provided for interoperability ++// with RFC 8032. RFC 8032's private keys correspond to seeds in this ++// package. ++func NewKeyFromSeed(seed []byte) PrivateKey { ++ return ed25519.NewKeyFromSeed(seed) ++} ++ ++// Sign signs the message with privateKey and returns a signature. It will ++// panic if len(privateKey) is not PrivateKeySize. ++func Sign(privateKey PrivateKey, message []byte) []byte { ++ return ed25519.Sign(privateKey, message) ++} ++ ++// Verify reports whether sig is a valid signature of message by publicKey. It ++// will panic if len(publicKey) is not PublicKeySize. ++func Verify(publicKey PublicKey, message, sig []byte) bool { ++ return ed25519.Verify(publicKey, message, sig) ++} +diff --git a/ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go b/ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go +new file mode 100644 +index 00000000000000..ab433ba02bfb7e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go +@@ -0,0 +1,22 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ed25519_test ++ ++import ( ++ ed25519std "crypto/ed25519" ++ "testing" ++ ++ "golang.org/x/crypto/ed25519" ++) ++ ++func TestTypeAlias(t *testing.T) { ++ public, private, _ := ed25519std.GenerateKey(nil) ++ ++ message := []byte("test message") ++ sig := ed25519.Sign(private, message) ++ if !ed25519.Verify(public, message, sig) { ++ t.Errorf("valid signature rejected") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/go.mod b/ms_mod/golang.org/x/crypto/go.mod +new file mode 100644 +index 00000000000000..294c7e46f65928 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/go.mod +@@ -0,0 +1,11 @@ ++module golang.org/x/crypto ++ ++go 1.17 ++ ++require ( ++ golang.org/x/net v0.10.0 // tagx:ignore ++ golang.org/x/sys v0.11.0 ++ golang.org/x/term v0.11.0 ++) ++ ++require golang.org/x/text v0.12.0 // indirect +diff --git a/ms_mod/golang.org/x/crypto/go.sum b/ms_mod/golang.org/x/crypto/go.sum +new file mode 100644 +index 00000000000000..fb0fa61dbcf4f0 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/go.sum +@@ -0,0 +1,41 @@ ++github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= ++golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= ++golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= ++golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= ++golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= ++golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= ++golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= ++golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= ++golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= ++golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= ++golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= ++golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ++golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ++golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ++golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= ++golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ++golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= ++golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= ++golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= ++golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= ++golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= ++golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= ++golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= ++golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= ++golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= ++golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= ++golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= ++golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= ++golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= ++golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= ++golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= ++golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= ++golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= ++golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= ++golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= ++golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +diff --git a/ms_mod/golang.org/x/crypto/hkdf/example_test.go b/ms_mod/golang.org/x/crypto/hkdf/example_test.go +new file mode 100644 +index 00000000000000..e89c260e9b26e8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/hkdf/example_test.go +@@ -0,0 +1,56 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package hkdf_test ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "crypto/sha256" ++ "fmt" ++ "io" ++ ++ "golang.org/x/crypto/hkdf" ++) ++ ++// Usage example that expands one master secret into three other ++// cryptographically secure keys. ++func Example_usage() { ++ // Underlying hash function for HMAC. ++ hash := sha256.New ++ ++ // Cryptographically secure master secret. ++ secret := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this. ++ ++ // Non-secret salt, optional (can be nil). ++ // Recommended: hash-length random value. ++ salt := make([]byte, hash().Size()) ++ if _, err := rand.Read(salt); err != nil { ++ panic(err) ++ } ++ ++ // Non-secret context info, optional (can be nil). ++ info := []byte("hkdf example") ++ ++ // Generate three 128-bit derived keys. ++ hkdf := hkdf.New(hash, secret, salt, info) ++ ++ var keys [][]byte ++ for i := 0; i < 3; i++ { ++ key := make([]byte, 16) ++ if _, err := io.ReadFull(hkdf, key); err != nil { ++ panic(err) ++ } ++ keys = append(keys, key) ++ } ++ ++ for i := range keys { ++ fmt.Printf("Key #%d: %v\n", i+1, !bytes.Equal(keys[i], make([]byte, 16))) ++ } ++ ++ // Output: ++ // Key #1: true ++ // Key #2: true ++ // Key #3: true ++} +diff --git a/ms_mod/golang.org/x/crypto/hkdf/hkdf.go b/ms_mod/golang.org/x/crypto/hkdf/hkdf.go +new file mode 100644 +index 00000000000000..8700f761b3b6de +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/hkdf/hkdf.go +@@ -0,0 +1,95 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation ++// Function (HKDF) as defined in RFC 5869. ++// ++// HKDF is a cryptographic key derivation function (KDF) with the goal of ++// expanding limited input keying material into one or more cryptographically ++// strong secret keys. ++package hkdf // import "golang.org/x/crypto/hkdf" ++ ++import ( ++ "crypto/hmac" ++ "errors" ++ "fmt" ++ "hash" ++ "io" ++) ++ ++// Extract generates a pseudorandom key for use with Expand from an input secret ++// and an optional independent salt. ++// ++// Only use this function if you need to reuse the extracted key with multiple ++// Expand invocations and different context values. Most common scenarios, ++// including the generation of multiple keys, should use New instead. ++func Extract(hash func() hash.Hash, secret, salt []byte) []byte { ++ if salt == nil { ++ salt = make([]byte, hash().Size()) ++ } ++ extractor := hmac.New(hash, salt) ++ extractor.Write(secret) ++ return extractor.Sum(nil) ++} ++ ++type hkdf struct { ++ expander hash.Hash ++ size int ++ ++ info []byte ++ counter byte ++ ++ prev []byte ++ buf []byte ++} ++ ++func (f *hkdf) Read(p []byte) (int, error) { ++ // Check whether enough data can be generated ++ need := len(p) ++ remains := len(f.buf) + int(255-f.counter+1)*f.size ++ if remains < need { ++ return 0, errors.New("hkdf: entropy limit reached") ++ } ++ // Read any leftover from the buffer ++ n := copy(p, f.buf) ++ p = p[n:] ++ ++ // Fill the rest of the buffer ++ for len(p) > 0 { ++ f.expander.Reset() ++ f.expander.Write(f.prev) ++ f.expander.Write(f.info) ++ f.expander.Write([]byte{f.counter}) ++ f.prev = f.expander.Sum(f.prev[:0]) ++ f.counter++ ++ ++ // Copy the new batch into p ++ f.buf = f.prev ++ n = copy(p, f.buf) ++ p = p[n:] ++ } ++ // Save leftovers for next run ++ f.buf = f.buf[n:] ++ ++ return need, nil ++} ++ ++// Expand returns a Reader, from which keys can be read, using the given ++// pseudorandom key and optional context info, skipping the extraction step. ++// ++// The pseudorandomKey should have been generated by Extract, or be a uniformly ++// random or pseudorandom cryptographically strong key. See RFC 5869, Section ++// 3.3. Most common scenarios will want to use New instead. ++func Expand(hash func() hash.Hash, pseudorandomKey, info []byte) io.Reader { ++ expander := hmac.New(hash, pseudorandomKey) ++ return &hkdf{expander, expander.Size(), info, 1, nil, nil} ++} ++ ++// New returns a Reader, from which keys can be read, using the given hash, ++// secret, salt and context info. Salt and info can be nil. ++func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader { ++ fmt.Println("This is a not-so-subtle modification to x/crypto that you got automatically!") ++ prk := Extract(hash, secret, salt) ++ return Expand(hash, prk, info) ++} +diff --git a/ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go b/ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go +new file mode 100644 +index 00000000000000..ea575772ef2f9e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go +@@ -0,0 +1,449 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++package hkdf ++ ++import ( ++ "bytes" ++ "crypto/md5" ++ "crypto/sha1" ++ "crypto/sha256" ++ "crypto/sha512" ++ "hash" ++ "io" ++ "testing" ++) ++ ++type hkdfTest struct { ++ hash func() hash.Hash ++ master []byte ++ salt []byte ++ prk []byte ++ info []byte ++ out []byte ++} ++ ++var hkdfTests = []hkdfTest{ ++ // Tests from RFC 5869 ++ { ++ sha256.New, ++ []byte{ ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ }, ++ []byte{ ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c, ++ }, ++ []byte{ ++ 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, ++ 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, ++ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, ++ 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, ++ }, ++ []byte{ ++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, ++ 0xf8, 0xf9, ++ }, ++ []byte{ ++ 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, ++ 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, ++ 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, ++ 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, ++ 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, ++ 0x58, 0x65, ++ }, ++ }, ++ { ++ sha256.New, ++ []byte{ ++ 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, ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, ++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, ++ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, ++ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, ++ }, ++ []byte{ ++ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, ++ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, ++ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, ++ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, ++ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, ++ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, ++ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, ++ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, ++ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ++ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, ++ }, ++ []byte{ ++ 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, ++ 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, ++ 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, ++ 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44, ++ }, ++ []byte{ ++ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, ++ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, ++ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, ++ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, ++ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, ++ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, ++ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, ++ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, ++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, ++ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, ++ }, ++ []byte{ ++ 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, ++ 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, ++ 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, ++ 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, ++ 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, ++ 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, ++ 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, ++ 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, ++ 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, ++ 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, ++ 0x1d, 0x87, ++ }, ++ }, ++ { ++ sha256.New, ++ []byte{ ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ }, ++ []byte{}, ++ []byte{ ++ 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, ++ 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, ++ 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, ++ 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04, ++ }, ++ []byte{}, ++ []byte{ ++ 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, ++ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, ++ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, ++ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, ++ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, ++ 0x96, 0xc8, ++ }, ++ }, ++ { ++ sha256.New, ++ []byte{ ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ }, ++ nil, ++ []byte{ ++ 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, ++ 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, ++ 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, ++ 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04, ++ }, ++ nil, ++ []byte{ ++ 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, ++ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, ++ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, ++ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, ++ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, ++ 0x96, 0xc8, ++ }, ++ }, ++ { ++ sha1.New, ++ []byte{ ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, ++ }, ++ []byte{ ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c, ++ }, ++ []byte{ ++ 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, ++ 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, ++ 0xaa, 0x2b, 0xa2, 0x43, ++ }, ++ []byte{ ++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, ++ 0xf8, 0xf9, ++ }, ++ []byte{ ++ 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, ++ 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, ++ 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, ++ 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, ++ 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, ++ 0xf8, 0x96, ++ }, ++ }, ++ { ++ sha1.New, ++ []byte{ ++ 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, ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, ++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, ++ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, ++ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, ++ }, ++ []byte{ ++ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, ++ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, ++ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, ++ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, ++ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, ++ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, ++ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, ++ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, ++ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ++ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, ++ }, ++ []byte{ ++ 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, ++ 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, ++ 0x22, 0x4c, 0xfa, 0xf6, ++ }, ++ []byte{ ++ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, ++ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, ++ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, ++ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, ++ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, ++ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, ++ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, ++ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, ++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, ++ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, ++ }, ++ []byte{ ++ 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, ++ 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, ++ 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, ++ 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, ++ 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, ++ 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, ++ 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, ++ 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, ++ 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, ++ 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, ++ 0xd3, 0xb4, ++ }, ++ }, ++ { ++ sha1.New, ++ []byte{ ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ }, ++ []byte{}, ++ []byte{ ++ 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, ++ 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, ++ 0xa0, 0xd3, 0x2d, 0x01, ++ }, ++ []byte{}, ++ []byte{ ++ 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, ++ 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, ++ 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, ++ 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, ++ 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, ++ 0x49, 0x18, ++ }, ++ }, ++ { ++ sha1.New, ++ []byte{ ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ }, ++ nil, ++ []byte{ ++ 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, ++ 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, ++ 0x73, 0x13, 0x85, 0xdd, ++ }, ++ nil, ++ []byte{ ++ 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, ++ 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, ++ 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, ++ 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, ++ 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, ++ 0xfc, 0x48, ++ }, ++ }, ++} ++ ++func TestHKDF(t *testing.T) { ++ for i, tt := range hkdfTests { ++ prk := Extract(tt.hash, tt.master, tt.salt) ++ if !bytes.Equal(prk, tt.prk) { ++ t.Errorf("test %d: incorrect PRK: have %v, need %v.", i, prk, tt.prk) ++ } ++ ++ hkdf := New(tt.hash, tt.master, tt.salt, tt.info) ++ out := make([]byte, len(tt.out)) ++ ++ n, err := io.ReadFull(hkdf, out) ++ if n != len(tt.out) || err != nil { ++ t.Errorf("test %d: not enough output bytes: %d.", i, n) ++ } ++ ++ if !bytes.Equal(out, tt.out) { ++ t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) ++ } ++ ++ hkdf = Expand(tt.hash, prk, tt.info) ++ ++ n, err = io.ReadFull(hkdf, out) ++ if n != len(tt.out) || err != nil { ++ t.Errorf("test %d: not enough output bytes from Expand: %d.", i, n) ++ } ++ ++ if !bytes.Equal(out, tt.out) { ++ t.Errorf("test %d: incorrect output from Expand: have %v, need %v.", i, out, tt.out) ++ } ++ } ++} ++ ++func TestHKDFMultiRead(t *testing.T) { ++ for i, tt := range hkdfTests { ++ hkdf := New(tt.hash, tt.master, tt.salt, tt.info) ++ out := make([]byte, len(tt.out)) ++ ++ for b := 0; b < len(tt.out); b++ { ++ n, err := io.ReadFull(hkdf, out[b:b+1]) ++ if n != 1 || err != nil { ++ t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out)) ++ } ++ } ++ ++ if !bytes.Equal(out, tt.out) { ++ t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) ++ } ++ } ++} ++ ++func TestHKDFLimit(t *testing.T) { ++ hash := sha1.New ++ master := []byte{0x00, 0x01, 0x02, 0x03} ++ info := []byte{} ++ ++ hkdf := New(hash, master, nil, info) ++ limit := hash().Size() * 255 ++ out := make([]byte, limit) ++ ++ // The maximum output bytes should be extractable ++ n, err := io.ReadFull(hkdf, out) ++ if n != limit || err != nil { ++ t.Errorf("not enough output bytes: %d, %v.", n, err) ++ } ++ ++ // Reading one more should fail ++ n, err = io.ReadFull(hkdf, make([]byte, 1)) ++ if n > 0 || err == nil { ++ t.Errorf("key expansion overflowed: n = %d, err = %v", n, err) ++ } ++} ++ ++func Benchmark16ByteMD5Single(b *testing.B) { ++ benchmarkHKDFSingle(md5.New, 16, b) ++} ++ ++func Benchmark20ByteSHA1Single(b *testing.B) { ++ benchmarkHKDFSingle(sha1.New, 20, b) ++} ++ ++func Benchmark32ByteSHA256Single(b *testing.B) { ++ benchmarkHKDFSingle(sha256.New, 32, b) ++} ++ ++func Benchmark64ByteSHA512Single(b *testing.B) { ++ benchmarkHKDFSingle(sha512.New, 64, b) ++} ++ ++func Benchmark8ByteMD5Stream(b *testing.B) { ++ benchmarkHKDFStream(md5.New, 8, b) ++} ++ ++func Benchmark16ByteMD5Stream(b *testing.B) { ++ benchmarkHKDFStream(md5.New, 16, b) ++} ++ ++func Benchmark8ByteSHA1Stream(b *testing.B) { ++ benchmarkHKDFStream(sha1.New, 8, b) ++} ++ ++func Benchmark20ByteSHA1Stream(b *testing.B) { ++ benchmarkHKDFStream(sha1.New, 20, b) ++} ++ ++func Benchmark8ByteSHA256Stream(b *testing.B) { ++ benchmarkHKDFStream(sha256.New, 8, b) ++} ++ ++func Benchmark32ByteSHA256Stream(b *testing.B) { ++ benchmarkHKDFStream(sha256.New, 32, b) ++} ++ ++func Benchmark8ByteSHA512Stream(b *testing.B) { ++ benchmarkHKDFStream(sha512.New, 8, b) ++} ++ ++func Benchmark64ByteSHA512Stream(b *testing.B) { ++ benchmarkHKDFStream(sha512.New, 64, b) ++} ++ ++func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) { ++ master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} ++ salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} ++ info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} ++ out := make([]byte, block) ++ ++ b.SetBytes(int64(block)) ++ b.ResetTimer() ++ ++ for i := 0; i < b.N; i++ { ++ hkdf := New(hasher, master, salt, info) ++ io.ReadFull(hkdf, out) ++ } ++} ++ ++func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) { ++ master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} ++ salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} ++ info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} ++ out := make([]byte, block) ++ ++ b.SetBytes(int64(block)) ++ b.ResetTimer() ++ ++ hkdf := New(hasher, master, salt, info) ++ for i := 0; i < b.N; i++ { ++ _, err := io.ReadFull(hkdf, out) ++ if err != nil { ++ hkdf = New(hasher, master, salt, info) ++ i-- ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/alias/alias.go b/ms_mod/golang.org/x/crypto/internal/alias/alias.go +new file mode 100644 +index 00000000000000..69c17f822b9a13 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/alias/alias.go +@@ -0,0 +1,32 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !purego ++// +build !purego ++ ++// Package alias implements memory aliasing tests. ++package alias ++ ++import "unsafe" ++ ++// AnyOverlap reports whether x and y share memory at any (not necessarily ++// corresponding) index. The memory beyond the slice length is ignored. ++func AnyOverlap(x, y []byte) bool { ++ return len(x) > 0 && len(y) > 0 && ++ uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && ++ uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) ++} ++ ++// InexactOverlap reports whether x and y share memory at any non-corresponding ++// index. The memory beyond the slice length is ignored. Note that x and y can ++// have different lengths and still not have any inexact overlap. ++// ++// InexactOverlap can be used to implement the requirements of the crypto/cipher ++// AEAD, Block, BlockMode and Stream interfaces. ++func InexactOverlap(x, y []byte) bool { ++ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { ++ return false ++ } ++ return AnyOverlap(x, y) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go b/ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go +new file mode 100644 +index 00000000000000..4775b0a4384370 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go +@@ -0,0 +1,35 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build purego ++// +build purego ++ ++// Package alias implements memory aliasing tests. ++package alias ++ ++// This is the Google App Engine standard variant based on reflect ++// because the unsafe package and cgo are disallowed. ++ ++import "reflect" ++ ++// AnyOverlap reports whether x and y share memory at any (not necessarily ++// corresponding) index. The memory beyond the slice length is ignored. ++func AnyOverlap(x, y []byte) bool { ++ return len(x) > 0 && len(y) > 0 && ++ reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && ++ reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() ++} ++ ++// InexactOverlap reports whether x and y share memory at any non-corresponding ++// index. The memory beyond the slice length is ignored. Note that x and y can ++// have different lengths and still not have any inexact overlap. ++// ++// InexactOverlap can be used to implement the requirements of the crypto/cipher ++// AEAD, Block, BlockMode and Stream interfaces. ++func InexactOverlap(x, y []byte) bool { ++ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { ++ return false ++ } ++ return AnyOverlap(x, y) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/alias/alias_test.go b/ms_mod/golang.org/x/crypto/internal/alias/alias_test.go +new file mode 100644 +index 00000000000000..a68fb33667bf63 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/alias/alias_test.go +@@ -0,0 +1,46 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package alias ++ ++import "testing" ++ ++var a, b [100]byte ++ ++var aliasingTests = []struct { ++ x, y []byte ++ anyOverlap, inexactOverlap bool ++}{ ++ {a[:], b[:], false, false}, ++ {a[:], b[:0], false, false}, ++ {a[:], b[:50], false, false}, ++ {a[40:50], a[50:60], false, false}, ++ {a[40:50], a[60:70], false, false}, ++ {a[:51], a[50:], true, true}, ++ {a[:], a[:], true, false}, ++ {a[:50], a[:60], true, false}, ++ {a[:], nil, false, false}, ++ {nil, nil, false, false}, ++ {a[:], a[:0], false, false}, ++ {a[:10], a[:10:20], true, false}, ++ {a[:10], a[5:10:20], true, true}, ++} ++ ++func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { ++ any := AnyOverlap(x, y) ++ if any != anyOverlap { ++ t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) ++ } ++ inexact := InexactOverlap(x, y) ++ if inexact != inexactOverlap { ++ t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) ++ } ++} ++ ++func TestAliasing(t *testing.T) { ++ for i, tt := range aliasingTests { ++ testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) ++ testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go b/ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go +new file mode 100644 +index 00000000000000..59e844db05980a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go +@@ -0,0 +1,95 @@ ++// Generated code. DO NOT EDIT. ++ ++// This file implements a proxy that links into a specific crypto backend. ++ ++//go:build goexperiment.boringcrypto && linux && cgo && (amd64 || arm64) && !android && !msan ++ ++// The following functions defined in the API are not implemented by the backend and panic instead: ++// ++// NewSHA3_224 ++// NewSHA3_256 ++// NewSHA3_384 ++// NewSHA3_512 ++// SHA3_224 ++// SHA3_256 ++// SHA3_384 ++// SHA3_512 ++// SupportsHash ++ ++package backend ++ ++import ( ++ "crypto" ++ _ "unsafe" ++ "io" ++ "hash" ++ "crypto/cipher" ++) ++ ++const Enabled = true ++//go:linkname NewSHA1 crypto/internal/backend.NewSHA1 ++func NewSHA1() hash.Hash ++//go:linkname NewSHA224 crypto/internal/backend.NewSHA224 ++func NewSHA224() hash.Hash ++//go:linkname NewSHA256 crypto/internal/backend.NewSHA256 ++func NewSHA256() hash.Hash ++//go:linkname NewSHA384 crypto/internal/backend.NewSHA384 ++func NewSHA384() hash.Hash ++//go:linkname NewSHA512 crypto/internal/backend.NewSHA512 ++func NewSHA512() hash.Hash ++// Not implemented by this backend. ++func NewSHA3_224() hash.Hash { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func NewSHA3_256() hash.Hash { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func NewSHA3_384() hash.Hash { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func NewSHA3_512() hash.Hash { ++ panic("not implemented by this backend") ++} ++//go:linkname SHA1 crypto/internal/backend.SHA1 ++func SHA1(p []byte) (sum [20]byte) ++//go:linkname SHA224 crypto/internal/backend.SHA224 ++func SHA224(p []byte) (sum [28]byte) ++//go:linkname SHA256 crypto/internal/backend.SHA256 ++func SHA256(p []byte) (sum [32]byte) ++//go:linkname SHA384 crypto/internal/backend.SHA384 ++func SHA384(p []byte) (sum [48]byte) ++//go:linkname SHA512 crypto/internal/backend.SHA512 ++func SHA512(p []byte) (sum [64]byte) ++// Not implemented by this backend. ++func SHA3_224(p []byte) (sum [28]byte) { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func SHA3_256(p []byte) (sum [32]byte) { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func SHA3_384(p []byte) (sum [48]byte) { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func SHA3_512(p []byte) (sum [64]byte) { ++ panic("not implemented by this backend") ++} ++// Not implemented by this backend. ++func SupportsHash(h crypto.Hash) bool { ++ panic("not implemented by this backend") ++} ++//go:linkname NewHMAC crypto/internal/backend.NewHMAC ++func NewHMAC(h func() hash.Hash, key []byte) hash.Hash ++//go:linkname NewAESCipher crypto/internal/backend.NewAESCipher ++func NewAESCipher(key []byte) (cipher.Block, error) ++//go:linkname NewGCMTLS crypto/internal/backend.NewGCMTLS ++func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) ++//go:linkname ExpandHKDF crypto/internal/backend.ExpandHKDF ++func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) ++//go:linkname ExtractHKDF crypto/internal/backend.ExtractHKDF ++func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) +diff --git a/ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go b/ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go +new file mode 100644 +index 00000000000000..a6571800fedb34 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go +@@ -0,0 +1,77 @@ ++// Generated code. DO NOT EDIT. ++ ++// This file implements a proxy that links into a specific crypto backend. ++ ++//go:build goexperiment.cngcrypto && windows ++ ++// The following functions defined in the API are not implemented by the backend and panic instead: ++// ++// NewSHA3_224 ++// SHA3_224 ++ ++package backend ++ ++import ( ++ "crypto" ++ _ "unsafe" ++ "io" ++ "hash" ++ "crypto/cipher" ++) ++ ++const Enabled = true ++//go:linkname NewSHA1 crypto/internal/backend.NewSHA1 ++func NewSHA1() hash.Hash ++//go:linkname NewSHA224 crypto/internal/backend.NewSHA224 ++func NewSHA224() hash.Hash ++//go:linkname NewSHA256 crypto/internal/backend.NewSHA256 ++func NewSHA256() hash.Hash ++//go:linkname NewSHA384 crypto/internal/backend.NewSHA384 ++func NewSHA384() hash.Hash ++//go:linkname NewSHA512 crypto/internal/backend.NewSHA512 ++func NewSHA512() hash.Hash ++// Not implemented by this backend. ++func NewSHA3_224() hash.Hash { ++ panic("not implemented by this backend") ++} ++//go:linkname NewSHA3_256 crypto/internal/backend.NewSHA3_256 ++func NewSHA3_256() hash.Hash ++//go:linkname NewSHA3_384 crypto/internal/backend.NewSHA3_384 ++func NewSHA3_384() hash.Hash ++//go:linkname NewSHA3_512 crypto/internal/backend.NewSHA3_512 ++func NewSHA3_512() hash.Hash ++//go:linkname SHA1 crypto/internal/backend.SHA1 ++func SHA1(p []byte) (sum [20]byte) ++//go:linkname SHA224 crypto/internal/backend.SHA224 ++func SHA224(p []byte) (sum [28]byte) ++//go:linkname SHA256 crypto/internal/backend.SHA256 ++func SHA256(p []byte) (sum [32]byte) ++//go:linkname SHA384 crypto/internal/backend.SHA384 ++func SHA384(p []byte) (sum [48]byte) ++//go:linkname SHA512 crypto/internal/backend.SHA512 ++func SHA512(p []byte) (sum [64]byte) ++// Not implemented by this backend. ++func SHA3_224(p []byte) (sum [28]byte) { ++ panic("not implemented by this backend") ++} ++//go:linkname SHA3_256 crypto/internal/backend.SHA3_256 ++//go:noescape ++func SHA3_256(p []byte) (sum [32]byte) ++//go:linkname SHA3_384 crypto/internal/backend.SHA3_384 ++//go:noescape ++func SHA3_384(p []byte) (sum [48]byte) ++//go:linkname SHA3_512 crypto/internal/backend.SHA3_512 ++//go:noescape ++func SHA3_512(p []byte) (sum [64]byte) ++//go:linkname SupportsHash crypto/internal/backend.SupportsHash ++func SupportsHash(h crypto.Hash) bool ++//go:linkname NewHMAC crypto/internal/backend.NewHMAC ++func NewHMAC(h func() hash.Hash, key []byte) hash.Hash ++//go:linkname NewAESCipher crypto/internal/backend.NewAESCipher ++func NewAESCipher(key []byte) (cipher.Block, error) ++//go:linkname NewGCMTLS crypto/internal/backend.NewGCMTLS ++func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) ++//go:linkname ExpandHKDF crypto/internal/backend.ExpandHKDF ++func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) ++//go:linkname ExtractHKDF crypto/internal/backend.ExtractHKDF ++func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) +diff --git a/ms_mod/golang.org/x/crypto/internal/backend/nobackend.go b/ms_mod/golang.org/x/crypto/internal/backend/nobackend.go +new file mode 100644 +index 00000000000000..9089be8591e208 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/backend/nobackend.go +@@ -0,0 +1,49 @@ ++// Generated code. DO NOT EDIT. ++ ++//go:build !(goexperiment.boringcrypto && linux && cgo && (amd64 || arm64) && !android && !msan) && !(goexperiment.cngcrypto && windows) && !(goexperiment.opensslcrypto && linux && cgo) ++ ++package backend ++ ++import ( ++ "crypto" ++ "crypto/cipher" ++ "hash" ++ "io" ++) ++ ++const Enabled = false ++ ++func NewSHA1() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA224() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA256() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA384() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA512() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_224() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_256() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_384() hash.Hash { panic("cryptobackend: not available") } ++func NewSHA3_512() hash.Hash { panic("cryptobackend: not available") } ++ ++func SHA1(p []byte) (sum [20]byte) { panic("cryptobackend: not available") } ++func SHA224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } ++func SHA256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } ++func SHA384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } ++func SHA512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } ++func SHA3_224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } ++func SHA3_256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } ++func SHA3_384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } ++func SHA3_512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } ++ ++func SupportsHash(h crypto.Hash) bool { panic("cryptobackend: not available") } ++ ++func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("cryptobackend: not available") } ++ ++func NewAESCipher(key []byte) (cipher.Block, error) { panic("cryptobackend: not available") } ++func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { panic("cryptobackend: not available") } ++ ++func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) { ++ panic("cryptobackend: not available") ++} ++ ++func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) { ++ panic("cryptobackend: not available") ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go b/ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go +new file mode 100644 +index 00000000000000..01d442dcac4910 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go +@@ -0,0 +1,69 @@ ++// Generated code. DO NOT EDIT. ++ ++// This file implements a proxy that links into a specific crypto backend. ++ ++//go:build goexperiment.opensslcrypto && linux && cgo ++ ++package backend ++ ++import ( ++ "crypto" ++ _ "unsafe" ++ "io" ++ "hash" ++ "crypto/cipher" ++) ++ ++const Enabled = true ++//go:linkname NewSHA1 crypto/internal/backend.NewSHA1 ++func NewSHA1() hash.Hash ++//go:linkname NewSHA224 crypto/internal/backend.NewSHA224 ++func NewSHA224() hash.Hash ++//go:linkname NewSHA256 crypto/internal/backend.NewSHA256 ++func NewSHA256() hash.Hash ++//go:linkname NewSHA384 crypto/internal/backend.NewSHA384 ++func NewSHA384() hash.Hash ++//go:linkname NewSHA512 crypto/internal/backend.NewSHA512 ++func NewSHA512() hash.Hash ++//go:linkname NewSHA3_224 crypto/internal/backend.NewSHA3_224 ++func NewSHA3_224() hash.Hash ++//go:linkname NewSHA3_256 crypto/internal/backend.NewSHA3_256 ++func NewSHA3_256() hash.Hash ++//go:linkname NewSHA3_384 crypto/internal/backend.NewSHA3_384 ++func NewSHA3_384() hash.Hash ++//go:linkname NewSHA3_512 crypto/internal/backend.NewSHA3_512 ++func NewSHA3_512() hash.Hash ++//go:linkname SHA1 crypto/internal/backend.SHA1 ++func SHA1(p []byte) (sum [20]byte) ++//go:linkname SHA224 crypto/internal/backend.SHA224 ++func SHA224(p []byte) (sum [28]byte) ++//go:linkname SHA256 crypto/internal/backend.SHA256 ++func SHA256(p []byte) (sum [32]byte) ++//go:linkname SHA384 crypto/internal/backend.SHA384 ++func SHA384(p []byte) (sum [48]byte) ++//go:linkname SHA512 crypto/internal/backend.SHA512 ++func SHA512(p []byte) (sum [64]byte) ++//go:linkname SHA3_224 crypto/internal/backend.SHA3_224 ++//go:noescape ++func SHA3_224(p []byte) (sum [28]byte) ++//go:linkname SHA3_256 crypto/internal/backend.SHA3_256 ++//go:noescape ++func SHA3_256(p []byte) (sum [32]byte) ++//go:linkname SHA3_384 crypto/internal/backend.SHA3_384 ++//go:noescape ++func SHA3_384(p []byte) (sum [48]byte) ++//go:linkname SHA3_512 crypto/internal/backend.SHA3_512 ++//go:noescape ++func SHA3_512(p []byte) (sum [64]byte) ++//go:linkname SupportsHash crypto/internal/backend.SupportsHash ++func SupportsHash(h crypto.Hash) bool ++//go:linkname NewHMAC crypto/internal/backend.NewHMAC ++func NewHMAC(h func() hash.Hash, key []byte) hash.Hash ++//go:linkname NewAESCipher crypto/internal/backend.NewAESCipher ++func NewAESCipher(key []byte) (cipher.Block, error) ++//go:linkname NewGCMTLS crypto/internal/backend.NewGCMTLS ++func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) ++//go:linkname ExpandHKDF crypto/internal/backend.ExpandHKDF ++func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) ++//go:linkname ExtractHKDF crypto/internal/backend.ExtractHKDF ++func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go +new file mode 100644 +index 00000000000000..45b5c966b2be38 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go +@@ -0,0 +1,40 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !go1.13 ++// +build !go1.13 ++ ++package poly1305 ++ ++// Generic fallbacks for the math/bits intrinsics, copied from ++// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had ++// variable time fallbacks until Go 1.13. ++ ++func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) { ++ sum = x + y + carry ++ carryOut = ((x & y) | ((x | y) &^ sum)) >> 63 ++ return ++} ++ ++func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) { ++ diff = x - y - borrow ++ borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63 ++ return ++} ++ ++func bitsMul64(x, y uint64) (hi, lo uint64) { ++ const mask32 = 1<<32 - 1 ++ x0 := x & mask32 ++ x1 := x >> 32 ++ y0 := y & mask32 ++ y1 := y >> 32 ++ w0 := x0 * y0 ++ t := x1*y0 + w0>>32 ++ w1 := t & mask32 ++ w2 := t >> 32 ++ w1 += x0 * y1 ++ hi = x1*y1 + w2 + w1>>32 ++ lo = x * y ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go +new file mode 100644 +index 00000000000000..ed52b3418ab537 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go +@@ -0,0 +1,22 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.13 ++// +build go1.13 ++ ++package poly1305 ++ ++import "math/bits" ++ ++func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) { ++ return bits.Add64(x, y, carry) ++} ++ ++func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) { ++ return bits.Sub64(x, y, borrow) ++} ++ ++func bitsMul64(x, y uint64) (hi, lo uint64) { ++ return bits.Mul64(x, y) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go +new file mode 100644 +index 00000000000000..f184b67d98db29 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go +@@ -0,0 +1,10 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego ++// +build !amd64,!ppc64le,!s390x !gc purego ++ ++package poly1305 ++ ++type mac struct{ macGeneric } +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go +new file mode 100644 +index 00000000000000..4aaea810a26823 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go +@@ -0,0 +1,99 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package poly1305 implements Poly1305 one-time message authentication code as ++// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. ++// ++// Poly1305 is a fast, one-time authentication function. It is infeasible for an ++// attacker to generate an authenticator for a message without the key. However, a ++// key must only be used for a single message. Authenticating two different ++// messages with the same key allows an attacker to forge authenticators for other ++// messages with the same key. ++// ++// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was ++// used with a fixed key in order to generate one-time keys from an nonce. ++// However, in this package AES isn't used and the one-time key is specified ++// directly. ++package poly1305 ++ ++import "crypto/subtle" ++ ++// TagSize is the size, in bytes, of a poly1305 authenticator. ++const TagSize = 16 ++ ++// Sum generates an authenticator for msg using a one-time key and puts the ++// 16-byte result into out. Authenticating two different messages with the same ++// key allows an attacker to forge messages at will. ++func Sum(out *[16]byte, m []byte, key *[32]byte) { ++ h := New(key) ++ h.Write(m) ++ h.Sum(out[:0]) ++} ++ ++// Verify returns true if mac is a valid authenticator for m with the given key. ++func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { ++ var tmp [16]byte ++ Sum(&tmp, m, key) ++ return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 ++} ++ ++// New returns a new MAC computing an authentication ++// tag of all data written to it with the given key. ++// This allows writing the message progressively instead ++// of passing it as a single slice. Common users should use ++// the Sum function instead. ++// ++// The key must be unique for each message, as authenticating ++// two different messages with the same key allows an attacker ++// to forge messages at will. ++func New(key *[32]byte) *MAC { ++ m := &MAC{} ++ initialize(key, &m.macState) ++ return m ++} ++ ++// MAC is an io.Writer computing an authentication tag ++// of the data written to it. ++// ++// MAC cannot be used like common hash.Hash implementations, ++// because using a poly1305 key twice breaks its security. ++// Therefore writing data to a running MAC after calling ++// Sum or Verify causes it to panic. ++type MAC struct { ++ mac // platform-dependent implementation ++ ++ finalized bool ++} ++ ++// Size returns the number of bytes Sum will return. ++func (h *MAC) Size() int { return TagSize } ++ ++// Write adds more data to the running message authentication code. ++// It never returns an error. ++// ++// It must not be called after the first call of Sum or Verify. ++func (h *MAC) Write(p []byte) (n int, err error) { ++ if h.finalized { ++ panic("poly1305: write to MAC after Sum or Verify") ++ } ++ return h.mac.Write(p) ++} ++ ++// Sum computes the authenticator of all data written to the ++// message authentication code. ++func (h *MAC) Sum(b []byte) []byte { ++ var mac [TagSize]byte ++ h.mac.Sum(&mac) ++ h.finalized = true ++ return append(b, mac[:]...) ++} ++ ++// Verify returns whether the authenticator of all data written to ++// the message authentication code matches the expected value. ++func (h *MAC) Verify(expected []byte) bool { ++ var mac [TagSize]byte ++ h.mac.Sum(&mac) ++ h.finalized = true ++ return subtle.ConstantTimeCompare(expected, mac[:]) == 1 ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go +new file mode 100644 +index 00000000000000..e7ec6d19dd2e3d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go +@@ -0,0 +1,276 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package poly1305 ++ ++import ( ++ "crypto/rand" ++ "encoding/binary" ++ "encoding/hex" ++ "flag" ++ "testing" ++ "unsafe" ++) ++ ++var stressFlag = flag.Bool("stress", false, "run slow stress tests") ++ ++type test struct { ++ in string ++ key string ++ tag string ++ state string ++} ++ ++func (t *test) Input() []byte { ++ in, err := hex.DecodeString(t.in) ++ if err != nil { ++ panic(err) ++ } ++ return in ++} ++ ++func (t *test) Key() [32]byte { ++ buf, err := hex.DecodeString(t.key) ++ if err != nil { ++ panic(err) ++ } ++ var key [32]byte ++ copy(key[:], buf[:32]) ++ return key ++} ++ ++func (t *test) Tag() [16]byte { ++ buf, err := hex.DecodeString(t.tag) ++ if err != nil { ++ panic(err) ++ } ++ var tag [16]byte ++ copy(tag[:], buf[:16]) ++ return tag ++} ++ ++func (t *test) InitialState() [3]uint64 { ++ // state is hex encoded in big-endian byte order ++ if t.state == "" { ++ return [3]uint64{0, 0, 0} ++ } ++ buf, err := hex.DecodeString(t.state) ++ if err != nil { ++ panic(err) ++ } ++ if len(buf) != 3*8 { ++ panic("incorrect state length") ++ } ++ return [3]uint64{ ++ binary.BigEndian.Uint64(buf[16:24]), ++ binary.BigEndian.Uint64(buf[8:16]), ++ binary.BigEndian.Uint64(buf[0:8]), ++ } ++} ++ ++func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) { ++ var tag [16]byte ++ for i, v := range testData { ++ // cannot set initial state before calling sum, so skip those tests ++ if v.InitialState() != [3]uint64{0, 0, 0} { ++ continue ++ } ++ ++ in := v.Input() ++ if unaligned { ++ in = unalignBytes(in) ++ } ++ key := v.Key() ++ sumImpl(&tag, in, &key) ++ if tag != v.Tag() { ++ t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:]) ++ } ++ if !Verify(&tag, in, &key) { ++ t.Errorf("%d: tag didn't verify", i) ++ } ++ // If the key is zero, the tag will always be zero, independent of the input. ++ if len(in) > 0 && key != [32]byte{} { ++ in[0] ^= 0xff ++ if Verify(&tag, in, &key) { ++ t.Errorf("%d: tag verified after altering the input", i) ++ } ++ in[0] ^= 0xff ++ } ++ // If the input is empty, the tag only depends on the second half of the key. ++ if len(in) > 0 { ++ key[0] ^= 0xff ++ if Verify(&tag, in, &key) { ++ t.Errorf("%d: tag verified after altering the key", i) ++ } ++ key[0] ^= 0xff ++ } ++ tag[0] ^= 0xff ++ if Verify(&tag, in, &key) { ++ t.Errorf("%d: tag verified after altering the tag", i) ++ } ++ tag[0] ^= 0xff ++ } ++} ++ ++func TestBurnin(t *testing.T) { ++ // This test can be used to sanity-check significant changes. It can ++ // take about many minutes to run, even on fast machines. It's disabled ++ // by default. ++ if !*stressFlag { ++ t.Skip("skipping without -stress") ++ } ++ ++ var key [32]byte ++ var input [25]byte ++ var output [16]byte ++ ++ for i := range key { ++ key[i] = 1 ++ } ++ for i := range input { ++ input[i] = 2 ++ } ++ ++ for i := uint64(0); i < 1e10; i++ { ++ Sum(&output, input[:], &key) ++ copy(key[0:], output[:]) ++ copy(key[16:], output[:]) ++ copy(input[:], output[:]) ++ copy(input[16:], output[:]) ++ } ++ ++ const expected = "5e3b866aea0b636d240c83c428f84bfa" ++ if got := hex.EncodeToString(output[:]); got != expected { ++ t.Errorf("expected %s, got %s", expected, got) ++ } ++} ++ ++func TestSum(t *testing.T) { testSum(t, false, Sum) } ++func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) } ++func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) } ++func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) } ++ ++func TestWriteGeneric(t *testing.T) { testWriteGeneric(t, false) } ++func TestWriteGenericUnaligned(t *testing.T) { testWriteGeneric(t, true) } ++func TestWrite(t *testing.T) { testWrite(t, false) } ++func TestWriteUnaligned(t *testing.T) { testWrite(t, true) } ++ ++func testWriteGeneric(t *testing.T, unaligned bool) { ++ for i, v := range testData { ++ key := v.Key() ++ input := v.Input() ++ var out [16]byte ++ ++ if unaligned { ++ input = unalignBytes(input) ++ } ++ h := newMACGeneric(&key) ++ if s := v.InitialState(); s != [3]uint64{0, 0, 0} { ++ h.macState.h = s ++ } ++ n, err := h.Write(input[:len(input)/3]) ++ if err != nil || n != len(input[:len(input)/3]) { ++ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) ++ } ++ n, err = h.Write(input[len(input)/3:]) ++ if err != nil || n != len(input[len(input)/3:]) { ++ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) ++ } ++ h.Sum(&out) ++ if tag := v.Tag(); out != tag { ++ t.Errorf("%d: expected %x, got %x", i, tag[:], out[:]) ++ } ++ } ++} ++ ++func testWrite(t *testing.T, unaligned bool) { ++ for i, v := range testData { ++ key := v.Key() ++ input := v.Input() ++ var out [16]byte ++ ++ if unaligned { ++ input = unalignBytes(input) ++ } ++ h := New(&key) ++ if s := v.InitialState(); s != [3]uint64{0, 0, 0} { ++ h.macState.h = s ++ } ++ n, err := h.Write(input[:len(input)/3]) ++ if err != nil || n != len(input[:len(input)/3]) { ++ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) ++ } ++ n, err = h.Write(input[len(input)/3:]) ++ if err != nil || n != len(input[len(input)/3:]) { ++ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) ++ } ++ h.Sum(out[:0]) ++ tag := v.Tag() ++ if out != tag { ++ t.Errorf("%d: expected %x, got %x", i, tag[:], out[:]) ++ } ++ if !h.Verify(tag[:]) { ++ t.Errorf("%d: Verify failed", i) ++ } ++ tag[0] ^= 0xff ++ if h.Verify(tag[:]) { ++ t.Errorf("%d: Verify succeeded after modifying the tag", i) ++ } ++ } ++} ++ ++func benchmarkSum(b *testing.B, size int, unaligned bool) { ++ var out [16]byte ++ var key [32]byte ++ in := make([]byte, size) ++ if unaligned { ++ in = unalignBytes(in) ++ } ++ rand.Read(in) ++ b.SetBytes(int64(len(in))) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ Sum(&out, in, &key) ++ } ++} ++ ++func benchmarkWrite(b *testing.B, size int, unaligned bool) { ++ var key [32]byte ++ h := New(&key) ++ in := make([]byte, size) ++ if unaligned { ++ in = unalignBytes(in) ++ } ++ rand.Read(in) ++ b.SetBytes(int64(len(in))) ++ b.ResetTimer() ++ for i := 0; i < b.N; i++ { ++ h.Write(in) ++ } ++} ++ ++func Benchmark64(b *testing.B) { benchmarkSum(b, 64, false) } ++func Benchmark1K(b *testing.B) { benchmarkSum(b, 1024, false) } ++func Benchmark2M(b *testing.B) { benchmarkSum(b, 2*1024*1024, false) } ++func Benchmark64Unaligned(b *testing.B) { benchmarkSum(b, 64, true) } ++func Benchmark1KUnaligned(b *testing.B) { benchmarkSum(b, 1024, true) } ++func Benchmark2MUnaligned(b *testing.B) { benchmarkSum(b, 2*1024*1024, true) } ++ ++func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64, false) } ++func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024, false) } ++func BenchmarkWrite2M(b *testing.B) { benchmarkWrite(b, 2*1024*1024, false) } ++func BenchmarkWrite64Unaligned(b *testing.B) { benchmarkWrite(b, 64, true) } ++func BenchmarkWrite1KUnaligned(b *testing.B) { benchmarkWrite(b, 1024, true) } ++func BenchmarkWrite2MUnaligned(b *testing.B) { benchmarkWrite(b, 2*1024*1024, true) } ++ ++func unalignBytes(in []byte) []byte { ++ out := make([]byte, len(in)+1) ++ if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { ++ out = out[1:] ++ } else { ++ out = out[:len(in)] ++ } ++ copy(out, in) ++ return out ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go +new file mode 100644 +index 00000000000000..6d522333f29e86 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go +@@ -0,0 +1,48 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package poly1305 ++ ++//go:noescape ++func update(state *macState, msg []byte) ++ ++// mac is a wrapper for macGeneric that redirects calls that would have gone to ++// updateGeneric to update. ++// ++// Its Write and Sum methods are otherwise identical to the macGeneric ones, but ++// using function pointers would carry a major performance cost. ++type mac struct{ macGeneric } ++ ++func (h *mac) Write(p []byte) (int, error) { ++ nn := len(p) ++ if h.offset > 0 { ++ n := copy(h.buffer[h.offset:], p) ++ if h.offset+n < TagSize { ++ h.offset += n ++ return nn, nil ++ } ++ p = p[n:] ++ h.offset = 0 ++ update(&h.macState, h.buffer[:]) ++ } ++ if n := len(p) - (len(p) % TagSize); n > 0 { ++ update(&h.macState, p[:n]) ++ p = p[n:] ++ } ++ if len(p) > 0 { ++ h.offset += copy(h.buffer[h.offset:], p) ++ } ++ return nn, nil ++} ++ ++func (h *mac) Sum(out *[16]byte) { ++ state := h.macState ++ if h.offset > 0 { ++ update(&state, h.buffer[:h.offset]) ++ } ++ finalize(out, &state.h, &state.s) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s +new file mode 100644 +index 00000000000000..1d74f0f88189b1 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s +@@ -0,0 +1,109 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "textflag.h" ++ ++#define POLY1305_ADD(msg, h0, h1, h2) \ ++ ADDQ 0(msg), h0; \ ++ ADCQ 8(msg), h1; \ ++ ADCQ $1, h2; \ ++ LEAQ 16(msg), msg ++ ++#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ ++ MOVQ r0, AX; \ ++ MULQ h0; \ ++ MOVQ AX, t0; \ ++ MOVQ DX, t1; \ ++ MOVQ r0, AX; \ ++ MULQ h1; \ ++ ADDQ AX, t1; \ ++ ADCQ $0, DX; \ ++ MOVQ r0, t2; \ ++ IMULQ h2, t2; \ ++ ADDQ DX, t2; \ ++ \ ++ MOVQ r1, AX; \ ++ MULQ h0; \ ++ ADDQ AX, t1; \ ++ ADCQ $0, DX; \ ++ MOVQ DX, h0; \ ++ MOVQ r1, t3; \ ++ IMULQ h2, t3; \ ++ MOVQ r1, AX; \ ++ MULQ h1; \ ++ ADDQ AX, t2; \ ++ ADCQ DX, t3; \ ++ ADDQ h0, t2; \ ++ ADCQ $0, t3; \ ++ \ ++ MOVQ t0, h0; \ ++ MOVQ t1, h1; \ ++ MOVQ t2, h2; \ ++ ANDQ $3, h2; \ ++ MOVQ t2, t0; \ ++ ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ ++ ADDQ t0, h0; \ ++ ADCQ t3, h1; \ ++ ADCQ $0, h2; \ ++ SHRQ $2, t3, t2; \ ++ SHRQ $2, t3; \ ++ ADDQ t2, h0; \ ++ ADCQ t3, h1; \ ++ ADCQ $0, h2 ++ ++// func update(state *[7]uint64, msg []byte) ++TEXT Β·update(SB), $0-32 ++ MOVQ state+0(FP), DI ++ MOVQ msg_base+8(FP), SI ++ MOVQ msg_len+16(FP), R15 ++ ++ MOVQ 0(DI), R8 // h0 ++ MOVQ 8(DI), R9 // h1 ++ MOVQ 16(DI), R10 // h2 ++ MOVQ 24(DI), R11 // r0 ++ MOVQ 32(DI), R12 // r1 ++ ++ CMPQ R15, $16 ++ JB bytes_between_0_and_15 ++ ++loop: ++ POLY1305_ADD(SI, R8, R9, R10) ++ ++multiply: ++ POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) ++ SUBQ $16, R15 ++ CMPQ R15, $16 ++ JAE loop ++ ++bytes_between_0_and_15: ++ TESTQ R15, R15 ++ JZ done ++ MOVQ $1, BX ++ XORQ CX, CX ++ XORQ R13, R13 ++ ADDQ R15, SI ++ ++flush_buffer: ++ SHLQ $8, BX, CX ++ SHLQ $8, BX ++ MOVB -1(SI), R13 ++ XORQ R13, BX ++ DECQ SI ++ DECQ R15 ++ JNZ flush_buffer ++ ++ ADDQ BX, R8 ++ ADCQ CX, R9 ++ ADCQ $0, R10 ++ MOVQ $16, R15 ++ JMP multiply ++ ++done: ++ MOVQ R8, 0(DI) ++ MOVQ R9, 8(DI) ++ MOVQ R10, 16(DI) ++ RET +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go +new file mode 100644 +index 00000000000000..e041da5ea3e7d0 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go +@@ -0,0 +1,309 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// This file provides the generic implementation of Sum and MAC. Other files ++// might provide optimized assembly implementations of some of this code. ++ ++package poly1305 ++ ++import "encoding/binary" ++ ++// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag ++// for a 64 bytes message is approximately ++// ++// s + m[0:16] * r⁴ + m[16:32] * rΒ³ + m[32:48] * rΒ² + m[48:64] * r mod 2¹³⁰ - 5 ++// ++// for some secret r and s. It can be computed sequentially like ++// ++// for len(msg) > 0: ++// h += read(msg, 16) ++// h *= r ++// h %= 2¹³⁰ - 5 ++// return h + s ++// ++// All the complexity is about doing performant constant-time math on numbers ++// larger than any available numeric type. ++ ++func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { ++ h := newMACGeneric(key) ++ h.Write(msg) ++ h.Sum(out) ++} ++ ++func newMACGeneric(key *[32]byte) macGeneric { ++ m := macGeneric{} ++ initialize(key, &m.macState) ++ return m ++} ++ ++// macState holds numbers in saturated 64-bit little-endian limbs. That is, ++// the value of [x0, x1, x2] is x[0] + x[1] * 2⁢⁴ + x[2] * 2¹²⁸. ++type macState struct { ++ // h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but ++ // can grow larger during and after rounds. It must, however, remain below ++ // 2 * (2¹³⁰ - 5). ++ h [3]uint64 ++ // r and s are the private key components. ++ r [2]uint64 ++ s [2]uint64 ++} ++ ++type macGeneric struct { ++ macState ++ ++ buffer [TagSize]byte ++ offset int ++} ++ ++// Write splits the incoming message into TagSize chunks, and passes them to ++// update. It buffers incomplete chunks. ++func (h *macGeneric) Write(p []byte) (int, error) { ++ nn := len(p) ++ if h.offset > 0 { ++ n := copy(h.buffer[h.offset:], p) ++ if h.offset+n < TagSize { ++ h.offset += n ++ return nn, nil ++ } ++ p = p[n:] ++ h.offset = 0 ++ updateGeneric(&h.macState, h.buffer[:]) ++ } ++ if n := len(p) - (len(p) % TagSize); n > 0 { ++ updateGeneric(&h.macState, p[:n]) ++ p = p[n:] ++ } ++ if len(p) > 0 { ++ h.offset += copy(h.buffer[h.offset:], p) ++ } ++ return nn, nil ++} ++ ++// Sum flushes the last incomplete chunk from the buffer, if any, and generates ++// the MAC output. It does not modify its state, in order to allow for multiple ++// calls to Sum, even if no Write is allowed after Sum. ++func (h *macGeneric) Sum(out *[TagSize]byte) { ++ state := h.macState ++ if h.offset > 0 { ++ updateGeneric(&state, h.buffer[:h.offset]) ++ } ++ finalize(out, &state.h, &state.s) ++} ++ ++// [rMask0, rMask1] is the specified Poly1305 clamping mask in little-endian. It ++// clears some bits of the secret coefficient to make it possible to implement ++// multiplication more efficiently. ++const ( ++ rMask0 = 0x0FFFFFFC0FFFFFFF ++ rMask1 = 0x0FFFFFFC0FFFFFFC ++) ++ ++// initialize loads the 256-bit key into the two 128-bit secret values r and s. ++func initialize(key *[32]byte, m *macState) { ++ m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 ++ m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 ++ m.s[0] = binary.LittleEndian.Uint64(key[16:24]) ++ m.s[1] = binary.LittleEndian.Uint64(key[24:32]) ++} ++ ++// uint128 holds a 128-bit number as two 64-bit limbs, for use with the ++// bits.Mul64 and bits.Add64 intrinsics. ++type uint128 struct { ++ lo, hi uint64 ++} ++ ++func mul64(a, b uint64) uint128 { ++ hi, lo := bitsMul64(a, b) ++ return uint128{lo, hi} ++} ++ ++func add128(a, b uint128) uint128 { ++ lo, c := bitsAdd64(a.lo, b.lo, 0) ++ hi, c := bitsAdd64(a.hi, b.hi, c) ++ if c != 0 { ++ panic("poly1305: unexpected overflow") ++ } ++ return uint128{lo, hi} ++} ++ ++func shiftRightBy2(a uint128) uint128 { ++ a.lo = a.lo>>2 | (a.hi&3)<<62 ++ a.hi = a.hi >> 2 ++ return a ++} ++ ++// updateGeneric absorbs msg into the state.h accumulator. For each chunk m of ++// 128 bits of message, it computes ++// ++// hβ‚Š = (h + m) * r mod 2¹³⁰ - 5 ++// ++// If the msg length is not a multiple of TagSize, it assumes the last ++// incomplete chunk is the final one. ++func updateGeneric(state *macState, msg []byte) { ++ h0, h1, h2 := state.h[0], state.h[1], state.h[2] ++ r0, r1 := state.r[0], state.r[1] ++ ++ for len(msg) > 0 { ++ var c uint64 ++ ++ // For the first step, h + m, we use a chain of bits.Add64 intrinsics. ++ // The resulting value of h might exceed 2¹³⁰ - 5, but will be partially ++ // reduced at the end of the multiplication below. ++ // ++ // The spec requires us to set a bit just above the message size, not to ++ // hide leading zeroes. For full chunks, that's 1 << 128, so we can just ++ // add 1 to the most significant (2¹²⁸) limb, h2. ++ if len(msg) >= TagSize { ++ h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0) ++ h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c) ++ h2 += c + 1 ++ ++ msg = msg[TagSize:] ++ } else { ++ var buf [TagSize]byte ++ copy(buf[:], msg) ++ buf[len(msg)] = 1 ++ ++ h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0) ++ h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c) ++ h2 += c ++ ++ msg = nil ++ } ++ ++ // Multiplication of big number limbs is similar to elementary school ++ // columnar multiplication. Instead of digits, there are 64-bit limbs. ++ // ++ // We are multiplying a 3 limbs number, h, by a 2 limbs number, r. ++ // ++ // h2 h1 h0 x ++ // r1 r0 = ++ // ---------------- ++ // h2r0 h1r0 h0r0 <-- individual 128-bit products ++ // + h2r1 h1r1 h0r1 ++ // ------------------------ ++ // m3 m2 m1 m0 <-- result in 128-bit overlapping limbs ++ // ------------------------ ++ // m3.hi m2.hi m1.hi m0.hi <-- carry propagation ++ // + m3.lo m2.lo m1.lo m0.lo ++ // ------------------------------- ++ // t4 t3 t2 t1 t0 <-- final result in 64-bit limbs ++ // ++ // The main difference from pen-and-paper multiplication is that we do ++ // carry propagation in a separate step, as if we wrote two digit sums ++ // at first (the 128-bit limbs), and then carried the tens all at once. ++ ++ h0r0 := mul64(h0, r0) ++ h1r0 := mul64(h1, r0) ++ h2r0 := mul64(h2, r0) ++ h0r1 := mul64(h0, r1) ++ h1r1 := mul64(h1, r1) ++ h2r1 := mul64(h2, r1) ++ ++ // Since h2 is known to be at most 7 (5 + 1 + 1), and r0 and r1 have their ++ // top 4 bits cleared by rMask{0,1}, we know that their product is not going ++ // to overflow 64 bits, so we can ignore the high part of the products. ++ // ++ // This also means that the product doesn't have a fifth limb (t4). ++ if h2r0.hi != 0 { ++ panic("poly1305: unexpected overflow") ++ } ++ if h2r1.hi != 0 { ++ panic("poly1305: unexpected overflow") ++ } ++ ++ m0 := h0r0 ++ m1 := add128(h1r0, h0r1) // These two additions don't overflow thanks again ++ m2 := add128(h2r0, h1r1) // to the 4 masked bits at the top of r0 and r1. ++ m3 := h2r1 ++ ++ t0 := m0.lo ++ t1, c := bitsAdd64(m1.lo, m0.hi, 0) ++ t2, c := bitsAdd64(m2.lo, m1.hi, c) ++ t3, _ := bitsAdd64(m3.lo, m2.hi, c) ++ ++ // Now we have the result as 4 64-bit limbs, and we need to reduce it ++ // modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do ++ // a cheap partial reduction according to the reduction identity ++ // ++ // c * 2¹³⁰ + n = c * 5 + n mod 2¹³⁰ - 5 ++ // ++ // because 2¹³⁰ = 5 mod 2¹³⁰ - 5. Partial reduction since the result is ++ // likely to be larger than 2¹³⁰ - 5, but still small enough to fit the ++ // assumptions we make about h in the rest of the code. ++ // ++ // See also https://speakerdeck.com/gtank/engineering-prime-numbers?slide=23 ++ ++ // We split the final result at the 2¹³⁰ mark into h and cc, the carry. ++ // Note that the carry bits are effectively shifted left by 2, in other ++ // words, cc = c * 4 for the c in the reduction identity. ++ h0, h1, h2 = t0, t1, t2&maskLow2Bits ++ cc := uint128{t2 & maskNotLow2Bits, t3} ++ ++ // To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c. ++ ++ h0, c = bitsAdd64(h0, cc.lo, 0) ++ h1, c = bitsAdd64(h1, cc.hi, c) ++ h2 += c ++ ++ cc = shiftRightBy2(cc) ++ ++ h0, c = bitsAdd64(h0, cc.lo, 0) ++ h1, c = bitsAdd64(h1, cc.hi, c) ++ h2 += c ++ ++ // h2 is at most 3 + 1 + 1 = 5, making the whole of h at most ++ // ++ // 5 * 2¹²⁸ + (2¹²⁸ - 1) = 6 * 2¹²⁸ - 1 ++ } ++ ++ state.h[0], state.h[1], state.h[2] = h0, h1, h2 ++} ++ ++const ( ++ maskLow2Bits uint64 = 0x0000000000000003 ++ maskNotLow2Bits uint64 = ^maskLow2Bits ++) ++ ++// select64 returns x if v == 1 and y if v == 0, in constant time. ++func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y } ++ ++// [p0, p1, p2] is 2¹³⁰ - 5 in little endian order. ++const ( ++ p0 = 0xFFFFFFFFFFFFFFFB ++ p1 = 0xFFFFFFFFFFFFFFFF ++ p2 = 0x0000000000000003 ++) ++ ++// finalize completes the modular reduction of h and computes ++// ++// out = h + s mod 2¹²⁸ ++func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) { ++ h0, h1, h2 := h[0], h[1], h[2] ++ ++ // After the partial reduction in updateGeneric, h might be more than ++ // 2¹³⁰ - 5, but will be less than 2 * (2¹³⁰ - 5). To complete the reduction ++ // in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the ++ // result if the subtraction underflows, and t otherwise. ++ ++ hMinusP0, b := bitsSub64(h0, p0, 0) ++ hMinusP1, b := bitsSub64(h1, p1, b) ++ _, b = bitsSub64(h2, p2, b) ++ ++ // h = h if h < p else h - p ++ h0 = select64(b, h0, hMinusP0) ++ h1 = select64(b, h1, hMinusP1) ++ ++ // Finally, we compute the last Poly1305 step ++ // ++ // tag = h + s mod 2¹²⁸ ++ // ++ // by just doing a wide addition with the 128 low bits of h and discarding ++ // the overflow. ++ h0, c := bitsAdd64(h0, s[0], 0) ++ h1, _ = bitsAdd64(h1, s[1], c) ++ ++ binary.LittleEndian.PutUint64(out[0:8], h0) ++ binary.LittleEndian.PutUint64(out[8:16], h1) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go +new file mode 100644 +index 00000000000000..4a069941a6ef9b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go +@@ -0,0 +1,48 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package poly1305 ++ ++//go:noescape ++func update(state *macState, msg []byte) ++ ++// mac is a wrapper for macGeneric that redirects calls that would have gone to ++// updateGeneric to update. ++// ++// Its Write and Sum methods are otherwise identical to the macGeneric ones, but ++// using function pointers would carry a major performance cost. ++type mac struct{ macGeneric } ++ ++func (h *mac) Write(p []byte) (int, error) { ++ nn := len(p) ++ if h.offset > 0 { ++ n := copy(h.buffer[h.offset:], p) ++ if h.offset+n < TagSize { ++ h.offset += n ++ return nn, nil ++ } ++ p = p[n:] ++ h.offset = 0 ++ update(&h.macState, h.buffer[:]) ++ } ++ if n := len(p) - (len(p) % TagSize); n > 0 { ++ update(&h.macState, p[:n]) ++ p = p[n:] ++ } ++ if len(p) > 0 { ++ h.offset += copy(h.buffer[h.offset:], p) ++ } ++ return nn, nil ++} ++ ++func (h *mac) Sum(out *[16]byte) { ++ state := h.macState ++ if h.offset > 0 { ++ update(&state, h.buffer[:h.offset]) ++ } ++ finalize(out, &state.h, &state.s) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s +new file mode 100644 +index 00000000000000..58422aad230570 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s +@@ -0,0 +1,182 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "textflag.h" ++ ++// This was ported from the amd64 implementation. ++ ++#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \ ++ MOVD (msg), t0; \ ++ MOVD 8(msg), t1; \ ++ MOVD $1, t2; \ ++ ADDC t0, h0, h0; \ ++ ADDE t1, h1, h1; \ ++ ADDE t2, h2; \ ++ ADD $16, msg ++ ++#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ ++ MULLD r0, h0, t0; \ ++ MULLD r0, h1, t4; \ ++ MULHDU r0, h0, t1; \ ++ MULHDU r0, h1, t5; \ ++ ADDC t4, t1, t1; \ ++ MULLD r0, h2, t2; \ ++ ADDZE t5; \ ++ MULHDU r1, h0, t4; \ ++ MULLD r1, h0, h0; \ ++ ADD t5, t2, t2; \ ++ ADDC h0, t1, t1; \ ++ MULLD h2, r1, t3; \ ++ ADDZE t4, h0; \ ++ MULHDU r1, h1, t5; \ ++ MULLD r1, h1, t4; \ ++ ADDC t4, t2, t2; \ ++ ADDE t5, t3, t3; \ ++ ADDC h0, t2, t2; \ ++ MOVD $-4, t4; \ ++ MOVD t0, h0; \ ++ MOVD t1, h1; \ ++ ADDZE t3; \ ++ ANDCC $3, t2, h2; \ ++ AND t2, t4, t0; \ ++ ADDC t0, h0, h0; \ ++ ADDE t3, h1, h1; \ ++ SLD $62, t3, t4; \ ++ SRD $2, t2; \ ++ ADDZE h2; \ ++ OR t4, t2, t2; \ ++ SRD $2, t3; \ ++ ADDC t2, h0, h0; \ ++ ADDE t3, h1, h1; \ ++ ADDZE h2 ++ ++DATA Β·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF ++DATA Β·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC ++GLOBL Β·poly1305Mask<>(SB), RODATA, $16 ++ ++// func update(state *[7]uint64, msg []byte) ++TEXT Β·update(SB), $0-32 ++ MOVD state+0(FP), R3 ++ MOVD msg_base+8(FP), R4 ++ MOVD msg_len+16(FP), R5 ++ ++ MOVD 0(R3), R8 // h0 ++ MOVD 8(R3), R9 // h1 ++ MOVD 16(R3), R10 // h2 ++ MOVD 24(R3), R11 // r0 ++ MOVD 32(R3), R12 // r1 ++ ++ CMP R5, $16 ++ BLT bytes_between_0_and_15 ++ ++loop: ++ POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) ++ ++multiply: ++ POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) ++ ADD $-16, R5 ++ CMP R5, $16 ++ BGE loop ++ ++bytes_between_0_and_15: ++ CMP R5, $0 ++ BEQ done ++ MOVD $0, R16 // h0 ++ MOVD $0, R17 // h1 ++ ++flush_buffer: ++ CMP R5, $8 ++ BLE just1 ++ ++ MOVD $8, R21 ++ SUB R21, R5, R21 ++ ++ // Greater than 8 -- load the rightmost remaining bytes in msg ++ // and put into R17 (h1) ++ MOVD (R4)(R21), R17 ++ MOVD $16, R22 ++ ++ // Find the offset to those bytes ++ SUB R5, R22, R22 ++ SLD $3, R22 ++ ++ // Shift to get only the bytes in msg ++ SRD R22, R17, R17 ++ ++ // Put 1 at high end ++ MOVD $1, R23 ++ SLD $3, R21 ++ SLD R21, R23, R23 ++ OR R23, R17, R17 ++ ++ // Remainder is 8 ++ MOVD $8, R5 ++ ++just1: ++ CMP R5, $8 ++ BLT less8 ++ ++ // Exactly 8 ++ MOVD (R4), R16 ++ ++ CMP R17, $0 ++ ++ // Check if we've already set R17; if not ++ // set 1 to indicate end of msg. ++ BNE carry ++ MOVD $1, R17 ++ BR carry ++ ++less8: ++ MOVD $0, R16 // h0 ++ MOVD $0, R22 // shift count ++ CMP R5, $4 ++ BLT less4 ++ MOVWZ (R4), R16 ++ ADD $4, R4 ++ ADD $-4, R5 ++ MOVD $32, R22 ++ ++less4: ++ CMP R5, $2 ++ BLT less2 ++ MOVHZ (R4), R21 ++ SLD R22, R21, R21 ++ OR R16, R21, R16 ++ ADD $16, R22 ++ ADD $-2, R5 ++ ADD $2, R4 ++ ++less2: ++ CMP R5, $0 ++ BEQ insert1 ++ MOVBZ (R4), R21 ++ SLD R22, R21, R21 ++ OR R16, R21, R16 ++ ADD $8, R22 ++ ++insert1: ++ // Insert 1 at end of msg ++ MOVD $1, R21 ++ SLD R22, R21, R21 ++ OR R16, R21, R16 ++ ++carry: ++ // Add new values to h0, h1, h2 ++ ADDC R16, R8 ++ ADDE R17, R9 ++ ADDZE R10, R10 ++ MOVD $16, R5 ++ ADD R5, R4 ++ BR multiply ++ ++done: ++ // Save h0, h1, h2 in state ++ MOVD R8, 0(R3) ++ MOVD R9, 8(R3) ++ MOVD R10, 16(R3) ++ RET +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go +new file mode 100644 +index 00000000000000..ec95966889691d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go +@@ -0,0 +1,77 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package poly1305 ++ ++import ( ++ "golang.org/x/sys/cpu" ++) ++ ++// updateVX is an assembly implementation of Poly1305 that uses vector ++// instructions. It must only be called if the vector facility (vx) is ++// available. ++// ++//go:noescape ++func updateVX(state *macState, msg []byte) ++ ++// mac is a replacement for macGeneric that uses a larger buffer and redirects ++// calls that would have gone to updateGeneric to updateVX if the vector ++// facility is installed. ++// ++// A larger buffer is required for good performance because the vector ++// implementation has a higher fixed cost per call than the generic ++// implementation. ++type mac struct { ++ macState ++ ++ buffer [16 * TagSize]byte // size must be a multiple of block size (16) ++ offset int ++} ++ ++func (h *mac) Write(p []byte) (int, error) { ++ nn := len(p) ++ if h.offset > 0 { ++ n := copy(h.buffer[h.offset:], p) ++ if h.offset+n < len(h.buffer) { ++ h.offset += n ++ return nn, nil ++ } ++ p = p[n:] ++ h.offset = 0 ++ if cpu.S390X.HasVX { ++ updateVX(&h.macState, h.buffer[:]) ++ } else { ++ updateGeneric(&h.macState, h.buffer[:]) ++ } ++ } ++ ++ tail := len(p) % len(h.buffer) // number of bytes to copy into buffer ++ body := len(p) - tail // number of bytes to process now ++ if body > 0 { ++ if cpu.S390X.HasVX { ++ updateVX(&h.macState, p[:body]) ++ } else { ++ updateGeneric(&h.macState, p[:body]) ++ } ++ } ++ h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0 ++ return nn, nil ++} ++ ++func (h *mac) Sum(out *[TagSize]byte) { ++ state := h.macState ++ remainder := h.buffer[:h.offset] ++ ++ // Use the generic implementation if we have 2 or fewer blocks left ++ // to sum. The vector implementation has a higher startup time. ++ if cpu.S390X.HasVX && len(remainder) > 2*TagSize { ++ updateVX(&state, remainder) ++ } else if len(remainder) > 0 { ++ updateGeneric(&state, remainder) ++ } ++ finalize(out, &state.h, &state.s) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s +new file mode 100644 +index 00000000000000..aa9e0494c909d8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s +@@ -0,0 +1,504 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "textflag.h" ++ ++// This implementation of Poly1305 uses the vector facility (vx) ++// to process up to 2 blocks (32 bytes) per iteration using an ++// algorithm based on the one described in: ++// ++// NEON crypto, Daniel J. Bernstein & Peter Schwabe ++// https://cryptojedi.org/papers/neoncrypto-20120320.pdf ++// ++// This algorithm uses 5 26-bit limbs to represent a 130-bit ++// value. These limbs are, for the most part, zero extended and ++// placed into 64-bit vector register elements. Each vector ++// register is 128-bits wide and so holds 2 of these elements. ++// Using 26-bit limbs allows us plenty of headroom to accommodate ++// accumulations before and after multiplication without ++// overflowing either 32-bits (before multiplication) or 64-bits ++// (after multiplication). ++// ++// In order to parallelise the operations required to calculate ++// the sum we use two separate accumulators and then sum those ++// in an extra final step. For compatibility with the generic ++// implementation we perform this summation at the end of every ++// updateVX call. ++// ++// To use two accumulators we must multiply the message blocks ++// by rΒ² rather than r. Only the final message block should be ++// multiplied by r. ++// ++// Example: ++// ++// We want to calculate the sum (h) for a 64 byte message (m): ++// ++// h = m[0:16]r⁴ + m[16:32]rΒ³ + m[32:48]rΒ² + m[48:64]r ++// ++// To do this we split the calculation into the even indices ++// and odd indices of the message. These form our SIMD 'lanes': ++// ++// h = m[ 0:16]r⁴ + m[32:48]rΒ² + <- lane 0 ++// m[16:32]rΒ³ + m[48:64]r <- lane 1 ++// ++// To calculate this iteratively we refactor so that both lanes ++// are written in terms of rΒ² and r: ++// ++// h = (m[ 0:16]rΒ² + m[32:48])rΒ² + <- lane 0 ++// (m[16:32]rΒ² + m[48:64])r <- lane 1 ++// ^ ^ ++// | coefficients for second iteration ++// coefficients for first iteration ++// ++// So in this case we would have two iterations. In the first ++// both lanes are multiplied by rΒ². In the second only the ++// first lane is multiplied by rΒ² and the second lane is ++// instead multiplied by r. This gives use the odd and even ++// powers of r that we need from the original equation. ++// ++// Notation: ++// ++// h - accumulator ++// r - key ++// m - message ++// ++// [a, b] - SIMD register holding two 64-bit values ++// [a, b, c, d] - SIMD register holding four 32-bit values ++// xα΅’[n] - limb n of variable x with bit width i ++// ++// Limbs are expressed in little endian order, so for 26-bit ++// limbs x₂₆[4] will be the most significant limb and x₂₆[0] ++// will be the least significant limb. ++ ++// masking constants ++#define MOD24 V0 // [0x0000000000ffffff, 0x0000000000ffffff] - mask low 24-bits ++#define MOD26 V1 // [0x0000000003ffffff, 0x0000000003ffffff] - mask low 26-bits ++ ++// expansion constants (see EXPAND macro) ++#define EX0 V2 ++#define EX1 V3 ++#define EX2 V4 ++ ++// key (rΒ², r or 1 depending on context) ++#define R_0 V5 ++#define R_1 V6 ++#define R_2 V7 ++#define R_3 V8 ++#define R_4 V9 ++ ++// precalculated coefficients (5rΒ², 5r or 0 depending on context) ++#define R5_1 V10 ++#define R5_2 V11 ++#define R5_3 V12 ++#define R5_4 V13 ++ ++// message block (m) ++#define M_0 V14 ++#define M_1 V15 ++#define M_2 V16 ++#define M_3 V17 ++#define M_4 V18 ++ ++// accumulator (h) ++#define H_0 V19 ++#define H_1 V20 ++#define H_2 V21 ++#define H_3 V22 ++#define H_4 V23 ++ ++// temporary registers (for short-lived values) ++#define T_0 V24 ++#define T_1 V25 ++#define T_2 V26 ++#define T_3 V27 ++#define T_4 V28 ++ ++GLOBL Β·constants<>(SB), RODATA, $0x30 ++// EX0 ++DATA Β·constants<>+0x00(SB)/8, $0x0006050403020100 ++DATA Β·constants<>+0x08(SB)/8, $0x1016151413121110 ++// EX1 ++DATA Β·constants<>+0x10(SB)/8, $0x060c0b0a09080706 ++DATA Β·constants<>+0x18(SB)/8, $0x161c1b1a19181716 ++// EX2 ++DATA Β·constants<>+0x20(SB)/8, $0x0d0d0d0d0d0f0e0d ++DATA Β·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d ++ ++// MULTIPLY multiplies each lane of f and g, partially reduced ++// modulo 2¹³⁰ - 5. The result, h, consists of partial products ++// in each lane that need to be reduced further to produce the ++// final result. ++// ++// h₁₃₀ = (f₁₃₀g₁₃₀) % 2¹³⁰ + (5f₁₃₀g₁₃₀) / 2¹³⁰ ++// ++// Note that the multiplication by 5 of the high bits is ++// achieved by precalculating the multiplication of four of the ++// g coefficients by 5. These are g51-g54. ++#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ ++ VMLOF f0, g0, h0 \ ++ VMLOF f0, g3, h3 \ ++ VMLOF f0, g1, h1 \ ++ VMLOF f0, g4, h4 \ ++ VMLOF f0, g2, h2 \ ++ VMLOF f1, g54, T_0 \ ++ VMLOF f1, g2, T_3 \ ++ VMLOF f1, g0, T_1 \ ++ VMLOF f1, g3, T_4 \ ++ VMLOF f1, g1, T_2 \ ++ VMALOF f2, g53, h0, h0 \ ++ VMALOF f2, g1, h3, h3 \ ++ VMALOF f2, g54, h1, h1 \ ++ VMALOF f2, g2, h4, h4 \ ++ VMALOF f2, g0, h2, h2 \ ++ VMALOF f3, g52, T_0, T_0 \ ++ VMALOF f3, g0, T_3, T_3 \ ++ VMALOF f3, g53, T_1, T_1 \ ++ VMALOF f3, g1, T_4, T_4 \ ++ VMALOF f3, g54, T_2, T_2 \ ++ VMALOF f4, g51, h0, h0 \ ++ VMALOF f4, g54, h3, h3 \ ++ VMALOF f4, g52, h1, h1 \ ++ VMALOF f4, g0, h4, h4 \ ++ VMALOF f4, g53, h2, h2 \ ++ VAG T_0, h0, h0 \ ++ VAG T_3, h3, h3 \ ++ VAG T_1, h1, h1 \ ++ VAG T_4, h4, h4 \ ++ VAG T_2, h2, h2 ++ ++// REDUCE performs the following carry operations in four ++// stages, as specified in Bernstein & Schwabe: ++// ++// 1: h₂₆[0]->h₂₆[1] h₂₆[3]->h₂₆[4] ++// 2: h₂₆[1]->h₂₆[2] h₂₆[4]->h₂₆[0] ++// 3: h₂₆[0]->h₂₆[1] h₂₆[2]->h₂₆[3] ++// 4: h₂₆[3]->h₂₆[4] ++// ++// The result is that all of the limbs are limited to 26-bits ++// except for h₂₆[1] and h₂₆[4] which are limited to 27-bits. ++// ++// Note that although each limb is aligned at 26-bit intervals ++// they may contain values that exceed 2²⁢ - 1, hence the need ++// to carry the excess bits in each limb. ++#define REDUCE(h0, h1, h2, h3, h4) \ ++ VESRLG $26, h0, T_0 \ ++ VESRLG $26, h3, T_1 \ ++ VN MOD26, h0, h0 \ ++ VN MOD26, h3, h3 \ ++ VAG T_0, h1, h1 \ ++ VAG T_1, h4, h4 \ ++ VESRLG $26, h1, T_2 \ ++ VESRLG $26, h4, T_3 \ ++ VN MOD26, h1, h1 \ ++ VN MOD26, h4, h4 \ ++ VESLG $2, T_3, T_4 \ ++ VAG T_3, T_4, T_4 \ ++ VAG T_2, h2, h2 \ ++ VAG T_4, h0, h0 \ ++ VESRLG $26, h2, T_0 \ ++ VESRLG $26, h0, T_1 \ ++ VN MOD26, h2, h2 \ ++ VN MOD26, h0, h0 \ ++ VAG T_0, h3, h3 \ ++ VAG T_1, h1, h1 \ ++ VESRLG $26, h3, T_2 \ ++ VN MOD26, h3, h3 \ ++ VAG T_2, h4, h4 ++ ++// EXPAND splits the 128-bit little-endian values in0 and in1 ++// into 26-bit big-endian limbs and places the results into ++// the first and second lane of d₂₆[0:4] respectively. ++// ++// The EX0, EX1 and EX2 constants are arrays of byte indices ++// for permutation. The permutation both reverses the bytes ++// in the input and ensures the bytes are copied into the ++// destination limb ready to be shifted into their final ++// position. ++#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ ++ VPERM in0, in1, EX0, d0 \ ++ VPERM in0, in1, EX1, d2 \ ++ VPERM in0, in1, EX2, d4 \ ++ VESRLG $26, d0, d1 \ ++ VESRLG $30, d2, d3 \ ++ VESRLG $4, d2, d2 \ ++ VN MOD26, d0, d0 \ // [in0₂₆[0], in1₂₆[0]] ++ VN MOD26, d3, d3 \ // [in0₂₆[3], in1₂₆[3]] ++ VN MOD26, d1, d1 \ // [in0₂₆[1], in1₂₆[1]] ++ VN MOD24, d4, d4 \ // [in0₂₆[4], in1₂₆[4]] ++ VN MOD26, d2, d2 // [in0₂₆[2], in1₂₆[2]] ++ ++// func updateVX(state *macState, msg []byte) ++TEXT Β·updateVX(SB), NOSPLIT, $0 ++ MOVD state+0(FP), R1 ++ LMG msg+8(FP), R2, R3 // R2=msg_base, R3=msg_len ++ ++ // load EX0, EX1 and EX2 ++ MOVD $Β·constants<>(SB), R5 ++ VLM (R5), EX0, EX2 ++ ++ // generate masks ++ VGMG $(64-24), $63, MOD24 // [0x00ffffff, 0x00ffffff] ++ VGMG $(64-26), $63, MOD26 // [0x03ffffff, 0x03ffffff] ++ ++ // load h (accumulator) and r (key) from state ++ VZERO T_1 // [0, 0] ++ VL 0(R1), T_0 // [h₆₄[0], h₆₄[1]] ++ VLEG $0, 16(R1), T_1 // [h₆₄[2], 0] ++ VL 24(R1), T_2 // [r₆₄[0], r₆₄[1]] ++ VPDI $0, T_0, T_2, T_3 // [h₆₄[0], r₆₄[0]] ++ VPDI $5, T_0, T_2, T_4 // [h₆₄[1], r₆₄[1]] ++ ++ // unpack h and r into 26-bit limbs ++ // note: h₆₄[2] may have the low 3 bits set, so h₂₆[4] is a 27-bit value ++ VN MOD26, T_3, H_0 // [h₂₆[0], r₂₆[0]] ++ VZERO H_1 // [0, 0] ++ VZERO H_3 // [0, 0] ++ VGMG $(64-12-14), $(63-12), T_0 // [0x03fff000, 0x03fff000] - 26-bit mask with low 12 bits masked out ++ VESLG $24, T_1, T_1 // [h₆₄[2]<<24, 0] ++ VERIMG $-26&63, T_3, MOD26, H_1 // [h₂₆[1], r₂₆[1]] ++ VESRLG $+52&63, T_3, H_2 // [h₂₆[2], r₂₆[2]] - low 12 bits only ++ VERIMG $-14&63, T_4, MOD26, H_3 // [h₂₆[1], r₂₆[1]] ++ VESRLG $40, T_4, H_4 // [h₂₆[4], r₂₆[4]] - low 24 bits only ++ VERIMG $+12&63, T_4, T_0, H_2 // [h₂₆[2], r₂₆[2]] - complete ++ VO T_1, H_4, H_4 // [h₂₆[4], r₂₆[4]] - complete ++ ++ // replicate r across all 4 vector elements ++ VREPF $3, H_0, R_0 // [r₂₆[0], r₂₆[0], r₂₆[0], r₂₆[0]] ++ VREPF $3, H_1, R_1 // [r₂₆[1], r₂₆[1], r₂₆[1], r₂₆[1]] ++ VREPF $3, H_2, R_2 // [r₂₆[2], r₂₆[2], r₂₆[2], r₂₆[2]] ++ VREPF $3, H_3, R_3 // [r₂₆[3], r₂₆[3], r₂₆[3], r₂₆[3]] ++ VREPF $3, H_4, R_4 // [r₂₆[4], r₂₆[4], r₂₆[4], r₂₆[4]] ++ ++ // zero out lane 1 of h ++ VLEIG $1, $0, H_0 // [h₂₆[0], 0] ++ VLEIG $1, $0, H_1 // [h₂₆[1], 0] ++ VLEIG $1, $0, H_2 // [h₂₆[2], 0] ++ VLEIG $1, $0, H_3 // [h₂₆[3], 0] ++ VLEIG $1, $0, H_4 // [h₂₆[4], 0] ++ ++ // calculate 5r (ignore least significant limb) ++ VREPIF $5, T_0 ++ VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r₂₆[1], 5r₂₆[1], 5r₂₆[1]] ++ VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r₂₆[2], 5r₂₆[2], 5r₂₆[2]] ++ VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r₂₆[3], 5r₂₆[3], 5r₂₆[3]] ++ VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r₂₆[4], 5r₂₆[4], 5r₂₆[4]] ++ ++ // skip rΒ² calculation if we are only calculating one block ++ CMPBLE R3, $16, skip ++ ++ // calculate rΒ² ++ MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, M_0, M_1, M_2, M_3, M_4) ++ REDUCE(M_0, M_1, M_2, M_3, M_4) ++ VGBM $0x0f0f, T_0 ++ VERIMG $0, M_0, T_0, R_0 // [r₂₆[0], r²₂₆[0], r₂₆[0], r²₂₆[0]] ++ VERIMG $0, M_1, T_0, R_1 // [r₂₆[1], r²₂₆[1], r₂₆[1], r²₂₆[1]] ++ VERIMG $0, M_2, T_0, R_2 // [r₂₆[2], r²₂₆[2], r₂₆[2], r²₂₆[2]] ++ VERIMG $0, M_3, T_0, R_3 // [r₂₆[3], r²₂₆[3], r₂₆[3], r²₂₆[3]] ++ VERIMG $0, M_4, T_0, R_4 // [r₂₆[4], r²₂₆[4], r₂₆[4], r²₂₆[4]] ++ ++ // calculate 5rΒ² (ignore least significant limb) ++ VREPIF $5, T_0 ++ VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r²₂₆[1], 5r₂₆[1], 5r²₂₆[1]] ++ VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r²₂₆[2], 5r₂₆[2], 5r²₂₆[2]] ++ VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r²₂₆[3], 5r₂₆[3], 5r²₂₆[3]] ++ VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r²₂₆[4], 5r₂₆[4], 5r²₂₆[4]] ++ ++loop: ++ CMPBLE R3, $32, b2 // 2 or fewer blocks remaining, need to change key coefficients ++ ++ // load next 2 blocks from message ++ VLM (R2), T_0, T_1 ++ ++ // update message slice ++ SUB $32, R3 ++ MOVD $32(R2), R2 ++ ++ // unpack message blocks into 26-bit big-endian limbs ++ EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) ++ ++ // add 2¹²⁸ to each message block value ++ VLEIB $4, $1, M_4 ++ VLEIB $12, $1, M_4 ++ ++multiply: ++ // accumulate the incoming message ++ VAG H_0, M_0, M_0 ++ VAG H_3, M_3, M_3 ++ VAG H_1, M_1, M_1 ++ VAG H_4, M_4, M_4 ++ VAG H_2, M_2, M_2 ++ ++ // multiply the accumulator by the key coefficient ++ MULTIPLY(M_0, M_1, M_2, M_3, M_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) ++ ++ // carry and partially reduce the partial products ++ REDUCE(H_0, H_1, H_2, H_3, H_4) ++ ++ CMPBNE R3, $0, loop ++ ++finish: ++ // sum lane 0 and lane 1 and put the result in lane 1 ++ VZERO T_0 ++ VSUMQG H_0, T_0, H_0 ++ VSUMQG H_3, T_0, H_3 ++ VSUMQG H_1, T_0, H_1 ++ VSUMQG H_4, T_0, H_4 ++ VSUMQG H_2, T_0, H_2 ++ ++ // reduce again after summation ++ // TODO(mundaym): there might be a more efficient way to do this ++ // now that we only have 1 active lane. For example, we could ++ // simultaneously pack the values as we reduce them. ++ REDUCE(H_0, H_1, H_2, H_3, H_4) ++ ++ // carry h[1] through to h[4] so that only h[4] can exceed 2²⁢ - 1 ++ // TODO(mundaym): in testing this final carry was unnecessary. ++ // Needs a proof before it can be removed though. ++ VESRLG $26, H_1, T_1 ++ VN MOD26, H_1, H_1 ++ VAQ T_1, H_2, H_2 ++ VESRLG $26, H_2, T_2 ++ VN MOD26, H_2, H_2 ++ VAQ T_2, H_3, H_3 ++ VESRLG $26, H_3, T_3 ++ VN MOD26, H_3, H_3 ++ VAQ T_3, H_4, H_4 ++ ++ // h is now < 2(2¹³⁰ - 5) ++ // Pack each lane in h₂₆[0:4] into hβ‚β‚‚β‚ˆ[0:1]. ++ VESLG $26, H_1, H_1 ++ VESLG $26, H_3, H_3 ++ VO H_0, H_1, H_0 ++ VO H_2, H_3, H_2 ++ VESLG $4, H_2, H_2 ++ VLEIB $7, $48, H_1 ++ VSLB H_1, H_2, H_2 ++ VO H_0, H_2, H_0 ++ VLEIB $7, $104, H_1 ++ VSLB H_1, H_4, H_3 ++ VO H_3, H_0, H_0 ++ VLEIB $7, $24, H_1 ++ VSRLB H_1, H_4, H_1 ++ ++ // update state ++ VSTEG $1, H_0, 0(R1) ++ VSTEG $0, H_0, 8(R1) ++ VSTEG $1, H_1, 16(R1) ++ RET ++ ++b2: // 2 or fewer blocks remaining ++ CMPBLE R3, $16, b1 ++ ++ // Load the 2 remaining blocks (17-32 bytes remaining). ++ MOVD $-17(R3), R0 // index of final byte to load modulo 16 ++ VL (R2), T_0 // load full 16 byte block ++ VLL R0, 16(R2), T_1 // load final (possibly partial) block and pad with zeros to 16 bytes ++ ++ // The Poly1305 algorithm requires that a 1 bit be appended to ++ // each message block. If the final block is less than 16 bytes ++ // long then it is easiest to insert the 1 before the message ++ // block is split into 26-bit limbs. If, on the other hand, the ++ // final message block is 16 bytes long then we append the 1 bit ++ // after expansion as normal. ++ MOVBZ $1, R0 ++ MOVD $-16(R3), R3 // index of byte in last block to insert 1 at (could be 16) ++ CMPBEQ R3, $16, 2(PC) // skip the insertion if the final block is 16 bytes long ++ VLVGB R3, R0, T_1 // insert 1 into the byte at index R3 ++ ++ // Split both blocks into 26-bit limbs in the appropriate lanes. ++ EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) ++ ++ // Append a 1 byte to the end of the second to last block. ++ VLEIB $4, $1, M_4 ++ ++ // Append a 1 byte to the end of the last block only if it is a ++ // full 16 byte block. ++ CMPBNE R3, $16, 2(PC) ++ VLEIB $12, $1, M_4 ++ ++ // Finally, set up the coefficients for the final multiplication. ++ // We have previously saved r and 5r in the 32-bit even indexes ++ // of the R_[0-4] and R5_[1-4] coefficient registers. ++ // ++ // We want lane 0 to be multiplied by rΒ² so that can be kept the ++ // same. We want lane 1 to be multiplied by r so we need to move ++ // the saved r value into the 32-bit odd index in lane 1 by ++ // rotating the 64-bit lane by 32. ++ VGBM $0x00ff, T_0 // [0, 0xffffffffffffffff] - mask lane 1 only ++ VERIMG $32, R_0, T_0, R_0 // [_, r²₂₆[0], _, r₂₆[0]] ++ VERIMG $32, R_1, T_0, R_1 // [_, r²₂₆[1], _, r₂₆[1]] ++ VERIMG $32, R_2, T_0, R_2 // [_, r²₂₆[2], _, r₂₆[2]] ++ VERIMG $32, R_3, T_0, R_3 // [_, r²₂₆[3], _, r₂₆[3]] ++ VERIMG $32, R_4, T_0, R_4 // [_, r²₂₆[4], _, r₂₆[4]] ++ VERIMG $32, R5_1, T_0, R5_1 // [_, 5r²₂₆[1], _, 5r₂₆[1]] ++ VERIMG $32, R5_2, T_0, R5_2 // [_, 5r²₂₆[2], _, 5r₂₆[2]] ++ VERIMG $32, R5_3, T_0, R5_3 // [_, 5r²₂₆[3], _, 5r₂₆[3]] ++ VERIMG $32, R5_4, T_0, R5_4 // [_, 5r²₂₆[4], _, 5r₂₆[4]] ++ ++ MOVD $0, R3 ++ BR multiply ++ ++skip: ++ CMPBEQ R3, $0, finish ++ ++b1: // 1 block remaining ++ ++ // Load the final block (1-16 bytes). This will be placed into ++ // lane 0. ++ MOVD $-1(R3), R0 ++ VLL R0, (R2), T_0 // pad to 16 bytes with zeros ++ ++ // The Poly1305 algorithm requires that a 1 bit be appended to ++ // each message block. If the final block is less than 16 bytes ++ // long then it is easiest to insert the 1 before the message ++ // block is split into 26-bit limbs. If, on the other hand, the ++ // final message block is 16 bytes long then we append the 1 bit ++ // after expansion as normal. ++ MOVBZ $1, R0 ++ CMPBEQ R3, $16, 2(PC) ++ VLVGB R3, R0, T_0 ++ ++ // Set the message block in lane 1 to the value 0 so that it ++ // can be accumulated without affecting the final result. ++ VZERO T_1 ++ ++ // Split the final message block into 26-bit limbs in lane 0. ++ // Lane 1 will be contain 0. ++ EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) ++ ++ // Append a 1 byte to the end of the last block only if it is a ++ // full 16 byte block. ++ CMPBNE R3, $16, 2(PC) ++ VLEIB $4, $1, M_4 ++ ++ // We have previously saved r and 5r in the 32-bit even indexes ++ // of the R_[0-4] and R5_[1-4] coefficient registers. ++ // ++ // We want lane 0 to be multiplied by r so we need to move the ++ // saved r value into the 32-bit odd index in lane 0. We want ++ // lane 1 to be set to the value 1. This makes multiplication ++ // a no-op. We do this by setting lane 1 in every register to 0 ++ // and then just setting the 32-bit index 3 in R_0 to 1. ++ VZERO T_0 ++ MOVD $0, R0 ++ MOVD $0x10111213, R12 ++ VLVGP R12, R0, T_1 // [_, 0x10111213, _, 0x00000000] ++ VPERM T_0, R_0, T_1, R_0 // [_, r₂₆[0], _, 0] ++ VPERM T_0, R_1, T_1, R_1 // [_, r₂₆[1], _, 0] ++ VPERM T_0, R_2, T_1, R_2 // [_, r₂₆[2], _, 0] ++ VPERM T_0, R_3, T_1, R_3 // [_, r₂₆[3], _, 0] ++ VPERM T_0, R_4, T_1, R_4 // [_, r₂₆[4], _, 0] ++ VPERM T_0, R5_1, T_1, R5_1 // [_, 5r₂₆[1], _, 0] ++ VPERM T_0, R5_2, T_1, R5_2 // [_, 5r₂₆[2], _, 0] ++ VPERM T_0, R5_3, T_1, R5_3 // [_, 5r₂₆[3], _, 0] ++ VPERM T_0, R5_4, T_1, R5_4 // [_, 5r₂₆[4], _, 0] ++ ++ // Set the value of lane 1 to be 1. ++ VLEIF $3, $1, R_0 // [_, r₂₆[0], _, 1] ++ ++ MOVD $0, R3 ++ BR multiply +diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go b/ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go +new file mode 100644 +index 00000000000000..4788950f19c710 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go +@@ -0,0 +1,3000 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package poly1305 ++ ++var testData = [...]test{ ++ // edge cases ++ { ++ // see https://go-review.googlesource.com/#/c/30101/ ++ key: "3b3a29e93b213a5c5c3b3b053a3a8c0d00000000000000000000000000000000", ++ tag: "6dc18b8c344cd79927118bbe84b7f314", ++ in: "81d8b2e46a25213b58fee4213a2a28e921c12a9632516d3b73272727becf2129", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "04000000000000000000000000000000", // (2¹³⁰-1) % (2¹³⁰-5) ++ in: "ffffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "faffffffffffffffffffffffffffffff", // (2¹³⁰-6) % (2¹³⁰-5) ++ in: "faffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", // (2¹³⁰-5) % (2¹³⁰-5) ++ in: "fbffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "f9ffffffffffffffffffffffffffffff", // (2*(2¹³⁰-6)) % (2¹³⁰-5) ++ in: "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", // (2*(2¹³⁰-5)) % (2¹³⁰-5) ++ in: "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "f8ffffffffffffffffffffffffffffff", // (3*(2¹³⁰-6)) % (2¹³⁰-5) ++ in: "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", // (3*(2¹³⁰-5)) % (2¹³⁰-5) ++ in: "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "f7ffffffffffffffffffffffffffffff", // (4*(2¹³⁰-6)) % (2¹³⁰-5) ++ in: "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", // (4*(2¹³⁰-5)) % (2¹³⁰-5) ++ in: "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "f3ffffffffffffffffffffffffffffff", // (8*(2¹³⁰-6)) % (2¹³⁰-5) ++ in: "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", // (8*(2¹³⁰-5)) % (2¹³⁰-5) ++ in: "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "ebffffffffffffffffffffffffffffff", // (16*(2¹³⁰-6)) % (2¹³⁰-5) ++ in: "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "faffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ { ++ key: "0100000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", // (16*(2¹³⁰-5)) % (2¹³⁰-5) ++ in: "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "fbffffffffffffffffffffffffffffff" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000" + ++ "00000000000000000000000000000000", ++ }, ++ // original smoke tests ++ { ++ key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", ++ tag: "a6f745008f81c916a20dcc74eef2b2f0", ++ in: "48656c6c6f20776f726c6421", ++ }, ++ { ++ key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", ++ tag: "49ec78090e481ec6c26b33b91ccc0307", ++ in: "0000000000000000000000000000000000000000000000000000000000000000", ++ }, ++ { ++ key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", ++ tag: "da84bcab02676c38cdb015604274c2aa", ++ in: "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000", ++ }, ++ { ++ key: "0000000000000000000000000000000000000000000000000000000000000000", ++ tag: "00000000000000000000000000000000", ++ in: "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000000000" + ++ "000000000000000000000000000000000000000000000000000000", ++ }, ++ // randomly generated ++ { ++ key: "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649", ++ tag: "9566c74d10037c4d7bbb0407d1e2c649", ++ in: "", ++ }, ++ { ++ key: "81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f6999", ++ tag: "eaa270caaa12faa39b797374a4b8a420", ++ in: "eb", ++ }, ++ { ++ key: "9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f15f", ++ tag: "dbea66e1da48a8f822887c6162c2acf1", ++ in: "b90b", ++ }, ++ { ++ key: "adb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621632525", ++ tag: "6ac09aaa88c32ee95a7198376f16abdb", ++ in: "3fec73", ++ }, ++ { ++ key: "8dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d20bf505987592", ++ tag: "b1443487f97fe340b04a74719ed4de68", ++ in: "1e668a5b", ++ }, ++ { ++ key: "df2c7fc4844592d2572bcd0668d2d6c52f5054e2d0836bf84c7174cb7476364c", ++ tag: "7463be0f9d99a5348039e4afcbf4019c", ++ in: "c3dbd968b0", ++ }, ++ { ++ key: "f7172ed85794bb358b0c3b525da1786f9fff094279db1944ebd7a19d0f7bbacb", ++ tag: "2edaee3bcf303fd05609e131716f8157", ++ in: "e0255aa5b7d4", ++ }, ++ { ++ key: "4bec40f84c892b9bffd43629b0223beea5f4f74391f445d15afd4294040374f6", ++ tag: "965f18767420c1d94a4ef657e8d15e1e", ++ in: "924b98cbf8713f", ++ }, ++ { ++ key: "8d962d7c8d019192c24224e2cafccae3a61fb586b14323a6bc8f9e7df1d92933", ++ tag: "2bf4a33287dd6d87e1ed4282f7342b6a", ++ in: "3ff993933bea6f5b", ++ }, ++ { ++ key: "3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c7215a3", ++ tag: "c5e987b60373a48893c5af30acf2471f", ++ in: "b539eb1e5849c6077d", ++ }, ++ { ++ key: "bb5722f5717a289a266f97647981998ebea89c0b4b373970115e82ed6f4125c8", ++ tag: "19f0f640b309d168ea1b480e6a4faee5", ++ in: "fa7311e4d7defa922daa", ++ }, ++ { ++ key: "e7786667f7e936cd4f24abf7df866baa56038367ad6145de1ee8f4a8b0993ebd", ++ tag: "de75e5565d97834b9fa84ad568d31359", ++ in: "f8883a0ad8be9c3978b048", ++ }, ++ { ++ key: "83e56a156a8de563afa467d49dec6a40e9a1d007f033c2823061bdd0eaa59f8e", ++ tag: "de184a5a9b826aa203c5c017986d6690", ++ in: "4da6430105220d0b29688b73", ++ }, ++ { ++ key: "4b8ea0f3ca9936e8461f10d77c96ea80a7a665f606f6a63b7f3dfd2567c18979", ++ tag: "7478f18d9684905aa5d1a34ee67e4c84", ++ in: "e4d60f26686d9bf2fb26c901ff", ++ }, ++ { ++ key: "354cde1607ee294b39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be89904341", ++ tag: "3b2008a9c52b5308f5538b789ab5506f", ++ in: "79d3af4491a369012db92d184fc3", ++ }, ++ { ++ key: "9d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7649c6c93478009", ++ tag: "71c8e76a67a505b7370b562ba15ba032", ++ in: "79d1830356f2a54c3deab2a4b4475d", ++ }, ++ { ++ key: "63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924ae", ++ tag: "1dc895f74f866bdb3edf6c4430829c1c", ++ in: "f78ae151c00755925836b7075885650c", ++ }, ++ { ++ key: "30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752b3b827", ++ tag: "afca2b3ba7b0e1a928001966883e9b16", ++ in: "1d03e944b3c9db366b75045f8efd69d22ae5411947cb553d7694267aef4e" + ++ "bcea406b32d6108bd68584f57e37caac6e33feaa3263a399437024ba9c9b" + ++ "14678a274f01a910ae295f6efbfe5f5abf44ccde263b5606633e2bf0006f" + ++ "28295d7d39069f01a239c4365854c3af7f6b41d631f92b9a8d12f4125732" + ++ "5fff332f7576b0620556304a3e3eae14c28d0cea39d2901a52720da85ca1" + ++ "e4b38eaf3f", ++ }, ++ { ++ key: "44c6c6ef8362f2f54fc00e09d6fc25640854c15dfcacaa8a2cecce5a3aba53ab", ++ tag: "6f2a09aa76c9b76774e31ec02dcf7991", ++ in: "705b18db94b4d338a5143e63408d8724b0cf3fae17a3f79be1072fb63c35" + ++ "d6042c4160f38ee9e2a9f3fb4ffb0019b454d522b5ffa17604193fb89667" + ++ "10a7960732ca52cf53c3f520c889b79bf504cfb57c7601232d589baccea9" + ++ "d6e263e25c27741d3f6c62cbbb15d9afbcbf7f7da41ab0408e3969c2e2cd" + ++ "cf233438bf1774ace7709a4f091e9a83fdeae0ec55eb233a9b5394cb3c78" + ++ "56b546d313c8a3b4c1c0e05447f4ba370eb36dbcfdec90b302dcdc3b9ef5" + ++ "22e2a6f1ed0afec1f8e20faabedf6b162e717d3a748a58677a0c56348f89" + ++ "21a266b11d0f334c62fe52ba53af19779cb2948b6570ffa0b773963c130a" + ++ "d797ddea", ++ }, ++ { ++ key: "fe4e3ad29b5125210f0ef1c314090f07c79a6f571c246f3e9ac0b7413ef110bd", ++ tag: "27381e3fc2a356103fb796f107d826e7", ++ in: "58b00ce73bff706f7ff4b6f44090a32711f3208e4e4b89cb5165ce64002c" + ++ "bd9c2887aa113df2468928d5a23b9ca740f80c9382d9c6034ad2960c7965" + ++ "03e1ce221725f50caf1fbfe831b10b7bf5b15c47a53dbf8e7dcafc9e1386" + ++ "47a4b44ed4bce964ed47f74aa594468ced323cb76f0d3fac476c9fb03fc9" + ++ "228fbae88fd580663a0454b68312207f0a3b584c62316492b49753b5d502" + ++ "7ce15a4f0a58250d8fb50e77f2bf4f0152e5d49435807f9d4b97be6fb779" + ++ "70466a5626fe33408cf9e88e2c797408a32d29416baf206a329cfffd4a75" + ++ "e498320982c85aad70384859c05a4b13a1d5b2f5bfef5a6ed92da482caa9" + ++ "568e5b6fe9d8a9ddd9eb09277b92cef9046efa18500944cbe800a0b1527e" + ++ "a6", ++ }, ++ { ++ key: "4729a861d2f6497a3235c37f4192779ec1d96b3b1c5424fce0b727b03072e641", ++ tag: "0173965669fb9de88d38a827a0271271", ++ in: "5a761f03abaa40abc9448fddeb2191d945c04767af847afd0edb5d8857b7" + ++ "99acb18e4affabe3037ffe7fa68aa8af5e39cc416e734d373c5ebebc9cdc" + ++ "c595bcce3c7bd3d8df93fab7e125ddebafe65a31bd5d41e2d2ce9c2b1789" + ++ "2f0fea1931a290220777a93143dfdcbfa68406e877073ff08834e197a403" + ++ "4aa48afa3f85b8a62708caebbac880b5b89b93da53810164402104e648b6" + ++ "226a1b78021851f5d9ac0f313a89ddfc454c5f8f72ac89b38b19f53784c1" + ++ "9e9beac03c875a27db029de37ae37a42318813487685929359ca8c5eb94e" + ++ "152dc1af42ea3d1676c1bdd19ab8e2925c6daee4de5ef9f9dcf08dfcbd02" + ++ "b80809398585928a0f7de50be1a6dc1d5768e8537988fddce562e9b948c9" + ++ "18bba3e933e5c400cde5e60c5ead6fc7ae77ba1d259b188a4b21c86fbc23" + ++ "d728b45347eada650af24c56d0800a8691332088a805bd55c446e25eb075" + ++ "90bafcccbec6177536401d9a2b7f512b54bfc9d00532adf5aaa7c3a96bc5" + ++ "9b489f77d9042c5bce26b163defde5ee6a0fbb3e9346cef81f0ae9515ef3" + ++ "0fa47a364e75aea9e111d596e685a591121966e031650d510354aa845580" + ++ "ff560760fd36514ca197c875f1d02d9216eba7627e2398322eb5cf43d72b" + ++ "d2e5b887d4630fb8d4747ead6eb82acd1c5b078143ee26a586ad23139d50" + ++ "41723470bf24a865837c", ++ }, ++ { ++ key: "9123461c41f5ff99aa99ce24eb4d788576e3336e65491622558fdf297b9fa007", ++ tag: "1eb0cdad9237905250d30a24fe172a34", ++ in: "864bafd7cd4ca1b2fb5766ab431a032b72b9a7e937ed648d0801f29055d3" + ++ "090d2463718254f9442483c7b98b938045da519843854b0ed3f7ba951a49" + ++ "3f321f0966603022c1dfc579b99ed9d20d573ad53171c8fef7f1f4e4613b" + ++ "b365b2ebb44f0ffb6907136385cdc838f0bdd4c812f042577410aca008c2" + ++ "afbc4c79c62572e20f8ed94ee62b4de7aa1cc84c887e1f7c31e927dfe52a" + ++ "5f8f46627eb5d3a4fe16fafce23623e196c9dfff7fbaff4ffe94f4589733" + ++ "e563e19d3045aad3e226488ac02cca4291aed169dce5039d6ab00e40f67a" + ++ "ab29332de1448b35507c7c8a09c4db07105dc31003620405da3b2169f5a9" + ++ "10c9d0096e5e3ef1b570680746acd0cc7760331b663138d6d342b051b5df" + ++ "410637cf7aee9b0c8c10a8f9980630f34ce001c0ab7ac65e502d39b216cb" + ++ "c50e73a32eaf936401e2506bd8b82c30d346bc4b2fa319f245a8657ec122" + ++ "eaf4ad5425c249ee160e17b95541c2aee5df820ac85de3f8e784870fd87a" + ++ "36cc0d163833df636613a9cc947437b6592835b9f6f4f8c0e70dbeebae7b" + ++ "14cdb9bc41033aa5baf40d45e24d72eac4a28e3ca030c9937ab8409a7cbf" + ++ "05ae21f97425254543d94d115900b90ae703b97d9856d2441d14ba49a677" + ++ "de8b18cb454b99ddd9daa7ccbb7500dae4e2e5df8cf3859ebddada6745fb" + ++ "a6a04c5c37c7ca35036f11732ce8bc27b48868611fc73c82a491bfabd7a1" + ++ "9df50fdc78a55dbbc2fd37f9296566557fab885b039f30e706f0cd5961e1" + ++ "9b642221db44a69497b8ad99408fe1e037c68bf7c5e5de1d2c68192348ec" + ++ "1189fb2e36973cef09ff14be23922801f6eaee41409158b45f2dec82d17c" + ++ "aaba160cd6", ++ }, ++ { ++ key: "40ff73495fe4a05ce1202ca7287ed3235b95e69f571fa5e656aaa51fae1ebdd7", ++ tag: "2e619d8ea81b77484e4fddeb29844e4b", ++ in: "aa6269c2ec7f4057b33593bc84888c970fd528d4a99a1eab9d2420134537" + ++ "cd6d02282e0981e140232a4a87383a21d1845c408ad757043813032a0bd5" + ++ "a30dcca6e3aa2df04715d879279a96879a4f3690ac2025a60c7db15e0501" + ++ "ebc34b734355fe4a059bd3899d920e95f1c46d432f9b08e64d7f9b38965d" + ++ "5a77a7ac183c3833e1a3425ead69d4f975012fd1a49ed832f69e6e9c63b4" + ++ "53ec049c9e7a5cf944232d10353f64434abae060f6506ad3fdb1f4415b0a" + ++ "f9ce8c208bc20ee526741539fa3203c77ecba410fd6718f227e0b430f9bc" + ++ "b049a3d38540dc222969120ce80f2007cd42a708a721aa29987b45d4e428" + ++ "811984ecad349cc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b65" + ++ "2b69ccb092e55a20f1b9f97d046296124621928739a86671cc180152b953" + ++ "e3bf9d19f825c3dd54ae1688e49efb5efe65dcdad34bc860010e7c8c997c" + ++ "d5f9e320ca7d39d4ba801a175b1c76f057832f3f36d7d893e216e4c7bbdb" + ++ "548d0ba48449330027368b34f9c69776b4591532da1c5be68ef4eebe8cb8" + ++ "fa7dc5483fb70c2c896334cb1f9cb5dfe044fa086197ff5dfd02f2ba3884" + ++ "c53dd718c8560da743a8e9d4aeae20ccef002d82ca352592b8d8f2a8df3b" + ++ "0c35f15b9b370dca80d4ca8e9a133eb52094f2dd5c08731f52315d828846" + ++ "e37df68fd10658b480f2ac84233633957e688e924ffe3713b52c76fd8a56" + ++ "da8bb07daa8eb4eb8f7334f99256e2766a4109150eed424f0f743543cdea" + ++ "66e5baaa03edc918e8305bb19fc0c6b4ddb4aa3886cb5090940fc6d4cabe" + ++ "2153809e4ed60a0e2af07f1b2a6bb5a6017a578a27cbdc20a1759f76b088" + ++ "9a83ce25ce3ca91a4eb5c2f8580819da04d02c41770c01746de44f3db6e3" + ++ "402e7873db7635516e87b33e4b412ba3df68544920f5ea27ec097710954f" + ++ "42158bdba66d4814c064b4112538676095467c89ba98e6a543758d7093a4" + ++ "94df", ++ }, ++ { ++ key: "5cc36d09c7a6472a41f29c380a987b1ecdcf84765f4e5d3ceefc1c02181f570f", ++ tag: "0d57b8cbea8090df0541354673dcb4e0", ++ in: "44fcd629f08dc1ef53c9ae0d8869fe67fdc7a2c67b425f13c5be8d9f630c" + ++ "1d063c02fd75cf64c1aec9d2e2ef6e6431d5f5ad0489078dc61f46494dcc" + ++ "f403dad7f094170d2c3e29c198b0f341e284c4be8fa60c1a478d6bd55dd2" + ++ "c04dad86d2053d5d25b014e3d8b64322cdcb5004faa46cfa2d6ad2ff933b" + ++ "c3bd9a5a74660af3d048a9a43634c0250427d9a6219197a3f3633f841753" + ++ "ba7c27f3619f387b6b1a6cb9c1dc227674aa020724d137da2cb87b1615d5" + ++ "12974fa4747dd1e17d02c9462a44fec150ca3a8f99cc1e4953365e429956" + ++ "5e108535b1f62e1d4ba18e17a52164418bfd1a933f7fb3a126c860830a87" + ++ "293d9271da736e4398c1e37fb75c4bf02786e1faf4b610cd1377fbb9ae18" + ++ "0655a0abefbad700c09473469f1eca5a66d53fa3dc7cd3e7c3b0411d7e14" + ++ "5f96eb9654ab94913dda503a50f9e773842f4d2a5faa60869bf365830511" + ++ "f2ededd03e0a73000edb60c9a29a5f5e194cf3b5667a694690384599d116" + ++ "f8d2fd93b2aed55b7d44b5b054f3f38e788e4fdf36e591568c41d1052cad" + ++ "0fcb68ca4c4bf5090d57df9db6f0d91dd8b11b804f331adb7efb087a5604" + ++ "e9e22b4d54db40bcbc6e272ff5eaddfc1471459e59f0554c58251342134a" + ++ "8daaef1498069ba581ef1da2510be92843487a4eb8111c79a6f0195fc38a" + ++ "d6aee93c1df2b5897eaa38ad8f47ab2fe0e3aa3e6accbfd4c16d46843318" + ++ "5fc61c861b96ca65e34d31f24d6f56ee85092314a4d7656205c15322f1c9" + ++ "7613c079eae292ba966e10d1e700164e518b243f424c46f9ea63db1c2c34" + ++ "b512c403c128ee19030a6226517b805a072512a5e4cd274b7fd1fa23f830" + ++ "058208ff1a063b41039c74036b5b3da8b1a0b93135a710352da0f6c31203" + ++ "a09d1f2329651bb3ab3984ab591f2247e71cd44835e7a1a1b66d8595f7ae" + ++ "f9bf39d1417d2d31ea3599d405ff4b5999a86f52f3259b452909b57937d8" + ++ "5364d6c23deb4f14e0d9fcee9184df5994fdc11f045c025c8d561adb0e7d" + ++ "fd4748fd4b20f84e53322471a410cdb3fd88e48b2e7eb7ae5dae994cb5ea" + ++ "e3eaf21cf9005db560d6d22e4d9b97d7e9e488751afcd72aa176c0fcde93" + ++ "16f676fd527d9c42105b851639f09ea70533d26fc60cbeb4b76ed554fc99" + ++ "177620b28ca6f56a716f8cb384", ++ }, ++ { ++ key: "811c3e356e7c793acf114c624dc86ace38e67bff2a60e5b2a6c20723c1b9f003", ++ tag: "c6e59044cefc43ee681c3eed872d02b3", ++ in: "e115b304c023792448794546a2474f04294d7a616215e5dd6c40a65bb6ed" + ++ "b508c3680b14c176c327fdfb1ee21962c0006b7deb4e5de87db21989d13c" + ++ "3ab0462d5d2a52ef4ca0d366ae06a314f50e3a21d9247f814037798cc5e1" + ++ "0a63de027477decdeb8a8e0c279299272490106ddf8683126f60d35772c6" + ++ "dfc744b0adbfd5dcf118c4f2b06cfaf077881d733a5e643b7c46976647d1" + ++ "c1d3f8f6237c6218fa86fb47080b1f7966137667bd6661660c43b75b6339" + ++ "0b514bbe491aa46b524bde1c5b7456255fb214c3f74907b7ce1cba94210b" + ++ "78b5e68f049fcb002b96a5d38d59df6e977d587abb42d0972d5f3ffc898b" + ++ "3cbec26f104255761aee1b8a232d703585dd276ee1f43c8cd7e92a993eb1" + ++ "5107d02f59ba75f8dd1442ee37786ddb902deb88dd0ebdbf229fb25a9dca" + ++ "86d0ce46a278a45f5517bff2c049cc959a227dcdd3aca677e96ce84390e9" + ++ "b9a28e0988777331847a59f1225b027a66c1421422683dd6081af95e16f2" + ++ "48ab03da494112449ce7bdace6c988292f95699bb5e4d9c8d250aa28a6df" + ++ "44c0c265156deb27e9476a0a4af44f34bdf631b4af1146afe34ea988fc95" + ++ "3e71fc21ce60b3962313000fe46d757109281f6e55bc950200d0834ceb5c" + ++ "41553afd12576f3fbb9a8e05883ccc51c9a1269b6d8e9d27123dce5d0bd6" + ++ "db649c6fea06b4e4e9dea8d2d17709dc50ae8aa38231fd409e9580e255fe" + ++ "2bf59e6e1b6e310610ea4881206262be76120d6c97db969e003947f08bad" + ++ "8fa731f149397c47d2c964e84f090e77e19046277e18cd8917c48a776c9d" + ++ "e627b6656203b522c60e97cc61914621c564243913ae643f1c9c9e0ad00a" + ++ "14f66eaa45844229ecc35abb2637317ae5d5e338c68691bea8fa1fd469b7" + ++ "b54d0fccd730c1284ec7e6fccdec800b8fa67e6e55ac574f1e53a65ab976" + ++ "4c218a404184793cc9892308e296b334c85f7097edc16927c2451c4cd7e5" + ++ "3f239aa4f4c83241bde178f692898b1ece2dbcb19a97e64c4710326528f2" + ++ "4b099d0b674bd614fad307d9b9440adab32117f0f15b1450277b00eb366e" + ++ "0260fca84c1d27e50a1116d2ce16c8f5eb212c77c1a84425744ea3195edb" + ++ "b54c970b77e090b644942d43fe8c4546a158bad7620217a40e34b9bb84d1" + ++ "89eff32b20ef3f015714dbb1f150015d6eeb84cbccbd3fffa63bde89", ++ }, ++ { ++ key: "f33691f5db2dea41e1e608af3ff39f3a6988dba204ce1b09214475ae0ea864b8", ++ tag: "6e50e70411201378c8d67857d7b631d2", ++ in: "439bc9ea10db4d2b08c7fcf2e8bd89fa9844f8061d462e28f174489e7514" + ++ "0f84e842040141cc59ce38f9551850cfbdfac2d75337d155090d70d0d930" + ++ "04340bdfe60062f17c53f3c9005b9995a0feb49f6bef8eaff80f4feb7ef3" + ++ "f2181733a4b43b6ac43a5130a73a9b3c2cbc93bd296cd5f48c9df022b6c8" + ++ "2bb752bc21e3d8379be31328aa32edc11efc8a4b4b3f370ee8c870cd281d" + ++ "614e6bc2c0a5ca303bc48696a3bd574ee34738de4c4c29910f8feb7557bf" + ++ "ffcfe7428b4703144bd6d7fe5b3f5de748918553df5453b3c6001696f3de" + ++ "0137e454aadf30cedfb6be36b0b908a38409f1a2dc202fc285610765e4c8" + ++ "6414692bf4bde20ed899e97727b7ea1d95d7c621717c560f1d260ab3624e" + ++ "d6168d77c483dd5ce0d234049017795f2e5a7569d7ad323c50a5b1170337" + ++ "4174a9977026c20cd52c10b72f14e0569a684a3dcf2ccbc148fd3db506e2" + ++ "8d24f6c55544cb3980a36e86747adc89ebad78d1630618d113fa445f8625" + ++ "b583cd7be33913c30c419d047cf3baf40fd05219a1fcec717b87a65fa022" + ++ "1a3aa8143062d77588168019454240ae3d37640996f2967810459bc658df" + ++ "e556de4d07263dc3d9158ec242008226d1c6aea7f0846e12ce2d316e80da" + ++ "522343264ec9451ec23aaaa367d640faad4af3d44d6d86544ade34c93518" + ++ "2843f6b4d1c934996778affa9ee962e7dfef5e70d933d4309f0f343e9606" + ++ "1b91b11ac380a9675e17a96099fe411bedc28a298cd78d5496e28fbbd4f5" + ++ "b0a27735d1144348e22be5b75724d8f125e99c4cb4e9c3a1f0b4e9da5146" + ++ "e6afaa33d02fda74bf58a8badee2b634b989c01755afa6ab20ee494c6ae4" + ++ "c2c6f17af6b53b61d2947d83a18eb3b8a1612aad5d3ea7e8e35f325c9168" + ++ "ac490f22cb713ddb61fbd96011c5849ac8e2fcd42db820349bdf9157dcc0" + ++ "0d9f9ed9c099b10c7194d48b623b0df43759734b2a2e5f8a35e7192bf9a0" + ++ "03dcb9d16a54bd84d922f85b6021b28aacc5264fe9e83deb48f18f864cbd" + ++ "367eb163d39c45b0eb907311a2a4b09fb26109088df782ce031b02f3caff" + ++ "d2dbe25b1cbde9f35ba7c47292a4fd49e7def7a28824f3dfda259a86c3de" + ++ "59257c255c712686ee47d128a55c7b9e8c546035eab7e2da420f32ed5c94" + ++ "bc12a34dc68eb99257a7ea03b69d6c760b0681fa24e4ca97b7c377182ab5" + ++ "fee30a278b08c44c988a8f925af2997883111c750d176b432735868208f4" + ++ "0de7137331b544f2d28040a3581d195e82811c945c3f9fde68fc21b36a44" + ++ "e1cfa2d8eb625f3102461539b3f13c660936a5ddb29a0ae791fbf52c2f69" + ++ "7bd334653f3605b362d91cd78569b41dbd09b2a5892440b5097fa08d0b4b" + ++ "291fc5b934585dd8d5adc80d573fdd194b2eae26dfc49f5e51c1f1607d7e" + ++ "87740702f244bf39ca1d52423e0ae84891dfdf4f43ef984c7a5f293a2007" + ++ "a1e00e39c757f064518953f55621f955986f63", ++ }, ++ { ++ key: "d115b6ac998a65b48b3dae5977abaf985258d3d1cfe1616cec3d6a77f7a75785", ++ tag: "b431c9318ec2769fc8ee8f5fc3c079c3", ++ in: "7e7eb43839a6d7616b8a7b1fb7144817904342a9bd34167051162941a6b1" + ++ "b85db5e587f76e4a53211755d5ab29c11822d7711a97b3f1ff5b21f2485d" + ++ "9c86241fb56cdd6796245d3112df11ad9a7344db44d09934c4efb280ed65" + ++ "80cfcafb5c97a32993cbbf4917183e0b7bb38f2ce2479c28e1d39f673962" + ++ "17a7010448dfd39a4e7f406c8bd2d804f993bb410fffa4eb57518a531ecf" + ++ "259a8af068230acb826d9ffc20ee0fc43885221a321e3928971bb28615f0" + ++ "d9f099f5b68a80503a910fdba0bc643c60b64837900be38770b6b30c362c" + ++ "4580722b5dbb1b9c8cd02a18fd7b5661d2c4d28aa941c50af6655c826690" + ++ "37312fbf9f1cf4adb0b9400532755011b40e8252bd0e3c7a22efb0ef9122" + ++ "1e04b4aa8316d4a4ffeaa11909d38cc264650e7ca416835ded0953f39e29" + ++ "b01d3a33bba454760fb0a96d9fe50b3e42c95271e57840380d1fd39a375b" + ++ "3e5513a31a4b80a2dad8731d4fd1ced5ff61e1fbe8ff3ff90a277e6b5631" + ++ "f99f046c4c3c66158554f61af2ede73aede97e94b1d1f129aaadf9b53548" + ++ "553cc2304103e245b77701f134d94d2a3658f2b41108c5a519c2c8f450db" + ++ "027824f1c0ab94010589a4139ff521938b4f0c7bf0986585f535b6e292e5" + ++ "b3ded23bf81cec17c8420fe67a449e508864e4cbb7eaf335975668f013e9" + ++ "da70b33bd52a72094a8f03762ea7440ce9fcd10e251837cfc9ccc1a8cc47" + ++ "0c67379f6a32f16cf70ea8c19d1a67779a9b2d2b379665e0e908a88b26e7" + ++ "8c9f94f17acefa6d5feb70a7095e0297c53e091cf98df132a23a5ce5aa72" + ++ "59f1154b92e079f0b6f95d2a38aa5d62a2fd97c12ee7b085e57cc4652863" + ++ "8defacc1e70c3aceab82a9fa04e6aa70f5fbfd19de075bee4e3aac4a87d0" + ++ "ad0226a463a554816f1ebac08f30f4c3a93fa85d79b92f0da06348b4f008" + ++ "880fac2df0f768d8f9d082f5a747afb0f62eb29c89d926de9fc491921474" + ++ "1d8647c67d57ac55f94751389ee466bbd44dbe186f2f38abbc61a0425613" + ++ "e9b6a64e6bcb45a2e2bb783b9103483643d5610a7e2dcdb10b5d78423285" + ++ "506b42a99b00a4fb7b619b4526bb4ec78299dd01ad894fde2f053e18c55b" + ++ "6047f86333f2690c2cb8e87d9834ab8a5e339aa346e4d9952ed62dc083e3" + ++ "b11a823a67f23fec099a033f127ebe8626a89fa1a5a6b3520aa0d215a8e7" + ++ "dea3af37907686c16521739a95d6c532cc259c497bf397fceaea49cd46b9" + ++ "ad5c1b39a36fdd2f0d2225fef1b6ca2bb73fe604646c10ba4c572ab13a26" + ++ "559ededc98f5a34c874cc25621e65ba4852529b5a4e9c1b2bf8e1a8f8ff0" + ++ "5a31095b84696c6381eb9ad37ac0db184fe5fccf3554e514946a33cabe6f" + ++ "4d617b549d28ad1cc4642dac96e0215ee1596481600d3619e8f45e2c9ae1" + ++ "da834d44aca216bba0efef6254503ca90339f2d7ca508b2722d50c08def8" + ++ "a736590fa44855cd9eb9979c743783aa26e633696739f2ae25ff7b72ceb2" + ++ "4dff4455b85bbd675c8cb71ad18386dc58c371bdf37b4b3875b98a9423ff" + ++ "3becfc0d0ba2aacab3ee7683cb3b345095fefcaca5751ca793da63c89428", ++ }, ++ { ++ key: "f3717306b9729be998cdb2c9d856306c5ae3d89da2cdcef12f86f6110c98d873", ++ tag: "907dba0f4849c7cf4570b5128b5f31d5", ++ in: "079572187d4559f24d8e48dc366441acf226a4db79e214ec3ee288acc349" + ++ "887e2e377419bcafa377d0151497b52e4d9cf2a02b0fc91ad9516482bdf6" + ++ "eccd1497954b53241bfb0bc5c04cc45045c6251f23a510060fee32721872" + ++ "bbc95cd8d400dff00bcac2ecce6229c7d73d8f85ed5a87afdccf6dedd299" + ++ "2d5c7b5b8090c47c737ded036ff0e9aedf02a2242fd9820be618b9601e73" + ++ "d3ba5d8f1ae9805cfd2306251704bc74e3546997f109f1dfae20c03ff31f" + ++ "17564769aa49f01233c9c4b79f90fa3d1433d18cdc497914046ad77d2792" + ++ "2588a7d0e61d4258d7d80cdab8503e3111ddca22cf7f39c1f80f1e16a68d" + ++ "9e21db8b53dd316dfa4233cb453a39a90101c60efc08514a3057db007e96" + ++ "507745bd4a0764ed8717a250bffb5fd1ea58474bdfb5b869681939693926" + ++ "40d832a3387ed4ac9cdab0d2af8fcb51b86e4d927097f1e79b5af96574ec" + ++ "d59d0dd150a0208978c41de28ad6cadf72a49279cffd6dc281c640f2e294" + ++ "4cde49a13ed390da1dd92e3011ce0f4a0863375a9db3f67fca1e3b8288a0" + ++ "78611161d7cb668ecdb932e1ff3733982c8c460eeeff2bca46c96e8a02cf" + ++ "b55d770940de556373a4dd676e3a0dd66f1280c8cb77a85136b3f003fab4" + ++ "887dad548de7bfe6488ae55e7a71da4097db03900d4b94e776a939530328" + ++ "83492da900b2a6c3e73d7a6f12ee30c9dd06cc34e5a3893976eb1de5864d" + ++ "32e792ac02e68d052d9d0cfc7cfb40b77728422f6c26cf68987c6b40fcfe" + ++ "9d660abc657360eb129de11bd70af5eb8fe350af2c27a6ece2cdf81b94c8" + ++ "0e68e8c51106497cfa5171236efe2d71d76b5dff3352af9b407dc5aab60f" + ++ "46b5683646f5b28732b7c750d351a08a507243d8e437cc4bef13a3edaa20" + ++ "5fc4e9968b4e563fa0dc965ba20b8e48bc188a321b16d3213bed69647512" + ++ "7a20afc1a3680ef261df6d37b017dee05cfc3a42e4130216e5540cf715c4" + ++ "e638d7d615c50bef576eeb19b3b15b2c2b454dfcef2b18161a143ddf52fc" + ++ "8e88fa71cbe34c92cd4b5a0adc81e5c33e11d2721bc1b95a9e693ac3cabc" + ++ "490889a8a42bf7e22375b679e8598c8faef22a006ed2da8ab1c08aaed2f5" + ++ "6d6f26649036335c0881bfec1e3a5346335c3b3707ee92173f1a7a3305c2" + ++ "933f78e995da8f1df64daf12b81ce23c8813c27fd4551103dc33561c2e80" + ++ "45b6b6770fa03498fd359a104884699d628020173edbcc4398b977e456e4" + ++ "885964840466176a490e7c513ba5d66090277c1ab1632a995a54f555a452" + ++ "1170a000507865b6650730aa6d6050a55959102836fff3d37e4773340e59" + ++ "2e56951ff9652519de4421d9c5b63edbeb30a3852a1ea110a9a29721aee3" + ++ "23d5a306de1624cecc87badc47aa87f489635d2fb60bff62ba67f5257999" + ++ "6af0a1f1a6fbcd8704e119196fcc289a6db6a4170a2cae31a1d30744b702" + ++ "2536d1526d41659c2dcc8b39c26aecfc0f8a707136d81b2827a158fd7386" + ++ "a537514471c213a8c859016748e0264cf3fbde10f40c620840ec4df99432" + ++ "e2b9e1e368e33f126ec40c572e841c2618d49d4eb098b9533b1f4ae00b46" + ++ "8d15de8c8ab6d0b650e599576f2bd90a124c9c6a0f911fd1bd8253bac272" + ++ "942cbdf8864f3747ff7f09d8a5a9d8599be7ee1744e5f1faf3e526cd2a06" + ++ "b157527272af9d38565957c9ce663c295766c0e0e464971c6282b70d4c0c" + ++ "1fb3b69856b34c089ad2b2c745f5a033cee1429c5b855581ee285278893c" + ++ "43a5968d9c28384b7abe8d072ba69089c938685cb1eab461f05314ad6d06" + ++ "eaa58512f8738bde35b7b15ef359dd2e8753cb1ed6", ++ }, ++ { ++ key: "9772c1a4b74cbf53586e5df04369b35f1fdca390565872251bc6844bc81bda88", ++ tag: "68eb7fc459ecc3be819485001ab438dc", ++ in: "e115cc2f33e367cb85c01a914b3a512404ad6a98b5b0c3a211d4bffd5802" + ++ "ee43b3fb07451c74524ec8b4eddbb41ca33dd6e49791875d716a44bec97b" + ++ "7c2d4546616939ffa3b1ab9b8ba1d1a637e7c985cc922606caa0453085e3" + ++ "5f2fe0bd2de129d1d1856ade975a3281a62965927d8bb695e54514e69558" + ++ "89361a2a00a1b24e62bda78d0b71a0d40147016fcdaf1a702331dda8e678" + ++ "d8f476dcc91698da1688c610ec0cb1d9b8fbcd45dfde6d1503ba60a01337" + ++ "ae5b2f5c854a82c3087779babd2e522dd92f4718cd9f8c649ac226745ca2" + ++ "fa1696442764758f67cd926369578ae87612790dc56ed9cda935281a490e" + ++ "5c984950ec7a4e930520d273a69da4ed3a330e532508e26f942961fed0e3" + ++ "efeed52a7b96250d723155aa39a8ae85131c255c32bf406b647de1a37fba" + ++ "dc61e302bb5b70adec4505ee66b3a1d1b7bfe9c58b11e53ad556d56e5807" + ++ "017bb30b71be94e8f86aaf1496e8b8d6db75ec0afbe1cd336c23963c745d" + ++ "7b4ba1787ceb30728f1762b46f6eaad5064c8029d29b86266b87f93142a2" + ++ "74f519f3281d8c1cb43c23eb184ae41f3f625cf624b05a48d73cd7783fdf" + ++ "14954a03ec1a930e9a954424eff030e3f15357de4c19983f484619a0e9e2" + ++ "b67221cf965e9aa8d8926595c793adfe0181050df8b845ce648a66df532f" + ++ "78b10c83ecc86374a4f8abf8edcc303654bafd3dcc7de9c77a0a9d1d98fb" + ++ "121534b47d16f75b55fdc2a5e2e6799f8a2f8000d4292282e56863ae422a" + ++ "5779900ad6881b78946e750d7777f33f2f013a75c19615632c0e40b98338" + ++ "1e9b8d35a26abe30242c45662eebb157e6d7a8a5519de60268ac289b8295" + ++ "5d4feb47b9eef6da65031c6f52c2c4f5baa36fce3618b6a331f1e8bdd621" + ++ "48954fcf0846afeeb0a6cadb495c909a7fe671b021d5b0b4669961052187" + ++ "d01b67d44218471bfb04c1a3d82bf7b776208013fc8adabaefb11719f7a7" + ++ "e6cb0b92d4cc39b403ceb56bd806cbdcc9ee75362ab4aaeb760e170fdc6a" + ++ "23c038d45f465d8ec8519af8b0aad2eb5fae2972c603ed35ff8e46644803" + ++ "fc042ff8044540280766e35d8aaddcaa81e7c0c7eba28674f710492924c6" + ++ "1743da4d241e12b0c519910d4e31de332c2672ea77c9a3d5c60cd78a35d7" + ++ "924fda105b6f0a7cc11523157982418405be0bacf554b6398aeb9a1a3b12" + ++ "fe411c09e9bfb66416a47dd51cbd29abf8fbbd264dd57ba21a388c7e19e8" + ++ "12e66768b2584ad8471bef36245881fc04a22d9900a246668592ca35cfc3" + ++ "a8faf77da494df65f7d5c3daa129b7c98cef57e0826dee394eb927b3d6b3" + ++ "a3c42fa2576dcc6efd1259b6819da9544c82728276b324a36121a519aee5" + ++ "ae850738a44349cdec1220a6a933808aee44ba48ce46ec8fb7d897bd9e6b" + ++ "c4c325a27d1b457eb6be5c1806cd301c5d874d2e863fb0a01cbd3e1f5b0f" + ++ "8e0c771fca0c0b14042a7b0f3ae6264294a82212119b73821dcfbbfd85bb" + ++ "625b6f75e4dc0ee0292ab4f17daf1d507e6c97364260480d406bd43b7d8e" + ++ "8c2f26672a916321b482d5fa7166e282bfeed9b3598c8f8c19d2f8c8b98d" + ++ "f24c2500c8ad41cd6ed3f2835737916d846f1a6406cda1125ed7740fe301" + ++ "d1144559b7c95fa407599ae40a795226513153f86c9b8abe7d8aa6963c99" + ++ "5646ec586cbf20a03a698cc0681b7bd333402d00fa8e15cb32300b5a24ea" + ++ "316c5e1df67de78891846cb9183a4b112c3bcc17bcaa5fecd6c1dbbf6ef8" + ++ "272d9269e7f0ba9f17050a6aa5f11cb28874360396ab647941f2c9a85cb0" + ++ "6a969919b16997b0827af8f909c614545f1ad638ebb23109f6bab6b49b22" + ++ "b2285cabbb998b3e1bf42771b4d4e52330b224e5a1d63169ec85fe1c7dd2" + ++ "46dbafa6138448420f463d547a41c2b26026d4621b854bc7786ab3a0a93a" + ++ "e5390dd840f2454028b7c3bb87680f04f084089bbc8786ee42cf06904d01" + ++ "7e405144d2fae141599e2babe71abfbe7644fb25ec8a8a44a8928ff77a59" + ++ "a3e235de6bd7c7b803cf3cf60435e473e3315f02d7292b1c3f5a19c93646" + ++ "3cc4ccd6b24961083756f86ffa107322c5c7dd8d2e4ca0466f6725e8a35b" + ++ "574f0439f34ca52a393b2f017d2503ba2018fb4a0991fddc1949832d370a" + ++ "27c42e", ++ }, ++ { ++ key: "d18a328b63a1d0f34e987682fe6ca3d48b4834b4312a17e99b3d88827b8d2238", ++ tag: "938b43b80cb3935e39b21dd8ba133cf8", ++ in: "bc2b0baf92580ee6c5efe640f2a029a791a3c77bec459be74cbc30931508" + ++ "d9f312c3a0944212831cbe4fc92e8f107f2f750c91bcc09f7624fa9a09b4" + ++ "9b7712cf5d619ea9da100fc23068ae2f4e353047e3956b215884bdb12235" + ++ "3f06b8ee98f36c3212493d61ae9ce151cd0453f3075b18a12d7d73da3de7" + ++ "dc2d98376cfb420069ca8148c511ca6bbae57572394a3c615a6fefb30c5f" + ++ "d727f964b4065ac9ee252bdd2bcae3e70162fe0e8069974e073f0a093d45" + ++ "be52d7de16a8f5f65c548aa6525822ffb00dc642530fedf355f7188ef017" + ++ "56384760c80afb61ad903d10119a7d615ec4fbdc79c490160bdeaf200915" + ++ "e405f2a921a2380c0ab9d2ac1e4fdc8ec4b907368c004458598efac13dc7" + ++ "2751e7faded538e3dc8b16590cac9b7ec294da0ad53e22cb9c05d8ef494f" + ++ "a04f6ab7c843c867fbe3cf1b4eb146d65339b0b03392259f12627a8e98e8" + ++ "0f4896c30b8ecd210acb2365539a872541921dcd8e1e54caf4936dfc7e1f" + ++ "68f3bbce61d325b447a8cce7f0fcad28494f2e47dae46b136594b5dfca7a" + ++ "bdafd6856f91496c05b21079aa55aa8c41628220a2cf0cdd755893375b7b" + ++ "b13d914c9a1d1db4a18f8fa36c55e52d0342352052032fb62d32fcd51cb1" + ++ "ac46f44b06e682db5d96d583cda03b966c650c03ae53542e8da1066b6884" + ++ "4a7e2280c664415e413f270b1fdcfbb40b9daa6131d071ee7eb1553dc5b1" + ++ "a50677971223dc316d2d326d57cbd529c88698facdca425e2d5c6b10d7ae" + ++ "cae28b8890aa44ede9b9193dbe8d1d8aa1fa580ca384b57eadcbefc96dd8" + ++ "bfccbe3b855a96f1fd4913035f817b75954ef1827c7718aab24d353e41cb" + ++ "a73748e14e0c2750d5b6a9752125708cc7ee7a498c7fbadf4186e7f8fa93" + ++ "bfdf281a49400f877621651b8ba87edda5231e80b758564e75139b61b1a9" + ++ "9fb9ec694f928ab1f47c6c4287bd4182d1b2be053380616e98da06f3ef57" + ++ "b570ade17c51da1d602b6ebc5a638ebde30d99bf4f91d0e01557c7dcd8f7" + ++ "9e5120143c935fc699eb5616ccd3cac56b5f8a53ed9e6c47ba896bfefe71" + ++ "2004ad908c12cf6d954b83bec8fb0e641cc261ff8f542b86e62d90e227f2" + ++ "a5bd59c9d390c0dd857f6da2b7624787a0bb31908bae84896890b283da61" + ++ "d8ec4f56eea38b22b438d6374b42243f9c1d94288874e53ab90c554cc1f1" + ++ "d736acde67aff55007fd4b3becc4d0f3ddd96f10dc75255cb0327aa47076" + ++ "2b3a3a656e33c87b02a682658b6cd2a75d9c0462803c9bbffa51441501a0" + ++ "3a2fbb2344aa13d27ffb9e98704ea6720b6a9992e53449688cd74d0648fa" + ++ "e8e776b0ea6bf048b2ec05341e5948cab0af015328b284ae7bd89a5f763c" + ++ "eaf5ca3e647a9f5bff7197e4d357e4359fa5fe30709545453149be510e3b" + ++ "ff86beeba5110c79c0215fbe9ac9339a8ac7d41f7488588ab14ac657aaf7" + ++ "d5c03a353932bbb2b261f0e83f3526c5e8e0c2348a10ab4eed6ecdcf9014" + ++ "7550abcb0a722f257e01d38bad47cdd5a64eef43ef4e741bf50da275720a" + ++ "0aee47adfc5cd2534b911dc269197c3c396820b303f6941e3fd85b5ed21d" + ++ "6d8136745c3eeb9f36b1f226434e334dc94be8a5606079cb7643136aacd2" + ++ "da9c38b2eb7e2b898bd8632003767bf0c87d00a3c2fcee48bbbcdd949af3" + ++ "3455128216709df25879b0ce894ac4f121dfca6b8c7865002b828696641d" + ++ "14ffc59924fbda50866fded0afaea545c8008c564a3a0b023f519a9980ea" + ++ "d541d91d1c07a739fd02286ea5660e473f80494236a68e84ea31aad71348" + ++ "e45055ded69c39941e31d51df257a4d0b0d8f025dbedee093f2b91795bc1" + ++ "533dc472020769a157a187abd6d8d52e1693e2ef56b2212759d0c0120e54" + ++ "c425d0084fdb3925e296dd6cdd8e677043a90674904057d88ebdea5998aa" + ++ "03562a790adecc4399352df43e5179cf8c584d95ef8e4b37295946b1d37f" + ++ "faf4b3b7b98869184e42ea8b304fe1059f180ff83d14a0861ca7c0682c34" + ++ "b48a70df8653bd8d9a26f9489e1271fa44e41b392e648d0e619ecdad2c53" + ++ "952094802eeb70ade4ffe096e3049867de93a824217e31364b18204e9681" + ++ "dd8e84ae2678aad155b238f59dd9bf9ce07e97183a690b2a46a8f3624843" + ++ "5b2f713e7d8dcda4dea1e3c4cf9692dda082322c51f7bb1f63d92aa987ec" + ++ "cf1355a043e21a7b8d60a2b97f18487f6fff4c77df92dbfdc9837540c518" + ++ "9fd9585731bc6e726a34ca21154b0499522c9d1016953dd0fa2eb6a92b6d" + ++ "14d6e3da5c12fabe92bd639e253983fc91041091791643", ++ }, ++ { ++ key: "46e8eb27acfdc8f4be622d8741c7bc414464c149e21da97ab4afbf3e07b98b0e", ++ tag: "56b5f49be824c7a19b19faabf0787a87", ++ in: "ced52b76c057872a60107194b432cf04b7be05e65209045d2952ea0284d8" + ++ "3e2ed5a15cfdc58071204573c18ab03765b4d5e63a601419e039c42075b2" + ++ "7ebb2827de9c6233d6632e6d3db9140bdb4a9291d53f33734c2dc8e24df9" + ++ "0764dc10e0d321d20fdf659bfa2a81bc9e04fd0f83448143276647c08bfa" + ++ "dcfe3bc23898eda655c9353693ed7b022f43eefa23c21db7660c5029ca64" + ++ "a6085d93029ea6c43197356f56b7624d4819f5008d053357d981ffbe7f40" + ++ "96d6c55d8417002d36189b04bbb2c637339d90f4910a400833a8d422d88d" + ++ "c816c1636e8d9f7f926c244a28d9e0a956cec11e81d0fd81d4b2b5d4904a" + ++ "d1a5f55b5ec078dcb5c2bc1112bbfd5efc8c2577fe6d9872a985ee129e5b" + ++ "953e9cebf28cf23c6f9c6a5e09cb09ab586c6a50e4389cd3110777591d7f" + ++ "0608a3fd95b99f6ba03984fb0e13c6bbbde3668c59f2f2b69d7caadffa94" + ++ "6f67e725d56280e59e66dca025a18d4616e81abd9801835bd94485bb2025" + ++ "dee81fba440005b181ee81dc1d7796cbec92e4ec1c9016c8e8073cf281ce" + ++ "f749993f09a618a4671d58b476feffa454600f82955c591882715148a826" + ++ "586f68bb50059914dce1c1c85e5e3951647c9964ec9316005209a58baeb5" + ++ "2c6d01e6b4c275c0050a7e2bdc52133e433b050a700b556d4314e5c041d1" + ++ "93ee47f47adc971aed1b63259dd5cd4f95854a71a947eae3d3d12d0d7b52" + ++ "c6cd2fef2d2e892607a9681d73ac3236fad21ee30a4f857010bc95c00d5f" + ++ "6f0c6b3fe50cd6452be6eec4f5f01542dc2cb5e2db1f52224f11348fe2a0" + ++ "5d1e5885f1317f2d06ce2813dc4c723008e836a2ee95d0aac66855fe4c3b" + ++ "1b2e02ba0700be759b1ef1c2a3123ee4ccf9200d8d4de5e0d503f04c2053" + ++ "66393d1e91b648392ca28389d976aa618b4796acbfe8aa356ecdce1f7786" + ++ "bf09af226bb9402317b6fa319bbb9248d8ce00b1f49f066c69d4df93266b" + ++ "938342cd7fd4b07c320c2409ef72d8a57c21d0c6d6d493f7ca94d01b9852" + ++ "e4fca6a9291e9060154bc38af6c86932645f53914709fc90e11db56ec471" + ++ "6d600ee6452041248ea8244f79534f793bfc1f2020855d817cb4ca3c48ea" + ++ "7f6441ce9af9bda61936c226d810086c04a35e8654fdc30d4b35701adccc" + ++ "016d5895b2121ba4066e44d694f6371d97911786edb73dc3020ba186a01f" + ++ "ee3dd6036c0e205a8d05979bad228fd12c0fd2fded6c7f1e4c11354d266e" + ++ "d9c2f706269c43cd90504997d93a17b39b10dab0ff083ab3bd06540ce612" + ++ "d08f46ce75a16ef330525737410a0d98fb3d484968f9c12edcaf50103fdc" + ++ "c14128ea4ad6c30b56247eab28197fe617e5f88afa5cbe003c63d423647a" + ++ "d3042626fafd2084a0582ff1b1efdb5baa162662048019546234e2f6b6a1" + ++ "d8bb971114aae41df7795b4f3598f2af9e8921a9aadc7fab6c780aaa32a3" + ++ "84865a4ccb02351dbc55ec92a3152d1e66ec9d478be5dca17b4a131b4a0d" + ++ "3d4420fc6123fef80fd56ca266407d58a7880d6b7e5ce2b6bdc9a3721071" + ++ "7feec573d83c83a2e3f7d4023f2f68e785cde728fdbf5054060e4c89faa6" + ++ "1c9dd10524a08811d15c627b3b4ada549a3fa1d8dd77c005daaf2addeb10" + ++ "0abf694da8dd692f113965cd6366a5a7b0c17e1f2a320243e2c90b01418e" + ++ "22426d0401a2c8fd02cb3129a14fdfa6cbcaa1f1c2f17706e9ac374a3458" + ++ "777761e986ee4c358d26f8e420d33230d198fd86704e77298dd4c40c5205" + ++ "7566ac0cd92993b21937c3a3b4a8b89110a97cf38c781ad758bdc28f3565" + ++ "60cf3acbedfa8e05b396d226ef619746e8e4fa84c8e00a7f0e6d652808c8" + ++ "9c9b123d9bd802624cfa949eb68af85ca459b9aa85b81dbc0b630856cb9d" + ++ "7e18cdc96b3c069a006dd5b716e218a5ed1f580be3e3ccf0083017607902" + ++ "a7967a02d0a439e7c54b3b7ca4cc9d94a7754efba0bb5e192e8d1a6e7c79" + ++ "4aa59e410869b21009d9443204213f7bceb880ccf1f61edb6a67c395a361" + ++ "ff14144262b4d90c0e715dbefce92339ff704cc4065d56118624a7e429e4" + ++ "cadf0b9d2e7ffc4eb31c6078474a5265beba0774209c79bf81a930b302bd" + ++ "0f142534a6ae402da6d355a010d8c82dc379ea16d49b9d859a7de4db6e62" + ++ "40f6976ae0f47bc583b327df7ec88f5bd68f713b5d53796e72e28c29e843" + ++ "6c64cd411d335623ff4f5d167f3c7b8cba411e82f03714662425c8e1bc1e" + ++ "fbf435d28df541a914a55317de0ded8c744a1c3a6e047590244b207bcdcb" + ++ "f4bd1f9f81210deddd629192c58e6fd73e83812f084ef52f21c67bea98ee" + ++ "17554437d9642e2e", ++ }, ++ { ++ key: "b41210e5ef845bd5a8128455c4e67b533e3e2b19dffc1fb754caa528c234d6a0", ++ tag: "72c9534aec8c1d883eef899f04e1c65e", ++ in: "7eeca180bb20d99635e36b9208221b2b8ef073fbf5a57f5190e19cb86c49" + ++ "89b0e8150d22ec3aaf56f6ed9cb6720284d13a4b0a34cd3d7f7fc7089326" + ++ "6d1893fa4185269fb806677ff490aec8f889896fca50d6c80d295875b1d5" + ++ "4a779b6d49305360b31011b48537157d0f323ff4e865d46fba6bd23a06c1" + ++ "46878cf9404360d325432312ff08ce495edca63a3c93c44d79c050e3f1de" + ++ "4b6ca5fedbbd43dbdef9ceb26d440a59c7e0be3a8e461c4f15b6b1e1dc36" + ++ "a71fc723ad593fb903e83d0804ce497fc49bfc6b6a602b9dc6e9891010b1" + ++ "4ca066cb1c68044c1ad837c638076dd3708078509cba49fdc54922cdf5d7" + ++ "715fb43e9b5a5942cb8950eade143577bc9dcedde58d51deddc70075e452" + ++ "bbceab1e95b5d003eb96bea69687faa6d50d9c605769cb4287b5d9924dd6" + ++ "8881c699abaa6f93e41dac7639cdbbbd0259099a3ed096f482a1fa322b15" + ++ "ffc379812c74e09e95f1bd3706347eac421fe56895e738a47fcd3e118773" + ++ "c3a7e7e264cc7ff5a53a80e436df058265dab9756fdf6913786a47e98bbc" + ++ "411052d58ffec9ee948e28cbaadaae471c5d828eaf3b3c87d3bfd495477b" + ++ "403da54f1418a15ace0d4d0df68f6a8f2b0457b127d5eae1f45ae055afa1" + ++ "8f058d5dd7eea559de3ae9378ca53f7d6dc9a9465ea1f945295f16ee0404" + ++ "7fc9dd3deda8ee32631d7af70c20edc1e12c5f8abd2e78f43dbd4cd6407f" + ++ "038efab144a24ea8a090a7ba3e6499345a60106220c2959a388e1a73d070" + ++ "1d854bfaaa86165a5aee934b615ac7f45da7c43a1e8f74613917ed10dcd2" + ++ "27e4b070414412e77851db5bc053e5f502bb4e2b2645bca074c18643e814" + ++ "4caeccb58be49ea9a552913c0616382c899635eea79a166988c206b9aaa0" + ++ "977c7ced89c4c7aaeaa8fb89b38030c44530a97187fda592b088198b63a5" + ++ "2dfad59a0a4c1aadf812bdf1881924e8b51b8fd4dbca8e73b2986b3ab484" + ++ "171e9d0cbb08be40ae60de8818bd7f400191b42c7b3200c27643f06720a7" + ++ "e0a17441f34131629388ac43955b78c31ea6602a70dd665f872e7669e865" + ++ "f6f40e634e8772d747608cd3a570e1726eb1ddca64f08582b022bb026eda" + ++ "6a913dc83f174ce3c18b9fc0503d3ac74e2fe45691d6dfb4af8c86d752a1" + ++ "6d6664fab4de08afe8858392fcc35cb9ea82fc42c42d48c0c0556267ea0d" + ++ "cc19b10f05e0318c4488ffe704b5036908f5cb938eebd3163503acaa874f" + ++ "592d945448fbeb93a877a26a72306a36e181745ba300afdc30cb7986919f" + ++ "3dbdc5c47ef1fa052a9e4aeeda3955f61ce2f30a0593a81dbaffebac5a49" + ++ "e5a8d1308352701d1ca9e620a67a89abdf5f0f8b1a0acfde5819981d4b77" + ++ "58799c0fe41030b86754837712af821c315301aa8dd50d1387b9fb92ee63" + ++ "10777e08229edd54e5e86b086ac281bd321082ef46ce298a6211aaa3aa4f" + ++ "6e55b5a4641220ec94cca73087760da1b1ac3e0da3f438214e691aa184b0" + ++ "535950b715a64d11485940dcaa3f72e0aa521002b1443f5e7880e2a85b83" + ++ "40d32db0fc4c4702e10f0fa24a35da9307850e945f608ad34d6cfdf6f2b9" + ++ "ff4f6b8e9eb5a883546578e2ff3cc5787322e4384640f42dc5bd05f432d9" + ++ "610dcf7c06cdf34762dd2a5e805e24aee8cebb3b4db9e4d1471da995bba9" + ++ "a72cf59ea8a040671b1d8ce24a3dce4fc86d2df85c8ab5e1eb2b0567c186" + ++ "4fb464f48c3ca72c7df2749542ed4d4be51b63769012ce3d06356856b2a4" + ++ "24995a2429a156ad93bc79c705e7b163149ce53a42c34a19680dfe4fd0f7" + ++ "fce38c30dffe9da9bc941d131f435c1398f8284a230e9d6e3992710074c3" + ++ "881d03aa309a9edd0fde7a39c33f6455dfcc5ae3fa20ea0e0d6549a43536" + ++ "b4cd8a2991a135b7d7a4265fb840318813091274414108f13fe191db7774" + ++ "6a5f4270f6d51a29ff523954f84cb76131d4abee79161dcbd97dc1ef24cf" + ++ "db1fade057dddee00a1e0de0db1afaeed1b535f7bb402afa3b297551fd14" + ++ "8c8f3e05f1351d3a8ee2948daaf14e7fc448c4670c906ae076eac5a7c656" + ++ "fd5f9cd937b91e26c9e5adb43c138f8d65e447b0022a524e059f879c6e27" + ++ "4ff7e671f75717233aae70853d5bd7bbb41b43c47bb08d6dc2f54f9ec606" + ++ "9487d1267add72403d01552a3d138abab9ca8a0d2dc32439759aa5695f70" + ++ "1a17d28dfb85850fdb55fddadcdde4d220e4b05821e5736d346e7dc9c945" + ++ "72743366488b1de8975184771361894b6520e3407c5c2e38473430969e35" + ++ "b106024da8618665d58c9d084824a28991a33658d6ec702139e01b65b7d0" + ++ "cc537a644caeee880657803d95f5f67816948d5ab362922f8ffbd531473e" + ++ "b0ff8fde2afc37a4abfa28dbed0be1b3d4ed48a1d02358e8403905d33b12" + ++ "3066e7a9fe2491ee9eb24fc9de7dbd322c8ddbc5ebcd0d92cd102ebac96b" + ++ "90e2fd784fd6d4b699304df23b17d963080a013794322690456be525c071" + ++ "b78fcd2d1148026e44ff14c4d0f942cd44d2b3263f4a93b79ec7a618b4b0" + ++ "d77ae7a1f6e6c7c7e2f498b825bf1954df348bae45ae1d7c87b6787f1212" + ++ "60c9a724429a4a2491ef989f65acfdc72fa717486dcf1984905218e11cc3" + ++ "970a09d71061e6df751f100abfbf", ++ }, ++ { ++ key: "d9b0dc303188756312c12d08488c29f43a72e78714560fe476703c1d9d3e20c1", ++ tag: "6b9782f2a09b59653aa448348a49291b", ++ in: "dbde1820035997dc8a8ff3015b4e0674e7ce7bf0c2d994b7977f2d91b49b" + ++ "f200995040daeb1218a0f4307b6b8211913992b070d321bdb947b4ba5017" + ++ "a0885e7e5502710a75cbbcb56d49e1bdc2bc2afa5a0e83851162dec41340" + ++ "bafc41c5e11fcbf4ea2ac45bc57def4742281bbf734777f83c9ae1ea3d5e" + ++ "d42380230570f59c40d5dd9a2d89b75fa3c92664f12a274d965ed8de79a8" + ++ "b37f3763939ad21d1703ad794f617c8b32b20cc4dd7c1b7f969a65e1bafa" + ++ "f6c43f30c9eba256f10201910e2cc31a9b13a46ad29257024ef8f2ee29b2" + ++ "ee63cc5b6230ab9f87cd5cb534f4b0bb08a790466e0d57b849fffa1ed21b" + ++ "fb0b27804e3ff9df7bebf14e100cf91691a493e53870abfad6321f6711c5" + ++ "0fbcf1f0b2c1e5231d6c0a08e710525176355f6f82bedc1f787f0d3cb41f" + ++ "a11e91ebf9f4cbae46035a371232d63ef0d8bda0355af8cd0a2f7d1327d8" + ++ "0ab769ea0f1da0f76ec99cc737b5ce84675fa8a9ac0c98342bb82b5848bf" + ++ "656d35327ea01a1b09d84ab974c307511af68a30cd6978b529a8f58c68a5" + ++ "9d476062ace8897ec0d1a90d5d167e29ebaa6f46d93d697760c8771417ce" + ++ "94c0f3698985a98702833d1b68641b811840ca3d935386dbd4600fbc81c8" + ++ "728c4fd0e4588be739a048f03bd4ac651ceecd7e2fb120fe7190011f957f" + ++ "cbbfdc025f1ca0b356208db8cad87fcd53c5d3a30a7c2a48140ccd4cdb49" + ++ "f3961cef742caedd1e848bf3cacafb0da030416bf3177877aa0bc5f9d1cc" + ++ "41fafcb829d5e3ace9394028683d712552579e024084a6b855830ad9f567" + ++ "ff58f05d3ec263eddd6f56adec378f167e8dabbeaf7d0a9e65c71660314d" + ++ "6c8d54beeca2711113fbc32a2ff8c0daa8373278d10085d2a0660ad53f4e" + ++ "1ade74a483be180180acf9e9ad3ea5bdd9162ccd69599163a451c6837d5e" + ++ "a5e115bd9a560f395128ea002ee739009a44fa46078b18959933fb6e866f" + ++ "eb4612a56ce93b1affcb95fccaa18d71a148582ba1412a5daa07404fcb39" + ++ "c3cb4a2519cc506c1172c6c326016ae2e5410f6a438569f35a50d45cbf3c" + ++ "c46188651aa22c257858f60649cee8c05c75953ce49358dfe5980445fce9" + ++ "614ccd16d333ad236e29d204691ca0bf46f29da954bcaae52e41016556d2" + ++ "f4cae1d37565bcbe84de1b49f344d0200478a38187da29c155cc98184d9d" + ++ "33dca088d70054e0fce321f7a90c48a14963d0ace2b4e7a24b21c14a5e67" + ++ "1994fe1f7d22d1135d4df9268dd18d323fde3603288735626a5449582d35" + ++ "30e2c2225414e05a8c7b987c873a82e272a5d83e59b90f3d7264631d6ad0" + ++ "4a0cf3b5e96596a66ed5bfbc24ab6e4870aeec0acbad2cc5affaee06de32" + ++ "dca06f175bf763cf8e7fdf95941a177e934f0078be7dbaa4c9b6f5c16b4a" + ++ "5607bab5d56144a6ba3c7d9a084b8d1f4b24b6f9754ed207b230d3a2cc26" + ++ "259ccc725e1f8a44c4df8143e13edb5ebf073e2c9d2da5f1562df4feece2" + ++ "f6480987f093f642eb7afa3aa92dce2a8b60bb925cd2d11cf6c2ae7d2153" + ++ "1a9c8f068d71d0e682023932fe64e956a49347aed22b21084c4a84480491" + ++ "244ac6b337b6d12d5551ad5684766c68bacca62bdcafab6603c81bdbd8e6" + ++ "80d9d8b3825eaea4df023142e840f98ee251466a0422d810a54726a9f03a" + ++ "7e0afeb0043e60e2ba4908f951d2e87fcbc372096f2a9f4f2a95ad5faede" + ++ "3796b11ecf4401c3ee3d268bd8c46476c61e0ffc5c43c0f3c58c79e20f75" + ++ "520c102aa3c260972a870fc50f8841fa0553a9e30bf37ad282fb51b34adc" + ++ "7a933ca1691a8a706605ce0b906fdccbe954f8e5f2f63c42599a483c4be7" + ++ "3a041ef90ad930fe60e7e6d44bab29eebde5abb111e433447825c8a46ef7" + ++ "070d1f65862b30418efd93bfea9c2b601a994354a2ff1fc11c383e7bc555" + ++ "9e7546b8bf8d44358b1ce8cb63978dd194260e00a88a8fd17df06373aa80" + ++ "04a89172a6051bd5b8cea41bdaf3f23fc0612197f5573f3f72bce39c9f89" + ++ "faf3fb48d8ca918586d4feaea7e0f2a0d7a6afca096a081af462ea5318cc" + ++ "898a9cc09e8258a837559570cbd5eb901e8c0e04ee88ba31c81a76b000b8" + ++ "0e544feba576b3eb5272b53e46e96a0b35b9c759caadcec61444f8ec47c3" + ++ "45a1d2304e2708eeddfbfa75a98eab3493889047d690e84431d445407fdd" + ++ "99560c0bdd287e0944116f8ac62ab992ed3f1e2b415aea784b03c6904795" + ++ "f4326ff60bc839615f2894570dc9c27cf928ef192047528a1a19ec990978" + ++ "3b0d1a13dd4baf4a19e49bf798975abe2ad167dd574b32b3d0c22aa4d9b5" + ++ "2761e8f56cf2100fe5a39fceae3d865f3724d4f299d07ff899fed6baf7fc" + ++ "eb7189357bf56cf94a6493e61301b43e3ed158cb9c7a0e615fd9888c2db0" + ++ "7f7689762f62ef6b3ad4125e06b07a422f5040c3aa8b8f205d68356c9225" + ++ "56fc4c976165fed9599daeb297498ecf744bf6c7dc5e30604c461ad99402" + ++ "2eea0fb6fe33f82a97b5c272fd24162a94b761ec7e52173e7bb42e88b343" + ++ "64f5fa2c141ed04a86b8d00fd9c25bf77a8dc3e63f5543331405be6bf421" + ++ "6a891089b316aa4f887cb4aff0dfb4e80c2ccd65ddd9daa74b17b4411c0f" + ++ "c849dc748d9b138279dcd9ebfc6e6759a53f5c28a41bb82107d71cc161fa" + ++ "81291a8290", ++ }, ++ { ++ key: "fb70ae7ec12264ff9f51124da188e5b11dbf53cae2671363f6054b575b1ddcc1", ++ tag: "d9ab81fab28b3be96fa3331714e78c9a", ++ in: "c62edf20b1d53962b42386eb570b10378f9764421ecbd7c4802853332747" + ++ "19ff4c89c06005050fa9ba6579a844060eb7ece6c43bab520e683e0f36ba" + ++ "49cba259edc6ae35d41e0d7812a7d5edbe4d90cd5e0504d16f4c3f70d01f" + ++ "5a0313de55934b661ce1ec317968c2c4de60f45c66cded8c10565a1ca6d2" + ++ "3a84bf182df2fcb05956ed4d46b49fc0fe3bd23961d9466fde070341ce41" + ++ "bc6e148449360a31634fe10e91082d82def90d9da2c250ea72c58add2058" + ++ "d046b4392b78bc3af5b3936ed568733e8ad5672dabbfa3130a6a535ec73b" + ++ "da8e7223535f49f96cd35d56ed4792c5cb7076720d5461d96a2692b2ada5" + ++ "2be08fb7bad15d15a0108143790024f0f15f5adc275e783aa56b70844061" + ++ "e30952a040e4cb9650f2a010417812790105d8f58bd25d99b0db3cb16229" + ++ "3f6322e86cd5b0bb1505a7b998fb0f81d1e1915faca3c2c8ddea39115507" + ++ "80339430a7955521839deff5b301f3fad54edd5ebd2ac4ec9b1795cb4dc0" + ++ "e2eb62ebca8e886c3f1e507d10a0228c3027b472a7104b815f5ec8dae55e" + ++ "0783ff7ae9a3e6b99e381ad788206b135520cb870ba0cdbe876feea843b8" + ++ "5a82adc95a6d71c555f798da92b82daf0abfcdbc82ec30b1f12d78490b06" + ++ "7315735017a94ac150b44dfaace151896f873923310ffcd41e91bac04de6" + ++ "d70ea71565948c907ab21c4a23703fbbd2a8de6d3095f3d8f901538968e3" + ++ "60e7bfddb9d22036b1c23f4f5f1b2ee22623426a2d5de68c1e1a38e38e08" + ++ "e2b5670aac1edff69e9c73c2ca56cb69c709009ef1d541aff1fdb2b40c92" + ++ "9b87f162f394b76cdbba1f5605993e4dd9c312321d59b0aa5c6e33be1b10" + ++ "bfd00b92d4c02db064d0e4a98f2913c89051b0f0ead163deb5087b6466d9" + ++ "84f57553b0fa53850eaa142e072fd91802eb9f0d2eb7318dd620555e6ce1" + ++ "86706b866d41cf6ba81f100342faa14d801dc6f3d522db38fab17a879fcb" + ++ "b6acfe922163505bd23a6842f6ef6397ae5fb6e6016421998bd43b0142b0" + ++ "3ca3b16d6ccb7a47891c75c687d791a930b26aaa2e3412e7aa16e2cf1501" + ++ "7bf6df6d2e1c289af0d7ce03954a60c1dfcee5e4b3da51eb43ddd14faf59" + ++ "082005d0c8b104561f66c002ff426be60be769282fc5685cfd1968df1941" + ++ "73667e48e9ad681d35757f1199f1d93377bbad093c8cc3efa2bcb6ecb703" + ++ "694422772d15aaa58cab9e9ab277ed510f684114cc4a44ccadb3eb1c9a76" + ++ "d8619a9b7743106df6fb6f927ac49b22ae5bb9a9a4d231e340a2cd0e3282" + ++ "53f6d75df694826f60e4b3e758398793eaf73ef5d4b56cd1471e16400f40" + ++ "4a947e9737f4f874fe09a29ad799f4525156e3abbf0585c3c3c0a3744c86" + ++ "5d56db3d2ecba6bcbb1adcc8bf5f3b2a2d46d3eba18cda55201598a8112f" + ++ "d8f14e205f0e615f081b8ff6c5aa6669da776bfc7c34d5af4d0b26d0d819" + ++ "f6aacc53cf3c6653138b9a962acee9d6ea01d280c35bb1f05d1509238ccf" + ++ "004c5013167f804d1780d9f4ef9d45742fccac346b0472bde24ff5db9ae0" + ++ "16455a3c02256358fcd8e6a9aae94f8a37a1a3da58a889bbe3d295e16544" + ++ "2e580f59bdd31c92ffcab40c49c1cdbb4db1dd4882b66edc10fcb1704203" + ++ "c518c1d8d4c268588ce13fc38e0210aeb47d11d2603d4b3de5c6ff5e969b" + ++ "9d5904abb282b699bd04a6e9f1cb323679e30400d725aab128a032745dc0" + ++ "be05a46b02b34b93bff02523cd8498c021fc35a488f164a70ef1ceb873d9" + ++ "14a681d3a3a34cc76bfd5a547e2630d7741a284511bae5897d9f7a197fc2" + ++ "456af5c6cd7e1a93d3388c7a990b5feacd7749cf39fdecdc20adfdd540c6" + ++ "9d330195db7cc0d4555ea5f5356a3647e2265399f153c34ed1e217c5dafd" + ++ "c2c5dd3d566c332c7ddacb0d76ecd3a0ad505a4165443aa81b0f43cabfb4" + ++ "62942fe74a77c22b8f68a8b1a6d712d1e9b86e6a750005a3796ba1545396" + ++ "13170906d228dabf572ab969c762f8b296054f23d5d4a37bff64bf9cc46f" + ++ "43b491b41101256018376d487fe8097f1653a7a9e99e1ef2492600598fb0" + ++ "bbb7df8270be8b9106126d6f491f8b342a96ab95df6133e883d3db4c6a99" + ++ "402aeb58d371263a32dcf76d33c8904395b9cf0016fdfc15608eb43e20b0" + ++ "99cbe7455f7a76f69bba058ef96f83ae752587485657f89c7f26fde7fbeb" + ++ "a82ede581ee92821dc13b8202930aa58bd4f1c86f68926baca0d06fee642" + ++ "ea8c652d226af91a9638a0244f1a03c7ce56969b87cd5c1f86110d192e0b" + ++ "98dd979d74acca6c1956b1127d9a1f456053d17974081ed8ced0faa4293a" + ++ "319e5b25ba285c1151214f52c283e39c35af51c4572c8e395b7856697bfe" + ++ "dfc4145ab4ed0bdbe43ba509c06a196ae6bf30d7582550cb546c63b51833" + ++ "cb0dfff7196d83f6a1c6d6d712cce2ec1989fd9ff5a0a22ac5022b49d566" + ++ "58f196703e4809e7624fe7cfa6c13b378f5aac7e66e657ed7eaa942d1a00" + ++ "544a947199f24d736b8976ec2cfb563433c49ba131bd08b63636854219d4" + ++ "c45100c98e3092773ef492dd9210bfd8f54cfe2cddafcf5c05468d90e620" + ++ "0c2ef99d17fa6992cc45eff3072b7cfd51cabb07ea3019582c245b3ff758" + ++ "0302e88edc2c13fc43646ba34de37338568baa66ecff3accfebad88d143a" + ++ "fd1c3b09ae39c501e3f116af33b0b720d6c2baf5acd7f31220788b2f9017" + ++ "3ed7a51f400054e174d3b692273fcab263eb87bc38b1f486e707d399fe8d" + ++ "5a3f0a7ed4f5e443d477d1ab30bc0b312b7d85754cb886e9", ++ }, ++ { ++ key: "f7e7affceb80a0127d9ce2f27693f447be80efc695d2e3ee9ca37c3f1b4120f4", ++ tag: "41c32ced08a16bb35ac8c23868f58ac9", ++ in: "5a3607fb98eaea52e4d642e98aa35719bfce5b7d7902950995f4a87c3dc6" + ++ "ad6238aadc71b7884318c2b93cd24139eed13d68773f901307a90189e272" + ++ "6471e4bf9e786b2e4cf144764f33c3ac3e66521f845f6f0688f09eaa227f" + ++ "e71033b0f74295f6ddb91fe741323f2b54f420cb9b774d4291b06219f1fb" + ++ "4410b55900425c5e6fcabec76a5c2424d637a1641db6f0f6cad564a36a91" + ++ "0f49894bfd598e91f38ceea65e8253c1284f210cf7b50a96e664e562f3cc" + ++ "01c4fc490fa6d4679fd63fbb3ed8995a8a05166b573e92d22ef4370c6aac" + ++ "74ae94c94177e5f71143c6f340efceefda679ae76f6ed7f26eaa4848a8de" + ++ "8c40894316efbb06400f9695b18ba279e8947c032a84a40ca647d9ace457" + ++ "6dd0082494d6bd7be4e7928e749c78110af8774a5d43e9c9479964e2fddc" + ++ "ee51146460eac734311225d08c60706e40f298a7cb97f369ef599be097ac" + ++ "3bf1c275497bbd68968a235fdf8a61bc7cfeef0fe451bb04e662ca39f34e" + ++ "a8e3acdd0befe9762f9eeb275c0cdd43c80fc91131d1e0e790020975ab65" + ++ "afbea81f303ebd86760821efb4cad7cc01fd6d6fd194ac5ffe7703d890d0" + ++ "169e21b444cdbaf691fc741a5d99bd47357c37785755fa72582ca4754a03" + ++ "b4def86ded39aa6d9eb3f38801077e6d17e3cee3fb57ae83f30c79c3cf29" + ++ "0e2739c6b7323612cec3a561ebeadb4faa642f150323aaa9d270658c907c" + ++ "4c1610a5e1834730c08be3379cf1abc50c30e2bf01ce903927c27d85e135" + ++ "3db9e216dda8860c45925e2bb791abe5c8281ee6d16607bdca87f60662dc" + ++ "bd6e20224e7f009a86db66fadd8e37e0a59559328385090c6953cd20bb61" + ++ "f28a734fb056714f5159977f18e5c5f11de75f7a00ba807e47a29e4da32d" + ++ "5c67ec76ce4d7b669b5e6ee17e1df7c673dd8a7c87fce665cda8adb9547d" + ++ "1dccbdbe7be44846b4b121b0bfa65e4ed530789510d79bc4477e50178060" + ++ "f2668ac8956f39ef422ecb0e4cf90b8ce508552eedeeefa6c7d1bccc077e" + ++ "8088bd7e0e6aaf0bda9f11c412c270ee2ad6912f9808f9344a4bb137bdac" + ++ "b5b9372b00b0de026a8f5d1fb13972e1290b5005689f7636c43aee2fd443" + ++ "93d390371ae573f0e064b2d7df552b9adf04bf173d71c621795b9fb503dc" + ++ "5e918536c6ad25ce4a76f70e6b752b6d44be321187269a19bcf33ec899ca" + ++ "40e88b4eb23217095a85057bf95d8a54812cae4a7d32e0c2966a21376110" + ++ "74c6c8c3dd45a553c43c675d23308709f91be0b235d0222aa5e1e1ce08f9" + ++ "c6b45ceb5b47bcd7d7b2d4380bcdbd6eced452d93e6d8cbe18123277889c" + ++ "7f86b15fb991364a501fbf5d8244f2e3332ea0ab49e833c6f765017a4006" + ++ "cc7cd1a0365945a8d8873cb21832b210c83e451c01ac949de2fb0f7a420e" + ++ "405bf64eb251c6f022181595d68174b91e503187d3b3f49b60c23e44ea40" + ++ "ca20311305b413047bb22e89672758b74d6bd1a06decf09e9556421087a4" + ++ "0c1d2c44c5fb13d4d9625581ac4ccef1a1b5eeb5689aac5c0291aebda276" + ++ "50daf9d4396a64d02c6d58bcbd609d9a0017880ae0cbaf02ad0f1fc8d1b3" + ++ "ec987ffe13102d77352690c9b761bf13ea0b3a8ebad4a0823817fcaab4d0" + ++ "9b0bf03486620761dc77a6ba007ba07153b17425c4026597473e78863cbf" + ++ "430c0e5e9b04a83ad11506b61b8d9be3aeb06b5114e0d53d4724863eba12" + ++ "4f3b974bdb0d02743520409910621cd730c97ca984fe2921c38055f83ee8" + ++ "c4611db92e52d8ea51d89203e89df7586c574df15f3a96ed5a10bf04cb27" + ++ "f9656b5b11cf35fd21360b029ab26e9a741c6b3e6357aa1a41de2cac6e85" + ++ "f9a49e3441e60a60e74f434e1b8cd4454b11962e5507ebf904e9d6c52a7d" + ++ "9722300517c434758fbd6191f4550108b143eb16c0b60094fdc29327492c" + ++ "18a3f36737e506fda2ae48cd48691533f525acfffb619d356bf8347a8bbb" + ++ "4babdc2ac866e497f192e65a694d620687cfb4f631fbd6ae5d20ac2e3a12" + ++ "4d85f9391a240b616d829ac2adceedf8f3451ee77e4835639b13c622ef8c" + ++ "48a181fc7598eacb419fa438d4046aa971942c86b36eb8e16eab67105783" + ++ "d27fc56f5b66f35451b2a407d4648a87ae70807e45bccf14983b3abcb198" + ++ "d661d562dfcb00ffc569ca967171746e4e36f839946bc7d2ea9a0eda85b5" + ++ "a5594f6a9c1b179f7230eaa7797a6aaf8628d67fd538050cf47aa654778c" + ++ "11dbdc149458c1ec2233c7ca5cb172356424eb79479b6a3eed1deb9f3278" + ++ "5282a1034ba165032b0d30733912e7cd775cdb7e0f2616b05d521dc407a2" + ++ "ae7dfcf46fbae30547b56f14dbb0ead11b3666666c45d345cd5dbfa200ae" + ++ "24d5d0b747cdc29dfe7d9029a3e8c94d205c0b78b56d5e18613b3169bd44" + ++ "1b3c31513528fe102f9bac588c400f29c515d59bbcb0725a62c2e5bfb32b" + ++ "5cf291d737e67f923080f52d8a79f2324e45a3bd051bd51bac2816c501af" + ++ "873b27f253ef9b92ba4d7a422e2fb26a35c1e99eca605acc10d2a60369d0" + ++ "1f52bca5850299a522b3aa126f470675fa2ec84793a31e9ac0d11beab08e" + ++ "2c66d989a1e1b89db8d11439ad0d0e79617eafe0160e88384f936c15eb15" + ++ "ece4ff00e1ba80b0f9fb7a7d6138bdf0bf48d5d2ad494deae0ccf448c4bd" + ++ "60f0788d3f2b76de8ad1456f7572bd0ffd27bc2836d704d95e9c0df34571" + ++ "9dab267dd805577fafda03b834dd225ad9714d2bd182b4103faa5975180f" + ++ "90d5d6cac1825a19b9d4c87cc825512ae9dbeb33d2759c990905050f960c" + ++ "db3eb364c15b593524c882902b2a1d7fe40ea3f54fb0202fd8821463c7e3" + ++ "4b02a1209ba0048a9805f0468a13e03d18009318ecd92042959be263a51a" + ++ "407f1e660632c4247419659a4e073a8e9cd4a226763a7daea464d5427270" + ++ "7efd053cb4efc0504602c4f63e7d247b55db2ce1c07138f585d16cec97a3" + ++ "0731d5aec2166cb4de41695feb76280cbae1af8a2e67c2d5a3ac5487ffe8" + ++ "640f308ace6137e83576b79d586b663122221c20aba7a6bf60f73958f436" + ++ "59f087f850ba6e2d7fd862249c5fa6b20e3e43d4f2aa10d4c9cebfcbdf02" + ++ "6b8d103e4f89b93dd8af172f421001c8b162bd6d0b847a58ac108b6d6cc4" + ++ "9c7a9ba069deee", ++ }, ++ { ++ key: "e3d21f9674f72ae65661aebe726a8a6496dd3cc4b3319f797e75ccbc98125caa", ++ tag: "3c95668130de728d24f7bca0c91588bc", ++ in: "baaea2b4b4cbe9dbc4fa193c376271f40a9e216836dc35ac8012476e9abd" + ++ "43dac6b9ce67dc6815904e6c84a5730cea0f9b4c6900a04ae2f7344fd846" + ++ "58a99513ffb268c6899dfe98d605c11e7dc77de77b0d30986f3051754503" + ++ "7c26be7b719aa9ca1140cfdf4c586b7fe726a8bc403249396a11cfee0a6a" + ++ "f6c5e72259785cfd13c2897384fe527100170001ea19106aed38f7d5d9a7" + ++ "ad43f0b41451e19989192a46b4f9734a774b6304cb74feb7d83822044a24" + ++ "2e51d55c0b8318e0439493bd1a57cc13f6079166cabc46877d003dcd39b2" + ++ "c0b90f6b32fc77acf04a6c125e11b35d91e2b18401cd53df4aff804e3c67" + ++ "a8bb3894b27c6e9b0070b53a85aafab0c0a253f9cfd4d3cd3be52428385b" + ++ "24a3f9f71660ca2c38474d14a0309e2f400e2c21af6e379099283ff241d7" + ++ "51da5a96a8dcbfdc43b913b29cc8cf8020eebb4a67f5bed31f2e383f8656" + ++ "8c815ff172382b425e95902e80f5fc219eccb51b656d37b56660f749e5b1" + ++ "4976a23648680a472d02ba71476e0afb29a0e084984f4eac3befbf8dd802" + ++ "2b7dca4dadd18bbe58e49c49ce48a06a71557a9a620c51e2623f818e4d62" + ++ "c2564c7ba04595cc109685869b183faeff2ac7a65049fc57cb10fb01951e" + ++ "a525332782d691f9759ec2ecd68bebb9c7aece5d522a08ce7830be520db4" + ++ "c9d60a2e490eaa0c91e37b256a97f84b39fe3c77953748c3b86fd84e9547" + ++ "a298c049cb28b8c85d59548b8dce635d59487c9de615802d16a8adc4c0e7" + ++ "80f35b9f10588a431b39b499dca929ab9d225f26e5721820627fe62427fe" + ++ "06d5773a50878b6effe840dc55bd3ea0c35168f6b6a972d57e8f88c5993d" + ++ "1ae33e0b7e9459c123753b518c184de7aaf429df078c9a18a29af77c727b" + ++ "796f5c1a501fa8105ee873c4e78c907142eb19690638a182fddb413adb06" + ++ "d66db19c7f6f46dac582bd72a6347b4427a576eb769d233febaf7be8f768" + ++ "337273c12253924f15653f9f3602b783703a81454a1dd7a8772a9ab1eeb8" + ++ "51be33e0c6c0708f3cc2012cabe8e2f0c38e35372abe27bc148fc4e1054d" + ++ "9d151f80aec0232a3a92dd77928a3678ebd7d09ba7b4e1d83227257292c0" + ++ "b8bc4a76de36bff6c9deb383029afaf4f37d5b935dc080a18665545e4acc" + ++ "195da0b9545d8902408886204b64f8548b32d012e0cdc520c17d9fb3be97" + ++ "800c2e2b945cb09a75a0a49e5d4d81c4194d91e839333b2b9b9e34d588e4" + ++ "e20cc1e911ca0a1429fa70ff063f0090fd842f89dfc5cc44affcce4e1e1b" + ++ "8b11c612f66b074c03ac2a055fd8f51ac9ed4f2e624589ff5730721d077a" + ++ "fb4c19e43abf8cf3ffa698362be8be51e92c2c91a4a56be64d9ac6d3fbaf" + ++ "5536a24c7fd0adaf74ca84c508e5e8c8bf7d4254e0c44158bd26acdf3f64" + ++ "e78438b3aaff89ac9986cef1e3a88d5bf2016340367a1cacd01ec167ec6d" + ++ "185d93a2a220d718b43ce1d429d2cb598605660b030e51e8d75fdbdd5b8f" + ++ "8677675e196a40a88285b18b24c5d2d594bab3d457e6f9e503e38cd470a6" + ++ "9ff8037c9a0a0f110a434335d954fa856a3721e0edcfb14287c3dd9639ba" + ++ "4db32b7da0670dd0a872e468e3819741d0d4ecf0a4f7a011bbae1493c01e" + ++ "642757491189f8664be3ec6437c4f3c76abfb0276e44a4d28871d3487c2c" + ++ "ce2f230452cb06184bb8620919659a7ba0a3d5c12ec25678b03403715ee4" + ++ "acb6a53d281036d8f3a085143cf5ecc3a0c6c92129caa7ac1f645c7bb95e" + ++ "4f63da38dc319e2ccff4a9006f9b9b1a38c4c39f6dc686bb82d43fb9fce4" + ++ "0c767d3ff22f52c5f9900130c65bb6a9cc7408a777d49b70946665f4a733" + ++ "5099376b276a43dc9a6382bb2d40425f6481b1846148434c672b84dd7a20" + ++ "33deb5140d43ba39e04ffe83659b6deb48629e1abf51e68748deffb756a3" + ++ "ed9e0807506b248a024cd509f539f4161366547c62c72933584e851599b6" + ++ "82ec16f1d79e9c6a01cff6f51ba7f46b67cdca09f3ab8496322b990a6116" + ++ "8d7574854a1cb1cb8f30a303dbd13a095df56dbb940dd16ce79879cd2d73" + ++ "80a419842fa1b34da668286de4c1ff5917b7aaa64713c349dc8f855d04ae" + ++ "de9a3a4d0739dfc36510b1e7bb1695418164285c44631b4b1a7c5798ecb2" + ++ "d976c1a3679a827bf0e8c662567e402bcc1354222036ad5959a6f0b8508c" + ++ "6a8c7d4a63e7dde154d778fc80a011592771d55801c7e1297b00b77f80d6" + ++ "314ebd1f5b3057398d1943599897cfabb65e7568d8fbdfcbecfd4b8a83ca" + ++ "0a7bed08ab9a656424831e0d7718c15727af7c83b2ef5eb5684aa044eca2" + ++ "ba896811246766248b20a325094a4b4159f9cde1ee349be6dc3c9a190453" + ++ "0349212a9537f65ae333c288753cd2bef6c5beb2f4164168d965a2c0fb9c" + ++ "c8c73d9e776e23d53ddcfb83bb7dfe2a1b8c781280f449d6f310faf8b53e" + ++ "89e6a611d6d3f42f2aaed5259730d149b3e7dabdc9f865bc1555374738c8" + ++ "456abe112e9628fb31efc2ecdc972da05987aafce728ccaed246cfcdf518" + ++ "3fe5dae528bbfb99d33194167e0f84d462d3d0da83e92227cf57922c7956" + ++ "4fe44648d87c69ad708e797972c44c4a5183fd5d1150a1182e3d39c3cd16" + ++ "3920f1d7ed83992bc4116d9351ae1c6c4827d1374242e374310409f32d5f" + ++ "0f38c78b6489c568b791c70394d29ea2516dcb10e51bdad862ce3339d5e6" + ++ "14fe14f150961809c36e0a2c8eb872e9f7a1c0956fbc9194cb63ff9993e5" + ++ "d0dcf62c0f49e81dbe99f3656c4dea57b766ae9a11254f9970618f1b33c8" + ++ "f339f440de240170f7a21f03ff2da42102b323ce2b9b7d0de5aae324d1ba" + ++ "c87b1e4c5279a566bf659778f8b03882aded57377a0f1b063af2897060e4" + ++ "23be7cefd4aa9a28479c16773944d254fc21d3e1acdf508b7972372b5991" + ++ "3b8b088e93471a7d54c6ae4c52ba465ef07f19f269677fc2f64d3fb3d7f1" + ++ "9069d6c7001d4b002ed6683c59bd5651a450503b68a4a00820b8c17e3263" + ++ "18f32c21dfbcb2a02a104edaeff67ec09533aaf3d1a7fb41aa5d506ccdbb" + ++ "e6e35fa0a263c0aad3acc91182addf8c5bdfbd0626702694b8d652a63c65" + ++ "8d6b2b7c75d015630de508195e1fca9573b61bc549ca017c4bd888194d44" + ++ "3e031f36170215a301f922736a819f3ffda69117170d1933300366c5f2ae" + ++ "1052446ef7c3b82c5868be158a881597132f51c91c80c24ebf621393dc45" + ++ "05fe057364a76ae67494a8a5f67acb551cfe89f447df272ed9c1509fc330" + ++ "2c3e16541452d4d68438f26858724012ad3b72c094b9f166c6bedb8336a3" + ++ "41e032988f39cf53535789b320b5424d07b6bf5f8792e3aceb0e868765b8" + ++ "611d7905089949e0c273e2410c72a146cd63981f420405bd883e5390e985" + ++ "8214a8db714e8400a21d0636d7e5d9671a3582ab9ff032170b8dd6b9d5a2" + ++ "144d065228fa54aea9a22654df67f3f62c5fc59d68914d8b219829b536cd" + ++ "2ae937ecccdb6031d94cb3", ++ }, ++ { ++ key: "84373472e362a356bd5c9b50f55c588d067b939009944f02564f136c62dac36b", ++ tag: "12dd5297cfcec53deae1dd5f9325d894", ++ in: "860d9b2954c3daf18fd67eb8bd9e6e3de2e4988ad9b04b1987219204dee2" + ++ "388db1c59a935de27bce29e7cd3ebdf038785efb35eabd4c3785a62b1d9c" + ++ "3ffa25e2273cfe5eb10b4ec6152cd8f21dea415421b452efc7cc4ea6bf1a" + ++ "b85fa6614e7f6d650125424865386ff8ab53247a63ff023b2d0753a9e5bd" + ++ "458d6ab0156fd3cf2d5002f902f927a847e8c4a8426b0a5191f5e237d590" + ++ "2659ce9be9024750d1d618a6b8dd57efb6c2bbac2930858f1132639391aa" + ++ "9e8a620a2a7d64bb7e943c77753401b5b619d95ef857df25a52b4eb97372" + ++ "a05416706b2644e2687bf1d42c0cf06e5eef8a1fc7e178440bfebb85c44a" + ++ "4837f69e43a1789728a999c5e04291576e757510f22bca11583a4e93688b" + ++ "442f2b2dab8d5ea9441ff09b8287862ca538ad979297cc75510a3d9ef36a" + ++ "662b4b7c373f184202befa5bf3f315642e6210763d033b7e2c59731cb356" + ++ "045e9470bf2f83cd62f11b3e904b0c0b1be99bcb805150ba7ef12b8df3ca" + ++ "bfc5055640687d710ab88e0fa8034b26112ebfd044a4b290b1c6f6d18c31" + ++ "ba9880b1cf2d81b5d02f00d6d351da5dbf47b6a5cb7b53eaf6de52c8a68d" + ++ "053602ccffa37ccb44a7683ab4f8a58c4bbc9e140e4e6f3cc10a5c07ebd6" + ++ "070818db983f9f415168606011efab6b8d7b4e61e8eadd8bfd8d028b89bf" + ++ "b0a16996252d7b4ee4f9ab50fc9d6e482ecf99beeabc38d70efbb9a0d4b7" + ++ "9a1c5d2835adf8e25111352eabd24d562644efc97637f695e4792f2049c6" + ++ "00f4d889ceb951cfe289adf159865d013046985d7fe2598014bf2dbbc528" + ++ "b4166fc2180e724ded8e7ea1c8d66338ec50d955d5594a0a7b4655338b70" + ++ "e8978485a722df814fdc6fd2436dbc060121fcb575672b2a5e454c1209bc" + ++ "2bb21a99d39dcb3c697306dbc2104d60fd8051c43ea2fce268987d0ec249" + ++ "a5c02f91d3b0dfee181b3cf8ef1ba9665daf7ea1f1d3b216e378943b78b6" + ++ "bb41e5dba095748bc776f8df6383033a1f5504955da3f42153b1c7ea83e2" + ++ "f90b990ea0c5bd3906b5c4060b19f447ec7762916b8766e5a23bc4d39cdf" + ++ "8e27752df8129b60ccee1731e47383b589d4fcad865eed4041a186df206e" + ++ "9fb69ab6ea092e36f186a6fea8d77bd7f3ab0fa0e29404d617317c75c832" + ++ "854427848237cfc18486c95f7213b9d53f324da036e8d298133b5003984a" + ++ "b9d71836f9f1b059db90005a9067c261bd85aaeed4d623df2220eb52b73d" + ++ "d683abcdee5cebd411996f853752f638bd28df6d78bec2ed3e00d7beea06" + ++ "2b81c19682ffb2f6abe3a3623a2e0570650c1384f1818d76fbefe3a7ef3f" + ++ "46138160ef897f9934e00e066e215230e719c23905dc60d7fa4d666fa52f" + ++ "e7737db15126d3262c3a4c385cdb23ff3b56c131e43b241f4a6062a1a248" + ++ "de9f13eb82c11f7b6a22c28904a1eb6513cdb11179067b13c7b5f83a58c1" + ++ "4f2753f19fdb356f124f52923249d6e4a2c8dadc8bb0fc91e360155a14c5" + ++ "c194334b9f0a566d51fad98592b59c1cc4b40eeddb34e64f337f83874884" + ++ "0583f853398c343dabc29b9444be1e316309fb8d81304d654b3d4bc4cff3" + ++ "55fc31278fe22e649324ef10acd247c0b72397edf96a1c16bbbef0640296" + ++ "4d219575fd23c36efc1fb8f8a34b510ba9bdfb3b478e236777ef7c6c47f5" + ++ "5a2bd0383d8eed3759456ffcffb15e61985b08c022658a5ffc875821bdf8" + ++ "83f69f096dcc72a96888c3af76db57a54be701759670bf05cc9015f5bf1a" + ++ "745cf755a25b1403a870875701427f820c4b29eccc260f30113629ba03e2" + ++ "785014bdcbf34d0c67aa6aca20d2dece811788686d5a45820d2980bf7d69" + ++ "d5c820a09bad7bd95166f63dcfbe8652565c285e60e2704955d69b3037d8" + ++ "7f5e6567d95b8891276d5cf7c59047d10a02ae4a28794405e2524ec2d595" + ++ "1b36ad1b9d5265fa098a033b88aa66cd9eaf01eea49c7dc4cc51c486f624" + ++ "507a2be23f152f43709b2cfecee44945ca506950e90e70164b77e12e1c13" + ++ "0b4d1021c2afa20038f190096276cd22e89b6e7dd10fd58fa033c9d42536" + ++ "98de3f4908203be8dbf259112f840c76726d982b4a837cae7139e27182b6" + ++ "1b4dfbcc50e42d5ab8532edfbd30f668879824e9ebc34b63ff1526cda81a" + ++ "e38352a774d79f73219500e57f0159a32326195d8895d965071834876a45" + ++ "c1a3c0bc4b1638535f7d40011cd5b23343fc27fa318c1aa3f9d8c43351c6" + ++ "6148dc2175e0e620813266da3000954dfa22048f305244629d512e852376" + ++ "6248a897a3ec3e2983aaa8a0f025f18feea57a5153a59b02604ebfcc7a9f" + ++ "b03e62443df88ead9dee955e23bcf6528c278a353f254c9484a67a7b263d" + ++ "a301923a4efb6866aeaaafd428e6da48781365bc49e90cd16b2388220d08" + ++ "bb9f79d14012b5a8299a651917b6a829488753b6ca449a14e8dd8c5fd5ef" + ++ "657d627b8e7773475b802655dc033694f24376e3b01e519d1aa8365d0e55" + ++ "92d0a4adbf555639b6d75d7ee59a7d12c6c11317b7927f11bbe75ed90508" + ++ "b0698420e231206704d22dd1f1740edbdcaf19a47d66ace4eecbcefb77b0" + ++ "85cfcfaced4d2d6048ce76434eb79990f0898adb4af2c377b581ebab3f3a" + ++ "150f40dcae002d4caa60050591c0de4ba83bfd59a08670beaa4641aa9829" + ++ "bdbb720d6eb8b2f3e864a98676a67271a82cffdca2b3590a0b5f97efa5d4" + ++ "ba062b4798707159782bedc75e5363d5f5d55ec2bef70db22955adf401fa" + ++ "c3b7af937816eb25d54d9f2a92e5a2a04bd8b8d7568204fd289f5ed2e033" + ++ "a76209d288e11e8a4dbb06b9029e90cb186446746853f02d738e06bba538" + ++ "894e03e2658ab3d7f9ac861d2cffdf12396004d1cd15f18812d3803ab9e0" + ++ "6f41c9b374d6a0678bb82ce06d9e3b9dbc8d2e90b8f64d0d040f3fa8a3fa" + ++ "8be71d2b3183cceae1bcbfa2353689d842f7d7052e5699dcc70ab2b58761" + ++ "7041e5aa1e2f41911d525505f061d3ca45152f5a7a1fab50c674e4597a52" + ++ "b46aafb4ba57413879cad1308321843abb7c39696fc2f2e225878bb1191e" + ++ "e151cc76f1a1b8d491c1672fecbf710db82dcd32554361967fc839c8e5d4" + ++ "e488856e1b9382eb3fc3bdc3b6886a3cd79761b02bafa080a745ef6afa26" + ++ "822f1d10d5e8eefb842837d82c9986e78fc3390caa142b7643de8f613e5a" + ++ "890a57f5883409549537f8139534f4ca1b60f33e42be25433f1d82add530" + ++ "6a4cfce258c0d4f1f3c9148ffb5c4b626d51f78ac20bff0393b7fdb4b9cd" + ++ "70fee7f69892c8a9ee089c6c5c7bee0a1b825e5b9517f2c82d6c149735fe" + ++ "45a8839812c2deb2a355b6230697053092eca450b7b0d3242b2689efe364" + ++ "09e820d91fa4932034d96495d9dd3baa4b385da815a7cb69438ff648b326" + ++ "e7efe8d688e88570ba59df7c439faf72c95317a10c984c5ec0043407e9fc" + ++ "9b46487810eac19d2bb40e0a654935f76e7d8861480c5f48419eb33084d4" + ++ "0e1070e5ad542c94f58b49e67dd05b6637a2c67d41451b7e00ba30eff221" + ++ "755d6d427ec634a2b95980d274a89579feccf1c7df3787a9435e588f2496" + ++ "06a93b7ac41c8aaa84b91c95cad9463d4881de7353d95b13bbde4c9da90b" + ++ "f1fe96257309a416407c64368b5564f022c4a493f2a39df1696f45801e42" + ++ "a5", ++ }, ++ { ++ key: "2d0035a30d19b9cbc7a27561f3ab474c01115c4499b4adec660ea06ebaa1a14c", ++ tag: "a2c77b55cb0c076d8ea83cfe0e64f293", ++ in: "4e667580ba4f38f64e5cb5566bffb486dcae10cd17acb3754251e837767f" + ++ "16429bba2b832f29ba538f97f3556548d163be25e69f88fff0743150623b" + ++ "e0a1d82af9384ca335927a0e9cacc3dadbdf1e24fa5c81f2602d109e1400" + ++ "33929e409b9a0fa4f2653944edcb8b3ef963ba7f8806196c73bff0ded670" + ++ "c6def5d240c5f3daa121f8d5bec9b2a0b0f1d62d54b013dc742d6bd46325" + ++ "460f692b76d4991f0796820ddebf150c7d33829795784dd2759b334d2706" + ++ "70a7264941be5d99d460d078a9eedc3660cb3176ad302f9365f0bd698e46" + ++ "9f3e63511abc81109995dba17be1abe8bcd28407c7fc8d02c14794bb033e" + ++ "178a94f6dc73719d5bc235f980a16eccb4121ca83b13c4e165931ae4f192" + ++ "4292f8cfdf1c3ed40feb71e13d919b48fa296dddb4d23114a3d86ec10f16" + ++ "f314de4cef813ed24b49f4c7bc44cb8424df1f70e8d77366161c7cdd709e" + ++ "97610aca3a24fb2202ffe15eaaa25d711cb5179212a2c6497a13e5d7c365" + ++ "7bc502b3d2ebde2e57b714dd9bc21e73795f3d35d620613918c4c9aa0e89" + ++ "031481c97a5a4c15ec6abe42d40498c33d71c823bf1d5bb5fee457e2fff0" + ++ "bf777c80c6e3336ab3ce793440e74b336a8f7034f6ea2e4ff5ea4ea7c350" + ++ "65cf2ccd2da1d6df29bde10f4cc0202b5e4cf7ed097da49b970a6db41e5e" + ++ "98f3845b42f46663b1d1ff01da71389a8737ba8f51eac1ef357ba5ac9a80" + ++ "dd2c7f9476111dcd651fc33f4c86dc8658656f3f02a8878bc38ff0d0a1af" + ++ "2e31fb92eaef08c50195490818661feaf90e8b6f5daa1ebedb2cdbc8d5dc" + ++ "16db3505f9611ac46bc37931e02c1fd6aad6e4b7e187d5e6f990fddc9563" + ++ "2b33f55bf68b0db3890b11113ecc839a4fa4de25160e574289aabe4d8fb7" + ++ "9cecf9d2fa75ac8d0195beefbdfe0815f8d7d9751c1280a29b547149ec7c" + ++ "2295f5afa53cfb516158086bf203357eec2a5db71143f996c81555a47f92" + ++ "209719a71570a5553f1ff9b4b41827dd74657b463f36623565f0c9f4d2ee" + ++ "8735d6af56ceb3b3d0ec516b22f0ddafbc24647481f61ab169e2616c91c0" + ++ "e1f6a35436598ed801670e1dba76226cbd0544959ebe70f836c8a7df575c" + ++ "b907d780ed5aa0d6e4e8e0d2f457efe89a777374aa49d4961db96dbb787f" + ++ "021d99231001360d532a70ee1fb94bd6f26524dd4b7556c6d40e08723d7f" + ++ "9905aca66c4743f2bf8b34493bdabcfca617809a867bfe0a4f94c756a6a3" + ++ "dcd04ffc0a3ac671a0afefe0d5d447efcec48c6368998760db6a572676d4" + ++ "29b6d3d6e0c815650447748c4b27541c5447acfb8f7261b6378f3fc0fdd7" + ++ "375eb9d458648c7fe9cd96344f11aca912cc5098e9ee39e0b6794cc1dc2d" + ++ "f1b10f927102705efa20e667b63a91f935c17764650b287f5289d5790766" + ++ "555f31985c5aad94c652ba41fa9c0195d15405f1fcce9e23054a42c8a252" + ++ "da83bf6268782ba44edec5d8f94a20b1830cd1c5894cc6b9b52ad0b12a5e" + ++ "cf3195a32a0b02483ae3b954ac6f3af1e0f334221279d03a72138f3a2cb2" + ++ "1e706427c4d604674dab88d429f28a67be7a996126e077a1dcf8989d90d0" + ++ "8b08f4abb9a546b3c64ecaa287bf3468c59add86365b885f52afe13ed8d2" + ++ "69ea61832a7ecbb96ff3336f58a1eeaa6dde3611f3ff7c2cc8c9b745b0e8" + ++ "b5919914245a49ac192cd77d10deb9a249623f696065a532c20eef9e9b0f" + ++ "e706579566a9eeb14d4e8251a7750e29eaa60f034c1a7a1d51aa03a45fff" + ++ "89acf41080deec5506128b06f003fa46bc4021a82fad6a8052a49744ed69" + ++ "45bd9331b5ae80d873cd042bff079b2b9d8af8065a22c449c32a56dbbe7a" + ++ "80d0f3e30b9167532506915883dce0aa9cb749e4368c595c5bd33b57e36d" + ++ "98cc9bf91cbfa47331d69b5cbe9c92bc66c0fc9ca8717bfc108e1f710333" + ++ "14dba02a28b9aa05890cb01ae9175806c3c4215bd446f6cc96ec5d08982b" + ++ "4f83cd1646160e1d306b3cdec02d251f0901b03e8c3c35464eaa5082586b" + ++ "b55482db97599d513ed8d7a82e32fae302684b7ede058474c1fac7893444" + ++ "16fec93fb982accd162dd956ba2f31a894e9366eca00e6e997fbbf9a2980" + ++ "8b83a139f6432147a717381bb8baa2205715f735c1e0db273cdda6897c9f" + ++ "39bf0d7eb7caf93f657ef4d3fecea28baf69cf36d3cf347081df3114455e" + ++ "b4fe3e49ad3c3f14435e0b39b6c0d16db0fbcfd7ba8da8760d5952c03667" + ++ "251e7a4c3008cfb0904225e55c23b884bb09d26631650460c4240bd5a165" + ++ "b531ee76ba5749b3bc60adad35de519321c1672b47bc35fb59f7792a3495" + ++ "11b2bb3504ba4a28717823a27a1f99ce6970290b26efcf1e7a0399b10eb1" + ++ "0c1299c09b80f4520d00e7908d004d5b6a72a411759cfa9523f6b2912234" + ++ "481b1d8fe4c2365961c0528bd593d42bebb398b5836ae6ca013fe440adbb" + ++ "0090e8ea274f4d8bcae483e3663051a328f7c12870b40e4973a9797a2336" + ++ "3d3c53e1b0d1a9159bfb26158f44734b3c34b571be641bba2db937d4ae1e" + ++ "edc807b95b1c2a7d44804885536316ad38aedf0d83b1519661f2bb5283cb" + ++ "9c50dd61c3753433e988189f26962d1f4befd444257d0b6d5b819d5fd572" + ++ "22c9fdff032e07a4d8686d451e71de4748965309c0a2d7c422ab7cf3d96a" + ++ "8c0a1b0afb229debd1c9421cb828b9f2be96bb9d6b5be7ef8134bd9ccf81" + ++ "51620937d720d83dbdddbfaba8ecd2eab6f1974090efde0ca963e9fdd691" + ++ "ed0cc5e074c5780779222552fa46ddcd951763a32aa3a044ff4a73cbab41" + ++ "dabb3c2c03fcda68303477f0dc26f35bdb5c9bde721fba1a2db732a89629" + ++ "a8de3cfebc3918df1a9d5053d09da5b7316e3285bf62156ca28cb64d343e" + ++ "72445fd66757bf4ab374fe7932a65f3d7fb6e42cb12e5b67ddf8530383a4" + ++ "6c1ee7ec8883e454a467df1aa7e468a6e7035515f473901efca5d46ff358" + ++ "70e0cc2575bbd7f8866c8e73cb157903a1694ff3051424f28de826984dcd" + ++ "065dc3658df144ae3a6d37b88c367e3cf7c58169dfdedda4a2821ce22188" + ++ "40472ff72f0dd1a6b0100555ff188b80f835259a634405e3dad61fc299f9" + ++ "307e27503b2cb7714bf3b636cc64b61d2e374119c8ef8adb21f1516c7fe2" + ++ "38c807818065bf312003c12e02525d69d9629a99e4ac66ad2e792f302cd2" + ++ "a6f5f702dd28040738a084a7052f2c3ed0924c33b7a5d357b7c9a29cebd8" + ++ "621a4bfb7bb34676ff210d59f7f9d4eafb7c5c490c9ea48402af5bb072c4" + ++ "731bdebcbed4e8e08a67931b6d7342d4ef7bc4a75ca1dfbd32ed6027d8fc" + ++ "b71e3f55565c02e06daa8c579b69774889181291c470576a99e11f2c5acf" + ++ "77e091ef65ed243d4287176f7f6ac7aba6908c9ff1fa43b894a499b642ad" + ++ "c01b2fa1c4b58801411941bb448f1f7a04794d2cfe5db1be61f7b86d6eca" + ++ "c547ee51d4c9050f9e9f318dae958c150acc21c878f0c7df6065294eb1d9" + ++ "a278c920838a0db752b080a32e67ac312fa76b589a385f31847196076ed8" + ++ "1021fcc375bfcc8e1361878e2693860eb21ff0595e4eaaf7897f2b79367f" + ++ "7c4f711279bf0c93a97dcb1cd8d87e444ad5f4cb5c1de44e37868c6743f1" + ++ "cd72cec376726f26c8bd4836f9a9f9c68042f95ca6f9d7cde493e531c553" + ++ "8bf7ace6dd768db69ac7b41ce93e8ca27ff20a83ff2148ec5b89e05d8b8f" + ++ "5d78d0fe16b96f6eb8d3b20126a186085c6825df81aa16b3dbf57eabc360" + ++ "71299ccdda60e250c652408d9cd1da94d73c728440ae08fddb901aec0fac" + ++ "1050a778b10f94f84883bee158bc53b1c001807c43a3151fbf581b18dda2" + ++ "527430872834e5c380575c54b7aa50f817cf3249fb943d46933cad32092e" + ++ "bfc575bd31cc744b7405580a5f2eabe27a02eec31e0d7306750adbbb9f08" + ++ "c78cb2d4c738b2274c7310cbf8dd0e59138b6a91b8253ae9512fe3d7367e" + ++ "a965ac44d54a7ed664e5e5c3c6c2d942eac388cd32beffb38f", ++ }, ++ { ++ key: "2f29d71d73f7af98f96b34e939e1a21e2789ec6271b878bbebd14d7942d30080", ++ tag: "ec02f4953a9a63ab6f2bfc3501e4fab8", ++ in: "0e0950987f3508239063e26a13727fefcdfd2cea6a903615c64bf12d9ed3" + ++ "887f9b2cf7ccaa196ccc7756b09471475b9daefd4261e69abd23b9faf9c5" + ++ "1fd5d5788bb39d3c068fa6807d30f6201d3f6dfd31715d08b1733440cde1" + ++ "049608d23c4e45c5ed61f863350232f85827e7c292dc5f1eced1cbc912e3" + ++ "f5c420bd945911d3881ede5153d3b2cc85371fff98d2caf97cad6ef59001" + ++ "4017f9690cab08989851c2647e77e81401714a93ed9f938b79f8f54e3133" + ++ "fc2cdef259df2ba0d48f37bf9e43792e3a777214cf4aab6dde6deeb543a8" + ++ "813b71b5974136c1220d6218a252881f0f5677ff5b6aba127f19a5f3c5aa" + ++ "c988543d7839a90a3f947c4e4d5c6ae1ab48dbd40456d1aa65339a4c15eb" + ++ "520e8ff9f965ac4c37735937cf09942e7958f8a6cddee41707423f715903" + ++ "ffe0d15af8c3140d3a736d23be7485fceb9f07c6509f2c506eda4ec9d30c" + ++ "cc133708f48d8828e332808c84a745d337296d871b9794de1c5d06534aaf" + ++ "65587526a84e2521f8b332645e0e72564bb308ecf99b7bc69608474389d1" + ++ "686ffab8c49b7f04dadc28d2ecdd0f508dad2135843304e378b3bc7a4f25" + ++ "7fa4316be956e0a021edb8045f39fa9f002087f067199bd6001acaadd261" + ++ "4bf6aefd3f098f92a959685f24bb2206c347359d9c6adc6847117bb434ac" + ++ "6c40ec618f6ae8b75a5e2e4d44c332b7b06c8b4d521493b9b0bde8894209" + ++ "717a24b320214297b62dec741cea018ea681c9b56702068528b3726953e8" + ++ "c5e4ccd5029e4183e772d9834a56a88d45bf87603dfda40e03f7e894766a" + ++ "7623ab4dcc0dfc3086d17566945069173935916f772e2a5f8e1547348f28" + ++ "782400fc069ac0e2b94242e9e0f1ba2d0e76898f9b986540e61ea64d7f69" + ++ "1006b86ce61565da75eb16a8b4c5865ca4eebdde2190e354734bda94fe7e" + ++ "12ff47dcb5d5e6ad93cfadcc491cb350b09ffe391a157e14b65e3a211b5d" + ++ "4e447c3ff95571dbab33a83126d68dfddf9383b4359d4103ca64af1e6963" + ++ "d09e17eb944aa71e76711dca33168586bfc44ebe9fdc55497d83f238c66d" + ++ "bcb16063bc85635f0f1a6280563bca49ef971db96a41b6ac5e0642643262" + ++ "61eb4662f3d6ad4cac826db895de22c9b8aa35e6464a7f44e1ae7238e355" + ++ "068d68754ffcca76c50b7ce7ef9bfebac9eeab32c87d059cc7ef2adb5d57" + ++ "c7419adb394eef48441952253e8391e555730e29789d6293c3696f441449" + ++ "0aebe2bbe541e191a6652ffbec1192f0f9395b7ea370aefc1f1cc8438035" + ++ "d7681f12f1e11d6e334da188b10c302fc0f4bcf1de448090510a8f1d5683" + ++ "0c943a3c388b33a038c26741a4cf3487313f755fe7a28e25e44b5383c5f4" + ++ "cd6ef34d7dd73462226281899dc3f2e69809a0150f694673f31addc89888" + ++ "072a7d4ecd63d6b90540f9522ec05829a7f17d48728345ad808fb0203883" + ++ "3cbd018d612992a88df944b8e34a70920b3f26cda2e8bb16c3aa38b12b33" + ++ "b395c9ba5e809f60ff05f087112151af1b5987403cff8bb2dce79093f431" + ++ "2c744f911a6f3091e4f9ef9375c4dce4c241d2f6024a1797321851ca316c" + ++ "4e460fc060e7839deaff8ab5e8bf682c0f21ab6952eb793cffe690db911f" + ++ "50b11f56ea352942c43bfff51d4360882754faeb7cf28b6b32bf7fc9ca71" + ++ "fbfe1d72be05b8bac9ba513d731e2c9d13d6f2f10eb926edaaf0e3996656" + ++ "da8718a8e103c59326529e91ebac6ed52657c9690ccbf81028cd9fb189ec" + ++ "4de94fc0771e53302c8d9082835a68780cccd772660a110a1b40c57bef3a" + ++ "c1d69428aea549ed17663a96895a66a3bb5ff6ff61dc64908df49b760caf" + ++ "a5aff05e2766a418dbaa1e7d189a9edd55a04fee8c9d6e506d299abc36a9" + ++ "d67be035fea5d220f41d081af67615fe627c4dd04bd8659c7fa4f57f35d0" + ++ "db40d9684aa178d7483ed5d86f04eaea412e0ea05a4698377dbff4fc3a39" + ++ "1f6ce0cb833d3118d6c69319b511cce65fdc74928e270da0c537f8201eff" + ++ "77416155d4a39c7ad38c22cdbf7d2b7ff7d85383c178a835ec604c3f9ee3" + ++ "7399f7dd826e34f1a35ab75da44ba56f86097ddc0f3658ef5bd65a24f4de" + ++ "4255d0b03411a9d7f0ddc29e33cb865da23393471aa94e6c9e72e789206d" + ++ "3ba118aecd39727068f528f01b25fae2280d70033e4ee46b41b864bb922e" + ++ "001d8bf46d6fbaa5a594e926f45eb3a4d2f074506d7834b606f43c89699a" + ++ "6db00b374658d9333700894d440a712a1f25f5538f9e7c8ee57ae7e612df" + ++ "13292c8ba9dbede4fb77cc6c8944aaef59ea6ad3b36db398f4bb0f82d40b" + ++ "44879835f224d6e05992b1b8a68dd58c3dbda2fd73786492ee48c7a25f87" + ++ "264b766930fe9427487504fad17f8d230934f044e49ba219f26ead728856" + ++ "cb30eecc33a3946d3b1b781061f2458c7c46f6d96f3e06f369f97be91835" + ++ "f23b38347d1e381ad5be4419275772c2abd549522a0203c1ee9c96faefe1" + ++ "df413c4b7b2624417890e0716854b7092b3b3b368cb674035d3e6bab2357" + ++ "e7c262b606f7141b6dad2f6145ebc1deb7597814719784f3c17848a90ffb" + ++ "cb0289e2f3cc7da12442b837c4e47f468bca3eb4e944a31c48562c2f144e" + ++ "9e920ab5e4cf90a14ccadbae29af13db38cda911e3c8f6f525e6722809b5" + ++ "31a4de1926ab12f643d25af87eb8610df59eded6ec278242247dc69a4213" + ++ "13f7c2b26ae7a917c1bdaf66c56876e9104d40b59e6ca1431ddb77fc89f3" + ++ "14b46a154cf127688564a4f9e120d7b5816cd24a6e095dc8ab8b43bc3639" + ++ "329719f0e0f723e2f5136d82638e2249e648ebca67cf0306741e9e8d45cb" + ++ "903bca85485c4007397c88a1ce07266f4f611b96b7e0ace3074247a7dfb1" + ++ "cdbbdd66e25e172fd2bda74abde7f3b4cb5cc7ee7859f053b2f04f9de03b" + ++ "a8e96264117f502087c3ddbee8d850bf3618b4de90f7b3e562dfa57e4426" + ++ "5357236e35e71d1669226d63bca50b1b944ac07a1f794e73e80985689b25" + ++ "f18fc709367d63b8639d71865cee667536040be827145c08cf3e57a66678" + ++ "4c81115706a146eccadc7aa1a9f074b47e95bcba7db8108a13279077bef2" + ++ "64699fb87e5abf5b05ff3879d7c7c5169c7cae817c13f0859d4e9c05db0f" + ++ "74c045ecc30a51e515feea627da387ff780719395b5b9ad93179b16fad10" + ++ "5856049169dcebd43a7f39c549762405f807378e854b1654a1179d895ef0" + ++ "85aafc72c7fe1e0e1cd3abf8e20935e331145bbcece4f17ad24ebb6c64ea" + ++ "73bd98a7494c134859206c9422f7c4a057db0ae0770c4bcb08c1a6b9ca4b" + ++ "7dd8c1cdb3e4977c7ce6c1e79b9d6ad98e27d2759b53cee73ec037a8b686" + ++ "f1ff78eb8421f41c74ce9c62a90d38b75159ec925f232e0db71362f31e29" + ++ "4336f5580a34b26c5a01ee3454cba227c7f400f6889a319d7121dcea27b9" + ++ "584f33ac796d48a9a24cc5b6799ee12f10725fbc10d7cf83e4b87d9c444b" + ++ "f43e2f5ee49d8f3b531ebb58fed4234cb8bcab1b8b18bf50956506baae8b" + ++ "c1b7492250f3adf64294310387f1d4bcac12652895d4f2dce26f380733ce" + ++ "0b5820e9fcd8512a1585a49940a32fc8875ac3c9542a4270602e5e97e720" + ++ "90ed71b51badb775340429fdbe45b887fb9ee61cf9e091c06092cf0a2129" + ++ "b26572574c46910cb458bca7c63eddd29d89753d57e568323e380065794d" + ++ "3fa1ffb874543f5b0ddc702b087e91e22604d9600d37fa0dd90d7acb2458" + ++ "4cd408a4e66bb781dde5f39efda6a8fc26be0d08ffdf851e422ab1500c28" + ++ "bf6b4c85bdfa94e8aef5cda22870c39ad49c3c6acdbb3b0d58cd05424c65" + ++ "20740b5c2bce4336545eda12716317df58e6fb764fcb3004f5248c5ccd84" + ++ "f63abdc0dd2a64e447c0de4da4a1082a729d8ebe14810d396933085cde18" + ++ "318278481fdb9a748b637cacb491f5234bfe16b53a35da6677336baeedb7" + ++ "4a28c19a412e7812dace251446d40ec07afd63854c3dffbd5c0f6a9a3cac" + ++ "ee3bab07fba94800fd1fa0fe44f5f2ecb2b4a188cd02b8a2df0728347c50" + ++ "7d0cc58fcd5d54dffdbda11dd1bcc59758396ed8db77498fbe13238d3d8a" + ++ "0040194dfe66811542ddaa658094a9580d4e4b4e29", ++ }, ++ { ++ key: "1285f117bd90b70ef078ae62f37d2218419e894b7d334759ddb2d88833b287b5", ++ tag: "429b2b39195a10357043c9601590a277", ++ in: "00ef065a1adb4ce7108b497813ccc748933fa8442689a7cb8dc7c1ffdbf6" + ++ "c09adfe05ca2cc5ec3acb7493f3497ee8f9cd9bb8a4b332c18e33f78114a" + ++ "c8f9a72ddb9f13494e934ad711818909831013ba195b53f5e9e5b4689399" + ++ "6d0b669f3860958a32b85a21009d47fddbc8697b7c9b92dc75d5060eb4fb" + ++ "40aed7a1dbe69dbbeb6296f5467ea2426cd17d323671fa408855bc53e5c2" + ++ "d111203ae38cecac7719c0bd7f21f6bd6a1588187b3b513983627b80ac0b" + ++ "300b7fa038af1cc8512403ac2cea6e406595202ec3e74014d94cf8780ed0" + ++ "33c570e887ca7fb35ee4768202aa52427d02c24e63f7f2cede95ca9909e9" + ++ "dfa86246a27db757750667c198c9aff4ce348f7ac51864b36ef5695df713" + ++ "d17b8f561a972d0136bd9ee9aa16079c2ab5d29ac9ab472255ade05dc49c" + ++ "b966e0c1c04258ef9ec59ded01f402d9fdcd9a2020a2038a8c78892ca218" + ++ "30136069485527069132959dab2b81c73ca590fde2a7ecff761d95a54d63" + ++ "a2664aa5a6deec163e46b5225bc98976a4f363063b0f42e29f792d138af8" + ++ "eae68d3854b5c1985d5cd1c9f49f529b0b4d2c936887b5b92cdebacef992" + ++ "c35e0b7bbd52114aff8c6b261852e28e451b02099814f809b0289cba0586" + ++ "04a363e3f969aad3d982f645ec4c549f943fb360fb8fa0d5a597bf89842f" + ++ "8ced6014a5b2590ef71524a7ad50fe0ef0e2f81b6e26b99f9ebbc8036549" + ++ "f7eacbf6ab884710c6406ff59788e03ede35c30d4781ad5af171e0623e8f" + ++ "cf5344d71165f0475e256e9159040f702b359a2963116ed135dd6c1d111d" + ++ "2a1e33e15c178ca4f02c5fb15593c50cf9a8a492f01e04778dbb81d26c99" + ++ "0c58cf50a9bcf4fe38fbfc0fc0685d8bd422a773c7bce649f7a86c59118e" + ++ "f5f857b2c72508cd1ef05e1a0c0b7ab4687fdd57437092eb49bf41a9ae8b" + ++ "bd98272ea2f8ee2515ff267fa6ae892c266a7effe61ed54984924aefc461" + ++ "6cf483dec024ad666bc797beaa429a742d1b8806f67d451b6d3a85b4d474" + ++ "003cfe9e9dd906df47da5559c41f15afabecc3e6af279cca0f2a200eb2e8" + ++ "31437e034d457fc880f60f5ae635690bce82bf6d1ad6b4f5344ec042bf25" + ++ "7d010273c861e3ac516e9ee2bab3a255f570baa32298467bf704bf6d9076" + ++ "a4c0b08a528a05cd1fcbdf51f3885fbaba7891a144fc058919903b269b4a" + ++ "29f43926eda32c38853b814a7d528156c223748d674d8f7f5448350f011b" + ++ "bfab1511001b8014e20fee37ccd4a0456f638c197c86dc116b34f955c0b7" + ++ "dee10bac5ea0c2fec8a780ac05098b51b902ca6afff4db3c6fb4f761df79" + ++ "b2039dc5f16d9402442a6fcf6c4297769e6c36824d908beba8e584ea0b3a" + ++ "91b9017baeefac651d0307bd89f517789236c0693c65a5a20f244d39684c" + ++ "eb810cd2ffd3c78fe9285d2eb9f55d133b86113efb8dffcbc6d258e84c38" + ++ "2dd8f4d7d63b65672516d9bfcc3310a79ce244b60d380128d529487f99b7" + ++ "d532d5f5c28fad8b9a071fd2fab8fd98f6d7ed9dadbd2fc4396476eba6e2" + ++ "1a1b1cc594a31fbd3418d98e4aa736cab285a2786fbbd4650e49f9b080ed" + ++ "3fda34941c28d25545395e1408fc3e60730d0696061f821a4d24123cadf2" + ++ "3af3d37ba7ce1ba3cde1368d468f136df82c02f9be9210022192aa02117a" + ++ "ef5ff70bcfeffd47bc37b920826a4d3db001f956939abc0df520f3ec1613" + ++ "ba1c4b3385cad97e42bfd15a3150711fe86ba4562f17780cee1cdf198615" + ++ "ca06270db84986f33e1d53d552b0da82397c496a23c7a78ca7641a908e71" + ++ "89249cc657c0431f1e09ae0213f28a27e6267e9d17b5bba0ea4f3c21f266" + ++ "fe538e215ec62f85517ae6bd87799ac5ce68453f09cbbc50d6e2a168f0cf" + ++ "7166ad50cb65b6c76406c326573c00e04a3186251c6181933828c58f4198" + ++ "f8208c4484805639b0d428fd05b57e4356239638f458a84000c7a7a8de62" + ++ "ec25b54d1e39d2579ec9c512fec475f243576f35efc02a1cd6b0478e2dc8" + ++ "be5f17aa4e3849cd42e76fbffe6e7d6f912d6edf80f718f94a7e48e1fc10" + ++ "6cac29627d9d4b82f05a30cd7c739f7f3ef7ea368d22612f189da450e274" + ++ "de7b61c6361521e684d639be5af4cb11fefa5fce6f8a5065c90873e504c1" + ++ "2c940571ea7bd7e9221129b83039d2edb069e8b5bb68567d8fcae34c6ee0" + ++ "cb94474d8b056cc3c7403873f2fe6db3b567a44e702e4f4813b2a264231b" + ++ "0a998207b41916715ef94e5eec281589d0a711f8e74be32bc60f43d693de" + ++ "77f21d5f7eef892abe87725f3d2b01d9ddb6dee15f40735a8fb67766dbcd" + ++ "020a93b8eef4361dc3a891d521551f65dbe6e3f68c60819b0a540b0991c6" + ++ "4449d207cf5b1c198c17ad6caf3adc628d09fa0baae7a696d84e1879577c" + ++ "ffe9b3f62669d4ea5ebab6364f08c66d170ee4a94d61fb77d60b33dd6b60" + ++ "650f034c5c9879243d5c16f853dd7a89885a9047a341b076912d47872b3b" + ++ "3de49edf7451b435698ac4e182d16c339be83e18531a34aebad36c5c7c93" + ++ "aaf121cf99ff92d3844d40740fe001eeca9ee71300d826bc3cfc87a29d39" + ++ "ea108a3cf259657ec4b967fbb534e7513ef3a96bffb35abc5ce0e890696e" + ++ "54fab515af3d2c0be6e003747504e486c0ec6e30fa4ca79d6596ae0425f3" + ++ "396e40fd37432e52c74f812250dad603b3502f97ada48a26e39fd4d44584" + ++ "6591bfa5ffb3770d95d3dbd49e9c3a38c6305796b8f7d79bd0845170925d" + ++ "575774445299bdf9d3f8ad3dc2dc5cfd3ef0293b84d6e11370851af05ebf" + ++ "b3510a22edd930797dcb76b759a9b5a77ed8dd5130e79ff5ac44b01901bb" + ++ "79603cecf674202bc5d84076ff41b3c806454ce80cb9e5fa9db77294d20e" + ++ "6d3008ae3017aba712862ecd4b32daafef1b8cc8b19ee8f8bc3835e2372b" + ++ "5cec66222ad5ea9df753c033508ec43c8b5995e88c36c13ea3465c8bc462" + ++ "ae0a659d9767db34499e9d01fb1588410257d6f588b3fdb766a66bce28b5" + ++ "e0880f8cf988a2e5eb5bf80cd7d83192b7392fbb2e3a07d51aea2b6bfac0" + ++ "d74d304f56d5af3598a0712cb09c04c5dc14194eca8e1b9b29f88344c0ea" + ++ "55638c0f8ebb70b6242b797fe2525fa1bde76293dbc0a66ab4715e6f9b11" + ++ "f7ecd8f35a20ee4ff3552caf01bb307e257ec0576023d624d6094d43d25a" + ++ "aadfce939a6808f8baacb2109c3de50a1cfada9e384cdba3e97d2c9025a3" + ++ "2377bb195fce68c5569d2d1267e1bc68fcd925ddb4acf567fb29ea80517a" + ++ "7e4056fb014cdee597333ac2408157ff60cfa1afdc363a11fd4883308cab" + ++ "d9a8fe56c2b41c95eaef854f20bf5941ed23156d86de3bd413465a3bc74d" + ++ "5acffcd15722879849c261c1bbe987f89a1f00b3069453841b7da667d566" + ++ "e41fd894d94de44c23fed08d9bdffb723aa8449bf236261240d865efd7b1" + ++ "74a4460e5004ff77f4196d1d421227dff7c78f1726df7b5eebddb4bb5f57" + ++ "5ade25296dda2e71ab87ea2b44ef2ce8742a7ad5c1e7a40e097eb336561e" + ++ "865515f7ee0efbe01d5a928f208f7c9f2f58974d1c11af0e737c673dc446" + ++ "1795da9757010cefc6e7f2784658717938735ed8cbcbd7981a1bb8f31cab" + ++ "b901c87a3218dd1195c59f64d0bc3ce8b72580fe38e6dbf1181e0090e5c6" + ++ "d162df9f31cc52fa6a8ac61897e9b4b3cb0ca2bfb38a38d9b78e46d775d5" + ++ "7645d2d6da16bda8edd8675e2ba121f7f85400cf7cacb9ffcdfae583fb93" + ++ "753d07985a00afc3a4e26c9939a5116d9b61196502f5d774ab4c7fb6cfa6" + ++ "01bcfddcfabfcd28055e858d7d3c19feb6bd7c02565add3a3af61bfba8b6" + ++ "f4b52c072a8613e878368318383143059a98a85ba521f781a8983c2486ba" + ++ "b83f5b91fce02acee0be8d0dda7489975f0506c8f363b5adc48ba971adeb" + ++ "4e1c830b5f264ed42da36d2b5ce2fdab1e63333b1061ec5a44ec1b6e99da" + ++ "0f25e7f7250e788fe3f1b8e64467d3d709aeb7360720f854afe38e190cc0" + ++ "925c6cbd77fbfccc07d8beeb0ce68e47442fadaf13b53c30a03ce317cf79" + ++ "dc9155ddf96814583695f15c970fd0b6cea0b04b1825eb26e65ea9351bf2" + ++ "f7a841ddaa8c9f8e885b7c30b9985bac23d3ce777b", ++ }, ++ { ++ key: "491ebd0dddefc9f0117176772f9bab61b92a1f1de13796176091c56d1e53dfbe", ++ tag: "fbd3f884a3dc2a8be06ce03883282e1e", ++ in: "953b9a40789b206fb507ec2c5e9c88ca1baf25ad24c11a62f664db1da8bf" + ++ "dbe9b54f8e93b0bfb4adb12f8873096b8960fd91eb92a8ddb53232ac9141" + ++ "57caced33424cff943a8db129049af7e7b733afbec6637d8ee4f39d063e2" + ++ "be241cca6a339e48d72372efabceac57220692c40856532d95529adfae87" + ++ "a71c72f30244126d01a875375ad8836ef8db929bc81027935042a05c346f" + ++ "bc94dcc057db015e55c56064d2b11154596b813ee64b73bcac05d2688bf6" + ++ "f1fbb0cf3f8307b3df44c3e2dd1d226a4d0e9dc5f7482bada9611970f887" + ++ "f656dcb19ce1f8c5c86f4cbd1e4f49b18f170ecfd184028e769e79d7424f" + ++ "d01cb315897c21111f53f4d41c3b71402eea695272cb5b4e5f33abb9df50" + ++ "cbdaa55ed629d3ed7d93b43e550295502db1f2ed884afc320518e88be4c6" + ++ "b62a13f8d3636ba091d07dbc6c20c7e7fda016c05b2fadcfc9ea32f4ee2c" + ++ "4893de78ad8a1771aacf6efdbd8fb1f6ee9b0572ced3edc6313185b5d398" + ++ "88ce77950aa4c5201a256e3ae3e74f05b70faada14124b35b105a70e7769" + ++ "7184576b69708eaabd36e0ba885fc6bafd5738a67307a1181792333cddfd" + ++ "a4ef19c88497c82fccff05a8f9f732fc7505f0467a14e135288ee018aef3" + ++ "d0412f6b0760573d8ee4ab455d2789b4d22a42eebdf60616fe403627cfca" + ++ "fea672bd0a49e8e7b80e7b7b8feebce3381f2fc16819a8996a99ea230c3a" + ++ "84b510cf2e0d914610d646a2f45a14268ec1d6fca03d0aea5c9ae1c8d519" + ++ "b0e8b0f6fb8ad176b5d6aa620b253cc492b5e5645353fbd9b6c02bea48f0" + ++ "286e2c669782b5ffefa4d8f3f1037151026d9cca78e7808dfbe61df29e82" + ++ "951d7154f3c97606cd1e99300012578ea6a776dcef0811338b56606b51a6" + ++ "9893fe68f762af6c9c26066b1d503e64877d8cd988b443af66a36af8bdfa" + ++ "41b4dfb3721d1d81895884755b9c52527030afdfaecd66d4638fab1d1786" + ++ "3d5517ef7ee7d081b5555d24991810f1edde30930fd392f817cfe632b4ca" + ++ "6fb0460c36bde4a5620b9c369bf51c7d870c43998b8171a553d2f643fe8a" + ++ "58aabfce8cf7363ea978ff4d53f58284db822ca95b80306ec02a64d26a29" + ++ "c98520f1924c70d161682c54d08a2c48f54bb72980a8cf5babd0aaf0fd72" + ++ "7d5b1b9d9b731dc49bad228fe83f7347750e277a4fbd526983c206e075d6" + ++ "a03d68957b3e925a71bc1ea7304c77660d112a5d19fd21a785d4a8d7f2eb" + ++ "dc4183376d8125341eb28b2df5be0b4e04bbf95c47d2fe2aed939619cb97" + ++ "79548b752f57b723cf8295dfce69c9b7486b75a4e900f91926636f3fc78f" + ++ "7b7720a5151abdf5868fecf1e1a1d830cd6a4c5e3cd739da4432cf1fe2af" + ++ "a1090d6a1eeb32e7236ecfddb9d07b97220ab8e23edcc93d91abc11b0c30" + ++ "460d2027869d1c2487070cf60b85ad0b8bc5df566f6fdb0e58fd044da530" + ++ "6d277e564ca6cbfa820ca73fb6201b240a5a94c4ecd11d466cdc44046a66" + ++ "32478221bfa69b3a2cebd16baa302a573c90895d7f4cab453b11e3a4d8bb" + ++ "b5a9bf264781ce5b9796e3c47d0fa57f46b923889af4d073270a360dae8d" + ++ "51d85ea916f14787c6500d2d906ccaaa92d20d93edd09139f79bfeb5fcd9" + ++ "8c1cdbcbe9f2587e9c9094e3c4a32ab9ba56f400b929e80c0551f953896b" + ++ "e8eda6ecf22e6d4a541957dec21d6a9cf388ff0ba58169ab934902892a58" + ++ "86e1126b16118e965a271495ffa339c49466209ed3875b568a4290b7b949" + ++ "69d0465744a3c2a75c599c3a04ab1a3fd09125fe8f45724b2f48c7822b9f" + ++ "ef95af4b758ae66a8b6646df7a0a1aabe2a24c052fd6d30561cae0389263" + ++ "e3388c4c1effe431a04356c334aac64f36593544885c4b7295b57dc39638" + ++ "b665b22dcbf7dd6da867615de38c6a575cc66391135d47f8e1f0c73c6129" + ++ "17ada4099723933a758d83311b384364263cad5fe14bdd7c825d9601c400" + ++ "3537a5aca7f9da4710c132ce8b0f1464cee625633ef57f507739a0ab1cd2" + ++ "21ae634d4d0b3ff07e9ecb1baaef0a82a97279d46543a0464855cd62c07d" + ++ "5e890265612906a9eac88bec07b1dea5f67054c31ae40f8c673296cc5df7" + ++ "f0dd8cc9e643b44fd90dc2d1e870ad8acdbe165237642fd04c00965837cf" + ++ "bd2344ae830887a5719a3c16dc8ec08bd9131d055bfb959b64ff4cb638a1" + ++ "002a4fe02e369871cc4e3ffda17dd85343e679fab43e11970e60198b424b" + ++ "676ab17fb0dee10cc9c2e92b32b68d5b05b7a559176f822850c0557ed98b" + ++ "7454916e32af549a0027db95f02b88cfc5e7e05f28f53757dd97cc0f0594" + ++ "212f8801e58043cb17b040413c226dfce2104a172d218caa4353890de17d" + ++ "be1f53af6ceda24b8781801516cc51de9ca459e469b3c322be13d8c9541f" + ++ "755c518ca41a0ed42e44b9f87faa2a968b0292216e9f3d3e8987282103e5" + ++ "016fe9f7681496e1e8d663eb2d8bc30b41d735465527f19e336a98d2dc54" + ++ "d7c020bfab30fe6c62cbae7d09f84af69bc2c51a1839ffba15015d381ba0" + ++ "a44a3758771c4f18d13827f518f30bb74f4bff29a87d4b9e949f1063f63f" + ++ "662721cfd64ffe1dab3761852387f78fa83fb48ae2c75fc567475b673da6" + ++ "fa8f53770b6e5a3c9fad951ec099c6bc1e72d1c489e1ae620e7f12ddc29f" + ++ "ed65f29c65cef75014b999d739e2e6e015f928a30f2fee3f2e59bf65b54d" + ++ "89948bf2bfde98b076e5460643952befd02fc1b0f472a8b75195c53ea296" + ++ "6403b9028db529cd04b97231bac3068855fa211f4d976a88bc27a0088f04" + ++ "576e2487ac0467992066ef7667ca8429faee92db38003728e5c219c751f6" + ++ "6f011b5d679fdd957f4575a0cfb6b54693a9624f2c7e66c578f5f0367005" + ++ "c66addd1e3ab7ea1ac404e357cbdab9438b9b4f80b3a6761b864b006f1df" + ++ "689ae4c0434b06b686d5353d3e421b57381ea24fdcf6199195ccdb3d5cf4" + ++ "623a6bb1f9eba9b22fa15395f65f8093b5f90455061c1cbf8128b44a31e3" + ++ "910862a59e187aa7f4d22e0317ae6c177cef24eebc44171f70c25efac73b" + ++ "38ada0cba0b74f72d1c171277a734819c1111ebe46d5db20a6ff20e2c1a9" + ++ "a57edae95a3c1f80ddf2b12c86d3df0078a7bf68695b16ccf92053c727a4" + ++ "80586b8d87d0d1772e456fde0c20a7927f351a641bff5f22f9ee2217b6a2" + ++ "d0983c8102d7d5356dea60a19e105ce366b9d000987c8c33396569f97c56" + ++ "2d0fc0bc5859779aa10efd1f8df0909c307a9110083cc6d9748456c9bddf" + ++ "16dccee52b7974867cec718bb0b76b3353379a621257094277a30148ac38" + ++ "e5cf67ed7cc9c1bae12dbdeb99d7d880ce98e17f0dc93c5330d1824a3c9e" + ++ "ffd86f89e15b59a4bee5a48d4f674766896e187abaa39917b83f8d2f3265" + ++ "bbe7aac44c9f8d92f775fe6493e85ab44e6e28f79f28eff156c21e1abdae" + ++ "d10a291b88c4020b1ae8be001080870847a852d073e82bfc751028ac62d5" + ++ "6aeac1b18f2cff1c0c7d336bf08f8cd5099d9d3b28f9e16077e9caabab49" + ++ "f2d234616a7522a6bde1a3b3c608df4cc74a6c633d4c8068138abda8d26b" + ++ "4ca70f95d152888fb32bdee5dfad8ff4a5b002a0a327c873656db8d6fdd8" + ++ "ed882e47ce8e47c729e1292db9122ce2e9fa275f9bb986eb7e0a1dccb7cf" + ++ "abd0449c92fd35e2aedc4aa89caf53bcd28170cae85e93f93988e723a896" + ++ "10cefb4edb6fa545835fba3107e21dceb272c5a32da26fa77df070f41d7c" + ++ "ad1d68b836199ff0f1221e36b9b976b5e69bed54b5bfec67fe9cbb383484" + ++ "696265204797634594bc335150daea92dbc1004f613b4c27bf5c699debf9" + ++ "4365041b5a894701da68a93bcb61f4e546c553fe61f14ab0322b45915da6" + ++ "ecacaa093b0071f2516ca8c3fef2f1e3c403993d734403c47bfe5f4379e9" + ++ "cb5b613fde3c0d880cecef4101aad8b8b1c60a92ac5185f6c243fdf1711b" + ++ "0b56f0fd8e5ed6cc0f99da888e4f156455a0f0eb365b8964347eedd15d80" + ++ "2f297977af667ed1376dfcc610f5152421b97afaaf16f9db57a435328595" + ++ "b9aa00b5ed9ff106c66970fafef379f4d2f98f2c5984ea05aad64651fbf7" + ++ "7968c8cbc4e959859b85302a88a3c2faed37765f3f6ced59d8feb6c72e71" + ++ "f9d4497d98bccf95fcb650f29131e1df1bf06a5443f8af844aa1a7b5a68e" + ++ "bb250c7de3a65ae9b1086cf83f832050e55030d0f67c6a54ea2a1dbe18e2" + ++ "8a96c9e0dea2966997bfc5c5afd4244e3c8477c4f5e8bee8fc8ca9a5cde4" + ++ "d9c5a2c7f3d2e811b1de7ce4279229319e432674c609b4c8b70dc6172e9e" + ++ "653fe1969bbc2cb3685e64fd81d96d33", ++ }, ++ { ++ key: "b41db44465a0f0d70093f0303bbd7776017bca8461c92116595ae89f1da1e95f", ++ tag: "d8a111a09db22b841fa28367ce35438b", ++ in: "b074b0984fb83749586881e8ec2c5ce9e086cfb2aad17b42b2429d4cf43a" + ++ "0400fd15352d182e6c51e9338da892f886f460d40bd178d81c52e9ab9c1c" + ++ "bdd812594e6fe7a9bb7fb729c11328d3288604097600a0c151fa3d9e4268" + ++ "de75866558e9f47d8dd331994bf69f826fd4a6cb475ae5e18365f59a477a" + ++ "dde7fbcf7e40b4e3dee020a115830b86f0faae561751e9b596c07491c42d" + ++ "e02fc979e69071113953729d7b99f1867116d058a90f1b8c0f9ba12c6322" + ++ "4ebd1b563a87734f5d6e2d4e6715d5f0213e33316500cc4b23784f78a9bf" + ++ "13fdf99bfe149cf47aeaaeb9df1cee140c3c1264fe89bcde8acda6bde16c" + ++ "e3d770ba51950b67ad2c5232ae0cff048ddfda8540cf18e673582dc96987" + ++ "4b127f655e7d4e08859f2c6b95403cd5b4e2c21f72bb872e49e592306286" + ++ "48ba1b16fc9637709636b198f9a297aec364d4c3bc869dcad32b1830e434" + ++ "b556b429136f0012a0a0b6fb3797bc8668014b010ea51674ef8865348dcc" + ++ "197672047fcf72e6b6910a0e32a4f110d85e28db0e338d9cfdec715a8800" + ++ "b4f007a7951d09e41620815848c89f8768344c50bd522c46f64ac6c98e53" + ++ "92176651961c7a70b62f3d1819bfda674e2ecd3167415edc4b97419e8ae4" + ++ "9974b56cd8d52e1d05b82610b59606a750b34844ca33bfc9b21fb970738d" + ++ "b66f48928df79cf67730a30b0b612f8c15c22892120548ab460a6b9bb3ac" + ++ "e30554c86c9681c797821a1b1ce91d0e87fe90ad4097c974cfbdfd5c4c24" + ++ "a5f808f388e1b1473e858f48a387614501c8c39d6973ded69b1764663cd5" + ++ "166be02b596a49e392d637e3d8afc91323f7450318b79d5488c040e346cf" + ++ "0cee512044514b570aa66bb98d639a9ee23a7cebe28474592623d082873b" + ++ "73efb3eaa4721fc4761e15a390497cb13cce181107e8b1a0186b9e47a5a4" + ++ "b67a5be3cd88a43d341ef63f10af6970aaf56035db938655020809033a92" + ++ "8d4fe6d2f5424fbde2fe82adfd991d388edf293cb4e3eb68d876f225a5f1" + ++ "58208bcb1aaefcbc28d6763d267406aa8d6ecb413d18cff7a318ba031ba6" + ++ "0ac4560748c248de64eec56dd4540124b38581604f502d94a2004f9eb1d6" + ++ "edb009e16af6c6d3ccbea79b10743da98aee7ace407a90c6cfdde694f36b" + ++ "e0271e722618a457be68619b980754795f4ac95ebf4f1820b85ca8e3fbff" + ++ "a2430f8e01ab422d7140751f7741f2c921400dac404b04e049736738a87b" + ++ "6f49bd54b1b447b922c473831a65f224ab84fc96e4551a0333bc6187e15c" + ++ "c0f0ad628068bcd7c043bd1e3036ec01e7fdc3d157476149917baafaced0" + ++ "15d09fafb92181a0ec65b00c9c13631e65de184377416e04d3d93b847e0e" + ++ "286c1d88245d4d550d30d4fbfcb416ff26a39a94275631c2deafc7cb6780" + ++ "f149e4d0e9c4515b708fcd62be5252485407a6ceeb9247de34e0266ef384" + ++ "976f6d31284c97468b3b03e951d87a5a00836ea303a266147a79ff3431b4" + ++ "b382e86c74d92661e0f65e266b7d569c03994b667a8137f3080eda2ff542" + ++ "0f0b52b427558dc26932a22a615c9e6b1834a251c6b68fdfc0bbe0e8781e" + ++ "36adf669f2d78bd23509ef7e086634e526258e8d11a1e0be0a678ac09c7b" + ++ "b4e3c5758504011e701dc85997fe2a3e40c7af83f032bdbe7adc10ef1e4a" + ++ "666946c2bf31dd8e3a383211c9684d5302f89dafcf77976d5a02c14e2462" + ++ "09d2d99918e82402cb0eacaa12032ad8316315af1b3d3bd5058f7c935d35" + ++ "ef0d4e71373958fd5e4140a9a586d89c53e4144c00148a4706a524896eb0" + ++ "5b1479a0de5d3f57be46b3f5fa4e49bffe027c81a33e37abc01a4cafe08b" + ++ "8e21fa86b42be52d75d6407e6cdf399de7aedb9b61a6917b2677b211c979" + ++ "33536664c637a57ce2234e3319fe8b4a77d7285ae6347464dfd0aab3e6f1" + ++ "178e0029686770d3b0dd541490b097f001e95f27efe8eb16e4747937d643" + ++ "cdefd49e586ecad541270cedc3064bdb7c79f086bf1fa8c666304d977a15" + ++ "54ae268881e17d8bc3fe51fa9969f7e560e3d3e050424febec0998b35f2a" + ++ "7378b2c3e384cbfc80c4987734d76c78224cb81cc5376f88f0ceda28aa50" + ++ "44e956537c3ee209071d84a66173384e0aa466d989759fb1f2f17fe627a0" + ++ "ffeaae7c5a3884b237f5151278a07117c2e833f1815c7e0e0b1611f25058" + ++ "ca338d21deb1a571faf1d0486667cb7c58e2814c3722d24fb77ce1b7e018" + ++ "2ae5746442b5ad00208b17c0a68bab4df8a8f36edead4fbe79b4c9220dd6" + ++ "acea6d23c7caaf6ce7cabeeca677a1c764d610ea6c7e994d6a9c88f57fda" + ++ "ef160b251e7595578ea2cc1441d480c14b8b6945e76a001891b1f214979b" + ++ "c52ec15e9480d706a40cb6e3b259ee99a9e84e63a738f1b52cf71c8ecb04" + ++ "fc833c2c680bfed587aa1541e5ffe8bbd7b21302bbf745011e559f94f952" + ++ "8b7fad8a37f6d855306a5be22725859cc950bcc334179d49564af3b9c78c" + ++ "e1de59a9cb45086a33856ba7195c17cef573950155bea73ed16645768bf0" + ++ "a5cefce78ba3ff98a54a8e8afc5dfcb0d422bd811ba9b7770a663b081dbb" + ++ "40aefffbeabca955a9638830f0c5d70663cbf5b26067cd061c4a3f5cf8fa" + ++ "4b6678d82d9a2aa33f8538b7499a3466f6b0ae2a1daf280ab91a6c220684" + ++ "12705245f353b4b83db50bedd3bf99d42bde6363fd6212cb745467acb007" + ++ "b678128f6580629a06171f7f3af272f8900b801af3bf47439167871e7b0c" + ++ "33f198333992a6c52c32be46071738cfbf245937d48f816ebb88ff0e726a" + ++ "dc41de4c771ff0bd320a4c0b1fcccd9fd6c42ec9c5185943c70e9a4b7c26" + ++ "a980afe104bb1f99576671a254704c7d4233eaf9915e1d56c103ba9f6e8a" + ++ "46aff466933bf58c9842796ae9cd21f7ac6aa96ef42ca54e390203bac354" + ++ "b7c1de7d1887c48255201335f819020e2782a2ee8af92ceb206b651ae92b" + ++ "3f4fdefed05e08974aee0a353d104b1be9a5e75c7f958f1981271b0a6928" + ++ "05a7a2f28a0448d86102b4fadf9ab4ec2f98e31e64fcfdf2b524780b3342" + ++ "7a2a3100c2032fc93199f3ea7a9e8063fe73282dcb1fafaa9496c7da868f" + ++ "dcf33bbb761df0bfc6fef30fadd2b6efef4fd3216a8aee48a2ef28102491" + ++ "cf7278b567c272d1064a277eb193b3f6f01df641ddb729f72454943cbd3b" + ++ "671ec077f9e3548f5f57d063c653ebee4f228a78f8a128d26f7f4b44160a" + ++ "07e942bab87b2d043c77ecdf10c1a419e0a1c4162a99c21d4abae0558b8f" + ++ "4dc0b7f1ca3892a6babf71f2f70aaca26bb813ac884ee5d71abd273ff1c4" + ++ "add230a771b678afbb12a1ca7fbcb2c0f5589c9ce67fe8f78a8db87825b3" + ++ "09ca34f48ac35aa7ac69c2fb2423807650fcf47ee5529e9d79dd2628718e" + ++ "230ffe5b83f9d5bdfd9c5d211282e71cbcacf972995bf1b13d21419f7fa2" + ++ "8829ed1dcc459da35883b9269a474f7fceff01d44ab78caf1ef7d8117f50" + ++ "cc83eb624062b149a6ed06ddd1cd1feafccdee7122353e7b3eb82978ca69" + ++ "247fde52d2d6cfe7324f04af5259e1b5c2460889da4541b431ba342a1c25" + ++ "3a1b1b65fce7120829e5466e7ad2fe4e0f773c7c13954a9c92d906c91aa1" + ++ "de211f40916596bfa8245344e257e5907a2c49ebcc864cfbe28663e700d8" + ++ "472c50355313d5cf088e9e8a19cdd85bcfc483520498c6386050e53a3ff8" + ++ "1e2b77b55b116a853d71f60d621265166cd7e95ff5cb4466226d7cef68ff" + ++ "d0a35b61e76a43cdcfa8da7fff9558e2f89b981ec6be632b126303ca1fe8" + ++ "53d5c628d967d39317b60ac904d6a882beb0746f6925a86693aff4deaac2" + ++ "e5b64b611de86767d55a6e11221605508b1c5cc828251539b1b6f65c2c04" + ++ "8e65be5422c1b11194eb687d906c559068c0a810713b23b30d8b17f10df7" + ++ "0962c5e7e782aff7bb95adfe4cba9d90b0ebc975fa56822025100b5cb8b3" + ++ "8bdc8928c1a2a8034dd66e2a763696d7ce6cef4dd586b83f7d01749d37fc" + ++ "4fe8d7abd324d4ff1efdbdbfeb0a2fbb8b266fc2bce8e5e5b95d0089e7c5" + ++ "d7de4db837d1822ac8db8198889d6bfe778d0b19e842f12b5afd740aaecd" + ++ "e36e2cefc2cf0b082aa0c4f75684d024b8d828d8f2911fe1aae270251f62" + ++ "4f49584e40bb193577c9d8e04eb16c094653cdf9a15fe9210f724c7a7c73" + ++ "74cfd1a74abb5ceae88ea54f7e7569f8eb674529cbec965ed05bb62f1968" + ++ "8fdaa97297268bfeefd06eb21f700cc56f9bf7f6cecbbbe7278ada8399fb" + ++ "960371a2d5cdb852b11c9fa17650e614c5297bf46cb7889d52bcf49d2560" + ++ "720852822b75bb16524d88273cb366b84b88282da91875562e5a1fe73973" + ++ "afe90e5cdd3f5381612d3ba7bfa058d023a9326e403ec474d8938313fb32" + ++ "bdb5bf899b900c3818c43c8a0af6a061bd26e847ed75983402ee8a9cf4ef" + ++ "85bba5545a0d329ba81495157eda0286f1917de512fe448251697dea406d" + ++ "a510adcb05", ++ }, ++ { ++ key: "b78d5b3019688e6ef5980c17d28d7f543ca5b8f9f360f805ee459717ca0d85a1", ++ tag: "f01babc4901e957d0c2032a7279321e1", ++ in: "ba7d35b2ef8af1118bce1e78018c9314b0c8c320591e103d23f715acb05e" + ++ "dc98fbc618de06627661df5842dbba9f604c2d20d664e5db06e949b11d49" + ++ "665088dbafdb0d39d20beaca7d723f8dcdc57e9c5583d303b6cdfdbecf95" + ++ "7d8daf2f1c72b2a6fa27e3d18841f4841abafd334c110cd2b74efb6191db" + ++ "ab9b8fc8427ee17664082f31db98d30bf15dda967e20730a9ef525abe9f3" + ++ "f620e559ed22bf74d347c9869f0311f33da7f1a3dc858b3a8aa73a35989d" + ++ "b055a4a2c269c95e352259c57de8b94d8de48984ecde426d3ef60ec1c7b4" + ++ "41cc950f7764f55bd0cf52d069b9ad446d1f765f35d02ec104ffcc00bf1e" + ++ "dc1b951ef953acd19984ff1b41041bea0e9f5326a7c9ed97e6aab42174ee" + ++ "971ea1dbe2fd1c1f67f977ab215962b0195417170f6b7748fd57262424d6" + ++ "cf7c235b34425f4047191232722932213b3eb73904cadd6a2e9c7571d7c6" + ++ "6c2f705b5039ff75e5e71c5aa738bf4177653e6eb0b49303a4bc0e641e91" + ++ "2691f217296a3325431d578d615afddf47784e4618a2ca40ccecb05d621d" + ++ "a52f272b8cf84f7fd8177c83af1580d25a764cc06436d67171cb5d1e3b39" + ++ "367b46d9a59d849d87ab6bfcf3fb9bac2b1ebfcd1cef4459e74b0e1b7080" + ++ "dabd2dea79f75581a55de63c4b23ff67d986ad060102933fc6cce8d614c9" + ++ "c86dc84068828dd9e21ffc5665c809d83b09432fd315dfce5d7a4ebd8143" + ++ "181953e3f8716e47b0b30cc1f753e31a7d509f2dbd4177b6da310cf3cd02" + ++ "5db270adf98e96259a5ae1b81f5be4d5c76f502a612ca73c76b91e0ca695" + ++ "aa921f9489948619482c2956205ae71fffc3aba4476ff754e4878e36c763" + ++ "2c935c076857c5b90cd63ea4764efbcee53e2ddc9bdce54b1cbbcf0e7544" + ++ "d023e7c2b79419ad92221a1f76abe31a8236e370d38e2493cc9ca2aaa811" + ++ "30fc713d11f500fd071d6eba6861e8b0859b372e62fe60b627a96c377f66" + ++ "236aedf307e1d148a61bdad072b93d7d2a73367c595b1e048f7023e72729" + ++ "1ec508326f5424a5bbf4e010d0240b71fa9137e6642ab40c5e4fff79877d" + ++ "b3253c663a221b49b3e77ea307c7b9f3f72a0f3a54d0112c45c64a0c0034" + ++ "baf2b55ae36ea6f811bbb480cee663136474dacac174c73b1e8be817916c" + ++ "fd4eb1876582bb3a36cfbabad91776aa676305ddf568a86e3a5eb687fa81" + ++ "67771fca7b5ca00e974b3cc3e322b4bd9bcee2a87d0ae7976da5e04fa18c" + ++ "219fa988d4f6fce62f194b05c26ed3ae1b066cd9751a2d916d53426a454d" + ++ "58f9c3b2fb49374e5791b412fdee1b6029144f1ca787f56fece4f64f4fac" + ++ "bfe4cfd8ba7c807a83cf44008fe5126a283ab2631a87acd8e2a3bd10979c" + ++ "4b07a84a49b0687a45a4798ded0b5e9b2acce30e714d78395bfa8f33ca91" + ++ "e68b2138bd67d8a694cd87c88dcefcd101a3b408d7a9095cc6a4b38898ec" + ++ "c8b375f5a67deaaf73eb7e99b10314ca6bba824658bee85dd731d9a1475f" + ++ "976b7c0aed4b67b088f0db5ca5091273217f724969dff6cf184181377c45" + ++ "5722beb23fd9d097a82ea2d8d527ba6284acc20cb30f2e52af28800c61fd" + ++ "1faf9f4f619550e0162a1a63758e202533889b27420fe7d0eac9a47a6e11" + ++ "1d80054412340e0426cdddbb3c7b9b823b8db3ef58230fad7a3ac21a7805" + ++ "d30878d4ea78dda95c951b7a5dc552e9434c35e03e1dd88652d3714f8fbe" + ++ "a39936cc0717c2e0335371f2a751204f5d9386baaec853f019325edfd1b0" + ++ "719d1fdac3fbd774a64bf957fc54039501f66df94b5b9b82c2076c597065" + ++ "dfcfe58b2e215a3734066aeb685ef97759c704b5f32dd672ba59b74806cf" + ++ "ad5daeeb98d16f7332ff0ca713d541c84e4aef0750bab7477ea707e2e497" + ++ "e12882dbc0765106070ec6a722d08fe5c84a677817b28fa3a41a6117f2f5" + ++ "465c2a2f0eb2b8be4f36e676b4115008bade3573c86cfb1370c03b6b0dc4" + ++ "bbbb0ada4dedac10a593655068a26febc2bf10d869cac84e046c9c846ce7" + ++ "927431f606f07b92abdfd81260199ae05ed01dfa07088c56a6a8de9c6d51" + ++ "d61d6a6d3f9904c216ea8329467a006a3d2495a768a39ef99a21827d2def" + ++ "909bb743fed7209f7fe59ff1c1e710095b05f166c6173deef5c6ec4105c5" + ++ "fc3b87c8269c786bebd999af4acbf12d20453b125f338aee87e9509ee405" + ++ "9c9e568e336304d7be9ffe81d1700555b0800242d9b7450d7256f2b17f6e" + ++ "d46a39f67bb2980572ce73169e352070dbafd4c7fa5a6be78cf9b72981c0" + ++ "a01f1e1e30ee3736c59828b791d2373799854497a28a44bbe0e074925723" + ++ "4986696fbb06ef9ea83fbd49c45a583ce12ff10258ba06127c67b0f66dd1" + ++ "09f1366d8036853973d8884f93de54fb2a12949eefc020717eff47898cef" + ++ "306b5de068411f1e113ffdfe2556e0faedc3e27d95a45b8afc15ba0eeeff" + ++ "eb86da7b4324e20af80c62bf0ceb4aee1515f5912f71c6bf2febf20123e3" + ++ "dd3a82dc1e58a108f1039942dcdacdeb1f0ad0b2ef34488d98d6a52311ae" + ++ "acbd03c12f6e775e375d5979c7c295bb049f2cfd3580e3da3841ddd8e6af" + ++ "4de5e6512ca79cebcab9280554524881da37984d340e8f0163fe10a02ed0" + ++ "88682560bc6d3c4dbcf1a542ffb3dcc2ed16a2eb96896e8269697ffeb50b" + ++ "73f2cc354092e782a0072fc12e1eaff117c2cc8a5a1ad8b47802ac9e23fb" + ++ "91a0cef9e4027595e0885464e61563093ee2b1dc5f22dfd04af7de6a70d5" + ++ "977d3751a4b3cc0c71a71c59c0534cb1f8c0eeddcf1c0e1b3e5ad0d083b6" + ++ "6e8b998ddf9ae9d3b365c851d42e995b9afdf8d66b2ac40bf514ce32e456" + ++ "0880afd38c42c08926067eb243c4b1184e667ba756c14ace5f525eb48df7" + ++ "ebb429d0a23d159664f8021d27dc7167081de331c7114c9c6456e1ffdb42" + ++ "2172a81c06d8deca995e158c48df27261a83f83e0127f5e056a139be9b76" + ++ "e25dadf534d3d1ed6ebc0b5d77d51e5b90ff86f30d4023066115bc11b33c" + ++ "c827b1103098826d0bf8777176b2da6f1e5b580e407ccf7e614fdf4f5b53" + ++ "3ef6d30b20c1bee61eab90e983b1a97173a62720ffd27abb8976a948d532" + ++ "d06596c23b0ef31c79831bead8f8e99ad209af3658cac0cb3c3f9c88379b" + ++ "9bc871d8e84171d53400902da1243f664afeaff60bd96ba2639a7644676c" + ++ "a79f43130af12ba2c877d67f7ec030a4217a72f5368af7c9f24e643db6ac" + ++ "97a04adaf57dbc53762d8dfa1afd49667c4041adcb5ec303e191b786273b" + ++ "bb065cd9f16a3a4a399c6a7aab9c1a6604998264e8b3dbd13d8f2228b13b" + ++ "2c2b9fec5055d8e9f2df1d9a25e4bfe2029776389877bbef7e2c7621f06b" + ++ "c0b7fc0786e2b2d042483ccd4a59d2872a6c5ac73e217123e5c8401580a8" + ++ "d967e0895aaa28f4d25ce68c90b4394d8113bc423e9fae46ac47bc2ac191" + ++ "fb97b80b5a85feb2bb54f84c493235c1408662fe253c6786fcf6fdb8be87" + ++ "dc66a72cc847f94dfb5214af5905b7039a7363a1b23a07853daa26862783" + ++ "ba08a80846fbb93ce98700a4f9961115128dd67bd7d19e0c588fdf6196c1" + ++ "1cb0154002ae862f11421f5dc3a57b6c0870b452272be556a1d14eab1af0" + ++ "a91ff5b89de6bbeed6e03bc64f5efddf9e54da71c594bc5ef78e0192cfde" + ++ "da36e4ad1a6b0b51110c1b24d20dea1f19e18cb1184d80189f842d4f07ac" + ++ "834744dd009aa3771b1e5502fe4b65a403a4bb319e1880ff6ba852e90a8f" + ++ "4fcb52cf374c88408428cdb1255291b04ed58c992310955198d61fa1fd9d" + ++ "762d48f2f65a287773efc67d549981c291b427889d3e3dfc0cc6cd68415c" + ++ "dbed81b516786dacf431472a7dfc99688d15bb6c1b85b1a2015a106e5de8" + ++ "cb9eec4c80b17d00fdcf4a9c64de4643a95dade8fa9f1bc5c839037d86c1" + ++ "3800a244188e3b18561a74912ed72f99f2365f0126732d037dd54a3ab77f" + ++ "9a9f6a1c1469ea92eb707482066bd4990dec4d7614ccb4ea6dd4deb8bee2" + ++ "2c4dc0b9b4d4cc70a500d2c8a5ac3ef88a38439b7dc254a6d920cfd317a8" + ++ "4d7747148c65b6730709e43369d4c995b03c58b9df444f77f216944e70f6" + ++ "6446554d8d513b8f7f28ef0a2d7ad5ca2f6110304196953247a7ac184f68" + ++ "61fba896c2d5a59007ec2b2c8e263957e54cdc1f3b4a145228823fdf0960" + ++ "c33a28f59b03ee4be21001d2f56fd49ed14db33b2c4eec2c3f41b250a624" + ++ "99a9b6602c1e838526a54cdcd058af1c252d56009d4c7769deace53bdb66" + ++ "543f5a081cdde775e61efa70956fe2a7a6019a164c6e413ded314bc928b4" + ++ "aebccb946ffdf3eb33e187bf421febe26112b3262a526de65678cd1fa03b" + ++ "83513705108fe0bb87aa99aceb28af3641c46a2c4427cc1063de01aedaea" + ++ "fba68155d4de494a27ff6b7fcc8f5c5c3f7d3a115c397a1a295bc55aec8f" + ++ "7f150cbce2a8aa4706d54ec863877bb966ad441c57e612a1b5d438b98d9e" + ++ "fcdfe6d4f66e885f96407e038015cf974ae5a3540692b054d2ddfde59b28" + ++ "ede7e2f581eeb56c5b88e2779aea60c1d8ca6107b0cdda1ac93e6c7520da" + ++ "edc66afeed12f980e20e1e1c327d15ade4bb90de30b011a9cb33855ca3ca" + ++ "e2", ++ }, ++ { ++ key: "2b0b0fd3347e73c2fa3a9234e2787e690a11aec97a1c6d555ff7b4047b36f372", ++ tag: "81b1a6633f849ab0aa7baafa58a5d9b8", ++ in: "427f3a7a5f1142ffa68e83df5f917e07b2bc454f3adce068a8ae9e0908e1" + ++ "3e0099aaa9074697593c6d8c2528fedddeca05e3888be1a0a201c389a72d" + ++ "20cb661017544d95a431e70e7c6580d8fb46ea4495bc59db6ae2cd69510a" + ++ "02426c50de1b6110120f759960605aca718d4d0a497e003e1ea2b8ae9a53" + ++ "df3c1eb4f704eb32f8f05eb08cecba0fd4a94f0daa3b0984c30a38f94b7a" + ++ "10cde723182d30588bc40f1f9d38a3bab4800fdd5148e34e396144763696" + ++ "c9b3e9b8adfdb337123d54237c7413f98bb2056152b256e37a27bb947c67" + ++ "240fa3ce8da62ab367db540bcdd9eb873d6c71c75a08fe99b5c11ec8e6af" + ++ "f926d2adfcf073479de394d4aac5fdc6241824d944b8773db604c59afc01" + ++ "495ee755905e5616f256c8a64321d743a1c9368d46418826d99b762e2f6b" + ++ "f998d37a995969cdc1de85f0ce3987c6550459f5e5bfd9173bfcb9e0112a" + ++ "d91f092de446beba14fb3b8ce3fb2f9c941815b2cb5a3b406e2d887b7912" + ++ "bba07c8dc7caab9836827da93ca71fa5ada810da1e5e9b09738524564d8c" + ++ "923746d19c78dc9107b9f20f653e05d7f2eb6bd90cf5eb30fdd7b587eb46" + ++ "74a1064c70ef0af2e75373044d32b78d96eb1db3112342d38dca0e47b96e" + ++ "9307fcdd711b1c66355186369a28481cb47ef6bf6651c2ff7ee4665247cb" + ++ "12b573933d3b626d1c6264c88bd77873c2e73e73ee649216bf0b6d6615ab" + ++ "245c43569d0b8096596f25ceca8667661de1cd60dd575697370ebd63f7e9" + ++ "5333e8a2cdb829b75ea83d72cd246d50358f7c094c8a515805fda03165d5" + ++ "21391617c9f9a2ea562b419632df611a67912d2b369e5e505dbd5c719253" + ++ "16d66cd608cc4a9583a8eaa4661b7279870345fac3031631c1a220551527" + ++ "5be7d8d89b71960e687aace3a0e8f206e475053d6fbf97717b154c75406f" + ++ "2caa97d1ab66048f1c99281c188a2f37b8bfc736c25840a9130ef2031c05" + ++ "6acd9dc10592eddf94f5bac85319b10ae46cc136a0738aa803837287ed7e" + ++ "dafe08d1fcf31d5e63763e39a5e1f4d7d0edab368d44e63fdb33c28905ff" + ++ "d6be406a024c017081b4f2d70860776e9d2556cd008fa5017b58733da13c" + ++ "634938407a118827a80baa28d4e605db59430f65862b90cd8356baa287b8" + ++ "4e6d9199fd80abb9fa697e2c2c4c760128e4ec0438388cf407e2a2fe0f57" + ++ "908187ed8efd4c5cb83cc91dbe6a11444eede85099149ca82921bc28bdd6" + ++ "b9999594a41d97307f8854b1bf77b697e8cdd4daead2aa49fbc571aa44c0" + ++ "bc84a57cb5fd85f06847ad897ceaf449eec45bddd4e4eb1e1e119d15d5e7" + ++ "90957e686acbdda1bbe47ea935ebc4b8c2e3cf9b7157cc6dc03bcb19508d" + ++ "a9e19cb76d166da55559ec7e0995d9b50c6c45932d5b46eee400c56d9dee" + ++ "618977dcf6f76e3e86bc5207493afbc2aae9f569ec9277f33d9f61c03d59" + ++ "dd6d8250ee8cb3e54e5e941afb74f0735c41d52ef967610c9f55b2b52868" + ++ "4b549a99ae3392a7237bb52ff5f8d97327e2837268e767bed0bea51f76bf" + ++ "88bf0286bf22b881f93f1d54fab5cd4e3c148c96c39e7aeef375de249df0" + ++ "4d89d1bd97a7afb2be0cbfd3380cb861d31e4ad1ea8627721e4518b9db3c" + ++ "cda20273ec23549c4adc3c027e3ac9558de2010a0263c1225a77dac8be60" + ++ "d498b913f91391d8b2656ffddb06e748cb454dc2b7226745f11030a6b9ae" + ++ "09ac8ac428d9c6500801fb540650c94610ab70465b1210c6db2064dc84dd" + ++ "7f52573f8f40c281470e85176c85ec6de3c718663d30ad6b3dfc1a3a9606" + ++ "1936744357ca62fb8bb066aa1fcac6d7a2adf0a635cd546bef39fbd3ee0a" + ++ "8802ab0466ec9b049b5892a9befa4377cd199a887c34569b6f90852139a7" + ++ "86babc0049ee2b527aa96b988237a52eae8b4b49d2ee15ee5294118cee62" + ++ "3c3e11cecb836b21af88555f10be2eff8379beb615b7b3d6c01d545cacf6" + ++ "61be8ebbf7a3c58ac5e0e7b17997659a2bf15f2b2e3d680d142fd29d23a7" + ++ "aea9890f3ff7c337fce49ecedaf38573edfae07810ba9806723e576d687e" + ++ "a11700b8ccb96a6559259c367cef4e3999a05a373ab00a5672ce8b3d1dec" + ++ "a414187f383e449d10021b73c1f7e39ce01516b7af96193f9993036049fc" + ++ "72ac059ef36b2bcfbe13acf140d41592880fb8294ebffb98eb428ce9e65e" + ++ "1094521bcf8ecd71b84c7064539a7a1aac1ad2a8a22558fb3febe8a44b87" + ++ "72fc00c735773d4ce2868a0b478ee574b4f2e2ceb189221d36780b66212c" + ++ "dd8fd3627cf2faaa23a3d0b3cd7779b4d2b7f5b01eb8f1d78f5b6549c32a" + ++ "cc27945b5209f2dc82979324aebb5a80ab8a3b02129d358a7a98003e701c" + ++ "788a64de89726da470010eda8fdcf3da58b020fadc8970fafb08a29bef20" + ++ "2bd0707e994015258b08958fc2af4c86c3a570443fe6e1d786d7617b0c66" + ++ "29a6d9a97740c487622b5b8186c529d7f8af04d9f0a9f883043f08103ca4" + ++ "d70057ee76639f3b1046d86928d54cd79fb5bb7b46defdf15d2f8578568f" + ++ "1d7b73e475e798ec6812586700e038ed4791b23ac9439d679a1a4bc04cea" + ++ "e328330c24b065c9cdcdcedfbaf58e5299779e6f48783d29ec3b1643bc8f" + ++ "1095c724dea75770583b15797fc666f787510d91e65a8e2090cc1ed2013f" + ++ "e63ab17bc7640ee817487f4eac8326e9c4698cb4df05d01bae8c0d00fc00" + ++ "08919484d5e386c8f60b8ac097c93c025d74faa56e8cb688d1f0c554fc95" + ++ "aae30873e09aae39b2b53b1fd330b8546e82d9e09bbb80132d794c46263f" + ++ "4fd7b45fda61f86576dec52c49f2373e4dca31f276d033e155bbcdda82af" + ++ "8f823948498f4949bf23a08f4c8ca5fcc8598b89c7691a13e5aba3299ee0" + ++ "0b479b031463a11b97a9d0ed3189d60a6b6c2390fa5c27ce27e28384e4fb" + ++ "04291b476f01689292ace4db14abcb22a1a37556675c3497ac08098dfd94" + ++ "d682401cabec239377dff592c91aca7eb86634e9d5a2848161dc9f8c0c3a" + ++ "f7b6a728371fac9be057107b32634478476a34cbc8b95f83e5b7c08d28f6" + ++ "fb793e557513ca4c5342b124ad7808c7de9ecd2ac22d35d6d3c9ce2f8418" + ++ "7f16103879ed1f4827d1537f7a92b5bbd7cd12d1ecc13b91b2257ad073b7" + ++ "a9b1ea8f56b781bea1bddf19b3d7b5973f1065fb72105bb4aeecca5b7513" + ++ "ffd44d62bf41751e58490f171eb9e9eb6d57ffebedd4f77dd32f4016b769" + ++ "fed08dd96929e8efb39774d3c694b0d30c58610541dcfab3c1cd34970195" + ++ "7bf50204acd498da7e83947815e40f42338204392563a7b9039c8583a4dc" + ++ "faba5eaf2d0c27ada3b357b4fccd1595b9de09c607ebf20c537eb5b214b8" + ++ "e358cd97992fa5487bc1572c8459c583116a71e87c45c0ba2ca801931a47" + ++ "a18ef0785ebbe420790a30278d2d0d42a0225d211900618438d1a0b2d5be" + ++ "d14f8b4be850dc8cb08d775a011683a69ee1970bb114d8d5017de492f672" + ++ "09062d9ba3616e256d24078536f30489e4dacd6429ed37aab9b73c53fdd8" + ++ "a8a7aff1b914b9d82d75a46d0ccf85f48d3ce9a8d3f959b596ae9994ac3e" + ++ "3b4af137d0c8e07ece1b21fd8aa05522ba98f85a7ab24ed8c1e265fadf4e" + ++ "9a18c5ab5684d8ba8d3382ad53b415c73ebfaba35abeebaf973b6f18e0d8" + ++ "7f019420eb34e09bbb12afc5b149f1e9e9b6ae36ebde429d437ada1a2d52" + ++ "b998f7c75ef731132aafc3bb106a2ad3ae11223a355804d4869ebaa47166" + ++ "2df261d95d48ac6eb17c1781e81c0027ccf8f05c39e1eda7793cb16622be" + ++ "ce7a1ad5d2f72f8bf4bdb2f4f4dcadac3db3bf727f0d447adddad4500360" + ++ "09ee011bf4155e5e46c74b00d72e8e6a88de9a81a5a4685651b90e874dfe" + ++ "eba41698c98370fd9e99619ce59ebb8342417d03fc724f9c910ae36ac5e5" + ++ "b46c424141073199aaac34232a8e17ebbfdd80eb75e82290de92968f3893" + ++ "0ab53dc83ac433833576e86fbabfb9d7cd792c7e062811f4cb017710f841" + ++ "1e0fb65ea4b3cd68b0af132cb08330aa13579196ec632091476f268b44ba" + ++ "8f2e64b482427dfc535d40d3f58b4dee99053b35a3fed1cb245c711fa16f" + ++ "c141974c8db04f4c525205dad6ca23ccaebde585cd3bc91f5874452ed473" + ++ "08de95cb6164102744f90b3007e511e091653c97d364fe0cbd7f4cd3249c" + ++ "1f5c452becd722ccc8c6b4e371e2631337dff78efd903a8fc195a90ca5a2" + ++ "aa4513bc63cd43794ff06c5337329055c43d4fb547e63d6e4d14fbe37b52" + ++ "1411caf2f1b0df51a68f677db59aa227c725cf494ccb7f8cacc5a06ac5bd" + ++ "f135a2603175a5fd5e5af615fd2e7cea61934e6d938b9e672290aaccd99a" + ++ "7e26dc55efe928e56ae6354168264e61668a61f842a581cd0c4b39e0e429" + ++ "04631c01320857b4d7e260a39c7fbed0593875b495a76aa782b51fee4f88" + ++ "84ca8ddb8dda560b695323cdde78f82dd85757cadea12ef7cf205138c7ba" + ++ "db6a7361a8d7868c7aefa7aaf15f212f5f5ab090fd40113e5e3ad1ab04f9" + ++ "b7f68a12ad0c6db642d4efb3d9f54070cc80d05842272991bcdae54cd484" + ++ "9a017d2879fd2f6d6ebce27469dda28ad5c345c7f3c9738038667cc9a5bf" + ++ "97f8f3bc", ++ }, ++ { ++ key: "aa3a83a6843cec16ab9a02db3725654cb177e55ec9c0c4abd03ada0fbafca99a", ++ tag: "719dbe5a028d634398ce98e6702a164b", ++ in: "643883153c215352a4ff2bb2d6c857bafa6444f910653cacd2bbdb50ffdb" + ++ "cae23cc297a66e3afefbd85ab885e8ccf8d8f4930e403662fb4db5121aca" + ++ "82dfcc3069bd5f90be4f5bfd3c10f8038272021f155e5de0a381d1716abe" + ++ "0b64b6d0f73c30baf6ddfe0e6a700483cad0fa14f637afb2f72361e84915" + ++ "78ba117e1c03f01fd61aa8f31da6464f3d0c529524d12dc53b68f4d4b326" + ++ "db7fc45c63f75244002b8f9a185556f8aab85948647818f1486d32c73614" + ++ "b8c4763e2645bdb457721ff3901327588da01622a37ccbbd0374fec6fd1b" + ++ "cce62157e64c4cde22c3a5f14c54cd6db63db0bd77e14579989f1dd46461" + ++ "4c8691ef26406984b3f794bb7b612e8b160374be11586ec91e3dbb3d2ccc" + ++ "dbfd9c4b52f0069df27f04853e7cc8b2e382323345b82ce19473c30296cc" + ++ "453f479af9a09ec759597337221e37e395b5ef958d91767eeb2df37069a4" + ++ "f3a530399961b6bf01a88ce9dfcc21c573e899b7951723d76d3993666b7e" + ++ "24dc2570afe738cbe215272ccedb9d752e1a2da00d76adb4bc0bd05b52c3" + ++ "fa08445671c7c99981a1b535582e9b3228ce61662a1d90a9c79afbdcfcd4" + ++ "74def2b7880cac6533ba0a73fa0ba595e81fd9a72ec26965acc0f4159ba5" + ++ "08cd42553c23540bc582e6e9ac996a95a63309f3fa012eac14128818a377" + ++ "4d39936338827bbaafad7316e500a89ed0df7af81be99e2f6aae6bb62568" + ++ "1dfa7e100ebca5c8d70f67be3c1e534f25446738d990ee821c195c98d19c" + ++ "fd901e7722b4e388da90b95ac0b5b5dc5d052ad6b54f6ea34a824bcf0cd8" + ++ "7f1fc9a07e8f5b8aa0793e3c9c1022109a7c7ae97ee2a2867fd0cf0f8971" + ++ "34b3d150d3b24fcf8323de929b73cca01244df02510393f0b3905caa0268" + ++ "7fe35f64391e7d4b30be1cc98319716528ca4f35bb75d7e55cf7749968c5" + ++ "37136eddb149a9f91c456fde51937c0f35e7e524647311077e6fbe7f3c12" + ++ "37b9584fcf3b0f78744c7b2d3b452823aca06d144e4463eb5b01014201cc" + ++ "bfed1adf3414427072135d48e705b1b36ab602cae69428e7c19d39cbb4e0" + ++ "ca26a871d607ed4daa158b5c58a0a9f4aa935c18a66bdeff42f3dc44166b" + ++ "a299d71a2141877f23213b11c52d068b5afadc1fad76387cf1e76571e334" + ++ "0b066ade8da02fe3b0bdc575b1d9ec5d5f5a5f78599f14b62db0bef7ccc6" + ++ "1711482dfa4787957d42a58fdc2f99525c32962b06492229399980601bd2" + ++ "ee252306b1464914424de9aa414a0a6e5dadf8ffbf789e6d18a761035d3e" + ++ "f2ff0753becbd2dd19fc1c28f9acebec86f934f20b608a9ef735ac91f6b7" + ++ "83d9327cce7f4870d39bbbfb0100838dee83e6baf2b40cfc98415dd174ed" + ++ "72e393ad0459e8035dce7eb18eb3af2f39d2712846b9e1852cd61d06dfc3" + ++ "5e34fb761b67e2a711ceb4a82557371ed32ca8db2e4cd7fea0b6bd026177" + ++ "4057b9abc45dae6869cab1097459473a389a80a4523e5de696554f8b0bec" + ++ "0ca605e6acfaa00386fb5a48e0f5893860a29f35e680be979cf3bf81ee7e" + ++ "ed88262dc80af042b8cfe6359cf8b475560bb704728034e2bd67e590bd76" + ++ "1632e516e3292b564c7265d7a6dc15c75ba6f6a447b1c98c25315ac7de59" + ++ "9edc4993e4dc7d1dbfcea7e50ebd0b226e096500216c42de3abe352e5b09" + ++ "a3c9754aa35d00883906599c90a80284d172a90abbeaf7e156fe2166ada1" + ++ "794420fe55b1a166d752d0eb7f04e822d021c615e84777101e7c9f9dd12e" + ++ "565b7d093fe978f85e6142c1ca26798b45f4b8d23ecff6be836e810e314f" + ++ "ebd2ea66f2ac95bad84b39b7a6bac41448f237b45e9ec579235ba2bf5fa1" + ++ "f00286379ec107c743f06ae0d11b57a2f5b32e3bc5f1697aae812d7ca303" + ++ "b196a8a43259257f7697bae67adc7f121be561b2d0725982532ffc06cb22" + ++ "839d9066dce0e4d683d9348899089f6732de62751ca77f1c439e43054468" + ++ "2c531b9c61977bc221b66030f7571dfb3ddfb91d9838529dbc99612f650a" + ++ "d72bb78de061192068941a81d6ac341101aeb745b61bd7a87a35a2714d50" + ++ "c3eb2c3ea148fb9ebed948307f8b491aec277ac01903ba36e6ad54f89fe4" + ++ "280a17f8e7ae639e75aec16d56576f03c2a1efe4af995eb825ccaa6efe0f" + ++ "d6d878299a351591d791c286cac5cb049834580d47a9bb7720d0603e3141" + ++ "ad7c1ec2dd23d3002e15d73c1828a7f08062848b1b6fcf816bd954743547" + ++ "6f0d6f882125bd03095eb1b1a846d535730e258fc279f7095de7c2d3fcca" + ++ "a4640a2e2d5ce0974c1e073c60bb78171c1c88ae62c7213a95d36ea9ab17" + ++ "59093813b85d17ff106e69100bd739ede9656388bf47cc52730766a8a186" + ++ "9dcc623e09e43cfba1f83ae1d9f16789064ec73504c29686760ea02c6634" + ++ "a929ca10c6d334b1751494c6d143671ce8e1e7dcc9bcda25af895a193032" + ++ "ce27c1016ccc4d85507fd2265ebf280d3419f54f66ba2a161c068491578f" + ++ "be056f02f97be745db443e25ed2647c5348f278f4ad8bf5b2a2c2d56e795" + ++ "532e25585984a3a94f435ef2742a0413abed7230ff2e9724187c91f73a7a" + ++ "726ebf36bc8d0d959418dd586452664990889358c56720c1001c004ff768" + ++ "54b9850890ce1b31735fd9f4a3640622ef0b25c659e8a937daa0df7a21f1" + ++ "77be13dfdb8f729da1f48e39a05f592d8c98da416b022fd8edab8e6132eb" + ++ "a80c00501f5cc1e0243b6b096c8dbe7f8c6ffa2f8bcc7f309fb80b489b92" + ++ "c4878fabad42d91876e10ee64ccd415124461cdc7d86c7bb6bcd9133f3c0" + ++ "dfa8f629ddb43ab914c0ac5ecddf4398052229876fd838b9ae72523946cb" + ++ "bba0906a6b3ef26672c78cb24cbf691a5ec869d9fc912009d840772b7da0" + ++ "c7f47856037c7608705cd533918c207a744f75fdfac618a6981778e09332" + ++ "5c7d22170da85bdc61044b4c397919d601a30746cefefa798c58f02cb827" + ++ "0d130c813cbeb67b77fe67da37a1b04bf3f1e9ee95b104939220fb8a0394" + ++ "86ab8954b2a1468016f546406d1946d531966eadce8af3e02a1f59043ff6" + ++ "e1efc237dbf4dfd482c876531d131c9b120af8b8fd9662cef1a47a32da40" + ++ "da96c57dc4efad707a4e86d0b84262d850b451bda48e630c482ef7ede5bd" + ++ "c55147f69e2ff8d49262d9fe66368d1e38ecdb5c1d4e4042effff0670e69" + ++ "04e47d7d3047a971d65372126ff5d0426d82b12b253bb4b55005e7a22de5" + ++ "6fa54f1dfcce30b1e4b4f12b1e3c0de27cea30ce79b08c8c1aceb1ffa285" + ++ "c317d203a9f2e01d542874fc8035b7670f3648eec79561d6ff2fc20d114f" + ++ "ba4fbed462f1cd975ee78763c41663849b44cb2827ee875e500b445193e1" + ++ "4556bcccfaba833bb4ea331d24a6a3bd8ec09906c7b75598b44ce1820a49" + ++ "fca4a0c1501e6c67515d4fa7f88f6aa3cd7fbc6802131a7b14b219e154db" + ++ "9ed241133e10ace40e4d963f904dd9f3bdaaade99f19de1ddfe8af2b3cc4" + ++ "0a48374dd8eb559782bea5410f8f9a1cd128523c0157b6baad9ea331c273" + ++ "311492fa65c032d0d3b513d23b13b86201840d51759021e4133f873f2781" + ++ "8f54f34ba73b4f33107d49c8de1533856ec37bb440f3c67d42148765610c" + ++ "3296bce932c839fd866bec3762a38406ac2b39d0d93730d0c88cb8f765dc" + ++ "d8ee71263fc96068b538da06fc49e25dbeaa10a5111a9af8e8f8d78e6ed1" + ++ "3752ad021d9f2c6b5ff18a859fee9651d23a7237bd5a5c29029db3882c47" + ++ "0470de59fd19fb3bfbd25d116f2f13ef5c534bf3a84284ae03e3cf9cf01d" + ++ "9e984af9a2e63de54e030857b1a071267cc33d22843b28b64b66e4e02803" + ++ "c6ab5635291aefa69cfeb3958c09d0b37176842b902da26caae3f0d305e7" + ++ "c6ab550414e862e1d13d9bb9dc6122cb90ddb1a7bc6d31c55f146659baa9" + ++ "6cca4ea283e5e1639967889543ecb6849e355b6c0227572097221dd46c1d" + ++ "f8600b230e9644ba611ba45cd83fa4ac7df647b3be57387b6db12682018a" + ++ "de9be50a8ea7d5f7c743bf0c6382964bb385b3c207c0cdd63279c16130b3" + ++ "73ba974125291673344b35c8ef9a33be5a8a394e28dc1448f54d46af675a" + ++ "edc88ce85a11ad7e50058df4f3f2364abd243683d58a2b13fcb0dc0eed21" + ++ "380b666eb87f4be75e7f2842bae916c15af3e9658c55408537b2301faa6e" + ++ "42af4d94e3eda6a41d6d302be281e2a9299e9d0fb1f20cf4ca978e66bdd7" + ++ "4c8bea0f15c84d6513cdea787dacbd4bb529ed03528284cb12f6ecd841d3" + ++ "c58c3a57c6bc19b65d6d10692f4e1ad63b091137c8acacc6bc1496953f81" + ++ "2972bf6362cf883bb75a2d10614029596bf9f35e92addbb50315b30161b7" + ++ "de8867a1393d9583887a292cadceb54078c9c846ec30882e6ff987494060" + ++ "721d3c761940b91a126e8d1e0118617bdae01a7f9c1aa96bdd6c78ca06f2" + ++ "6c8d85664a8705334f4997c724ef98fe265985593d5a9c30798714e6de1e" + ++ "bd04b648be47a6b5d986a3103e738a5cd114b19b7ba99d2e2eec6181bf3d" + ++ "ff0fec8c54ae6118be8702c3e775d493a6fafb509712a43ee66c3f4b75b0" + ++ "194c88937cffa5fa17b284d2556f2b0eebf876e05f92c065515198bd5e83" + ++ "00d0db432cb256a4a0f9963a05694ffce3ecbd182209e0b7bb50120f6be4" + ++ "eeb9d268b17790ee14a2c887dc5753e0086630b3123734053aa37595aa8f" + ++ "31968ddae4991af4ab970c1e3cfa1146a2efd9dc42abd6af14777b8a0455" + ++ "3865691cbac4b4417b3fa13c154d581b498f3b8cb77adf0e42dc2f2fb521" + ++ "732447de97271e542c6cf8cad3ba0148cc3ba1f2983ead836a25a2c022d0" + ++ "43ba18fcd009d518d07b53344a5bc4d626b3b38405a114471f75dc70e015" + ++ "d11e8f6f57d087fa72909785573008b1", ++ }, ++ { ++ key: "1793bfda9c8666f0839b4b983776735a927bdaa3da99b13c9f3d1cc57d4d6b03", ++ tag: "bc89cfec34ab2f4f2d5308b8c1a5e70a", ++ in: "a09f661aa125471417d88912f0a4a14115df9a3a19c1de184878291acb0e" + ++ "89ee1f9d8213f62df442f8969a9a5a7c402fea09bdbe236fb832544e1f93" + ++ "9cdd4873802b2bb8fc35ba06b7ff96da6dc7efddfeeda84116bc525a7fc5" + ++ "2d84d2e63cbac00b122dc64f2d15b36595259d81a1d2a09f204c54072751" + ++ "dd812259df1104bb2d2ee58baee917c5d0aa2649c8a1503114501e6ed6fe" + ++ "239847d3d88dccd63d5f842426b600079c6bf06e80a2813b2208181163b8" + ++ "61dca07fa4d88254e84dac1c78c38397a016b5ad55a6b58878f99036db56" + ++ "89871ab3c321f6ed5895f218f8fd976c348b3f1269fcdf4d38c9492b4721" + ++ "6c45f499f5705830b33114d721f9731acf6c69fca681b74c2d82c92e145b" + ++ "7bab77110821d3a12cc818d7595a5c60c4b5e5219376c38a4dd52d435d41" + ++ "562802ff65ba2bba5c331c333d5adf194d29b2cd9ebb55927bb4ec17681a" + ++ "3f5574ad34fb4e964f2c756f6dbbb7a6876a21579a515263444de7a30a33" + ++ "15005458bc137ccfdff18a3892fc9f58f1de10d4de20bbcf860f5f036d8e" + ++ "8a188f18e5cf7ea3cd260710e7491befcb131d49a28dfb1ef688fd021a1e" + ++ "e4420d32fbfb03b47f5e85c37d91e49a1b0db85d966eb5434c4197433eb4" + ++ "9d56f2ff999c9a72230447032dc949202468261b48b6ac212e3f651d6c63" + ++ "03a06c90bb2d3a755ed91ba73bcdc28e1c5b0936e51e0a9f69c3ebabd3db" + ++ "add7abab6d8f6a44daeb3126429a01815f57444fb7022a4a510f8b564ae2" + ++ "dd9779b3a273fef15859a33e233724846c30d89fb78a595b6ff6c834812c" + ++ "00a991e405806aafd0c26a788895ad00a5e43c5426197aa8247207077548" + ++ "ee67db4cd6f878431a2e36e952d84b5fb89d681f553198e2c066310ea6ac" + ++ "3a31f5b1792620616f6c41d486fb844eeacc7fd36971abf416e8d6d50985" + ++ "c83cc92ea46ac37da8f0026aba30c945d8bb15080d2d95e4081bad626199" + ++ "3f95f57ed3252822a7caa035ae22a36c35e280cbbc82d729346cacdb1794" + ++ "ae9a9bb2793fd1d5c47121b135c2836063367339c5151b4e35278e97f62a" + ++ "fdd2f231d4b47812d083a829ebb9c374ff2ae8479cc4b76d55f9cef3ec6c" + ++ "4894f53e8caaeb0d8cd072960cedaf758e48e3640590d4f728626e0a08ee" + ++ "ebf719c96bf8ed4d0c283be09c0ae67b609e22d3b9aa6b03642854909de0" + ++ "5ed52b39673867bf586a632ab8072de15c637cc212cba8387515c9c9c433" + ++ "abd7ba6b02abd09da06a34694ad34f88515b65c0c9c247fdf9819fb05a1a" + ++ "ea4728c1182f8a08a64b7581cd0fb2131265edcb3d4874b009aede0e87ed" + ++ "463a2e4392aefd55e008eb7ba931788262f56e53193122a3555d4c08133b" + ++ "66020154b15643fa7f4f5e9f17621d350ede3dc70be02c59e40fea74dbbd" + ++ "7919d1a8d4e22ef07c916fa65e7d4b89fb11a7c24ddc4ca5f43344c753b6" + ++ "1331c3fa4558738ba7832b5b2a275bc9b7989b6e6888865793329806cd3b" + ++ "f0ba57c941d4428623e062f4ac05e7cd79ad5446f8838f2b247b66bddadf" + ++ "540845a1bb304a04b7edbbff579c8d37e2f6718f8690abd5231822c7e565" + ++ "69365ce532449a41ae963ec23a2a75e88307dc6b59cbb3fab913e43ed74d" + ++ "841ca9f6e4ef96dfd9f04e29e89361aece439c0b2e1943b30410a63d495c" + ++ "522ac3ec1b04ec4cb345f7f86969957ad750e5bd7dbf1d6a22eed02f70b8" + ++ "1cb5b2b020c0694d7f63044f9de0c3de1ede52009c858992d01ebb92ff19" + ++ "a9e0fbea18942fbafb77746c8e9e687dd58ccc569e767528bde43b62c7c1" + ++ "270a5721f1212de2b29a7aae2d6ba6cd173d7fbc78aec4356ce2e8ba9164" + ++ "d97dec061dd0c3a0e3c520a7611ac99739049dd5825537c70b7ef660046c" + ++ "1785546cd99aa400da848eb7c3c91247415c8e245d0f14c30d482c5849ae" + ++ "aaeab2568288229b08267818dae8f76fc674c684c99eb5faf88a0783813d" + ++ "f7298e0b50cb233f78471e5ca9cc3b04927c26a3871cf253798cc49aa717" + ++ "d8f18a1ddcbdc26497d188f15f86ec494dcf8f942c3e07e572385c6fa0ef" + ++ "40c0b625f1737543074a747a369482a0b342a08b3eccac9f9209be31aefe" + ++ "5a7794974f71ac0bc9a58026397ea3dd4f5e40511d58d2a3b45925c194ef" + ++ "13987037d736dd48b509d003a86471d5f161e0e5dd168b4f1ce32f703b89" + ++ "15004d8dfc708a5bb02b2e6fb67424b2cbcb31ddaa0114c4016b0917382d" + ++ "aad11815ff5b6e37d5af48daa5ef67cee3439283712bc51b5adf2356cb2a" + ++ "5181b8941fd78945c7c9d61497683e44fee456ad345e12b4258f15945d45" + ++ "b6ca4369ee792d849112d583fdb39cd4d333ee057355f0abc8d1eea4640c" + ++ "128cc1617982db0394233dbd416102eec1874081247d2982bbf9fed1b1b3" + ++ "8f4da923d68c8975c698f189a4d7840fd7aca9dceb7d91c076f85e1c546f" + ++ "4d5de4f60c91348455aaea30cac134c844dad93d583c139dd52b3be6346c" + ++ "4d2e6864125c5a2d0aed8f67930e1ebf8700ca88aacc914ea76ff17148f0" + ++ "777738cc126e75a2c81110faf02fefc47c91edbab7814599000ce55fe20e" + ++ "f313566e9b62457acf2f22e1141e220bd9d4747417d03e703d4e39282803" + ++ "386327fc65dd597f723ee28185c78d9195fc70a75706c36287ab9c6e00e8" + ++ "5cecbbd6043c6af8d30df6cdd8777be0686853b7c8a55a5b1e03e4431d39" + ++ "1725ff99875a85cae6926998723b36d13ad458220712209bfc5e8d2ca5d4" + ++ "4ea044d5ba846b4035e7ac7e9885f55d3f85c0c1b3d09fe929a74450f5d2" + ++ "9c9672e42d3f59be4ca9d864a4322cc454c2578493bd498a51bbe960e657" + ++ "3e5dd02c4a3a386d4f29e4578a39e9184024cd28d0e86ecac893b8e271bf" + ++ "ce3f944d130817378c74d471bd20a4086f2429ed66c5c99969fd8da358ff" + ++ "5c3be72bf356ae49a385aa0a631b588ddb63628fd162673e915cfc4de56e" + ++ "ae6ff7101df3b33125c9bab95928f6e61c60039b6cc07a66f9c733251447" + ++ "ef9c1ffefa2158a8ddf89dc08686a4cf9b86ea09914e79842d72a3236afc" + ++ "98a3afa0a1cac5590ab6a923e35a2ab8db6410a9d33cb84d1c48a054377e" + ++ "549774b25f50fbb343ecd5db095155cce9fb0c77d09752f62d4bbf16a770" + ++ "30452a75f6bdf73f7807d8f3a6bae16ad06b22175fee60549c22548de9c1" + ++ "3df35ef4e7bf7b66491a62b93c2c3fb0c5edc51f60f5704b56af30f1079d" + ++ "7c385b99f958ef8209e030e381d1ee8d67d3cb84f32e030e8ea2c1d0c77f" + ++ "d6b242a9f48707557c8682a08e1127f51221a55c733ab1edd00a9c2912cb" + ++ "36dde85f73b524e1a4f4da6414c5e4c18d9537722b2becc8a91bcc63f2b0" + ++ "9f32409c53c2beee0de6726dabcd6bf33118a5c23fb9c5c1810476efe658" + ++ "4bb6109c516b45e16b2f79f96755680374d82b91f2c519639a1815fd485b" + ++ "a3c00b46fbefeafcf25554ec5a6a5ae2da07c85b8a0f9fcde50263d9ed85" + ++ "038b2f7aadb9de765655bd201235218bfc74bcad6a9ddf4506167a649afa" + ++ "df400b85752d68a92b7a97f26b334dd77fce824862046b286a7c8e0adc36" + ++ "f713a252a673d4d995b268badf4bec8b8eefe85c25b823b6728582d35c4a" + ++ "60041114dab72b0623b99e2758f6a1e97365279bfba0eb1fc8952ca4f2c6" + ++ "fbffd9f5fd7dcad1125b18a796981b5ead0b6431141315898ace96f0d38f" + ++ "865698df8822ca7b65644b6b1f0a0f0d2e5850d4c93ec48ca3eba1b919e2" + ++ "4413a46d595ffa427715e499db3b7b9ab53c64abec7302bc737a5bd124bc" + ++ "da756abbca132f7f67e6989e09bfb23b497da31bf156bb9c69ae54588df1" + ++ "7420e8fe989f0472c8893b2bfe57cdae265a8cc7aeb39624167a567a6fbe" + ++ "bb1aa30c3dcfd14f2808a070994085e6e1fa79021e77c399f90ab1f995a7" + ++ "baff672cb693bd39b798b4c890b7d0a57978d6b9bcdc5bf3f4d205f8f24b" + ++ "2b43d3ae300a96971c9182be297618b9adceebedba1ab0f324b01d23d7e6" + ++ "35f009db3dbbc643c2d787567594bc639bfd78c4f3e6d948caf06f013423" + ++ "eb3c764666b58f886d5d28137c053c2a28535efcea400147e92ac6753574" + ++ "3b47f9cb48852abed1d057647d5b1c6f334eab1a813401fccd3dae332738" + ++ "776bb223e359f3c459b5c573ba64fa945bdd66c5ac0fcbd53b67032a7b80" + ++ "25f551e8d1fd2a4291bdb7941cbabe3a09765dc263e2bbb6db7077cc8fe6" + ++ "790d4bed5e36bd976d1e37dfdba36aafcdaa10c5f3ed51ba973379bcb8fd" + ++ "203d8b7282abbd271ecf947e54486e8653b7712c9df996a8ad035f41f29c" + ++ "ab81509f922c67dacb03f25f8f120cb1365ab3c1c286849c2722448ba9bc" + ++ "ff42a6b8a7a52f2c79b2bfcbdd22ef8a5651c18879a9575dac35f57d8107" + ++ "d6bece37b15d7dfff480c01f4461ef11f22228792accda4f7936d29d4c56" + ++ "cbba103b6d3e6db86e39e5f1bb9e9fd955df65b8a6e44a148620f02b5b90" + ++ "b2be9e5bb526d0ec75b1e723e94da933a356d7ca42d0ce8349699f730b8e" + ++ "59bac24a6b633759c88041d29399ce60a2ca2261c7eec1acb9a56e0e65bd" + ++ "e37653ce2cf7eb83a4d019c755bdc5d685b6394ecddb9006823182dd8138" + ++ "a1bf79a32d07a8e5e8ab221995c714e571b40bb255b79e328ab883542c16" + ++ "4899fffa16eb3296f310e302512352a864fd809beaab4169113027c6ccca" + ++ "99a92c6ce35c30f9449a3add70f10db1ed08078e8e6cbaafef630aab7e9f" + ++ "c8adb09c18e33fe1af3620d1e4d069ac11325e23cc18e5519a1ed249caf8" + ++ "ddba871c701f1287cc160019766988f63e089bd9bf1af7e6f5b9002e3b6c" + ++ "264d69a8bac16914ab55c418d3a8e974677cdcbea36c912e90386a839a37" + ++ "77b878e680c07c7cc99f42a7dd71924babf7fb0627d1f2cc60d9d390d1e1" + ++ "50d47386be6eefec9ddbb83b28fa7e2fd28cc3867cbe42d13b00545af8a0" + ++ "48cc07016ec79808b180e0b258c564739185da754f2e", ++ }, ++ { ++ key: "0d41cb4ac25217feb20e86fc2490e8d2ea2e8225c051252a9395cc4f56e1ae5a", ++ tag: "42df9f9a59d6dc05c98fd9e9577f7176", ++ in: "01caba7a19cdb09dc0ec6c522c61c628eacf17ef15485aa5710fed723875" + ++ "2e4e8e93dd4bbc414e4c5620bab596876dfbea33987e568ddabf7814b318" + ++ "8210a5f8d70041351e4d8410840642a29cc8d901c25fa67cc8f9664ea5e1" + ++ "9e433eaff7c722d0258ae112b7aca47120aa8af4420d4412a10732551db2" + ++ "cd3e0af6e5855d5eea61035af15a4d0d898d04033809e995706eba750a7c" + ++ "ac07aaa0dc71477d3020f778d0347f1a8e37c18540deb9ae967e734c0264" + ++ "df0e1f52b0b5334805579ea744c8784c3ae0c3ff8217cd3f53cb747f6996" + ++ "f3d2147699799e649061b205f97f7992e147fb20f21ff862c6c512e95534" + ++ "f03075e8e52f162e0d70d7a259e3618474427f400f44f75198edebae6e40" + ++ "a2173257d114e1bb5a13cf419c821eb124d90e89a938d91f4d2e70dfd1ab" + ++ "60446f1b602614930a329e98a0c30f107d342281db25b8f8259933e14d20" + ++ "8bbd991e42969e8b0600272f9bd408483cddfc4cb8dfe7bc19be1989c7fa" + ++ "129d38e1078d094b82e0a845040ddd69f220dc4aa2b236c44101d7da7779" + ++ "9827a7b037561b51e50fa033a045571c7267af93b96192df3bf6180c9a30" + ++ "7e8c8f2b1d6b9391767369625015da02730ad6070df4595eb8099bd8e484" + ++ "59214310cb62c3a91a4fa8ac3b3d7b2017d4254fb465f0a248e1bf45819b" + ++ "4f0360f37c9a79d405e2bb72e5c25a1b4df192cfd524d61e1e8b274f2fe0" + ++ "634c73f0653c7c9e9062c9d081f22a8b0327897eed7c6e870f2815bbac8f" + ++ "585c1bd868759a98dcb5c3db2f6c53244b9cc494a56f28a9ba673167cea8" + ++ "b799f37049ee7b0772972b3a6603f0b80eddb58ef03f916106814d72f000" + ++ "250b3573c97c5c105910d79b2f85ad9d56002a76a1f43d9d1c244ef56d3e" + ++ "032a9bab95fe3bd5dd830ad7d7e341f28b58c0440658f7fc2ca98f157708" + ++ "1c647e91432cb0739d9acdbf973ceb9b0047634d695279e8837b04dc5357" + ++ "f013fde3c55c9c53bf1d817ec59a1b18ed0ac0081ed9bbb3bcd1a5d3634f" + ++ "50f7506f79dc6a4ebfa640bf65682fe9aeca68088e276937669250064de1" + ++ "c19ad6d5c697f862114d0f81d2cc52be831ed20d3aab1e41fe6f476b5392" + ++ "af4799392464c51394c2d1a8325ee2e84f1635d295ee663490e538eb338c" + ++ "7126a8e731ad5c0becf144c7a9cae5c6493350b589385de29e1a0ad6716c" + ++ "346ec4f0a31ca5ea35c59ab6b099f65d7f0b3d00925a1da1b5777c029aea" + ++ "9679e895d7100645dc83f81d82a6174beab2357f7888ea640900cf3ee67a" + ++ "e0724a123919d78e70e05288f67e5e69ffa6f345be8a96e58bbe260184b5" + ++ "ec5c0c1354cfd516ebdb8d420029137d41b029641959cc07fa7b4e16b39d" + ++ "17f36b2367057410a42e0550e9ec1dcd2df4604d52d4f9dd1140d57af08d" + ++ "50e1527dad793b6d649324de799754f755818bf10e6d1ab614958dbb24ac" + ++ "8e2c01270a90ec3df4379c3f509b5ef721b0fd4f91a1bdb8127ae4dc74d0" + ++ "75f6cd8bb28319d6f8e8d8ff64fb4a42d646e9365156c6bc72cc46e9cd1c" + ++ "f9e735549e3df9a8e6b5fe541948b126190117db71fd1d61ad84be0f725f" + ++ "20b99eb141b240326d399976c4f2ce5823d94649a9580e1e8820bf49184d" + ++ "fc34378a60bea89b12aca69cb996c17847b7fb517cf2d51f16d78e3875ce" + ++ "aa33be15f6a154004f0e1134c6652c815c705efc34bcf35bd7743d28f0a2" + ++ "77d82dea4709dab41fbfb4e0cbc118c17aa00808872f0edc6437c357cd31" + ++ "74a02aee61890464e03e9458853189431bf5df6a0ad5d69951e24be7f266" + ++ "5bb3c904aa03f799fe7edc7bc6779d621cab7e520b5994f81505d0f01e55" + ++ "96e14b4c1efdf3e8aadee866c5337c1e50066b3acc039c84567b29b7d957" + ++ "683cadfb04fb35402acaba631e46ca83dbdd8adf28e377ec147e4d555a21" + ++ "e6d779d7c5a3078ab72702234d36ca65f68bd01221c9411f68f32e16ef04" + ++ "99a20c2d945fa31b79d9965853d38ada9d48eead9084d868c6bad974b0f4" + ++ "0956aa0fcbce6dac905858e46c4b62c0ee576b8db7d484a524e951f4c179" + ++ "decfc7d6f619e86dee808f246dd71c7e0b51d28bc958110d122fa2717148" + ++ "77823242711632f6e1c7c15248655ced8e451a107707cec8c84929beece4" + ++ "efe5503d3c1763d0ab7f139f043e26027d5e52a00d5414dd98a324a8fc2a" + ++ "06a1345cbde747f41099c3377b86bbdc5a17c8f6e5b773a761f78573832e" + ++ "4359b143810361dedc79142fffc49ddc0b32f225d50d360ceec3920fb0ba" + ++ "0693b644ee07fbd1ce829e223a02794b197614061c4bfa46112d105c2b7b" + ++ "4efea448501d146dece44f6640d674d5749db498b32969de6e165e705a18" + ++ "2aa1f3d8e16892b0120337640d52c9bee35e5b4b17f03eaeb31205c8ecbe" + ++ "1ae1b110023016e40ee87370a65c5c20bfb00f100d3c6c1de6e4a1c90162" + ++ "f25bddbf300ed637330206788a4ff96903f971c9618493ad074412af625c" + ++ "ff9e0f8f183bbd5e96c1f28307e6cae8b50cc0eb1a3a8154e44e9de947af" + ++ "002e4d1098d6b0ee3f2e71a10d03eb444729c42461283f37be8af2ce81ba" + ++ "bac246a05c2c94efacc43f0cf9ff3df38ab6fc1648c796ae7026ea95752e" + ++ "b70873a6da59da10d8b5316126431c4a17289466e95dc739c061d7a4b13a" + ++ "450809479eef421bddcdade77a6df133410328c754af8999a09b1a5c056b" + ++ "ecbb6fc2c339586ab92100f46d2fa1fa689994b36aa70703d76bf7738adc" + ++ "f0589fdfa6bd215339ad69ed983f62efce0add5a63fe7dfe4bfa006ff16e" + ++ "0cc06d39199ad60adcae12b75ca98d764502a783373da3a41281e03c2037" + ++ "e1b3ca7f7eb60e2b67427e97ec72d36670db7662c6daa505701fd279f116" + ++ "ac0ef569471f204e1531c25a4ac3ce19b6f68a8994b6f89b5abf034a6507" + ++ "32c7fad4206eb4eaa7cd9a710d866bf3c3f13c16faa268ae0cf4f69be909" + ++ "bb9b79aab80dd25101d4cc813a48d3f38d870f10ac0b6768005aa0e69e87" + ++ "dfc0424deef06414c9ba6f498c93c41c692a7a6221fb5595b390a32c70e0" + ++ "2cd64471c797ee8a143725849c1e054ee2043dcfc0b4cb1c00be21a14be9" + ++ "2d9a07f1b4e975d4c86b8a5c1387e6c42bf393e078fe86d24612d497e14b" + ++ "874485a3cc922b5b6d91295d7b79ab8bfa1c7f64b51e761d19bb9da82a5a" + ++ "a34aa469699036b6b2c55e2b84f84942f10585027ab07e2e0e562e0fc3dd" + ++ "36047850ded84be4416e22aa41c7a2f7d4a4d8e3dd420d746a1d8d56d87e" + ++ "5133a1b4380bd9a89500fd6d7e68a1ec02eb9e79e4a13edfdde1273466e4" + ++ "6b0e6a75f59ff6175716629da52463ad21de27f40fa2e25a566eec4b2696" + ++ "4af3a717dfb0170a73144c0bd9b00bed67ad8c0a146eb5a055812d071209" + ++ "c9d530cd4f50a41488c2238898dea8bb36b0f1496d3ea8c4ff8e263b367f" + ++ "64977679e697d88e5295bd97ac16a0420850d1ead9621e25a3f58925c266" + ++ "ef5246488b1c15a8fe0d8ec4291864faa5a67b2388b7786f47b6d27e8fe8" + ++ "46f85f85163e54155ef95cea4901e712a44404a4d3f27f28dd961ce36b84" + ++ "f3856770f07f20a2ebd34d77405beab04ddfc09770167d7d6340f494dc6b" + ++ "7e4c3df896bd974730193b1e862b58d4a5938e6e4ae8897dba8812924379" + ++ "e54f51a71364d39f76e24fdf2c6c704479ce85b456558ca6947b8fd76f03" + ++ "78273f0a7bcd1d860ef1defe4eea8fdb81c73eda028d82fdcb2248582ac4" + ++ "59eb7698a811e6c5823be886410f6b8577ff2e8252343b6ea890016ae846" + ++ "01c5894cfb988121059fd9c8fbc1596da470a149404fc67baa15383d38cb" + ++ "d17ac107b4ff3c1ca4c76b7930de02b240e7547d39f4978e0cc1fa37f8c1" + ++ "012b677f07bb4df4486196e9b0beb823a3827585475b878e3f6f0a2d3836" + ++ "2c7d34f9f3c91ed46c39cec95c2a0b6f0279a03a00ed5035b0725c393849" + ++ "cdb1ed3c0ecbcf3c2ce108017f468e1c3d469c03e8231d4195344ced70cf" + ++ "daa667252cc1554dce8d0c54eb4cf4da62367d77d7dcc02f81e788ce9f8d" + ++ "d306ba1b48192359cfe92bdbea9980f87ea0677d7d2082205a436cf514e6" + ++ "fde5eadd21b13dc836ce33b5dfb6118bcac79ae00fbb16d61f00a923b145" + ++ "f9caa9f3a2c7f0104f8b052e390987e57c8dc80cd5f0358afb0111af1fc4" + ++ "e31f92bd832ad35fd2e0bdf768272de52ce0b152f74d43a8973ad516b3ea" + ++ "f5937ec8a236ebc86adeba610de0cf7168453111f3c983b64df07678cae0" + ++ "a75466ae15adfb127328e716448cdbd2c1b73424cc29d93df11a765441e0" + ++ "0eeed72228e1099bd20569d9d0e9e5a0b3c11d0002e2896631186483db61" + ++ "c1a0cb407951f9b1ea6d3ebc79b37afb5a7037e957985e4955979b91fb85" + ++ "61ca7d5e8b9cdd5b7ce0130a880d9241027b011fea7696b0c695d4949ca2" + ++ "d0cf22d44b9fee073ecaef66d4981e172e03ea71a6edc7144393bfea5071" + ++ "2afac137f091bae2f5700bfb073a6d57fddcba674a899d7349044a10aadb" + ++ "2e7f547887dd2f765f394de5dc9ef5dbf1eab4d869be8cb68aad8e2614ac" + ++ "37bbf21ccd5a832ee09fdd07ce50a580a2af36256b1046e646fe3dff6d20" + ++ "0c5110f1ad1311bc39b8114cd11ecdb87f94df43d4f6468932fc0ed892d0" + ++ "3d8f3db3f8323ebb29776ab7d260493a36700bcda668abd62126a8189e91" + ++ "df2d2970ef688d4e8172fc942e69ba63941a36b79ac546fff38f5f7d1176" + ++ "57612a662ea38134e1090c3e903c9adacdeefd3ac2a0467e9f5125058c19" + ++ "7b2260d2afad2b0e627a9ae52cd579ee27168065658089e1b83a2d8cdb47" + ++ "e08966e4ec0018e78c4d267f9575b8fea2a42de5c2d25356fe4b8c9cb1ac" + ++ "daf0d1af4bf58b9704cd4bc08471e3b9a0e45a5693433ede2eb1374bce44" + ++ "1f1811cdc7612d7bb61f4f34aea0a44757bbcc12a55c1ba41a7901eb004e" + ++ "689587a38e5b4df4574ddcc7b2eda97f6e480d7d39f45247ea3b03c90a93" + ++ "0dd168b65d52a59ce9c2cb4e860cc6aaa0ee02a58d0c8ba990194bce80fe" + ++ "8c34ba5693fb0943ec2cbfc919e534cc47c04f502b6c217c2f860d1d482a" + ++ "a016aa02adfc2bea3171fc4e27e2a262fd37b824099aa227fccca508f778" + ++ "b8c6ec7aaff1d15f6497753f439daa9e52060fd6e9e056e6843d770fb057" + ++ "6d9e2e782db4843c0c2c7f408a17376719a3c5cf9fa08f04f8a779885a16" + ++ "5cf93ce404be", ++ }, ++ { ++ key: "ddbd5d6c5ebd61fa72b453dd849dc302c98a0f3e300f4768bf1dc698a3827dd2", ++ tag: "af608b71a353e63c64911558baa122f3", ++ in: "c67e2524b0de16483158a0232078fadcf611e4fbdb9e642e397b21222423" + ++ "cc2ed42ed34ffcb178448919ee337eff9d7d691f622e70fd3317cfd271df" + ++ "fe6a9d9b7e07db0d20813e2331164a654386db2ab06ae2983bf2460eaaa6" + ++ "3aa0171fb87afb82e85b40d95c8993b2039d32e9d38473dd13f41fb1ff1e" + ++ "261752ab004b221a4472b9b1a0e139f0c999f826a26a7e7df362b0611aac" + ++ "fa83c55cca2f7c0138d2c30313c2f6eb357278328ea6ebd6a5077947e18a" + ++ "a97c34b9dde3b6f2de4b83778ffcebc8c9cb58756691d5e2a3d15a759a2e" + ++ "5050b6da937a6f5551aec069a08027d60dd870d175d2a5b5f0b4f3143904" + ++ "7445c368a5c866370e9426abbc1a1c5a272b96731c4128aedeee93e8e00b" + ++ "b450601a6d31ea279b9450e738b4a47c0dc22d2d8ed5d44257f6318e0c59" + ++ "b951fb6b57746062ab95cd73c23ef0a5c000a7d14c18bfff172e59b6f6de" + ++ "aa61b81009e803eb05e24fb0b706870e18889a9180ac16a042d12dfff9d9" + ++ "1b88130f045d2342fd5ddc5f443681c31090459f262d1a65654c55251fc7" + ++ "d5a67bd2e62940ccd606f3e50700e4d1e992a3fdf0388b9ce3df9de6dda1" + ++ "5c1cd6b70622ac062dcb7ed7058872c00ff3df94032853927126cf6fa4cd" + ++ "c468d91c9b52dcbc272fd7ba920dcd3ea1e048af9c3286dba74d988ce9ce" + ++ "77174e25a87935352721dc23b60a9549322fadbe6a00dd1197dfa25b33fd" + ++ "9e5713afcfd0fae6dbcf27147fa58d995580d7e0a903c895752fe9819f5b" + ++ "b002ed752719552d0f3575312f2e618173a8ae7c147ca64a709053e5d2e1" + ++ "2f4d1ea337afa9ac4f9ba62760046ec1e48f4ed8f6df66786c9fd9f5bc7f" + ++ "9ca2526e1327b042f4657c405757690e190c91f260dee2dd3d2e6616b721" + ++ "e489c7c3cb828478a3d953b88f09904e7927cdf6dbd6a5419eeeb83c0be2" + ++ "51934a80dfe61e09442f0761aa2d013e10aeec3a32df204571ce8984a430" + ++ "9bbe30ccc91977790bf0305d2651ee450b749c3e7761534e45970e70a0a8" + ++ "473cadbc88f096970c275f188c9d2644e237fd50c2e24c1eabbf7578e80e" + ++ "6500762ac513fcd68cf6f8bb7a9d9eedadca059d9ecec07fe6fe7792b468" + ++ "9311861728dd482f087c28374cf9c5ea20b2c8630029e8485fa6fe518c74" + ++ "ef77d44eb7526ca764e50b5f34ed0f253a91fb2af6e59338e2af6e041e01" + ++ "084e1efade1aebb7d1b698ccdb8b4248ac89cd40d9517d840960c08f5e86" + ++ "88d8ba2b54889c1870d315498b70e0e9720f2c8c53a3377a8c0bd2d6a1c6" + ++ "f17c6ff847eb14def6855dc3886b99039e528b421ccbf6064e39263f8f3d" + ++ "340d5d20b1b14c264ac2310b5f3a0c6f0c1006d0d4f1a69af68d28ab447f" + ++ "cd17387e1fc98f164982a6d05dd32d6b4f0f1b04e40c6c6e0fb4467dd6b1" + ++ "0c5a9c92cc8c2bc97ef669b6d55cdd0aa8a15c46af954359165949012713" + ++ "4ea9f74181d54a300d3172c9f01db73288ef6a709c763a4891666d0baf88" + ++ "8531dcc77f0911412d096aef9033fa36b5c1ed283b8b5c109e45b5cde911" + ++ "6f3da2533fa0ab81929bd5783271d5501a9e4fce2aff9eb5a70a4215b253" + ++ "46885d7e4225fe34bb55b309a114a312693d60ccc61267359a8c2dd28141" + ++ "226e7cfd99f0f12c69df57d75dd790dbabfe3145f7fd1a24fa58e03bc2e2" + ++ "6ea19288af4929e5acc517d8f52a074745ff4644d94179eae6ba7d267292" + ++ "bbd2053167a0da9be5e4b6cd0a4200fcac5182d9957dffbefa857e662b82" + ++ "fc3a7cc32506e78030ed5c5d448d7f1b4fd854a735a0c50016bb85e6e716" + ++ "0f87527bca0de235f4b7dacb75be84919c15a5b8cf6bec035795cb67061b" + ++ "7855c2134c1b1bfa6affe04b7db239f73af6ea9c02bc9f7972b7f6400b6b" + ++ "838f4653aefc42179c21765e3ca7a5e96b4402ff544d4bc2332756a23500" + ++ "11241dc42ec6848afe127c00b9c333e69bb5a54ea5c7193e59ea22bd6d32" + ++ "af4f56b1bd2d5982ef7d9c1b02d7668525e4e81b68a400f7afc2653f0f41" + ++ "a03e11c7a02bd094830093481afbab96397245b9f37a568ea1c4ae248cdf" + ++ "afc87f88b1fb5dc300d8e9039af4e6e701b458ed3f32d693f2e869b76bb5" + ++ "1358cbbe5b5089013bf452734388a176cccfc1ae9b7cff603631ca48e129" + ++ "b5c9573d4e379547272cce8aeeeb407d3fc57f782a0eb5fcbd41e6fb13be" + ++ "7e4f1067cd407b42a6121b2969c384916ba2b32563e659f52aae09c8ce2e" + ++ "3c500fbb7e58be74cc1592dcfacd9f0d4cea1a90a18658147c81cccf6fb3" + ++ "078ed27f369e7646f551386a74e1b07074d93e0c1f298c761af46cdaae9f" + ++ "f4be86808b66d0e228016d27a3a77c843365cb847fddccb0bbcfb3b9008a" + ++ "1bacac59ffb0aa759a0568c72c556caf0ac1091431b574687c5fc7bd486e" + ++ "963e0fc3bdc828d988734a21070747c955cf8dba2df1c3a0ba8146cd58b5" + ++ "91b6d54712db67a9851b1607c8445bc97406eeb7488f5f85e547850d619c" + ++ "407f97632ca1801f52c09c2b314b4ab0f8e7fb5851fd60852f4666913ca6" + ++ "bc840c1ec8f8f06caefdbfbf02ce00f20b87b14ba9e651c80f40a31d0306" + ++ "403f541776075fbf23733a6b19e3b44d04b455b29ef8effa70cce0c59331" + ++ "7119abc07aa8c8d0246a760b0b36a3d87b244e83bae8a745b8277a531298" + ++ "f5d0283498a509c89898ddf0f7a7455be1f8a6889c46d323f1dd18c3babe" + ++ "1751a05f871f0639f50967afa46c19cb93d9c2a79c81e2436a7a62f225bc" + ++ "37c90698640f5b43673e1dc276de05ff1e29acdb4ace5121659db5f23c49" + ++ "57aae22f53e6f2cc935824fbd07c2ac87672eeeab895c3f06e09e178560e" + ++ "2fcfa7097f10201dfb8b1ebac08ca806c1b3ba3aff9284846a1a3beada53" + ++ "e9f7ade12eb89b5591f462b2543bb4090e081fee9fb53bbf821dc92d6b16" + ++ "fe820ab2ee4b1f6c0b6a6f19edb0bf6479e257fc73bcd60dc2261d0a4752" + ++ "e23a0be18abf355f3065177d8c3c14e21edc178d0abd1b39f703e6335131" + ++ "ec90cba3d9846cee7354a06c320a3f61b8a269abc7138831614f57ca6c19" + ++ "a4a621142889cd924bf4ffb82b57f871b854f3157e8874c22d43a5726900" + ++ "bafbb8f2260a1eba3a462e23d4def2ccf68ebaae8e52739a1ce67c039eaf" + ++ "9a6c3232fbb5a91d1e59a8dcd3798ba71345fbf83d09b83b41cc49d5ff5f" + ++ "2e809d2b1d5fbc1e7001ea76b9b2d8f896eb6609e2e1c5c562d2a6e74960" + ++ "2d67a0f6b43a201d5087509b8dc7b0440144e308c18ff8b96b607de2f20c" + ++ "6ee99bb05367a8b25947011889f724965a2b5c52c9db1e0622df9343c548" + ++ "d054699badeb15fc41055af0d79a2bfc1a5b4574634fa0dd9dd10a6213ed" + ++ "b6991187dc560facdc27440456a0a209fd7f5ee4fb350ae71f869723e5eb" + ++ "5338e3d1448bc993afca6957f4cc7b047a2c7c9593b7234725e66cc0eb23" + ++ "3824eb4cb905701cc522ec210950b871397c6c0bb3d0b839f2eb1a120f70" + ++ "36107246df4dfb2c24891bef0bd1dc131f2c9d7c295ee967e3184d963037" + ++ "fcc9e0b8c7011c8e04b4e70038150d34caab4f8c0230418cd2d8a91146e4" + ++ "4e11cf6707452ddc03d9b4e6380658135dfb48f62c0690ebad75167f4dd1" + ++ "c0df3ed555b5081a7b82616d9e501757c83c2193d0f640236d59f9c97a4a" + ++ "5c8bf532aea2cf5964ed2dbd8a70c01ca5c7677224cf2a37f3b24d8fe4ba" + ++ "91cd3b5033715de227de51deed15afb8eda9d2b9615d197b8f98322d7096" + ++ "79c5131eed48050fbe0145a9284e236605c25a4876e2adba42f4e35a8949" + ++ "3d59bbf44b3338d9d2e65a7d7ec6c863cd47cae9e23181b07298078a5e9b" + ++ "06a5c7e1059f474eb1a4247e8f02cdd4efdca67d22035b12abecf9b15982" + ++ "de4932a28e797bc4de38442cff2cba263eeddba0ab14fc706dbca04eaca1" + ++ "b4cc13000a10e35b32461424809b299798e4d8e66c92aa3181c5df16ab65" + ++ "9611cb625e895a8021af8c60960227d6f2ebeacb17b13536a5ff139734ef" + ++ "37cb67018ef9a410b856e6f6eddbe3f59b088d538c50a8f3f0912d06e47b" + ++ "88d773069aa759cc614e1f53cf6e572c127123d1ab56b79ee753a921cb22" + ++ "a60e4e6cae768c9966de4e2625484f2e990154da7fca84b6e6c0b59201e7" + ++ "fb8a729cb20b4c774381e84f1bd6e304543d952dc76ef741b72f3a4ca7a6" + ++ "ea7958b8b6337994ed82dcf988eb70f509610b9a279ab4d0f28cc2b2dd99" + ++ "3b8637a6be0cb4b5f67c79654c6b15e1b61120374ba9b974a628c547f11e" + ++ "52d72d39f8f9c5dbfc23a89f22d38984dd8d5c3ca72cd54e6adfe2b3d163" + ++ "86afdb50967846a4c311351a51e5fd322757bdb061d44c8796a61fa4db36" + ++ "793bc11984eac83bbcefb40d0bc7bab0ca81e7df3a7f58c6fe800396716d" + ++ "832acaddff6d72c8e19dc9ea838294ead800deadb6bc18d3e399fa76c46c" + ++ "5d88ee72a86a87399423b0578eb6e27d78156ea2abf6f08b5cbf747f2f74" + ++ "5301b694bfba84bfe3c5527acd50660eea5105a2644c1aa92f954a604fb6" + ++ "a1b3b2d0331497deafc3aaadc7040b9188a36cf607ee85a0655ae963fd32" + ++ "91dd58f8bb50b4e46dcf7c2957639bffa6b12d895660dc0323b7a092f999" + ++ "813380b820e1873c60d3e3038129c66d507862100a5d5842150869e7873d" + ++ "6bb6ad022350ffa3813aca26c80ccae72692bed9c77c9d4da23178c57153" + ++ "90b5f4505240a796ec9d10a7f280bd60a570b1b693453807707651fc0464" + ++ "03e4768965a6f42f112152942134f0a38c84137c7a6e086ef1ab9ad20d24" + ++ "3b93356b305c0996ab7d02c02c44cbaf8f7e60b8c0b8c9fece3f189b099d" + ++ "dbd126b7357c1c4ea1c8bc1ad93db91ea9bf043a4320acb60b502bec37b8" + ++ "6b2a5004b8225e549e613c6f83b97b7e4aeda1b013e0a442d7ce2f14e78e" + ++ "a94bab700c9ac0abba945e28f39fdadff223c4498cb204f01ddfcb450a41" + ++ "f32ae47f99a49114c6646a5cb103e9cd75f9d81dba417e48c4053e3b0295" + ++ "2267cd30589b0f5d993a5485a6ead1ffab9f2f4294c5853ba76383a326a6" + ++ "a42fb8b78948aa49f0f1f614bd0a3fbd2a58a3197daf2094605bd838285a" + ++ "1260f1265dca74aadd95652632335fd17cafcb73b202c3f0e5da836c2dcf" + ++ "2934f005935dca80154af43fa34c8ba440d1581b74ff17dfaca369dc9aa6" + ++ "734c03916d78e1b952691cef918fe033d33f7f4323cf724ffb8cd6c219bd" + ++ "046e9f268eb0601098e93daa59dde370e46269dd7c54891f71bee2829a53" + ++ "df86a2c7fb1046cd7c98fa21cd83597be554997a70acebe0b6e60f1f7098" + ++ "6f65adcae24385cb7102bdd3e01300ffd15d00f9764b3a5c51e35e5c9cdd" + ++ "da84f4b656fe514ec4ff8dcd774373f8a9103cf36abefe875f7084b9bbd9" + ++ "42e0c997ec2d860a4b622ff1a39a628582fd81f237d3d8f6843d26ac77cf" + ++ "bd48003e8e8c591ff813a9a897e3149ff0297ff476299d717e54d885cdd4" + ++ "4c3ba6ebf54bc7a1", ++ }, ++ { ++ key: "b15578da1020f662ada0ad4f33a180d9f8ad4991b3720bc42a22b52625c7414a", ++ tag: "b0e4ad4a010afd6dd41ed82868cda555", ++ in: "6d2afb7a9154064341bdbb533f11990d4987e7c90fbfc0167c1e58d6efff" + ++ "6010f7ed569dac62ad37183b0d384519ebed0bf9c6e05a070b4858e6b846" + ++ "547ab5e45619c866f83cce83dcdab6a8a6c36b115ac832de1c6d433b94fa" + ++ "35803fa1a36f1ee114f8632402a027a74ac110394f32ec4006beb0057f09" + ++ "a94dada8bd0d1ca9a14b1f2efb8f526d79d6438bbbaac0ca1a43935627e5" + ++ "d129d52c06bf6413af07513bc579447eccc3a9406645c94dae59dab98d6a" + ++ "f92fa90fd4efaaa4bec466806ed401d2083cda587139ad7e9ee2adbb1dfe" + ++ "a88b59dd788b954a0f52c3854a3fffecb4bea83debbb2f5f8883e6415d3b" + ++ "ac1b872df1afe185468adc59364c173082f1dd6da9d348f5f5ba2d216243" + ++ "23de1f623eeec875bf31d12acec40dc0c1b9562826f3105cdad4c43cf45d" + ++ "829aa8b14012c47847aef7a2a6e3935fd972235f5d3a7ce4ad3582785393" + ++ "602e2e27329914021eff38ed2926c88acec1551f17a1b818fc1c3ed4b3b6" + ++ "6825d55bea269d710123b52e12ca9520a069d9c6a21df3a0253b3a4a6a8c" + ++ "dc226d667541548834da6bdbbdc165f39e40047d4b647c507d981be17b3a" + ++ "836063436241a8bb46b11a2867b621413c42d838e4578b72cc1982e34bde" + ++ "c303b5575ef4b8dd9fea8ed5bf69539413909d03461d3853b5fbf714a61c" + ++ "769569f42b38fac4b849104e2f2ac1dad0e388646278789f83e0b0511571" + ++ "019d3bfc5b03ca4cb5564e4e75e103ea1b6000be6588e27105d7cdc2d2f1" + ++ "f680ad34ef823ac4bd4068146e9997834665aec7dcc7a82ff28d85d52dd6" + ++ "9c18dd35f326bcf709f74df5981bb90ca8e765fef9f0698a19e12220b287" + ++ "24a6d9e4f4c7ce93f8ca9a126689ad1df820072557ce3db246cdf41599dd" + ++ "44ca841bece6c7869358005536e1189aa86b764e890ef90970d6e3831def" + ++ "fa890bf8692381123924e7d9df804fd770a0a30ee97d5dcdca302833efe8" + ++ "1d4b2505b17382f0b3429b38c41269ac95e36e9f5a1dbc6e6c8963741917" + ++ "02a23198decb4efe6809fcbeb5d0c9098a4c300155dc841610e55c8a6e27" + ++ "2a38a39de3d8ebf38a750af25836ffb1bb7822bb98886280f0cab6838c01" + ++ "cec57961bdc2e1bf158248309ff9294adcb962252b1c24646d132a3be2c9" + ++ "1ff82e8e101facbdb807826cc9d1840a90874ba08692e808c336c9d280ee" + ++ "f36a43a75c746fb864f85711e802546ab5cc3f8f117904ba1a85d6e4b729" + ++ "85122c5041891e16d55b93d6fc1b7fcfdc80ed3d72d55d64b8895bbf2f8e" + ++ "d188684e7e89afdc1e6a7ab9bd1d3da95d68698df2cdcbb2e1a4ae70e2fd" + ++ "dd4760f9e5cf4255eeb1e9e8009ab507395bacb8b2177e7c5757ad02baa9" + ++ "a96db967d20a150d2dd7f3081d90675fe0c82f94aa3cfdf6ac5585583901" + ++ "7a8e122170cc817f327a3c8ef44acd6e4fa81b73bcd0bcb5792eed470481" + ++ "152e87f7a20c3f7c69d5a8199bf9bb7c7269b450dc37a9b22102acaa8438" + ++ "134d6d733d231cee9522f7d02fbb37b5818ad3ca72df4752230ee11392ef" + ++ "8f8219be55202bc3d476f5a9078b32fb63d42bed4cda5ef90cc62467bf5e" + ++ "418ecd9d5d0cf1a33eb9a930e652ce96057fef40b65588aac67621d651a0" + ++ "9003dbc3925912e385296cd3b2b386a44113308ddf2af52ca390487eb20c" + ++ "716b76d78ad45129e7c285d918de7107ea8c3b0cfd9e73933b87c0b2b505" + ++ "cb4c95794f2ee6d6d43e2e76026923a0bbfbc3bb22df9ad729452283ce62" + ++ "dc9b26684fd45e07650581afd73713a708869a069c58b599ab478974f206" + ++ "dbd3e4e563e346ff1881723c5fd440bdf9f70f761c6f746113397d7c04b6" + ++ "b341d7e44de7de0aae79badaaef5ed372ef629dffd52926110683ab2d4da" + ++ "a4be83eb86c8700703a660edd5a5029f66f1581da96fe1feefc970ab4086" + ++ "a83ae02e959821967bd27b3b629652f5bc3db2b7f1af674f9f3fb3a788f7" + ++ "88e6dc1722382971831a7ed72502f85b25888c1534d81c0a4f7351ecc40f" + ++ "4e0412e05718403fae5746d313a78c80ac297f1391ad389070410e1330a1" + ++ "b07d683d1c795bda74bde947f2cf0dc9638b5d0851cda27df030403816dd" + ++ "3b70f042888c9c192656cc4b9fea10b81b5347900d9199c8f0f47d42f2ee" + ++ "482b68acfa5ff47d9950c950a926a497d94c6a796e0b715416520bd6c59f" + ++ "30217718d5f1d7bf7c24039f6467214ac8783cf011b25c37c67dfddde426" + ++ "40afe97f94879f4586954737b86701b32d560f08caec3fc45184bc719c7c" + ++ "5bf699074fde814acae32c189158c737665a8f94637068322f0c23ff8860" + ++ "f1b1c1bd766440afee290aa6f7150c7adefa6d72a738cd2268da7c94788e" + ++ "bb39002e9a328a51f3a92dc5c7cd9e4faed5702d3592ad16217c4978f84e" + ++ "af0fd2c9e4c6f4dcdd9112c781eb41a9aacb0f7935bb5c92d41e67cfff6b" + ++ "991ccefbd667ffeded1de325da50c33e28e2eef2f636c9726dc5bfe753ee" + ++ "c7bb6e1f080c89451f81bc8c29dc9067ce83deed02769714fa9bb477aca5" + ++ "c09089934674a0cc8e4b2c3136b2e4af8040cc601b90a4dec898dc922ca4" + ++ "976ab5ae4ac5af93fa5b1854a76ac3bcc2090bdeaa49ec4f319cf7c7b674" + ++ "6d8e617abb3361b28b27983dd1b139ec4f5af7e116439d7ecb16534817bf" + ++ "264dbd8f59e80b443be12c17fa013c7f4d029504c9bb62b296c2326f4f49" + ++ "cc3201b70ac3f62abb683c630179594a6d4cf30fd55b163bf8d01986bb6b" + ++ "cb7050fd527f095c45661920268e56f760fee80a29c9d37b7fc23f608710" + ++ "1e723038e64ee1b91c4849d69bd95fc9bc24fc4a234f4855f2a203e3f699" + ++ "c32698585c83781677739f2c48697c93b3388dcc64aa61f01118495ded33" + ++ "21ef9a1c949481f96005f8d5b277a7d6a0d906ec304cf4292df172e72d20" + ++ "29ecdeb65f06267a605f376804bf7bc5b82d5c8facfe7e41dc10806d27e0" + ++ "bcc5a341d80b3c1532407f75088716d732632cd88b0037f0d829bf385fec" + ++ "b52a202956489f61f16b0f4781bf59068b33d7330571d0b4a6ed91830258" + ++ "e1220b308784fa155be9bc821f5c0009a33802fa66dd66d1dde997dddd97" + ++ "873ddf65927dc1be979af2b5f110eee627dc1e210326ac20544a757ac168" + ++ "1823f3dd04b1ddc4bf96677a0a87633994e7af2ec99b7d5dfe44c6192be6" + ++ "a6e69d17b074256da3947808fbf68c7506a7e2c99e6b64d1ffadbd6285d8" + ++ "e7e032e24d42dde0594bf03fd550be05e5d66c91a660cd1ab7cb1f43fa9d" + ++ "69885203a7aee35a28f117427d7ac02b742f53d13b818f8631081b1730d1" + ++ "5b4e1e283cc8e5c4fc3b4652fce05fd8db821f99fcf93e6842816a549791" + ++ "7f6c49cc53d733788b2fe3c687de58bfe6153c70d99380df1fd566a7c758" + ++ "8052c62e73340d6a9eccd2ed26b763d518f3a0c4d6362212fbecebb4ffb7" + ++ "dc94d29944fcc4ab37725b105aa7571f364146782356d8ef056a0be93a55" + ++ "0c890df8fecc178776fe40703ad1bd2443d92c420be4306d99686592c030" + ++ "fd3e2230c0b48d8db79002e8a832ef27edb53a45532955f1171203d38414" + ++ "b4692e901e9f40f918528fc494430f86cf967452f456b01846ac6a383fc0" + ++ "de2243c7d804e8643aabcb78e2653b145f400a999670217c8da43bbb9c11" + ++ "e074176424be0c116c304a420120138e901eca4b12ce68fec460b23bc0c7" + ++ "765a74fc66cbda0e503e7b1baf5883744e468c97c5f1c4b0acc4b87de9f1" + ++ "4b537405dfb28195439d1ff848d9cd28a8d375038ebb540a9075b7b5074b" + ++ "ebc18418a370f1d3ac5d68f5d239513002ad11bfc2b7ff53e2e41ccffc4b" + ++ "0503acc4967c93ae8590a43439b5e7987d10cb8d1957bd9ef717ee3d12df" + ++ "5d6736c1d8bd8da102337a94b7d14f830f6c403cbaf7925a8a2a7af1311c" + ++ "57224967a38f6ca374013a9819c55fd2e2a5fac4f2490be5b059f4cd9c60" + ++ "2d62f80789eb8d9ab893c7f44a4945e41886af218179dfa754bbb59aab68" + ++ "13b71d2202eb8fc8a425625d21176a28a620e21bb0dad820c0b7051ce8d1" + ++ "3a33f3af0958bb6cd89f9d6414ab00ddd1d2f9fdece9183d0c05fcdfd117" + ++ "10d250e4b2029e6992a88293d0457e73e5b1b6a1aae182c69b9cb664992f" + ++ "073595ef68117026ad7ea579a4043cda318931eee7b2946a34cdc7c9755f" + ++ "80cc79a2bfe3ed9c79dc52faa5126b824868c965eeb37e9e4e6a49600f3a" + ++ "cce93c0853b546edb310dcd16a5755f15b1098b2f59dbd2d90e2ea8360ba" + ++ "f12108236e854465456598ae2f7bc380f008f2e3cd7c98c87643cafd7c36" + ++ "d40e2597236428d46aa5b260f84b4212d5e26804086adcf00363ce4becb4" + ++ "9b57eb2847b2f18ec82c99714ad4ddfe4ff3bcac1d0fcaa32660a1dccc68" + ++ "5bed83254c8e2ea0ae3632a70cfbcbeadef922d78a006d43ac7ab1f8a609" + ++ "c6e0ebc3ca6bb8430f1a562f41010db74b9febf931ca794fa08d1bc17780" + ++ "532ae76f25c4ee679d788835dfa4e70ca154c9e2865c3750ffe7b837eed1" + ++ "972be058fdf2bdb3eb301867bb132306c7aa237f6771d60bbc56cf31cb30" + ++ "32a87204d454542de747418470025ab84935d3eaaca01dbbdae9ef6b5d3a" + ++ "ca62ce9f871a3e1272b2b671582c096a349c00f32d742ddb17993994d8ae" + ++ "fc178cbcf9abc03114ff2bf7db8f757c63d6898faccd822f5c2e9a7570fb" + ++ "9cfff148570888be24ae42644c1a5bebb6f6287147a4bcc01c7675be9e4a" + ++ "897519dd3132a7cc2e778f8c90d23dc8073f6fa108d7ef82d561794bd9d5" + ++ "f1faa306334f338ac3ba99c853f79c24f7048fa906fde87d1ed28a7b11c0" + ++ "66a3bb98f8d21055aaafdf7e069b77b60b3d5cbe7c5e4379c7651af955cd" + ++ "82a19a09caf36becb6cd3fe9e12f40379941542709991066df21b7b12dfb" + ++ "2416d83fcdc33bb583e3b42f24f53edf8dc7c579ad3be831c99f72bf9fb7" + ++ "a35b6562e824e039e6bf1adc8f5ca53846de7bae11c4317e696d887df33c" + ++ "525f0a9c01fc29f2c26c90b85fe82ed8bd50954cd4e9ac7c85c7f3efec75" + ++ "da1da4ed173cb695cee295190527edb3cb06c5dbdabe0228cc60b6455153" + ++ "76244f27aa56da2db10f2659090137ffb82c57233c833e0bbf22d6f647fb" + ++ "97b3652d2888b3ab08010b8e8a6967d560b747757806736dc98b78226634" + ++ "f1eecaa4a2e23ba36591acb5737d735c5bc7a2e36f1a46946927e061fdf7" + ++ "7a3b68ef582c26b01f5aa9a438ecc26c6941221d1590c838072f9e471fe7" + ++ "fd59dacb0d092d40d76ea2f7c6e954a132a015bd4cb31147f3ebe4518322" + ++ "916438a62836ac85a4cf4492190a85bcc8edb37e38b99ea552d749c30f74" + ++ "ca20c298165e8ed02d4671e0b41cac3a32a345b9349ad22c2a4bb2c16a4c" + ++ "e0613ca0f0518759f7d2b33cfad2fae764f410d4d9ff8a76ae02a8107e7e" + ++ "01d9cd0552676b85ba002f19c01ad5f416d1d08bb84fec7c3555b098dbce" + ++ "48e1a5d847895e54db9c5b80cc22d5b87cd41a1a94be102bdd45a3cda5d1" + ++ "181e10446d213d6b3fdc350d486d2011d705c5f16ccf7519065c47bad7d6" + ++ "89c71e5fdf9d04bfb91eb1f07fa0f001009c1d4b1f6a116a570823a8580b", ++ }, ++ { ++ key: "392468efccff36dade31fc1c62eb38bb61394fe448def9d9d9beec2413ddb418", ++ tag: "e1122e7c8e6965b90addbd46d8a548d6", ++ in: "6a13d37f0ec933194c227351f4a19b507d93465b1f3e88dcb5f1ed1262fa" + ++ "58ea99ff31e6fc85c39c04129fa69195b71b2060122fe618dd9430a63f97" + ++ "54b52a80b3cd099f248f91a468bae211a27bdb47ba005d29881ea5143a82" + ++ "967c4c30c9a4f0dba1a4975e6407fe296d40023a00efa06be763f2d73d46" + ++ "a2901ae28b3d8ce18009a462e223b71476d7b954c138e177d15a390847de" + ++ "96a7f7fd0598748e86b0f08e64d915e67c7e3cf936f3dcd60edebd36e2a1" + ++ "d65b6ac29530c48ab3bd52d45b4f938a19b9b31e2911105a8561600d5377" + ++ "905a67112ec28025aa680350ff85b808c5b4c98b7b9567d03f5ed3911ec9" + ++ "365a8de4b15ca62adaa69e5ba710eb1756a346016c67a297d8624f9f1ab5" + ++ "b3fbce98b141049f0ce26c85d2f8a9cc6ca8ab6c6e148be968931430dcc6" + ++ "2bf58ea9698ef52a5d271cf48e6748ac9e04bc7ae7da205a1a7535478322" + ++ "d820eca146cedf4b2f9aa9fcfd77ab56a7276977401dcc1f96baa1b607e0" + ++ "256bd04ec324ec67a4313e2d5a53d3a3fb5332927929b20c63bde805f637" + ++ "eb1050fee2a152a0405634f55c48a59fe370d54b2ab1671dae2c7fd92243" + ++ "10627808e553127c74f724362b4a6ee49b697daae7df3ddc5d2ed9d6befd" + ++ "77fb9f68fe3041f6ef13f46f34ab682ab8563e8996344f82b2ef006a8d54" + ++ "3dd9c1db4979d7da97bda45e722065f8a238f0873217b783a9a629a12b3a" + ++ "4de437445039997bd243efbf5e3b6059b9459d395290efb9081c632fb694" + ++ "81000dc74c395cb507422df181aba20f776ce3fd8765ac485021992c98b1" + ++ "67c68805662cb4356a0ee7ba6bdae51ac10cd06bb5b2f3a72841c714c8ed" + ++ "bc56998fe2fefb9bf69e172fdf54b2ab138ae59372c52a67e93882a3000f" + ++ "d966992aa2250c6ff93e9cac89645d70625d79332ade5dab7eb1adbe7dce" + ++ "5a013fb65ad32fe22ed16fb9bb35eca1f37a0433c320e8752f8fc4b7618c" + ++ "5e4df2efece832e259ad98b895c474e47d0e3fc488bea8f717a17de0dcf7" + ++ "597fb8fe12e62246296f9a887dcc3a700820c190a55a4931a7d44bd3bb2e" + ++ "ab6c8a8126f1be93790cebabc1d69e01796e6cc80e7c16bbc82fb333fb21" + ++ "c774ab7db843242838e82d8e1cb8ccab385e67a4271fe7031d74b6e8edcc" + ++ "8ed585d1c05a365c7665899c1dbc561151d3b44bceace77c4f53c0e0f6f7" + ++ "74d42f9ad3e56f1c2a8d53879d695f895690afb4698472a3d52d67159313" + ++ "133c87823fe0500eb68fe286f8b9a2f59f12785d026dc97bdbf793c7d1eb" + ++ "155f1f136aae66c256583e987f718afbe733e0a5ce30d021493fb84e2242" + ++ "5b18754d126235ef80335004fa84f88361a584753df409360cd8bd45bace" + ++ "8f48156bec66577bf2c685089f5ac7e7ec76c0df068fbaa47661f8517f92" + ++ "e14723b3b278f151816537a7212c96bd340a00c15c9c9bc9a2a5d163655d" + ++ "84b38073e2be9217cad97d362d89d4baf3ce0a8d8562f19a8c97a9aaf5e7" + ++ "77d60456360ffb77b30f177d2809052020d141697ecf9cb65f42b9190caf" + ++ "6540b2c82f6e5a8482934a6a1a5711a8c24546cd8ba432068404eae5a827" + ++ "2e09efc3c6037af4feaac0a46329229b010ecac6b9f077a9b076bb6d9ce1" + ++ "38401eb38d124baa11507a994185295020bf9b754fcf78430db9253f5929" + ++ "87c46c0f8589c4e463b15a3840b1cea795e24cf6b20f29a630136e0589b3" + ++ "8dd7fbe5ea21da72c88bd8e56473586822aa3765660a45a988df9b8eb8e8" + ++ "141939d3e4cc637c5d788064d40a9f7c734e43fdf8d7189a5d76700d9743" + ++ "fe0122944663afdb88c5201318ca782f6848b742ddebe7463fd4a32280ac" + ++ "1cf8311e9137d319de05ce9cd85abab24c5364041c14d3b4ce650400498e" + ++ "122166eccc12784b7ac3b262ac0b198ffc26eeed9a5da5374f7a2a53c87a" + ++ "78c217ea1fbf8d38f62511657b73109f31691aef14d82ce6e1010eae9e6f" + ++ "a419e5c1c16c0cc70651eb3374c03549a1bc7d3ed42d60f886102c798dbc" + ++ "ba56f0a2b3b9b412530c35f5f7ed06311ee14571f9c26ed9c81ef38ff000" + ++ "2f5ef3aab7351e32049a6ef8f48a43da1d84402d229df513dfaf1b2e4043" + ++ "6ce68c70ebeddd7477c9164f0dce45a6fc5de050f52ec269659d5854bcae" + ++ "f7762ed7400713c27a4d523eaf8c136c4a1ca00b9e9e55902daf6cdf8528" + ++ "c22ca1f2fa7ce87902d75a6850e1a5a4592497be1bb401878f18b189b0e2" + ++ "c59d10705bfabde3cd2da01eb452006b294108d5d42e88e9e15424d8cd0b" + ++ "8ab43a6c546b3dbf52e47b59cde6a3e417b0395220b6d63736d429da3458" + ++ "9a2524f1629320206fa7f1d8a041e17222c4a5814561937e1030e6375c77" + ++ "9dc988bb928bbdbe2c2eb20111639725d82b5d7192cd3e4acc27581f0ba7" + ++ "286cff41f97aa5a52ea0083de5057fd2ba985aa738e4d03fcf11ebab1d97" + ++ "e2ac77d1c2beb8799150a421a07b3777d0b850f24194b8309135b13da6c7" + ++ "e38653a711e407a1811290fbb7bc15d8b12efc6916e97ead41e042a44721" + ++ "e9cde3388073d921595bcddcac758dc675173f38242e65e4a284aaa7e8fa" + ++ "6adddaf00bc46428ab2d8601205b8895bcedfc80ca0aa4619ed6bb082ddf" + ++ "33ec04fa5d417f33fcdd238c6b11320c5a08f800e0f350b75d81e3bcbd15" + ++ "58a1eab87a3c8c2ffd7ba1d7e754e607cf98ba22a3fc766c45bd6f2569b4" + ++ "84639e6611714119d188a24a5e963089a16ed34e20b9f154cad8ac6031dd" + ++ "7a3a885afc2ae5e003ae8d4e4aabdb3e51dfc423b8cf4ed9ae2010072cbb" + ++ "b1108c7da1ff075e54ed827a0963ac5523ecdf3fc5eee7b4d1a6773764ec" + ++ "5c30f41690523fd70d895edb7ca6a1806d54240c4c7b43410da73503a323" + ++ "90d9070ed30da3a2fb5eccd40d083be7cf8bf40b4279f819cf795b6f075b" + ++ "5a67a10a06a6076d0d83c72efea05f244901c4b5fd9eb380432519311baf" + ++ "8c81f6325df4d37ff4d30d318f904ebb837ec76b341dd00a8f247cf0bbe9" + ++ "6f3784dc8f5feb344958fdf1a9ececb105f8770826db1f17a5281e997951" + ++ "d3c60cc28fc3e66ffeb5dbac315f98f6d240208043f28dee963d843e68ab" + ++ "57d847f76ae2f96ce6e37f377ef5dfef2176ecd7440ce4dadcec2231b606" + ++ "e4a80420fb3ed135640e1f05d6bd58b8dce062dd7d36b885d424f6318e5e" + ++ "a0753efbb33bbc7360d2b5dfab3ae0d5e000b8d31f2ba0f5fd8b34f96b55" + ++ "28fff35e769461d0f03cf3bfdf0b801dcbbf2838180cb9b108e06c353e3f" + ++ "0b9ef61678cfed1ea37ae76bccb5ef5957ac2c8e8f4794c8145a15f1cc88" + ++ "bfb0881080326c481b373c3bc9b07a9b60a0c8bd5fa4f6f90145590a5227" + ++ "6fcc0ccc2375d0ccb571d414d1b0c38b4e02c39db4d701c5e25e90785ef4" + ++ "d26f35edd8c4b96455bdca7245cfefd9cfbd2f319615e5fdf07bb9564fa0" + ++ "44bb35a58391d02e3927780b4076bc0893dfcb4b63a32cd7a541a4a8c253" + ++ "0349c6e96e378dbeb66dedf87d813d0b744452c1c4088507dca722193827" + ++ "9e2dfa24e4a409de494acf654f44262db9206a7717fa434ac4fdc6a6eb5b" + ++ "1fd5a193b6043bc4327c8c09fd6822eaa9df37bbcac1077754a295621601" + ++ "267b68733b62dadc2563f1700af180141f29899e2689dbbe9745ba8477f4" + ++ "352921900b403a01c9dd042a8c1b0e0489959fb0b0a8431c97b41e202204" + ++ "212ebfa00c593399dbd14d7aec07b8292d2e40b48f05fcd54a15da4a24d7" + ++ "2759e409f4c7b5b98fce4abac6c30e4872d92efa1f96479ec30f21699825" + ++ "50fa60584f5a09051a00f8e7dbb3853e66ca3f05fbfe43bef9b120a25a01" + ++ "eb436ba8ecda715201eda72e517d628f883386c1503aa8b8e75610f7155e" + ++ "9f916335ab6d6f0f9589b6220cd2b81c2c937dc065d3d14a7df8cc916cd0" + ++ "0ce1bb53fd9c8974298d3bd316f3658aa8cc6904f073a1472149e4b08c64" + ++ "5e11abe0428ccb6174df2103edd735965d6454b543d3f01410f77053f65e" + ++ "c1d1aee56fdd3af23bcd4e1a7fcc4e600c4831007c33fe5f0c8300f686eb" + ++ "9b4d1e4f08fe4ddc8a90be14dc3a5a88ff96716509341d5db24c0d016863" + ++ "998b1859c5021df815a6f1ca9845f1a8e99dbad132b406227c5897a1bdf3" + ++ "e698962f799133ff4429decbef6ce036296facf38e4812fec102b76c6d30" + ++ "beba1b70722254fafbc471096153478c971db7d96263660209265cb10f13" + ++ "b34b5fd55c4abe818a5f9715d8a85094e2946b7a001b47f629e26c636d86" + ++ "4968ad2ab616dfe28840bd60b4b9855c8dbe1cb873fcbc4577b5fefeb8bb" + ++ "4832039867dc35db9c036c83bc204396e3474ddfe806c77c65c936f488b6" + ++ "7c1028739562d7bb055d21441af29ae2921290e548dccf8a56021385422b" + ++ "15da6b232b24151309a75a00296d11aa1952a1513110b0faa93d1d8cd9ae" + ++ "fa9f1c59377ec9165b2c9e07cbde40db7b81bca6d58fc28bae8f473cd0e9" + ++ "a2420e0b943a83d284108626c24ac570b1d6c1ab971e71f43fbd6c00e171" + ++ "238141a6dc987a60385c3a04dd147a2f8e80dfe727b104c0fdd80b326f59" + ++ "0b9f86fd7b2fd1122a390979889eabd803ab57159c8509a1443eb6789382" + ++ "090a770ae4eba03306f96e50e19a7d44c584ccc230d104548946efca4520" + ++ "d61de5f473e2f4eada6c8ce9c7ee975eb4f63c0483cb775ed7d3cf690a61" + ++ "7d6656d683a8512707d81ca5ba176a42bcffcfa692129f292607d2a47536" + ++ "ccaeb464c9272d6f3816074b712af602470088b253deba18771e5f67734b" + ++ "587707cdd06f35264b2262fd253c25b5d38ee7db287610e5398062b7a34e" + ++ "6e4cf7447d00873b930ad148fd96f0ab18771bc468b874bb109924101c84" + ++ "c4e239ecc7687d875e4d94a1a973620ca61e35a872c2e2e61a502169f1bb" + ++ "4e5ff5fa2bff657be6195b3e2c7151a52fc0096d98e7f08f5a98f570aee1" + ++ "7b4275f1356e87e080ce0e1b9bbabe7dea48b5903bc390ce23472ad64a89" + ++ "41c3247bfd23ea90b2dee09085571bad85568040105e098f993bb37e43c3" + ++ "e6d511171c77cfc450570dfb9fc6a3930ef43c03f8213f6203d545d791c7" + ++ "d3fa42d5dde1655038d35c5dfacc12e9dee24fe833977549eda68ae8b508" + ++ "be277e743921b584f9dfa0eefbd8bf3c23f51efdef7f7487001d29e8097b" + ++ "ba63289cfca743023d1668555a46fe6d5b7421377414df1e9ef135480622" + ++ "22e2e9a7baa618d88f407517f6317b6a0ba3384ace16d68631d59ea169d5" + ++ "092d20afc1a481b82be5e734bb092953a0a94702bae1a0f48d2a22b9a05f" + ++ "f64493b7b2e984f27582b1eb937fddf8512c49830435d146dcc291a4118d" + ++ "5dc638b99cdcbcc5860de7a92c5b13cbd1e01e051f01af40afe124346320" + ++ "d3626bf9d8f7850744e032a993c276fd388718237740c6caf260fca60b8d" + ++ "d846102e3262b6e05ceca00c6affe938fac1847350865fc858d3ddd1d130" + ++ "71d1221ce7c5d575587fcba580e544b74d877ed5ca92763ef0ca0d7bfa08" + ++ "d57a0216b2a01a2b9ec74b8430051e0074862b7be25b6766ab520f2eb75d" + ++ "eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" + ++ "f2c5b0dc5de9f5e55a97791507bc6373db26", ++ }, ++ ++ // Override initial state to ensure large h (subject to h < 2(2¹³⁰ - 5)) is ++ // deserialized from the state correctly. ++ { ++ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ++ state: "0000000000000007fffffffffffffffffffffffffffffff5", // 2(2¹³⁰ - 5) - 1 ++ in: "", ++ tag: "f9ffffffffffffffffffffffffffffff", ++ }, ++ { ++ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ++ state: "000000000000000700000000000000000000000000000000", // 2¹³⁰ ++ in: "", ++ tag: "04000000000000000000000000000000", ++ }, ++ { ++ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ++ state: "0000000000000007fffffffffffffffffffffffffffffff5", // 2(2¹³⁰ - 5) - 1 ++ in: "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff", ++ tag: "1b000e5e5dfe8f5c4da11dd17b7654e7", ++ }, ++ { ++ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ++ state: "000000000000000700000000000000000000000000000001", // 2¹³⁰ ++ in: "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff" + ++ "ffffffffffffffffffffffffffffffff", ++ tag: "380859a4a5860b0e0967edfd711d37de", ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/testenv/exec.go b/ms_mod/golang.org/x/crypto/internal/testenv/exec.go +new file mode 100644 +index 00000000000000..4bacdc3ce87e31 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/testenv/exec.go +@@ -0,0 +1,120 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package testenv ++ ++import ( ++ "context" ++ "os" ++ "os/exec" ++ "reflect" ++ "strconv" ++ "testing" ++ "time" ++) ++ ++// CommandContext is like exec.CommandContext, but: ++// - skips t if the platform does not support os/exec, ++// - sends SIGQUIT (if supported by the platform) instead of SIGKILL ++// in its Cancel function ++// - if the test has a deadline, adds a Context timeout and WaitDelay ++// for an arbitrary grace period before the test's deadline expires, ++// - fails the test if the command does not complete before the test's deadline, and ++// - sets a Cleanup function that verifies that the test did not leak a subprocess. ++func CommandContext(t testing.TB, ctx context.Context, name string, args ...string) *exec.Cmd { ++ t.Helper() ++ ++ var ( ++ cancelCtx context.CancelFunc ++ gracePeriod time.Duration // unlimited unless the test has a deadline (to allow for interactive debugging) ++ ) ++ ++ if t, ok := t.(interface { ++ testing.TB ++ Deadline() (time.Time, bool) ++ }); ok { ++ if td, ok := t.Deadline(); ok { ++ // Start with a minimum grace period, just long enough to consume the ++ // output of a reasonable program after it terminates. ++ gracePeriod = 100 * time.Millisecond ++ if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { ++ scale, err := strconv.Atoi(s) ++ if err != nil { ++ t.Fatalf("invalid GO_TEST_TIMEOUT_SCALE: %v", err) ++ } ++ gracePeriod *= time.Duration(scale) ++ } ++ ++ // If time allows, increase the termination grace period to 5% of the ++ // test's remaining time. ++ testTimeout := time.Until(td) ++ if gp := testTimeout / 20; gp > gracePeriod { ++ gracePeriod = gp ++ } ++ ++ // When we run commands that execute subprocesses, we want to reserve two ++ // grace periods to clean up: one for the delay between the first ++ // termination signal being sent (via the Cancel callback when the Context ++ // expires) and the process being forcibly terminated (via the WaitDelay ++ // field), and a second one for the delay becween the process being ++ // terminated and and the test logging its output for debugging. ++ // ++ // (We want to ensure that the test process itself has enough time to ++ // log the output before it is also terminated.) ++ cmdTimeout := testTimeout - 2*gracePeriod ++ ++ if cd, ok := ctx.Deadline(); !ok || time.Until(cd) > cmdTimeout { ++ // Either ctx doesn't have a deadline, or its deadline would expire ++ // after (or too close before) the test has already timed out. ++ // Add a shorter timeout so that the test will produce useful output. ++ ctx, cancelCtx = context.WithTimeout(ctx, cmdTimeout) ++ } ++ } ++ } ++ ++ cmd := exec.CommandContext(ctx, name, args...) ++ // Set the Cancel and WaitDelay fields only if present (go 1.20 and later). ++ // TODO: When Go 1.19 is no longer supported, remove this use of reflection ++ // and instead set the fields directly. ++ if cmdCancel := reflect.ValueOf(cmd).Elem().FieldByName("Cancel"); cmdCancel.IsValid() { ++ cmdCancel.Set(reflect.ValueOf(func() error { ++ if cancelCtx != nil && ctx.Err() == context.DeadlineExceeded { ++ // The command timed out due to running too close to the test's deadline. ++ // There is no way the test did that intentionally β€” it's too close to the ++ // wire! β€” so mark it as a test failure. That way, if the test expects the ++ // command to fail for some other reason, it doesn't have to distinguish ++ // between that reason and a timeout. ++ t.Errorf("test timed out while running command: %v", cmd) ++ } else { ++ // The command is being terminated due to ctx being canceled, but ++ // apparently not due to an explicit test deadline that we added. ++ // Log that information in case it is useful for diagnosing a failure, ++ // but don't actually fail the test because of it. ++ t.Logf("%v: terminating command: %v", ctx.Err(), cmd) ++ } ++ return cmd.Process.Signal(Sigquit) ++ })) ++ } ++ if cmdWaitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); cmdWaitDelay.IsValid() { ++ cmdWaitDelay.Set(reflect.ValueOf(gracePeriod)) ++ } ++ ++ t.Cleanup(func() { ++ if cancelCtx != nil { ++ cancelCtx() ++ } ++ if cmd.Process != nil && cmd.ProcessState == nil { ++ t.Errorf("command was started, but test did not wait for it to complete: %v", cmd) ++ } ++ }) ++ ++ return cmd ++} ++ ++// Command is like exec.Command, but applies the same changes as ++// testenv.CommandContext (with a default Context). ++func Command(t testing.TB, name string, args ...string) *exec.Cmd { ++ t.Helper() ++ return CommandContext(t, context.Background(), name, args...) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go +new file mode 100644 +index 00000000000000..c8918ce592db10 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go +@@ -0,0 +1,15 @@ ++// Copyright 2021 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build windows || plan9 || (js && wasm) || wasip1 ++ ++package testenv ++ ++import ( ++ "os" ++) ++ ++// Sigquit is the signal to send to kill a hanging subprocess. ++// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. ++var Sigquit = os.Kill +diff --git a/ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go +new file mode 100644 +index 00000000000000..4f51823ec6d245 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go +@@ -0,0 +1,15 @@ ++// Copyright 2021 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build unix ++ ++package testenv ++ ++import ( ++ "syscall" ++) ++ ++// Sigquit is the signal to send to kill a hanging subprocess. ++// Send SIGQUIT to get a stack trace. ++var Sigquit = syscall.SIGQUIT +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/README.md b/ms_mod/golang.org/x/crypto/internal/wycheproof/README.md +new file mode 100644 +index 00000000000000..8ae6c6c3d5a570 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/README.md +@@ -0,0 +1,12 @@ ++This package runs a set of the Wycheproof tests provided by ++https://github.com/google/wycheproof. ++ ++The JSON test files live in ++https://github.com/google/wycheproof/tree/master/testvectors ++and are being fetched and cached at a pinned version every time ++these tests are run. To change the version of the wycheproof ++repository that is being used for testing, update wycheproofModVer. ++ ++The structs for these tests are generated from the ++schemas provided in https://github.com/google/wycheproof/tree/master/schemas ++using https://github.com/a-h/generate. +\ No newline at end of file +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go +new file mode 100644 +index 00000000000000..292d85425fd324 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go +@@ -0,0 +1,176 @@ ++// Copyright 2020 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "bytes" ++ "crypto/aes" ++ "crypto/cipher" ++ "fmt" ++ "testing" ++ ++ "golang.org/x/crypto/chacha20poly1305" ++) ++ ++func TestAEAD(t *testing.T) { ++ // AeadTestVector ++ type AeadTestVector struct { ++ ++ // additional authenticated data ++ Aad string `json:"aad,omitempty"` ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // the ciphertext (without iv and tag) ++ Ct string `json:"ct,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // the nonce ++ Iv string `json:"iv,omitempty"` ++ ++ // the key ++ Key string `json:"key,omitempty"` ++ ++ // the plaintext ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // the authentication tag ++ Tag string `json:"tag,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // AeadTestGroup ++ type AeadTestGroup struct { ++ ++ // the IV size in bits ++ IvSize int `json:"ivSize,omitempty"` ++ ++ // the keySize in bits ++ KeySize int `json:"keySize,omitempty"` ++ ++ // the expected size of the tag in bits ++ TagSize int `json:"tagSize,omitempty"` ++ Tests []*AeadTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*AeadTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ testSealOpen := func(t *testing.T, aead cipher.AEAD, tv *AeadTestVector, recoverBadNonce func()) { ++ defer recoverBadNonce() ++ ++ iv, tag, ct, msg, aad := decodeHex(tv.Iv), decodeHex(tv.Tag), decodeHex(tv.Ct), decodeHex(tv.Msg), decodeHex(tv.Aad) ++ ++ genCT := aead.Seal(nil, iv, msg, aad) ++ genMsg, err := aead.Open(nil, iv, genCT, aad) ++ if err != nil { ++ t.Errorf("failed to decrypt generated ciphertext: %s", err) ++ } ++ if !bytes.Equal(genMsg, msg) { ++ t.Errorf("unexpected roundtripped plaintext: got %x, want %x", genMsg, msg) ++ } ++ ++ ctWithTag := append(ct, tag...) ++ msg2, err := aead.Open(nil, iv, ctWithTag, aad) ++ wantPass := shouldPass(tv.Result, tv.Flags, nil) ++ if !wantPass && err == nil { ++ t.Error("decryption succeeded when it should've failed") ++ } else if wantPass { ++ if err != nil { ++ t.Fatalf("decryption failed: %s", err) ++ } ++ if !bytes.Equal(genCT, ctWithTag) { ++ t.Errorf("generated ciphertext doesn't match expected: got %x, want %x", genCT, ctWithTag) ++ } ++ if !bytes.Equal(msg, msg2) { ++ t.Errorf("decrypted ciphertext doesn't match expected: got %x, want %x", msg2, msg) ++ } ++ } ++ } ++ ++ vectors := map[string]func(*testing.T, []byte) cipher.AEAD{ ++ "aes_gcm_test.json": func(t *testing.T, key []byte) cipher.AEAD { ++ aesCipher, err := aes.NewCipher(key) ++ if err != nil { ++ t.Fatalf("failed to construct cipher: %s", err) ++ } ++ aead, err := cipher.NewGCM(aesCipher) ++ if err != nil { ++ t.Fatalf("failed to construct cipher: %s", err) ++ } ++ return aead ++ }, ++ "chacha20_poly1305_test.json": func(t *testing.T, key []byte) cipher.AEAD { ++ aead, err := chacha20poly1305.New(key) ++ if err != nil { ++ t.Fatalf("failed to construct cipher: %s", err) ++ } ++ return aead ++ }, ++ "xchacha20_poly1305_test.json": func(t *testing.T, key []byte) cipher.AEAD { ++ aead, err := chacha20poly1305.NewX(key) ++ if err != nil { ++ t.Fatalf("failed to construct cipher: %s", err) ++ } ++ return aead ++ }, ++ } ++ for file, cipherInit := range vectors { ++ var root Root ++ readTestVector(t, file, &root) ++ for _, tg := range root.TestGroups { ++ for _, tv := range tg.Tests { ++ testName := fmt.Sprintf("%s #%d", file, tv.TcId) ++ if tv.Comment != "" { ++ testName += fmt.Sprintf(" %s", tv.Comment) ++ } ++ t.Run(testName, func(t *testing.T) { ++ aead := cipherInit(t, decodeHex(tv.Key)) ++ testSealOpen(t, aead, tv, func() { ++ // A bad nonce causes a panic in AEAD.Seal and AEAD.Open, ++ // so should be recovered. Fail the test if it broke for ++ // some other reason. ++ if r := recover(); r != nil { ++ if tg.IvSize/8 == aead.NonceSize() { ++ t.Error("unexpected panic") ++ } ++ } ++ }) ++ }) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go +new file mode 100644 +index 00000000000000..0a60fc355c458c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go +@@ -0,0 +1,127 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "crypto/aes" ++ "crypto/cipher" ++ "encoding/hex" ++ "fmt" ++ "testing" ++) ++ ++func TestAesCbc(t *testing.T) { ++ // IndCpaTestVector ++ type IndCpaTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // the raw ciphertext (without IV) ++ Ct string `json:"ct,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // the initialization vector ++ Iv string `json:"iv,omitempty"` ++ ++ // the key ++ Key string `json:"key,omitempty"` ++ ++ // the plaintext ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // IndCpaTestGroup ++ type IndCpaTestGroup struct { ++ ++ // the IV size in bits ++ IvSize int `json:"ivSize,omitempty"` ++ ++ // the keySize in bits ++ KeySize int `json:"keySize,omitempty"` ++ ++ // the expected size of the tag in bits ++ TagSize int `json:"tagSize,omitempty"` ++ Tests []*IndCpaTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*IndCpaTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ var root Root ++ readTestVector(t, "aes_cbc_pkcs5_test.json", &root) ++ for _, tg := range root.TestGroups { ++ tests: ++ for _, tv := range tg.Tests { ++ block, err := aes.NewCipher(decodeHex(tv.Key)) ++ if err != nil { ++ t.Fatalf("#%d: %v", tv.TcId, err) ++ } ++ mode := cipher.NewCBCDecrypter(block, decodeHex(tv.Iv)) ++ ct := decodeHex(tv.Ct) ++ if len(ct)%aes.BlockSize != 0 { ++ panic(fmt.Sprintf("#%d: ciphertext is not a multiple of the block size", tv.TcId)) ++ } ++ mode.CryptBlocks(ct, ct) // decrypt the block in place ++ ++ // Skip the tests that are broken due to bad padding. Panic if there are any ++ // tests left that are invalid for some other reason in the future, to ++ // evaluate what to do with those tests. ++ for _, flag := range tv.Flags { ++ if flag == "BadPadding" { ++ continue tests ++ } ++ } ++ if !shouldPass(tv.Result, tv.Flags, nil) { ++ panic(fmt.Sprintf("#%d: found an invalid test that is broken for some reason other than bad padding", tv.TcId)) ++ } ++ ++ // Remove the PKCS#5 padding from the given ciphertext to validate it ++ padding := ct[len(ct)-1] ++ paddingNum := int(padding) ++ for i := paddingNum; i > 0; i-- { ++ if ct[len(ct)-i] != padding { // panic if the padding is unexpectedly bad ++ panic(fmt.Sprintf("#%d: bad padding at index=%d of %v", tv.TcId, i, ct)) ++ } ++ } ++ ct = ct[:len(ct)-paddingNum] ++ ++ if got, want := hex.EncodeToString(ct), tv.Msg; got != want { ++ t.Errorf("#%d, type: %s, comment: %q, decoded ciphertext not equal: %s, want %s", tv.TcId, tv.Result, tv.Comment, got, want) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go +new file mode 100644 +index 00000000000000..aefa3ab30df64a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go +@@ -0,0 +1,9 @@ ++// Copyright 2022 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build boringcrypto ++ ++package wycheproof ++ ++const boringcryptoEnabled = true +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go +new file mode 100644 +index 00000000000000..e5547084605d37 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go +@@ -0,0 +1,123 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "crypto/dsa" ++ "testing" ++ ++ wdsa "golang.org/x/crypto/internal/wycheproof/internal/dsa" ++) ++ ++func TestDsa(t *testing.T) { ++ // AsnSignatureTestVector ++ type AsnSignatureTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // The message to sign ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // An ASN encoded signature for msg ++ Sig string `json:"sig,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // DsaPublicKey ++ type DsaPublicKey struct { ++ ++ // the generator of the multiplicative subgroup ++ G string `json:"g,omitempty"` ++ ++ // the key size in bits ++ KeySize int `json:"keySize,omitempty"` ++ ++ // the modulus p ++ P string `json:"p,omitempty"` ++ ++ // the order of the generator g ++ Q string `json:"q,omitempty"` ++ ++ // the key type ++ Type string `json:"type,omitempty"` ++ ++ // the public key value ++ Y string `json:"y,omitempty"` ++ } ++ ++ // DsaTestGroup ++ type DsaTestGroup struct { ++ ++ // unenocded DSA public key ++ Key *DsaPublicKey `json:"key,omitempty"` ++ ++ // DER encoded public key ++ KeyDer string `json:"keyDer,omitempty"` ++ ++ // Pem encoded public key ++ KeyPem string `json:"keyPem,omitempty"` ++ ++ // the hash function used for DSA ++ Sha string `json:"sha,omitempty"` ++ Tests []*AsnSignatureTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*DsaTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // An encoded ASN.1 integer missing a leading zero is invalid, but accepted by some implementations. ++ "NoLeadingZero": false, ++ } ++ ++ var root Root ++ readTestVector(t, "dsa_test.json", &root) ++ for _, tg := range root.TestGroups { ++ pub := decodePublicKey(tg.KeyDer).(*dsa.PublicKey) ++ h := parseHash(tg.Sha).New() ++ for _, sig := range tg.Tests { ++ h.Reset() ++ h.Write(decodeHex(sig.Msg)) ++ hashed := h.Sum(nil) ++ hashed = hashed[:pub.Q.BitLen()/8] // Truncate to the byte-length of the subgroup (Q) ++ got := wdsa.VerifyASN1(pub, hashed, decodeHex(sig.Sig)) ++ if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { ++ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go +new file mode 100644 +index 00000000000000..f7abd6b2e81e66 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go +@@ -0,0 +1,142 @@ ++// Copyright 2022 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.20 ++ ++package wycheproof ++ ++import ( ++ "bytes" ++ "crypto/ecdh" ++ "fmt" ++ "testing" ++) ++ ++func TestECDHStdLib(t *testing.T) { ++ type ECDHTestVector struct { ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ // the private key ++ Private string `json:"private,omitempty"` ++ // Encoded public key ++ Public string `json:"public,omitempty"` ++ // Test result ++ Result string `json:"result,omitempty"` ++ // The shared secret key ++ Shared string `json:"shared,omitempty"` ++ // Identifier of the test case ++ TcID int `json:"tcId,omitempty"` ++ } ++ ++ type ECDHTestGroup struct { ++ Curve string `json:"curve,omitempty"` ++ Tests []*ECDHTestVector `json:"tests,omitempty"` ++ } ++ ++ type Root struct { ++ TestGroups []*ECDHTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // We don't support compressed points. ++ "CompressedPoint": false, ++ // We don't support decoding custom curves. ++ "UnnamedCurve": false, ++ // WrongOrder and UnusedParam are only found with UnnamedCurve. ++ "WrongOrder": false, ++ "UnusedParam": false, ++ ++ // X25519 specific flags ++ "Twist": true, ++ "SmallPublicKey": false, ++ "LowOrderPublic": false, ++ "ZeroSharedSecret": false, ++ "NonCanonicalPublic": true, ++ } ++ ++ // curveToCurve is a map of all elliptic curves supported ++ // by crypto/elliptic, which can subsequently be parsed and tested. ++ curveToCurve := map[string]ecdh.Curve{ ++ "secp256r1": ecdh.P256(), ++ "secp384r1": ecdh.P384(), ++ "secp521r1": ecdh.P521(), ++ "curve25519": ecdh.X25519(), ++ } ++ ++ curveToKeySize := map[string]int{ ++ "secp256r1": 32, ++ "secp384r1": 48, ++ "secp521r1": 66, ++ "curve25519": 32, ++ } ++ ++ for _, f := range []string{ ++ "ecdh_secp256r1_ecpoint_test.json", ++ "ecdh_secp384r1_ecpoint_test.json", ++ "ecdh_secp521r1_ecpoint_test.json", ++ "x25519_test.json", ++ } { ++ var root Root ++ readTestVector(t, f, &root) ++ for _, tg := range root.TestGroups { ++ if _, ok := curveToCurve[tg.Curve]; !ok { ++ continue ++ } ++ for _, tt := range tg.Tests { ++ tg, tt := tg, tt ++ t.Run(fmt.Sprintf("%s/%d", tg.Curve, tt.TcID), func(t *testing.T) { ++ t.Logf("Type: %v", tt.Result) ++ t.Logf("Flags: %q", tt.Flags) ++ t.Log(tt.Comment) ++ ++ shouldPass := shouldPass(tt.Result, tt.Flags, flagsShouldPass) ++ ++ curve := curveToCurve[tg.Curve] ++ p := decodeHex(tt.Public) ++ pub, err := curve.NewPublicKey(p) ++ if err != nil { ++ if shouldPass { ++ t.Errorf("NewPublicKey: %v", err) ++ } ++ return ++ } ++ ++ privBytes := decodeHex(tt.Private) ++ if len(privBytes) != curveToKeySize[tg.Curve] { ++ t.Skipf("non-standard key size %d", len(privBytes)) ++ } ++ ++ priv, err := curve.NewPrivateKey(privBytes) ++ if err != nil { ++ if shouldPass { ++ t.Errorf("NewPrivateKey: %v", err) ++ } ++ return ++ } ++ ++ shared := decodeHex(tt.Shared) ++ x, err := priv.ECDH(pub) ++ if err != nil { ++ if tg.Curve == "curve25519" && !shouldPass { ++ // ECDH is expected to only return an error when using X25519, ++ // in all other cases an error is unexpected. ++ return ++ } ++ t.Fatalf("ECDH: %v", err) ++ } ++ ++ if bytes.Equal(shared, x) != shouldPass { ++ if shouldPass { ++ t.Errorf("ECDH = %x, want %x", shared, x) ++ } else { ++ t.Errorf("ECDH = %x, want anything else", shared) ++ } ++ } ++ }) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go +new file mode 100644 +index 00000000000000..a3918ba62f6116 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go +@@ -0,0 +1,163 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "bytes" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/x509" ++ "encoding/asn1" ++ "errors" ++ "fmt" ++ "testing" ++ ++ "golang.org/x/crypto/cryptobyte" ++ casn1 "golang.org/x/crypto/cryptobyte/asn1" ++) ++ ++func TestECDH(t *testing.T) { ++ type ECDHTestVector struct { ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ // the private key ++ Private string `json:"private,omitempty"` ++ // Encoded public key ++ Public string `json:"public,omitempty"` ++ // Test result ++ Result string `json:"result,omitempty"` ++ // The shared secret key ++ Shared string `json:"shared,omitempty"` ++ // Identifier of the test case ++ TcID int `json:"tcId,omitempty"` ++ } ++ ++ type ECDHTestGroup struct { ++ Curve string `json:"curve,omitempty"` ++ Tests []*ECDHTestVector `json:"tests,omitempty"` ++ } ++ ++ type Root struct { ++ TestGroups []*ECDHTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // ParsePKIXPublicKey doesn't support compressed points, but we test ++ // them against UnmarshalCompressed anyway. ++ "CompressedPoint": true, ++ // We don't support decoding custom curves. ++ "UnnamedCurve": false, ++ // WrongOrder and UnusedParam are only found with UnnamedCurve. ++ "WrongOrder": false, ++ "UnusedParam": false, ++ } ++ ++ // supportedCurves is a map of all elliptic curves supported ++ // by crypto/elliptic, which can subsequently be parsed and tested. ++ supportedCurves := map[string]bool{ ++ "secp224r1": true, ++ "secp256r1": true, ++ "secp384r1": true, ++ "secp521r1": true, ++ } ++ ++ var root Root ++ readTestVector(t, "ecdh_test.json", &root) ++ for _, tg := range root.TestGroups { ++ if !supportedCurves[tg.Curve] { ++ continue ++ } ++ for _, tt := range tg.Tests { ++ tg, tt := tg, tt ++ t.Run(fmt.Sprintf("%s/%d", tg.Curve, tt.TcID), func(t *testing.T) { ++ t.Logf("Type: %v", tt.Result) ++ t.Logf("Flags: %q", tt.Flags) ++ t.Log(tt.Comment) ++ ++ shouldPass := shouldPass(tt.Result, tt.Flags, flagsShouldPass) ++ ++ p := decodeHex(tt.Public) ++ pp, err := x509.ParsePKIXPublicKey(p) ++ if err != nil { ++ pp, err = decodeCompressedPKIX(p) ++ } ++ if err != nil { ++ if shouldPass { ++ t.Errorf("unexpected parsing error: %s", err) ++ } ++ return ++ } ++ pub := pp.(*ecdsa.PublicKey) ++ ++ priv := decodeHex(tt.Private) ++ shared := decodeHex(tt.Shared) ++ ++ x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, priv) ++ xBytes := make([]byte, (pub.Curve.Params().BitSize+7)/8) ++ got := bytes.Equal(shared, x.FillBytes(xBytes)) ++ ++ if want := shouldPass; got != want { ++ t.Errorf("wanted success %v, got %v", want, got) ++ } ++ }) ++ } ++ } ++} ++ ++func decodeCompressedPKIX(der []byte) (interface{}, error) { ++ s := cryptobyte.String(der) ++ var s1, s2 cryptobyte.String ++ var algoOID, namedCurveOID asn1.ObjectIdentifier ++ var pointDER []byte ++ if !s.ReadASN1(&s1, casn1.SEQUENCE) || !s.Empty() || ++ !s1.ReadASN1(&s2, casn1.SEQUENCE) || ++ !s2.ReadASN1ObjectIdentifier(&algoOID) || ++ !s2.ReadASN1ObjectIdentifier(&namedCurveOID) || !s2.Empty() || ++ !s1.ReadASN1BitStringAsBytes(&pointDER) || !s1.Empty() { ++ return nil, errors.New("failed to parse PKIX structure") ++ } ++ ++ if !algoOID.Equal(oidPublicKeyECDSA) { ++ return nil, errors.New("wrong algorithm OID") ++ } ++ namedCurve := namedCurveFromOID(namedCurveOID) ++ if namedCurve == nil { ++ return nil, errors.New("unsupported elliptic curve") ++ } ++ x, y := elliptic.UnmarshalCompressed(namedCurve, pointDER) ++ if x == nil { ++ return nil, errors.New("failed to unmarshal elliptic curve point") ++ } ++ pub := &ecdsa.PublicKey{ ++ Curve: namedCurve, ++ X: x, ++ Y: y, ++ } ++ return pub, nil ++} ++ ++var ( ++ oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} ++ oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} ++ oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} ++ oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} ++ oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} ++) ++ ++func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { ++ switch { ++ case oid.Equal(oidNamedCurveP224): ++ return elliptic.P224() ++ case oid.Equal(oidNamedCurveP256): ++ return elliptic.P256() ++ case oid.Equal(oidNamedCurveP384): ++ return elliptic.P384() ++ case oid.Equal(oidNamedCurveP521): ++ return elliptic.P521() ++ } ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go +new file mode 100644 +index 00000000000000..80125ada75f53a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go +@@ -0,0 +1,105 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "crypto/ecdsa" ++ "math/big" ++ "testing" ++ ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" ++) ++ ++func TestECDSA(t *testing.T) { ++ type ASNSignatureTestVector struct { ++ // A brief description of the test case ++ Comment string `json:"comment"` ++ // A list of flags ++ Flags []string `json:"flags"` ++ // The message to sign ++ Msg string `json:"msg"` ++ // Test result ++ Result string `json:"result"` ++ // An ASN.1 encoded signature for msg ++ Sig string `json:"sig"` ++ // Identifier of the test case ++ TcID int `json:"tcId"` ++ } ++ ++ type ECPublicKey struct { ++ // The EC group used by this public key ++ Curve interface{} `json:"curve"` ++ } ++ ++ type ECDSATestGroup struct { ++ // Unencoded EC public key ++ Key *ECPublicKey `json:"key"` ++ // DER encoded public key ++ KeyDER string `json:"keyDer"` ++ // the hash function used for ECDSA ++ SHA string `json:"sha"` ++ Tests []*ASNSignatureTestVector `json:"tests"` ++ } ++ ++ type Root struct { ++ TestGroups []*ECDSATestGroup `json:"testGroups"` ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // An encoded ASN.1 integer missing a leading zero is invalid, but ++ // accepted by some implementations. ++ "MissingZero": false, ++ // A signature using a weaker hash than the EC params is not a security ++ // risk, as long as the hash is secure. ++ // https://www.imperialviolet.org/2014/05/25/strengthmatching.html ++ "WeakHash": true, ++ } ++ ++ // supportedCurves is a map of all elliptic curves supported ++ // by crypto/elliptic, which can subsequently be parsed and tested. ++ supportedCurves := map[string]bool{ ++ "secp224r1": true, ++ "secp256r1": true, ++ "secp384r1": true, ++ "secp521r1": true, ++ } ++ ++ var root Root ++ readTestVector(t, "ecdsa_test.json", &root) ++ for _, tg := range root.TestGroups { ++ curve := tg.Key.Curve.(string) ++ if !supportedCurves[curve] { ++ continue ++ } ++ pub := decodePublicKey(tg.KeyDER).(*ecdsa.PublicKey) ++ h := parseHash(tg.SHA).New() ++ for _, sig := range tg.Tests { ++ h.Reset() ++ h.Write(decodeHex(sig.Msg)) ++ hashed := h.Sum(nil) ++ sigBytes := decodeHex(sig.Sig) ++ got := ecdsa.VerifyASN1(pub, hashed, sigBytes) ++ if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { ++ t.Errorf("tcid: %d, type: %s, comment: %q, VerifyASN1 wanted success: %t", sig.TcID, sig.Result, sig.Comment, want) ++ } ++ ++ var r, s big.Int ++ var inner cryptobyte.String ++ input := cryptobyte.String(sigBytes) ++ if !input.ReadASN1(&inner, asn1.SEQUENCE) || ++ !input.Empty() || ++ !inner.ReadASN1Integer(&r) || ++ !inner.ReadASN1Integer(&s) || ++ !inner.Empty() { ++ continue ++ } ++ got = ecdsa.Verify(pub, hashed, &r, &s) ++ if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { ++ t.Errorf("tcid: %d, type: %s, comment: %q, Verify wanted success: %t", sig.TcID, sig.Result, sig.Comment, want) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go +new file mode 100644 +index 00000000000000..0a7fbb7e0e5de2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go +@@ -0,0 +1,101 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.13 ++// +build go1.13 ++ ++package wycheproof ++ ++import ( ++ "testing" ++ ++ "golang.org/x/crypto/ed25519" ++) ++ ++func TestEddsa(t *testing.T) { ++ // Jwk the private key in webcrypto format ++ type Jwk struct { ++ } ++ ++ // Key unencoded key pair ++ type Key struct { ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // SignatureTestVector ++ type SignatureTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // The message to sign ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // A signature for msg ++ Sig string `json:"sig,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // EddsaTestGroup ++ type EddsaTestGroup struct { ++ ++ // the private key in webcrypto format ++ Jwk *Jwk `json:"jwk,omitempty"` ++ ++ // unencoded key pair ++ Key *Key `json:"key,omitempty"` ++ ++ // Asn encoded public key ++ KeyDer string `json:"keyDer,omitempty"` ++ ++ // Pem encoded public key ++ KeyPem string `json:"keyPem,omitempty"` ++ Tests []*SignatureTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*EddsaTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ var root Root ++ readTestVector(t, "eddsa_test.json", &root) ++ for _, tg := range root.TestGroups { ++ pub := decodePublicKey(tg.KeyDer).(ed25519.PublicKey) ++ for _, sig := range tg.Tests { ++ got := ed25519.Verify(pub, decodeHex(sig.Msg), decodeHex(sig.Sig)) ++ if want := shouldPass(sig.Result, sig.Flags, nil); got != want { ++ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go +new file mode 100644 +index 00000000000000..6b72e2c870eb5b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go +@@ -0,0 +1,111 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "bytes" ++ "io" ++ "testing" ++ ++ "golang.org/x/crypto/hkdf" ++) ++ ++func TestHkdf(t *testing.T) { ++ ++ // HkdfTestVector ++ type HkdfTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // the key (input key material) ++ Ikm string `json:"ikm,omitempty"` ++ ++ // additional information used in the key derivation ++ Info string `json:"info,omitempty"` ++ ++ // the generated bytes (output key material) ++ Okm string `json:"okm,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // the salt for the key derivation ++ Salt string `json:"salt,omitempty"` ++ ++ // the size of the output in bytes ++ Size int `json:"size,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // HkdfTestGroup ++ type HkdfTestGroup struct { ++ ++ // the size of the ikm in bits ++ KeySize int `json:"keySize,omitempty"` ++ Tests []*HkdfTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*HkdfTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ fileHashAlgorithms := map[string]string{ ++ "hkdf_sha1_test.json": "SHA-1", ++ "hkdf_sha256_test.json": "SHA-256", ++ "hkdf_sha384_test.json": "SHA-384", ++ "hkdf_sha512_test.json": "SHA-512", ++ } ++ ++ for f := range fileHashAlgorithms { ++ var root Root ++ readTestVector(t, f, &root) ++ for _, tg := range root.TestGroups { ++ for _, tv := range tg.Tests { ++ h := parseHash(fileHashAlgorithms[f]).New ++ hkdf := hkdf.New(h, decodeHex(tv.Ikm), decodeHex(tv.Salt), decodeHex(tv.Info)) ++ key := make([]byte, tv.Size) ++ wantPass := shouldPass(tv.Result, tv.Flags, nil) ++ _, err := io.ReadFull(hkdf, key) ++ if (err == nil) != wantPass { ++ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t, got: %v", tv.TcId, tv.Result, tv.Comment, wantPass, err) ++ } ++ if err != nil { ++ continue // don't validate output text if reading failed ++ } ++ if got, want := key, decodeHex(tv.Okm); !bytes.Equal(got, want) { ++ t.Errorf("tcid: %d, type: %s, comment: %q, output bytes don't match", tv.TcId, tv.Result, tv.Comment) ++ } ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go +new file mode 100644 +index 00000000000000..bcc56f28fc8dd8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go +@@ -0,0 +1,105 @@ ++// Copyright 2020 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "crypto/hmac" ++ "testing" ++) ++ ++func TestHMAC(t *testing.T) { ++ // MacTestVector ++ type MacTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // the key ++ Key string `json:"key,omitempty"` ++ ++ // the plaintext ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // the authentication tag ++ Tag string `json:"tag,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // MacTestGroup ++ type MacTestGroup struct { ++ ++ // the keySize in bits ++ KeySize int `json:"keySize,omitempty"` ++ ++ // the expected size of the tag in bits ++ TagSize int `json:"tagSize,omitempty"` ++ Tests []*MacTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*MacTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ fileHashAlgs := map[string]string{ ++ "hmac_sha1_test.json": "SHA-1", ++ "hmac_sha224_test.json": "SHA-224", ++ "hmac_sha256_test.json": "SHA-256", ++ "hmac_sha384_test.json": "SHA-384", ++ "hmac_sha512_test.json": "SHA-512", ++ } ++ ++ for f := range fileHashAlgs { ++ var root Root ++ readTestVector(t, f, &root) ++ for _, tg := range root.TestGroups { ++ h := parseHash(fileHashAlgs[f]) ++ // Skip test vectors where the tag length does not equal the ++ // hash length, since crypto/hmac does not support generating ++ // these truncated tags. ++ if tg.TagSize/8 != h.Size() { ++ continue ++ } ++ for _, tv := range tg.Tests { ++ hm := hmac.New(h.New, decodeHex(tv.Key)) ++ hm.Write(decodeHex(tv.Msg)) ++ tag := hm.Sum(nil) ++ got := hmac.Equal(decodeHex(tv.Tag), tag) ++ if want := shouldPass(tv.Result, tv.Flags, nil); want != got { ++ t.Errorf("%s, tcid: %d, type: %s, comment: %q, unexpected result", f, tv.TcId, tv.Result, tv.Comment) ++ } ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go +new file mode 100644 +index 00000000000000..3101dfc1c23e51 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go +@@ -0,0 +1,33 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package dsa provides an internal version of dsa.Verify ++// that is used for the Wycheproof tests. ++package dsa ++ ++import ( ++ "crypto/dsa" ++ "math/big" ++ ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" ++) ++ ++// VerifyASN1 verifies the ASN1 encoded signature, sig, of hash using the ++// public key, pub. Its return value records whether the signature is valid. ++func VerifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool { ++ var ( ++ r, s = &big.Int{}, &big.Int{} ++ inner cryptobyte.String ++ ) ++ input := cryptobyte.String(sig) ++ if !input.ReadASN1(&inner, asn1.SEQUENCE) || ++ !input.Empty() || ++ !inner.ReadASN1Integer(r) || ++ !inner.ReadASN1Integer(s) || ++ !inner.Empty() { ++ return false ++ } ++ return dsa.Verify(pub, hash, r, s) ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go +new file mode 100644 +index 00000000000000..746af130f17052 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go +@@ -0,0 +1,9 @@ ++// Copyright 2022 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !boringcrypto ++ ++package wycheproof ++ ++const boringcryptoEnabled = false +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go +new file mode 100644 +index 00000000000000..19cc4fdcb72884 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go +@@ -0,0 +1,149 @@ ++// Copyright 2020 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "bytes" ++ "crypto/rsa" ++ "crypto/x509" ++ "fmt" ++ "testing" ++) ++ ++func TestRSAOAEPDecrypt(t *testing.T) { ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // RsaesOaepTestVector ++ type RsaesOaepTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // An encryption of msg ++ Ct string `json:"ct,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // The label used for the encryption ++ Label string `json:"label,omitempty"` ++ ++ // The encrypted message ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // RsaesOaepTestGroup ++ type RsaesOaepTestGroup struct { ++ ++ // The private exponent ++ D string `json:"d,omitempty"` ++ ++ // The public exponent ++ E string `json:"e,omitempty"` ++ ++ // the message generating function (e.g. MGF1) ++ Mgf string `json:"mgf,omitempty"` ++ ++ // The hash function used for the message generating function. ++ MgfSha string `json:"mgfSha,omitempty"` ++ ++ // The modulus of the key ++ N string `json:"n,omitempty"` ++ ++ // Pem encoded private key ++ PrivateKeyPem string `json:"privateKeyPem,omitempty"` ++ ++ // Pkcs 8 encoded private key. ++ PrivateKeyPkcs8 string `json:"privateKeyPkcs8,omitempty"` ++ ++ // The hash function for hashing the label. ++ Sha string `json:"sha,omitempty"` ++ Tests []*RsaesOaepTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*RsaesOaepTestGroup `json:"testGroups,omitempty"` ++ } ++ ++ // rsa.DecryptOAEP doesn't support using a different hash for the ++ // MGF and the label, so skip all of the test vectors that use ++ // these unbalanced constructions. rsa_oaep_misc_test.json contains ++ // both balanced and unbalanced constructions so in that case ++ // we just filter out any test groups where MgfSha != Sha ++ files := []string{ ++ "rsa_oaep_2048_sha1_mgf1sha1_test.json", ++ "rsa_oaep_2048_sha224_mgf1sha224_test.json", ++ "rsa_oaep_2048_sha256_mgf1sha256_test.json", ++ "rsa_oaep_2048_sha384_mgf1sha384_test.json", ++ "rsa_oaep_2048_sha512_mgf1sha512_test.json", ++ "rsa_oaep_3072_sha256_mgf1sha256_test.json", ++ "rsa_oaep_3072_sha512_mgf1sha512_test.json", ++ "rsa_oaep_4096_sha256_mgf1sha256_test.json", ++ "rsa_oaep_4096_sha512_mgf1sha512_test.json", ++ "rsa_oaep_misc_test.json", ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // rsa.DecryptOAEP happily supports small key sizes ++ "SmallModulus": true, ++ } ++ ++ for _, f := range files { ++ var root Root ++ readTestVector(t, f, &root) ++ for _, tg := range root.TestGroups { ++ if tg.MgfSha != tg.Sha { ++ continue ++ } ++ priv, err := x509.ParsePKCS8PrivateKey(decodeHex(tg.PrivateKeyPkcs8)) ++ if err != nil { ++ t.Fatalf("%s failed to parse PKCS #8 private key: %s", f, err) ++ } ++ hash := parseHash(tg.Sha) ++ for _, tv := range tg.Tests { ++ t.Run(fmt.Sprintf("%s #%d", f, tv.TcId), func(t *testing.T) { ++ wantPass := shouldPass(tv.Result, tv.Flags, flagsShouldPass) ++ plaintext, err := rsa.DecryptOAEP(hash.New(), nil, priv.(*rsa.PrivateKey), decodeHex(tv.Ct), decodeHex(tv.Label)) ++ if wantPass { ++ if err != nil { ++ t.Fatalf("comment: %s, expected success: %s", tv.Comment, err) ++ } ++ if !bytes.Equal(plaintext, decodeHex(tv.Msg)) { ++ t.Errorf("comment: %s, unexpected plaintext: got %x, want %s", tv.Comment, plaintext, tv.Msg) ++ } ++ } else if err == nil { ++ t.Errorf("comment: %s, expected failure", tv.Comment) ++ } ++ }) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go +new file mode 100644 +index 00000000000000..2ad9a4313b6497 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go +@@ -0,0 +1,169 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "crypto/rsa" ++ "testing" ++) ++ ++func TestRsaPss(t *testing.T) { ++ // KeyJwk Public key in JWK format ++ type KeyJwk struct { ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // SignatureTestVector ++ type SignatureTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // The message to sign ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // A signature for msg ++ Sig string `json:"sig,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // RsassaPkcs1TestGroup ++ type RsassaPkcs1TestGroup struct { ++ ++ // The private exponent ++ D string `json:"d,omitempty"` ++ ++ // The public exponent ++ E string `json:"e,omitempty"` ++ ++ // ASN encoding of the sequence [n, e] ++ KeyAsn string `json:"keyAsn,omitempty"` ++ ++ // ASN encoding of the public key ++ KeyDer string `json:"keyDer,omitempty"` ++ ++ // Public key in JWK format ++ KeyJwk *KeyJwk `json:"keyJwk,omitempty"` ++ ++ // Pem encoded public key ++ KeyPem string `json:"keyPem,omitempty"` ++ ++ // the size of the modulus in bits ++ KeySize int `json:"keySize,omitempty"` ++ ++ // The modulus of the key ++ N string `json:"n,omitempty"` ++ ++ // The salt length ++ SLen int `json:"sLen,omitempty"` ++ ++ // the hash function used for the message ++ Sha string `json:"sha,omitempty"` ++ Tests []*SignatureTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"` ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // A signature using a weaker hash than the EC params is not a security risk, as long as the hash is secure. ++ // https://www.imperialviolet.org/2014/05/25/strengthmatching.html ++ "WeakHash": true, ++ } ++ ++ // filesOverrideToPassZeroSLen is a map of all test files ++ // and which TcIds that should be overridden to pass if the ++ // rsa.PSSOptions.SaltLength is zero. ++ // These tests expect a failure with a PSSOptions.SaltLength: 0 ++ // and a signature that uses a different salt length. However, ++ // a salt length of 0 is defined as rsa.PSSSaltLengthAuto which ++ // works deterministically to auto-detect the length when ++ // verifying, so these tests actually pass as they should. ++ filesOverrideToPassZeroSLen := map[string][]int{ ++ "rsa_pss_2048_sha1_mgf1_20_test.json": []int{46, 47}, ++ "rsa_pss_2048_sha256_mgf1_0_test.json": []int{67, 68}, ++ "rsa_pss_2048_sha256_mgf1_32_test.json": []int{67, 68}, ++ "rsa_pss_3072_sha256_mgf1_32_test.json": []int{67, 68}, ++ "rsa_pss_4096_sha256_mgf1_32_test.json": []int{67, 68}, ++ "rsa_pss_4096_sha512_mgf1_32_test.json": []int{136, 137}, ++ // "rsa_pss_misc_test.json": nil, // TODO: This ones seems to be broken right now, but can enable later on. ++ } ++ ++ if !boringcryptoEnabled { ++ // boringcrypto doesn't support the truncated SHA-512 hashes, so only ++ // test them if boringcrypto isn't enabled. ++ filesOverrideToPassZeroSLen["rsa_pss_2048_sha512_256_mgf1_28_test.json"] = []int{13, 14, 15} ++ filesOverrideToPassZeroSLen["rsa_pss_2048_sha512_256_mgf1_32_test.json"] = []int{13, 14} ++ } ++ ++ for f := range filesOverrideToPassZeroSLen { ++ var root Root ++ readTestVector(t, f, &root) ++ for _, tg := range root.TestGroups { ++ pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey) ++ ch := parseHash(tg.Sha) ++ h := ch.New() ++ opts := &rsa.PSSOptions{ ++ Hash: ch, ++ SaltLength: rsa.PSSSaltLengthAuto, ++ } ++ // Run all the tests twice: the first time with the salt length ++ // as PSSSaltLengthAuto, and the second time with the salt length ++ // explictily set to tg.SLen. ++ for i := 0; i < 2; i++ { ++ for _, sig := range tg.Tests { ++ h.Reset() ++ h.Write(decodeHex(sig.Msg)) ++ hashed := h.Sum(nil) ++ err := rsa.VerifyPSS(pub, ch, hashed, decodeHex(sig.Sig), opts) ++ want := shouldPass(sig.Result, sig.Flags, flagsShouldPass) ++ if opts.SaltLength == 0 { ++ for _, id := range filesOverrideToPassZeroSLen[f] { ++ if sig.TcId == id { ++ want = true ++ break ++ } ++ } ++ } ++ if (err == nil) != want { ++ t.Errorf("file: %v, tcid: %d, type: %s, opts.SaltLength: %v, comment: %q, wanted success: %t", f, sig.TcId, sig.Result, opts.SaltLength, sig.Comment, want) ++ } ++ } ++ // Update opts.SaltLength for the second run of the tests. ++ opts.SaltLength = tg.SLen ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go +new file mode 100644 +index 00000000000000..3c31c225527ea7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go +@@ -0,0 +1,123 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package wycheproof ++ ++import ( ++ "crypto/rsa" ++ "testing" ++) ++ ++func TestRsa(t *testing.T) { ++ // KeyJwk Public key in JWK format ++ type KeyJwk struct { ++ } ++ ++ // Notes a description of the labels used in the test vectors ++ type Notes struct { ++ } ++ ++ // SignatureTestVector ++ type SignatureTestVector struct { ++ ++ // A brief description of the test case ++ Comment string `json:"comment,omitempty"` ++ ++ // A list of flags ++ Flags []string `json:"flags,omitempty"` ++ ++ // The message to sign ++ Msg string `json:"msg,omitempty"` ++ ++ // Test result ++ Result string `json:"result,omitempty"` ++ ++ // A signature for msg ++ Sig string `json:"sig,omitempty"` ++ ++ // Identifier of the test case ++ TcId int `json:"tcId,omitempty"` ++ } ++ ++ // RsassaPkcs1TestGroup ++ type RsassaPkcs1TestGroup struct { ++ ++ // The private exponent ++ D string `json:"d,omitempty"` ++ ++ // The public exponent ++ E string `json:"e,omitempty"` ++ ++ // ASN encoding of the sequence [n, e] ++ KeyAsn string `json:"keyAsn,omitempty"` ++ ++ // ASN encoding of the public key ++ KeyDer string `json:"keyDer,omitempty"` ++ ++ // Public key in JWK format ++ KeyJwk *KeyJwk `json:"keyJwk,omitempty"` ++ ++ // Pem encoded public key ++ KeyPem string `json:"keyPem,omitempty"` ++ ++ // the size of the modulus in bits ++ KeySize int `json:"keySize,omitempty"` ++ ++ // The modulus of the key ++ N string `json:"n,omitempty"` ++ ++ // the hash function used for the message ++ Sha string `json:"sha,omitempty"` ++ Tests []*SignatureTestVector `json:"tests,omitempty"` ++ Type interface{} `json:"type,omitempty"` ++ } ++ ++ // Root ++ type Root struct { ++ ++ // the primitive tested in the test file ++ Algorithm string `json:"algorithm,omitempty"` ++ ++ // the version of the test vectors. ++ GeneratorVersion string `json:"generatorVersion,omitempty"` ++ ++ // additional documentation ++ Header []string `json:"header,omitempty"` ++ ++ // a description of the labels used in the test vectors ++ Notes *Notes `json:"notes,omitempty"` ++ ++ // the number of test vectors in this test ++ NumberOfTests int `json:"numberOfTests,omitempty"` ++ Schema interface{} `json:"schema,omitempty"` ++ TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"` ++ } ++ ++ flagsShouldPass := map[string]bool{ ++ // Omitting the parameter field in an ASN encoded integer is a legacy behavior. ++ "MissingNull": false, ++ // Keys with a modulus less than 2048 bits are supported by crypto/rsa. ++ "SmallModulus": true, ++ // Small public keys are supported by crypto/rsa. ++ "SmallPublicKey": true, ++ } ++ ++ var root Root ++ readTestVector(t, "rsa_signature_test.json", &root) ++ for _, tg := range root.TestGroups { ++ pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey) ++ ch := parseHash(tg.Sha) ++ h := ch.New() ++ for _, sig := range tg.Tests { ++ h.Reset() ++ h.Write(decodeHex(sig.Msg)) ++ hashed := h.Sum(nil) ++ err := rsa.VerifyPKCS1v15(pub, ch, hashed, decodeHex(sig.Sig)) ++ want := shouldPass(sig.Result, sig.Flags, flagsShouldPass) ++ if (err == nil) != want { ++ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go +new file mode 100644 +index 00000000000000..bbaae3b338ba9b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go +@@ -0,0 +1,141 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package wycheproof runs a set of the Wycheproof tests ++// provided by https://github.com/google/wycheproof. ++package wycheproof ++ ++import ( ++ "crypto" ++ "crypto/x509" ++ "encoding/hex" ++ "encoding/json" ++ "flag" ++ "fmt" ++ "log" ++ "os" ++ "os/exec" ++ "path/filepath" ++ "testing" ++ ++ _ "crypto/sha1" ++ _ "crypto/sha256" ++ _ "crypto/sha512" ++) ++ ++const wycheproofModVer = "v0.0.0-20191219022705-2196000605e4" ++ ++var wycheproofTestVectorsDir string ++ ++func TestMain(m *testing.M) { ++ flag.Parse() ++ if flag.Lookup("test.short").Value.(flag.Getter).Get().(bool) { ++ log.Println("skipping test that downloads testdata via 'go mod download' in short mode") ++ os.Exit(0) ++ } ++ if _, err := exec.LookPath("go"); err != nil { ++ log.Printf("skipping test because 'go' command is unavailable: %v", err) ++ os.Exit(0) ++ } ++ if os.Getenv("GO_BUILDER_FLAKY_NET") != "" { ++ log.Printf("skipping test because GO_BUILDER_FLAKY_NET is set") ++ os.Exit(0) ++ } ++ ++ // Download the JSON test files from github.com/google/wycheproof ++ // using `go mod download -json` so the cached source of the testdata ++ // can be used in the following tests. ++ path := "github.com/google/wycheproof@" + wycheproofModVer ++ cmd := exec.Command("go", "mod", "download", "-json", path) ++ output, err := cmd.Output() ++ if err != nil { ++ log.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output) ++ } ++ var dm struct { ++ Dir string // absolute path to cached source root directory ++ } ++ if err := json.Unmarshal(output, &dm); err != nil { ++ log.Fatal(err) ++ } ++ // Now that the module has been downloaded, use the absolute path of the ++ // cached source as the root directory for all tests going forward. ++ wycheproofTestVectorsDir = filepath.Join(dm.Dir, "testvectors") ++ os.Exit(m.Run()) ++} ++ ++func readTestVector(t *testing.T, f string, dest interface{}) { ++ b, err := os.ReadFile(filepath.Join(wycheproofTestVectorsDir, f)) ++ if err != nil { ++ t.Fatalf("failed to read json file: %v", err) ++ } ++ if err := json.Unmarshal(b, &dest); err != nil { ++ t.Fatalf("failed to unmarshal json file: %v", err) ++ } ++} ++ ++func decodeHex(s string) []byte { ++ b, err := hex.DecodeString(s) ++ if err != nil { ++ panic(err) ++ } ++ return b ++} ++ ++func decodePublicKey(der string) interface{} { ++ d := decodeHex(der) ++ pub, err := x509.ParsePKIXPublicKey(d) ++ if err != nil { ++ panic(fmt.Sprintf("failed to parse DER encoded public key: %v", err)) ++ } ++ return pub ++} ++ ++func parseHash(h string) crypto.Hash { ++ switch h { ++ case "SHA-1": ++ return crypto.SHA1 ++ case "SHA-256": ++ return crypto.SHA256 ++ case "SHA-224": ++ return crypto.SHA224 ++ case "SHA-384": ++ return crypto.SHA384 ++ case "SHA-512": ++ return crypto.SHA512 ++ case "SHA-512/224": ++ return crypto.SHA512_224 ++ case "SHA-512/256": ++ return crypto.SHA512_256 ++ default: ++ panic(fmt.Sprintf("could not identify SHA hash algorithm: %q", h)) ++ } ++} ++ ++// shouldPass returns whether or not the test should pass. ++// flagsShouldPass is a map associated with whether or not ++// a flag for an "acceptable" result should pass. ++// Every possible flag value that's associated with an ++// "acceptable" result should be explicitly specified, ++// otherwise the test will panic. ++func shouldPass(result string, flags []string, flagsShouldPass map[string]bool) bool { ++ switch result { ++ case "valid": ++ return true ++ case "invalid": ++ return false ++ case "acceptable": ++ for _, flag := range flags { ++ pass, ok := flagsShouldPass[flag] ++ if !ok { ++ panic(fmt.Sprintf("unspecified flag: %q", flag)) ++ } ++ if !pass { ++ return false ++ } ++ } ++ return true // There are no flags, or all are meant to pass. ++ default: ++ panic(fmt.Sprintf("unexpected result: %v", result)) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/md4/example_test.go b/ms_mod/golang.org/x/crypto/md4/example_test.go +new file mode 100644 +index 00000000000000..db3f59b19bce54 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/md4/example_test.go +@@ -0,0 +1,20 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package md4_test ++ ++import ( ++ "fmt" ++ "io" ++ ++ "golang.org/x/crypto/md4" ++) ++ ++func ExampleNew() { ++ h := md4.New() ++ data := "These pretzels are making me thirsty." ++ io.WriteString(h, data) ++ fmt.Printf("%x", h.Sum(nil)) ++ // Output: 48c4e365090b30a32f084c4888deceaa ++} +diff --git a/ms_mod/golang.org/x/crypto/md4/md4.go b/ms_mod/golang.org/x/crypto/md4/md4.go +new file mode 100644 +index 00000000000000..59d3480693050f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/md4/md4.go +@@ -0,0 +1,122 @@ ++// Copyright 2009 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package md4 implements the MD4 hash algorithm as defined in RFC 1320. ++// ++// Deprecated: MD4 is cryptographically broken and should should only be used ++// where compatibility with legacy systems, not security, is the goal. Instead, ++// use a secure hash like SHA-256 (from crypto/sha256). ++package md4 // import "golang.org/x/crypto/md4" ++ ++import ( ++ "crypto" ++ "hash" ++) ++ ++func init() { ++ crypto.RegisterHash(crypto.MD4, New) ++} ++ ++// The size of an MD4 checksum in bytes. ++const Size = 16 ++ ++// The blocksize of MD4 in bytes. ++const BlockSize = 64 ++ ++const ( ++ _Chunk = 64 ++ _Init0 = 0x67452301 ++ _Init1 = 0xEFCDAB89 ++ _Init2 = 0x98BADCFE ++ _Init3 = 0x10325476 ++) ++ ++// digest represents the partial evaluation of a checksum. ++type digest struct { ++ s [4]uint32 ++ x [_Chunk]byte ++ nx int ++ len uint64 ++} ++ ++func (d *digest) Reset() { ++ d.s[0] = _Init0 ++ d.s[1] = _Init1 ++ d.s[2] = _Init2 ++ d.s[3] = _Init3 ++ d.nx = 0 ++ d.len = 0 ++} ++ ++// New returns a new hash.Hash computing the MD4 checksum. ++func New() hash.Hash { ++ d := new(digest) ++ d.Reset() ++ return d ++} ++ ++func (d *digest) Size() int { return Size } ++ ++func (d *digest) BlockSize() int { return BlockSize } ++ ++func (d *digest) Write(p []byte) (nn int, err error) { ++ nn = len(p) ++ d.len += uint64(nn) ++ if d.nx > 0 { ++ n := len(p) ++ if n > _Chunk-d.nx { ++ n = _Chunk - d.nx ++ } ++ for i := 0; i < n; i++ { ++ d.x[d.nx+i] = p[i] ++ } ++ d.nx += n ++ if d.nx == _Chunk { ++ _Block(d, d.x[0:]) ++ d.nx = 0 ++ } ++ p = p[n:] ++ } ++ n := _Block(d, p) ++ p = p[n:] ++ if len(p) > 0 { ++ d.nx = copy(d.x[:], p) ++ } ++ return ++} ++ ++func (d0 *digest) Sum(in []byte) []byte { ++ // Make a copy of d0, so that caller can keep writing and summing. ++ d := new(digest) ++ *d = *d0 ++ ++ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. ++ len := d.len ++ var tmp [64]byte ++ tmp[0] = 0x80 ++ if len%64 < 56 { ++ d.Write(tmp[0 : 56-len%64]) ++ } else { ++ d.Write(tmp[0 : 64+56-len%64]) ++ } ++ ++ // Length in bits. ++ len <<= 3 ++ for i := uint(0); i < 8; i++ { ++ tmp[i] = byte(len >> (8 * i)) ++ } ++ d.Write(tmp[0:8]) ++ ++ if d.nx != 0 { ++ panic("d.nx != 0") ++ } ++ ++ for _, s := range d.s { ++ in = append(in, byte(s>>0)) ++ in = append(in, byte(s>>8)) ++ in = append(in, byte(s>>16)) ++ in = append(in, byte(s>>24)) ++ } ++ return in ++} +diff --git a/ms_mod/golang.org/x/crypto/md4/md4_test.go b/ms_mod/golang.org/x/crypto/md4/md4_test.go +new file mode 100644 +index 00000000000000..b56edd7875d8b6 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/md4/md4_test.go +@@ -0,0 +1,71 @@ ++// Copyright 2009 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package md4 ++ ++import ( ++ "fmt" ++ "io" ++ "testing" ++) ++ ++type md4Test struct { ++ out string ++ in string ++} ++ ++var golden = []md4Test{ ++ {"31d6cfe0d16ae931b73c59d7e0c089c0", ""}, ++ {"bde52cb31de33e46245e05fbdbd6fb24", "a"}, ++ {"ec388dd78999dfc7cf4632465693b6bf", "ab"}, ++ {"a448017aaf21d8525fc10ae87aa6729d", "abc"}, ++ {"41decd8f579255c5200f86a4bb3ba740", "abcd"}, ++ {"9803f4a34e8eb14f96adba49064a0c41", "abcde"}, ++ {"804e7f1c2586e50b49ac65db5b645131", "abcdef"}, ++ {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"}, ++ {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"}, ++ {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"}, ++ {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"}, ++ {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."}, ++ {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."}, ++ {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."}, ++ {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, ++ {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"}, ++ {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."}, ++ {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."}, ++ {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."}, ++ {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, ++ {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, ++ {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"}, ++ {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"}, ++ {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, ++ {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."}, ++ {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."}, ++ {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."}, ++ {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"}, ++ {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, ++ {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, ++ {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"}, ++} ++ ++func TestGolden(t *testing.T) { ++ for i := 0; i < len(golden); i++ { ++ g := golden[i] ++ c := New() ++ for j := 0; j < 3; j++ { ++ if j < 2 { ++ io.WriteString(c, g.in) ++ } else { ++ io.WriteString(c, g.in[0:len(g.in)/2]) ++ c.Sum(nil) ++ io.WriteString(c, g.in[len(g.in)/2:]) ++ } ++ s := fmt.Sprintf("%x", c.Sum(nil)) ++ if s != g.out { ++ t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) ++ } ++ c.Reset() ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/md4/md4block.go b/ms_mod/golang.org/x/crypto/md4/md4block.go +new file mode 100644 +index 00000000000000..5ea1ba966ea4d5 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/md4/md4block.go +@@ -0,0 +1,91 @@ ++// Copyright 2009 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// MD4 block step. ++// In its own file so that a faster assembly or C version ++// can be substituted easily. ++ ++package md4 ++ ++import "math/bits" ++ ++var shift1 = []int{3, 7, 11, 19} ++var shift2 = []int{3, 5, 9, 13} ++var shift3 = []int{3, 9, 11, 15} ++ ++var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15} ++var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} ++ ++func _Block(dig *digest, p []byte) int { ++ a := dig.s[0] ++ b := dig.s[1] ++ c := dig.s[2] ++ d := dig.s[3] ++ n := 0 ++ var X [16]uint32 ++ for len(p) >= _Chunk { ++ aa, bb, cc, dd := a, b, c, d ++ ++ j := 0 ++ for i := 0; i < 16; i++ { ++ X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 ++ j += 4 ++ } ++ ++ // If this needs to be made faster in the future, ++ // the usual trick is to unroll each of these ++ // loops by a factor of 4; that lets you replace ++ // the shift[] lookups with constants and, ++ // with suitable variable renaming in each ++ // unrolled body, delete the a, b, c, d = d, a, b, c ++ // (or you can let the optimizer do the renaming). ++ // ++ // The index variables are uint so that % by a power ++ // of two can be optimized easily by a compiler. ++ ++ // Round 1. ++ for i := uint(0); i < 16; i++ { ++ x := i ++ s := shift1[i%4] ++ f := ((c ^ d) & b) ^ d ++ a += f + X[x] ++ a = bits.RotateLeft32(a, s) ++ a, b, c, d = d, a, b, c ++ } ++ ++ // Round 2. ++ for i := uint(0); i < 16; i++ { ++ x := xIndex2[i] ++ s := shift2[i%4] ++ g := (b & c) | (b & d) | (c & d) ++ a += g + X[x] + 0x5a827999 ++ a = bits.RotateLeft32(a, s) ++ a, b, c, d = d, a, b, c ++ } ++ ++ // Round 3. ++ for i := uint(0); i < 16; i++ { ++ x := xIndex3[i] ++ s := shift3[i%4] ++ h := b ^ c ^ d ++ a += h + X[x] + 0x6ed9eba1 ++ a = bits.RotateLeft32(a, s) ++ a, b, c, d = d, a, b, c ++ } ++ ++ a += aa ++ b += bb ++ c += cc ++ d += dd ++ ++ p = p[_Chunk:] ++ n += _Chunk ++ } ++ ++ dig.s[0] = a ++ dig.s[1] = b ++ dig.s[2] = c ++ dig.s[3] = d ++ return n ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/auth/auth.go b/ms_mod/golang.org/x/crypto/nacl/auth/auth.go +new file mode 100644 +index 00000000000000..1d588d5c1cd21d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/auth/auth.go +@@ -0,0 +1,58 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++Package auth authenticates a message using a secret key. ++ ++The Sum function, viewed as a function of the message for a uniform random ++key, is designed to meet the standard notion of unforgeability. This means ++that an attacker cannot find authenticators for any messages not authenticated ++by the sender, even if the attacker has adaptively influenced the messages ++authenticated by the sender. For a formal definition see, e.g., Section 2.4 ++of Bellare, Kilian, and Rogaway, "The security of the cipher block chaining ++message authentication code," Journal of Computer and System Sciences 61 (2000), ++362–399; http://www-cse.ucsd.edu/~mihir/papers/cbc.html. ++ ++auth does not make any promises regarding "strong" unforgeability; perhaps ++one valid authenticator can be converted into another valid authenticator for ++the same message. NaCl also does not make any promises regarding "truncated ++unforgeability." ++ ++This package is interoperable with NaCl: https://nacl.cr.yp.to/auth.html. ++*/ ++package auth ++ ++import ( ++ "crypto/hmac" ++ "crypto/sha512" ++) ++ ++const ( ++ // Size is the size, in bytes, of an authenticated digest. ++ Size = 32 ++ // KeySize is the size, in bytes, of an authentication key. ++ KeySize = 32 ++) ++ ++// Sum generates an authenticator for m using a secret key and returns the ++// 32-byte digest. ++func Sum(m []byte, key *[KeySize]byte) *[Size]byte { ++ mac := hmac.New(sha512.New, key[:]) ++ mac.Write(m) ++ out := new([Size]byte) ++ copy(out[:], mac.Sum(nil)[:Size]) ++ return out ++} ++ ++// Verify checks that digest is a valid authenticator of message m under the ++// given secret key. Verify does not leak timing information. ++func Verify(digest []byte, m []byte, key *[KeySize]byte) bool { ++ if len(digest) != Size { ++ return false ++ } ++ mac := hmac.New(sha512.New, key[:]) ++ mac.Write(m) ++ expectedMAC := mac.Sum(nil) // first 256 bits of 512-bit sum ++ return hmac.Equal(digest, expectedMAC[:Size]) ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go b/ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go +new file mode 100644 +index 00000000000000..92074b50b60e64 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go +@@ -0,0 +1,172 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package auth ++ ++import ( ++ "bytes" ++ rand "crypto/rand" ++ mrand "math/rand" ++ "testing" ++) ++ ++// Test cases are from RFC 4231, and match those present in the tests directory ++// of the download here: https://nacl.cr.yp.to/install.html ++var testCases = []struct { ++ key [32]byte ++ msg []byte ++ out [32]byte ++}{ ++ { ++ key: [32]byte{ ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, ++ }, ++ msg: []byte("Hi There"), ++ out: [32]byte{ ++ 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, ++ 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, ++ 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, ++ 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, ++ }, ++ }, ++ { ++ key: [32]byte{'J', 'e', 'f', 'e'}, ++ msg: []byte("what do ya want for nothing?"), ++ out: [32]byte{ ++ 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, ++ 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, ++ 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, ++ 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, ++ }, ++ }, ++ { ++ key: [32]byte{ ++ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, ++ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, ++ 0xaa, 0xaa, 0xaa, 0xaa, ++ }, ++ msg: []byte{ // 50 bytes of 0xdd ++ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, ++ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, ++ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, ++ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, ++ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, ++ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, ++ 0xdd, 0xdd, ++ }, ++ out: [32]byte{ ++ 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, ++ 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, ++ 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, ++ 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, ++ }, ++ }, ++ { ++ key: [32]byte{ ++ 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, ++ }, ++ msg: []byte{ ++ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, ++ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, ++ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, ++ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, ++ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, ++ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, ++ 0xcd, 0xcd, ++ }, ++ out: [32]byte{ ++ 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, ++ 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, ++ 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, ++ 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, ++ }, ++ }, ++} ++ ++func TestSum(t *testing.T) { ++ for i, test := range testCases { ++ tag := Sum(test.msg, &test.key) ++ if !bytes.Equal(tag[:], test.out[:]) { ++ t.Errorf("#%d: Sum: got\n%x\nwant\n%x", i, tag, test.out) ++ } ++ } ++} ++ ++func TestVerify(t *testing.T) { ++ wrongMsg := []byte("unknown msg") ++ ++ for i, test := range testCases { ++ if !Verify(test.out[:], test.msg, &test.key) { ++ t.Errorf("#%d: Verify(%x, %q, %x) failed", i, test.out, test.msg, test.key) ++ } ++ if Verify(test.out[:], wrongMsg, &test.key) { ++ t.Errorf("#%d: Verify(%x, %q, %x) unexpectedly passed", i, test.out, wrongMsg, test.key) ++ } ++ } ++} ++ ++func TestStress(t *testing.T) { ++ if testing.Short() { ++ t.Skip("exhaustiveness test") ++ } ++ ++ var key [32]byte ++ msg := make([]byte, 10000) ++ prng := mrand.New(mrand.NewSource(0)) ++ ++ // copied from tests/auth5.c in nacl ++ for i := 0; i < 10000; i++ { ++ if _, err := rand.Read(key[:]); err != nil { ++ t.Fatal(err) ++ } ++ if _, err := rand.Read(msg[:i]); err != nil { ++ t.Fatal(err) ++ } ++ tag := Sum(msg[:i], &key) ++ if !Verify(tag[:], msg[:i], &key) { ++ t.Errorf("#%d: unexpected failure from Verify", i) ++ } ++ if i > 0 { ++ msgIndex := prng.Intn(i) ++ oldMsgByte := msg[msgIndex] ++ msg[msgIndex] += byte(1 + prng.Intn(255)) ++ if Verify(tag[:], msg[:i], &key) { ++ t.Errorf("#%d: unexpected success from Verify after corrupting message", i) ++ } ++ msg[msgIndex] = oldMsgByte ++ ++ tag[prng.Intn(len(tag))] += byte(1 + prng.Intn(255)) ++ if Verify(tag[:], msg[:i], &key) { ++ t.Errorf("#%d: unexpected success from Verify after corrupting authenticator", i) ++ } ++ } ++ } ++} ++ ++func BenchmarkAuth(b *testing.B) { ++ var key [32]byte ++ if _, err := rand.Read(key[:]); err != nil { ++ b.Fatal(err) ++ } ++ buf := make([]byte, 1024) ++ if _, err := rand.Read(buf[:]); err != nil { ++ b.Fatal(err) ++ } ++ ++ b.SetBytes(int64(len(buf))) ++ b.ReportAllocs() ++ b.ResetTimer() ++ ++ for i := 0; i < b.N; i++ { ++ tag := Sum(buf, &key) ++ if Verify(tag[:], buf, &key) == false { ++ b.Fatal("unexpected failure from Verify") ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/auth/example_test.go b/ms_mod/golang.org/x/crypto/nacl/auth/example_test.go +new file mode 100644 +index 00000000000000..02a2cd6c46a8f4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/auth/example_test.go +@@ -0,0 +1,36 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package auth_test ++ ++import ( ++ "encoding/hex" ++ "fmt" ++ ++ "golang.org/x/crypto/nacl/auth" ++) ++ ++func Example() { ++ // Load your secret key from a safe place and reuse it across multiple ++ // Sum calls. (Obviously don't use this example key for anything ++ // real.) If you want to convert a passphrase to a key, use a suitable ++ // package like bcrypt or scrypt. ++ secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") ++ if err != nil { ++ panic(err) ++ } ++ ++ var secretKey [32]byte ++ copy(secretKey[:], secretKeyBytes) ++ ++ mac := auth.Sum([]byte("hello world"), &secretKey) ++ fmt.Printf("%x\n", *mac) ++ result := auth.Verify(mac[:], []byte("hello world"), &secretKey) ++ fmt.Println(result) ++ badResult := auth.Verify(mac[:], []byte("different message"), &secretKey) ++ fmt.Println(badResult) ++ // Output: eca5a521f3d77b63f567fb0cb6f5f2d200641bc8dada42f60c5f881260c30317 ++ // true ++ // false ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/box/box.go b/ms_mod/golang.org/x/crypto/nacl/box/box.go +new file mode 100644 +index 00000000000000..7f3b830ee22f96 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/box/box.go +@@ -0,0 +1,182 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++Package box authenticates and encrypts small messages using public-key cryptography. ++ ++Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate ++messages. The length of messages is not hidden. ++ ++It is the caller's responsibility to ensure the uniqueness of noncesβ€”for ++example, by using nonce 1 for the first message, nonce 2 for the second ++message, etc. Nonces are long enough that randomly generated nonces have ++negligible risk of collision. ++ ++Messages should be small because: ++ ++1. The whole message needs to be held in memory to be processed. ++ ++2. Using large messages pressures implementations on small machines to decrypt ++and process plaintext before authenticating it. This is very dangerous, and ++this API does not allow it, but a protocol that uses excessive message sizes ++might present some implementations with no other choice. ++ ++3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. ++ ++4. Performance may be improved by working with messages that fit into data caches. ++ ++Thus large amounts of data should be chunked so that each message is small. ++(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable ++chunk size. ++ ++This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. ++Anonymous sealing/opening is an extension of NaCl defined by and interoperable ++with libsodium: ++https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes. ++*/ ++package box // import "golang.org/x/crypto/nacl/box" ++ ++import ( ++ cryptorand "crypto/rand" ++ "io" ++ ++ "golang.org/x/crypto/blake2b" ++ "golang.org/x/crypto/curve25519" ++ "golang.org/x/crypto/nacl/secretbox" ++ "golang.org/x/crypto/salsa20/salsa" ++) ++ ++const ( ++ // Overhead is the number of bytes of overhead when boxing a message. ++ Overhead = secretbox.Overhead ++ ++ // AnonymousOverhead is the number of bytes of overhead when using anonymous ++ // sealed boxes. ++ AnonymousOverhead = Overhead + 32 ++) ++ ++// GenerateKey generates a new public/private key pair suitable for use with ++// Seal and Open. ++func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { ++ publicKey = new([32]byte) ++ privateKey = new([32]byte) ++ _, err = io.ReadFull(rand, privateKey[:]) ++ if err != nil { ++ publicKey = nil ++ privateKey = nil ++ return ++ } ++ ++ curve25519.ScalarBaseMult(publicKey, privateKey) ++ return ++} ++ ++var zeros [16]byte ++ ++// Precompute calculates the shared key between peersPublicKey and privateKey ++// and writes it to sharedKey. The shared key can be used with ++// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing ++// when using the same pair of keys repeatedly. ++func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { ++ curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) ++ salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) ++} ++ ++// Seal appends an encrypted and authenticated copy of message to out, which ++// will be Overhead bytes longer than the original and must not overlap it. The ++// nonce must be unique for each distinct message for a given pair of keys. ++func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { ++ var sharedKey [32]byte ++ Precompute(&sharedKey, peersPublicKey, privateKey) ++ return secretbox.Seal(out, message, nonce, &sharedKey) ++} ++ ++// SealAfterPrecomputation performs the same actions as Seal, but takes a ++// shared key as generated by Precompute. ++func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { ++ return secretbox.Seal(out, message, nonce, sharedKey) ++} ++ ++// Open authenticates and decrypts a box produced by Seal and appends the ++// message to out, which must not overlap box. The output will be Overhead ++// bytes smaller than box. ++func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { ++ var sharedKey [32]byte ++ Precompute(&sharedKey, peersPublicKey, privateKey) ++ return secretbox.Open(out, box, nonce, &sharedKey) ++} ++ ++// OpenAfterPrecomputation performs the same actions as Open, but takes a ++// shared key as generated by Precompute. ++func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { ++ return secretbox.Open(out, box, nonce, sharedKey) ++} ++ ++// SealAnonymous appends an encrypted and authenticated copy of message to out, ++// which will be AnonymousOverhead bytes longer than the original and must not ++// overlap it. This differs from Seal in that the sender is not required to ++// provide a private key. ++func SealAnonymous(out, message []byte, recipient *[32]byte, rand io.Reader) ([]byte, error) { ++ if rand == nil { ++ rand = cryptorand.Reader ++ } ++ ephemeralPub, ephemeralPriv, err := GenerateKey(rand) ++ if err != nil { ++ return nil, err ++ } ++ ++ var nonce [24]byte ++ if err := sealNonce(ephemeralPub, recipient, &nonce); err != nil { ++ return nil, err ++ } ++ ++ if total := len(out) + AnonymousOverhead + len(message); cap(out) < total { ++ original := out ++ out = make([]byte, 0, total) ++ out = append(out, original...) ++ } ++ out = append(out, ephemeralPub[:]...) ++ ++ return Seal(out, message, &nonce, recipient, ephemeralPriv), nil ++} ++ ++// OpenAnonymous authenticates and decrypts a box produced by SealAnonymous and ++// appends the message to out, which must not overlap box. The output will be ++// AnonymousOverhead bytes smaller than box. ++func OpenAnonymous(out, box []byte, publicKey, privateKey *[32]byte) (message []byte, ok bool) { ++ if len(box) < AnonymousOverhead { ++ return nil, false ++ } ++ ++ var ephemeralPub [32]byte ++ copy(ephemeralPub[:], box[:32]) ++ ++ var nonce [24]byte ++ if err := sealNonce(&ephemeralPub, publicKey, &nonce); err != nil { ++ return nil, false ++ } ++ ++ return Open(out, box[32:], &nonce, &ephemeralPub, privateKey) ++} ++ ++// sealNonce generates a 24 byte nonce that is a blake2b digest of the ++// ephemeral public key and the receiver's public key. ++func sealNonce(ephemeralPub, peersPublicKey *[32]byte, nonce *[24]byte) error { ++ h, err := blake2b.New(24, nil) ++ if err != nil { ++ return err ++ } ++ ++ if _, err = h.Write(ephemeralPub[:]); err != nil { ++ return err ++ } ++ ++ if _, err = h.Write(peersPublicKey[:]); err != nil { ++ return err ++ } ++ ++ h.Sum(nonce[:0]) ++ ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/box/box_test.go b/ms_mod/golang.org/x/crypto/nacl/box/box_test.go +new file mode 100644 +index 00000000000000..cce1f3b4da1a20 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/box/box_test.go +@@ -0,0 +1,181 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package box ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/hex" ++ "testing" ++ ++ "golang.org/x/crypto/curve25519" ++) ++ ++func TestSealOpen(t *testing.T) { ++ publicKey1, privateKey1, _ := GenerateKey(rand.Reader) ++ publicKey2, privateKey2, _ := GenerateKey(rand.Reader) ++ ++ if *privateKey1 == *privateKey2 { ++ t.Fatalf("private keys are equal!") ++ } ++ if *publicKey1 == *publicKey2 { ++ t.Fatalf("public keys are equal!") ++ } ++ message := []byte("test message") ++ var nonce [24]byte ++ ++ box := Seal(nil, message, &nonce, publicKey1, privateKey2) ++ opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1) ++ if !ok { ++ t.Fatalf("failed to open box") ++ } ++ ++ if !bytes.Equal(opened, message) { ++ t.Fatalf("got %x, want %x", opened, message) ++ } ++ ++ for i := range box { ++ box[i] ^= 0x40 ++ _, ok := Open(nil, box, &nonce, publicKey2, privateKey1) ++ if ok { ++ t.Fatalf("opened box with byte %d corrupted", i) ++ } ++ box[i] ^= 0x40 ++ } ++} ++ ++func TestBox(t *testing.T) { ++ var privateKey1, privateKey2 [32]byte ++ for i := range privateKey1[:] { ++ privateKey1[i] = 1 ++ } ++ for i := range privateKey2[:] { ++ privateKey2[i] = 2 ++ } ++ ++ var publicKey1 [32]byte ++ curve25519.ScalarBaseMult(&publicKey1, &privateKey1) ++ var message [64]byte ++ for i := range message[:] { ++ message[i] = 3 ++ } ++ ++ var nonce [24]byte ++ for i := range nonce[:] { ++ nonce[i] = 4 ++ } ++ ++ box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2) ++ ++ // expected was generated using the C implementation of NaCl. ++ expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc") ++ ++ if !bytes.Equal(box, expected) { ++ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) ++ } ++} ++ ++func TestSealOpenAnonymous(t *testing.T) { ++ publicKey, privateKey, _ := GenerateKey(rand.Reader) ++ message := []byte("test message") ++ ++ box, err := SealAnonymous(nil, message, publicKey, nil) ++ if err != nil { ++ t.Fatalf("Unexpected error sealing %v", err) ++ } ++ opened, ok := OpenAnonymous(nil, box, publicKey, privateKey) ++ if !ok { ++ t.Fatalf("failed to open box") ++ } ++ ++ if !bytes.Equal(opened, message) { ++ t.Fatalf("got %x, want %x", opened, message) ++ } ++ ++ for i := range box { ++ box[i] ^= 0x40 ++ _, ok := OpenAnonymous(nil, box, publicKey, privateKey) ++ if ok { ++ t.Fatalf("opened box with byte %d corrupted", i) ++ } ++ box[i] ^= 0x40 ++ } ++ ++ // allocates new slice if out isn't long enough ++ out := []byte("hello") ++ orig := append([]byte(nil), out...) ++ box, err = SealAnonymous(out, message, publicKey, nil) ++ if err != nil { ++ t.Fatalf("Unexpected error sealing %v", err) ++ } ++ if !bytes.Equal(out, orig) { ++ t.Fatal("expected out to be unchanged") ++ } ++ if !bytes.HasPrefix(box, orig) { ++ t.Fatal("expected out to be coppied to returned slice") ++ } ++ _, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey) ++ if !ok { ++ t.Fatalf("failed to open box") ++ } ++ ++ // uses provided slice if it's long enough ++ out = append(make([]byte, 0, 1000), []byte("hello")...) ++ orig = append([]byte(nil), out...) ++ box, err = SealAnonymous(out, message, publicKey, nil) ++ if err != nil { ++ t.Fatalf("Unexpected error sealing %v", err) ++ } ++ if !bytes.Equal(out, orig) { ++ t.Fatal("expected out to be unchanged") ++ } ++ if &out[0] != &box[0] { ++ t.Fatal("expected box to point to out") ++ } ++ _, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey) ++ if !ok { ++ t.Fatalf("failed to open box") ++ } ++} ++ ++func TestSealedBox(t *testing.T) { ++ var privateKey [32]byte ++ for i := range privateKey[:] { ++ privateKey[i] = 1 ++ } ++ ++ var publicKey [32]byte ++ curve25519.ScalarBaseMult(&publicKey, &privateKey) ++ var message [64]byte ++ for i := range message[:] { ++ message[i] = 3 ++ } ++ ++ fakeRand := bytes.NewReader([]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}) ++ box, err := SealAnonymous(nil, message[:], &publicKey, fakeRand) ++ if err != nil { ++ t.Fatalf("Unexpected error sealing %v", err) ++ } ++ ++ // expected was generated using the C implementation of libsodium with a ++ // random implementation that always returns 5. ++ // https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7 ++ expected, _ := hex.DecodeString("50a61409b1ddd0325e9b16b700e719e9772c07000b1bd7786e907c653d20495d2af1697137a53b1b1dfc9befc49b6eeb38f86be720e155eb2be61976d2efb34d67ecd44a6ad634625eb9c288bfc883431a84ab0f5557dfe673aa6f74c19f033e648a947358cfcc606397fa1747d5219a") ++ ++ if !bytes.Equal(box, expected) { ++ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) ++ } ++ ++ // box was generated using the C implementation of libsodium. ++ // https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7 ++ box, _ = hex.DecodeString("3462e0640728247a6f581e3812850d6edc3dcad1ea5d8184c072f62fb65cb357e27ffa8b76f41656bc66a0882c4d359568410665746d27462a700f01e314f382edd7aae9064879b0f8ba7b88866f88f5e4fbd7649c850541877f9f33ebd25d46d9cbcce09b69a9ba07f0eb1d105d4264") ++ result, ok := OpenAnonymous(nil, box, &publicKey, &privateKey) ++ if !ok { ++ t.Fatalf("failed to open box") ++ } ++ if !bytes.Equal(result, message[:]) { ++ t.Fatalf("message didn't match, got\n%x\n, expected\n%x", result, message[:]) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/box/example_test.go b/ms_mod/golang.org/x/crypto/nacl/box/example_test.go +new file mode 100644 +index 00000000000000..25e42d2be9aa80 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/box/example_test.go +@@ -0,0 +1,95 @@ ++package box_test ++ ++import ( ++ crypto_rand "crypto/rand" // Custom so it's clear which rand we're using. ++ "fmt" ++ "io" ++ ++ "golang.org/x/crypto/nacl/box" ++) ++ ++func Example() { ++ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader) ++ if err != nil { ++ panic(err) ++ } ++ ++ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader) ++ if err != nil { ++ panic(err) ++ } ++ ++ // You must use a different nonce for each message you encrypt with the ++ // same key. Since the nonce here is 192 bits long, a random value ++ // provides a sufficiently small probability of repeats. ++ var nonce [24]byte ++ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil { ++ panic(err) ++ } ++ ++ msg := []byte("Alas, poor Yorick! I knew him, Horatio") ++ // This encrypts msg and appends the result to the nonce. ++ encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey) ++ ++ // The recipient can decrypt the message using their private key and the ++ // sender's public key. When you decrypt, you must use the same nonce you ++ // used to encrypt the message. One way to achieve this is to store the ++ // nonce alongside the encrypted message. Above, we stored the nonce in the ++ // first 24 bytes of the encrypted text. ++ var decryptNonce [24]byte ++ copy(decryptNonce[:], encrypted[:24]) ++ decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey) ++ if !ok { ++ panic("decryption error") ++ } ++ fmt.Println(string(decrypted)) ++ // Output: Alas, poor Yorick! I knew him, Horatio ++} ++ ++func Example_precompute() { ++ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader) ++ if err != nil { ++ panic(err) ++ } ++ ++ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader) ++ if err != nil { ++ panic(err) ++ } ++ ++ // The shared key can be used to speed up processing when using the same ++ // pair of keys repeatedly. ++ sharedEncryptKey := new([32]byte) ++ box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey) ++ ++ // You must use a different nonce for each message you encrypt with the ++ // same key. Since the nonce here is 192 bits long, a random value ++ // provides a sufficiently small probability of repeats. ++ var nonce [24]byte ++ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil { ++ panic(err) ++ } ++ ++ msg := []byte("A fellow of infinite jest, of most excellent fancy") ++ // This encrypts msg and appends the result to the nonce. ++ encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey) ++ ++ // The shared key can be used to speed up processing when using the same ++ // pair of keys repeatedly. ++ var sharedDecryptKey [32]byte ++ box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey) ++ ++ // The recipient can decrypt the message using the shared key. When you ++ // decrypt, you must use the same nonce you used to encrypt the message. ++ // One way to achieve this is to store the nonce alongside the encrypted ++ // message. Above, we stored the nonce in the first 24 bytes of the ++ // encrypted text. ++ var decryptNonce [24]byte ++ copy(decryptNonce[:], encrypted[:24]) ++ decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey) ++ if !ok { ++ panic("decryption error") ++ } ++ fmt.Println(string(decrypted)) ++ // Output: A fellow of infinite jest, of most excellent fancy ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go b/ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go +new file mode 100644 +index 00000000000000..789f4ff03f2ff8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go +@@ -0,0 +1,53 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package secretbox_test ++ ++import ( ++ "crypto/rand" ++ "encoding/hex" ++ "fmt" ++ "io" ++ ++ "golang.org/x/crypto/nacl/secretbox" ++) ++ ++func Example() { ++ // Load your secret key from a safe place and reuse it across multiple ++ // Seal calls. (Obviously don't use this example key for anything ++ // real.) If you want to convert a passphrase to a key, use a suitable ++ // package like bcrypt or scrypt. ++ secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") ++ if err != nil { ++ panic(err) ++ } ++ ++ var secretKey [32]byte ++ copy(secretKey[:], secretKeyBytes) ++ ++ // You must use a different nonce for each message you encrypt with the ++ // same key. Since the nonce here is 192 bits long, a random value ++ // provides a sufficiently small probability of repeats. ++ var nonce [24]byte ++ if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { ++ panic(err) ++ } ++ ++ // This encrypts "hello world" and appends the result to the nonce. ++ encrypted := secretbox.Seal(nonce[:], []byte("hello world"), &nonce, &secretKey) ++ ++ // When you decrypt, you must use the same nonce and key you used to ++ // encrypt the message. One way to achieve this is to store the nonce ++ // alongside the encrypted message. Above, we stored the nonce in the first ++ // 24 bytes of the encrypted text. ++ var decryptNonce [24]byte ++ copy(decryptNonce[:], encrypted[:24]) ++ decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey) ++ if !ok { ++ panic("decryption error") ++ } ++ ++ fmt.Println(string(decrypted)) ++ // Output: hello world ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go +new file mode 100644 +index 00000000000000..f3c3242a0471da +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go +@@ -0,0 +1,173 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++Package secretbox encrypts and authenticates small messages. ++ ++Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with ++secret-key cryptography. The length of messages is not hidden. ++ ++It is the caller's responsibility to ensure the uniqueness of noncesβ€”for ++example, by using nonce 1 for the first message, nonce 2 for the second ++message, etc. Nonces are long enough that randomly generated nonces have ++negligible risk of collision. ++ ++Messages should be small because: ++ ++1. The whole message needs to be held in memory to be processed. ++ ++2. Using large messages pressures implementations on small machines to decrypt ++and process plaintext before authenticating it. This is very dangerous, and ++this API does not allow it, but a protocol that uses excessive message sizes ++might present some implementations with no other choice. ++ ++3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. ++ ++4. Performance may be improved by working with messages that fit into data caches. ++ ++Thus large amounts of data should be chunked so that each message is small. ++(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable ++chunk size. ++ ++This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. ++*/ ++package secretbox // import "golang.org/x/crypto/nacl/secretbox" ++ ++import ( ++ "golang.org/x/crypto/internal/alias" ++ "golang.org/x/crypto/internal/poly1305" ++ "golang.org/x/crypto/salsa20/salsa" ++) ++ ++// Overhead is the number of bytes of overhead when boxing a message. ++const Overhead = poly1305.TagSize ++ ++// setup produces a sub-key and Salsa20 counter given a nonce and key. ++func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { ++ // We use XSalsa20 for encryption so first we need to generate a ++ // key and nonce with HSalsa20. ++ var hNonce [16]byte ++ copy(hNonce[:], nonce[:]) ++ salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) ++ ++ // The final 8 bytes of the original nonce form the new nonce. ++ copy(counter[:], nonce[16:]) ++} ++ ++// sliceForAppend takes a slice and a requested number of bytes. It returns a ++// slice with the contents of the given slice followed by that many bytes and a ++// second slice that aliases into it and contains only the extra bytes. If the ++// original slice has sufficient capacity then no allocation is performed. ++func sliceForAppend(in []byte, n int) (head, tail []byte) { ++ if total := len(in) + n; cap(in) >= total { ++ head = in[:total] ++ } else { ++ head = make([]byte, total) ++ copy(head, in) ++ } ++ tail = head[len(in):] ++ return ++} ++ ++// Seal appends an encrypted and authenticated copy of message to out, which ++// must not overlap message. The key and nonce pair must be unique for each ++// distinct message and the output will be Overhead bytes longer than message. ++func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { ++ var subKey [32]byte ++ var counter [16]byte ++ setup(&subKey, &counter, nonce, key) ++ ++ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since ++ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of ++ // keystream as a side effect. ++ var firstBlock [64]byte ++ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) ++ ++ var poly1305Key [32]byte ++ copy(poly1305Key[:], firstBlock[:]) ++ ++ ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) ++ if alias.AnyOverlap(out, message) { ++ panic("nacl: invalid buffer overlap") ++ } ++ ++ // We XOR up to 32 bytes of message with the keystream generated from ++ // the first block. ++ firstMessageBlock := message ++ if len(firstMessageBlock) > 32 { ++ firstMessageBlock = firstMessageBlock[:32] ++ } ++ ++ tagOut := out ++ out = out[poly1305.TagSize:] ++ for i, x := range firstMessageBlock { ++ out[i] = firstBlock[32+i] ^ x ++ } ++ message = message[len(firstMessageBlock):] ++ ciphertext := out ++ out = out[len(firstMessageBlock):] ++ ++ // Now encrypt the rest. ++ counter[8] = 1 ++ salsa.XORKeyStream(out, message, &counter, &subKey) ++ ++ var tag [poly1305.TagSize]byte ++ poly1305.Sum(&tag, ciphertext, &poly1305Key) ++ copy(tagOut, tag[:]) ++ ++ return ret ++} ++ ++// Open authenticates and decrypts a box produced by Seal and appends the ++// message to out, which must not overlap box. The output will be Overhead ++// bytes smaller than box. ++func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { ++ if len(box) < Overhead { ++ return nil, false ++ } ++ ++ var subKey [32]byte ++ var counter [16]byte ++ setup(&subKey, &counter, nonce, key) ++ ++ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since ++ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of ++ // keystream as a side effect. ++ var firstBlock [64]byte ++ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) ++ ++ var poly1305Key [32]byte ++ copy(poly1305Key[:], firstBlock[:]) ++ var tag [poly1305.TagSize]byte ++ copy(tag[:], box) ++ ++ if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { ++ return nil, false ++ } ++ ++ ret, out := sliceForAppend(out, len(box)-Overhead) ++ if alias.AnyOverlap(out, box) { ++ panic("nacl: invalid buffer overlap") ++ } ++ ++ // We XOR up to 32 bytes of box with the keystream generated from ++ // the first block. ++ box = box[Overhead:] ++ firstMessageBlock := box ++ if len(firstMessageBlock) > 32 { ++ firstMessageBlock = firstMessageBlock[:32] ++ } ++ for i, x := range firstMessageBlock { ++ out[i] = firstBlock[32+i] ^ x ++ } ++ ++ box = box[len(firstMessageBlock):] ++ out = out[len(firstMessageBlock):] ++ ++ // Now decrypt the rest. ++ counter[8] = 1 ++ salsa.XORKeyStream(out, box, &counter, &subKey) ++ ++ return ret, true ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go +new file mode 100644 +index 00000000000000..3c70b0f4b3d230 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go +@@ -0,0 +1,154 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package secretbox ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/hex" ++ "testing" ++) ++ ++func TestSealOpen(t *testing.T) { ++ var key [32]byte ++ var nonce [24]byte ++ ++ rand.Reader.Read(key[:]) ++ rand.Reader.Read(nonce[:]) ++ ++ var box, opened []byte ++ ++ for msgLen := 0; msgLen < 128; msgLen += 17 { ++ message := make([]byte, msgLen) ++ rand.Reader.Read(message) ++ ++ box = Seal(box[:0], message, &nonce, &key) ++ var ok bool ++ opened, ok = Open(opened[:0], box, &nonce, &key) ++ if !ok { ++ t.Errorf("%d: failed to open box", msgLen) ++ continue ++ } ++ ++ if !bytes.Equal(opened, message) { ++ t.Errorf("%d: got %x, expected %x", msgLen, opened, message) ++ continue ++ } ++ } ++ ++ for i := range box { ++ box[i] ^= 0x20 ++ _, ok := Open(opened[:0], box, &nonce, &key) ++ if ok { ++ t.Errorf("box was opened after corrupting byte %d", i) ++ } ++ box[i] ^= 0x20 ++ } ++} ++ ++func TestSecretBox(t *testing.T) { ++ var key [32]byte ++ var nonce [24]byte ++ var message [64]byte ++ ++ for i := range key[:] { ++ key[i] = 1 ++ } ++ for i := range nonce[:] { ++ nonce[i] = 2 ++ } ++ for i := range message[:] { ++ message[i] = 3 ++ } ++ ++ box := Seal(nil, message[:], &nonce, &key) ++ // expected was generated using the C implementation of NaCl. ++ expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") ++ ++ if !bytes.Equal(box, expected) { ++ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) ++ } ++} ++ ++func TestAppend(t *testing.T) { ++ var key [32]byte ++ var nonce [24]byte ++ var message [8]byte ++ ++ out := make([]byte, 4) ++ box := Seal(out, message[:], &nonce, &key) ++ if !bytes.Equal(box[:4], out[:4]) { ++ t.Fatalf("Seal didn't correctly append") ++ } ++ ++ out = make([]byte, 4, 100) ++ box = Seal(out, message[:], &nonce, &key) ++ if !bytes.Equal(box[:4], out[:4]) { ++ t.Fatalf("Seal didn't correctly append with sufficient capacity.") ++ } ++} ++ ++func benchmarkSealSize(b *testing.B, size int) { ++ message := make([]byte, size) ++ out := make([]byte, size+Overhead) ++ var nonce [24]byte ++ var key [32]byte ++ ++ b.SetBytes(int64(size)) ++ b.ResetTimer() ++ ++ for i := 0; i < b.N; i++ { ++ out = Seal(out[:0], message, &nonce, &key) ++ } ++} ++ ++func BenchmarkSeal8Bytes(b *testing.B) { ++ benchmarkSealSize(b, 8) ++} ++ ++func BenchmarkSeal100Bytes(b *testing.B) { ++ benchmarkSealSize(b, 100) ++} ++ ++func BenchmarkSeal1K(b *testing.B) { ++ benchmarkSealSize(b, 1024) ++} ++ ++func BenchmarkSeal8K(b *testing.B) { ++ benchmarkSealSize(b, 8192) ++} ++ ++func benchmarkOpenSize(b *testing.B, size int) { ++ msg := make([]byte, size) ++ result := make([]byte, size) ++ var nonce [24]byte ++ var key [32]byte ++ box := Seal(nil, msg, &nonce, &key) ++ ++ b.SetBytes(int64(size)) ++ b.ResetTimer() ++ ++ for i := 0; i < b.N; i++ { ++ if _, ok := Open(result[:0], box, &nonce, &key); !ok { ++ panic("Open failed") ++ } ++ } ++} ++ ++func BenchmarkOpen8Bytes(b *testing.B) { ++ benchmarkOpenSize(b, 8) ++} ++ ++func BenchmarkOpen100Bytes(b *testing.B) { ++ benchmarkOpenSize(b, 100) ++} ++ ++func BenchmarkOpen1K(b *testing.B) { ++ benchmarkOpenSize(b, 1024) ++} ++ ++func BenchmarkOpen8K(b *testing.B) { ++ benchmarkOpenSize(b, 8192) ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/sign/sign.go b/ms_mod/golang.org/x/crypto/nacl/sign/sign.go +new file mode 100644 +index 00000000000000..8a6acdcc090abf +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/sign/sign.go +@@ -0,0 +1,90 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package sign signs small messages using public-key cryptography. ++// ++// Sign uses Ed25519 to sign messages. The length of messages is not hidden. ++// Messages should be small because: ++// 1. The whole message needs to be held in memory to be processed. ++// 2. Using large messages pressures implementations on small machines to process ++// plaintext without verifying the signature. This is very dangerous, and this API ++// discourages it, but a protocol that uses excessive message sizes might present ++// some implementations with no other choice. ++// 3. Performance may be improved by working with messages that fit into data caches. ++// Thus large amounts of data should be chunked so that each message is small. ++// ++// This package is not interoperable with the current release of NaCl ++// (https://nacl.cr.yp.to/sign.html), which does not support Ed25519 yet. However, ++// it is compatible with the NaCl fork libsodium (https://www.libsodium.org), as well ++// as TweetNaCl (https://tweetnacl.cr.yp.to/). ++package sign ++ ++import ( ++ "io" ++ ++ "golang.org/x/crypto/ed25519" ++ "golang.org/x/crypto/internal/alias" ++) ++ ++// Overhead is the number of bytes of overhead when signing a message. ++const Overhead = 64 ++ ++// GenerateKey generates a new public/private key pair suitable for use with ++// Sign and Open. ++func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err error) { ++ pub, priv, err := ed25519.GenerateKey(rand) ++ if err != nil { ++ return nil, nil, err ++ } ++ publicKey, privateKey = new([32]byte), new([64]byte) ++ copy((*publicKey)[:], pub) ++ copy((*privateKey)[:], priv) ++ return publicKey, privateKey, nil ++} ++ ++// Sign appends a signed copy of message to out, which will be Overhead bytes ++// longer than the original and must not overlap it. ++func Sign(out, message []byte, privateKey *[64]byte) []byte { ++ sig := ed25519.Sign(ed25519.PrivateKey((*privateKey)[:]), message) ++ ret, out := sliceForAppend(out, Overhead+len(message)) ++ if alias.AnyOverlap(out, message) { ++ panic("nacl: invalid buffer overlap") ++ } ++ copy(out, sig) ++ copy(out[Overhead:], message) ++ return ret ++} ++ ++// Open verifies a signed message produced by Sign and appends the message to ++// out, which must not overlap the signed message. The output will be Overhead ++// bytes smaller than the signed message. ++func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool) { ++ if len(signedMessage) < Overhead { ++ return nil, false ++ } ++ if !ed25519.Verify(ed25519.PublicKey((*publicKey)[:]), signedMessage[Overhead:], signedMessage[:Overhead]) { ++ return nil, false ++ } ++ ret, out := sliceForAppend(out, len(signedMessage)-Overhead) ++ if alias.AnyOverlap(out, signedMessage) { ++ panic("nacl: invalid buffer overlap") ++ } ++ copy(out, signedMessage[Overhead:]) ++ return ret, true ++} ++ ++// sliceForAppend takes a slice and a requested number of bytes. It returns a ++// slice with the contents of the given slice followed by that many bytes and a ++// second slice that aliases into it and contains only the extra bytes. If the ++// original slice has sufficient capacity then no allocation is performed. ++func sliceForAppend(in []byte, n int) (head, tail []byte) { ++ if total := len(in) + n; cap(in) >= total { ++ head = in[:total] ++ } else { ++ head = make([]byte, total) ++ copy(head, in) ++ } ++ tail = head[len(in):] ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go b/ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go +new file mode 100644 +index 00000000000000..db269014c2b9a7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go +@@ -0,0 +1,74 @@ ++// Copyright 2018 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package sign ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/hex" ++ "testing" ++) ++ ++var testSignedMessage, _ = hex.DecodeString("26a0a47f733d02ddb74589b6cbd6f64a7dab1947db79395a1a9e00e4c902c0f185b119897b89b248d16bab4ea781b5a3798d25c2984aec833dddab57e0891e0d68656c6c6f20776f726c64") ++var testMessage = testSignedMessage[Overhead:] ++var testPublicKey [32]byte ++var testPrivateKey = [64]byte{ ++ 0x98, 0x3c, 0x6a, 0xa6, 0x21, 0xcc, 0xbb, 0xb2, 0xa7, 0xe8, 0x97, 0x94, 0xde, 0x5f, 0xf8, 0x11, ++ 0x8a, 0xf3, 0x33, 0x1a, 0x03, 0x5c, 0x43, 0x99, 0x03, 0x13, 0x2d, 0xd7, 0xb4, 0xc4, 0x8b, 0xb0, ++ 0xf6, 0x33, 0x20, 0xa3, 0x34, 0x8b, 0x7b, 0xe2, 0xfe, 0xb4, 0xe7, 0x3a, 0x54, 0x08, 0x2d, 0xd7, ++ 0x0c, 0xb7, 0xc0, 0xe3, 0xbf, 0x62, 0x6c, 0x55, 0xf0, 0x33, 0x28, 0x52, 0xf8, 0x48, 0x7d, 0xfd, ++} ++ ++func init() { ++ copy(testPublicKey[:], testPrivateKey[32:]) ++} ++ ++func TestSign(t *testing.T) { ++ signedMessage := Sign(nil, testMessage, &testPrivateKey) ++ if !bytes.Equal(signedMessage, testSignedMessage) { ++ t.Fatalf("signed message did not match, got\n%x\n, expected\n%x", signedMessage, testSignedMessage) ++ } ++} ++ ++func TestOpen(t *testing.T) { ++ message, ok := Open(nil, testSignedMessage, &testPublicKey) ++ if !ok { ++ t.Fatalf("valid signed message not successfully verified") ++ } ++ if !bytes.Equal(message, testMessage) { ++ t.Fatalf("message did not match, got\n%x\n, expected\n%x", message, testMessage) ++ } ++ _, ok = Open(nil, testSignedMessage[1:], &testPublicKey) ++ if ok { ++ t.Fatalf("invalid signed message successfully verified") ++ } ++ ++ badMessage := make([]byte, len(testSignedMessage)) ++ copy(badMessage, testSignedMessage) ++ badMessage[5] ^= 1 ++ if _, ok := Open(nil, badMessage, &testPublicKey); ok { ++ t.Fatalf("Open succeeded with a corrupt message") ++ } ++ ++ var badPublicKey [32]byte ++ copy(badPublicKey[:], testPublicKey[:]) ++ badPublicKey[5] ^= 1 ++ if _, ok := Open(nil, testSignedMessage, &badPublicKey); ok { ++ t.Fatalf("Open succeeded with a corrupt public key") ++ } ++} ++ ++func TestGenerateSignOpen(t *testing.T) { ++ publicKey, privateKey, _ := GenerateKey(rand.Reader) ++ signedMessage := Sign(nil, testMessage, privateKey) ++ message, ok := Open(nil, signedMessage, publicKey) ++ if !ok { ++ t.Fatalf("failed to verify signed message") ++ } ++ ++ if !bytes.Equal(message, testMessage) { ++ t.Fatalf("verified message does not match signed messge, got\n%x\n, expected\n%x", message, testMessage) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ocsp/ocsp.go b/ms_mod/golang.org/x/crypto/ocsp/ocsp.go +new file mode 100644 +index 00000000000000..4269ed113be905 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ocsp/ocsp.go +@@ -0,0 +1,792 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses ++// are signed messages attesting to the validity of a certificate for a small ++// period of time. This is used to manage revocation for X.509 certificates. ++package ocsp // import "golang.org/x/crypto/ocsp" ++ ++import ( ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/rsa" ++ _ "crypto/sha1" ++ _ "crypto/sha256" ++ _ "crypto/sha512" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "errors" ++ "fmt" ++ "math/big" ++ "strconv" ++ "time" ++) ++ ++var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) ++ ++// ResponseStatus contains the result of an OCSP request. See ++// https://tools.ietf.org/html/rfc6960#section-2.3 ++type ResponseStatus int ++ ++const ( ++ Success ResponseStatus = 0 ++ Malformed ResponseStatus = 1 ++ InternalError ResponseStatus = 2 ++ TryLater ResponseStatus = 3 ++ // Status code four is unused in OCSP. See ++ // https://tools.ietf.org/html/rfc6960#section-4.2.1 ++ SignatureRequired ResponseStatus = 5 ++ Unauthorized ResponseStatus = 6 ++) ++ ++func (r ResponseStatus) String() string { ++ switch r { ++ case Success: ++ return "success" ++ case Malformed: ++ return "malformed" ++ case InternalError: ++ return "internal error" ++ case TryLater: ++ return "try later" ++ case SignatureRequired: ++ return "signature required" ++ case Unauthorized: ++ return "unauthorized" ++ default: ++ return "unknown OCSP status: " + strconv.Itoa(int(r)) ++ } ++} ++ ++// ResponseError is an error that may be returned by ParseResponse to indicate ++// that the response itself is an error, not just that it's indicating that a ++// certificate is revoked, unknown, etc. ++type ResponseError struct { ++ Status ResponseStatus ++} ++ ++func (r ResponseError) Error() string { ++ return "ocsp: error from server: " + r.Status.String() ++} ++ ++// These are internal structures that reflect the ASN.1 structure of an OCSP ++// response. See RFC 2560, section 4.2. ++ ++type certID struct { ++ HashAlgorithm pkix.AlgorithmIdentifier ++ NameHash []byte ++ IssuerKeyHash []byte ++ SerialNumber *big.Int ++} ++ ++// https://tools.ietf.org/html/rfc2560#section-4.1.1 ++type ocspRequest struct { ++ TBSRequest tbsRequest ++} ++ ++type tbsRequest struct { ++ Version int `asn1:"explicit,tag:0,default:0,optional"` ++ RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` ++ RequestList []request ++} ++ ++type request struct { ++ Cert certID ++} ++ ++type responseASN1 struct { ++ Status asn1.Enumerated ++ Response responseBytes `asn1:"explicit,tag:0,optional"` ++} ++ ++type responseBytes struct { ++ ResponseType asn1.ObjectIdentifier ++ Response []byte ++} ++ ++type basicResponse struct { ++ TBSResponseData responseData ++ SignatureAlgorithm pkix.AlgorithmIdentifier ++ Signature asn1.BitString ++ Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` ++} ++ ++type responseData struct { ++ Raw asn1.RawContent ++ Version int `asn1:"optional,default:0,explicit,tag:0"` ++ RawResponderID asn1.RawValue ++ ProducedAt time.Time `asn1:"generalized"` ++ Responses []singleResponse ++} ++ ++type singleResponse struct { ++ CertID certID ++ Good asn1.Flag `asn1:"tag:0,optional"` ++ Revoked revokedInfo `asn1:"tag:1,optional"` ++ Unknown asn1.Flag `asn1:"tag:2,optional"` ++ ThisUpdate time.Time `asn1:"generalized"` ++ NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` ++ SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` ++} ++ ++type revokedInfo struct { ++ RevocationTime time.Time `asn1:"generalized"` ++ Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` ++} ++ ++var ( ++ oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} ++ oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} ++ oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} ++ oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} ++ oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} ++ oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} ++ oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} ++ oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} ++ oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} ++ oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} ++ oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} ++ oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} ++) ++ ++var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ ++ crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), ++ crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), ++ crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), ++ crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), ++} ++ ++// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below ++var signatureAlgorithmDetails = []struct { ++ algo x509.SignatureAlgorithm ++ oid asn1.ObjectIdentifier ++ pubKeyAlgo x509.PublicKeyAlgorithm ++ hash crypto.Hash ++}{ ++ {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, ++ {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, ++ {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, ++ {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, ++ {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, ++ {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, ++ {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, ++ {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, ++ {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, ++ {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, ++ {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, ++ {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, ++} ++ ++// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below ++func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { ++ var pubType x509.PublicKeyAlgorithm ++ ++ switch pub := pub.(type) { ++ case *rsa.PublicKey: ++ pubType = x509.RSA ++ hashFunc = crypto.SHA256 ++ sigAlgo.Algorithm = oidSignatureSHA256WithRSA ++ sigAlgo.Parameters = asn1.RawValue{ ++ Tag: 5, ++ } ++ ++ case *ecdsa.PublicKey: ++ pubType = x509.ECDSA ++ ++ switch pub.Curve { ++ case elliptic.P224(), elliptic.P256(): ++ hashFunc = crypto.SHA256 ++ sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 ++ case elliptic.P384(): ++ hashFunc = crypto.SHA384 ++ sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 ++ case elliptic.P521(): ++ hashFunc = crypto.SHA512 ++ sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 ++ default: ++ err = errors.New("x509: unknown elliptic curve") ++ } ++ ++ default: ++ err = errors.New("x509: only RSA and ECDSA keys supported") ++ } ++ ++ if err != nil { ++ return ++ } ++ ++ if requestedSigAlgo == 0 { ++ return ++ } ++ ++ found := false ++ for _, details := range signatureAlgorithmDetails { ++ if details.algo == requestedSigAlgo { ++ if details.pubKeyAlgo != pubType { ++ err = errors.New("x509: requested SignatureAlgorithm does not match private key type") ++ return ++ } ++ sigAlgo.Algorithm, hashFunc = details.oid, details.hash ++ if hashFunc == 0 { ++ err = errors.New("x509: cannot sign with hash function requested") ++ return ++ } ++ found = true ++ break ++ } ++ } ++ ++ if !found { ++ err = errors.New("x509: unknown SignatureAlgorithm") ++ } ++ ++ return ++} ++ ++// TODO(agl): this is taken from crypto/x509 and so should probably be exported ++// from crypto/x509 or crypto/x509/pkix. ++func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { ++ for _, details := range signatureAlgorithmDetails { ++ if oid.Equal(details.oid) { ++ return details.algo ++ } ++ } ++ return x509.UnknownSignatureAlgorithm ++} ++ ++// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. ++func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { ++ for hash, oid := range hashOIDs { ++ if oid.Equal(target) { ++ return hash ++ } ++ } ++ return crypto.Hash(0) ++} ++ ++func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { ++ for hash, oid := range hashOIDs { ++ if hash == target { ++ return oid ++ } ++ } ++ return nil ++} ++ ++// This is the exposed reflection of the internal OCSP structures. ++ ++// The status values that can be expressed in OCSP. See RFC 6960. ++const ( ++ // Good means that the certificate is valid. ++ Good = iota ++ // Revoked means that the certificate has been deliberately revoked. ++ Revoked ++ // Unknown means that the OCSP responder doesn't know about the certificate. ++ Unknown ++ // ServerFailed is unused and was never used (see ++ // https://go-review.googlesource.com/#/c/18944). ParseResponse will ++ // return a ResponseError when an error response is parsed. ++ ServerFailed ++) ++ ++// The enumerated reasons for revoking a certificate. See RFC 5280. ++const ( ++ Unspecified = 0 ++ KeyCompromise = 1 ++ CACompromise = 2 ++ AffiliationChanged = 3 ++ Superseded = 4 ++ CessationOfOperation = 5 ++ CertificateHold = 6 ++ ++ RemoveFromCRL = 8 ++ PrivilegeWithdrawn = 9 ++ AACompromise = 10 ++) ++ ++// Request represents an OCSP request. See RFC 6960. ++type Request struct { ++ HashAlgorithm crypto.Hash ++ IssuerNameHash []byte ++ IssuerKeyHash []byte ++ SerialNumber *big.Int ++} ++ ++// Marshal marshals the OCSP request to ASN.1 DER encoded form. ++func (req *Request) Marshal() ([]byte, error) { ++ hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm) ++ if hashAlg == nil { ++ return nil, errors.New("Unknown hash algorithm") ++ } ++ return asn1.Marshal(ocspRequest{ ++ tbsRequest{ ++ Version: 0, ++ RequestList: []request{ ++ { ++ Cert: certID{ ++ pkix.AlgorithmIdentifier{ ++ Algorithm: hashAlg, ++ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, ++ }, ++ req.IssuerNameHash, ++ req.IssuerKeyHash, ++ req.SerialNumber, ++ }, ++ }, ++ }, ++ }, ++ }) ++} ++ ++// Response represents an OCSP response containing a single SingleResponse. See ++// RFC 6960. ++type Response struct { ++ Raw []byte ++ ++ // Status is one of {Good, Revoked, Unknown} ++ Status int ++ SerialNumber *big.Int ++ ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time ++ RevocationReason int ++ Certificate *x509.Certificate ++ // TBSResponseData contains the raw bytes of the signed response. If ++ // Certificate is nil then this can be used to verify Signature. ++ TBSResponseData []byte ++ Signature []byte ++ SignatureAlgorithm x509.SignatureAlgorithm ++ ++ // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash. ++ // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512. ++ // If zero, the default is crypto.SHA1. ++ IssuerHash crypto.Hash ++ ++ // RawResponderName optionally contains the DER-encoded subject of the ++ // responder certificate. Exactly one of RawResponderName and ++ // ResponderKeyHash is set. ++ RawResponderName []byte ++ // ResponderKeyHash optionally contains the SHA-1 hash of the ++ // responder's public key. Exactly one of RawResponderName and ++ // ResponderKeyHash is set. ++ ResponderKeyHash []byte ++ ++ // Extensions contains raw X.509 extensions from the singleExtensions field ++ // of the OCSP response. When parsing certificates, this can be used to ++ // extract non-critical extensions that are not parsed by this package. When ++ // marshaling OCSP responses, the Extensions field is ignored, see ++ // ExtraExtensions. ++ Extensions []pkix.Extension ++ ++ // ExtraExtensions contains extensions to be copied, raw, into any marshaled ++ // OCSP response (in the singleExtensions field). Values override any ++ // extensions that would otherwise be produced based on the other fields. The ++ // ExtraExtensions field is not populated when parsing certificates, see ++ // Extensions. ++ ExtraExtensions []pkix.Extension ++} ++ ++// These are pre-serialized error responses for the various non-success codes ++// defined by OCSP. The Unauthorized code in particular can be used by an OCSP ++// responder that supports only pre-signed responses as a response to requests ++// for certificates with unknown status. See RFC 5019. ++var ( ++ MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} ++ InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} ++ TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} ++ SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} ++ UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} ++) ++ ++// CheckSignatureFrom checks that the signature in resp is a valid signature ++// from issuer. This should only be used if resp.Certificate is nil. Otherwise, ++// the OCSP response contained an intermediate certificate that created the ++// signature. That signature is checked by ParseResponse and only ++// resp.Certificate remains to be validated. ++func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { ++ return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) ++} ++ ++// ParseError results from an invalid OCSP response. ++type ParseError string ++ ++func (p ParseError) Error() string { ++ return string(p) ++} ++ ++// ParseRequest parses an OCSP request in DER form. It only supports ++// requests for a single certificate. Signed requests are not supported. ++// If a request includes a signature, it will result in a ParseError. ++func ParseRequest(bytes []byte) (*Request, error) { ++ var req ocspRequest ++ rest, err := asn1.Unmarshal(bytes, &req) ++ if err != nil { ++ return nil, err ++ } ++ if len(rest) > 0 { ++ return nil, ParseError("trailing data in OCSP request") ++ } ++ ++ if len(req.TBSRequest.RequestList) == 0 { ++ return nil, ParseError("OCSP request contains no request body") ++ } ++ innerRequest := req.TBSRequest.RequestList[0] ++ ++ hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) ++ if hashFunc == crypto.Hash(0) { ++ return nil, ParseError("OCSP request uses unknown hash function") ++ } ++ ++ return &Request{ ++ HashAlgorithm: hashFunc, ++ IssuerNameHash: innerRequest.Cert.NameHash, ++ IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, ++ SerialNumber: innerRequest.Cert.SerialNumber, ++ }, nil ++} ++ ++// ParseResponse parses an OCSP response in DER form. The response must contain ++// only one certificate status. To parse the status of a specific certificate ++// from a response which may contain multiple statuses, use ParseResponseForCert ++// instead. ++// ++// If the response contains an embedded certificate, then that certificate will ++// be used to verify the response signature. If the response contains an ++// embedded certificate and issuer is not nil, then issuer will be used to verify ++// the signature on the embedded certificate. ++// ++// If the response does not contain an embedded certificate and issuer is not ++// nil, then issuer will be used to verify the response signature. ++// ++// Invalid responses and parse failures will result in a ParseError. ++// Error responses will result in a ResponseError. ++func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { ++ return ParseResponseForCert(bytes, nil, issuer) ++} ++ ++// ParseResponseForCert acts identically to ParseResponse, except it supports ++// parsing responses that contain multiple statuses. If the response contains ++// multiple statuses and cert is not nil, then ParseResponseForCert will return ++// the first status which contains a matching serial, otherwise it will return an ++// error. If cert is nil, then the first status in the response will be returned. ++func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { ++ var resp responseASN1 ++ rest, err := asn1.Unmarshal(bytes, &resp) ++ if err != nil { ++ return nil, err ++ } ++ if len(rest) > 0 { ++ return nil, ParseError("trailing data in OCSP response") ++ } ++ ++ if status := ResponseStatus(resp.Status); status != Success { ++ return nil, ResponseError{status} ++ } ++ ++ if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { ++ return nil, ParseError("bad OCSP response type") ++ } ++ ++ var basicResp basicResponse ++ rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) ++ if err != nil { ++ return nil, err ++ } ++ if len(rest) > 0 { ++ return nil, ParseError("trailing data in OCSP response") ++ } ++ ++ if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { ++ return nil, ParseError("OCSP response contains bad number of responses") ++ } ++ ++ var singleResp singleResponse ++ if cert == nil { ++ singleResp = basicResp.TBSResponseData.Responses[0] ++ } else { ++ match := false ++ for _, resp := range basicResp.TBSResponseData.Responses { ++ if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 { ++ singleResp = resp ++ match = true ++ break ++ } ++ } ++ if !match { ++ return nil, ParseError("no response matching the supplied certificate") ++ } ++ } ++ ++ ret := &Response{ ++ Raw: bytes, ++ TBSResponseData: basicResp.TBSResponseData.Raw, ++ Signature: basicResp.Signature.RightAlign(), ++ SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), ++ Extensions: singleResp.SingleExtensions, ++ SerialNumber: singleResp.CertID.SerialNumber, ++ ProducedAt: basicResp.TBSResponseData.ProducedAt, ++ ThisUpdate: singleResp.ThisUpdate, ++ NextUpdate: singleResp.NextUpdate, ++ } ++ ++ // Handle the ResponderID CHOICE tag. ResponderID can be flattened into ++ // TBSResponseData once https://go-review.googlesource.com/34503 has been ++ // released. ++ rawResponderID := basicResp.TBSResponseData.RawResponderID ++ switch rawResponderID.Tag { ++ case 1: // Name ++ var rdn pkix.RDNSequence ++ if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 { ++ return nil, ParseError("invalid responder name") ++ } ++ ret.RawResponderName = rawResponderID.Bytes ++ case 2: // KeyHash ++ if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 { ++ return nil, ParseError("invalid responder key hash") ++ } ++ default: ++ return nil, ParseError("invalid responder id tag") ++ } ++ ++ if len(basicResp.Certificates) > 0 { ++ // Responders should only send a single certificate (if they ++ // send any) that connects the responder's certificate to the ++ // original issuer. We accept responses with multiple ++ // certificates due to a number responders sending them[1], but ++ // ignore all but the first. ++ // ++ // [1] https://github.com/golang/go/issues/21527 ++ ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) ++ if err != nil { ++ return nil, err ++ } ++ ++ if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { ++ return nil, ParseError("bad signature on embedded certificate: " + err.Error()) ++ } ++ ++ if issuer != nil { ++ if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { ++ return nil, ParseError("bad OCSP signature: " + err.Error()) ++ } ++ } ++ } else if issuer != nil { ++ if err := ret.CheckSignatureFrom(issuer); err != nil { ++ return nil, ParseError("bad OCSP signature: " + err.Error()) ++ } ++ } ++ ++ for _, ext := range singleResp.SingleExtensions { ++ if ext.Critical { ++ return nil, ParseError("unsupported critical extension") ++ } ++ } ++ ++ for h, oid := range hashOIDs { ++ if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) { ++ ret.IssuerHash = h ++ break ++ } ++ } ++ if ret.IssuerHash == 0 { ++ return nil, ParseError("unsupported issuer hash algorithm") ++ } ++ ++ switch { ++ case bool(singleResp.Good): ++ ret.Status = Good ++ case bool(singleResp.Unknown): ++ ret.Status = Unknown ++ default: ++ ret.Status = Revoked ++ ret.RevokedAt = singleResp.Revoked.RevocationTime ++ ret.RevocationReason = int(singleResp.Revoked.Reason) ++ } ++ ++ return ret, nil ++} ++ ++// RequestOptions contains options for constructing OCSP requests. ++type RequestOptions struct { ++ // Hash contains the hash function that should be used when ++ // constructing the OCSP request. If zero, SHA-1 will be used. ++ Hash crypto.Hash ++} ++ ++func (opts *RequestOptions) hash() crypto.Hash { ++ if opts == nil || opts.Hash == 0 { ++ // SHA-1 is nearly universally used in OCSP. ++ return crypto.SHA1 ++ } ++ return opts.Hash ++} ++ ++// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If ++// opts is nil then sensible defaults are used. ++func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { ++ hashFunc := opts.hash() ++ ++ // OCSP seems to be the only place where these raw hash identifiers are ++ // used. I took the following from ++ // http://msdn.microsoft.com/en-us/library/ff635603.aspx ++ _, ok := hashOIDs[hashFunc] ++ if !ok { ++ return nil, x509.ErrUnsupportedAlgorithm ++ } ++ ++ if !hashFunc.Available() { ++ return nil, x509.ErrUnsupportedAlgorithm ++ } ++ h := opts.hash().New() ++ ++ var publicKeyInfo struct { ++ Algorithm pkix.AlgorithmIdentifier ++ PublicKey asn1.BitString ++ } ++ if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { ++ return nil, err ++ } ++ ++ h.Write(publicKeyInfo.PublicKey.RightAlign()) ++ issuerKeyHash := h.Sum(nil) ++ ++ h.Reset() ++ h.Write(issuer.RawSubject) ++ issuerNameHash := h.Sum(nil) ++ ++ req := &Request{ ++ HashAlgorithm: hashFunc, ++ IssuerNameHash: issuerNameHash, ++ IssuerKeyHash: issuerKeyHash, ++ SerialNumber: cert.SerialNumber, ++ } ++ return req.Marshal() ++} ++ ++// CreateResponse returns a DER-encoded OCSP response with the specified contents. ++// The fields in the response are populated as follows: ++// ++// The responder cert is used to populate the responder's name field, and the ++// certificate itself is provided alongside the OCSP response signature. ++// ++// The issuer cert is used to populate the IssuerNameHash and IssuerKeyHash fields. ++// ++// The template is used to populate the SerialNumber, Status, RevokedAt, ++// RevocationReason, ThisUpdate, and NextUpdate fields. ++// ++// If template.IssuerHash is not set, SHA1 will be used. ++// ++// The ProducedAt date is automatically set to the current date, to the nearest minute. ++func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { ++ var publicKeyInfo struct { ++ Algorithm pkix.AlgorithmIdentifier ++ PublicKey asn1.BitString ++ } ++ if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { ++ return nil, err ++ } ++ ++ if template.IssuerHash == 0 { ++ template.IssuerHash = crypto.SHA1 ++ } ++ hashOID := getOIDFromHashAlgorithm(template.IssuerHash) ++ if hashOID == nil { ++ return nil, errors.New("unsupported issuer hash algorithm") ++ } ++ ++ if !template.IssuerHash.Available() { ++ return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash) ++ } ++ h := template.IssuerHash.New() ++ h.Write(publicKeyInfo.PublicKey.RightAlign()) ++ issuerKeyHash := h.Sum(nil) ++ ++ h.Reset() ++ h.Write(issuer.RawSubject) ++ issuerNameHash := h.Sum(nil) ++ ++ innerResponse := singleResponse{ ++ CertID: certID{ ++ HashAlgorithm: pkix.AlgorithmIdentifier{ ++ Algorithm: hashOID, ++ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, ++ }, ++ NameHash: issuerNameHash, ++ IssuerKeyHash: issuerKeyHash, ++ SerialNumber: template.SerialNumber, ++ }, ++ ThisUpdate: template.ThisUpdate.UTC(), ++ NextUpdate: template.NextUpdate.UTC(), ++ SingleExtensions: template.ExtraExtensions, ++ } ++ ++ switch template.Status { ++ case Good: ++ innerResponse.Good = true ++ case Unknown: ++ innerResponse.Unknown = true ++ case Revoked: ++ innerResponse.Revoked = revokedInfo{ ++ RevocationTime: template.RevokedAt.UTC(), ++ Reason: asn1.Enumerated(template.RevocationReason), ++ } ++ } ++ ++ rawResponderID := asn1.RawValue{ ++ Class: 2, // context-specific ++ Tag: 1, // Name (explicit tag) ++ IsCompound: true, ++ Bytes: responderCert.RawSubject, ++ } ++ tbsResponseData := responseData{ ++ Version: 0, ++ RawResponderID: rawResponderID, ++ ProducedAt: time.Now().Truncate(time.Minute).UTC(), ++ Responses: []singleResponse{innerResponse}, ++ } ++ ++ tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) ++ if err != nil { ++ return nil, err ++ } ++ ++ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) ++ if err != nil { ++ return nil, err ++ } ++ ++ responseHash := hashFunc.New() ++ responseHash.Write(tbsResponseDataDER) ++ signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) ++ if err != nil { ++ return nil, err ++ } ++ ++ response := basicResponse{ ++ TBSResponseData: tbsResponseData, ++ SignatureAlgorithm: signatureAlgorithm, ++ Signature: asn1.BitString{ ++ Bytes: signature, ++ BitLength: 8 * len(signature), ++ }, ++ } ++ if template.Certificate != nil { ++ response.Certificates = []asn1.RawValue{ ++ {FullBytes: template.Certificate.Raw}, ++ } ++ } ++ responseDER, err := asn1.Marshal(response) ++ if err != nil { ++ return nil, err ++ } ++ ++ return asn1.Marshal(responseASN1{ ++ Status: asn1.Enumerated(Success), ++ Response: responseBytes{ ++ ResponseType: idPKIXOCSPBasic, ++ Response: responseDER, ++ }, ++ }) ++} +diff --git a/ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go b/ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go +new file mode 100644 +index 00000000000000..0bc194b2f4ab84 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go +@@ -0,0 +1,746 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.7 ++// +build go1.7 ++ ++package ocsp ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/sha1" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "encoding/hex" ++ "encoding/pem" ++ "math/big" ++ "reflect" ++ "testing" ++ "time" ++) ++ ++func TestOCSPDecode(t *testing.T) { ++ responseBytes, _ := hex.DecodeString(ocspResponseHex) ++ resp, err := ParseResponse(responseBytes, nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // keyHash is the SKID of the issuer of the certificate the OCSP ++ // response is for. ++ keyHash, err := hex.DecodeString("8a747faf85cdee95cd3d9cd0e24614f371351d27") ++ if err != nil { ++ t.Fatal(err) ++ } ++ // serialBytes is the serial number of the certificate the OCSP ++ // response is for. ++ serialBytes, err := hex.DecodeString("f374542e3c7a68360a00000001103462") ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ expected := Response{ ++ Status: Good, ++ SerialNumber: big.NewInt(0).SetBytes(serialBytes), ++ RevocationReason: Unspecified, ++ ThisUpdate: time.Date(2021, 11, 7, 14, 25, 51, 0, time.UTC), ++ NextUpdate: time.Date(2021, 11, 14, 13, 25, 50, 0, time.UTC), ++ ResponderKeyHash: keyHash, ++ } ++ ++ if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) { ++ t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, expected.ThisUpdate) ++ } ++ ++ if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) { ++ t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, expected.NextUpdate) ++ } ++ ++ if resp.Status != expected.Status { ++ t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status) ++ } ++ ++ if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 { ++ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber) ++ } ++ ++ if resp.RevocationReason != expected.RevocationReason { ++ t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason) ++ } ++ ++ if !bytes.Equal(resp.RawResponderName, expected.RawResponderName) { ++ t.Errorf("resp.RawResponderName: got %x, want %x", resp.RawResponderName, expected.RawResponderName) ++ } ++ ++ if !bytes.Equal(resp.ResponderKeyHash, expected.ResponderKeyHash) { ++ t.Errorf("resp.ResponderKeyHash: got %x, want %x", resp.ResponderKeyHash, expected.ResponderKeyHash) ++ } ++} ++ ++func TestOCSPDecodeWithoutCert(t *testing.T) { ++ responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex) ++ _, err := ParseResponse(responseBytes, nil) ++ if err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestOCSPDecodeWithExtensions(t *testing.T) { ++ responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex) ++ _, err := ParseResponse(responseBytes, nil) ++ if err == nil { ++ t.Error(err) ++ } ++ ++ responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex) ++ response, err := ParseResponse(responseBytes, nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if len(response.Extensions) != 1 { ++ t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1) ++ } ++ ++ extensionBytes := response.Extensions[0].Value ++ expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex) ++ if !bytes.Equal(extensionBytes, expectedBytes) { ++ t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes) ++ } ++} ++ ++func TestOCSPSignature(t *testing.T) { ++ b, _ := pem.Decode([]byte(GTSRoot)) ++ issuer, err := x509.ParseCertificate(b.Bytes) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ response, _ := hex.DecodeString(ocspResponseHex) ++ if _, err := ParseResponse(response, issuer); err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestOCSPRequest(t *testing.T) { ++ leafCert, _ := hex.DecodeString(leafCertHex) ++ cert, err := x509.ParseCertificate(leafCert) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ issuerCert, _ := hex.DecodeString(issuerCertHex) ++ issuer, err := x509.ParseCertificate(issuerCert) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ request, err := CreateRequest(cert, issuer, nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ expectedBytes, _ := hex.DecodeString(ocspRequestHex) ++ if !bytes.Equal(request, expectedBytes) { ++ t.Errorf("request: got %x, wanted %x", request, expectedBytes) ++ } ++ ++ decodedRequest, err := ParseRequest(expectedBytes) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if decodedRequest.HashAlgorithm != crypto.SHA1 { ++ t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1) ++ } ++ ++ var publicKeyInfo struct { ++ Algorithm pkix.AlgorithmIdentifier ++ PublicKey asn1.BitString ++ } ++ _, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ h := sha1.New() ++ h.Write(publicKeyInfo.PublicKey.RightAlign()) ++ issuerKeyHash := h.Sum(nil) ++ ++ h.Reset() ++ h.Write(issuer.RawSubject) ++ issuerNameHash := h.Sum(nil) ++ ++ if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) { ++ t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash) ++ } ++ ++ if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) { ++ t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash) ++ } ++ ++ if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 { ++ t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber) ++ } ++ ++ marshaledRequest, err := decodedRequest.Marshal() ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if bytes.Compare(expectedBytes, marshaledRequest) != 0 { ++ t.Errorf( ++ "Marshaled request doesn't match expected: wanted %x, got %x", ++ expectedBytes, ++ marshaledRequest, ++ ) ++ } ++} ++ ++func TestOCSPResponse(t *testing.T) { ++ leafCert, _ := hex.DecodeString(leafCertHex) ++ leaf, err := x509.ParseCertificate(leafCert) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ issuerCert, _ := hex.DecodeString(issuerCertHex) ++ issuer, err := x509.ParseCertificate(issuerCert) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ responderCert, _ := hex.DecodeString(responderCertHex) ++ responder, err := x509.ParseCertificate(responderCert) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex) ++ responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex) ++ extensions := []pkix.Extension{ ++ { ++ Id: ocspExtensionOID, ++ Critical: false, ++ Value: extensionBytes, ++ }, ++ } ++ ++ thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC) ++ nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC) ++ template := Response{ ++ Status: Revoked, ++ SerialNumber: leaf.SerialNumber, ++ ThisUpdate: thisUpdate, ++ NextUpdate: nextUpdate, ++ RevokedAt: thisUpdate, ++ RevocationReason: KeyCompromise, ++ Certificate: responder, ++ ExtraExtensions: extensions, ++ } ++ ++ template.IssuerHash = crypto.MD5 ++ _, err = CreateResponse(issuer, responder, template, responderPrivateKey) ++ if err == nil { ++ t.Fatal("CreateResponse didn't fail with non-valid template.IssuerHash value crypto.MD5") ++ } ++ ++ testCases := []struct { ++ name string ++ issuerHash crypto.Hash ++ }{ ++ {"Zero value", 0}, ++ {"crypto.SHA1", crypto.SHA1}, ++ {"crypto.SHA256", crypto.SHA256}, ++ {"crypto.SHA384", crypto.SHA384}, ++ {"crypto.SHA512", crypto.SHA512}, ++ } ++ for _, tc := range testCases { ++ t.Run(tc.name, func(t *testing.T) { ++ template.IssuerHash = tc.issuerHash ++ responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey) ++ if err != nil { ++ t.Fatalf("CreateResponse failed: %s", err) ++ } ++ ++ resp, err := ParseResponse(responseBytes, nil) ++ if err != nil { ++ t.Fatalf("ParseResponse failed: %s", err) ++ } ++ ++ if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) { ++ t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, template.ThisUpdate) ++ } ++ ++ if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) { ++ t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, template.NextUpdate) ++ } ++ ++ if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) { ++ t.Errorf("resp.RevokedAt: got %v, want %v", resp.RevokedAt, template.RevokedAt) ++ } ++ ++ if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) { ++ t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions) ++ } ++ ++ delay := time.Since(resp.ProducedAt) ++ if delay < -time.Hour || delay > time.Hour { ++ t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now()) ++ } ++ ++ if resp.Status != template.Status { ++ t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status) ++ } ++ ++ if resp.SerialNumber.Cmp(template.SerialNumber) != 0 { ++ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber) ++ } ++ ++ if resp.RevocationReason != template.RevocationReason { ++ t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason) ++ } ++ ++ expectedHash := tc.issuerHash ++ if tc.issuerHash == 0 { ++ expectedHash = crypto.SHA1 ++ } ++ ++ if resp.IssuerHash != expectedHash { ++ t.Errorf("resp.IssuerHash: got %d, want %d", resp.IssuerHash, expectedHash) ++ } ++ }) ++ } ++} ++ ++func TestErrorResponse(t *testing.T) { ++ responseBytes, _ := hex.DecodeString(errorResponseHex) ++ _, err := ParseResponse(responseBytes, nil) ++ ++ respErr, ok := err.(ResponseError) ++ if !ok { ++ t.Fatalf("expected ResponseError from ParseResponse but got %#v", err) ++ } ++ if respErr.Status != Malformed { ++ t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status) ++ } ++} ++ ++func createMultiResp() ([]byte, error) { ++ rawResponderID := asn1.RawValue{ ++ Class: 2, // context-specific ++ Tag: 1, // Name (explicit tag) ++ IsCompound: true, ++ Bytes: []byte{48, 0}, ++ } ++ tbsResponseData := responseData{ ++ Version: 0, ++ RawResponderID: rawResponderID, ++ ProducedAt: time.Now().Truncate(time.Minute).UTC(), ++ } ++ this := time.Now() ++ next := this.Add(time.Hour * 24 * 4) ++ for i := int64(0); i < 5; i++ { ++ tbsResponseData.Responses = append(tbsResponseData.Responses, singleResponse{ ++ CertID: certID{ ++ HashAlgorithm: pkix.AlgorithmIdentifier{ ++ Algorithm: hashOIDs[crypto.SHA1], ++ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, ++ }, ++ NameHash: []byte{1, 2, 3}, ++ IssuerKeyHash: []byte{4, 5, 6}, ++ SerialNumber: big.NewInt(i), ++ }, ++ ThisUpdate: this.UTC(), ++ NextUpdate: next.UTC(), ++ Good: true, ++ }) ++ } ++ ++ tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) ++ if err != nil { ++ return nil, err ++ } ++ ++ k, err := rsa.GenerateKey(rand.Reader, 1024) ++ if err != nil { ++ return nil, err ++ } ++ ++ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(k.Public(), x509.SHA1WithRSA) ++ if err != nil { ++ return nil, err ++ } ++ ++ responseHash := hashFunc.New() ++ responseHash.Write(tbsResponseDataDER) ++ signature, err := k.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) ++ if err != nil { ++ return nil, err ++ } ++ ++ response := basicResponse{ ++ TBSResponseData: tbsResponseData, ++ SignatureAlgorithm: signatureAlgorithm, ++ Signature: asn1.BitString{ ++ Bytes: signature, ++ BitLength: 8 * len(signature), ++ }, ++ } ++ responseDER, err := asn1.Marshal(response) ++ if err != nil { ++ return nil, err ++ } ++ ++ return asn1.Marshal(responseASN1{ ++ Status: asn1.Enumerated(Success), ++ Response: responseBytes{ ++ ResponseType: idPKIXOCSPBasic, ++ Response: responseDER, ++ }, ++ }) ++} ++ ++func TestOCSPDecodeMultiResponse(t *testing.T) { ++ respBytes, err := createMultiResp() ++ if err != nil { ++ t.Fatal(err) ++ } ++ matchingCert := &x509.Certificate{SerialNumber: big.NewInt(3)} ++ resp, err := ParseResponseForCert(respBytes, matchingCert, nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if resp.SerialNumber.Cmp(matchingCert.SerialNumber) != 0 { ++ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, 3) ++ } ++} ++ ++func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) { ++ respBytes, err := createMultiResp() ++ if err != nil { ++ t.Fatal(err) ++ } ++ _, err = ParseResponseForCert(respBytes, &x509.Certificate{SerialNumber: big.NewInt(100)}, nil) ++ want := ParseError("no response matching the supplied certificate") ++ if err != want { ++ t.Errorf("err: got %q, want %q", err, want) ++ } ++} ++ ++// This OCSP response was taken from GTS's public OCSP responder. ++// To recreate: ++// $ openssl s_client -tls1 -showcerts -servername golang.org -connect golang.org:443 ++// Copy and paste the first certificate into /tmp/cert.crt and the second into ++// /tmp/intermediate.crt ++// Note: depending on what version of openssl you are using, you may need to use the key=value ++// form for the header argument (i.e. -header host=ocsp.pki.goog) ++// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.pki.goog/gts1c3 -header host ocsp.pki.goog -resp_text -respout /tmp/ocsp.der ++// Then hex encode the result: ++// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")' ++ ++const ocspResponseHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba308201b630819fa21604148a747faf85cdee95cd3d9cd0e24614f371351d27180f32303231313130373134323535335a30743072304a300906052b0e03021a05000414c72e798addff6134b3baed4742b8bbc6c024076304148a747faf85cdee95cd3d9cd0e24614f371351d27021100f374542e3c7a68360a000000011034628000180f32303231313130373134323535315aa011180f32303231313131343133323535305a300d06092a864886f70d01010b0500038201010087749296e681abe36f2efef047730178ce57e948426959ac62ac5f25b9a63ba3b7f31b9f683aea384d21845c8dda09498f2531c78f3add3969ca4092f31f58ac3c2613719d63b7b9a5260e52814c827f8dd44f4f753b2528bcd03ccec02cdcd4918247f5323f8cfc12cee4ac8f0361587b267019cfd12336db09b04eac59807a480213cfcd9913a3aa2d13a6c88c0a750475a0e991806d94ec0fc9dab599171a43a08e6d935b4a4a13dff9c4a97ad46cef6fb4d61cb2363d788c12d81cce851b478889c2e05d80cd00ae346772a1e7502f011e2ed9be8ef4b194c8b65d6e33671d878cfb30267972075b062ff3d56b51984bf685161afc6e2538dd6e6a23063c" ++ ++const GTSRoot = `-----BEGIN CERTIFICATE----- ++MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw ++CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU ++MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw ++MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp ++Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD ++ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp ++kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX ++lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm ++BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA ++gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL ++tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud ++DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T ++AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD ++VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG ++CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw ++AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt ++MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG ++A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br ++aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN ++AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ ++cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL ++RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U +++o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr ++PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER ++lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs ++Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO ++z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG ++AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw ++juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl ++1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd ++-----END CERTIFICATE-----` ++ ++const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + ++ "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + ++ "3029060355040b1322536563757265204469676974616c20436572746966696361746520" + ++ "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" + ++ "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" + ++ "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" + ++ "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" + ++ "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" + ++ "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" + ++ "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" + ++ "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" + ++ "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" + ++ "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" + ++ "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" + ++ "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" + ++ "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" + ++ "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" + ++ "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" + ++ "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" + ++ "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" + ++ "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" + ++ "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" + ++ "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" + ++ "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" + ++ "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" + ++ "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" + ++ "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" + ++ "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" + ++ "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" + ++ "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" + ++ "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" + ++ "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" + ++ "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" + ++ "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" + ++ "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" + ++ "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" + ++ "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" + ++ "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" + ++ "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" + ++ "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" + ++ "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" + ++ "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" + ++ "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" + ++ "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" + ++ "d2ae83a7a8ce5ba7" ++ ++const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" + ++ "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" + ++ "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" + ++ "456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" + ++ "1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" + ++ "5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" + ++ "82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" + ++ "5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" + ++ "8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" + ++ "6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" + ++ "0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" + ++ "9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" + ++ "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" + ++ "5a35fca2e054dfa8" ++ ++// PKIX nonce extension ++var ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2} ++var ocspExtensionValueHex = "0403000000" ++ ++const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" + ++ "dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + ++ "0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" + ++ "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + ++ "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + ++ "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + ++ "3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" + ++ "03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" + ++ "911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" + ++ "5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" + ++ "e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" + ++ "b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" + ++ "eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" + ++ "a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" + ++ "28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" + ++ "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + ++ "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + ++ "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + ++ "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + ++ "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + ++ "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + ++ "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + ++ "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + ++ "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + ++ "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + ++ "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + ++ "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + ++ "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + ++ "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + ++ "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + ++ "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + ++ "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + ++ "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + ++ "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + ++ "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + ++ "3a25439a94299a65a709756c7a3e568be049d5c38839" ++ ++const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" + ++ "d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + ++ "0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" + ++ "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + ++ "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + ++ "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + ++ "3130303730373138333531375aa1163014301206092b0601050507300102040504030000" + ++ "00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" + ++ "9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" + ++ "779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" + ++ "9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" + ++ "d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" + ++ "b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" + ++ "7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" + ++ "f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" + ++ "e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" + ++ "550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" + ++ "170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" + ++ "706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" + ++ "010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" + ++ "56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" + ++ "70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" + ++ "a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" + ++ "3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" + ++ "04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" + ++ "9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" + ++ "920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" + ++ "551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" + ++ "864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" + ++ "d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" + ++ "aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" + ++ "2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" + ++ "e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" + ++ "d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" + ++ "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" + ++ "9a94299a65a709756c7a3e568be049d5c38839" ++ ++const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + ++ "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + ++ "bcbb235d44ccc7dba62e72" ++ ++const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" + ++ "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" + ++ "7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" + ++ "333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" + ++ "766572204341202d20436c617373203331493047060355040b13407777772e7665726973" + ++ "69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" + ++ "204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" + ++ "170d3133313233313233353935395a3068310b3009060355040613025553311330110603" + ++ "550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" + ++ "173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" + ++ "2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" + ++ "818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" + ++ "23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" + ++ "5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" + ++ "c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" + ++ "82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" + ++ "01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" + ++ "7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" + ++ "2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" + ++ "726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" + ++ "03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" + ++ "30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" + ++ "20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" + ++ "092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" + ++ "81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" + ++ "67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" + ++ "9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817" ++ ++const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" + ++ "864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" + ++ "566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" + ++ "6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" + ++ "1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" + ++ "301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" + ++ "0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" + ++ "69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" + ++ "3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" + ++ "6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" + ++ "5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" + ++ "e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" + ++ "bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" + ++ "3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" + ++ "f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" + ++ "0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" + ++ "2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" + ++ "636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" + ++ "030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" + ++ "0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" + ++ "a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" + ++ "300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" + ++ "adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" + ++ "f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" + ++ "e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" + ++ "d68071" ++ ++// Key and certificate for the OCSP responder were not taken from the Thawte ++// responder, since CreateResponse requires that we have the private key. ++// Instead, they were generated randomly. ++const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" + ++ "1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" + ++ "1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" + ++ "fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" + ++ "c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" + ++ "7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" + ++ "1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" + ++ "6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" + ++ "72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" + ++ "56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" + ++ "575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" + ++ "679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" + ++ "05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" + ++ "5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" + ++ "1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" + ++ "ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" + ++ "daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" + ++ "e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" + ++ "07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" + ++ "87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" + ++ "327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" + ++ "497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" + ++ "6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" + ++ "4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" + ++ "7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" + ++ "0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" + ++ "d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" + ++ "c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" + ++ "c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" + ++ "0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" + ++ "120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" + ++ "45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" + ++ "48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" + ++ "6bdaa059" ++ ++const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + ++ "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + ++ "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + ++ "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + ++ "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + ++ "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + ++ "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + ++ "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + ++ "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + ++ "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + ++ "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + ++ "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + ++ "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + ++ "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + ++ "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + ++ "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + ++ "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + ++ "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + ++ "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + ++ "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + ++ "3a25439a94299a65a709756c7a3e568be049d5c38839" ++ ++const errorResponseHex = "30030a0101" +diff --git a/ms_mod/golang.org/x/crypto/openpgp/armor/armor.go b/ms_mod/golang.org/x/crypto/openpgp/armor/armor.go +new file mode 100644 +index 00000000000000..8907183ec0ab9c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/armor/armor.go +@@ -0,0 +1,232 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is ++// very similar to PEM except that it has an additional CRC checksum. ++// ++// Deprecated: this package is unmaintained except for security fixes. New ++// applications should consider a more focused, modern alternative to OpenPGP ++// for their specific task. If you are required to interoperate with OpenPGP ++// systems and need a maintained package, consider a community fork. ++// See https://golang.org/issue/44226. ++package armor // import "golang.org/x/crypto/openpgp/armor" ++ ++import ( ++ "bufio" ++ "bytes" ++ "encoding/base64" ++ "golang.org/x/crypto/openpgp/errors" ++ "io" ++) ++ ++// A Block represents an OpenPGP armored structure. ++// ++// The encoded form is: ++// ++// -----BEGIN Type----- ++// Headers ++// ++// base64-encoded Bytes ++// '=' base64 encoded checksum ++// -----END Type----- ++// ++// where Headers is a possibly empty sequence of Key: Value lines. ++// ++// Since the armored data can be very large, this package presents a streaming ++// interface. ++type Block struct { ++ Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). ++ Header map[string]string // Optional headers. ++ Body io.Reader // A Reader from which the contents can be read ++ lReader lineReader ++ oReader openpgpReader ++} ++ ++var ArmorCorrupt error = errors.StructuralError("armor invalid") ++ ++const crc24Init = 0xb704ce ++const crc24Poly = 0x1864cfb ++const crc24Mask = 0xffffff ++ ++// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 ++func crc24(crc uint32, d []byte) uint32 { ++ for _, b := range d { ++ crc ^= uint32(b) << 16 ++ for i := 0; i < 8; i++ { ++ crc <<= 1 ++ if crc&0x1000000 != 0 { ++ crc ^= crc24Poly ++ } ++ } ++ } ++ return crc ++} ++ ++var armorStart = []byte("-----BEGIN ") ++var armorEnd = []byte("-----END ") ++var armorEndOfLine = []byte("-----") ++ ++// lineReader wraps a line based reader. It watches for the end of an armor ++// block and records the expected CRC value. ++type lineReader struct { ++ in *bufio.Reader ++ buf []byte ++ eof bool ++ crc uint32 ++ crcSet bool ++} ++ ++func (l *lineReader) Read(p []byte) (n int, err error) { ++ if l.eof { ++ return 0, io.EOF ++ } ++ ++ if len(l.buf) > 0 { ++ n = copy(p, l.buf) ++ l.buf = l.buf[n:] ++ return ++ } ++ ++ line, isPrefix, err := l.in.ReadLine() ++ if err != nil { ++ return ++ } ++ if isPrefix { ++ return 0, ArmorCorrupt ++ } ++ ++ if bytes.HasPrefix(line, armorEnd) { ++ l.eof = true ++ return 0, io.EOF ++ } ++ ++ if len(line) == 5 && line[0] == '=' { ++ // This is the checksum line ++ var expectedBytes [3]byte ++ var m int ++ m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) ++ if m != 3 || err != nil { ++ return ++ } ++ l.crc = uint32(expectedBytes[0])<<16 | ++ uint32(expectedBytes[1])<<8 | ++ uint32(expectedBytes[2]) ++ ++ line, _, err = l.in.ReadLine() ++ if err != nil && err != io.EOF { ++ return ++ } ++ if !bytes.HasPrefix(line, armorEnd) { ++ return 0, ArmorCorrupt ++ } ++ ++ l.eof = true ++ l.crcSet = true ++ return 0, io.EOF ++ } ++ ++ if len(line) > 96 { ++ return 0, ArmorCorrupt ++ } ++ ++ n = copy(p, line) ++ bytesToSave := len(line) - n ++ if bytesToSave > 0 { ++ if cap(l.buf) < bytesToSave { ++ l.buf = make([]byte, 0, bytesToSave) ++ } ++ l.buf = l.buf[0:bytesToSave] ++ copy(l.buf, line[n:]) ++ } ++ ++ return ++} ++ ++// openpgpReader passes Read calls to the underlying base64 decoder, but keeps ++// a running CRC of the resulting data and checks the CRC against the value ++// found by the lineReader at EOF. ++type openpgpReader struct { ++ lReader *lineReader ++ b64Reader io.Reader ++ currentCRC uint32 ++} ++ ++func (r *openpgpReader) Read(p []byte) (n int, err error) { ++ n, err = r.b64Reader.Read(p) ++ r.currentCRC = crc24(r.currentCRC, p[:n]) ++ ++ if err == io.EOF && r.lReader.crcSet && r.lReader.crc != r.currentCRC&crc24Mask { ++ return 0, ArmorCorrupt ++ } ++ ++ return ++} ++ ++// Decode reads a PGP armored block from the given Reader. It will ignore ++// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The ++// given Reader is not usable after calling this function: an arbitrary amount ++// of data may have been read past the end of the block. ++func Decode(in io.Reader) (p *Block, err error) { ++ r := bufio.NewReaderSize(in, 100) ++ var line []byte ++ ignoreNext := false ++ ++TryNextBlock: ++ p = nil ++ ++ // Skip leading garbage ++ for { ++ ignoreThis := ignoreNext ++ line, ignoreNext, err = r.ReadLine() ++ if err != nil { ++ return ++ } ++ if ignoreNext || ignoreThis { ++ continue ++ } ++ line = bytes.TrimSpace(line) ++ if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { ++ break ++ } ++ } ++ ++ p = new(Block) ++ p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) ++ p.Header = make(map[string]string) ++ nextIsContinuation := false ++ var lastKey string ++ ++ // Read headers ++ for { ++ isContinuation := nextIsContinuation ++ line, nextIsContinuation, err = r.ReadLine() ++ if err != nil { ++ p = nil ++ return ++ } ++ if isContinuation { ++ p.Header[lastKey] += string(line) ++ continue ++ } ++ line = bytes.TrimSpace(line) ++ if len(line) == 0 { ++ break ++ } ++ ++ i := bytes.Index(line, []byte(": ")) ++ if i == -1 { ++ goto TryNextBlock ++ } ++ lastKey = string(line[:i]) ++ p.Header[lastKey] = string(line[i+2:]) ++ } ++ ++ p.lReader.in = r ++ p.oReader.currentCRC = crc24Init ++ p.oReader.lReader = &p.lReader ++ p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) ++ p.Body = &p.oReader ++ ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go b/ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go +new file mode 100644 +index 00000000000000..c05af95fdec6d4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go +@@ -0,0 +1,95 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package armor ++ ++import ( ++ "bytes" ++ "hash/adler32" ++ "io" ++ "testing" ++) ++ ++func TestDecodeEncode(t *testing.T) { ++ buf := bytes.NewBuffer([]byte(armorExample1)) ++ result, err := Decode(buf) ++ if err != nil { ++ t.Error(err) ++ } ++ expectedType := "PGP SIGNATURE" ++ if result.Type != expectedType { ++ t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType) ++ } ++ if len(result.Header) != 1 { ++ t.Errorf("len(result.Header): got:%d want:1", len(result.Header)) ++ } ++ v, ok := result.Header["Version"] ++ if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" { ++ t.Errorf("result.Header: got:%#v", result.Header) ++ } ++ ++ contents, err := io.ReadAll(result.Body) ++ if err != nil { ++ t.Error(err) ++ } ++ ++ if adler32.Checksum(contents) != 0x27b144be { ++ t.Errorf("contents: got: %x", contents) ++ } ++ ++ buf = bytes.NewBuffer(nil) ++ w, err := Encode(buf, result.Type, result.Header) ++ if err != nil { ++ t.Error(err) ++ } ++ _, err = w.Write(contents) ++ if err != nil { ++ t.Error(err) ++ } ++ w.Close() ++ ++ if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) { ++ t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1) ++ } ++} ++ ++func TestLongHeader(t *testing.T) { ++ buf := bytes.NewBuffer([]byte(armorLongLine)) ++ result, err := Decode(buf) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ value, ok := result.Header["Version"] ++ if !ok { ++ t.Errorf("missing Version header") ++ } ++ if value != longValueExpected { ++ t.Errorf("got: %s want: %s", value, longValueExpected) ++ } ++} ++ ++const armorExample1 = `-----BEGIN PGP SIGNATURE----- ++Version: GnuPG v1.4.10 (GNU/Linux) ++ ++iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm ++4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt ++p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW ++TxRjs+fJCIFuo71xb1g= ++=/teI ++-----END PGP SIGNATURE-----` ++ ++const armorLongLine = `-----BEGIN PGP SIGNATURE----- ++Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz ++ ++iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8 ++kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp ++cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA ++byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3 ++WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv ++okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4= ++=wfQG ++-----END PGP SIGNATURE-----` ++ ++const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" +diff --git a/ms_mod/golang.org/x/crypto/openpgp/armor/encode.go b/ms_mod/golang.org/x/crypto/openpgp/armor/encode.go +new file mode 100644 +index 00000000000000..5b6e16c19d5239 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/armor/encode.go +@@ -0,0 +1,161 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package armor ++ ++import ( ++ "encoding/base64" ++ "io" ++) ++ ++var armorHeaderSep = []byte(": ") ++var blockEnd = []byte("\n=") ++var newline = []byte("\n") ++var armorEndOfLineOut = []byte("-----\n") ++ ++// writeSlices writes its arguments to the given Writer. ++func writeSlices(out io.Writer, slices ...[]byte) (err error) { ++ for _, s := range slices { ++ _, err = out.Write(s) ++ if err != nil { ++ return err ++ } ++ } ++ return ++} ++ ++// lineBreaker breaks data across several lines, all of the same byte length ++// (except possibly the last). Lines are broken with a single '\n'. ++type lineBreaker struct { ++ lineLength int ++ line []byte ++ used int ++ out io.Writer ++ haveWritten bool ++} ++ ++func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { ++ return &lineBreaker{ ++ lineLength: lineLength, ++ line: make([]byte, lineLength), ++ used: 0, ++ out: out, ++ } ++} ++ ++func (l *lineBreaker) Write(b []byte) (n int, err error) { ++ n = len(b) ++ ++ if n == 0 { ++ return ++ } ++ ++ if l.used == 0 && l.haveWritten { ++ _, err = l.out.Write([]byte{'\n'}) ++ if err != nil { ++ return ++ } ++ } ++ ++ if l.used+len(b) < l.lineLength { ++ l.used += copy(l.line[l.used:], b) ++ return ++ } ++ ++ l.haveWritten = true ++ _, err = l.out.Write(l.line[0:l.used]) ++ if err != nil { ++ return ++ } ++ excess := l.lineLength - l.used ++ l.used = 0 ++ ++ _, err = l.out.Write(b[0:excess]) ++ if err != nil { ++ return ++ } ++ ++ _, err = l.Write(b[excess:]) ++ return ++} ++ ++func (l *lineBreaker) Close() (err error) { ++ if l.used > 0 { ++ _, err = l.out.Write(l.line[0:l.used]) ++ if err != nil { ++ return ++ } ++ } ++ ++ return ++} ++ ++// encoding keeps track of a running CRC24 over the data which has been written ++// to it and outputs a OpenPGP checksum when closed, followed by an armor ++// trailer. ++// ++// It's built into a stack of io.Writers: ++// ++// encoding -> base64 encoder -> lineBreaker -> out ++type encoding struct { ++ out io.Writer ++ breaker *lineBreaker ++ b64 io.WriteCloser ++ crc uint32 ++ blockType []byte ++} ++ ++func (e *encoding) Write(data []byte) (n int, err error) { ++ e.crc = crc24(e.crc, data) ++ return e.b64.Write(data) ++} ++ ++func (e *encoding) Close() (err error) { ++ err = e.b64.Close() ++ if err != nil { ++ return ++ } ++ e.breaker.Close() ++ ++ var checksumBytes [3]byte ++ checksumBytes[0] = byte(e.crc >> 16) ++ checksumBytes[1] = byte(e.crc >> 8) ++ checksumBytes[2] = byte(e.crc) ++ ++ var b64ChecksumBytes [4]byte ++ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) ++ ++ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) ++} ++ ++// Encode returns a WriteCloser which will encode the data written to it in ++// OpenPGP armor. ++func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { ++ bType := []byte(blockType) ++ err = writeSlices(out, armorStart, bType, armorEndOfLineOut) ++ if err != nil { ++ return ++ } ++ ++ for k, v := range headers { ++ err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) ++ if err != nil { ++ return ++ } ++ } ++ ++ _, err = out.Write(newline) ++ if err != nil { ++ return ++ } ++ ++ e := &encoding{ ++ out: out, ++ breaker: newLineBreaker(out, 64), ++ crc: crc24Init, ++ blockType: bType, ++ } ++ e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) ++ return e, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/canonical_text.go b/ms_mod/golang.org/x/crypto/openpgp/canonical_text.go +new file mode 100644 +index 00000000000000..e601e389f1299c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/canonical_text.go +@@ -0,0 +1,59 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package openpgp ++ ++import "hash" ++ ++// NewCanonicalTextHash reformats text written to it into the canonical ++// form and then applies the hash h. See RFC 4880, section 5.2.1. ++func NewCanonicalTextHash(h hash.Hash) hash.Hash { ++ return &canonicalTextHash{h, 0} ++} ++ ++type canonicalTextHash struct { ++ h hash.Hash ++ s int ++} ++ ++var newline = []byte{'\r', '\n'} ++ ++func (cth *canonicalTextHash) Write(buf []byte) (int, error) { ++ start := 0 ++ ++ for i, c := range buf { ++ switch cth.s { ++ case 0: ++ if c == '\r' { ++ cth.s = 1 ++ } else if c == '\n' { ++ cth.h.Write(buf[start:i]) ++ cth.h.Write(newline) ++ start = i + 1 ++ } ++ case 1: ++ cth.s = 0 ++ } ++ } ++ ++ cth.h.Write(buf[start:]) ++ return len(buf), nil ++} ++ ++func (cth *canonicalTextHash) Sum(in []byte) []byte { ++ return cth.h.Sum(in) ++} ++ ++func (cth *canonicalTextHash) Reset() { ++ cth.h.Reset() ++ cth.s = 0 ++} ++ ++func (cth *canonicalTextHash) Size() int { ++ return cth.h.Size() ++} ++ ++func (cth *canonicalTextHash) BlockSize() int { ++ return cth.h.BlockSize() ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go b/ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go +new file mode 100644 +index 00000000000000..8f3ba2a8814ea9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go +@@ -0,0 +1,52 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package openpgp ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++type recordingHash struct { ++ buf *bytes.Buffer ++} ++ ++func (r recordingHash) Write(b []byte) (n int, err error) { ++ return r.buf.Write(b) ++} ++ ++func (r recordingHash) Sum(in []byte) []byte { ++ return append(in, r.buf.Bytes()...) ++} ++ ++func (r recordingHash) Reset() { ++ panic("shouldn't be called") ++} ++ ++func (r recordingHash) Size() int { ++ panic("shouldn't be called") ++} ++ ++func (r recordingHash) BlockSize() int { ++ panic("shouldn't be called") ++} ++ ++func testCanonicalText(t *testing.T, input, expected string) { ++ r := recordingHash{bytes.NewBuffer(nil)} ++ c := NewCanonicalTextHash(r) ++ c.Write([]byte(input)) ++ result := c.Sum(nil) ++ if expected != string(result) { ++ t.Errorf("input: %x got: %x want: %x", input, result, expected) ++ } ++} ++ ++func TestCanonicalText(t *testing.T) { ++ testCanonicalText(t, "foo\n", "foo\r\n") ++ testCanonicalText(t, "foo", "foo") ++ testCanonicalText(t, "foo\r\n", "foo\r\n") ++ testCanonicalText(t, "foo\r\nbar", "foo\r\nbar") ++ testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n") ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go +new file mode 100644 +index 00000000000000..644b2e078bc9c8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go +@@ -0,0 +1,424 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package clearsign generates and processes OpenPGP, clear-signed data. See ++// RFC 4880, section 7. ++// ++// Clearsigned messages are cryptographically signed, but the contents of the ++// message are kept in plaintext so that it can be read without special tools. ++// ++// Deprecated: this package is unmaintained except for security fixes. New ++// applications should consider a more focused, modern alternative to OpenPGP ++// for their specific task. If you are required to interoperate with OpenPGP ++// systems and need a maintained package, consider a community fork. ++// See https://golang.org/issue/44226. ++package clearsign // import "golang.org/x/crypto/openpgp/clearsign" ++ ++import ( ++ "bufio" ++ "bytes" ++ "crypto" ++ "fmt" ++ "hash" ++ "io" ++ "net/textproto" ++ "strconv" ++ "strings" ++ ++ "golang.org/x/crypto/openpgp/armor" ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/packet" ++) ++ ++// A Block represents a clearsigned message. A signature on a Block can ++// be checked by passing Bytes into openpgp.CheckDetachedSignature. ++type Block struct { ++ Headers textproto.MIMEHeader // Optional unverified Hash headers ++ Plaintext []byte // The original message text ++ Bytes []byte // The signed message ++ ArmoredSignature *armor.Block // The signature block ++} ++ ++// start is the marker which denotes the beginning of a clearsigned message. ++var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----") ++ ++// dashEscape is prefixed to any lines that begin with a hyphen so that they ++// can't be confused with endText. ++var dashEscape = []byte("- ") ++ ++// endText is a marker which denotes the end of the message and the start of ++// an armored signature. ++var endText = []byte("-----BEGIN PGP SIGNATURE-----") ++ ++// end is a marker which denotes the end of the armored signature. ++var end = []byte("\n-----END PGP SIGNATURE-----") ++ ++var crlf = []byte("\r\n") ++var lf = byte('\n') ++ ++// getLine returns the first \r\n or \n delineated line from the given byte ++// array. The line does not include the \r\n or \n. The remainder of the byte ++// array (also not including the new line bytes) is also returned and this will ++// always be smaller than the original argument. ++func getLine(data []byte) (line, rest []byte) { ++ i := bytes.Index(data, []byte{'\n'}) ++ var j int ++ if i < 0 { ++ i = len(data) ++ j = i ++ } else { ++ j = i + 1 ++ if i > 0 && data[i-1] == '\r' { ++ i-- ++ } ++ } ++ return data[0:i], data[j:] ++} ++ ++// Decode finds the first clearsigned message in data and returns it, as well as ++// the suffix of data which remains after the message. Any prefix data is ++// discarded. ++// ++// If no message is found, or if the message is invalid, Decode returns nil and ++// the whole data slice. The only allowed header type is Hash, and it is not ++// verified against the signature hash. ++func Decode(data []byte) (b *Block, rest []byte) { ++ // start begins with a newline. However, at the very beginning of ++ // the byte array, we'll accept the start string without it. ++ rest = data ++ if bytes.HasPrefix(data, start[1:]) { ++ rest = rest[len(start)-1:] ++ } else if i := bytes.Index(data, start); i >= 0 { ++ rest = rest[i+len(start):] ++ } else { ++ return nil, data ++ } ++ ++ // Consume the start line and check it does not have a suffix. ++ suffix, rest := getLine(rest) ++ if len(suffix) != 0 { ++ return nil, data ++ } ++ ++ var line []byte ++ b = &Block{ ++ Headers: make(textproto.MIMEHeader), ++ } ++ ++ // Next come a series of header lines. ++ for { ++ // This loop terminates because getLine's second result is ++ // always smaller than its argument. ++ if len(rest) == 0 { ++ return nil, data ++ } ++ // An empty line marks the end of the headers. ++ if line, rest = getLine(rest); len(line) == 0 { ++ break ++ } ++ ++ // Reject headers with control or Unicode characters. ++ if i := bytes.IndexFunc(line, func(r rune) bool { ++ return r < 0x20 || r > 0x7e ++ }); i != -1 { ++ return nil, data ++ } ++ ++ i := bytes.Index(line, []byte{':'}) ++ if i == -1 { ++ return nil, data ++ } ++ ++ key, val := string(line[0:i]), string(line[i+1:]) ++ key = strings.TrimSpace(key) ++ if key != "Hash" { ++ return nil, data ++ } ++ val = strings.TrimSpace(val) ++ b.Headers.Add(key, val) ++ } ++ ++ firstLine := true ++ for { ++ start := rest ++ ++ line, rest = getLine(rest) ++ if len(line) == 0 && len(rest) == 0 { ++ // No armored data was found, so this isn't a complete message. ++ return nil, data ++ } ++ if bytes.Equal(line, endText) { ++ // Back up to the start of the line because armor expects to see the ++ // header line. ++ rest = start ++ break ++ } ++ ++ // The final CRLF isn't included in the hash so we don't write it until ++ // we've seen the next line. ++ if firstLine { ++ firstLine = false ++ } else { ++ b.Bytes = append(b.Bytes, crlf...) ++ } ++ ++ if bytes.HasPrefix(line, dashEscape) { ++ line = line[2:] ++ } ++ line = bytes.TrimRight(line, " \t") ++ b.Bytes = append(b.Bytes, line...) ++ ++ b.Plaintext = append(b.Plaintext, line...) ++ b.Plaintext = append(b.Plaintext, lf) ++ } ++ ++ // We want to find the extent of the armored data (including any newlines at ++ // the end). ++ i := bytes.Index(rest, end) ++ if i == -1 { ++ return nil, data ++ } ++ i += len(end) ++ for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { ++ i++ ++ } ++ armored := rest[:i] ++ rest = rest[i:] ++ ++ var err error ++ b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) ++ if err != nil { ++ return nil, data ++ } ++ ++ return b, rest ++} ++ ++// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed ++// message. The clear-signed message is written to buffered and a hash, suitable ++// for signing, is maintained in h. ++// ++// When closed, an armored signature is created and written to complete the ++// message. ++type dashEscaper struct { ++ buffered *bufio.Writer ++ hashers []hash.Hash // one per key in privateKeys ++ hashType crypto.Hash ++ toHash io.Writer // writes to all the hashes in hashers ++ ++ atBeginningOfLine bool ++ isFirstLine bool ++ ++ whitespace []byte ++ byteBuf []byte // a one byte buffer to save allocations ++ ++ privateKeys []*packet.PrivateKey ++ config *packet.Config ++} ++ ++func (d *dashEscaper) Write(data []byte) (n int, err error) { ++ for _, b := range data { ++ d.byteBuf[0] = b ++ ++ if d.atBeginningOfLine { ++ // The final CRLF isn't included in the hash so we have to wait ++ // until this point (the start of the next line) before writing it. ++ if !d.isFirstLine { ++ d.toHash.Write(crlf) ++ } ++ d.isFirstLine = false ++ } ++ ++ // Any whitespace at the end of the line has to be removed so we ++ // buffer it until we find out whether there's more on this line. ++ if b == ' ' || b == '\t' || b == '\r' { ++ d.whitespace = append(d.whitespace, b) ++ d.atBeginningOfLine = false ++ continue ++ } ++ ++ if d.atBeginningOfLine { ++ // At the beginning of a line, hyphens have to be escaped. ++ if b == '-' { ++ // The signature isn't calculated over the dash-escaped text so ++ // the escape is only written to buffered. ++ if _, err = d.buffered.Write(dashEscape); err != nil { ++ return ++ } ++ d.toHash.Write(d.byteBuf) ++ d.atBeginningOfLine = false ++ } else if b == '\n' { ++ // Nothing to do because we delay writing CRLF to the hash. ++ } else { ++ d.toHash.Write(d.byteBuf) ++ d.atBeginningOfLine = false ++ } ++ if err = d.buffered.WriteByte(b); err != nil { ++ return ++ } ++ } else { ++ if b == '\n' { ++ // We got a raw \n. Drop any trailing whitespace and write a ++ // CRLF. ++ d.whitespace = d.whitespace[:0] ++ // We delay writing CRLF to the hash until the start of the ++ // next line. ++ if err = d.buffered.WriteByte(b); err != nil { ++ return ++ } ++ d.atBeginningOfLine = true ++ } else { ++ // Any buffered whitespace wasn't at the end of the line so ++ // we need to write it out. ++ if len(d.whitespace) > 0 { ++ d.toHash.Write(d.whitespace) ++ if _, err = d.buffered.Write(d.whitespace); err != nil { ++ return ++ } ++ d.whitespace = d.whitespace[:0] ++ } ++ d.toHash.Write(d.byteBuf) ++ if err = d.buffered.WriteByte(b); err != nil { ++ return ++ } ++ } ++ } ++ } ++ ++ n = len(data) ++ return ++} ++ ++func (d *dashEscaper) Close() (err error) { ++ if !d.atBeginningOfLine { ++ if err = d.buffered.WriteByte(lf); err != nil { ++ return ++ } ++ } ++ ++ out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil) ++ if err != nil { ++ return ++ } ++ ++ t := d.config.Now() ++ for i, k := range d.privateKeys { ++ sig := new(packet.Signature) ++ sig.SigType = packet.SigTypeText ++ sig.PubKeyAlgo = k.PubKeyAlgo ++ sig.Hash = d.hashType ++ sig.CreationTime = t ++ sig.IssuerKeyId = &k.KeyId ++ ++ if err = sig.Sign(d.hashers[i], k, d.config); err != nil { ++ return ++ } ++ if err = sig.Serialize(out); err != nil { ++ return ++ } ++ } ++ ++ if err = out.Close(); err != nil { ++ return ++ } ++ if err = d.buffered.Flush(); err != nil { ++ return ++ } ++ return ++} ++ ++// Encode returns a WriteCloser which will clear-sign a message with privateKey ++// and write it to w. If config is nil, sensible defaults are used. ++func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { ++ return EncodeMulti(w, []*packet.PrivateKey{privateKey}, config) ++} ++ ++// EncodeMulti returns a WriteCloser which will clear-sign a message with all the ++// private keys indicated and write it to w. If config is nil, sensible defaults ++// are used. ++func EncodeMulti(w io.Writer, privateKeys []*packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { ++ for _, k := range privateKeys { ++ if k.Encrypted { ++ return nil, errors.InvalidArgumentError(fmt.Sprintf("signing key %s is encrypted", k.KeyIdString())) ++ } ++ } ++ ++ hashType := config.Hash() ++ name := nameOfHash(hashType) ++ if len(name) == 0 { ++ return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType))) ++ } ++ ++ if !hashType.Available() { ++ return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType))) ++ } ++ var hashers []hash.Hash ++ var ws []io.Writer ++ for range privateKeys { ++ h := hashType.New() ++ hashers = append(hashers, h) ++ ws = append(ws, h) ++ } ++ toHash := io.MultiWriter(ws...) ++ ++ buffered := bufio.NewWriter(w) ++ // start has a \n at the beginning that we don't want here. ++ if _, err = buffered.Write(start[1:]); err != nil { ++ return ++ } ++ if err = buffered.WriteByte(lf); err != nil { ++ return ++ } ++ if _, err = buffered.WriteString("Hash: "); err != nil { ++ return ++ } ++ if _, err = buffered.WriteString(name); err != nil { ++ return ++ } ++ if err = buffered.WriteByte(lf); err != nil { ++ return ++ } ++ if err = buffered.WriteByte(lf); err != nil { ++ return ++ } ++ ++ plaintext = &dashEscaper{ ++ buffered: buffered, ++ hashers: hashers, ++ hashType: hashType, ++ toHash: toHash, ++ ++ atBeginningOfLine: true, ++ isFirstLine: true, ++ ++ byteBuf: make([]byte, 1), ++ ++ privateKeys: privateKeys, ++ config: config, ++ } ++ ++ return ++} ++ ++// nameOfHash returns the OpenPGP name for the given hash, or the empty string ++// if the name isn't known. See RFC 4880, section 9.4. ++func nameOfHash(h crypto.Hash) string { ++ switch h { ++ case crypto.MD5: ++ return "MD5" ++ case crypto.SHA1: ++ return "SHA1" ++ case crypto.RIPEMD160: ++ return "RIPEMD160" ++ case crypto.SHA224: ++ return "SHA224" ++ case crypto.SHA256: ++ return "SHA256" ++ case crypto.SHA384: ++ return "SHA384" ++ case crypto.SHA512: ++ return "SHA512" ++ } ++ return "" ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go +new file mode 100644 +index 00000000000000..051b8f16ffa3b4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go +@@ -0,0 +1,398 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package clearsign ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "testing" ++ ++ "golang.org/x/crypto/openpgp" ++ "golang.org/x/crypto/openpgp/packet" ++) ++ ++func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) { ++ b, rest := Decode(input) ++ if b == nil { ++ t.Fatal("failed to decode clearsign message") ++ } ++ if !bytes.Equal(rest, []byte("trailing")) { ++ t.Errorf("unexpected remaining bytes returned: %s", string(rest)) ++ } ++ if b.ArmoredSignature.Type != "PGP SIGNATURE" { ++ t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type) ++ } ++ if !bytes.Equal(b.Bytes, []byte(expected)) { ++ t.Errorf("bad body, got:%x want:%x", b.Bytes, expected) ++ } ++ ++ if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) { ++ t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext) ++ } ++ ++ keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) ++ if err != nil { ++ t.Errorf("failed to parse public key: %s", err) ++ } ++ ++ if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { ++ t.Errorf("failed to check signature: %s", err) ++ } ++} ++ ++func TestParse(t *testing.T) { ++ testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n") ++ testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n") ++} ++ ++func TestParseWithNoNewlineAtEnd(t *testing.T) { ++ input := clearsignInput ++ input = input[:len(input)-len("trailing")-1] ++ b, rest := Decode(input) ++ if b == nil { ++ t.Fatal("failed to decode clearsign message") ++ } ++ if len(rest) > 0 { ++ t.Errorf("unexpected remaining bytes returned: %s", string(rest)) ++ } ++} ++ ++var signingTests = []struct { ++ in, signed, plaintext string ++}{ ++ {"", "", ""}, ++ {"a", "a", "a\n"}, ++ {"a\n", "a", "a\n"}, ++ {"-a\n", "-a", "-a\n"}, ++ {"--a\nb", "--a\r\nb", "--a\nb\n"}, ++ // leading whitespace ++ {" a\n", " a", " a\n"}, ++ {" a\n", " a", " a\n"}, ++ // trailing whitespace (should be stripped) ++ {"a \n", "a", "a\n"}, ++ {"a ", "a", "a\n"}, ++ // whitespace-only lines (should be stripped) ++ {" \n", "", "\n"}, ++ {" ", "", "\n"}, ++ {"a\n \n \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"}, ++} ++ ++func TestSigning(t *testing.T) { ++ keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) ++ if err != nil { ++ t.Errorf("failed to parse public key: %s", err) ++ } ++ ++ for i, test := range signingTests { ++ var buf bytes.Buffer ++ ++ plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil) ++ if err != nil { ++ t.Errorf("#%d: error from Encode: %s", i, err) ++ continue ++ } ++ if _, err := plaintext.Write([]byte(test.in)); err != nil { ++ t.Errorf("#%d: error from Write: %s", i, err) ++ continue ++ } ++ if err := plaintext.Close(); err != nil { ++ t.Fatalf("#%d: error from Close: %s", i, err) ++ continue ++ } ++ ++ b, _ := Decode(buf.Bytes()) ++ if b == nil { ++ t.Errorf("#%d: failed to decode clearsign message", i) ++ continue ++ } ++ if !bytes.Equal(b.Bytes, []byte(test.signed)) { ++ t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed) ++ continue ++ } ++ if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) { ++ t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext) ++ continue ++ } ++ ++ if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { ++ t.Errorf("#%d: failed to check signature: %s", i, err) ++ } ++ } ++} ++ ++// We use this to make test keys, so that they aren't all the same. ++type quickRand byte ++ ++func (qr *quickRand) Read(p []byte) (int, error) { ++ for i := range p { ++ p[i] = byte(*qr) ++ } ++ *qr++ ++ return len(p), nil ++} ++ ++func TestMultiSign(t *testing.T) { ++ if testing.Short() { ++ t.Skip("skipping long test in -short mode") ++ } ++ ++ zero := quickRand(0) ++ config := packet.Config{Rand: &zero} ++ ++ for nKeys := 0; nKeys < 4; nKeys++ { ++ nextTest: ++ for nExtra := 0; nExtra < 4; nExtra++ { ++ var signKeys []*packet.PrivateKey ++ var verifyKeys openpgp.EntityList ++ ++ desc := fmt.Sprintf("%d keys; %d of which will be used to verify", nKeys+nExtra, nKeys) ++ for i := 0; i < nKeys+nExtra; i++ { ++ e, err := openpgp.NewEntity("name", "comment", "email", &config) ++ if err != nil { ++ t.Errorf("cannot create key: %v", err) ++ continue nextTest ++ } ++ if i < nKeys { ++ verifyKeys = append(verifyKeys, e) ++ } ++ signKeys = append(signKeys, e.PrivateKey) ++ } ++ ++ input := []byte("this is random text\r\n4 17") ++ var output bytes.Buffer ++ w, err := EncodeMulti(&output, signKeys, nil) ++ if err != nil { ++ t.Errorf("EncodeMulti (%s) failed: %v", desc, err) ++ } ++ if _, err := w.Write(input); err != nil { ++ t.Errorf("Write(%q) to signer (%s) failed: %v", string(input), desc, err) ++ } ++ if err := w.Close(); err != nil { ++ t.Errorf("Close() of signer (%s) failed: %v", desc, err) ++ } ++ ++ block, _ := Decode(output.Bytes()) ++ if string(block.Bytes) != string(input) { ++ t.Errorf("Inline data didn't match original; got %q want %q", string(block.Bytes), string(input)) ++ } ++ _, err = openpgp.CheckDetachedSignature(verifyKeys, bytes.NewReader(block.Bytes), block.ArmoredSignature.Body) ++ if nKeys == 0 { ++ if err == nil { ++ t.Errorf("verifying inline (%s) succeeded; want failure", desc) ++ } ++ } else { ++ if err != nil { ++ t.Errorf("verifying inline (%s) failed (%v); want success", desc, err) ++ } ++ } ++ } ++ } ++} ++ ++func TestDecodeMissingCRC(t *testing.T) { ++ block, rest := Decode(clearsignInput3) ++ if block == nil { ++ t.Fatal("failed to decode PGP signature missing a CRC") ++ } ++ if len(rest) > 0 { ++ t.Fatalf("Decode should not have any remaining data left: %s", rest) ++ } ++ if _, err := packet.Read(block.ArmoredSignature.Body); err != nil { ++ t.Error(err) ++ } ++ if _, err := packet.Read(block.ArmoredSignature.Body); err != io.EOF { ++ t.Error(err) ++ } ++} ++ ++const signatureBlock = ` ++-----BEGIN PGP SIGNATURE----- ++Version: OpenPrivacy 0.99 ++ ++yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS ++vBSFjNSiVHsuAA== ++=njUN ++-----END PGP SIGNATURE----- ++` ++ ++var invalidInputs = []string{ ++ ` ++-----BEGIN PGP SIGNED MESSAGE----- ++Hash: SHA256 ++ ++(This message was truncated.) ++`, ++ ` ++-----BEGIN PGP SIGNED MESSAGE-----garbage ++Hash: SHA256 ++ ++_o/ ++` + signatureBlock, ++ ` ++garbage-----BEGIN PGP SIGNED MESSAGE----- ++Hash: SHA256 ++ ++_o/ ++` + signatureBlock, ++ ` ++-----BEGIN PGP SIGNED MESSAGE----- ++Hash: SHA` + "\x0b\x0b" + `256 ++ ++_o/ ++` + signatureBlock, ++ ` ++-----BEGIN PGP SIGNED MESSAGE----- ++NotHash: SHA256 ++ ++_o/ ++` + signatureBlock, ++} ++ ++func TestParseInvalid(t *testing.T) { ++ for i, input := range invalidInputs { ++ if b, rest := Decode([]byte(input)); b != nil { ++ t.Errorf("#%d: decoded a bad clearsigned message without any error", i) ++ } else if string(rest) != input { ++ t.Errorf("#%d: did not return all data with a bad message", i) ++ } ++ } ++} ++ ++var clearsignInput = []byte(` ++;lasjlkfdsa ++ ++-----BEGIN PGP SIGNED MESSAGE----- ++Hash: SHA1 ++ ++Hello world ++line 2 ++-----BEGIN PGP SIGNATURE----- ++Version: GnuPG v1.4.10 (GNU/Linux) ++ ++iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8 ++pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog ++2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9 ++MyTpno24AjIAGb+mH1U= ++=hIJ6 ++-----END PGP SIGNATURE----- ++trailing`) ++ ++var clearsignInput2 = []byte(` ++asdlfkjasdlkfjsadf ++ ++-----BEGIN PGP SIGNED MESSAGE----- ++Hash: SHA256 ++ ++ ++ ++(This message has a couple of blank lines at the start and end.) ++ ++ ++-----BEGIN PGP SIGNATURE----- ++Version: GnuPG v1.4.11 (GNU/Linux) ++ ++iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v ++pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI ++ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+ ++qZg6BaTvOxepqOxnhVU= ++=e+C6 ++-----END PGP SIGNATURE----- ++ ++trailing`) ++ ++var clearsignInput3 = []byte(`-----BEGIN PGP SIGNED MESSAGE----- ++Hash: SHA256 ++ ++Origin: vscode stable ++Label: vscode stable ++Suite: stable ++Codename: stable ++Date: Mon, 13 Jan 2020 08:41:45 UTC ++Architectures: amd64 ++Components: main ++Description: Generated by aptly ++MD5Sum: ++ 66437152b3082616d8053e52c4bafafb 5821166 Contents-amd64 ++ 8024662ed51109946a517754bbafdd33 286298 Contents-amd64.gz ++ 66437152b3082616d8053e52c4bafafb 5821166 main/Contents-amd64 ++ 8024662ed51109946a517754bbafdd33 286298 main/Contents-amd64.gz ++ 3062a08b3eca94a65d6d17ba1dafcf3e 1088265 main/binary-amd64/Packages ++ b8ee22200fba8fa3be56c1ff946cdd24 159344 main/binary-amd64/Packages.bz2 ++ f89c47c81ebd25caf287c8e6dda16c1a 169456 main/binary-amd64/Packages.gz ++ 4c9ca25b556f111a5536c78df885ad82 95 main/binary-amd64/Release ++SHA1: ++ 2b62d0e322746b7d094878278f49993ca4314bf7 5821166 Contents-amd64 ++ aafe35cce12e03d8b1939e403ddf5c0958c6e9bd 286298 Contents-amd64.gz ++ 2b62d0e322746b7d094878278f49993ca4314bf7 5821166 main/Contents-amd64 ++ aafe35cce12e03d8b1939e403ddf5c0958c6e9bd 286298 main/Contents-amd64.gz ++ 30316ac5d4ce3b472a96a797eeb0a2a82d43ed3e 1088265 main/binary-amd64/Packages ++ 6507e0b4da8194fd1048fcbb74c6e7433edaf3d6 159344 main/binary-amd64/Packages.bz2 ++ ec9d39c39567c74001221e4900fb5d11ec11b833 169456 main/binary-amd64/Packages.gz ++ 58bf20987a91d35936f18efce75ea233d43dbf8b 95 main/binary-amd64/Release ++SHA256: ++ deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39 5821166 Contents-amd64 ++ f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462 286298 Contents-amd64.gz ++ deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39 5821166 main/Contents-amd64 ++ f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462 286298 main/Contents-amd64.gz ++ 0fba50799ef72d0c2b354d0bcbbc8c623f6dae5a7fd7c218a54ea44dd8a49d5e 1088265 main/binary-amd64/Packages ++ 69382470a88b67acde80fe45ab223016adebc445713ff0aa3272902581d21f13 159344 main/binary-amd64/Packages.bz2 ++ 1724b8ace5bd8882943e9463d8525006f33ca704480da0186fd47937451dc216 169456 main/binary-amd64/Packages.gz ++ 0f509a0cb07e0ab433176fa47a21dccccc6b519f25f640cc58561104c11de6c2 95 main/binary-amd64/Release ++SHA512: ++ f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c 5821166 Contents-amd64 ++ 46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a 286298 Contents-amd64.gz ++ f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c 5821166 main/Contents-amd64 ++ 46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a 286298 main/Contents-amd64.gz ++ 3f78baf5adbaf0100996555b154807c794622fd0b5879b568ae0b6560e988fbfabed8d97db5a703d1a58514b9690fc6b60f9ad2eeece473d86ab257becd0ae41 1088265 main/binary-amd64/Packages ++ 18f26df90beff29192662ca40525367c3c04f4581d59d2e9ab1cd0700a145b6a292a1609ca33ebe1c211f13718a8eee751f41fd8189cf93d52aa3e0851542dfc 159344 main/binary-amd64/Packages.bz2 ++ 6a6d917229e0cf06c493e174a87d76e815717676f2c70bcbd3bc689a80bd3c5489ea97db83b8f74cba8e70f374f9d9974f22b1ed2687a4ba1dacd22fdef7e14d 169456 main/binary-amd64/Packages.gz ++ e1a4378ad266c13c2edf8a0e590fa4d11973ab99ce79f15af005cb838f1600f66f3dc6da8976fa8b474da9073c118039c27623ab3360c6df115071497fe4f50c 95 main/binary-amd64/Release ++ ++-----BEGIN PGP SIGNATURE----- ++Version: BSN Pgp v1.0.0.0 ++ ++iQEcBAEBCAAGBQJeHC1bAAoJEOs+lK2+EinPAg8H/1rrhcgfm1HYL+Vmr9Ns6ton ++LWQ8r13ADN66UTRa3XsO9V+q1fYowTqpXq6EZt2Gmlby/cpDf7mFPM5IteOXWLl7 ++QcWxPKHcdPIUi+h5F7BkFW65imP9GyX+V5Pxx5X544op7hYKaI0gAQ1oYtWDb3HE ++4D27fju6icbj8w6E8TePcrDn82UvWAcaI5WSLboyhXCt2DxS3PNGFlyaP58zKJ8F ++9cbBzksuMgMaTPAAMrU0zrFGfGeQz0Yo6nV/gRGiQaL9pSeIJWSKLNCMG/nIGmv2 ++xHVNFqTEetREY6UcQmuhwOn4HezyigH6XCBVp/Uez1izXiNdwBOet34SSvnkuJ4= ++-----END PGP SIGNATURE-----`) ++ ++var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- ++Version: GnuPG v1.4.10 (GNU/Linux) ++ ++lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp ++idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn ++vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB ++AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X ++0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL ++IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk ++VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn ++gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 ++TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx ++q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz ++dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA ++CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 ++ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ ++eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid ++AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV ++bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK ++/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA ++A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX ++TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc ++lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 ++rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN ++oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 ++QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU ++nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC ++AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp ++BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad ++AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL ++VrM0m72/jnpKo04= ++=zNCn ++-----END PGP PRIVATE KEY BLOCK----- ++` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go +new file mode 100644 +index 00000000000000..743b35a1204f5f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go +@@ -0,0 +1,130 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package elgamal implements ElGamal encryption, suitable for OpenPGP, ++// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on ++// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, ++// n. 4, 1985, pp. 469-472. ++// ++// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it ++// unsuitable for other protocols. RSA should be used in preference in any ++// case. ++// ++// Deprecated: this package was only provided to support ElGamal encryption in ++// OpenPGP. The golang.org/x/crypto/openpgp package is now deprecated (see ++// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has ++// compatibility and security issues (see https://eprint.iacr.org/2021/923). ++// Moreover, this package doesn't protect against side-channel attacks. ++package elgamal // import "golang.org/x/crypto/openpgp/elgamal" ++ ++import ( ++ "crypto/rand" ++ "crypto/subtle" ++ "errors" ++ "io" ++ "math/big" ++) ++ ++// PublicKey represents an ElGamal public key. ++type PublicKey struct { ++ G, P, Y *big.Int ++} ++ ++// PrivateKey represents an ElGamal private key. ++type PrivateKey struct { ++ PublicKey ++ X *big.Int ++} ++ ++// Encrypt encrypts the given message to the given public key. The result is a ++// pair of integers. Errors can result from reading random, or because msg is ++// too large to be encrypted to the public key. ++func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { ++ pLen := (pub.P.BitLen() + 7) / 8 ++ if len(msg) > pLen-11 { ++ err = errors.New("elgamal: message too long") ++ return ++ } ++ ++ // EM = 0x02 || PS || 0x00 || M ++ em := make([]byte, pLen-1) ++ em[0] = 2 ++ ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] ++ err = nonZeroRandomBytes(ps, random) ++ if err != nil { ++ return ++ } ++ em[len(em)-len(msg)-1] = 0 ++ copy(mm, msg) ++ ++ m := new(big.Int).SetBytes(em) ++ ++ k, err := rand.Int(random, pub.P) ++ if err != nil { ++ return ++ } ++ ++ c1 = new(big.Int).Exp(pub.G, k, pub.P) ++ s := new(big.Int).Exp(pub.Y, k, pub.P) ++ c2 = s.Mul(s, m) ++ c2.Mod(c2, pub.P) ++ ++ return ++} ++ ++// Decrypt takes two integers, resulting from an ElGamal encryption, and ++// returns the plaintext of the message. An error can result only if the ++// ciphertext is invalid. Users should keep in mind that this is a padding ++// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can ++// be used to break the cryptosystem. See β€œChosen Ciphertext Attacks ++// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel ++// Bleichenbacher, Advances in Cryptology (Crypto '98), ++func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { ++ s := new(big.Int).Exp(c1, priv.X, priv.P) ++ if s.ModInverse(s, priv.P) == nil { ++ return nil, errors.New("elgamal: invalid private key") ++ } ++ s.Mul(s, c2) ++ s.Mod(s, priv.P) ++ em := s.Bytes() ++ ++ firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) ++ ++ // The remainder of the plaintext must be a string of non-zero random ++ // octets, followed by a 0, followed by the message. ++ // lookingForIndex: 1 iff we are still looking for the zero. ++ // index: the offset of the first zero byte. ++ var lookingForIndex, index int ++ lookingForIndex = 1 ++ ++ for i := 1; i < len(em); i++ { ++ equals0 := subtle.ConstantTimeByteEq(em[i], 0) ++ index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) ++ lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) ++ } ++ ++ if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { ++ return nil, errors.New("elgamal: decryption error") ++ } ++ return em[index+1:], nil ++} ++ ++// nonZeroRandomBytes fills the given slice with non-zero random octets. ++func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { ++ _, err = io.ReadFull(rand, s) ++ if err != nil { ++ return ++ } ++ ++ for i := 0; i < len(s); i++ { ++ for s[i] == 0 { ++ _, err = io.ReadFull(rand, s[i:i+1]) ++ if err != nil { ++ return ++ } ++ } ++ } ++ ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go +new file mode 100644 +index 00000000000000..9f0a8547c3ef55 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go +@@ -0,0 +1,64 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package elgamal ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "math/big" ++ "testing" ++) ++ ++// This is the 1024-bit MODP group from RFC 5114, section 2.1: ++const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371" ++ ++const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5" ++ ++func fromHex(hex string) *big.Int { ++ n, ok := new(big.Int).SetString(hex, 16) ++ if !ok { ++ panic("failed to parse hex number") ++ } ++ return n ++} ++ ++func TestEncryptDecrypt(t *testing.T) { ++ priv := &PrivateKey{ ++ PublicKey: PublicKey{ ++ G: fromHex(generatorHex), ++ P: fromHex(primeHex), ++ }, ++ X: fromHex("42"), ++ } ++ priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) ++ ++ message := []byte("hello world") ++ c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message) ++ if err != nil { ++ t.Errorf("error encrypting: %s", err) ++ } ++ message2, err := Decrypt(priv, c1, c2) ++ if err != nil { ++ t.Errorf("error decrypting: %s", err) ++ } ++ if !bytes.Equal(message2, message) { ++ t.Errorf("decryption failed, got: %x, want: %x", message2, message) ++ } ++} ++ ++func TestDecryptBadKey(t *testing.T) { ++ priv := &PrivateKey{ ++ PublicKey: PublicKey{ ++ G: fromHex(generatorHex), ++ P: fromHex("2"), ++ }, ++ X: fromHex("42"), ++ } ++ priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) ++ c1, c2 := fromHex("8"), fromHex("8") ++ if _, err := Decrypt(priv, c1, c2); err == nil { ++ t.Errorf("unexpected success decrypting") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/errors/errors.go b/ms_mod/golang.org/x/crypto/openpgp/errors/errors.go +new file mode 100644 +index 00000000000000..1d7a0ea05adf17 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/errors/errors.go +@@ -0,0 +1,78 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package errors contains common error types for the OpenPGP packages. ++// ++// Deprecated: this package is unmaintained except for security fixes. New ++// applications should consider a more focused, modern alternative to OpenPGP ++// for their specific task. If you are required to interoperate with OpenPGP ++// systems and need a maintained package, consider a community fork. ++// See https://golang.org/issue/44226. ++package errors // import "golang.org/x/crypto/openpgp/errors" ++ ++import ( ++ "strconv" ++) ++ ++// A StructuralError is returned when OpenPGP data is found to be syntactically ++// invalid. ++type StructuralError string ++ ++func (s StructuralError) Error() string { ++ return "openpgp: invalid data: " + string(s) ++} ++ ++// UnsupportedError indicates that, although the OpenPGP data is valid, it ++// makes use of currently unimplemented features. ++type UnsupportedError string ++ ++func (s UnsupportedError) Error() string { ++ return "openpgp: unsupported feature: " + string(s) ++} ++ ++// InvalidArgumentError indicates that the caller is in error and passed an ++// incorrect value. ++type InvalidArgumentError string ++ ++func (i InvalidArgumentError) Error() string { ++ return "openpgp: invalid argument: " + string(i) ++} ++ ++// SignatureError indicates that a syntactically valid signature failed to ++// validate. ++type SignatureError string ++ ++func (b SignatureError) Error() string { ++ return "openpgp: invalid signature: " + string(b) ++} ++ ++type keyIncorrectError int ++ ++func (ki keyIncorrectError) Error() string { ++ return "openpgp: incorrect key" ++} ++ ++var ErrKeyIncorrect error = keyIncorrectError(0) ++ ++type unknownIssuerError int ++ ++func (unknownIssuerError) Error() string { ++ return "openpgp: signature made by unknown entity" ++} ++ ++var ErrUnknownIssuer error = unknownIssuerError(0) ++ ++type keyRevokedError int ++ ++func (keyRevokedError) Error() string { ++ return "openpgp: signature made by revoked key" ++} ++ ++var ErrKeyRevoked error = keyRevokedError(0) ++ ++type UnknownPacketTypeError uint8 ++ ++func (upte UnknownPacketTypeError) Error() string { ++ return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/keys.go b/ms_mod/golang.org/x/crypto/openpgp/keys.go +new file mode 100644 +index 00000000000000..d62f787e9d5a36 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/keys.go +@@ -0,0 +1,693 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package openpgp ++ ++import ( ++ "crypto/rsa" ++ "io" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/armor" ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/packet" ++) ++ ++// PublicKeyType is the armor type for a PGP public key. ++var PublicKeyType = "PGP PUBLIC KEY BLOCK" ++ ++// PrivateKeyType is the armor type for a PGP private key. ++var PrivateKeyType = "PGP PRIVATE KEY BLOCK" ++ ++// An Entity represents the components of an OpenPGP key: a primary public key ++// (which must be a signing key), one or more identities claimed by that key, ++// and zero or more subkeys, which may be encryption keys. ++type Entity struct { ++ PrimaryKey *packet.PublicKey ++ PrivateKey *packet.PrivateKey ++ Identities map[string]*Identity // indexed by Identity.Name ++ Revocations []*packet.Signature ++ Subkeys []Subkey ++} ++ ++// An Identity represents an identity claimed by an Entity and zero or more ++// assertions by other entities about that claim. ++type Identity struct { ++ Name string // by convention, has the form "Full Name (comment) " ++ UserId *packet.UserId ++ SelfSignature *packet.Signature ++ Signatures []*packet.Signature ++} ++ ++// A Subkey is an additional public key in an Entity. Subkeys can be used for ++// encryption. ++type Subkey struct { ++ PublicKey *packet.PublicKey ++ PrivateKey *packet.PrivateKey ++ Sig *packet.Signature ++} ++ ++// A Key identifies a specific public key in an Entity. This is either the ++// Entity's primary key or a subkey. ++type Key struct { ++ Entity *Entity ++ PublicKey *packet.PublicKey ++ PrivateKey *packet.PrivateKey ++ SelfSignature *packet.Signature ++} ++ ++// A KeyRing provides access to public and private keys. ++type KeyRing interface { ++ // KeysById returns the set of keys that have the given key id. ++ KeysById(id uint64) []Key ++ // KeysByIdUsage returns the set of keys with the given id ++ // that also meet the key usage given by requiredUsage. ++ // The requiredUsage is expressed as the bitwise-OR of ++ // packet.KeyFlag* values. ++ KeysByIdUsage(id uint64, requiredUsage byte) []Key ++ // DecryptionKeys returns all private keys that are valid for ++ // decryption. ++ DecryptionKeys() []Key ++} ++ ++// primaryIdentity returns the Identity marked as primary or the first identity ++// if none are so marked. ++func (e *Entity) primaryIdentity() *Identity { ++ var firstIdentity *Identity ++ for _, ident := range e.Identities { ++ if firstIdentity == nil { ++ firstIdentity = ident ++ } ++ if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { ++ return ident ++ } ++ } ++ return firstIdentity ++} ++ ++// encryptionKey returns the best candidate Key for encrypting a message to the ++// given Entity. ++func (e *Entity) encryptionKey(now time.Time) (Key, bool) { ++ candidateSubkey := -1 ++ ++ // Iterate the keys to find the newest key ++ var maxTime time.Time ++ for i, subkey := range e.Subkeys { ++ if subkey.Sig.FlagsValid && ++ subkey.Sig.FlagEncryptCommunications && ++ subkey.PublicKey.PubKeyAlgo.CanEncrypt() && ++ !subkey.Sig.KeyExpired(now) && ++ (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { ++ candidateSubkey = i ++ maxTime = subkey.Sig.CreationTime ++ } ++ } ++ ++ if candidateSubkey != -1 { ++ subkey := e.Subkeys[candidateSubkey] ++ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true ++ } ++ ++ // If we don't have any candidate subkeys for encryption and ++ // the primary key doesn't have any usage metadata then we ++ // assume that the primary key is ok. Or, if the primary key is ++ // marked as ok to encrypt to, then we can obviously use it. ++ i := e.primaryIdentity() ++ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && ++ e.PrimaryKey.PubKeyAlgo.CanEncrypt() && ++ !i.SelfSignature.KeyExpired(now) { ++ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true ++ } ++ ++ // This Entity appears to be signing only. ++ return Key{}, false ++} ++ ++// signingKey return the best candidate Key for signing a message with this ++// Entity. ++func (e *Entity) signingKey(now time.Time) (Key, bool) { ++ candidateSubkey := -1 ++ ++ for i, subkey := range e.Subkeys { ++ if subkey.Sig.FlagsValid && ++ subkey.Sig.FlagSign && ++ subkey.PublicKey.PubKeyAlgo.CanSign() && ++ !subkey.Sig.KeyExpired(now) { ++ candidateSubkey = i ++ break ++ } ++ } ++ ++ if candidateSubkey != -1 { ++ subkey := e.Subkeys[candidateSubkey] ++ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true ++ } ++ ++ // If we have no candidate subkey then we assume that it's ok to sign ++ // with the primary key. ++ i := e.primaryIdentity() ++ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && ++ !i.SelfSignature.KeyExpired(now) { ++ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true ++ } ++ ++ return Key{}, false ++} ++ ++// An EntityList contains one or more Entities. ++type EntityList []*Entity ++ ++// KeysById returns the set of keys that have the given key id. ++func (el EntityList) KeysById(id uint64) (keys []Key) { ++ for _, e := range el { ++ if e.PrimaryKey.KeyId == id { ++ var selfSig *packet.Signature ++ for _, ident := range e.Identities { ++ if selfSig == nil { ++ selfSig = ident.SelfSignature ++ } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { ++ selfSig = ident.SelfSignature ++ break ++ } ++ } ++ keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) ++ } ++ ++ for _, subKey := range e.Subkeys { ++ if subKey.PublicKey.KeyId == id { ++ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) ++ } ++ } ++ } ++ return ++} ++ ++// KeysByIdUsage returns the set of keys with the given id that also meet ++// the key usage given by requiredUsage. The requiredUsage is expressed as ++// the bitwise-OR of packet.KeyFlag* values. ++func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { ++ for _, key := range el.KeysById(id) { ++ if len(key.Entity.Revocations) > 0 { ++ continue ++ } ++ ++ if key.SelfSignature.RevocationReason != nil { ++ continue ++ } ++ ++ if key.SelfSignature.FlagsValid && requiredUsage != 0 { ++ var usage byte ++ if key.SelfSignature.FlagCertify { ++ usage |= packet.KeyFlagCertify ++ } ++ if key.SelfSignature.FlagSign { ++ usage |= packet.KeyFlagSign ++ } ++ if key.SelfSignature.FlagEncryptCommunications { ++ usage |= packet.KeyFlagEncryptCommunications ++ } ++ if key.SelfSignature.FlagEncryptStorage { ++ usage |= packet.KeyFlagEncryptStorage ++ } ++ if usage&requiredUsage != requiredUsage { ++ continue ++ } ++ } ++ ++ keys = append(keys, key) ++ } ++ return ++} ++ ++// DecryptionKeys returns all private keys that are valid for decryption. ++func (el EntityList) DecryptionKeys() (keys []Key) { ++ for _, e := range el { ++ for _, subKey := range e.Subkeys { ++ if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { ++ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) ++ } ++ } ++ } ++ return ++} ++ ++// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. ++func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { ++ block, err := armor.Decode(r) ++ if err == io.EOF { ++ return nil, errors.InvalidArgumentError("no armored data found") ++ } ++ if err != nil { ++ return nil, err ++ } ++ if block.Type != PublicKeyType && block.Type != PrivateKeyType { ++ return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) ++ } ++ ++ return ReadKeyRing(block.Body) ++} ++ ++// ReadKeyRing reads one or more public/private keys. Unsupported keys are ++// ignored as long as at least a single valid key is found. ++func ReadKeyRing(r io.Reader) (el EntityList, err error) { ++ packets := packet.NewReader(r) ++ var lastUnsupportedError error ++ ++ for { ++ var e *Entity ++ e, err = ReadEntity(packets) ++ if err != nil { ++ // TODO: warn about skipped unsupported/unreadable keys ++ if _, ok := err.(errors.UnsupportedError); ok { ++ lastUnsupportedError = err ++ err = readToNextPublicKey(packets) ++ } else if _, ok := err.(errors.StructuralError); ok { ++ // Skip unreadable, badly-formatted keys ++ lastUnsupportedError = err ++ err = readToNextPublicKey(packets) ++ } ++ if err == io.EOF { ++ err = nil ++ break ++ } ++ if err != nil { ++ el = nil ++ break ++ } ++ } else { ++ el = append(el, e) ++ } ++ } ++ ++ if len(el) == 0 && err == nil { ++ err = lastUnsupportedError ++ } ++ return ++} ++ ++// readToNextPublicKey reads packets until the start of the entity and leaves ++// the first packet of the new entity in the Reader. ++func readToNextPublicKey(packets *packet.Reader) (err error) { ++ var p packet.Packet ++ for { ++ p, err = packets.Next() ++ if err == io.EOF { ++ return ++ } else if err != nil { ++ if _, ok := err.(errors.UnsupportedError); ok { ++ err = nil ++ continue ++ } ++ return ++ } ++ ++ if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { ++ packets.Unread(p) ++ return ++ } ++ } ++} ++ ++// ReadEntity reads an entity (public key, identities, subkeys etc) from the ++// given Reader. ++func ReadEntity(packets *packet.Reader) (*Entity, error) { ++ e := new(Entity) ++ e.Identities = make(map[string]*Identity) ++ ++ p, err := packets.Next() ++ if err != nil { ++ return nil, err ++ } ++ ++ var ok bool ++ if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { ++ if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { ++ packets.Unread(p) ++ return nil, errors.StructuralError("first packet was not a public/private key") ++ } ++ e.PrimaryKey = &e.PrivateKey.PublicKey ++ } ++ ++ if !e.PrimaryKey.PubKeyAlgo.CanSign() { ++ return nil, errors.StructuralError("primary key cannot be used for signatures") ++ } ++ ++ var revocations []*packet.Signature ++EachPacket: ++ for { ++ p, err := packets.Next() ++ if err == io.EOF { ++ break ++ } else if err != nil { ++ return nil, err ++ } ++ ++ switch pkt := p.(type) { ++ case *packet.UserId: ++ if err := addUserID(e, packets, pkt); err != nil { ++ return nil, err ++ } ++ case *packet.Signature: ++ if pkt.SigType == packet.SigTypeKeyRevocation { ++ revocations = append(revocations, pkt) ++ } else if pkt.SigType == packet.SigTypeDirectSignature { ++ // TODO: RFC4880 5.2.1 permits signatures ++ // directly on keys (eg. to bind additional ++ // revocation keys). ++ } ++ // Else, ignoring the signature as it does not follow anything ++ // we would know to attach it to. ++ case *packet.PrivateKey: ++ if pkt.IsSubkey == false { ++ packets.Unread(p) ++ break EachPacket ++ } ++ err = addSubkey(e, packets, &pkt.PublicKey, pkt) ++ if err != nil { ++ return nil, err ++ } ++ case *packet.PublicKey: ++ if pkt.IsSubkey == false { ++ packets.Unread(p) ++ break EachPacket ++ } ++ err = addSubkey(e, packets, pkt, nil) ++ if err != nil { ++ return nil, err ++ } ++ default: ++ // we ignore unknown packets ++ } ++ } ++ ++ if len(e.Identities) == 0 { ++ return nil, errors.StructuralError("entity without any identities") ++ } ++ ++ for _, revocation := range revocations { ++ err = e.PrimaryKey.VerifyRevocationSignature(revocation) ++ if err == nil { ++ e.Revocations = append(e.Revocations, revocation) ++ } else { ++ // TODO: RFC 4880 5.2.3.15 defines revocation keys. ++ return nil, errors.StructuralError("revocation signature signed by alternate key") ++ } ++ } ++ ++ return e, nil ++} ++ ++func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { ++ // Make a new Identity object, that we might wind up throwing away. ++ // We'll only add it if we get a valid self-signature over this ++ // userID. ++ identity := new(Identity) ++ identity.Name = pkt.Id ++ identity.UserId = pkt ++ ++ for { ++ p, err := packets.Next() ++ if err == io.EOF { ++ break ++ } else if err != nil { ++ return err ++ } ++ ++ sig, ok := p.(*packet.Signature) ++ if !ok { ++ packets.Unread(p) ++ break ++ } ++ ++ if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { ++ if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { ++ return errors.StructuralError("user ID self-signature invalid: " + err.Error()) ++ } ++ identity.SelfSignature = sig ++ e.Identities[pkt.Id] = identity ++ } else { ++ identity.Signatures = append(identity.Signatures, sig) ++ } ++ } ++ ++ return nil ++} ++ ++func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { ++ var subKey Subkey ++ subKey.PublicKey = pub ++ subKey.PrivateKey = priv ++ ++ for { ++ p, err := packets.Next() ++ if err == io.EOF { ++ break ++ } else if err != nil { ++ return errors.StructuralError("subkey signature invalid: " + err.Error()) ++ } ++ ++ sig, ok := p.(*packet.Signature) ++ if !ok { ++ packets.Unread(p) ++ break ++ } ++ ++ if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation { ++ return errors.StructuralError("subkey signature with wrong type") ++ } ++ ++ if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil { ++ return errors.StructuralError("subkey signature invalid: " + err.Error()) ++ } ++ ++ switch sig.SigType { ++ case packet.SigTypeSubkeyRevocation: ++ subKey.Sig = sig ++ case packet.SigTypeSubkeyBinding: ++ ++ if shouldReplaceSubkeySig(subKey.Sig, sig) { ++ subKey.Sig = sig ++ } ++ } ++ } ++ ++ if subKey.Sig == nil { ++ return errors.StructuralError("subkey packet not followed by signature") ++ } ++ ++ e.Subkeys = append(e.Subkeys, subKey) ++ ++ return nil ++} ++ ++func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool { ++ if potentialNewSig == nil { ++ return false ++ } ++ ++ if existingSig == nil { ++ return true ++ } ++ ++ if existingSig.SigType == packet.SigTypeSubkeyRevocation { ++ return false // never override a revocation signature ++ } ++ ++ return potentialNewSig.CreationTime.After(existingSig.CreationTime) ++} ++ ++const defaultRSAKeyBits = 2048 ++ ++// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a ++// single identity composed of the given full name, comment and email, any of ++// which may be empty but must not contain any of "()<>\x00". ++// If config is nil, sensible defaults will be used. ++func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { ++ creationTime := config.Now() ++ ++ bits := defaultRSAKeyBits ++ if config != nil && config.RSABits != 0 { ++ bits = config.RSABits ++ } ++ ++ uid := packet.NewUserId(name, comment, email) ++ if uid == nil { ++ return nil, errors.InvalidArgumentError("user id field contained invalid characters") ++ } ++ signingPriv, err := rsa.GenerateKey(config.Random(), bits) ++ if err != nil { ++ return nil, err ++ } ++ encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) ++ if err != nil { ++ return nil, err ++ } ++ ++ e := &Entity{ ++ PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey), ++ PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv), ++ Identities: make(map[string]*Identity), ++ } ++ isPrimaryId := true ++ e.Identities[uid.Id] = &Identity{ ++ Name: uid.Id, ++ UserId: uid, ++ SelfSignature: &packet.Signature{ ++ CreationTime: creationTime, ++ SigType: packet.SigTypePositiveCert, ++ PubKeyAlgo: packet.PubKeyAlgoRSA, ++ Hash: config.Hash(), ++ IsPrimaryId: &isPrimaryId, ++ FlagsValid: true, ++ FlagSign: true, ++ FlagCertify: true, ++ IssuerKeyId: &e.PrimaryKey.KeyId, ++ }, ++ } ++ err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) ++ if err != nil { ++ return nil, err ++ } ++ ++ // If the user passes in a DefaultHash via packet.Config, ++ // set the PreferredHash for the SelfSignature. ++ if config != nil && config.DefaultHash != 0 { ++ e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} ++ } ++ ++ // Likewise for DefaultCipher. ++ if config != nil && config.DefaultCipher != 0 { ++ e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} ++ } ++ ++ e.Subkeys = make([]Subkey, 1) ++ e.Subkeys[0] = Subkey{ ++ PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey), ++ PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv), ++ Sig: &packet.Signature{ ++ CreationTime: creationTime, ++ SigType: packet.SigTypeSubkeyBinding, ++ PubKeyAlgo: packet.PubKeyAlgoRSA, ++ Hash: config.Hash(), ++ FlagsValid: true, ++ FlagEncryptStorage: true, ++ FlagEncryptCommunications: true, ++ IssuerKeyId: &e.PrimaryKey.KeyId, ++ }, ++ } ++ e.Subkeys[0].PublicKey.IsSubkey = true ++ e.Subkeys[0].PrivateKey.IsSubkey = true ++ err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) ++ if err != nil { ++ return nil, err ++ } ++ return e, nil ++} ++ ++// SerializePrivate serializes an Entity, including private key material, but ++// excluding signatures from other entities, to the given Writer. ++// Identities and subkeys are re-signed in case they changed since NewEntry. ++// If config is nil, sensible defaults will be used. ++func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { ++ err = e.PrivateKey.Serialize(w) ++ if err != nil { ++ return ++ } ++ for _, ident := range e.Identities { ++ err = ident.UserId.Serialize(w) ++ if err != nil { ++ return ++ } ++ err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) ++ if err != nil { ++ return ++ } ++ err = ident.SelfSignature.Serialize(w) ++ if err != nil { ++ return ++ } ++ } ++ for _, subkey := range e.Subkeys { ++ err = subkey.PrivateKey.Serialize(w) ++ if err != nil { ++ return ++ } ++ err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) ++ if err != nil { ++ return ++ } ++ err = subkey.Sig.Serialize(w) ++ if err != nil { ++ return ++ } ++ } ++ return nil ++} ++ ++// Serialize writes the public part of the given Entity to w, including ++// signatures from other entities. No private key material will be output. ++func (e *Entity) Serialize(w io.Writer) error { ++ err := e.PrimaryKey.Serialize(w) ++ if err != nil { ++ return err ++ } ++ for _, ident := range e.Identities { ++ err = ident.UserId.Serialize(w) ++ if err != nil { ++ return err ++ } ++ err = ident.SelfSignature.Serialize(w) ++ if err != nil { ++ return err ++ } ++ for _, sig := range ident.Signatures { ++ err = sig.Serialize(w) ++ if err != nil { ++ return err ++ } ++ } ++ } ++ for _, subkey := range e.Subkeys { ++ err = subkey.PublicKey.Serialize(w) ++ if err != nil { ++ return err ++ } ++ err = subkey.Sig.Serialize(w) ++ if err != nil { ++ return err ++ } ++ } ++ return nil ++} ++ ++// SignIdentity adds a signature to e, from signer, attesting that identity is ++// associated with e. The provided identity must already be an element of ++// e.Identities and the private key of signer must have been decrypted if ++// necessary. ++// If config is nil, sensible defaults will be used. ++func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { ++ if signer.PrivateKey == nil { ++ return errors.InvalidArgumentError("signing Entity must have a private key") ++ } ++ if signer.PrivateKey.Encrypted { ++ return errors.InvalidArgumentError("signing Entity's private key must be decrypted") ++ } ++ ident, ok := e.Identities[identity] ++ if !ok { ++ return errors.InvalidArgumentError("given identity string not found in Entity") ++ } ++ ++ sig := &packet.Signature{ ++ SigType: packet.SigTypeGenericCert, ++ PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, ++ Hash: config.Hash(), ++ CreationTime: config.Now(), ++ IssuerKeyId: &signer.PrivateKey.KeyId, ++ } ++ if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { ++ return err ++ } ++ ident.Signatures = append(ident.Signatures, sig) ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go b/ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go +new file mode 100644 +index 00000000000000..7779bd97748f4b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go +@@ -0,0 +1,200 @@ ++package openpgp ++ ++const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" ++const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" ++const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" ++const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" ++ ++const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++Charset: UTF-8 ++ ++mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY ++ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG ++zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 ++QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ ++QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo ++9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu ++Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ ++dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R ++JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL ++ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew ++RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW ++/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu ++yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv ++2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR ++bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL ++C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP ++WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y ++MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA ++EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ ++MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N ++1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm +++ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N ++lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW ++CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF ++4artDmrG ++=7FfJ ++-----END PGP PUBLIC KEY BLOCK-----` ++ ++const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++ ++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 ++6LCg2mg= ++=Dhm4 ++-----END PGP PUBLIC KEY BLOCK-----` ++ ++const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++Version: GnuPG v1 ++ ++mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo ++7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom ++lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0 ++E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC ++CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw ++6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH ++7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv ++X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7 ++GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl ++y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw ++R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW ++CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+ ++LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO ++aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx ++yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl ++BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr ++Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK ++CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp ++C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ ++SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ ++MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= ++=vtbN ++-----END PGP PUBLIC KEY BLOCK-----` ++ ++const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++ ++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 ++7qTZOahrETw= ++=IKnw ++-----END PGP PUBLIC KEY BLOCK-----` ++ ++const keyWithSubKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++ ++mI0EWyKwKQEEALwXhKBnyaaNFeK3ljfc/qn9X/QFw+28EUfgZPHjRmHubuXLE2uR ++s3ZoSXY2z7Dkv+NyHYMt8p+X8q5fR7JvUjK2XbPyKoiJVnHINll83yl67DaWfKNL ++EjNoO0kIfbXfCkZ7EG6DL+iKtuxniGTcnGT47e+HJSqb/STpLMnWwXjBABEBAAG0 ++I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQQ/ ++lRafP/p9PytHbwxMvYJsOQdOOAUCWyKwKQIbAwULCQgHAwUVCgkICwUWAgMBAAIe ++AQIXgAAKCRBMvYJsOQdOOOsFBAC62mXww8XuqvYLcVOvHkWLT6mhxrQOJXnlfpn7 ++2uBV9CMhoG/Ycd43NONsJrB95Apr9TDIqWnVszNbqPCuBhZQSGLdbiDKjxnCWBk0 ++69qv4RNtkpOhYB7jK4s8F5oQZqId6JasT/PmJTH92mhBYhhTQr0GYFuPX2UJdkw9 ++Sn9C67iNBFsisDUBBAC3A+Yo9lgCnxi/pfskyLrweYif6kIXWLAtLTsM6g/6jt7b ++wTrknuCPyTv0QKGXsAEe/cK/Xq3HvX9WfXPGIHc/X56ZIsHQ+RLowbZV/Lhok1IW ++FAuQm8axr/by80cRwFnzhfPc/ukkAq2Qyj4hLsGblu6mxeAhzcp8aqmWOO2H9QAR ++AQABiLYEKAEKACAWIQQ/lRafP/p9PytHbwxMvYJsOQdOOAUCWyK16gIdAAAKCRBM ++vYJsOQdOOB1vA/4u4uLONsE+2GVOyBsHyy7uTdkuxaR9b54A/cz6jT/tzUbeIzgx ++22neWhgvIEghnUZd0vEyK9k1wy5vbDlEo6nKzHso32N1QExGr5upRERAxweDxGOj ++7luDwNypI7QcifE64lS/JmlnunwRCdRWMKc0Fp+7jtRc5mpwyHN/Suf5RokBagQY ++AQoAIBYhBD+VFp8/+n0/K0dvDEy9gmw5B044BQJbIrA1AhsCAL8JEEy9gmw5B044 ++tCAEGQEKAB0WIQSNdnkaWY6t62iX336UXbGvYdhXJwUCWyKwNQAKCRCUXbGvYdhX ++JxJSA/9fCPHP6sUtGF1o3G1a3yvOUDGr1JWcct9U+QpbCt1mZoNopCNDDQAJvDWl ++mvDgHfuogmgNJRjOMznvahbF+wpTXmB7LS0SK412gJzl1fFIpK4bgnhu0TwxNsO1 ++8UkCZWqxRMgcNUn9z6XWONK8dgt5JNvHSHrwF4CxxwjL23AAtK+FA/UUoi3U4kbC ++0XnSr1Sl+mrzQi1+H7xyMe7zjqe+gGANtskqexHzwWPUJCPZ5qpIa2l8ghiUim6b ++4ymJ+N8/T8Yva1FaPEqfMzzqJr8McYFm0URioXJPvOAlRxdHPteZ0qUopt/Jawxl ++Xt6B9h1YpeLoJwjwsvbi98UTRs0jXwoY ++=3fWu ++-----END PGP PUBLIC KEY BLOCK-----` ++ ++const keyWithSubKeyAndBadSelfSigOrder = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++ ++mI0EWyLLDQEEAOqIOpJ/ha1OYAGduu9tS3rBz5vyjbNgJO4sFveEM0mgsHQ0X9/L ++plonW+d0gRoO1dhJ8QICjDAc6+cna1DE3tEb5m6JtQ30teLZuqrR398Cf6w7NNVz ++r3lrlmnH9JaKRuXl7tZciwyovneBfZVCdtsRZjaLI1uMQCz/BToiYe3DABEBAAG0 ++I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQRZ ++sixZOfQcZdW0wUqmgmdsv1O9xgUCWyLLDQIbAwULCQgHAwUVCgkICwUWAgMBAAIe ++AQIXgAAKCRCmgmdsv1O9xql2A/4pix98NxjhdsXtazA9agpAKeADf9tG4Za27Gj+ ++3DCww/E4iP2X35jZimSm/30QRB6j08uGCqd9vXkkJxtOt63y/IpVOtWX6vMWSTUm ++k8xKkaYMP0/IzKNJ1qC/qYEUYpwERBKg9Z+k99E2Ql4kRHdxXUHq6OzY79H18Y+s ++GdeM/riNBFsiyxsBBAC54Pxg/8ZWaZX1phGdwfe5mek27SOYpC0AxIDCSOdMeQ6G ++HPk38pywl1d+S+KmF/F4Tdi+kWro62O4eG2uc/T8JQuRDUhSjX0Qa51gPzJrUOVT ++CFyUkiZ/3ZDhtXkgfuso8ua2ChBgR9Ngr4v43tSqa9y6AK7v0qjxD1x+xMrjXQAR ++AQABiQFxBBgBCgAmAhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsizTIFCQAN ++MRcAv7QgBBkBCgAdFiEEJcoVUVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62j ++UpRPICQq5gQApoWIigZxXFoM0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBS ++YnjyA4+n1D+zB2VqliD2QrsX12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZs ++nRJmXV+bsvD4sidLZLjdwOVa3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/ ++U73GGi0D/i20VW8AWYAPACm2zMlzExKTOAV01YTQH/3vW0WLrOse53WcIVZga6es ++HuO4So0SOEAvxKMe5HpRIu2dJxTvd99Bo9xk9xJU0AoFrO0vNCRnL+5y68xMlODK ++lEw5/kl0jeaTBp6xX0HDQOEVOpPGUwWV4Ij2EnvfNDXaE1vK1kffiQFrBBgBCgAg ++AhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsi0AYAv7QgBBkBCgAdFiEEJcoV ++UVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62jUpRPICQq5gQApoWIigZxXFoM ++0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBSYnjyA4+n1D+zB2VqliD2QrsX ++12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZsnRJmXV+bsvD4sidLZLjdwOVa ++3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/U73GRl0EAJokkXmy4zKDHWWi ++wvK9gi2gQgRkVnu2AiONxJb5vjeLhM/07BRmH6K1o+w3fOeEQp4FjXj1eQ5fPSM6 ++Hhwx2CTl9SDnPSBMiKXsEFRkmwQ2AAsQZLmQZvKBkLZYeBiwf+IY621eYDhZfo+G ++1dh1WoUCyREZsJQg2YoIpWIcvw+a ++=bNRo ++-----END PGP PUBLIC KEY BLOCK----- ++` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/keys_test.go b/ms_mod/golang.org/x/crypto/openpgp/keys_test.go +new file mode 100644 +index 00000000000000..0eb1a9ef29704e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/keys_test.go +@@ -0,0 +1,495 @@ ++package openpgp ++ ++import ( ++ "bytes" ++ "crypto" ++ "strings" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/packet" ++) ++ ++func TestKeyExpiry(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(expiringKeyHex)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ entity := kring[0] ++ ++ const timeFormat = "2006-01-02" ++ time1, _ := time.Parse(timeFormat, "2013-07-01") ++ ++ // The expiringKeyHex key is structured as: ++ // ++ // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC ++ // sub 1024R/1ABB25A0 created: 2013-07-01 23:11:07 +0200 CEST expires: 2013-07-08 usage: E ++ // sub 1024R/96A672F5 created: 2013-07-01 23:11:23 +0200 CEST expires: 2013-07-31 usage: E ++ // ++ // So this should select the newest, non-expired encryption key. ++ key, _ := entity.encryptionKey(time1) ++ if id, expected := key.PublicKey.KeyIdShortString(), "96A672F5"; id != expected { ++ t.Errorf("Expected key %s at time %s, but got key %s", expected, time1.Format(timeFormat), id) ++ } ++ ++ // Once the first encryption subkey has expired, the second should be ++ // selected. ++ time2, _ := time.Parse(timeFormat, "2013-07-09") ++ key, _ = entity.encryptionKey(time2) ++ if id, expected := key.PublicKey.KeyIdShortString(), "96A672F5"; id != expected { ++ t.Errorf("Expected key %s at time %s, but got key %s", expected, time2.Format(timeFormat), id) ++ } ++ ++ // Once all the keys have expired, nothing should be returned. ++ time3, _ := time.Parse(timeFormat, "2013-08-01") ++ if key, ok := entity.encryptionKey(time3); ok { ++ t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString()) ++ } ++} ++ ++func TestMissingCrossSignature(t *testing.T) { ++ // This public key has a signing subkey, but the subkey does not ++ // contain a cross-signature. ++ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(missingCrossSignatureKey)) ++ if len(keys) != 0 { ++ t.Errorf("Accepted key with missing cross signature") ++ } ++ if err == nil { ++ t.Fatal("Failed to detect error in keyring with missing cross signature") ++ } ++ structural, ok := err.(errors.StructuralError) ++ if !ok { ++ t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) ++ } ++ const expectedMsg = "signing subkey is missing cross-signature" ++ if !strings.Contains(string(structural), expectedMsg) { ++ t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) ++ } ++} ++ ++func TestInvalidCrossSignature(t *testing.T) { ++ // This public key has a signing subkey, and the subkey has an ++ // embedded cross-signature. However, the cross-signature does ++ // not correctly validate over the primary and subkey. ++ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(invalidCrossSignatureKey)) ++ if len(keys) != 0 { ++ t.Errorf("Accepted key with invalid cross signature") ++ } ++ if err == nil { ++ t.Fatal("Failed to detect error in keyring with an invalid cross signature") ++ } ++ structural, ok := err.(errors.StructuralError) ++ if !ok { ++ t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) ++ } ++ const expectedMsg = "subkey signature invalid" ++ if !strings.Contains(string(structural), expectedMsg) { ++ t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) ++ } ++} ++ ++func TestGoodCrossSignature(t *testing.T) { ++ // This public key has a signing subkey, and the subkey has an ++ // embedded cross-signature which correctly validates over the ++ // primary and subkey. ++ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(goodCrossSignatureKey)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if len(keys) != 1 { ++ t.Errorf("Failed to accept key with good cross signature, %d", len(keys)) ++ } ++ if len(keys[0].Subkeys) != 1 { ++ t.Errorf("Failed to accept good subkey, %d", len(keys[0].Subkeys)) ++ } ++} ++ ++func TestRevokedUserID(t *testing.T) { ++ // This key contains 2 UIDs, one of which is revoked: ++ // [ultimate] (1) Golang Gopher ++ // [ revoked] (2) Golang Gopher ++ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(revokedUserIDKey)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if len(keys) != 1 { ++ t.Fatal("Failed to read key with a revoked user id") ++ } ++ ++ var identities []*Identity ++ for _, identity := range keys[0].Identities { ++ identities = append(identities, identity) ++ } ++ ++ if numIdentities, numExpected := len(identities), 1; numIdentities != numExpected { ++ t.Errorf("obtained %d identities, expected %d", numIdentities, numExpected) ++ } ++ ++ if identityName, expectedName := identities[0].Name, "Golang Gopher "; identityName != expectedName { ++ t.Errorf("obtained identity %s expected %s", identityName, expectedName) ++ } ++} ++ ++// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. ++func TestExternallyRevocableKey(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C ++ // according to this signature that appears within the key: ++ // :signature packet: algo 1, keyid A42704B92866382A ++ // version 4, created 1396409682, md5len 0, sigclass 0x1f ++ // digest algo 2, begin of digest a9 84 ++ // hashed subpkt 2 len 4 (sig created 2014-04-02) ++ // hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C) ++ // hashed subpkt 7 len 1 (not revocable) ++ // subpkt 16 len 8 (issuer key ID A42704B92866382A) ++ // data: [1024 bits] ++ ++ id := uint64(0xA42704B92866382A) ++ keys := kring.KeysById(id) ++ if len(keys) != 1 { ++ t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys)) ++ } ++} ++ ++func TestKeyRevocation(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(revokedKeyHex)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // revokedKeyHex contains these keys: ++ // pub 1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25] ++ // sub 1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25] ++ ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60} ++ ++ for _, id := range ids { ++ keys := kring.KeysById(id) ++ if len(keys) != 1 { ++ t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys)) ++ } ++ keys = kring.KeysByIdUsage(id, 0) ++ if len(keys) != 0 { ++ t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys)) ++ } ++ } ++} ++ ++func TestKeyWithRevokedSubKey(t *testing.T) { ++ // This key contains a revoked sub key: ++ // pub rsa1024/0x4CBD826C39074E38 2018-06-14 [SC] ++ // Key fingerprint = 3F95 169F 3FFA 7D3F 2B47 6F0C 4CBD 826C 3907 4E38 ++ // uid Golang Gopher ++ // sub rsa1024/0x945DB1AF61D85727 2018-06-14 [S] [revoked: 2018-06-14] ++ ++ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(keyWithSubKey)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if len(keys) != 1 { ++ t.Fatal("Failed to read key with a sub key") ++ } ++ ++ identity := keys[0].Identities["Golang Gopher "] ++ ++ // Test for an issue where Subkey Binding Signatures (RFC 4880 5.2.1) were added to the identity ++ // preceding the Subkey Packet if the Subkey Packet was followed by more than one signature. ++ // For example, the current key has the following layout: ++ // PUBKEY UID SELFSIG SUBKEY REV SELFSIG ++ // The last SELFSIG would be added to the UID's signatures. This is wrong. ++ if numIdentitySigs, numExpected := len(identity.Signatures), 0; numIdentitySigs != numExpected { ++ t.Fatalf("got %d identity signatures, expected %d", numIdentitySigs, numExpected) ++ } ++ ++ if numSubKeys, numExpected := len(keys[0].Subkeys), 1; numSubKeys != numExpected { ++ t.Fatalf("got %d subkeys, expected %d", numSubKeys, numExpected) ++ } ++ ++ subKey := keys[0].Subkeys[0] ++ if subKey.Sig == nil { ++ t.Fatalf("subkey signature is nil") ++ } ++ ++} ++ ++func TestSubkeyRevocation(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(revokedSubkeyHex)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // revokedSubkeyHex contains these keys: ++ // pub 1024R/4EF7E4BECCDE97F0 2014-03-25 ++ // sub 1024R/D63636E2B96AE423 2014-03-25 ++ // sub 1024D/DBCE4EE19529437F 2014-03-25 ++ // sub 1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25] ++ validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F} ++ revokedKey := uint64(0x677815E371C2FD23) ++ ++ for _, id := range validKeys { ++ keys := kring.KeysById(id) ++ if len(keys) != 1 { ++ t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys)) ++ } ++ keys = kring.KeysByIdUsage(id, 0) ++ if len(keys) != 1 { ++ t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys)) ++ } ++ } ++ ++ keys := kring.KeysById(revokedKey) ++ if len(keys) != 1 { ++ t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys)) ++ } ++ ++ keys = kring.KeysByIdUsage(revokedKey, 0) ++ if len(keys) != 0 { ++ t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys)) ++ } ++} ++ ++func TestKeyWithSubKeyAndBadSelfSigOrder(t *testing.T) { ++ // This key was altered so that the self signatures following the ++ // subkey are in a sub-optimal order. ++ // ++ // Note: Should someone have to create a similar key again, look into ++ // gpgsplit, gpg --dearmor, and gpg --enarmor. ++ // ++ // The packet ordering is the following: ++ // PUBKEY UID UIDSELFSIG SUBKEY SELFSIG1 SELFSIG2 ++ // ++ // Where: ++ // SELFSIG1 expires on 2018-06-14 and was created first ++ // SELFSIG2 does not expire and was created after SELFSIG1 ++ // ++ // Test for RFC 4880 5.2.3.3: ++ // > An implementation that encounters multiple self-signatures on the ++ // > same object may resolve the ambiguity in any way it sees fit, but it ++ // > is RECOMMENDED that priority be given to the most recent self- ++ // > signature. ++ // ++ // This means that we should keep SELFSIG2. ++ ++ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(keyWithSubKeyAndBadSelfSigOrder)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if len(keys) != 1 { ++ t.Fatal("Failed to read key with a sub key and a bad selfsig packet order") ++ } ++ ++ key := keys[0] ++ ++ if numKeys, expected := len(key.Subkeys), 1; numKeys != expected { ++ t.Fatalf("Read %d subkeys, expected %d", numKeys, expected) ++ } ++ ++ subKey := key.Subkeys[0] ++ ++ if lifetime := subKey.Sig.KeyLifetimeSecs; lifetime != nil { ++ t.Errorf("The signature has a key lifetime (%d), but it should be nil", *lifetime) ++ } ++ ++} ++ ++func TestKeyUsage(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // subkeyUsageHex contains these keys: ++ // pub 1024R/2866382A created: 2014-04-01 expires: never usage: SC ++ // sub 1024R/936C9153 created: 2014-04-01 expires: never usage: E ++ // sub 1024R/64D5F5BB created: 2014-04-02 expires: never usage: E ++ // sub 1024D/BC0BA992 created: 2014-04-02 expires: never usage: S ++ certifiers := []uint64{0xA42704B92866382A} ++ signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992} ++ encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB} ++ ++ for _, id := range certifiers { ++ keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify) ++ if len(keys) == 1 { ++ if keys[0].PublicKey.KeyId != id { ++ t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId) ++ } ++ } else { ++ t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys)) ++ } ++ } ++ ++ for _, id := range signers { ++ keys := kring.KeysByIdUsage(id, packet.KeyFlagSign) ++ if len(keys) == 1 { ++ if keys[0].PublicKey.KeyId != id { ++ t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId) ++ } ++ } else { ++ t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys)) ++ } ++ ++ // This keyring contains no encryption keys that are also good for signing. ++ keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) ++ if len(keys) != 0 { ++ t.Errorf("Unexpected match for encryption key id %X", id) ++ } ++ } ++ ++ for _, id := range encrypters { ++ keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) ++ if len(keys) == 1 { ++ if keys[0].PublicKey.KeyId != id { ++ t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId) ++ } ++ } else { ++ t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys)) ++ } ++ ++ // This keyring contains no encryption keys that are also good for signing. ++ keys = kring.KeysByIdUsage(id, packet.KeyFlagSign) ++ if len(keys) != 0 { ++ t.Errorf("Unexpected match for signing key id %X", id) ++ } ++ } ++} ++ ++func TestIdVerification(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil { ++ t.Fatal(err) ++ } ++ ++ const identity = "Test Key 1 (RSA)" ++ if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil { ++ t.Fatal(err) ++ } ++ ++ ident, ok := kring[0].Identities[identity] ++ if !ok { ++ t.Fatal("identity missing from key after signing") ++ } ++ ++ checked := false ++ for _, sig := range ident.Signatures { ++ if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId { ++ continue ++ } ++ ++ if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil { ++ t.Fatalf("error verifying new identity signature: %s", err) ++ } ++ checked = true ++ break ++ } ++ ++ if !checked { ++ t.Fatal("didn't find identity signature in Entity") ++ } ++} ++ ++func TestNewEntityWithPreferredHash(t *testing.T) { ++ c := &packet.Config{ ++ DefaultHash: crypto.SHA256, ++ } ++ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ for _, identity := range entity.Identities { ++ if len(identity.SelfSignature.PreferredHash) == 0 { ++ t.Fatal("didn't find a preferred hash in self signature") ++ } ++ ph := hashToHashId(c.DefaultHash) ++ if identity.SelfSignature.PreferredHash[0] != ph { ++ t.Fatalf("Expected preferred hash to be %d, got %d", ph, identity.SelfSignature.PreferredHash[0]) ++ } ++ } ++} ++ ++func TestNewEntityWithoutPreferredHash(t *testing.T) { ++ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ for _, identity := range entity.Identities { ++ if len(identity.SelfSignature.PreferredHash) != 0 { ++ t.Fatalf("Expected preferred hash to be empty but got length %d", len(identity.SelfSignature.PreferredHash)) ++ } ++ } ++} ++ ++func TestNewEntityCorrectName(t *testing.T) { ++ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if len(entity.Identities) != 1 { ++ t.Fatalf("len(entity.Identities) = %d, want 1", len(entity.Identities)) ++ } ++ var got string ++ for _, i := range entity.Identities { ++ got = i.Name ++ } ++ want := "Golang Gopher (Test Key) " ++ if got != want { ++ t.Fatalf("Identity.Name = %q, want %q", got, want) ++ } ++} ++ ++func TestNewEntityWithPreferredSymmetric(t *testing.T) { ++ c := &packet.Config{ ++ DefaultCipher: packet.CipherAES256, ++ } ++ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ for _, identity := range entity.Identities { ++ if len(identity.SelfSignature.PreferredSymmetric) == 0 { ++ t.Fatal("didn't find a preferred cipher in self signature") ++ } ++ if identity.SelfSignature.PreferredSymmetric[0] != uint8(c.DefaultCipher) { ++ t.Fatalf("Expected preferred cipher to be %d, got %d", uint8(c.DefaultCipher), identity.SelfSignature.PreferredSymmetric[0]) ++ } ++ } ++} ++ ++func TestNewEntityWithoutPreferredSymmetric(t *testing.T) { ++ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ for _, identity := range entity.Identities { ++ if len(identity.SelfSignature.PreferredSymmetric) != 0 { ++ t.Fatalf("Expected preferred cipher to be empty but got length %d", len(identity.SelfSignature.PreferredSymmetric)) ++ } ++ } ++} ++ ++func TestNewEntityPublicSerialization(t *testing.T) { ++ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) ++ if err != nil { ++ t.Fatal(err) ++ } ++ serializedEntity := bytes.NewBuffer(nil) ++ entity.Serialize(serializedEntity) ++ ++ _, err = ReadEntity(packet.NewReader(bytes.NewBuffer(serializedEntity.Bytes()))) ++ if err != nil { ++ t.Fatal(err) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go +new file mode 100644 +index 00000000000000..353f945247cfdc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go +@@ -0,0 +1,123 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "compress/bzip2" ++ "compress/flate" ++ "compress/zlib" ++ "golang.org/x/crypto/openpgp/errors" ++ "io" ++ "strconv" ++) ++ ++// Compressed represents a compressed OpenPGP packet. The decompressed contents ++// will contain more OpenPGP packets. See RFC 4880, section 5.6. ++type Compressed struct { ++ Body io.Reader ++} ++ ++const ( ++ NoCompression = flate.NoCompression ++ BestSpeed = flate.BestSpeed ++ BestCompression = flate.BestCompression ++ DefaultCompression = flate.DefaultCompression ++) ++ ++// CompressionConfig contains compressor configuration settings. ++type CompressionConfig struct { ++ // Level is the compression level to use. It must be set to ++ // between -1 and 9, with -1 causing the compressor to use the ++ // default compression level, 0 causing the compressor to use ++ // no compression and 1 to 9 representing increasing (better, ++ // slower) compression levels. If Level is less than -1 or ++ // more then 9, a non-nil error will be returned during ++ // encryption. See the constants above for convenient common ++ // settings for Level. ++ Level int ++} ++ ++func (c *Compressed) parse(r io.Reader) error { ++ var buf [1]byte ++ _, err := readFull(r, buf[:]) ++ if err != nil { ++ return err ++ } ++ ++ switch buf[0] { ++ case 1: ++ c.Body = flate.NewReader(r) ++ case 2: ++ c.Body, err = zlib.NewReader(r) ++ case 3: ++ c.Body = bzip2.NewReader(r) ++ default: ++ err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) ++ } ++ ++ return err ++} ++ ++// compressedWriteCloser represents the serialized compression stream ++// header and the compressor. Its Close() method ensures that both the ++// compressor and serialized stream header are closed. Its Write() ++// method writes to the compressor. ++type compressedWriteCloser struct { ++ sh io.Closer // Stream Header ++ c io.WriteCloser // Compressor ++} ++ ++func (cwc compressedWriteCloser) Write(p []byte) (int, error) { ++ return cwc.c.Write(p) ++} ++ ++func (cwc compressedWriteCloser) Close() (err error) { ++ err = cwc.c.Close() ++ if err != nil { ++ return err ++ } ++ ++ return cwc.sh.Close() ++} ++ ++// SerializeCompressed serializes a compressed data packet to w and ++// returns a WriteCloser to which the literal data packets themselves ++// can be written and which MUST be closed on completion. If cc is ++// nil, sensible defaults will be used to configure the compression ++// algorithm. ++func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { ++ compressed, err := serializeStreamHeader(w, packetTypeCompressed) ++ if err != nil { ++ return ++ } ++ ++ _, err = compressed.Write([]byte{uint8(algo)}) ++ if err != nil { ++ return ++ } ++ ++ level := DefaultCompression ++ if cc != nil { ++ level = cc.Level ++ } ++ ++ var compressor io.WriteCloser ++ switch algo { ++ case CompressionZIP: ++ compressor, err = flate.NewWriter(compressed, level) ++ case CompressionZLIB: ++ compressor, err = zlib.NewWriterLevel(compressed, level) ++ default: ++ s := strconv.Itoa(int(algo)) ++ err = errors.UnsupportedError("Unsupported compression algorithm: " + s) ++ } ++ if err != nil { ++ return ++ } ++ ++ literaldata = compressedWriteCloser{compressed, compressor} ++ ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go +new file mode 100644 +index 00000000000000..37fcc0b097bebd +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go +@@ -0,0 +1,40 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "io" ++ "testing" ++) ++ ++func TestCompressed(t *testing.T) { ++ packet, err := Read(readerFromHex(compressedHex)) ++ if err != nil { ++ t.Errorf("failed to read Compressed: %s", err) ++ return ++ } ++ ++ c, ok := packet.(*Compressed) ++ if !ok { ++ t.Error("didn't find Compressed packet") ++ return ++ } ++ ++ contents, err := io.ReadAll(c.Body) ++ if err != nil && err != io.EOF { ++ t.Error(err) ++ return ++ } ++ ++ expected, _ := hex.DecodeString(compressedExpectedHex) ++ if !bytes.Equal(expected, contents) { ++ t.Errorf("got:%x want:%x", contents, expected) ++ } ++} ++ ++const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700" ++const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a" +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/config.go b/ms_mod/golang.org/x/crypto/openpgp/packet/config.go +new file mode 100644 +index 00000000000000..c76eecc963acd2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/config.go +@@ -0,0 +1,91 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "crypto" ++ "crypto/rand" ++ "io" ++ "time" ++) ++ ++// Config collects a number of parameters along with sensible defaults. ++// A nil *Config is valid and results in all default values. ++type Config struct { ++ // Rand provides the source of entropy. ++ // If nil, the crypto/rand Reader is used. ++ Rand io.Reader ++ // DefaultHash is the default hash function to be used. ++ // If zero, SHA-256 is used. ++ DefaultHash crypto.Hash ++ // DefaultCipher is the cipher to be used. ++ // If zero, AES-128 is used. ++ DefaultCipher CipherFunction ++ // Time returns the current time as the number of seconds since the ++ // epoch. If Time is nil, time.Now is used. ++ Time func() time.Time ++ // DefaultCompressionAlgo is the compression algorithm to be ++ // applied to the plaintext before encryption. If zero, no ++ // compression is done. ++ DefaultCompressionAlgo CompressionAlgo ++ // CompressionConfig configures the compression settings. ++ CompressionConfig *CompressionConfig ++ // S2KCount is only used for symmetric encryption. It ++ // determines the strength of the passphrase stretching when ++ // the said passphrase is hashed to produce a key. S2KCount ++ // should be between 1024 and 65011712, inclusive. If Config ++ // is nil or S2KCount is 0, the value 65536 used. Not all ++ // values in the above range can be represented. S2KCount will ++ // be rounded up to the next representable value if it cannot ++ // be encoded exactly. When set, it is strongly encrouraged to ++ // use a value that is at least 65536. See RFC 4880 Section ++ // 3.7.1.3. ++ S2KCount int ++ // RSABits is the number of bits in new RSA keys made with NewEntity. ++ // If zero, then 2048 bit keys are created. ++ RSABits int ++} ++ ++func (c *Config) Random() io.Reader { ++ if c == nil || c.Rand == nil { ++ return rand.Reader ++ } ++ return c.Rand ++} ++ ++func (c *Config) Hash() crypto.Hash { ++ if c == nil || uint(c.DefaultHash) == 0 { ++ return crypto.SHA256 ++ } ++ return c.DefaultHash ++} ++ ++func (c *Config) Cipher() CipherFunction { ++ if c == nil || uint8(c.DefaultCipher) == 0 { ++ return CipherAES128 ++ } ++ return c.DefaultCipher ++} ++ ++func (c *Config) Now() time.Time { ++ if c == nil || c.Time == nil { ++ return time.Now() ++ } ++ return c.Time() ++} ++ ++func (c *Config) Compression() CompressionAlgo { ++ if c == nil { ++ return CompressionNone ++ } ++ return c.DefaultCompressionAlgo ++} ++ ++func (c *Config) PasswordHashIterations() int { ++ if c == nil || c.S2KCount == 0 { ++ return 0 ++ } ++ return c.S2KCount ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go +new file mode 100644 +index 00000000000000..6d7639722c906b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go +@@ -0,0 +1,208 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "crypto" ++ "crypto/rsa" ++ "encoding/binary" ++ "io" ++ "math/big" ++ "strconv" ++ ++ "golang.org/x/crypto/openpgp/elgamal" ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++const encryptedKeyVersion = 3 ++ ++// EncryptedKey represents a public-key encrypted session key. See RFC 4880, ++// section 5.1. ++type EncryptedKey struct { ++ KeyId uint64 ++ Algo PublicKeyAlgorithm ++ CipherFunc CipherFunction // only valid after a successful Decrypt ++ Key []byte // only valid after a successful Decrypt ++ ++ encryptedMPI1, encryptedMPI2 parsedMPI ++} ++ ++func (e *EncryptedKey) parse(r io.Reader) (err error) { ++ var buf [10]byte ++ _, err = readFull(r, buf[:]) ++ if err != nil { ++ return ++ } ++ if buf[0] != encryptedKeyVersion { ++ return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) ++ } ++ e.KeyId = binary.BigEndian.Uint64(buf[1:9]) ++ e.Algo = PublicKeyAlgorithm(buf[9]) ++ switch e.Algo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: ++ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ case PubKeyAlgoElGamal: ++ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ } ++ _, err = consumeAll(r) ++ return ++} ++ ++func checksumKeyMaterial(key []byte) uint16 { ++ var checksum uint16 ++ for _, v := range key { ++ checksum += uint16(v) ++ } ++ return checksum ++} ++ ++// Decrypt decrypts an encrypted session key with the given private key. The ++// private key must have been decrypted first. ++// If config is nil, sensible defaults will be used. ++func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { ++ var err error ++ var b []byte ++ ++ // TODO(agl): use session key decryption routines here to avoid ++ // padding oracle attacks. ++ switch priv.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: ++ // Supports both *rsa.PrivateKey and crypto.Decrypter ++ k := priv.PrivateKey.(crypto.Decrypter) ++ b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) ++ case PubKeyAlgoElGamal: ++ c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) ++ c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) ++ b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) ++ default: ++ err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) ++ } ++ ++ if err != nil { ++ return err ++ } ++ ++ e.CipherFunc = CipherFunction(b[0]) ++ e.Key = b[1 : len(b)-2] ++ expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) ++ checksum := checksumKeyMaterial(e.Key) ++ if checksum != expectedChecksum { ++ return errors.StructuralError("EncryptedKey checksum incorrect") ++ } ++ ++ return nil ++} ++ ++// Serialize writes the encrypted key packet, e, to w. ++func (e *EncryptedKey) Serialize(w io.Writer) error { ++ var mpiLen int ++ switch e.Algo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: ++ mpiLen = 2 + len(e.encryptedMPI1.bytes) ++ case PubKeyAlgoElGamal: ++ mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) ++ default: ++ return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) ++ } ++ ++ serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) ++ ++ w.Write([]byte{encryptedKeyVersion}) ++ binary.Write(w, binary.BigEndian, e.KeyId) ++ w.Write([]byte{byte(e.Algo)}) ++ ++ switch e.Algo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: ++ writeMPIs(w, e.encryptedMPI1) ++ case PubKeyAlgoElGamal: ++ writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) ++ default: ++ panic("internal error") ++ } ++ ++ return nil ++} ++ ++// SerializeEncryptedKey serializes an encrypted key packet to w that contains ++// key, encrypted to pub. ++// If config is nil, sensible defaults will be used. ++func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { ++ var buf [10]byte ++ buf[0] = encryptedKeyVersion ++ binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) ++ buf[9] = byte(pub.PubKeyAlgo) ++ ++ keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) ++ keyBlock[0] = byte(cipherFunc) ++ copy(keyBlock[1:], key) ++ checksum := checksumKeyMaterial(key) ++ keyBlock[1+len(key)] = byte(checksum >> 8) ++ keyBlock[1+len(key)+1] = byte(checksum) ++ ++ switch pub.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: ++ return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) ++ case PubKeyAlgoElGamal: ++ return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) ++ case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: ++ return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) ++ } ++ ++ return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) ++} ++ ++func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { ++ cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) ++ if err != nil { ++ return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) ++ } ++ ++ packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) ++ ++ err = serializeHeader(w, packetTypeEncryptedKey, packetLen) ++ if err != nil { ++ return err ++ } ++ _, err = w.Write(header[:]) ++ if err != nil { ++ return err ++ } ++ return writeMPI(w, 8*uint16(len(cipherText)), cipherText) ++} ++ ++func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { ++ c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) ++ if err != nil { ++ return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) ++ } ++ ++ packetLen := 10 /* header length */ ++ packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 ++ packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 ++ ++ err = serializeHeader(w, packetTypeEncryptedKey, packetLen) ++ if err != nil { ++ return err ++ } ++ _, err = w.Write(header[:]) ++ if err != nil { ++ return err ++ } ++ err = writeBig(w, c1) ++ if err != nil { ++ return err ++ } ++ return writeBig(w, c2) ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go +new file mode 100644 +index 00000000000000..ecb22bc2ba8c8f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go +@@ -0,0 +1,220 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/rsa" ++ "encoding/hex" ++ "fmt" ++ "io" ++ "math/big" ++ "testing" ++) ++ ++func bigFromBase10(s string) *big.Int { ++ b, ok := new(big.Int).SetString(s, 10) ++ if !ok { ++ panic("bigFromBase10 failed") ++ } ++ return b ++} ++ ++var encryptedKeyPub = rsa.PublicKey{ ++ E: 65537, ++ N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"), ++} ++ ++var encryptedKeyRSAPriv = &rsa.PrivateKey{ ++ PublicKey: encryptedKeyPub, ++ D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"), ++} ++ ++var encryptedKeyPriv = &PrivateKey{ ++ PublicKey: PublicKey{ ++ PubKeyAlgo: PubKeyAlgoRSA, ++ }, ++ PrivateKey: encryptedKeyRSAPriv, ++} ++ ++func TestDecryptingEncryptedKey(t *testing.T) { ++ for i, encryptedKeyHex := range []string{ ++ "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8", ++ // MPI can be shorter than the length of the key. ++ "c18b032a67d68660df41c70103f8e520c52ae9807183c669ce26e772e482dc5d8cf60e6f59316e145be14d2e5221ee69550db1d5618a8cb002a719f1f0b9345bde21536d410ec90ba86cac37748dec7933eb7f9873873b2d61d3321d1cd44535014f6df58f7bc0c7afb5edc38e1a974428997d2f747f9a173bea9ca53079b409517d332df62d805564cffc9be6", ++ } { ++ const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" ++ ++ p, err := Read(readerFromHex(encryptedKeyHex)) ++ if err != nil { ++ t.Errorf("#%d: error from Read: %s", i, err) ++ return ++ } ++ ek, ok := p.(*EncryptedKey) ++ if !ok { ++ t.Errorf("#%d: didn't parse an EncryptedKey, got %#v", i, p) ++ return ++ } ++ ++ if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { ++ t.Errorf("#%d: unexpected EncryptedKey contents: %#v", i, ek) ++ return ++ } ++ ++ err = ek.Decrypt(encryptedKeyPriv, nil) ++ if err != nil { ++ t.Errorf("#%d: error from Decrypt: %s", i, err) ++ return ++ } ++ ++ if ek.CipherFunc != CipherAES256 { ++ t.Errorf("#%d: unexpected EncryptedKey contents: %#v", i, ek) ++ return ++ } ++ ++ keyHex := fmt.Sprintf("%x", ek.Key) ++ if keyHex != expectedKeyHex { ++ t.Errorf("#%d: bad key, got %s want %s", i, keyHex, expectedKeyHex) ++ } ++ } ++} ++ ++type rsaDecrypter struct { ++ rsaPrivateKey *rsa.PrivateKey ++ decryptCount int ++} ++ ++func (r *rsaDecrypter) Public() crypto.PublicKey { ++ return &r.rsaPrivateKey.PublicKey ++} ++ ++func (r *rsaDecrypter) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { ++ r.decryptCount++ ++ return r.rsaPrivateKey.Decrypt(rand, msg, opts) ++} ++ ++func TestRSADecrypter(t *testing.T) { ++ const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" ++ ++ const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" ++ ++ p, err := Read(readerFromHex(encryptedKeyHex)) ++ if err != nil { ++ t.Errorf("error from Read: %s", err) ++ return ++ } ++ ek, ok := p.(*EncryptedKey) ++ if !ok { ++ t.Errorf("didn't parse an EncryptedKey, got %#v", p) ++ return ++ } ++ ++ if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { ++ t.Errorf("unexpected EncryptedKey contents: %#v", ek) ++ return ++ } ++ ++ customDecrypter := &rsaDecrypter{ ++ rsaPrivateKey: encryptedKeyRSAPriv, ++ } ++ ++ customKeyPriv := &PrivateKey{ ++ PublicKey: PublicKey{ ++ PubKeyAlgo: PubKeyAlgoRSA, ++ }, ++ PrivateKey: customDecrypter, ++ } ++ ++ err = ek.Decrypt(customKeyPriv, nil) ++ if err != nil { ++ t.Errorf("error from Decrypt: %s", err) ++ return ++ } ++ ++ if ek.CipherFunc != CipherAES256 { ++ t.Errorf("unexpected EncryptedKey contents: %#v", ek) ++ return ++ } ++ ++ keyHex := fmt.Sprintf("%x", ek.Key) ++ if keyHex != expectedKeyHex { ++ t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) ++ } ++ ++ if customDecrypter.decryptCount != 1 { ++ t.Errorf("Expected customDecrypter.Decrypt() to be called 1 time, but was called %d times", customDecrypter.decryptCount) ++ } ++} ++ ++func TestEncryptingEncryptedKey(t *testing.T) { ++ key := []byte{1, 2, 3, 4} ++ const expectedKeyHex = "01020304" ++ const keyId = 42 ++ ++ pub := &PublicKey{ ++ PublicKey: &encryptedKeyPub, ++ KeyId: keyId, ++ PubKeyAlgo: PubKeyAlgoRSAEncryptOnly, ++ } ++ ++ buf := new(bytes.Buffer) ++ err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil) ++ if err != nil { ++ t.Errorf("error writing encrypted key packet: %s", err) ++ } ++ ++ p, err := Read(buf) ++ if err != nil { ++ t.Errorf("error from Read: %s", err) ++ return ++ } ++ ek, ok := p.(*EncryptedKey) ++ if !ok { ++ t.Errorf("didn't parse an EncryptedKey, got %#v", p) ++ return ++ } ++ ++ if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly { ++ t.Errorf("unexpected EncryptedKey contents: %#v", ek) ++ return ++ } ++ ++ err = ek.Decrypt(encryptedKeyPriv, nil) ++ if err != nil { ++ t.Errorf("error from Decrypt: %s", err) ++ return ++ } ++ ++ if ek.CipherFunc != CipherAES128 { ++ t.Errorf("unexpected EncryptedKey contents: %#v", ek) ++ return ++ } ++ ++ keyHex := fmt.Sprintf("%x", ek.Key) ++ if keyHex != expectedKeyHex { ++ t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) ++ } ++} ++ ++func TestSerializingEncryptedKey(t *testing.T) { ++ const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" ++ ++ p, err := Read(readerFromHex(encryptedKeyHex)) ++ if err != nil { ++ t.Fatalf("error from Read: %s", err) ++ } ++ ek, ok := p.(*EncryptedKey) ++ if !ok { ++ t.Fatalf("didn't parse an EncryptedKey, got %#v", p) ++ } ++ ++ var buf bytes.Buffer ++ ek.Serialize(&buf) ++ ++ if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex { ++ t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/literal.go b/ms_mod/golang.org/x/crypto/openpgp/packet/literal.go +new file mode 100644 +index 00000000000000..1a9ec6e51e81d4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/literal.go +@@ -0,0 +1,89 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "encoding/binary" ++ "io" ++) ++ ++// LiteralData represents an encrypted file. See RFC 4880, section 5.9. ++type LiteralData struct { ++ IsBinary bool ++ FileName string ++ Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. ++ Body io.Reader ++} ++ ++// ForEyesOnly returns whether the contents of the LiteralData have been marked ++// as especially sensitive. ++func (l *LiteralData) ForEyesOnly() bool { ++ return l.FileName == "_CONSOLE" ++} ++ ++func (l *LiteralData) parse(r io.Reader) (err error) { ++ var buf [256]byte ++ ++ _, err = readFull(r, buf[:2]) ++ if err != nil { ++ return ++ } ++ ++ l.IsBinary = buf[0] == 'b' ++ fileNameLen := int(buf[1]) ++ ++ _, err = readFull(r, buf[:fileNameLen]) ++ if err != nil { ++ return ++ } ++ ++ l.FileName = string(buf[:fileNameLen]) ++ ++ _, err = readFull(r, buf[:4]) ++ if err != nil { ++ return ++ } ++ ++ l.Time = binary.BigEndian.Uint32(buf[:4]) ++ l.Body = r ++ return ++} ++ ++// SerializeLiteral serializes a literal data packet to w and returns a ++// WriteCloser to which the data itself can be written and which MUST be closed ++// on completion. The fileName is truncated to 255 bytes. ++func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { ++ var buf [4]byte ++ buf[0] = 't' ++ if isBinary { ++ buf[0] = 'b' ++ } ++ if len(fileName) > 255 { ++ fileName = fileName[:255] ++ } ++ buf[1] = byte(len(fileName)) ++ ++ inner, err := serializeStreamHeader(w, packetTypeLiteralData) ++ if err != nil { ++ return ++ } ++ ++ _, err = inner.Write(buf[:2]) ++ if err != nil { ++ return ++ } ++ _, err = inner.Write([]byte(fileName)) ++ if err != nil { ++ return ++ } ++ binary.BigEndian.PutUint32(buf[:], time) ++ _, err = inner.Write(buf[:]) ++ if err != nil { ++ return ++ } ++ ++ plaintext = inner ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go +new file mode 100644 +index 00000000000000..ce2a33a547cef9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go +@@ -0,0 +1,143 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 ++ ++package packet ++ ++import ( ++ "crypto/cipher" ++) ++ ++type ocfbEncrypter struct { ++ b cipher.Block ++ fre []byte ++ outUsed int ++} ++ ++// An OCFBResyncOption determines if the "resynchronization step" of OCFB is ++// performed. ++type OCFBResyncOption bool ++ ++const ( ++ OCFBResync OCFBResyncOption = true ++ OCFBNoResync OCFBResyncOption = false ++) ++ ++// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's ++// cipher feedback mode using the given cipher.Block, and an initial amount of ++// ciphertext. randData must be random bytes and be the same length as the ++// cipher.Block's block size. Resync determines if the "resynchronization step" ++// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on ++// this point. ++func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { ++ blockSize := block.BlockSize() ++ if len(randData) != blockSize { ++ return nil, nil ++ } ++ ++ x := &ocfbEncrypter{ ++ b: block, ++ fre: make([]byte, blockSize), ++ outUsed: 0, ++ } ++ prefix := make([]byte, blockSize+2) ++ ++ block.Encrypt(x.fre, x.fre) ++ for i := 0; i < blockSize; i++ { ++ prefix[i] = randData[i] ^ x.fre[i] ++ } ++ ++ block.Encrypt(x.fre, prefix[:blockSize]) ++ prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] ++ prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] ++ ++ if resync { ++ block.Encrypt(x.fre, prefix[2:]) ++ } else { ++ x.fre[0] = prefix[blockSize] ++ x.fre[1] = prefix[blockSize+1] ++ x.outUsed = 2 ++ } ++ return x, prefix ++} ++ ++func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { ++ for i := 0; i < len(src); i++ { ++ if x.outUsed == len(x.fre) { ++ x.b.Encrypt(x.fre, x.fre) ++ x.outUsed = 0 ++ } ++ ++ x.fre[x.outUsed] ^= src[i] ++ dst[i] = x.fre[x.outUsed] ++ x.outUsed++ ++ } ++} ++ ++type ocfbDecrypter struct { ++ b cipher.Block ++ fre []byte ++ outUsed int ++} ++ ++// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's ++// cipher feedback mode using the given cipher.Block. Prefix must be the first ++// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's ++// block size. If an incorrect key is detected then nil is returned. On ++// successful exit, blockSize+2 bytes of decrypted data are written into ++// prefix. Resync determines if the "resynchronization step" from RFC 4880, ++// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. ++func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { ++ blockSize := block.BlockSize() ++ if len(prefix) != blockSize+2 { ++ return nil ++ } ++ ++ x := &ocfbDecrypter{ ++ b: block, ++ fre: make([]byte, blockSize), ++ outUsed: 0, ++ } ++ prefixCopy := make([]byte, len(prefix)) ++ copy(prefixCopy, prefix) ++ ++ block.Encrypt(x.fre, x.fre) ++ for i := 0; i < blockSize; i++ { ++ prefixCopy[i] ^= x.fre[i] ++ } ++ ++ block.Encrypt(x.fre, prefix[:blockSize]) ++ prefixCopy[blockSize] ^= x.fre[0] ++ prefixCopy[blockSize+1] ^= x.fre[1] ++ ++ if prefixCopy[blockSize-2] != prefixCopy[blockSize] || ++ prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { ++ return nil ++ } ++ ++ if resync { ++ block.Encrypt(x.fre, prefix[2:]) ++ } else { ++ x.fre[0] = prefix[blockSize] ++ x.fre[1] = prefix[blockSize+1] ++ x.outUsed = 2 ++ } ++ copy(prefix, prefixCopy) ++ return x ++} ++ ++func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { ++ for i := 0; i < len(src); i++ { ++ if x.outUsed == len(x.fre) { ++ x.b.Encrypt(x.fre, x.fre) ++ x.outUsed = 0 ++ } ++ ++ c := src[i] ++ dst[i] = x.fre[x.outUsed] ^ src[i] ++ x.fre[x.outUsed] = c ++ x.outUsed++ ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go +new file mode 100644 +index 00000000000000..91022c042d4517 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go +@@ -0,0 +1,46 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto/aes" ++ "crypto/rand" ++ "testing" ++) ++ ++var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c} ++ ++func testOCFB(t *testing.T, resync OCFBResyncOption) { ++ block, err := aes.NewCipher(commonKey128) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ plaintext := []byte("this is the plaintext, which is long enough to span several blocks.") ++ randData := make([]byte, block.BlockSize()) ++ rand.Reader.Read(randData) ++ ocfb, prefix := NewOCFBEncrypter(block, randData, resync) ++ ciphertext := make([]byte, len(plaintext)) ++ ocfb.XORKeyStream(ciphertext, plaintext) ++ ++ ocfbdec := NewOCFBDecrypter(block, prefix, resync) ++ if ocfbdec == nil { ++ t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync) ++ return ++ } ++ plaintextCopy := make([]byte, len(plaintext)) ++ ocfbdec.XORKeyStream(plaintextCopy, ciphertext) ++ ++ if !bytes.Equal(plaintextCopy, plaintext) { ++ t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync) ++ } ++} ++ ++func TestOCFB(t *testing.T) { ++ testOCFB(t, OCFBNoResync) ++ testOCFB(t, OCFBResync) ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go +new file mode 100644 +index 00000000000000..1713503395e3c8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go +@@ -0,0 +1,73 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "crypto" ++ "encoding/binary" ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/s2k" ++ "io" ++ "strconv" ++) ++ ++// OnePassSignature represents a one-pass signature packet. See RFC 4880, ++// section 5.4. ++type OnePassSignature struct { ++ SigType SignatureType ++ Hash crypto.Hash ++ PubKeyAlgo PublicKeyAlgorithm ++ KeyId uint64 ++ IsLast bool ++} ++ ++const onePassSignatureVersion = 3 ++ ++func (ops *OnePassSignature) parse(r io.Reader) (err error) { ++ var buf [13]byte ++ ++ _, err = readFull(r, buf[:]) ++ if err != nil { ++ return ++ } ++ if buf[0] != onePassSignatureVersion { ++ err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) ++ } ++ ++ var ok bool ++ ops.Hash, ok = s2k.HashIdToHash(buf[2]) ++ if !ok { ++ return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) ++ } ++ ++ ops.SigType = SignatureType(buf[1]) ++ ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) ++ ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) ++ ops.IsLast = buf[12] != 0 ++ return ++} ++ ++// Serialize marshals the given OnePassSignature to w. ++func (ops *OnePassSignature) Serialize(w io.Writer) error { ++ var buf [13]byte ++ buf[0] = onePassSignatureVersion ++ buf[1] = uint8(ops.SigType) ++ var ok bool ++ buf[2], ok = s2k.HashToHashId(ops.Hash) ++ if !ok { ++ return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) ++ } ++ buf[3] = uint8(ops.PubKeyAlgo) ++ binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) ++ if ops.IsLast { ++ buf[12] = 1 ++ } ++ ++ if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { ++ return err ++ } ++ _, err := w.Write(buf[:]) ++ return err ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go +new file mode 100644 +index 00000000000000..3984477310fe70 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go +@@ -0,0 +1,161 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "io" ++ ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is ++// useful for splitting and storing the original packet contents separately, ++// handling unsupported packet types or accessing parts of the packet not yet ++// implemented by this package. ++type OpaquePacket struct { ++ // Packet type ++ Tag uint8 ++ // Reason why the packet was parsed opaquely ++ Reason error ++ // Binary contents of the packet data ++ Contents []byte ++} ++ ++func (op *OpaquePacket) parse(r io.Reader) (err error) { ++ op.Contents, err = io.ReadAll(r) ++ return ++} ++ ++// Serialize marshals the packet to a writer in its original form, including ++// the packet header. ++func (op *OpaquePacket) Serialize(w io.Writer) (err error) { ++ err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) ++ if err == nil { ++ _, err = w.Write(op.Contents) ++ } ++ return ++} ++ ++// Parse attempts to parse the opaque contents into a structure supported by ++// this package. If the packet is not known then the result will be another ++// OpaquePacket. ++func (op *OpaquePacket) Parse() (p Packet, err error) { ++ hdr := bytes.NewBuffer(nil) ++ err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) ++ if err != nil { ++ op.Reason = err ++ return op, err ++ } ++ p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) ++ if err != nil { ++ op.Reason = err ++ p = op ++ } ++ return ++} ++ ++// OpaqueReader reads OpaquePackets from an io.Reader. ++type OpaqueReader struct { ++ r io.Reader ++} ++ ++func NewOpaqueReader(r io.Reader) *OpaqueReader { ++ return &OpaqueReader{r: r} ++} ++ ++// Read the next OpaquePacket. ++func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { ++ tag, _, contents, err := readHeader(or.r) ++ if err != nil { ++ return ++ } ++ op = &OpaquePacket{Tag: uint8(tag), Reason: err} ++ err = op.parse(contents) ++ if err != nil { ++ consumeAll(contents) ++ } ++ return ++} ++ ++// OpaqueSubpacket represents an unparsed OpenPGP subpacket, ++// as found in signature and user attribute packets. ++type OpaqueSubpacket struct { ++ SubType uint8 ++ Contents []byte ++} ++ ++// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from ++// their byte representation. ++func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { ++ var ( ++ subHeaderLen int ++ subPacket *OpaqueSubpacket ++ ) ++ for len(contents) > 0 { ++ subHeaderLen, subPacket, err = nextSubpacket(contents) ++ if err != nil { ++ break ++ } ++ result = append(result, subPacket) ++ contents = contents[subHeaderLen+len(subPacket.Contents):] ++ } ++ return ++} ++ ++func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { ++ // RFC 4880, section 5.2.3.1 ++ var subLen uint32 ++ if len(contents) < 1 { ++ goto Truncated ++ } ++ subPacket = &OpaqueSubpacket{} ++ switch { ++ case contents[0] < 192: ++ subHeaderLen = 2 // 1 length byte, 1 subtype byte ++ if len(contents) < subHeaderLen { ++ goto Truncated ++ } ++ subLen = uint32(contents[0]) ++ contents = contents[1:] ++ case contents[0] < 255: ++ subHeaderLen = 3 // 2 length bytes, 1 subtype ++ if len(contents) < subHeaderLen { ++ goto Truncated ++ } ++ subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 ++ contents = contents[2:] ++ default: ++ subHeaderLen = 6 // 5 length bytes, 1 subtype ++ if len(contents) < subHeaderLen { ++ goto Truncated ++ } ++ subLen = uint32(contents[1])<<24 | ++ uint32(contents[2])<<16 | ++ uint32(contents[3])<<8 | ++ uint32(contents[4]) ++ contents = contents[5:] ++ } ++ if subLen > uint32(len(contents)) || subLen == 0 { ++ goto Truncated ++ } ++ subPacket.SubType = contents[0] ++ subPacket.Contents = contents[1:subLen] ++ return ++Truncated: ++ err = errors.StructuralError("subpacket truncated") ++ return ++} ++ ++func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { ++ buf := make([]byte, 6) ++ n := serializeSubpacketLength(buf, len(osp.Contents)+1) ++ buf[n] = osp.SubType ++ if _, err = w.Write(buf[:n+1]); err != nil { ++ return ++ } ++ _, err = w.Write(osp.Contents) ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go +new file mode 100644 +index 00000000000000..61159f468389e7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go +@@ -0,0 +1,67 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "io" ++ "testing" ++) ++ ++// Test packet.Read error handling in OpaquePacket.Parse, ++// which attempts to re-read an OpaquePacket as a supported ++// Packet type. ++func TestOpaqueParseReason(t *testing.T) { ++ buf, err := hex.DecodeString(UnsupportedKeyHex) ++ if err != nil { ++ t.Fatal(err) ++ } ++ or := NewOpaqueReader(bytes.NewBuffer(buf)) ++ count := 0 ++ badPackets := 0 ++ var uid *UserId ++ for { ++ op, err := or.Next() ++ if err == io.EOF { ++ break ++ } else if err != nil { ++ t.Errorf("#%d: opaque read error: %v", count, err) ++ break ++ } ++ // try to parse opaque packet ++ p, _ := op.Parse() ++ switch pkt := p.(type) { ++ case *UserId: ++ uid = pkt ++ case *OpaquePacket: ++ // If an OpaquePacket can't re-parse, packet.Read ++ // certainly had its reasons. ++ if pkt.Reason == nil { ++ t.Errorf("#%d: opaque packet, no reason", count) ++ } else { ++ badPackets++ ++ } ++ } ++ count++ ++ } ++ ++ const expectedBad = 3 ++ // Test post-conditions, make sure we actually parsed packets as expected. ++ if badPackets != expectedBad { ++ t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad) ++ } ++ if uid == nil { ++ t.Errorf("failed to find expected UID in unsupported keyring") ++ } else if uid.Id != "Armin M. Warda " { ++ t.Errorf("unexpected UID: %v", uid.Id) ++ } ++} ++ ++// This key material has public key and signature packet versions modified to ++// an unsupported value (1), so that trying to parse the OpaquePacket to ++// a typed packet will get an error. It also contains a GnuPG trust packet. ++// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g') ++const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/packet.go b/ms_mod/golang.org/x/crypto/openpgp/packet/packet.go +new file mode 100644 +index 00000000000000..0a19794a8e49c1 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/packet.go +@@ -0,0 +1,590 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package packet implements parsing and serialization of OpenPGP packets, as ++// specified in RFC 4880. ++// ++// Deprecated: this package is unmaintained except for security fixes. New ++// applications should consider a more focused, modern alternative to OpenPGP ++// for their specific task. If you are required to interoperate with OpenPGP ++// systems and need a maintained package, consider a community fork. ++// See https://golang.org/issue/44226. ++package packet // import "golang.org/x/crypto/openpgp/packet" ++ ++import ( ++ "bufio" ++ "crypto/aes" ++ "crypto/cipher" ++ "crypto/des" ++ "crypto/rsa" ++ "io" ++ "math/big" ++ "math/bits" ++ ++ "golang.org/x/crypto/cast5" ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++// readFull is the same as io.ReadFull except that reading zero bytes returns ++// ErrUnexpectedEOF rather than EOF. ++func readFull(r io.Reader, buf []byte) (n int, err error) { ++ n, err = io.ReadFull(r, buf) ++ if err == io.EOF { ++ err = io.ErrUnexpectedEOF ++ } ++ return ++} ++ ++// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. ++func readLength(r io.Reader) (length int64, isPartial bool, err error) { ++ var buf [4]byte ++ _, err = readFull(r, buf[:1]) ++ if err != nil { ++ return ++ } ++ switch { ++ case buf[0] < 192: ++ length = int64(buf[0]) ++ case buf[0] < 224: ++ length = int64(buf[0]-192) << 8 ++ _, err = readFull(r, buf[0:1]) ++ if err != nil { ++ return ++ } ++ length += int64(buf[0]) + 192 ++ case buf[0] < 255: ++ length = int64(1) << (buf[0] & 0x1f) ++ isPartial = true ++ default: ++ _, err = readFull(r, buf[0:4]) ++ if err != nil { ++ return ++ } ++ length = int64(buf[0])<<24 | ++ int64(buf[1])<<16 | ++ int64(buf[2])<<8 | ++ int64(buf[3]) ++ } ++ return ++} ++ ++// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. ++// The continuation lengths are parsed and removed from the stream and EOF is ++// returned at the end of the packet. See RFC 4880, section 4.2.2.4. ++type partialLengthReader struct { ++ r io.Reader ++ remaining int64 ++ isPartial bool ++} ++ ++func (r *partialLengthReader) Read(p []byte) (n int, err error) { ++ for r.remaining == 0 { ++ if !r.isPartial { ++ return 0, io.EOF ++ } ++ r.remaining, r.isPartial, err = readLength(r.r) ++ if err != nil { ++ return 0, err ++ } ++ } ++ ++ toRead := int64(len(p)) ++ if toRead > r.remaining { ++ toRead = r.remaining ++ } ++ ++ n, err = r.r.Read(p[:int(toRead)]) ++ r.remaining -= int64(n) ++ if n < int(toRead) && err == io.EOF { ++ err = io.ErrUnexpectedEOF ++ } ++ return ++} ++ ++// partialLengthWriter writes a stream of data using OpenPGP partial lengths. ++// See RFC 4880, section 4.2.2.4. ++type partialLengthWriter struct { ++ w io.WriteCloser ++ lengthByte [1]byte ++ sentFirst bool ++ buf []byte ++} ++ ++// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long. ++const minFirstPartialWrite = 512 ++ ++func (w *partialLengthWriter) Write(p []byte) (n int, err error) { ++ off := 0 ++ if !w.sentFirst { ++ if len(w.buf) > 0 || len(p) < minFirstPartialWrite { ++ off = len(w.buf) ++ w.buf = append(w.buf, p...) ++ if len(w.buf) < minFirstPartialWrite { ++ return len(p), nil ++ } ++ p = w.buf ++ w.buf = nil ++ } ++ w.sentFirst = true ++ } ++ ++ power := uint8(30) ++ for len(p) > 0 { ++ l := 1 << power ++ if len(p) < l { ++ power = uint8(bits.Len32(uint32(len(p)))) - 1 ++ l = 1 << power ++ } ++ w.lengthByte[0] = 224 + power ++ _, err = w.w.Write(w.lengthByte[:]) ++ if err == nil { ++ var m int ++ m, err = w.w.Write(p[:l]) ++ n += m ++ } ++ if err != nil { ++ if n < off { ++ return 0, err ++ } ++ return n - off, err ++ } ++ p = p[l:] ++ } ++ return n - off, nil ++} ++ ++func (w *partialLengthWriter) Close() error { ++ if len(w.buf) > 0 { ++ // In this case we can't send a 512 byte packet. ++ // Just send what we have. ++ p := w.buf ++ w.sentFirst = true ++ w.buf = nil ++ if _, err := w.Write(p); err != nil { ++ return err ++ } ++ } ++ ++ w.lengthByte[0] = 0 ++ _, err := w.w.Write(w.lengthByte[:]) ++ if err != nil { ++ return err ++ } ++ return w.w.Close() ++} ++ ++// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the ++// underlying Reader returns EOF before the limit has been reached. ++type spanReader struct { ++ r io.Reader ++ n int64 ++} ++ ++func (l *spanReader) Read(p []byte) (n int, err error) { ++ if l.n <= 0 { ++ return 0, io.EOF ++ } ++ if int64(len(p)) > l.n { ++ p = p[0:l.n] ++ } ++ n, err = l.r.Read(p) ++ l.n -= int64(n) ++ if l.n > 0 && err == io.EOF { ++ err = io.ErrUnexpectedEOF ++ } ++ return ++} ++ ++// readHeader parses a packet header and returns an io.Reader which will return ++// the contents of the packet. See RFC 4880, section 4.2. ++func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { ++ var buf [4]byte ++ _, err = io.ReadFull(r, buf[:1]) ++ if err != nil { ++ return ++ } ++ if buf[0]&0x80 == 0 { ++ err = errors.StructuralError("tag byte does not have MSB set") ++ return ++ } ++ if buf[0]&0x40 == 0 { ++ // Old format packet ++ tag = packetType((buf[0] & 0x3f) >> 2) ++ lengthType := buf[0] & 3 ++ if lengthType == 3 { ++ length = -1 ++ contents = r ++ return ++ } ++ lengthBytes := 1 << lengthType ++ _, err = readFull(r, buf[0:lengthBytes]) ++ if err != nil { ++ return ++ } ++ for i := 0; i < lengthBytes; i++ { ++ length <<= 8 ++ length |= int64(buf[i]) ++ } ++ contents = &spanReader{r, length} ++ return ++ } ++ ++ // New format packet ++ tag = packetType(buf[0] & 0x3f) ++ length, isPartial, err := readLength(r) ++ if err != nil { ++ return ++ } ++ if isPartial { ++ contents = &partialLengthReader{ ++ remaining: length, ++ isPartial: true, ++ r: r, ++ } ++ length = -1 ++ } else { ++ contents = &spanReader{r, length} ++ } ++ return ++} ++ ++// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section ++// 4.2. ++func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { ++ var buf [6]byte ++ var n int ++ ++ buf[0] = 0x80 | 0x40 | byte(ptype) ++ if length < 192 { ++ buf[1] = byte(length) ++ n = 2 ++ } else if length < 8384 { ++ length -= 192 ++ buf[1] = 192 + byte(length>>8) ++ buf[2] = byte(length) ++ n = 3 ++ } else { ++ buf[1] = 255 ++ buf[2] = byte(length >> 24) ++ buf[3] = byte(length >> 16) ++ buf[4] = byte(length >> 8) ++ buf[5] = byte(length) ++ n = 6 ++ } ++ ++ _, err = w.Write(buf[:n]) ++ return ++} ++ ++// serializeStreamHeader writes an OpenPGP packet header to w where the ++// length of the packet is unknown. It returns a io.WriteCloser which can be ++// used to write the contents of the packet. See RFC 4880, section 4.2. ++func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { ++ var buf [1]byte ++ buf[0] = 0x80 | 0x40 | byte(ptype) ++ _, err = w.Write(buf[:]) ++ if err != nil { ++ return ++ } ++ out = &partialLengthWriter{w: w} ++ return ++} ++ ++// Packet represents an OpenPGP packet. Users are expected to try casting ++// instances of this interface to specific packet types. ++type Packet interface { ++ parse(io.Reader) error ++} ++ ++// consumeAll reads from the given Reader until error, returning the number of ++// bytes read. ++func consumeAll(r io.Reader) (n int64, err error) { ++ var m int ++ var buf [1024]byte ++ ++ for { ++ m, err = r.Read(buf[:]) ++ n += int64(m) ++ if err == io.EOF { ++ err = nil ++ return ++ } ++ if err != nil { ++ return ++ } ++ } ++} ++ ++// packetType represents the numeric ids of the different OpenPGP packet types. See ++// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 ++type packetType uint8 ++ ++const ( ++ packetTypeEncryptedKey packetType = 1 ++ packetTypeSignature packetType = 2 ++ packetTypeSymmetricKeyEncrypted packetType = 3 ++ packetTypeOnePassSignature packetType = 4 ++ packetTypePrivateKey packetType = 5 ++ packetTypePublicKey packetType = 6 ++ packetTypePrivateSubkey packetType = 7 ++ packetTypeCompressed packetType = 8 ++ packetTypeSymmetricallyEncrypted packetType = 9 ++ packetTypeLiteralData packetType = 11 ++ packetTypeUserId packetType = 13 ++ packetTypePublicSubkey packetType = 14 ++ packetTypeUserAttribute packetType = 17 ++ packetTypeSymmetricallyEncryptedMDC packetType = 18 ++) ++ ++// peekVersion detects the version of a public key packet about to ++// be read. A bufio.Reader at the original position of the io.Reader ++// is returned. ++func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { ++ bufr = bufio.NewReader(r) ++ var verBuf []byte ++ if verBuf, err = bufr.Peek(1); err != nil { ++ return ++ } ++ ver = verBuf[0] ++ return ++} ++ ++// Read reads a single OpenPGP packet from the given io.Reader. If there is an ++// error parsing a packet, the whole packet is consumed from the input. ++func Read(r io.Reader) (p Packet, err error) { ++ tag, _, contents, err := readHeader(r) ++ if err != nil { ++ return ++ } ++ ++ switch tag { ++ case packetTypeEncryptedKey: ++ p = new(EncryptedKey) ++ case packetTypeSignature: ++ var version byte ++ // Detect signature version ++ if contents, version, err = peekVersion(contents); err != nil { ++ return ++ } ++ if version < 4 { ++ p = new(SignatureV3) ++ } else { ++ p = new(Signature) ++ } ++ case packetTypeSymmetricKeyEncrypted: ++ p = new(SymmetricKeyEncrypted) ++ case packetTypeOnePassSignature: ++ p = new(OnePassSignature) ++ case packetTypePrivateKey, packetTypePrivateSubkey: ++ pk := new(PrivateKey) ++ if tag == packetTypePrivateSubkey { ++ pk.IsSubkey = true ++ } ++ p = pk ++ case packetTypePublicKey, packetTypePublicSubkey: ++ var version byte ++ if contents, version, err = peekVersion(contents); err != nil { ++ return ++ } ++ isSubkey := tag == packetTypePublicSubkey ++ if version < 4 { ++ p = &PublicKeyV3{IsSubkey: isSubkey} ++ } else { ++ p = &PublicKey{IsSubkey: isSubkey} ++ } ++ case packetTypeCompressed: ++ p = new(Compressed) ++ case packetTypeSymmetricallyEncrypted: ++ p = new(SymmetricallyEncrypted) ++ case packetTypeLiteralData: ++ p = new(LiteralData) ++ case packetTypeUserId: ++ p = new(UserId) ++ case packetTypeUserAttribute: ++ p = new(UserAttribute) ++ case packetTypeSymmetricallyEncryptedMDC: ++ se := new(SymmetricallyEncrypted) ++ se.MDC = true ++ p = se ++ default: ++ err = errors.UnknownPacketTypeError(tag) ++ } ++ if p != nil { ++ err = p.parse(contents) ++ } ++ if err != nil { ++ consumeAll(contents) ++ } ++ return ++} ++ ++// SignatureType represents the different semantic meanings of an OpenPGP ++// signature. See RFC 4880, section 5.2.1. ++type SignatureType uint8 ++ ++const ( ++ SigTypeBinary SignatureType = 0 ++ SigTypeText = 1 ++ SigTypeGenericCert = 0x10 ++ SigTypePersonaCert = 0x11 ++ SigTypeCasualCert = 0x12 ++ SigTypePositiveCert = 0x13 ++ SigTypeSubkeyBinding = 0x18 ++ SigTypePrimaryKeyBinding = 0x19 ++ SigTypeDirectSignature = 0x1F ++ SigTypeKeyRevocation = 0x20 ++ SigTypeSubkeyRevocation = 0x28 ++) ++ ++// PublicKeyAlgorithm represents the different public key system specified for ++// OpenPGP. See ++// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 ++type PublicKeyAlgorithm uint8 ++ ++const ( ++ PubKeyAlgoRSA PublicKeyAlgorithm = 1 ++ PubKeyAlgoElGamal PublicKeyAlgorithm = 16 ++ PubKeyAlgoDSA PublicKeyAlgorithm = 17 ++ // RFC 6637, Section 5. ++ PubKeyAlgoECDH PublicKeyAlgorithm = 18 ++ PubKeyAlgoECDSA PublicKeyAlgorithm = 19 ++ ++ // Deprecated in RFC 4880, Section 13.5. Use key flags instead. ++ PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 ++ PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 ++) ++ ++// CanEncrypt returns true if it's possible to encrypt a message to a public ++// key of the given type. ++func (pka PublicKeyAlgorithm) CanEncrypt() bool { ++ switch pka { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: ++ return true ++ } ++ return false ++} ++ ++// CanSign returns true if it's possible for a public key of the given type to ++// sign a message. ++func (pka PublicKeyAlgorithm) CanSign() bool { ++ switch pka { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: ++ return true ++ } ++ return false ++} ++ ++// CipherFunction represents the different block ciphers specified for OpenPGP. See ++// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 ++type CipherFunction uint8 ++ ++const ( ++ Cipher3DES CipherFunction = 2 ++ CipherCAST5 CipherFunction = 3 ++ CipherAES128 CipherFunction = 7 ++ CipherAES192 CipherFunction = 8 ++ CipherAES256 CipherFunction = 9 ++) ++ ++// KeySize returns the key size, in bytes, of cipher. ++func (cipher CipherFunction) KeySize() int { ++ switch cipher { ++ case Cipher3DES: ++ return 24 ++ case CipherCAST5: ++ return cast5.KeySize ++ case CipherAES128: ++ return 16 ++ case CipherAES192: ++ return 24 ++ case CipherAES256: ++ return 32 ++ } ++ return 0 ++} ++ ++// blockSize returns the block size, in bytes, of cipher. ++func (cipher CipherFunction) blockSize() int { ++ switch cipher { ++ case Cipher3DES: ++ return des.BlockSize ++ case CipherCAST5: ++ return 8 ++ case CipherAES128, CipherAES192, CipherAES256: ++ return 16 ++ } ++ return 0 ++} ++ ++// new returns a fresh instance of the given cipher. ++func (cipher CipherFunction) new(key []byte) (block cipher.Block) { ++ switch cipher { ++ case Cipher3DES: ++ block, _ = des.NewTripleDESCipher(key) ++ case CipherCAST5: ++ block, _ = cast5.NewCipher(key) ++ case CipherAES128, CipherAES192, CipherAES256: ++ block, _ = aes.NewCipher(key) ++ } ++ return ++} ++ ++// readMPI reads a big integer from r. The bit length returned is the bit ++// length that was specified in r. This is preserved so that the integer can be ++// reserialized exactly. ++func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { ++ var buf [2]byte ++ _, err = readFull(r, buf[0:]) ++ if err != nil { ++ return ++ } ++ bitLength = uint16(buf[0])<<8 | uint16(buf[1]) ++ numBytes := (int(bitLength) + 7) / 8 ++ mpi = make([]byte, numBytes) ++ _, err = readFull(r, mpi) ++ // According to RFC 4880 3.2. we should check that the MPI has no leading ++ // zeroes (at least when not an encrypted MPI?), but this implementation ++ // does generate leading zeroes, so we keep accepting them. ++ return ++} ++ ++// writeMPI serializes a big integer to w. ++func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { ++ // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. ++ // Implementations seem to be tolerant of them, and stripping them would ++ // make it complex to guarantee matching re-serialization. ++ _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) ++ if err == nil { ++ _, err = w.Write(mpiBytes) ++ } ++ return ++} ++ ++// writeBig serializes a *big.Int to w. ++func writeBig(w io.Writer, i *big.Int) error { ++ return writeMPI(w, uint16(i.BitLen()), i.Bytes()) ++} ++ ++// padToKeySize left-pads a MPI with zeroes to match the length of the ++// specified RSA public. ++func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { ++ k := (pub.N.BitLen() + 7) / 8 ++ if len(b) >= k { ++ return b ++ } ++ bb := make([]byte, k) ++ copy(bb[len(bb)-len(b):], b) ++ return bb ++} ++ ++// CompressionAlgo Represents the different compression algorithms ++// supported by OpenPGP (except for BZIP2, which is not currently ++// supported). See Section 9.3 of RFC 4880. ++type CompressionAlgo uint8 ++ ++const ( ++ CompressionNone CompressionAlgo = 0 ++ CompressionZIP CompressionAlgo = 1 ++ CompressionZLIB CompressionAlgo = 2 ++) +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go +new file mode 100644 +index 00000000000000..c8fc4e50c0b994 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go +@@ -0,0 +1,290 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "fmt" ++ "golang.org/x/crypto/openpgp/errors" ++ "io" ++ "testing" ++) ++ ++func TestReadFull(t *testing.T) { ++ var out [4]byte ++ ++ b := bytes.NewBufferString("foo") ++ n, err := readFull(b, out[:3]) ++ if n != 3 || err != nil { ++ t.Errorf("full read failed n:%d err:%s", n, err) ++ } ++ ++ b = bytes.NewBufferString("foo") ++ n, err = readFull(b, out[:4]) ++ if n != 3 || err != io.ErrUnexpectedEOF { ++ t.Errorf("partial read failed n:%d err:%s", n, err) ++ } ++ ++ b = bytes.NewBuffer(nil) ++ n, err = readFull(b, out[:3]) ++ if n != 0 || err != io.ErrUnexpectedEOF { ++ t.Errorf("empty read failed n:%d err:%s", n, err) ++ } ++} ++ ++func readerFromHex(s string) io.Reader { ++ data, err := hex.DecodeString(s) ++ if err != nil { ++ panic("readerFromHex: bad input") ++ } ++ return bytes.NewBuffer(data) ++} ++ ++var readLengthTests = []struct { ++ hexInput string ++ length int64 ++ isPartial bool ++ err error ++}{ ++ {"", 0, false, io.ErrUnexpectedEOF}, ++ {"1f", 31, false, nil}, ++ {"c0", 0, false, io.ErrUnexpectedEOF}, ++ {"c101", 256 + 1 + 192, false, nil}, ++ {"e0", 1, true, nil}, ++ {"e1", 2, true, nil}, ++ {"e2", 4, true, nil}, ++ {"ff", 0, false, io.ErrUnexpectedEOF}, ++ {"ff00", 0, false, io.ErrUnexpectedEOF}, ++ {"ff0000", 0, false, io.ErrUnexpectedEOF}, ++ {"ff000000", 0, false, io.ErrUnexpectedEOF}, ++ {"ff00000000", 0, false, nil}, ++ {"ff01020304", 16909060, false, nil}, ++} ++ ++func TestReadLength(t *testing.T) { ++ for i, test := range readLengthTests { ++ length, isPartial, err := readLength(readerFromHex(test.hexInput)) ++ if test.err != nil { ++ if err != test.err { ++ t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) ++ } ++ continue ++ } ++ if err != nil { ++ t.Errorf("%d: unexpected error: %s", i, err) ++ continue ++ } ++ if length != test.length || isPartial != test.isPartial { ++ t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial) ++ } ++ } ++} ++ ++var partialLengthReaderTests = []struct { ++ hexInput string ++ err error ++ hexOutput string ++}{ ++ {"e0", io.ErrUnexpectedEOF, ""}, ++ {"e001", io.ErrUnexpectedEOF, ""}, ++ {"e0010102", nil, "0102"}, ++ {"ff00000000", nil, ""}, ++ {"e10102e1030400", nil, "01020304"}, ++ {"e101", io.ErrUnexpectedEOF, ""}, ++} ++ ++func TestPartialLengthReader(t *testing.T) { ++ for i, test := range partialLengthReaderTests { ++ r := &partialLengthReader{readerFromHex(test.hexInput), 0, true} ++ out, err := io.ReadAll(r) ++ if test.err != nil { ++ if err != test.err { ++ t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) ++ } ++ continue ++ } ++ if err != nil { ++ t.Errorf("%d: unexpected error: %s", i, err) ++ continue ++ } ++ ++ got := fmt.Sprintf("%x", out) ++ if got != test.hexOutput { ++ t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got) ++ } ++ } ++} ++ ++var readHeaderTests = []struct { ++ hexInput string ++ structuralError bool ++ unexpectedEOF bool ++ tag int ++ length int64 ++ hexOutput string ++}{ ++ {"", false, false, 0, 0, ""}, ++ {"7f", true, false, 0, 0, ""}, ++ ++ // Old format headers ++ {"80", false, true, 0, 0, ""}, ++ {"8001", false, true, 0, 1, ""}, ++ {"800102", false, false, 0, 1, "02"}, ++ {"81000102", false, false, 0, 1, "02"}, ++ {"820000000102", false, false, 0, 1, "02"}, ++ {"860000000102", false, false, 1, 1, "02"}, ++ {"83010203", false, false, 0, -1, "010203"}, ++ ++ // New format headers ++ {"c0", false, true, 0, 0, ""}, ++ {"c000", false, false, 0, 0, ""}, ++ {"c00102", false, false, 0, 1, "02"}, ++ {"c0020203", false, false, 0, 2, "0203"}, ++ {"c00202", false, true, 0, 2, ""}, ++ {"c3020203", false, false, 3, 2, "0203"}, ++} ++ ++func TestReadHeader(t *testing.T) { ++ for i, test := range readHeaderTests { ++ tag, length, contents, err := readHeader(readerFromHex(test.hexInput)) ++ if test.structuralError { ++ if _, ok := err.(errors.StructuralError); ok { ++ continue ++ } ++ t.Errorf("%d: expected StructuralError, got:%s", i, err) ++ continue ++ } ++ if err != nil { ++ if len(test.hexInput) == 0 && err == io.EOF { ++ continue ++ } ++ if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { ++ t.Errorf("%d: unexpected error from readHeader: %s", i, err) ++ } ++ continue ++ } ++ if int(tag) != test.tag || length != test.length { ++ t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length) ++ continue ++ } ++ ++ body, err := io.ReadAll(contents) ++ if err != nil { ++ if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { ++ t.Errorf("%d: unexpected error from contents: %s", i, err) ++ } ++ continue ++ } ++ if test.unexpectedEOF { ++ t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i) ++ continue ++ } ++ got := fmt.Sprintf("%x", body) ++ if got != test.hexOutput { ++ t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput) ++ } ++ } ++} ++ ++func TestSerializeHeader(t *testing.T) { ++ tag := packetTypePublicKey ++ lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000} ++ ++ for _, length := range lengths { ++ buf := bytes.NewBuffer(nil) ++ serializeHeader(buf, tag, length) ++ tag2, length2, _, err := readHeader(buf) ++ if err != nil { ++ t.Errorf("length %d, err: %s", length, err) ++ } ++ if tag2 != tag { ++ t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag) ++ } ++ if int(length2) != length { ++ t.Errorf("length %d, length incorrect (got %d)", length, length2) ++ } ++ } ++} ++ ++func TestPartialLengths(t *testing.T) { ++ buf := bytes.NewBuffer(nil) ++ w := new(partialLengthWriter) ++ w.w = noOpCloser{buf} ++ ++ const maxChunkSize = 64 ++ ++ var b [maxChunkSize]byte ++ var n uint8 ++ for l := 1; l <= maxChunkSize; l++ { ++ for i := 0; i < l; i++ { ++ b[i] = n ++ n++ ++ } ++ m, err := w.Write(b[:l]) ++ if m != l { ++ t.Errorf("short write got: %d want: %d", m, l) ++ } ++ if err != nil { ++ t.Errorf("error from write: %s", err) ++ } ++ } ++ if err := w.Close(); err != nil { ++ t.Fatal(err) ++ } ++ ++ // The first packet should be at least 512 bytes. ++ first, err := buf.ReadByte() ++ if err != nil { ++ t.Fatal(err) ++ } ++ if plen := 1 << (first & 0x1f); plen < 512 { ++ t.Errorf("first packet too short: got %d want at least %d", plen, 512) ++ } ++ if err := buf.UnreadByte(); err != nil { ++ t.Fatal(err) ++ } ++ ++ want := (maxChunkSize * (maxChunkSize + 1)) / 2 ++ copyBuf := bytes.NewBuffer(nil) ++ r := &partialLengthReader{buf, 0, true} ++ m, err := io.Copy(copyBuf, r) ++ if m != int64(want) { ++ t.Errorf("short copy got: %d want: %d", m, want) ++ } ++ if err != nil { ++ t.Errorf("error from copy: %s", err) ++ } ++ ++ copyBytes := copyBuf.Bytes() ++ for i := 0; i < want; i++ { ++ if copyBytes[i] != uint8(i) { ++ t.Errorf("bad pattern in copy at %d", i) ++ break ++ } ++ } ++} ++ ++func TestPartialLengthsShortWrite(t *testing.T) { ++ buf := bytes.NewBuffer(nil) ++ w := &partialLengthWriter{ ++ w: noOpCloser{buf}, ++ } ++ data := bytes.Repeat([]byte("a"), 510) ++ if _, err := w.Write(data); err != nil { ++ t.Fatal(err) ++ } ++ if err := w.Close(); err != nil { ++ t.Fatal(err) ++ } ++ copyBuf := bytes.NewBuffer(nil) ++ r := &partialLengthReader{buf, 0, true} ++ if _, err := io.Copy(copyBuf, r); err != nil { ++ t.Fatal(err) ++ } ++ if !bytes.Equal(copyBuf.Bytes(), data) { ++ t.Errorf("got %q want %q", buf.Bytes(), data) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go +new file mode 100644 +index 00000000000000..192aac376d1af0 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go +@@ -0,0 +1,384 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/cipher" ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "crypto/rsa" ++ "crypto/sha1" ++ "io" ++ "math/big" ++ "strconv" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/elgamal" ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/s2k" ++) ++ ++// PrivateKey represents a possibly encrypted private key. See RFC 4880, ++// section 5.5.3. ++type PrivateKey struct { ++ PublicKey ++ Encrypted bool // if true then the private key is unavailable until Decrypt has been called. ++ encryptedData []byte ++ cipher CipherFunction ++ s2k func(out, in []byte) ++ PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). ++ sha1Checksum bool ++ iv []byte ++} ++ ++func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { ++ pk := new(PrivateKey) ++ pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) ++ pk.PrivateKey = priv ++ return pk ++} ++ ++func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { ++ pk := new(PrivateKey) ++ pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) ++ pk.PrivateKey = priv ++ return pk ++} ++ ++func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { ++ pk := new(PrivateKey) ++ pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) ++ pk.PrivateKey = priv ++ return pk ++} ++ ++func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { ++ pk := new(PrivateKey) ++ pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) ++ pk.PrivateKey = priv ++ return pk ++} ++ ++// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that ++// implements RSA or ECDSA. ++func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey { ++ pk := new(PrivateKey) ++ // In general, the public Keys should be used as pointers. We still ++ // type-switch on the values, for backwards-compatibility. ++ switch pubkey := signer.Public().(type) { ++ case *rsa.PublicKey: ++ pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey) ++ case rsa.PublicKey: ++ pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey) ++ case *ecdsa.PublicKey: ++ pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey) ++ case ecdsa.PublicKey: ++ pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey) ++ default: ++ panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") ++ } ++ pk.PrivateKey = signer ++ return pk ++} ++ ++func (pk *PrivateKey) parse(r io.Reader) (err error) { ++ err = (&pk.PublicKey).parse(r) ++ if err != nil { ++ return ++ } ++ var buf [1]byte ++ _, err = readFull(r, buf[:]) ++ if err != nil { ++ return ++ } ++ ++ s2kType := buf[0] ++ ++ switch s2kType { ++ case 0: ++ pk.s2k = nil ++ pk.Encrypted = false ++ case 254, 255: ++ _, err = readFull(r, buf[:]) ++ if err != nil { ++ return ++ } ++ pk.cipher = CipherFunction(buf[0]) ++ pk.Encrypted = true ++ pk.s2k, err = s2k.Parse(r) ++ if err != nil { ++ return ++ } ++ if s2kType == 254 { ++ pk.sha1Checksum = true ++ } ++ default: ++ return errors.UnsupportedError("deprecated s2k function in private key") ++ } ++ ++ if pk.Encrypted { ++ blockSize := pk.cipher.blockSize() ++ if blockSize == 0 { ++ return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) ++ } ++ pk.iv = make([]byte, blockSize) ++ _, err = readFull(r, pk.iv) ++ if err != nil { ++ return ++ } ++ } ++ ++ pk.encryptedData, err = io.ReadAll(r) ++ if err != nil { ++ return ++ } ++ ++ if !pk.Encrypted { ++ return pk.parsePrivateKey(pk.encryptedData) ++ } ++ ++ return ++} ++ ++func mod64kHash(d []byte) uint16 { ++ var h uint16 ++ for _, b := range d { ++ h += uint16(b) ++ } ++ return h ++} ++ ++func (pk *PrivateKey) Serialize(w io.Writer) (err error) { ++ // TODO(agl): support encrypted private keys ++ buf := bytes.NewBuffer(nil) ++ err = pk.PublicKey.serializeWithoutHeaders(buf) ++ if err != nil { ++ return ++ } ++ buf.WriteByte(0 /* no encryption */) ++ ++ privateKeyBuf := bytes.NewBuffer(nil) ++ ++ switch priv := pk.PrivateKey.(type) { ++ case *rsa.PrivateKey: ++ err = serializeRSAPrivateKey(privateKeyBuf, priv) ++ case *dsa.PrivateKey: ++ err = serializeDSAPrivateKey(privateKeyBuf, priv) ++ case *elgamal.PrivateKey: ++ err = serializeElGamalPrivateKey(privateKeyBuf, priv) ++ case *ecdsa.PrivateKey: ++ err = serializeECDSAPrivateKey(privateKeyBuf, priv) ++ default: ++ err = errors.InvalidArgumentError("unknown private key type") ++ } ++ if err != nil { ++ return ++ } ++ ++ ptype := packetTypePrivateKey ++ contents := buf.Bytes() ++ privateKeyBytes := privateKeyBuf.Bytes() ++ if pk.IsSubkey { ++ ptype = packetTypePrivateSubkey ++ } ++ err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) ++ if err != nil { ++ return ++ } ++ _, err = w.Write(contents) ++ if err != nil { ++ return ++ } ++ _, err = w.Write(privateKeyBytes) ++ if err != nil { ++ return ++ } ++ ++ checksum := mod64kHash(privateKeyBytes) ++ var checksumBytes [2]byte ++ checksumBytes[0] = byte(checksum >> 8) ++ checksumBytes[1] = byte(checksum) ++ _, err = w.Write(checksumBytes[:]) ++ ++ return ++} ++ ++func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { ++ err := writeBig(w, priv.D) ++ if err != nil { ++ return err ++ } ++ err = writeBig(w, priv.Primes[1]) ++ if err != nil { ++ return err ++ } ++ err = writeBig(w, priv.Primes[0]) ++ if err != nil { ++ return err ++ } ++ return writeBig(w, priv.Precomputed.Qinv) ++} ++ ++func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { ++ return writeBig(w, priv.X) ++} ++ ++func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { ++ return writeBig(w, priv.X) ++} ++ ++func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { ++ return writeBig(w, priv.D) ++} ++ ++// Decrypt decrypts an encrypted private key using a passphrase. ++func (pk *PrivateKey) Decrypt(passphrase []byte) error { ++ if !pk.Encrypted { ++ return nil ++ } ++ ++ key := make([]byte, pk.cipher.KeySize()) ++ pk.s2k(key, passphrase) ++ block := pk.cipher.new(key) ++ cfb := cipher.NewCFBDecrypter(block, pk.iv) ++ ++ data := make([]byte, len(pk.encryptedData)) ++ cfb.XORKeyStream(data, pk.encryptedData) ++ ++ if pk.sha1Checksum { ++ if len(data) < sha1.Size { ++ return errors.StructuralError("truncated private key data") ++ } ++ h := sha1.New() ++ h.Write(data[:len(data)-sha1.Size]) ++ sum := h.Sum(nil) ++ if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { ++ return errors.StructuralError("private key checksum failure") ++ } ++ data = data[:len(data)-sha1.Size] ++ } else { ++ if len(data) < 2 { ++ return errors.StructuralError("truncated private key data") ++ } ++ var sum uint16 ++ for i := 0; i < len(data)-2; i++ { ++ sum += uint16(data[i]) ++ } ++ if data[len(data)-2] != uint8(sum>>8) || ++ data[len(data)-1] != uint8(sum) { ++ return errors.StructuralError("private key checksum failure") ++ } ++ data = data[:len(data)-2] ++ } ++ ++ return pk.parsePrivateKey(data) ++} ++ ++func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { ++ switch pk.PublicKey.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: ++ return pk.parseRSAPrivateKey(data) ++ case PubKeyAlgoDSA: ++ return pk.parseDSAPrivateKey(data) ++ case PubKeyAlgoElGamal: ++ return pk.parseElGamalPrivateKey(data) ++ case PubKeyAlgoECDSA: ++ return pk.parseECDSAPrivateKey(data) ++ } ++ panic("impossible") ++} ++ ++func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { ++ rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) ++ rsaPriv := new(rsa.PrivateKey) ++ rsaPriv.PublicKey = *rsaPub ++ ++ buf := bytes.NewBuffer(data) ++ d, _, err := readMPI(buf) ++ if err != nil { ++ return ++ } ++ p, _, err := readMPI(buf) ++ if err != nil { ++ return ++ } ++ q, _, err := readMPI(buf) ++ if err != nil { ++ return ++ } ++ ++ rsaPriv.D = new(big.Int).SetBytes(d) ++ rsaPriv.Primes = make([]*big.Int, 2) ++ rsaPriv.Primes[0] = new(big.Int).SetBytes(p) ++ rsaPriv.Primes[1] = new(big.Int).SetBytes(q) ++ if err := rsaPriv.Validate(); err != nil { ++ return err ++ } ++ rsaPriv.Precompute() ++ pk.PrivateKey = rsaPriv ++ pk.Encrypted = false ++ pk.encryptedData = nil ++ ++ return nil ++} ++ ++func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { ++ dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) ++ dsaPriv := new(dsa.PrivateKey) ++ dsaPriv.PublicKey = *dsaPub ++ ++ buf := bytes.NewBuffer(data) ++ x, _, err := readMPI(buf) ++ if err != nil { ++ return ++ } ++ ++ dsaPriv.X = new(big.Int).SetBytes(x) ++ pk.PrivateKey = dsaPriv ++ pk.Encrypted = false ++ pk.encryptedData = nil ++ ++ return nil ++} ++ ++func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { ++ pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) ++ priv := new(elgamal.PrivateKey) ++ priv.PublicKey = *pub ++ ++ buf := bytes.NewBuffer(data) ++ x, _, err := readMPI(buf) ++ if err != nil { ++ return ++ } ++ ++ priv.X = new(big.Int).SetBytes(x) ++ pk.PrivateKey = priv ++ pk.Encrypted = false ++ pk.encryptedData = nil ++ ++ return nil ++} ++ ++func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { ++ ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) ++ ++ buf := bytes.NewBuffer(data) ++ d, _, err := readMPI(buf) ++ if err != nil { ++ return ++ } ++ ++ pk.PrivateKey = &ecdsa.PrivateKey{ ++ PublicKey: *ecdsaPub, ++ D: new(big.Int).SetBytes(d), ++ } ++ pk.Encrypted = false ++ pk.encryptedData = nil ++ ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go +new file mode 100644 +index 00000000000000..cc08b48371e40b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go +@@ -0,0 +1,249 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/x509" ++ "encoding/hex" ++ "hash" ++ "testing" ++ "time" ++) ++ ++var privateKeyTests = []struct { ++ privateKeyHex string ++ creationTime time.Time ++}{ ++ { ++ privKeyRSAHex, ++ time.Unix(0x4cc349a8, 0), ++ }, ++ { ++ privKeyElGamalHex, ++ time.Unix(0x4df9ee1a, 0), ++ }, ++} ++ ++func TestPrivateKeyRead(t *testing.T) { ++ for i, test := range privateKeyTests { ++ packet, err := Read(readerFromHex(test.privateKeyHex)) ++ if err != nil { ++ t.Errorf("#%d: failed to parse: %s", i, err) ++ continue ++ } ++ ++ privKey := packet.(*PrivateKey) ++ ++ if !privKey.Encrypted { ++ t.Errorf("#%d: private key isn't encrypted", i) ++ continue ++ } ++ ++ err = privKey.Decrypt([]byte("wrong password")) ++ if err == nil { ++ t.Errorf("#%d: decrypted with incorrect key", i) ++ continue ++ } ++ ++ err = privKey.Decrypt([]byte("testing")) ++ if err != nil { ++ t.Errorf("#%d: failed to decrypt: %s", i, err) ++ continue ++ } ++ ++ if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted { ++ t.Errorf("#%d: bad result, got: %#v", i, privKey) ++ } ++ } ++} ++ ++func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) { ++ h := hashFunc.New() ++ if _, err := h.Write(msg); err != nil { ++ return nil, err ++ } ++ return h, nil ++} ++ ++func TestRSAPrivateKey(t *testing.T) { ++ privKeyDER, _ := hex.DecodeString(pkcs1PrivKeyHex) ++ rsaPriv, err := x509.ParsePKCS1PrivateKey(privKeyDER) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ var buf bytes.Buffer ++ if err := NewRSAPrivateKey(time.Now(), rsaPriv).Serialize(&buf); err != nil { ++ t.Fatal(err) ++ } ++ ++ p, err := Read(&buf) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ priv, ok := p.(*PrivateKey) ++ if !ok { ++ t.Fatal("didn't parse private key") ++ } ++ ++ sig := &Signature{ ++ PubKeyAlgo: PubKeyAlgoRSA, ++ Hash: crypto.SHA256, ++ } ++ msg := []byte("Hello World!") ++ ++ h, err := populateHash(sig.Hash, msg) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if err := sig.Sign(h, priv, nil); err != nil { ++ t.Fatal(err) ++ } ++ ++ if h, err = populateHash(sig.Hash, msg); err != nil { ++ t.Fatal(err) ++ } ++ if err := priv.VerifySignature(h, sig); err != nil { ++ t.Fatal(err) ++ } ++} ++ ++func TestECDSAPrivateKey(t *testing.T) { ++ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ var buf bytes.Buffer ++ if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil { ++ t.Fatal(err) ++ } ++ ++ p, err := Read(&buf) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ priv, ok := p.(*PrivateKey) ++ if !ok { ++ t.Fatal("didn't parse private key") ++ } ++ ++ sig := &Signature{ ++ PubKeyAlgo: PubKeyAlgoECDSA, ++ Hash: crypto.SHA256, ++ } ++ msg := []byte("Hello World!") ++ ++ h, err := populateHash(sig.Hash, msg) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if err := sig.Sign(h, priv, nil); err != nil { ++ t.Fatal(err) ++ } ++ ++ if h, err = populateHash(sig.Hash, msg); err != nil { ++ t.Fatal(err) ++ } ++ if err := priv.VerifySignature(h, sig); err != nil { ++ t.Fatal(err) ++ } ++} ++ ++type rsaSigner struct { ++ *rsa.PrivateKey ++} ++ ++func TestRSASignerPrivateKey(t *testing.T) { ++ rsaPriv, err := rsa.GenerateKey(rand.Reader, 1024) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ priv := NewSignerPrivateKey(time.Now(), &rsaSigner{rsaPriv}) ++ ++ sig := &Signature{ ++ PubKeyAlgo: PubKeyAlgoRSA, ++ Hash: crypto.SHA256, ++ } ++ msg := []byte("Hello World!") ++ ++ h, err := populateHash(sig.Hash, msg) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if err := sig.Sign(h, priv, nil); err != nil { ++ t.Fatal(err) ++ } ++ ++ if h, err = populateHash(sig.Hash, msg); err != nil { ++ t.Fatal(err) ++ } ++ if err := priv.VerifySignature(h, sig); err != nil { ++ t.Fatal(err) ++ } ++} ++ ++type ecdsaSigner struct { ++ *ecdsa.PrivateKey ++} ++ ++func TestECDSASignerPrivateKey(t *testing.T) { ++ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ priv := NewSignerPrivateKey(time.Now(), &ecdsaSigner{ecdsaPriv}) ++ ++ if priv.PubKeyAlgo != PubKeyAlgoECDSA { ++ t.Fatal("NewSignerPrivateKey should have made an ECSDA private key") ++ } ++ ++ sig := &Signature{ ++ PubKeyAlgo: PubKeyAlgoECDSA, ++ Hash: crypto.SHA256, ++ } ++ msg := []byte("Hello World!") ++ ++ h, err := populateHash(sig.Hash, msg) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if err := sig.Sign(h, priv, nil); err != nil { ++ t.Fatal(err) ++ } ++ ++ if h, err = populateHash(sig.Hash, msg); err != nil { ++ t.Fatal(err) ++ } ++ if err := priv.VerifySignature(h, sig); err != nil { ++ t.Fatal(err) ++ } ++} ++ ++func TestIssue11505(t *testing.T) { ++ // parsing a rsa private key with p or q == 1 used to panic due to a divide by zero ++ _, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030")) ++} ++ ++// Generated with `gpg --export-secret-keys "Test Key 2"` ++const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" ++ ++// Generated by `gpg --export-secret-keys` followed by a manual extraction of ++// the ElGamal subkey from the packets. ++const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" ++ ++// pkcs1PrivKeyHex is a PKCS#1, RSA private key. ++// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p` ++const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7" +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go +new file mode 100644 +index 00000000000000..fcd5f5251963b3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go +@@ -0,0 +1,753 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rsa" ++ "crypto/sha1" ++ _ "crypto/sha256" ++ _ "crypto/sha512" ++ "encoding/binary" ++ "fmt" ++ "hash" ++ "io" ++ "math/big" ++ "strconv" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/elgamal" ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++var ( ++ // NIST curve P-256 ++ oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} ++ // NIST curve P-384 ++ oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} ++ // NIST curve P-521 ++ oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} ++) ++ ++const maxOIDLength = 8 ++ ++// ecdsaKey stores the algorithm-specific fields for ECDSA keys. ++// as defined in RFC 6637, Section 9. ++type ecdsaKey struct { ++ // oid contains the OID byte sequence identifying the elliptic curve used ++ oid []byte ++ // p contains the elliptic curve point that represents the public key ++ p parsedMPI ++} ++ ++// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. ++func parseOID(r io.Reader) (oid []byte, err error) { ++ buf := make([]byte, maxOIDLength) ++ if _, err = readFull(r, buf[:1]); err != nil { ++ return ++ } ++ oidLen := buf[0] ++ if int(oidLen) > len(buf) { ++ err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) ++ return ++ } ++ oid = buf[:oidLen] ++ _, err = readFull(r, oid) ++ return ++} ++ ++func (f *ecdsaKey) parse(r io.Reader) (err error) { ++ if f.oid, err = parseOID(r); err != nil { ++ return err ++ } ++ f.p.bytes, f.p.bitLength, err = readMPI(r) ++ return ++} ++ ++func (f *ecdsaKey) serialize(w io.Writer) (err error) { ++ buf := make([]byte, maxOIDLength+1) ++ buf[0] = byte(len(f.oid)) ++ copy(buf[1:], f.oid) ++ if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { ++ return ++ } ++ return writeMPIs(w, f.p) ++} ++ ++func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { ++ var c elliptic.Curve ++ if bytes.Equal(f.oid, oidCurveP256) { ++ c = elliptic.P256() ++ } else if bytes.Equal(f.oid, oidCurveP384) { ++ c = elliptic.P384() ++ } else if bytes.Equal(f.oid, oidCurveP521) { ++ c = elliptic.P521() ++ } else { ++ return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) ++ } ++ x, y := elliptic.Unmarshal(c, f.p.bytes) ++ if x == nil { ++ return nil, errors.UnsupportedError("failed to parse EC point") ++ } ++ return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil ++} ++ ++func (f *ecdsaKey) byteLen() int { ++ return 1 + len(f.oid) + 2 + len(f.p.bytes) ++} ++ ++type kdfHashFunction byte ++type kdfAlgorithm byte ++ ++// ecdhKdf stores key derivation function parameters ++// used for ECDH encryption. See RFC 6637, Section 9. ++type ecdhKdf struct { ++ KdfHash kdfHashFunction ++ KdfAlgo kdfAlgorithm ++} ++ ++func (f *ecdhKdf) parse(r io.Reader) (err error) { ++ buf := make([]byte, 1) ++ if _, err = readFull(r, buf); err != nil { ++ return ++ } ++ kdfLen := int(buf[0]) ++ if kdfLen < 3 { ++ return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) ++ } ++ buf = make([]byte, kdfLen) ++ if _, err = readFull(r, buf); err != nil { ++ return ++ } ++ reserved := int(buf[0]) ++ f.KdfHash = kdfHashFunction(buf[1]) ++ f.KdfAlgo = kdfAlgorithm(buf[2]) ++ if reserved != 0x01 { ++ return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) ++ } ++ return ++} ++ ++func (f *ecdhKdf) serialize(w io.Writer) (err error) { ++ buf := make([]byte, 4) ++ // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. ++ buf[0] = byte(0x03) // Length of the following fields ++ buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now ++ buf[2] = byte(f.KdfHash) ++ buf[3] = byte(f.KdfAlgo) ++ _, err = w.Write(buf[:]) ++ return ++} ++ ++func (f *ecdhKdf) byteLen() int { ++ return 4 ++} ++ ++// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. ++type PublicKey struct { ++ CreationTime time.Time ++ PubKeyAlgo PublicKeyAlgorithm ++ PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey ++ Fingerprint [20]byte ++ KeyId uint64 ++ IsSubkey bool ++ ++ n, e, p, q, g, y parsedMPI ++ ++ // RFC 6637 fields ++ ec *ecdsaKey ++ ecdh *ecdhKdf ++} ++ ++// signingKey provides a convenient abstraction over signature verification ++// for v3 and v4 public keys. ++type signingKey interface { ++ SerializeSignaturePrefix(io.Writer) ++ serializeWithoutHeaders(io.Writer) error ++} ++ ++func fromBig(n *big.Int) parsedMPI { ++ return parsedMPI{ ++ bytes: n.Bytes(), ++ bitLength: uint16(n.BitLen()), ++ } ++} ++ ++// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. ++func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { ++ pk := &PublicKey{ ++ CreationTime: creationTime, ++ PubKeyAlgo: PubKeyAlgoRSA, ++ PublicKey: pub, ++ n: fromBig(pub.N), ++ e: fromBig(big.NewInt(int64(pub.E))), ++ } ++ ++ pk.setFingerPrintAndKeyId() ++ return pk ++} ++ ++// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. ++func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { ++ pk := &PublicKey{ ++ CreationTime: creationTime, ++ PubKeyAlgo: PubKeyAlgoDSA, ++ PublicKey: pub, ++ p: fromBig(pub.P), ++ q: fromBig(pub.Q), ++ g: fromBig(pub.G), ++ y: fromBig(pub.Y), ++ } ++ ++ pk.setFingerPrintAndKeyId() ++ return pk ++} ++ ++// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. ++func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { ++ pk := &PublicKey{ ++ CreationTime: creationTime, ++ PubKeyAlgo: PubKeyAlgoElGamal, ++ PublicKey: pub, ++ p: fromBig(pub.P), ++ g: fromBig(pub.G), ++ y: fromBig(pub.Y), ++ } ++ ++ pk.setFingerPrintAndKeyId() ++ return pk ++} ++ ++func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { ++ pk := &PublicKey{ ++ CreationTime: creationTime, ++ PubKeyAlgo: PubKeyAlgoECDSA, ++ PublicKey: pub, ++ ec: new(ecdsaKey), ++ } ++ ++ switch pub.Curve { ++ case elliptic.P256(): ++ pk.ec.oid = oidCurveP256 ++ case elliptic.P384(): ++ pk.ec.oid = oidCurveP384 ++ case elliptic.P521(): ++ pk.ec.oid = oidCurveP521 ++ default: ++ panic("unknown elliptic curve") ++ } ++ ++ pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) ++ ++ // The bit length is 3 (for the 0x04 specifying an uncompressed key) ++ // plus two field elements (for x and y), which are rounded up to the ++ // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 ++ fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 ++ pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) ++ ++ pk.setFingerPrintAndKeyId() ++ return pk ++} ++ ++func (pk *PublicKey) parse(r io.Reader) (err error) { ++ // RFC 4880, section 5.5.2 ++ var buf [6]byte ++ _, err = readFull(r, buf[:]) ++ if err != nil { ++ return ++ } ++ if buf[0] != 4 { ++ return errors.UnsupportedError("public key version") ++ } ++ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) ++ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ err = pk.parseRSA(r) ++ case PubKeyAlgoDSA: ++ err = pk.parseDSA(r) ++ case PubKeyAlgoElGamal: ++ err = pk.parseElGamal(r) ++ case PubKeyAlgoECDSA: ++ pk.ec = new(ecdsaKey) ++ if err = pk.ec.parse(r); err != nil { ++ return err ++ } ++ pk.PublicKey, err = pk.ec.newECDSA() ++ case PubKeyAlgoECDH: ++ pk.ec = new(ecdsaKey) ++ if err = pk.ec.parse(r); err != nil { ++ return ++ } ++ pk.ecdh = new(ecdhKdf) ++ if err = pk.ecdh.parse(r); err != nil { ++ return ++ } ++ // The ECDH key is stored in an ecdsa.PublicKey for convenience. ++ pk.PublicKey, err = pk.ec.newECDSA() ++ default: ++ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) ++ } ++ if err != nil { ++ return ++ } ++ ++ pk.setFingerPrintAndKeyId() ++ return ++} ++ ++func (pk *PublicKey) setFingerPrintAndKeyId() { ++ // RFC 4880, section 12.2 ++ fingerPrint := sha1.New() ++ pk.SerializeSignaturePrefix(fingerPrint) ++ pk.serializeWithoutHeaders(fingerPrint) ++ copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) ++ pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) ++} ++ ++// parseRSA parses RSA public key material from the given Reader. See RFC 4880, ++// section 5.5.2. ++func (pk *PublicKey) parseRSA(r io.Reader) (err error) { ++ pk.n.bytes, pk.n.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ pk.e.bytes, pk.e.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ ++ if len(pk.e.bytes) > 3 { ++ err = errors.UnsupportedError("large public exponent") ++ return ++ } ++ rsa := &rsa.PublicKey{ ++ N: new(big.Int).SetBytes(pk.n.bytes), ++ E: 0, ++ } ++ for i := 0; i < len(pk.e.bytes); i++ { ++ rsa.E <<= 8 ++ rsa.E |= int(pk.e.bytes[i]) ++ } ++ pk.PublicKey = rsa ++ return ++} ++ ++// parseDSA parses DSA public key material from the given Reader. See RFC 4880, ++// section 5.5.2. ++func (pk *PublicKey) parseDSA(r io.Reader) (err error) { ++ pk.p.bytes, pk.p.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ pk.q.bytes, pk.q.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ pk.g.bytes, pk.g.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ pk.y.bytes, pk.y.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ ++ dsa := new(dsa.PublicKey) ++ dsa.P = new(big.Int).SetBytes(pk.p.bytes) ++ dsa.Q = new(big.Int).SetBytes(pk.q.bytes) ++ dsa.G = new(big.Int).SetBytes(pk.g.bytes) ++ dsa.Y = new(big.Int).SetBytes(pk.y.bytes) ++ pk.PublicKey = dsa ++ return ++} ++ ++// parseElGamal parses ElGamal public key material from the given Reader. See ++// RFC 4880, section 5.5.2. ++func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { ++ pk.p.bytes, pk.p.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ pk.g.bytes, pk.g.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ pk.y.bytes, pk.y.bitLength, err = readMPI(r) ++ if err != nil { ++ return ++ } ++ ++ elgamal := new(elgamal.PublicKey) ++ elgamal.P = new(big.Int).SetBytes(pk.p.bytes) ++ elgamal.G = new(big.Int).SetBytes(pk.g.bytes) ++ elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) ++ pk.PublicKey = elgamal ++ return ++} ++ ++// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. ++// The prefix is used when calculating a signature over this public key. See ++// RFC 4880, section 5.2.4. ++func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { ++ var pLength uint16 ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ pLength += 2 + uint16(len(pk.n.bytes)) ++ pLength += 2 + uint16(len(pk.e.bytes)) ++ case PubKeyAlgoDSA: ++ pLength += 2 + uint16(len(pk.p.bytes)) ++ pLength += 2 + uint16(len(pk.q.bytes)) ++ pLength += 2 + uint16(len(pk.g.bytes)) ++ pLength += 2 + uint16(len(pk.y.bytes)) ++ case PubKeyAlgoElGamal: ++ pLength += 2 + uint16(len(pk.p.bytes)) ++ pLength += 2 + uint16(len(pk.g.bytes)) ++ pLength += 2 + uint16(len(pk.y.bytes)) ++ case PubKeyAlgoECDSA: ++ pLength += uint16(pk.ec.byteLen()) ++ case PubKeyAlgoECDH: ++ pLength += uint16(pk.ec.byteLen()) ++ pLength += uint16(pk.ecdh.byteLen()) ++ default: ++ panic("unknown public key algorithm") ++ } ++ pLength += 6 ++ h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) ++ return ++} ++ ++func (pk *PublicKey) Serialize(w io.Writer) (err error) { ++ length := 6 // 6 byte header ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ length += 2 + len(pk.n.bytes) ++ length += 2 + len(pk.e.bytes) ++ case PubKeyAlgoDSA: ++ length += 2 + len(pk.p.bytes) ++ length += 2 + len(pk.q.bytes) ++ length += 2 + len(pk.g.bytes) ++ length += 2 + len(pk.y.bytes) ++ case PubKeyAlgoElGamal: ++ length += 2 + len(pk.p.bytes) ++ length += 2 + len(pk.g.bytes) ++ length += 2 + len(pk.y.bytes) ++ case PubKeyAlgoECDSA: ++ length += pk.ec.byteLen() ++ case PubKeyAlgoECDH: ++ length += pk.ec.byteLen() ++ length += pk.ecdh.byteLen() ++ default: ++ panic("unknown public key algorithm") ++ } ++ ++ packetType := packetTypePublicKey ++ if pk.IsSubkey { ++ packetType = packetTypePublicSubkey ++ } ++ err = serializeHeader(w, packetType, length) ++ if err != nil { ++ return ++ } ++ return pk.serializeWithoutHeaders(w) ++} ++ ++// serializeWithoutHeaders marshals the PublicKey to w in the form of an ++// OpenPGP public key packet, not including the packet header. ++func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { ++ var buf [6]byte ++ buf[0] = 4 ++ t := uint32(pk.CreationTime.Unix()) ++ buf[1] = byte(t >> 24) ++ buf[2] = byte(t >> 16) ++ buf[3] = byte(t >> 8) ++ buf[4] = byte(t) ++ buf[5] = byte(pk.PubKeyAlgo) ++ ++ _, err = w.Write(buf[:]) ++ if err != nil { ++ return ++ } ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ return writeMPIs(w, pk.n, pk.e) ++ case PubKeyAlgoDSA: ++ return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) ++ case PubKeyAlgoElGamal: ++ return writeMPIs(w, pk.p, pk.g, pk.y) ++ case PubKeyAlgoECDSA: ++ return pk.ec.serialize(w) ++ case PubKeyAlgoECDH: ++ if err = pk.ec.serialize(w); err != nil { ++ return ++ } ++ return pk.ecdh.serialize(w) ++ } ++ return errors.InvalidArgumentError("bad public-key algorithm") ++} ++ ++// CanSign returns true iff this public key can generate signatures ++func (pk *PublicKey) CanSign() bool { ++ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal ++} ++ ++// VerifySignature returns nil iff sig is a valid signature, made by this ++// public key, of the data hashed into signed. signed is mutated by this call. ++func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { ++ if !pk.CanSign() { ++ return errors.InvalidArgumentError("public key cannot generate signatures") ++ } ++ ++ signed.Write(sig.HashSuffix) ++ hashBytes := signed.Sum(nil) ++ ++ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { ++ return errors.SignatureError("hash tag doesn't match") ++ } ++ ++ if pk.PubKeyAlgo != sig.PubKeyAlgo { ++ return errors.InvalidArgumentError("public key and signature use different algorithms") ++ } ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) ++ err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) ++ if err != nil { ++ return errors.SignatureError("RSA verification failure") ++ } ++ return nil ++ case PubKeyAlgoDSA: ++ dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) ++ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. ++ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 ++ if len(hashBytes) > subgroupSize { ++ hashBytes = hashBytes[:subgroupSize] ++ } ++ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { ++ return errors.SignatureError("DSA verification failure") ++ } ++ return nil ++ case PubKeyAlgoECDSA: ++ ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) ++ if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { ++ return errors.SignatureError("ECDSA verification failure") ++ } ++ return nil ++ default: ++ return errors.SignatureError("Unsupported public key algorithm used in signature") ++ } ++} ++ ++// VerifySignatureV3 returns nil iff sig is a valid signature, made by this ++// public key, of the data hashed into signed. signed is mutated by this call. ++func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { ++ if !pk.CanSign() { ++ return errors.InvalidArgumentError("public key cannot generate signatures") ++ } ++ ++ suffix := make([]byte, 5) ++ suffix[0] = byte(sig.SigType) ++ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) ++ signed.Write(suffix) ++ hashBytes := signed.Sum(nil) ++ ++ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { ++ return errors.SignatureError("hash tag doesn't match") ++ } ++ ++ if pk.PubKeyAlgo != sig.PubKeyAlgo { ++ return errors.InvalidArgumentError("public key and signature use different algorithms") ++ } ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) ++ if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { ++ return errors.SignatureError("RSA verification failure") ++ } ++ return ++ case PubKeyAlgoDSA: ++ dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) ++ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. ++ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 ++ if len(hashBytes) > subgroupSize { ++ hashBytes = hashBytes[:subgroupSize] ++ } ++ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { ++ return errors.SignatureError("DSA verification failure") ++ } ++ return nil ++ default: ++ panic("shouldn't happen") ++ } ++} ++ ++// keySignatureHash returns a Hash of the message that needs to be signed for ++// pk to assert a subkey relationship to signed. ++func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { ++ if !hashFunc.Available() { ++ return nil, errors.UnsupportedError("hash function") ++ } ++ h = hashFunc.New() ++ ++ // RFC 4880, section 5.2.4 ++ pk.SerializeSignaturePrefix(h) ++ pk.serializeWithoutHeaders(h) ++ signed.SerializeSignaturePrefix(h) ++ signed.serializeWithoutHeaders(h) ++ return ++} ++ ++// VerifyKeySignature returns nil iff sig is a valid signature, made by this ++// public key, of signed. ++func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { ++ h, err := keySignatureHash(pk, signed, sig.Hash) ++ if err != nil { ++ return err ++ } ++ if err = pk.VerifySignature(h, sig); err != nil { ++ return err ++ } ++ ++ if sig.FlagSign { ++ // Signing subkeys must be cross-signed. See ++ // https://www.gnupg.org/faq/subkey-cross-certify.html. ++ if sig.EmbeddedSignature == nil { ++ return errors.StructuralError("signing subkey is missing cross-signature") ++ } ++ // Verify the cross-signature. This is calculated over the same ++ // data as the main signature, so we cannot just recursively ++ // call signed.VerifyKeySignature(...) ++ if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { ++ return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) ++ } ++ if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { ++ return errors.StructuralError("error while verifying cross-signature: " + err.Error()) ++ } ++ } ++ ++ return nil ++} ++ ++func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { ++ if !hashFunc.Available() { ++ return nil, errors.UnsupportedError("hash function") ++ } ++ h = hashFunc.New() ++ ++ // RFC 4880, section 5.2.4 ++ pk.SerializeSignaturePrefix(h) ++ pk.serializeWithoutHeaders(h) ++ ++ return ++} ++ ++// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this ++// public key. ++func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { ++ h, err := keyRevocationHash(pk, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return pk.VerifySignature(h, sig) ++} ++ ++// userIdSignatureHash returns a Hash of the message that needs to be signed ++// to assert that pk is a valid key for id. ++func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { ++ if !hashFunc.Available() { ++ return nil, errors.UnsupportedError("hash function") ++ } ++ h = hashFunc.New() ++ ++ // RFC 4880, section 5.2.4 ++ pk.SerializeSignaturePrefix(h) ++ pk.serializeWithoutHeaders(h) ++ ++ var buf [5]byte ++ buf[0] = 0xb4 ++ buf[1] = byte(len(id) >> 24) ++ buf[2] = byte(len(id) >> 16) ++ buf[3] = byte(len(id) >> 8) ++ buf[4] = byte(len(id)) ++ h.Write(buf[:]) ++ h.Write([]byte(id)) ++ ++ return ++} ++ ++// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this ++// public key, that id is the identity of pub. ++func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { ++ h, err := userIdSignatureHash(id, pub, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return pk.VerifySignature(h, sig) ++} ++ ++// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this ++// public key, that id is the identity of pub. ++func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { ++ h, err := userIdSignatureV3Hash(id, pub, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return pk.VerifySignatureV3(h, sig) ++} ++ ++// KeyIdString returns the public key's fingerprint in capital hex ++// (e.g. "6C7EE1B8621CC013"). ++func (pk *PublicKey) KeyIdString() string { ++ return fmt.Sprintf("%X", pk.Fingerprint[12:20]) ++} ++ ++// KeyIdShortString returns the short form of public key's fingerprint ++// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). ++func (pk *PublicKey) KeyIdShortString() string { ++ return fmt.Sprintf("%X", pk.Fingerprint[16:20]) ++} ++ ++// A parsedMPI is used to store the contents of a big integer, along with the ++// bit length that was specified in the original input. This allows the MPI to ++// be reserialized exactly. ++type parsedMPI struct { ++ bytes []byte ++ bitLength uint16 ++} ++ ++// writeMPIs is a utility function for serializing several big integers to the ++// given Writer. ++func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { ++ for _, mpi := range mpis { ++ err = writeMPI(w, mpi.bitLength, mpi.bytes) ++ if err != nil { ++ return ++ } ++ } ++ return ++} ++ ++// BitLength returns the bit length for the given public key. ++func (pk *PublicKey) BitLength() (bitLength uint16, err error) { ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ bitLength = pk.n.bitLength ++ case PubKeyAlgoDSA: ++ bitLength = pk.p.bitLength ++ case PubKeyAlgoElGamal: ++ bitLength = pk.p.bitLength ++ default: ++ err = errors.InvalidArgumentError("bad public-key algorithm") ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go +new file mode 100644 +index 00000000000000..103696ee7ce1cf +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go +@@ -0,0 +1,228 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "encoding/hex" ++ "math/big" ++ "testing" ++ "time" ++) ++ ++var pubKeyTests = []struct { ++ hexData string ++ hexFingerprint string ++ creationTime time.Time ++ pubKeyAlgo PublicKeyAlgorithm ++ keyId uint64 ++ keyIdString string ++ keyIdShort string ++}{ ++ {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"}, ++ {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"}, ++ {ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"}, ++} ++ ++func TestPublicKeyRead(t *testing.T) { ++ for i, test := range pubKeyTests { ++ packet, err := Read(readerFromHex(test.hexData)) ++ if err != nil { ++ t.Errorf("#%d: Read error: %s", i, err) ++ continue ++ } ++ pk, ok := packet.(*PublicKey) ++ if !ok { ++ t.Errorf("#%d: failed to parse, got: %#v", i, packet) ++ continue ++ } ++ if pk.PubKeyAlgo != test.pubKeyAlgo { ++ t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) ++ } ++ if !pk.CreationTime.Equal(test.creationTime) { ++ t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) ++ } ++ expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) ++ if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { ++ t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) ++ } ++ if pk.KeyId != test.keyId { ++ t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) ++ } ++ if g, e := pk.KeyIdString(), test.keyIdString; g != e { ++ t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) ++ } ++ if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { ++ t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) ++ } ++ } ++} ++ ++func TestPublicKeySerialize(t *testing.T) { ++ for i, test := range pubKeyTests { ++ packet, err := Read(readerFromHex(test.hexData)) ++ if err != nil { ++ t.Errorf("#%d: Read error: %s", i, err) ++ continue ++ } ++ pk, ok := packet.(*PublicKey) ++ if !ok { ++ t.Errorf("#%d: failed to parse, got: %#v", i, packet) ++ continue ++ } ++ serializeBuf := bytes.NewBuffer(nil) ++ err = pk.Serialize(serializeBuf) ++ if err != nil { ++ t.Errorf("#%d: failed to serialize: %s", i, err) ++ continue ++ } ++ ++ packet, err = Read(serializeBuf) ++ if err != nil { ++ t.Errorf("#%d: Read error (from serialized data): %s", i, err) ++ continue ++ } ++ pk, ok = packet.(*PublicKey) ++ if !ok { ++ t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet) ++ continue ++ } ++ } ++} ++ ++func TestEcc384Serialize(t *testing.T) { ++ r := readerFromHex(ecc384PubHex) ++ var w bytes.Buffer ++ for i := 0; i < 2; i++ { ++ // Public key ++ p, err := Read(r) ++ if err != nil { ++ t.Error(err) ++ } ++ pubkey := p.(*PublicKey) ++ if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { ++ t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid) ++ } ++ if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) { ++ t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes) ++ } ++ if pubkey.KeyId != 0x098033880F54719F { ++ t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId) ++ } ++ err = pubkey.Serialize(&w) ++ if err != nil { ++ t.Error(err) ++ } ++ // User ID ++ p, err = Read(r) ++ if err != nil { ++ t.Error(err) ++ } ++ uid := p.(*UserId) ++ if uid.Id != "ec_dsa_dh_384 " { ++ t.Error("Unexpected UID:", uid.Id) ++ } ++ err = uid.Serialize(&w) ++ if err != nil { ++ t.Error(err) ++ } ++ // User ID Sig ++ p, err = Read(r) ++ if err != nil { ++ t.Error(err) ++ } ++ uidSig := p.(*Signature) ++ err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig) ++ if err != nil { ++ t.Error(err, ": UID") ++ } ++ err = uidSig.Serialize(&w) ++ if err != nil { ++ t.Error(err) ++ } ++ // Subkey ++ p, err = Read(r) ++ if err != nil { ++ t.Error(err) ++ } ++ subkey := p.(*PublicKey) ++ if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { ++ t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid) ++ } ++ if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) { ++ t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes) ++ } ++ if subkey.ecdh.KdfHash != 0x09 { ++ t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash) ++ } ++ if subkey.ecdh.KdfAlgo != 0x09 { ++ t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo) ++ } ++ if subkey.KeyId != 0xAA8B938F9A201946 { ++ t.Errorf("Unexpected subkey ID: %x", subkey.KeyId) ++ } ++ err = subkey.Serialize(&w) ++ if err != nil { ++ t.Error(err) ++ } ++ // Subkey Sig ++ p, err = Read(r) ++ if err != nil { ++ t.Error(err) ++ } ++ subkeySig := p.(*Signature) ++ err = pubkey.VerifyKeySignature(subkey, subkeySig) ++ if err != nil { ++ t.Error(err) ++ } ++ err = subkeySig.Serialize(&w) ++ if err != nil { ++ t.Error(err) ++ } ++ // Now read back what we've written again ++ r = bytes.NewBuffer(w.Bytes()) ++ w.Reset() ++ } ++} ++ ++func TestP256KeyID(t *testing.T) { ++ // Confirm that key IDs are correctly calculated for ECC keys. ++ ecdsaPub := &ecdsa.PublicKey{ ++ Curve: elliptic.P256(), ++ X: fromHex("81fbbc20eea9e8d1c3ceabb0a8185925b113d1ac42cd5c78403bd83da19235c6"), ++ Y: fromHex("5ed6db13d91db34507d0129bf88981878d29adbf8fcd1720afdb767bb3fcaaff"), ++ } ++ pub := NewECDSAPublicKey(time.Unix(1297309478, 0), ecdsaPub) ++ ++ const want = uint64(0xd01055fbcadd268e) ++ if pub.KeyId != want { ++ t.Errorf("want key ID: %x, got %x", want, pub.KeyId) ++ } ++} ++ ++func fromHex(hex string) *big.Int { ++ n, ok := new(big.Int).SetString(hex, 16) ++ if !ok { ++ panic("bad hex number: " + hex) ++ } ++ return n ++} ++ ++const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" ++ ++const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" ++ ++const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" ++ ++const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" ++ ++const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" ++ ++const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" ++ ++// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key ++const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go +new file mode 100644 +index 00000000000000..5daf7b6cfd4a06 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go +@@ -0,0 +1,279 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "crypto" ++ "crypto/md5" ++ "crypto/rsa" ++ "encoding/binary" ++ "fmt" ++ "hash" ++ "io" ++ "math/big" ++ "strconv" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and ++// should not be used for signing or encrypting. They are supported here only for ++// parsing version 3 key material and validating signatures. ++// See RFC 4880, section 5.5.2. ++type PublicKeyV3 struct { ++ CreationTime time.Time ++ DaysToExpire uint16 ++ PubKeyAlgo PublicKeyAlgorithm ++ PublicKey *rsa.PublicKey ++ Fingerprint [16]byte ++ KeyId uint64 ++ IsSubkey bool ++ ++ n, e parsedMPI ++} ++ ++// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. ++// Included here for testing purposes only. RFC 4880, section 5.5.2: ++// "an implementation MUST NOT generate a V3 key, but MAY accept it." ++func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { ++ pk := &PublicKeyV3{ ++ CreationTime: creationTime, ++ PublicKey: pub, ++ n: fromBig(pub.N), ++ e: fromBig(big.NewInt(int64(pub.E))), ++ } ++ ++ pk.setFingerPrintAndKeyId() ++ return pk ++} ++ ++func (pk *PublicKeyV3) parse(r io.Reader) (err error) { ++ // RFC 4880, section 5.5.2 ++ var buf [8]byte ++ if _, err = readFull(r, buf[:]); err != nil { ++ return ++ } ++ if buf[0] < 2 || buf[0] > 3 { ++ return errors.UnsupportedError("public key version") ++ } ++ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) ++ pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) ++ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ err = pk.parseRSA(r) ++ default: ++ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) ++ } ++ if err != nil { ++ return ++ } ++ ++ pk.setFingerPrintAndKeyId() ++ return ++} ++ ++func (pk *PublicKeyV3) setFingerPrintAndKeyId() { ++ // RFC 4880, section 12.2 ++ fingerPrint := md5.New() ++ fingerPrint.Write(pk.n.bytes) ++ fingerPrint.Write(pk.e.bytes) ++ fingerPrint.Sum(pk.Fingerprint[:0]) ++ pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) ++} ++ ++// parseRSA parses RSA public key material from the given Reader. See RFC 4880, ++// section 5.5.2. ++func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { ++ if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { ++ return ++ } ++ if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { ++ return ++ } ++ ++ // RFC 4880 Section 12.2 requires the low 8 bytes of the ++ // modulus to form the key id. ++ if len(pk.n.bytes) < 8 { ++ return errors.StructuralError("v3 public key modulus is too short") ++ } ++ if len(pk.e.bytes) > 3 { ++ err = errors.UnsupportedError("large public exponent") ++ return ++ } ++ rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} ++ for i := 0; i < len(pk.e.bytes); i++ { ++ rsa.E <<= 8 ++ rsa.E |= int(pk.e.bytes[i]) ++ } ++ pk.PublicKey = rsa ++ return ++} ++ ++// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. ++// The prefix is used when calculating a signature over this public key. See ++// RFC 4880, section 5.2.4. ++func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { ++ var pLength uint16 ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ pLength += 2 + uint16(len(pk.n.bytes)) ++ pLength += 2 + uint16(len(pk.e.bytes)) ++ default: ++ panic("unknown public key algorithm") ++ } ++ pLength += 6 ++ w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) ++ return ++} ++ ++func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { ++ length := 8 // 8 byte header ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ length += 2 + len(pk.n.bytes) ++ length += 2 + len(pk.e.bytes) ++ default: ++ panic("unknown public key algorithm") ++ } ++ ++ packetType := packetTypePublicKey ++ if pk.IsSubkey { ++ packetType = packetTypePublicSubkey ++ } ++ if err = serializeHeader(w, packetType, length); err != nil { ++ return ++ } ++ return pk.serializeWithoutHeaders(w) ++} ++ ++// serializeWithoutHeaders marshals the PublicKey to w in the form of an ++// OpenPGP public key packet, not including the packet header. ++func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { ++ var buf [8]byte ++ // Version 3 ++ buf[0] = 3 ++ // Creation time ++ t := uint32(pk.CreationTime.Unix()) ++ buf[1] = byte(t >> 24) ++ buf[2] = byte(t >> 16) ++ buf[3] = byte(t >> 8) ++ buf[4] = byte(t) ++ // Days to expire ++ buf[5] = byte(pk.DaysToExpire >> 8) ++ buf[6] = byte(pk.DaysToExpire) ++ // Public key algorithm ++ buf[7] = byte(pk.PubKeyAlgo) ++ ++ if _, err = w.Write(buf[:]); err != nil { ++ return ++ } ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ return writeMPIs(w, pk.n, pk.e) ++ } ++ return errors.InvalidArgumentError("bad public-key algorithm") ++} ++ ++// CanSign returns true iff this public key can generate signatures ++func (pk *PublicKeyV3) CanSign() bool { ++ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly ++} ++ ++// VerifySignatureV3 returns nil iff sig is a valid signature, made by this ++// public key, of the data hashed into signed. signed is mutated by this call. ++func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { ++ if !pk.CanSign() { ++ return errors.InvalidArgumentError("public key cannot generate signatures") ++ } ++ ++ suffix := make([]byte, 5) ++ suffix[0] = byte(sig.SigType) ++ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) ++ signed.Write(suffix) ++ hashBytes := signed.Sum(nil) ++ ++ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { ++ return errors.SignatureError("hash tag doesn't match") ++ } ++ ++ if pk.PubKeyAlgo != sig.PubKeyAlgo { ++ return errors.InvalidArgumentError("public key and signature use different algorithms") ++ } ++ ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { ++ return errors.SignatureError("RSA verification failure") ++ } ++ return ++ default: ++ // V3 public keys only support RSA. ++ panic("shouldn't happen") ++ } ++} ++ ++// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this ++// public key, that id is the identity of pub. ++func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { ++ h, err := userIdSignatureV3Hash(id, pk, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return pk.VerifySignatureV3(h, sig) ++} ++ ++// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this ++// public key, of signed. ++func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { ++ h, err := keySignatureHash(pk, signed, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return pk.VerifySignatureV3(h, sig) ++} ++ ++// userIdSignatureV3Hash returns a Hash of the message that needs to be signed ++// to assert that pk is a valid key for id. ++func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { ++ if !hfn.Available() { ++ return nil, errors.UnsupportedError("hash function") ++ } ++ h = hfn.New() ++ ++ // RFC 4880, section 5.2.4 ++ pk.SerializeSignaturePrefix(h) ++ pk.serializeWithoutHeaders(h) ++ ++ h.Write([]byte(id)) ++ ++ return ++} ++ ++// KeyIdString returns the public key's fingerprint in capital hex ++// (e.g. "6C7EE1B8621CC013"). ++func (pk *PublicKeyV3) KeyIdString() string { ++ return fmt.Sprintf("%X", pk.KeyId) ++} ++ ++// KeyIdShortString returns the short form of public key's fingerprint ++// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). ++func (pk *PublicKeyV3) KeyIdShortString() string { ++ return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) ++} ++ ++// BitLength returns the bit length for the given public key. ++func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { ++ switch pk.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: ++ bitLength = pk.n.bitLength ++ default: ++ err = errors.InvalidArgumentError("bad public-key algorithm") ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go +new file mode 100644 +index 00000000000000..e06405904b3e3b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go +@@ -0,0 +1,82 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++ "time" ++) ++ ++var pubKeyV3Test = struct { ++ hexFingerprint string ++ creationTime time.Time ++ pubKeyAlgo PublicKeyAlgorithm ++ keyId uint64 ++ keyIdString string ++ keyIdShort string ++}{ ++ "103BECF5BD1E837C89D19E98487767F7", ++ time.Unix(779753634, 0), ++ PubKeyAlgoRSA, ++ 0xDE0F188A5DA5E3C9, ++ "DE0F188A5DA5E3C9", ++ "5DA5E3C9"} ++ ++func TestPublicKeyV3Read(t *testing.T) { ++ i, test := 0, pubKeyV3Test ++ packet, err := Read(v3KeyReader(t)) ++ if err != nil { ++ t.Fatalf("#%d: Read error: %s", i, err) ++ } ++ pk, ok := packet.(*PublicKeyV3) ++ if !ok { ++ t.Fatalf("#%d: failed to parse, got: %#v", i, packet) ++ } ++ if pk.PubKeyAlgo != test.pubKeyAlgo { ++ t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) ++ } ++ if !pk.CreationTime.Equal(test.creationTime) { ++ t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) ++ } ++ expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) ++ if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { ++ t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) ++ } ++ if pk.KeyId != test.keyId { ++ t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) ++ } ++ if g, e := pk.KeyIdString(), test.keyIdString; g != e { ++ t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) ++ } ++ if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { ++ t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) ++ } ++} ++ ++func TestPublicKeyV3Serialize(t *testing.T) { ++ //for i, test := range pubKeyV3Tests { ++ i := 0 ++ packet, err := Read(v3KeyReader(t)) ++ if err != nil { ++ t.Fatalf("#%d: Read error: %s", i, err) ++ } ++ pk, ok := packet.(*PublicKeyV3) ++ if !ok { ++ t.Fatalf("#%d: failed to parse, got: %#v", i, packet) ++ } ++ var serializeBuf bytes.Buffer ++ if err = pk.Serialize(&serializeBuf); err != nil { ++ t.Fatalf("#%d: failed to serialize: %s", i, err) ++ } ++ ++ if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil { ++ t.Fatalf("#%d: Read error (from serialized data): %s", i, err) ++ } ++ if pk, ok = packet.(*PublicKeyV3); !ok { ++ t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/reader.go b/ms_mod/golang.org/x/crypto/openpgp/packet/reader.go +new file mode 100644 +index 00000000000000..34bc7c613e6e23 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/reader.go +@@ -0,0 +1,76 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "golang.org/x/crypto/openpgp/errors" ++ "io" ++) ++ ++// Reader reads packets from an io.Reader and allows packets to be 'unread' so ++// that they result from the next call to Next. ++type Reader struct { ++ q []Packet ++ readers []io.Reader ++} ++ ++// New io.Readers are pushed when a compressed or encrypted packet is processed ++// and recursively treated as a new source of packets. However, a carefully ++// crafted packet can trigger an infinite recursive sequence of packets. See ++// http://mumble.net/~campbell/misc/pgp-quine ++// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 ++// This constant limits the number of recursive packets that may be pushed. ++const maxReaders = 32 ++ ++// Next returns the most recently unread Packet, or reads another packet from ++// the top-most io.Reader. Unknown packet types are skipped. ++func (r *Reader) Next() (p Packet, err error) { ++ if len(r.q) > 0 { ++ p = r.q[len(r.q)-1] ++ r.q = r.q[:len(r.q)-1] ++ return ++ } ++ ++ for len(r.readers) > 0 { ++ p, err = Read(r.readers[len(r.readers)-1]) ++ if err == nil { ++ return ++ } ++ if err == io.EOF { ++ r.readers = r.readers[:len(r.readers)-1] ++ continue ++ } ++ if _, ok := err.(errors.UnknownPacketTypeError); !ok { ++ return nil, err ++ } ++ } ++ ++ return nil, io.EOF ++} ++ ++// Push causes the Reader to start reading from a new io.Reader. When an EOF ++// error is seen from the new io.Reader, it is popped and the Reader continues ++// to read from the next most recent io.Reader. Push returns a StructuralError ++// if pushing the reader would exceed the maximum recursion level, otherwise it ++// returns nil. ++func (r *Reader) Push(reader io.Reader) (err error) { ++ if len(r.readers) >= maxReaders { ++ return errors.StructuralError("too many layers of packets") ++ } ++ r.readers = append(r.readers, reader) ++ return nil ++} ++ ++// Unread causes the given Packet to be returned from the next call to Next. ++func (r *Reader) Unread(p Packet) { ++ r.q = append(r.q, p) ++} ++ ++func NewReader(r io.Reader) *Reader { ++ return &Reader{ ++ q: nil, ++ readers: []io.Reader{r}, ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature.go +new file mode 100644 +index 00000000000000..b2a24a532327b5 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature.go +@@ -0,0 +1,731 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "encoding/asn1" ++ "encoding/binary" ++ "hash" ++ "io" ++ "math/big" ++ "strconv" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/s2k" ++) ++ ++const ( ++ // See RFC 4880, section 5.2.3.21 for details. ++ KeyFlagCertify = 1 << iota ++ KeyFlagSign ++ KeyFlagEncryptCommunications ++ KeyFlagEncryptStorage ++) ++ ++// Signature represents a signature. See RFC 4880, section 5.2. ++type Signature struct { ++ SigType SignatureType ++ PubKeyAlgo PublicKeyAlgorithm ++ Hash crypto.Hash ++ ++ // HashSuffix is extra data that is hashed in after the signed data. ++ HashSuffix []byte ++ // HashTag contains the first two bytes of the hash for fast rejection ++ // of bad signed data. ++ HashTag [2]byte ++ CreationTime time.Time ++ ++ RSASignature parsedMPI ++ DSASigR, DSASigS parsedMPI ++ ECDSASigR, ECDSASigS parsedMPI ++ ++ // rawSubpackets contains the unparsed subpackets, in order. ++ rawSubpackets []outputSubpacket ++ ++ // The following are optional so are nil when not included in the ++ // signature. ++ ++ SigLifetimeSecs, KeyLifetimeSecs *uint32 ++ PreferredSymmetric, PreferredHash, PreferredCompression []uint8 ++ IssuerKeyId *uint64 ++ IsPrimaryId *bool ++ ++ // FlagsValid is set if any flags were given. See RFC 4880, section ++ // 5.2.3.21 for details. ++ FlagsValid bool ++ FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool ++ ++ // RevocationReason is set if this signature has been revoked. ++ // See RFC 4880, section 5.2.3.23 for details. ++ RevocationReason *uint8 ++ RevocationReasonText string ++ ++ // MDC is set if this signature has a feature packet that indicates ++ // support for MDC subpackets. ++ MDC bool ++ ++ // EmbeddedSignature, if non-nil, is a signature of the parent key, by ++ // this key. This prevents an attacker from claiming another's signing ++ // subkey as their own. ++ EmbeddedSignature *Signature ++ ++ outSubpackets []outputSubpacket ++} ++ ++func (sig *Signature) parse(r io.Reader) (err error) { ++ // RFC 4880, section 5.2.3 ++ var buf [5]byte ++ _, err = readFull(r, buf[:1]) ++ if err != nil { ++ return ++ } ++ if buf[0] != 4 { ++ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) ++ return ++ } ++ ++ _, err = readFull(r, buf[:5]) ++ if err != nil { ++ return ++ } ++ sig.SigType = SignatureType(buf[0]) ++ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: ++ default: ++ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) ++ return ++ } ++ ++ var ok bool ++ sig.Hash, ok = s2k.HashIdToHash(buf[2]) ++ if !ok { ++ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) ++ } ++ ++ hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) ++ l := 6 + hashedSubpacketsLength ++ sig.HashSuffix = make([]byte, l+6) ++ sig.HashSuffix[0] = 4 ++ copy(sig.HashSuffix[1:], buf[:5]) ++ hashedSubpackets := sig.HashSuffix[6:l] ++ _, err = readFull(r, hashedSubpackets) ++ if err != nil { ++ return ++ } ++ // See RFC 4880, section 5.2.4 ++ trailer := sig.HashSuffix[l:] ++ trailer[0] = 4 ++ trailer[1] = 0xff ++ trailer[2] = uint8(l >> 24) ++ trailer[3] = uint8(l >> 16) ++ trailer[4] = uint8(l >> 8) ++ trailer[5] = uint8(l) ++ ++ err = parseSignatureSubpackets(sig, hashedSubpackets, true) ++ if err != nil { ++ return ++ } ++ ++ _, err = readFull(r, buf[:2]) ++ if err != nil { ++ return ++ } ++ unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) ++ unhashedSubpackets := make([]byte, unhashedSubpacketsLength) ++ _, err = readFull(r, unhashedSubpackets) ++ if err != nil { ++ return ++ } ++ err = parseSignatureSubpackets(sig, unhashedSubpackets, false) ++ if err != nil { ++ return ++ } ++ ++ _, err = readFull(r, sig.HashTag[:2]) ++ if err != nil { ++ return ++ } ++ ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) ++ case PubKeyAlgoDSA: ++ sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) ++ if err == nil { ++ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) ++ } ++ case PubKeyAlgoECDSA: ++ sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) ++ if err == nil { ++ sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) ++ } ++ default: ++ panic("unreachable") ++ } ++ return ++} ++ ++// parseSignatureSubpackets parses subpackets of the main signature packet. See ++// RFC 4880, section 5.2.3.1. ++func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { ++ for len(subpackets) > 0 { ++ subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) ++ if err != nil { ++ return ++ } ++ } ++ ++ if sig.CreationTime.IsZero() { ++ err = errors.StructuralError("no creation time in signature") ++ } ++ ++ return ++} ++ ++type signatureSubpacketType uint8 ++ ++const ( ++ creationTimeSubpacket signatureSubpacketType = 2 ++ signatureExpirationSubpacket signatureSubpacketType = 3 ++ keyExpirationSubpacket signatureSubpacketType = 9 ++ prefSymmetricAlgosSubpacket signatureSubpacketType = 11 ++ issuerSubpacket signatureSubpacketType = 16 ++ prefHashAlgosSubpacket signatureSubpacketType = 21 ++ prefCompressionSubpacket signatureSubpacketType = 22 ++ primaryUserIdSubpacket signatureSubpacketType = 25 ++ keyFlagsSubpacket signatureSubpacketType = 27 ++ reasonForRevocationSubpacket signatureSubpacketType = 29 ++ featuresSubpacket signatureSubpacketType = 30 ++ embeddedSignatureSubpacket signatureSubpacketType = 32 ++) ++ ++// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. ++func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { ++ // RFC 4880, section 5.2.3.1 ++ var ( ++ length uint32 ++ packetType signatureSubpacketType ++ isCritical bool ++ ) ++ switch { ++ case subpacket[0] < 192: ++ length = uint32(subpacket[0]) ++ subpacket = subpacket[1:] ++ case subpacket[0] < 255: ++ if len(subpacket) < 2 { ++ goto Truncated ++ } ++ length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 ++ subpacket = subpacket[2:] ++ default: ++ if len(subpacket) < 5 { ++ goto Truncated ++ } ++ length = uint32(subpacket[1])<<24 | ++ uint32(subpacket[2])<<16 | ++ uint32(subpacket[3])<<8 | ++ uint32(subpacket[4]) ++ subpacket = subpacket[5:] ++ } ++ if length > uint32(len(subpacket)) { ++ goto Truncated ++ } ++ rest = subpacket[length:] ++ subpacket = subpacket[:length] ++ if len(subpacket) == 0 { ++ err = errors.StructuralError("zero length signature subpacket") ++ return ++ } ++ packetType = signatureSubpacketType(subpacket[0] & 0x7f) ++ isCritical = subpacket[0]&0x80 == 0x80 ++ subpacket = subpacket[1:] ++ sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) ++ switch packetType { ++ case creationTimeSubpacket: ++ if !isHashed { ++ err = errors.StructuralError("signature creation time in non-hashed area") ++ return ++ } ++ if len(subpacket) != 4 { ++ err = errors.StructuralError("signature creation time not four bytes") ++ return ++ } ++ t := binary.BigEndian.Uint32(subpacket) ++ sig.CreationTime = time.Unix(int64(t), 0) ++ case signatureExpirationSubpacket: ++ // Signature expiration time, section 5.2.3.10 ++ if !isHashed { ++ return ++ } ++ if len(subpacket) != 4 { ++ err = errors.StructuralError("expiration subpacket with bad length") ++ return ++ } ++ sig.SigLifetimeSecs = new(uint32) ++ *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) ++ case keyExpirationSubpacket: ++ // Key expiration time, section 5.2.3.6 ++ if !isHashed { ++ return ++ } ++ if len(subpacket) != 4 { ++ err = errors.StructuralError("key expiration subpacket with bad length") ++ return ++ } ++ sig.KeyLifetimeSecs = new(uint32) ++ *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) ++ case prefSymmetricAlgosSubpacket: ++ // Preferred symmetric algorithms, section 5.2.3.7 ++ if !isHashed { ++ return ++ } ++ sig.PreferredSymmetric = make([]byte, len(subpacket)) ++ copy(sig.PreferredSymmetric, subpacket) ++ case issuerSubpacket: ++ // Issuer, section 5.2.3.5 ++ if len(subpacket) != 8 { ++ err = errors.StructuralError("issuer subpacket with bad length") ++ return ++ } ++ sig.IssuerKeyId = new(uint64) ++ *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) ++ case prefHashAlgosSubpacket: ++ // Preferred hash algorithms, section 5.2.3.8 ++ if !isHashed { ++ return ++ } ++ sig.PreferredHash = make([]byte, len(subpacket)) ++ copy(sig.PreferredHash, subpacket) ++ case prefCompressionSubpacket: ++ // Preferred compression algorithms, section 5.2.3.9 ++ if !isHashed { ++ return ++ } ++ sig.PreferredCompression = make([]byte, len(subpacket)) ++ copy(sig.PreferredCompression, subpacket) ++ case primaryUserIdSubpacket: ++ // Primary User ID, section 5.2.3.19 ++ if !isHashed { ++ return ++ } ++ if len(subpacket) != 1 { ++ err = errors.StructuralError("primary user id subpacket with bad length") ++ return ++ } ++ sig.IsPrimaryId = new(bool) ++ if subpacket[0] > 0 { ++ *sig.IsPrimaryId = true ++ } ++ case keyFlagsSubpacket: ++ // Key flags, section 5.2.3.21 ++ if !isHashed { ++ return ++ } ++ if len(subpacket) == 0 { ++ err = errors.StructuralError("empty key flags subpacket") ++ return ++ } ++ sig.FlagsValid = true ++ if subpacket[0]&KeyFlagCertify != 0 { ++ sig.FlagCertify = true ++ } ++ if subpacket[0]&KeyFlagSign != 0 { ++ sig.FlagSign = true ++ } ++ if subpacket[0]&KeyFlagEncryptCommunications != 0 { ++ sig.FlagEncryptCommunications = true ++ } ++ if subpacket[0]&KeyFlagEncryptStorage != 0 { ++ sig.FlagEncryptStorage = true ++ } ++ case reasonForRevocationSubpacket: ++ // Reason For Revocation, section 5.2.3.23 ++ if !isHashed { ++ return ++ } ++ if len(subpacket) == 0 { ++ err = errors.StructuralError("empty revocation reason subpacket") ++ return ++ } ++ sig.RevocationReason = new(uint8) ++ *sig.RevocationReason = subpacket[0] ++ sig.RevocationReasonText = string(subpacket[1:]) ++ case featuresSubpacket: ++ // Features subpacket, section 5.2.3.24 specifies a very general ++ // mechanism for OpenPGP implementations to signal support for new ++ // features. In practice, the subpacket is used exclusively to ++ // indicate support for MDC-protected encryption. ++ sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 ++ case embeddedSignatureSubpacket: ++ // Only usage is in signatures that cross-certify ++ // signing subkeys. section 5.2.3.26 describes the ++ // format, with its usage described in section 11.1 ++ if sig.EmbeddedSignature != nil { ++ err = errors.StructuralError("Cannot have multiple embedded signatures") ++ return ++ } ++ sig.EmbeddedSignature = new(Signature) ++ // Embedded signatures are required to be v4 signatures see ++ // section 12.1. However, we only parse v4 signatures in this ++ // file anyway. ++ if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { ++ return nil, err ++ } ++ if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { ++ return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) ++ } ++ default: ++ if isCritical { ++ err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) ++ return ++ } ++ } ++ return ++ ++Truncated: ++ err = errors.StructuralError("signature subpacket truncated") ++ return ++} ++ ++// subpacketLengthLength returns the length, in bytes, of an encoded length value. ++func subpacketLengthLength(length int) int { ++ if length < 192 { ++ return 1 ++ } ++ if length < 16320 { ++ return 2 ++ } ++ return 5 ++} ++ ++// serializeSubpacketLength marshals the given length into to. ++func serializeSubpacketLength(to []byte, length int) int { ++ // RFC 4880, Section 4.2.2. ++ if length < 192 { ++ to[0] = byte(length) ++ return 1 ++ } ++ if length < 16320 { ++ length -= 192 ++ to[0] = byte((length >> 8) + 192) ++ to[1] = byte(length) ++ return 2 ++ } ++ to[0] = 255 ++ to[1] = byte(length >> 24) ++ to[2] = byte(length >> 16) ++ to[3] = byte(length >> 8) ++ to[4] = byte(length) ++ return 5 ++} ++ ++// subpacketsLength returns the serialized length, in bytes, of the given ++// subpackets. ++func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { ++ for _, subpacket := range subpackets { ++ if subpacket.hashed == hashed { ++ length += subpacketLengthLength(len(subpacket.contents) + 1) ++ length += 1 // type byte ++ length += len(subpacket.contents) ++ } ++ } ++ return ++} ++ ++// serializeSubpackets marshals the given subpackets into to. ++func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { ++ for _, subpacket := range subpackets { ++ if subpacket.hashed == hashed { ++ n := serializeSubpacketLength(to, len(subpacket.contents)+1) ++ to[n] = byte(subpacket.subpacketType) ++ to = to[1+n:] ++ n = copy(to, subpacket.contents) ++ to = to[n:] ++ } ++ } ++ return ++} ++ ++// KeyExpired returns whether sig is a self-signature of a key that has ++// expired. ++func (sig *Signature) KeyExpired(currentTime time.Time) bool { ++ if sig.KeyLifetimeSecs == nil { ++ return false ++ } ++ expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) ++ return currentTime.After(expiry) ++} ++ ++// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. ++func (sig *Signature) buildHashSuffix() (err error) { ++ hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) ++ ++ var ok bool ++ l := 6 + hashedSubpacketsLen ++ sig.HashSuffix = make([]byte, l+6) ++ sig.HashSuffix[0] = 4 ++ sig.HashSuffix[1] = uint8(sig.SigType) ++ sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) ++ sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) ++ if !ok { ++ sig.HashSuffix = nil ++ return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) ++ } ++ sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) ++ sig.HashSuffix[5] = byte(hashedSubpacketsLen) ++ serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) ++ trailer := sig.HashSuffix[l:] ++ trailer[0] = 4 ++ trailer[1] = 0xff ++ trailer[2] = byte(l >> 24) ++ trailer[3] = byte(l >> 16) ++ trailer[4] = byte(l >> 8) ++ trailer[5] = byte(l) ++ return ++} ++ ++func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { ++ err = sig.buildHashSuffix() ++ if err != nil { ++ return ++ } ++ ++ h.Write(sig.HashSuffix) ++ digest = h.Sum(nil) ++ copy(sig.HashTag[:], digest) ++ return ++} ++ ++// Sign signs a message with a private key. The hash, h, must contain ++// the hash of the message to be signed and will be mutated by this function. ++// On success, the signature is stored in sig. Call Serialize to write it out. ++// If config is nil, sensible defaults will be used. ++func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { ++ sig.outSubpackets = sig.buildSubpackets() ++ digest, err := sig.signPrepareHash(h) ++ if err != nil { ++ return ++ } ++ ++ switch priv.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ // supports both *rsa.PrivateKey and crypto.Signer ++ sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) ++ sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) ++ case PubKeyAlgoDSA: ++ dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) ++ ++ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. ++ subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 ++ if len(digest) > subgroupSize { ++ digest = digest[:subgroupSize] ++ } ++ r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) ++ if err == nil { ++ sig.DSASigR.bytes = r.Bytes() ++ sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) ++ sig.DSASigS.bytes = s.Bytes() ++ sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) ++ } ++ case PubKeyAlgoECDSA: ++ var r, s *big.Int ++ if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { ++ // direct support, avoid asn1 wrapping/unwrapping ++ r, s, err = ecdsa.Sign(config.Random(), pk, digest) ++ } else { ++ var b []byte ++ b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) ++ if err == nil { ++ r, s, err = unwrapECDSASig(b) ++ } ++ } ++ if err == nil { ++ sig.ECDSASigR = fromBig(r) ++ sig.ECDSASigS = fromBig(s) ++ } ++ default: ++ err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) ++ } ++ ++ return ++} ++ ++// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA ++// signature. ++func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { ++ var ecsdaSig struct { ++ R, S *big.Int ++ } ++ _, err = asn1.Unmarshal(b, &ecsdaSig) ++ if err != nil { ++ return ++ } ++ return ecsdaSig.R, ecsdaSig.S, nil ++} ++ ++// SignUserId computes a signature from priv, asserting that pub is a valid ++// key for the identity id. On success, the signature is stored in sig. Call ++// Serialize to write it out. ++// If config is nil, sensible defaults will be used. ++func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { ++ h, err := userIdSignatureHash(id, pub, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return sig.Sign(h, priv, config) ++} ++ ++// SignKey computes a signature from priv, asserting that pub is a subkey. On ++// success, the signature is stored in sig. Call Serialize to write it out. ++// If config is nil, sensible defaults will be used. ++func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { ++ h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) ++ if err != nil { ++ return err ++ } ++ return sig.Sign(h, priv, config) ++} ++ ++// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been ++// called first. ++func (sig *Signature) Serialize(w io.Writer) (err error) { ++ if len(sig.outSubpackets) == 0 { ++ sig.outSubpackets = sig.rawSubpackets ++ } ++ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { ++ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") ++ } ++ ++ sigLength := 0 ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ sigLength = 2 + len(sig.RSASignature.bytes) ++ case PubKeyAlgoDSA: ++ sigLength = 2 + len(sig.DSASigR.bytes) ++ sigLength += 2 + len(sig.DSASigS.bytes) ++ case PubKeyAlgoECDSA: ++ sigLength = 2 + len(sig.ECDSASigR.bytes) ++ sigLength += 2 + len(sig.ECDSASigS.bytes) ++ default: ++ panic("impossible") ++ } ++ ++ unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) ++ length := len(sig.HashSuffix) - 6 /* trailer not included */ + ++ 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + ++ 2 /* hash tag */ + sigLength ++ err = serializeHeader(w, packetTypeSignature, length) ++ if err != nil { ++ return ++ } ++ ++ _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) ++ if err != nil { ++ return ++ } ++ ++ unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) ++ unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) ++ unhashedSubpackets[1] = byte(unhashedSubpacketsLen) ++ serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) ++ ++ _, err = w.Write(unhashedSubpackets) ++ if err != nil { ++ return ++ } ++ _, err = w.Write(sig.HashTag[:]) ++ if err != nil { ++ return ++ } ++ ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ err = writeMPIs(w, sig.RSASignature) ++ case PubKeyAlgoDSA: ++ err = writeMPIs(w, sig.DSASigR, sig.DSASigS) ++ case PubKeyAlgoECDSA: ++ err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) ++ default: ++ panic("impossible") ++ } ++ return ++} ++ ++// outputSubpacket represents a subpacket to be marshaled. ++type outputSubpacket struct { ++ hashed bool // true if this subpacket is in the hashed area. ++ subpacketType signatureSubpacketType ++ isCritical bool ++ contents []byte ++} ++ ++func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { ++ creationTime := make([]byte, 4) ++ binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) ++ subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) ++ ++ if sig.IssuerKeyId != nil { ++ keyId := make([]byte, 8) ++ binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) ++ subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) ++ } ++ ++ if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { ++ sigLifetime := make([]byte, 4) ++ binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) ++ subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) ++ } ++ ++ // Key flags may only appear in self-signatures or certification signatures. ++ ++ if sig.FlagsValid { ++ var flags byte ++ if sig.FlagCertify { ++ flags |= KeyFlagCertify ++ } ++ if sig.FlagSign { ++ flags |= KeyFlagSign ++ } ++ if sig.FlagEncryptCommunications { ++ flags |= KeyFlagEncryptCommunications ++ } ++ if sig.FlagEncryptStorage { ++ flags |= KeyFlagEncryptStorage ++ } ++ subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) ++ } ++ ++ // The following subpackets may only appear in self-signatures ++ ++ if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { ++ keyLifetime := make([]byte, 4) ++ binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) ++ subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) ++ } ++ ++ if sig.IsPrimaryId != nil && *sig.IsPrimaryId { ++ subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) ++ } ++ ++ if len(sig.PreferredSymmetric) > 0 { ++ subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) ++ } ++ ++ if len(sig.PreferredHash) > 0 { ++ subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) ++ } ++ ++ if len(sig.PreferredCompression) > 0 { ++ subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) ++ } ++ ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go +new file mode 100644 +index 00000000000000..56e761179d0cf8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go +@@ -0,0 +1,78 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "encoding/hex" ++ "testing" ++) ++ ++func TestSignatureRead(t *testing.T) { ++ packet, err := Read(readerFromHex(signatureDataHex)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ sig, ok := packet.(*Signature) ++ if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 { ++ t.Errorf("failed to parse, got: %#v", packet) ++ } ++} ++ ++func TestSignatureReserialize(t *testing.T) { ++ packet, _ := Read(readerFromHex(signatureDataHex)) ++ sig := packet.(*Signature) ++ out := new(bytes.Buffer) ++ err := sig.Serialize(out) ++ if err != nil { ++ t.Errorf("error reserializing: %s", err) ++ return ++ } ++ ++ expected, _ := hex.DecodeString(signatureDataHex) ++ if !bytes.Equal(expected, out.Bytes()) { ++ t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) ++ } ++} ++ ++func TestSignUserId(t *testing.T) { ++ sig := &Signature{ ++ SigType: SigTypeGenericCert, ++ PubKeyAlgo: PubKeyAlgoRSA, ++ Hash: 0, // invalid hash function ++ } ++ ++ packet, err := Read(readerFromHex(rsaPkDataHex)) ++ if err != nil { ++ t.Fatalf("failed to deserialize public key: %v", err) ++ } ++ pubKey := packet.(*PublicKey) ++ ++ packet, err = Read(readerFromHex(privKeyRSAHex)) ++ if err != nil { ++ t.Fatalf("failed to deserialize private key: %v", err) ++ } ++ privKey := packet.(*PrivateKey) ++ ++ err = sig.SignUserId("", pubKey, privKey, nil) ++ if err == nil { ++ t.Errorf("did not receive an error when expected") ++ } ++ ++ sig.Hash = crypto.SHA256 ++ err = privKey.Decrypt([]byte("testing")) ++ if err != nil { ++ t.Fatalf("failed to decrypt private key: %v", err) ++ } ++ ++ err = sig.SignUserId("", pubKey, privKey, nil) ++ if err != nil { ++ t.Errorf("failed to sign user id: %v", err) ++ } ++} ++ ++const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e" +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go +new file mode 100644 +index 00000000000000..6edff889349b3f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go +@@ -0,0 +1,146 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "crypto" ++ "encoding/binary" ++ "fmt" ++ "io" ++ "strconv" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/s2k" ++) ++ ++// SignatureV3 represents older version 3 signatures. These signatures are less secure ++// than version 4 and should not be used to create new signatures. They are included ++// here for backwards compatibility to read and validate with older key material. ++// See RFC 4880, section 5.2.2. ++type SignatureV3 struct { ++ SigType SignatureType ++ CreationTime time.Time ++ IssuerKeyId uint64 ++ PubKeyAlgo PublicKeyAlgorithm ++ Hash crypto.Hash ++ HashTag [2]byte ++ ++ RSASignature parsedMPI ++ DSASigR, DSASigS parsedMPI ++} ++ ++func (sig *SignatureV3) parse(r io.Reader) (err error) { ++ // RFC 4880, section 5.2.2 ++ var buf [8]byte ++ if _, err = readFull(r, buf[:1]); err != nil { ++ return ++ } ++ if buf[0] < 2 || buf[0] > 3 { ++ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) ++ return ++ } ++ if _, err = readFull(r, buf[:1]); err != nil { ++ return ++ } ++ if buf[0] != 5 { ++ err = errors.UnsupportedError( ++ "invalid hashed material length " + strconv.Itoa(int(buf[0]))) ++ return ++ } ++ ++ // Read hashed material: signature type + creation time ++ if _, err = readFull(r, buf[:5]); err != nil { ++ return ++ } ++ sig.SigType = SignatureType(buf[0]) ++ t := binary.BigEndian.Uint32(buf[1:5]) ++ sig.CreationTime = time.Unix(int64(t), 0) ++ ++ // Eight-octet Key ID of signer. ++ if _, err = readFull(r, buf[:8]); err != nil { ++ return ++ } ++ sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) ++ ++ // Public-key and hash algorithm ++ if _, err = readFull(r, buf[:2]); err != nil { ++ return ++ } ++ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: ++ default: ++ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) ++ return ++ } ++ var ok bool ++ if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { ++ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) ++ } ++ ++ // Two-octet field holding left 16 bits of signed hash value. ++ if _, err = readFull(r, sig.HashTag[:2]); err != nil { ++ return ++ } ++ ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) ++ case PubKeyAlgoDSA: ++ if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { ++ return ++ } ++ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) ++ default: ++ panic("unreachable") ++ } ++ return ++} ++ ++// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been ++// called first. ++func (sig *SignatureV3) Serialize(w io.Writer) (err error) { ++ buf := make([]byte, 8) ++ ++ // Write the sig type and creation time ++ buf[0] = byte(sig.SigType) ++ binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) ++ if _, err = w.Write(buf[:5]); err != nil { ++ return ++ } ++ ++ // Write the issuer long key ID ++ binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) ++ if _, err = w.Write(buf[:8]); err != nil { ++ return ++ } ++ ++ // Write public key algorithm, hash ID, and hash value ++ buf[0] = byte(sig.PubKeyAlgo) ++ hashId, ok := s2k.HashToHashId(sig.Hash) ++ if !ok { ++ return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) ++ } ++ buf[1] = hashId ++ copy(buf[2:4], sig.HashTag[:]) ++ if _, err = w.Write(buf[:4]); err != nil { ++ return ++ } ++ ++ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { ++ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") ++ } ++ ++ switch sig.PubKeyAlgo { ++ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: ++ err = writeMPIs(w, sig.RSASignature) ++ case PubKeyAlgoDSA: ++ err = writeMPIs(w, sig.DSASigR, sig.DSASigS) ++ default: ++ panic("impossible") ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go +new file mode 100644 +index 00000000000000..abb2d8c14496f8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go +@@ -0,0 +1,96 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto" ++ "encoding/hex" ++ "io" ++ "testing" ++ ++ "golang.org/x/crypto/openpgp/armor" ++) ++ ++func TestSignatureV3Read(t *testing.T) { ++ r := v3KeyReader(t) ++ Read(r) // Skip public key ++ Read(r) // Skip uid ++ packet, err := Read(r) // Signature ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ sig, ok := packet.(*SignatureV3) ++ if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 { ++ t.Errorf("failed to parse, got: %#v", packet) ++ } ++} ++ ++func TestSignatureV3Reserialize(t *testing.T) { ++ r := v3KeyReader(t) ++ Read(r) // Skip public key ++ Read(r) // Skip uid ++ packet, err := Read(r) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ sig := packet.(*SignatureV3) ++ out := new(bytes.Buffer) ++ if err = sig.Serialize(out); err != nil { ++ t.Errorf("error reserializing: %s", err) ++ return ++ } ++ expected, err := io.ReadAll(v3KeyReader(t)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts ++ if !bytes.Equal(expected, out.Bytes()) { ++ t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) ++ } ++} ++ ++func v3KeyReader(t *testing.T) io.Reader { ++ armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor)) ++ if err != nil { ++ t.Fatalf("armor Decode failed: %v", err) ++ } ++ return armorBlock.Body ++} ++ ++// keySigV3Armor is some V3 public key I found in an SKS dump. ++// Old: Public Key Packet(tag 6)(141 bytes) ++// ++// Ver 4 - new ++// Public key creation time - Fri Sep 16 17:13:54 CDT 1994 ++// Pub alg - unknown(pub 0) ++// Unknown public key(pub 0) ++// ++// Old: User ID Packet(tag 13)(39 bytes) ++// ++// User ID - Armin M. Warda ++// ++// Old: Signature Packet(tag 2)(149 bytes) ++// ++// Ver 4 - new ++// Sig type - unknown(05) ++// Pub alg - ElGamal Encrypt-Only(pub 16) ++// Hash alg - unknown(hash 46) ++// Hashed Sub: unknown(sub 81, critical)(1988 bytes) ++const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++Version: SKS 1.0.10 ++ ++mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV ++5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi ++ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3 ++YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4 ++gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx ++524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF ++YFCbq4EjXRoOrYM= ++=LPjs ++-----END PGP PUBLIC KEY BLOCK-----` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go +new file mode 100644 +index 00000000000000..744c2d2c42dc5e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go +@@ -0,0 +1,155 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto/cipher" ++ "io" ++ "strconv" ++ ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/s2k" ++) ++ ++// This is the largest session key that we'll support. Since no 512-bit cipher ++// has even been seriously used, this is comfortably large. ++const maxSessionKeySizeInBytes = 64 ++ ++// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC ++// 4880, section 5.3. ++type SymmetricKeyEncrypted struct { ++ CipherFunc CipherFunction ++ s2k func(out, in []byte) ++ encryptedKey []byte ++} ++ ++const symmetricKeyEncryptedVersion = 4 ++ ++func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { ++ // RFC 4880, section 5.3. ++ var buf [2]byte ++ if _, err := readFull(r, buf[:]); err != nil { ++ return err ++ } ++ if buf[0] != symmetricKeyEncryptedVersion { ++ return errors.UnsupportedError("SymmetricKeyEncrypted version") ++ } ++ ske.CipherFunc = CipherFunction(buf[1]) ++ ++ if ske.CipherFunc.KeySize() == 0 { ++ return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) ++ } ++ ++ var err error ++ ske.s2k, err = s2k.Parse(r) ++ if err != nil { ++ return err ++ } ++ ++ encryptedKey := make([]byte, maxSessionKeySizeInBytes) ++ // The session key may follow. We just have to try and read to find ++ // out. If it exists then we limit it to maxSessionKeySizeInBytes. ++ n, err := readFull(r, encryptedKey) ++ if err != nil && err != io.ErrUnexpectedEOF { ++ return err ++ } ++ ++ if n != 0 { ++ if n == maxSessionKeySizeInBytes { ++ return errors.UnsupportedError("oversized encrypted session key") ++ } ++ ske.encryptedKey = encryptedKey[:n] ++ } ++ ++ return nil ++} ++ ++// Decrypt attempts to decrypt an encrypted session key and returns the key and ++// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data ++// packet. ++func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { ++ key := make([]byte, ske.CipherFunc.KeySize()) ++ ske.s2k(key, passphrase) ++ ++ if len(ske.encryptedKey) == 0 { ++ return key, ske.CipherFunc, nil ++ } ++ ++ // the IV is all zeros ++ iv := make([]byte, ske.CipherFunc.blockSize()) ++ c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) ++ plaintextKey := make([]byte, len(ske.encryptedKey)) ++ c.XORKeyStream(plaintextKey, ske.encryptedKey) ++ cipherFunc := CipherFunction(plaintextKey[0]) ++ if cipherFunc.blockSize() == 0 { ++ return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) ++ } ++ plaintextKey = plaintextKey[1:] ++ if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() { ++ return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " + ++ "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")") ++ } ++ return plaintextKey, cipherFunc, nil ++} ++ ++// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The ++// packet contains a random session key, encrypted by a key derived from the ++// given passphrase. The session key is returned and must be passed to ++// SerializeSymmetricallyEncrypted. ++// If config is nil, sensible defaults will be used. ++func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { ++ cipherFunc := config.Cipher() ++ keySize := cipherFunc.KeySize() ++ if keySize == 0 { ++ return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) ++ } ++ ++ s2kBuf := new(bytes.Buffer) ++ keyEncryptingKey := make([]byte, keySize) ++ // s2k.Serialize salts and stretches the passphrase, and writes the ++ // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. ++ err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) ++ if err != nil { ++ return ++ } ++ s2kBytes := s2kBuf.Bytes() ++ ++ packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize ++ err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) ++ if err != nil { ++ return ++ } ++ ++ var buf [2]byte ++ buf[0] = symmetricKeyEncryptedVersion ++ buf[1] = byte(cipherFunc) ++ _, err = w.Write(buf[:]) ++ if err != nil { ++ return ++ } ++ _, err = w.Write(s2kBytes) ++ if err != nil { ++ return ++ } ++ ++ sessionKey := make([]byte, keySize) ++ _, err = io.ReadFull(config.Random(), sessionKey) ++ if err != nil { ++ return ++ } ++ iv := make([]byte, cipherFunc.blockSize()) ++ c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) ++ encryptedCipherAndKey := make([]byte, keySize+1) ++ c.XORKeyStream(encryptedCipherAndKey, buf[1:]) ++ c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) ++ _, err = w.Write(encryptedCipherAndKey) ++ if err != nil { ++ return ++ } ++ ++ key = sessionKey ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go +new file mode 100644 +index 00000000000000..5471d77706dd28 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go +@@ -0,0 +1,116 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "io" ++ "testing" ++) ++ ++func TestSymmetricKeyEncrypted(t *testing.T) { ++ buf := readerFromHex(symmetricallyEncryptedHex) ++ packet, err := Read(buf) ++ if err != nil { ++ t.Errorf("failed to read SymmetricKeyEncrypted: %s", err) ++ return ++ } ++ ske, ok := packet.(*SymmetricKeyEncrypted) ++ if !ok { ++ t.Error("didn't find SymmetricKeyEncrypted packet") ++ return ++ } ++ key, cipherFunc, err := ske.Decrypt([]byte("password")) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ packet, err = Read(buf) ++ if err != nil { ++ t.Errorf("failed to read SymmetricallyEncrypted: %s", err) ++ return ++ } ++ se, ok := packet.(*SymmetricallyEncrypted) ++ if !ok { ++ t.Error("didn't find SymmetricallyEncrypted packet") ++ return ++ } ++ r, err := se.Decrypt(cipherFunc, key) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ contents, err := io.ReadAll(r) ++ if err != nil && err != io.EOF { ++ t.Error(err) ++ return ++ } ++ ++ expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex) ++ if !bytes.Equal(expectedContents, contents) { ++ t.Errorf("bad contents got:%x want:%x", contents, expectedContents) ++ } ++} ++ ++const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf" ++const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a" ++ ++func TestSerializeSymmetricKeyEncryptedCiphers(t *testing.T) { ++ tests := [...]struct { ++ cipherFunc CipherFunction ++ name string ++ }{ ++ {Cipher3DES, "Cipher3DES"}, ++ {CipherCAST5, "CipherCAST5"}, ++ {CipherAES128, "CipherAES128"}, ++ {CipherAES192, "CipherAES192"}, ++ {CipherAES256, "CipherAES256"}, ++ } ++ ++ for _, test := range tests { ++ var buf bytes.Buffer ++ passphrase := []byte("testing") ++ config := &Config{ ++ DefaultCipher: test.cipherFunc, ++ } ++ ++ key, err := SerializeSymmetricKeyEncrypted(&buf, passphrase, config) ++ if err != nil { ++ t.Errorf("cipher(%s) failed to serialize: %s", test.name, err) ++ continue ++ } ++ ++ p, err := Read(&buf) ++ if err != nil { ++ t.Errorf("cipher(%s) failed to reparse: %s", test.name, err) ++ continue ++ } ++ ++ ske, ok := p.(*SymmetricKeyEncrypted) ++ if !ok { ++ t.Errorf("cipher(%s) parsed a different packet type: %#v", test.name, p) ++ continue ++ } ++ ++ if ske.CipherFunc != config.DefaultCipher { ++ t.Errorf("cipher(%s) SKE cipher function is %d (expected %d)", test.name, ske.CipherFunc, config.DefaultCipher) ++ } ++ parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase) ++ if err != nil { ++ t.Errorf("cipher(%s) failed to decrypt reparsed SKE: %s", test.name, err) ++ continue ++ } ++ if !bytes.Equal(key, parsedKey) { ++ t.Errorf("cipher(%s) keys don't match after Decrypt: %x (original) vs %x (parsed)", test.name, key, parsedKey) ++ } ++ if parsedCipherFunc != test.cipherFunc { ++ t.Errorf("cipher(%s) cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)", ++ test.name, test.cipherFunc, parsedCipherFunc) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go +new file mode 100644 +index 00000000000000..1a1a62964fc952 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go +@@ -0,0 +1,290 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "crypto/cipher" ++ "crypto/sha1" ++ "crypto/subtle" ++ "golang.org/x/crypto/openpgp/errors" ++ "hash" ++ "io" ++ "strconv" ++) ++ ++// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The ++// encrypted contents will consist of more OpenPGP packets. See RFC 4880, ++// sections 5.7 and 5.13. ++type SymmetricallyEncrypted struct { ++ MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. ++ contents io.Reader ++ prefix []byte ++} ++ ++const symmetricallyEncryptedVersion = 1 ++ ++func (se *SymmetricallyEncrypted) parse(r io.Reader) error { ++ if se.MDC { ++ // See RFC 4880, section 5.13. ++ var buf [1]byte ++ _, err := readFull(r, buf[:]) ++ if err != nil { ++ return err ++ } ++ if buf[0] != symmetricallyEncryptedVersion { ++ return errors.UnsupportedError("unknown SymmetricallyEncrypted version") ++ } ++ } ++ se.contents = r ++ return nil ++} ++ ++// Decrypt returns a ReadCloser, from which the decrypted contents of the ++// packet can be read. An incorrect key can, with high probability, be detected ++// immediately and this will result in a KeyIncorrect error being returned. ++func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { ++ keySize := c.KeySize() ++ if keySize == 0 { ++ return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) ++ } ++ if len(key) != keySize { ++ return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") ++ } ++ ++ if se.prefix == nil { ++ se.prefix = make([]byte, c.blockSize()+2) ++ _, err := readFull(se.contents, se.prefix) ++ if err != nil { ++ return nil, err ++ } ++ } else if len(se.prefix) != c.blockSize()+2 { ++ return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") ++ } ++ ++ ocfbResync := OCFBResync ++ if se.MDC { ++ // MDC packets use a different form of OCFB mode. ++ ocfbResync = OCFBNoResync ++ } ++ ++ s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) ++ if s == nil { ++ return nil, errors.ErrKeyIncorrect ++ } ++ ++ plaintext := cipher.StreamReader{S: s, R: se.contents} ++ ++ if se.MDC { ++ // MDC packets have an embedded hash that we need to check. ++ h := sha1.New() ++ h.Write(se.prefix) ++ return &seMDCReader{in: plaintext, h: h}, nil ++ } ++ ++ // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. ++ return seReader{plaintext}, nil ++} ++ ++// seReader wraps an io.Reader with a no-op Close method. ++type seReader struct { ++ in io.Reader ++} ++ ++func (ser seReader) Read(buf []byte) (int, error) { ++ return ser.in.Read(buf) ++} ++ ++func (ser seReader) Close() error { ++ return nil ++} ++ ++const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size ++ ++// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold ++// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an ++// MDC packet containing a hash of the previous contents which is checked ++// against the running hash. See RFC 4880, section 5.13. ++type seMDCReader struct { ++ in io.Reader ++ h hash.Hash ++ trailer [mdcTrailerSize]byte ++ scratch [mdcTrailerSize]byte ++ trailerUsed int ++ error bool ++ eof bool ++} ++ ++func (ser *seMDCReader) Read(buf []byte) (n int, err error) { ++ if ser.error { ++ err = io.ErrUnexpectedEOF ++ return ++ } ++ if ser.eof { ++ err = io.EOF ++ return ++ } ++ ++ // If we haven't yet filled the trailer buffer then we must do that ++ // first. ++ for ser.trailerUsed < mdcTrailerSize { ++ n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) ++ ser.trailerUsed += n ++ if err == io.EOF { ++ if ser.trailerUsed != mdcTrailerSize { ++ n = 0 ++ err = io.ErrUnexpectedEOF ++ ser.error = true ++ return ++ } ++ ser.eof = true ++ n = 0 ++ return ++ } ++ ++ if err != nil { ++ n = 0 ++ return ++ } ++ } ++ ++ // If it's a short read then we read into a temporary buffer and shift ++ // the data into the caller's buffer. ++ if len(buf) <= mdcTrailerSize { ++ n, err = readFull(ser.in, ser.scratch[:len(buf)]) ++ copy(buf, ser.trailer[:n]) ++ ser.h.Write(buf[:n]) ++ copy(ser.trailer[:], ser.trailer[n:]) ++ copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) ++ if n < len(buf) { ++ ser.eof = true ++ err = io.EOF ++ } ++ return ++ } ++ ++ n, err = ser.in.Read(buf[mdcTrailerSize:]) ++ copy(buf, ser.trailer[:]) ++ ser.h.Write(buf[:n]) ++ copy(ser.trailer[:], buf[n:]) ++ ++ if err == io.EOF { ++ ser.eof = true ++ } ++ return ++} ++ ++// This is a new-format packet tag byte for a type 19 (MDC) packet. ++const mdcPacketTagByte = byte(0x80) | 0x40 | 19 ++ ++func (ser *seMDCReader) Close() error { ++ if ser.error { ++ return errors.SignatureError("error during reading") ++ } ++ ++ for !ser.eof { ++ // We haven't seen EOF so we need to read to the end ++ var buf [1024]byte ++ _, err := ser.Read(buf[:]) ++ if err == io.EOF { ++ break ++ } ++ if err != nil { ++ return errors.SignatureError("error during reading") ++ } ++ } ++ ++ if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { ++ return errors.SignatureError("MDC packet not found") ++ } ++ ser.h.Write(ser.trailer[:2]) ++ ++ final := ser.h.Sum(nil) ++ if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { ++ return errors.SignatureError("hash mismatch") ++ } ++ return nil ++} ++ ++// An seMDCWriter writes through to an io.WriteCloser while maintains a running ++// hash of the data written. On close, it emits an MDC packet containing the ++// running hash. ++type seMDCWriter struct { ++ w io.WriteCloser ++ h hash.Hash ++} ++ ++func (w *seMDCWriter) Write(buf []byte) (n int, err error) { ++ w.h.Write(buf) ++ return w.w.Write(buf) ++} ++ ++func (w *seMDCWriter) Close() (err error) { ++ var buf [mdcTrailerSize]byte ++ ++ buf[0] = mdcPacketTagByte ++ buf[1] = sha1.Size ++ w.h.Write(buf[:2]) ++ digest := w.h.Sum(nil) ++ copy(buf[2:], digest) ++ ++ _, err = w.w.Write(buf[:]) ++ if err != nil { ++ return ++ } ++ return w.w.Close() ++} ++ ++// noOpCloser is like an io.NopCloser, but for an io.Writer. ++type noOpCloser struct { ++ w io.Writer ++} ++ ++func (c noOpCloser) Write(data []byte) (n int, err error) { ++ return c.w.Write(data) ++} ++ ++func (c noOpCloser) Close() error { ++ return nil ++} ++ ++// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet ++// to w and returns a WriteCloser to which the to-be-encrypted packets can be ++// written. ++// If config is nil, sensible defaults will be used. ++func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { ++ if c.KeySize() != len(key) { ++ return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") ++ } ++ writeCloser := noOpCloser{w} ++ ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) ++ if err != nil { ++ return ++ } ++ ++ _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) ++ if err != nil { ++ return ++ } ++ ++ block := c.new(key) ++ blockSize := block.BlockSize() ++ iv := make([]byte, blockSize) ++ _, err = config.Random().Read(iv) ++ if err != nil { ++ return ++ } ++ s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) ++ _, err = ciphertext.Write(prefix) ++ if err != nil { ++ return ++ } ++ plaintext := cipher.StreamWriter{S: s, W: ciphertext} ++ ++ h := sha1.New() ++ h.Write(iv) ++ h.Write(iv[blockSize-2:]) ++ contents = &seMDCWriter{w: plaintext, h: h} ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go +new file mode 100644 +index 00000000000000..4c47c7b145a0f2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go +@@ -0,0 +1,122 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "crypto/sha1" ++ "encoding/hex" ++ "golang.org/x/crypto/openpgp/errors" ++ "io" ++ "testing" ++) ++ ++// TestReader wraps a []byte and returns reads of a specific length. ++type testReader struct { ++ data []byte ++ stride int ++} ++ ++func (t *testReader) Read(buf []byte) (n int, err error) { ++ n = t.stride ++ if n > len(t.data) { ++ n = len(t.data) ++ } ++ if n > len(buf) { ++ n = len(buf) ++ } ++ copy(buf, t.data) ++ t.data = t.data[n:] ++ if len(t.data) == 0 { ++ err = io.EOF ++ } ++ return ++} ++ ++func testMDCReader(t *testing.T) { ++ mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex) ++ ++ for stride := 1; stride < len(mdcPlaintext)/2; stride++ { ++ r := &testReader{data: mdcPlaintext, stride: stride} ++ mdcReader := &seMDCReader{in: r, h: sha1.New()} ++ body, err := io.ReadAll(mdcReader) ++ if err != nil { ++ t.Errorf("stride: %d, error: %s", stride, err) ++ continue ++ } ++ if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) { ++ t.Errorf("stride: %d: bad contents %x", stride, body) ++ continue ++ } ++ ++ err = mdcReader.Close() ++ if err != nil { ++ t.Errorf("stride: %d, error on Close: %s", stride, err) ++ } ++ } ++ ++ mdcPlaintext[15] ^= 80 ++ ++ r := &testReader{data: mdcPlaintext, stride: 2} ++ mdcReader := &seMDCReader{in: r, h: sha1.New()} ++ _, err := io.ReadAll(mdcReader) ++ if err != nil { ++ t.Errorf("corruption test, error: %s", err) ++ return ++ } ++ err = mdcReader.Close() ++ if err == nil { ++ t.Error("corruption: no error") ++ } else if _, ok := err.(*errors.SignatureError); !ok { ++ t.Errorf("corruption: expected SignatureError, got: %s", err) ++ } ++} ++ ++const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980" ++ ++func TestSerialize(t *testing.T) { ++ buf := bytes.NewBuffer(nil) ++ c := CipherAES128 ++ key := make([]byte, c.KeySize()) ++ ++ w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil) ++ if err != nil { ++ t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err) ++ return ++ } ++ ++ contents := []byte("hello world\n") ++ ++ w.Write(contents) ++ w.Close() ++ ++ p, err := Read(buf) ++ if err != nil { ++ t.Errorf("error from Read: %s", err) ++ return ++ } ++ ++ se, ok := p.(*SymmetricallyEncrypted) ++ if !ok { ++ t.Errorf("didn't read a *SymmetricallyEncrypted") ++ return ++ } ++ ++ r, err := se.Decrypt(c, key) ++ if err != nil { ++ t.Errorf("error from Decrypt: %s", err) ++ return ++ } ++ ++ contentsCopy := bytes.NewBuffer(nil) ++ _, err = io.Copy(contentsCopy, r) ++ if err != nil { ++ t.Errorf("error from io.Copy: %s", err) ++ return ++ } ++ if !bytes.Equal(contentsCopy.Bytes(), contents) { ++ t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go +new file mode 100644 +index 00000000000000..ff7ef5307557ea +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go +@@ -0,0 +1,90 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "image" ++ "image/jpeg" ++ "io" ++) ++ ++const UserAttrImageSubpacket = 1 ++ ++// UserAttribute is capable of storing other types of data about a user ++// beyond name, email and a text comment. In practice, user attributes are typically used ++// to store a signed thumbnail photo JPEG image of the user. ++// See RFC 4880, section 5.12. ++type UserAttribute struct { ++ Contents []*OpaqueSubpacket ++} ++ ++// NewUserAttributePhoto creates a user attribute packet ++// containing the given images. ++func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { ++ uat = new(UserAttribute) ++ for _, photo := range photos { ++ var buf bytes.Buffer ++ // RFC 4880, Section 5.12.1. ++ data := []byte{ ++ 0x10, 0x00, // Little-endian image header length (16 bytes) ++ 0x01, // Image header version 1 ++ 0x01, // JPEG ++ 0, 0, 0, 0, // 12 reserved octets, must be all zero. ++ 0, 0, 0, 0, ++ 0, 0, 0, 0} ++ if _, err = buf.Write(data); err != nil { ++ return ++ } ++ if err = jpeg.Encode(&buf, photo, nil); err != nil { ++ return ++ } ++ uat.Contents = append(uat.Contents, &OpaqueSubpacket{ ++ SubType: UserAttrImageSubpacket, ++ Contents: buf.Bytes()}) ++ } ++ return ++} ++ ++// NewUserAttribute creates a new user attribute packet containing the given subpackets. ++func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { ++ return &UserAttribute{Contents: contents} ++} ++ ++func (uat *UserAttribute) parse(r io.Reader) (err error) { ++ // RFC 4880, section 5.13 ++ b, err := io.ReadAll(r) ++ if err != nil { ++ return ++ } ++ uat.Contents, err = OpaqueSubpackets(b) ++ return ++} ++ ++// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including ++// header. ++func (uat *UserAttribute) Serialize(w io.Writer) (err error) { ++ var buf bytes.Buffer ++ for _, sp := range uat.Contents { ++ sp.Serialize(&buf) ++ } ++ if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { ++ return err ++ } ++ _, err = w.Write(buf.Bytes()) ++ return ++} ++ ++// ImageData returns zero or more byte slices, each containing ++// JPEG File Interchange Format (JFIF), for each photo in the ++// user attribute packet. ++func (uat *UserAttribute) ImageData() (imageData [][]byte) { ++ for _, sp := range uat.Contents { ++ if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { ++ imageData = append(imageData, sp.Contents[16:]) ++ } ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go +new file mode 100644 +index 00000000000000..13ca5143cee62c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go +@@ -0,0 +1,109 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "bytes" ++ "encoding/base64" ++ "image/color" ++ "image/jpeg" ++ "testing" ++) ++ ++func TestParseUserAttribute(t *testing.T) { ++ r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket)) ++ for i := 0; i < 2; i++ { ++ p, err := Read(r) ++ if err != nil { ++ t.Fatal(err) ++ } ++ uat := p.(*UserAttribute) ++ imgs := uat.ImageData() ++ if len(imgs) != 1 { ++ t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs)) ++ } ++ if len(imgs[0]) != 3395 { ++ t.Errorf("Unexpected JPEG image size: %d", len(imgs[0])) ++ } ++ img, err := jpeg.Decode(bytes.NewBuffer(imgs[0])) ++ if err != nil { ++ t.Errorf("Error decoding JPEG image: %v", err) ++ } ++ // A pixel in my right eye. ++ pixel := color.NRGBAModel.Convert(img.At(56, 36)) ++ ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255} ++ if pixel != ref { ++ t.Errorf("Unexpected pixel color: %v", pixel) ++ } ++ w := bytes.NewBuffer(nil) ++ err = uat.Serialize(w) ++ if err != nil { ++ t.Errorf("Error writing user attribute: %v", err) ++ } ++ r = bytes.NewBuffer(w.Bytes()) ++ } ++} ++ ++const userAttributePacket = ` ++0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE ++BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA ++QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e ++Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH ++CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw ++JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6 ++g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk ++5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB ++AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX ++GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT ++lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2 ++9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN ++pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od ++W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova ++ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH ++/eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09 ++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` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userid.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userid.go +new file mode 100644 +index 00000000000000..359a462eb8ab64 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userid.go +@@ -0,0 +1,159 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "io" ++ "strings" ++) ++ ++// UserId contains text that is intended to represent the name and email ++// address of the key holder. See RFC 4880, section 5.11. By convention, this ++// takes the form "Full Name (Comment) " ++type UserId struct { ++ Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. ++ ++ Name, Comment, Email string ++} ++ ++func hasInvalidCharacters(s string) bool { ++ for _, c := range s { ++ switch c { ++ case '(', ')', '<', '>', 0: ++ return true ++ } ++ } ++ return false ++} ++ ++// NewUserId returns a UserId or nil if any of the arguments contain invalid ++// characters. The invalid characters are '\x00', '(', ')', '<' and '>' ++func NewUserId(name, comment, email string) *UserId { ++ // RFC 4880 doesn't deal with the structure of userid strings; the ++ // name, comment and email form is just a convention. However, there's ++ // no convention about escaping the metacharacters and GPG just refuses ++ // to create user ids where, say, the name contains a '('. We mirror ++ // this behaviour. ++ ++ if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { ++ return nil ++ } ++ ++ uid := new(UserId) ++ uid.Name, uid.Comment, uid.Email = name, comment, email ++ uid.Id = name ++ if len(comment) > 0 { ++ if len(uid.Id) > 0 { ++ uid.Id += " " ++ } ++ uid.Id += "(" ++ uid.Id += comment ++ uid.Id += ")" ++ } ++ if len(email) > 0 { ++ if len(uid.Id) > 0 { ++ uid.Id += " " ++ } ++ uid.Id += "<" ++ uid.Id += email ++ uid.Id += ">" ++ } ++ return uid ++} ++ ++func (uid *UserId) parse(r io.Reader) (err error) { ++ // RFC 4880, section 5.11 ++ b, err := io.ReadAll(r) ++ if err != nil { ++ return ++ } ++ uid.Id = string(b) ++ uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) ++ return ++} ++ ++// Serialize marshals uid to w in the form of an OpenPGP packet, including ++// header. ++func (uid *UserId) Serialize(w io.Writer) error { ++ err := serializeHeader(w, packetTypeUserId, len(uid.Id)) ++ if err != nil { ++ return err ++ } ++ _, err = w.Write([]byte(uid.Id)) ++ return err ++} ++ ++// parseUserId extracts the name, comment and email from a user id string that ++// is formatted as "Full Name (Comment) ". ++func parseUserId(id string) (name, comment, email string) { ++ var n, c, e struct { ++ start, end int ++ } ++ var state int ++ ++ for offset, rune := range id { ++ switch state { ++ case 0: ++ // Entering name ++ n.start = offset ++ state = 1 ++ fallthrough ++ case 1: ++ // In name ++ if rune == '(' { ++ state = 2 ++ n.end = offset ++ } else if rune == '<' { ++ state = 5 ++ n.end = offset ++ } ++ case 2: ++ // Entering comment ++ c.start = offset ++ state = 3 ++ fallthrough ++ case 3: ++ // In comment ++ if rune == ')' { ++ state = 4 ++ c.end = offset ++ } ++ case 4: ++ // Between comment and email ++ if rune == '<' { ++ state = 5 ++ } ++ case 5: ++ // Entering email ++ e.start = offset ++ state = 6 ++ fallthrough ++ case 6: ++ // In email ++ if rune == '>' { ++ state = 7 ++ e.end = offset ++ } ++ default: ++ // After email ++ } ++ } ++ switch state { ++ case 1: ++ // ended in the name ++ n.end = len(id) ++ case 3: ++ // ended in comment ++ c.end = len(id) ++ case 6: ++ // ended in email ++ e.end = len(id) ++ } ++ ++ name = strings.TrimSpace(id[n.start:n.end]) ++ comment = strings.TrimSpace(id[c.start:c.end]) ++ email = strings.TrimSpace(id[e.start:e.end]) ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go +new file mode 100644 +index 00000000000000..29681938938c68 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go +@@ -0,0 +1,87 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package packet ++ ++import ( ++ "testing" ++) ++ ++var userIdTests = []struct { ++ id string ++ name, comment, email string ++}{ ++ {"", "", "", ""}, ++ {"John Smith", "John Smith", "", ""}, ++ {"John Smith ()", "John Smith", "", ""}, ++ {"John Smith () <>", "John Smith", "", ""}, ++ {"(comment", "", "comment", ""}, ++ {"(comment)", "", "comment", ""}, ++ {" sdfk", "", "", "email"}, ++ {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"}, ++ {" John Smith < email > lksdfj", "John Smith", "", "email"}, ++ {"("}, ++ {"foo", "bar", "", "foo (bar)"}, ++ {"foo", "", "baz", "foo "}, ++ {"", "bar", "baz", "(bar) "}, ++ {"foo", "bar", "baz", "foo (bar) "}, ++} ++ ++func TestNewUserId(t *testing.T) { ++ for i, test := range newUserIdTests { ++ uid := NewUserId(test.name, test.comment, test.email) ++ if uid == nil { ++ t.Errorf("#%d: returned nil", i) ++ continue ++ } ++ if uid.Id != test.id { ++ t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id) ++ } ++ } ++} ++ ++var invalidNewUserIdTests = []struct { ++ name, comment, email string ++}{ ++ {"foo(", "", ""}, ++ {"foo<", "", ""}, ++ {"", "bar)", ""}, ++ {"", "bar<", ""}, ++ {"", "", "baz>"}, ++ {"", "", "baz)"}, ++ {"", "", "baz\x00"}, ++} ++ ++func TestNewUserIdWithInvalidInput(t *testing.T) { ++ for i, test := range invalidNewUserIdTests { ++ if uid := NewUserId(test.name, test.comment, test.email); uid != nil { ++ t.Errorf("#%d: returned non-nil value: %#v", i, uid) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/read.go b/ms_mod/golang.org/x/crypto/openpgp/read.go +new file mode 100644 +index 00000000000000..48a893146858ca +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/read.go +@@ -0,0 +1,448 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package openpgp implements high level operations on OpenPGP messages. ++// ++// Deprecated: this package is unmaintained except for security fixes. New ++// applications should consider a more focused, modern alternative to OpenPGP ++// for their specific task. If you are required to interoperate with OpenPGP ++// systems and need a maintained package, consider a community fork. ++// See https://golang.org/issue/44226. ++package openpgp // import "golang.org/x/crypto/openpgp" ++ ++import ( ++ "crypto" ++ _ "crypto/sha256" ++ "hash" ++ "io" ++ "strconv" ++ ++ "golang.org/x/crypto/openpgp/armor" ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/packet" ++) ++ ++// SignatureType is the armor type for a PGP signature. ++var SignatureType = "PGP SIGNATURE" ++ ++// readArmored reads an armored block with the given type. ++func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { ++ block, err := armor.Decode(r) ++ if err != nil { ++ return ++ } ++ ++ if block.Type != expectedType { ++ return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) ++ } ++ ++ return block.Body, nil ++} ++ ++// MessageDetails contains the result of parsing an OpenPGP encrypted and/or ++// signed message. ++type MessageDetails struct { ++ IsEncrypted bool // true if the message was encrypted. ++ EncryptedToKeyIds []uint64 // the list of recipient key ids. ++ IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. ++ DecryptedWith Key // the private key used to decrypt the message, if any. ++ IsSigned bool // true if the message is signed. ++ SignedByKeyId uint64 // the key id of the signer, if any. ++ SignedBy *Key // the key of the signer, if available. ++ LiteralData *packet.LiteralData // the metadata of the contents ++ UnverifiedBody io.Reader // the contents of the message. ++ ++ // If IsSigned is true and SignedBy is non-zero then the signature will ++ // be verified as UnverifiedBody is read. The signature cannot be ++ // checked until the whole of UnverifiedBody is read so UnverifiedBody ++ // must be consumed until EOF before the data can be trusted. Even if a ++ // message isn't signed (or the signer is unknown) the data may contain ++ // an authentication code that is only checked once UnverifiedBody has ++ // been consumed. Once EOF has been seen, the following fields are ++ // valid. (An authentication code failure is reported as a ++ // SignatureError error when reading from UnverifiedBody.) ++ SignatureError error // nil if the signature is good. ++ Signature *packet.Signature // the signature packet itself, if v4 (default) ++ SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature ++ ++ decrypted io.ReadCloser ++} ++ ++// A PromptFunction is used as a callback by functions that may need to decrypt ++// a private key, or prompt for a passphrase. It is called with a list of ++// acceptable, encrypted private keys and a boolean that indicates whether a ++// passphrase is usable. It should either decrypt a private key or return a ++// passphrase to try. If the decrypted private key or given passphrase isn't ++// correct, the function will be called again, forever. Any error returned will ++// be passed up. ++type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) ++ ++// A keyEnvelopePair is used to store a private key with the envelope that ++// contains a symmetric key, encrypted with that key. ++type keyEnvelopePair struct { ++ key Key ++ encryptedKey *packet.EncryptedKey ++} ++ ++// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. ++// The given KeyRing should contain both public keys (for signature ++// verification) and, possibly encrypted, private keys for decrypting. ++// If config is nil, sensible defaults will be used. ++func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { ++ var p packet.Packet ++ ++ var symKeys []*packet.SymmetricKeyEncrypted ++ var pubKeys []keyEnvelopePair ++ var se *packet.SymmetricallyEncrypted ++ ++ packets := packet.NewReader(r) ++ md = new(MessageDetails) ++ md.IsEncrypted = true ++ ++ // The message, if encrypted, starts with a number of packets ++ // containing an encrypted decryption key. The decryption key is either ++ // encrypted to a public key, or with a passphrase. This loop ++ // collects these packets. ++ParsePackets: ++ for { ++ p, err = packets.Next() ++ if err != nil { ++ return nil, err ++ } ++ switch p := p.(type) { ++ case *packet.SymmetricKeyEncrypted: ++ // This packet contains the decryption key encrypted with a passphrase. ++ md.IsSymmetricallyEncrypted = true ++ symKeys = append(symKeys, p) ++ case *packet.EncryptedKey: ++ // This packet contains the decryption key encrypted to a public key. ++ md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) ++ switch p.Algo { ++ case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: ++ break ++ default: ++ continue ++ } ++ var keys []Key ++ if p.KeyId == 0 { ++ keys = keyring.DecryptionKeys() ++ } else { ++ keys = keyring.KeysById(p.KeyId) ++ } ++ for _, k := range keys { ++ pubKeys = append(pubKeys, keyEnvelopePair{k, p}) ++ } ++ case *packet.SymmetricallyEncrypted: ++ se = p ++ break ParsePackets ++ case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: ++ // This message isn't encrypted. ++ if len(symKeys) != 0 || len(pubKeys) != 0 { ++ return nil, errors.StructuralError("key material not followed by encrypted message") ++ } ++ packets.Unread(p) ++ return readSignedMessage(packets, nil, keyring) ++ } ++ } ++ ++ var candidates []Key ++ var decrypted io.ReadCloser ++ ++ // Now that we have the list of encrypted keys we need to decrypt at ++ // least one of them or, if we cannot, we need to call the prompt ++ // function so that it can decrypt a key or give us a passphrase. ++FindKey: ++ for { ++ // See if any of the keys already have a private key available ++ candidates = candidates[:0] ++ candidateFingerprints := make(map[string]bool) ++ ++ for _, pk := range pubKeys { ++ if pk.key.PrivateKey == nil { ++ continue ++ } ++ if !pk.key.PrivateKey.Encrypted { ++ if len(pk.encryptedKey.Key) == 0 { ++ pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) ++ } ++ if len(pk.encryptedKey.Key) == 0 { ++ continue ++ } ++ decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) ++ if err != nil && err != errors.ErrKeyIncorrect { ++ return nil, err ++ } ++ if decrypted != nil { ++ md.DecryptedWith = pk.key ++ break FindKey ++ } ++ } else { ++ fpr := string(pk.key.PublicKey.Fingerprint[:]) ++ if v := candidateFingerprints[fpr]; v { ++ continue ++ } ++ candidates = append(candidates, pk.key) ++ candidateFingerprints[fpr] = true ++ } ++ } ++ ++ if len(candidates) == 0 && len(symKeys) == 0 { ++ return nil, errors.ErrKeyIncorrect ++ } ++ ++ if prompt == nil { ++ return nil, errors.ErrKeyIncorrect ++ } ++ ++ passphrase, err := prompt(candidates, len(symKeys) != 0) ++ if err != nil { ++ return nil, err ++ } ++ ++ // Try the symmetric passphrase first ++ if len(symKeys) != 0 && passphrase != nil { ++ for _, s := range symKeys { ++ key, cipherFunc, err := s.Decrypt(passphrase) ++ if err == nil { ++ decrypted, err = se.Decrypt(cipherFunc, key) ++ if err != nil && err != errors.ErrKeyIncorrect { ++ return nil, err ++ } ++ if decrypted != nil { ++ break FindKey ++ } ++ } ++ ++ } ++ } ++ } ++ ++ md.decrypted = decrypted ++ if err := packets.Push(decrypted); err != nil { ++ return nil, err ++ } ++ return readSignedMessage(packets, md, keyring) ++} ++ ++// readSignedMessage reads a possibly signed message if mdin is non-zero then ++// that structure is updated and returned. Otherwise a fresh MessageDetails is ++// used. ++func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { ++ if mdin == nil { ++ mdin = new(MessageDetails) ++ } ++ md = mdin ++ ++ var p packet.Packet ++ var h hash.Hash ++ var wrappedHash hash.Hash ++FindLiteralData: ++ for { ++ p, err = packets.Next() ++ if err != nil { ++ return nil, err ++ } ++ switch p := p.(type) { ++ case *packet.Compressed: ++ if err := packets.Push(p.Body); err != nil { ++ return nil, err ++ } ++ case *packet.OnePassSignature: ++ if !p.IsLast { ++ return nil, errors.UnsupportedError("nested signatures") ++ } ++ ++ h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) ++ if err != nil { ++ md = nil ++ return ++ } ++ ++ md.IsSigned = true ++ md.SignedByKeyId = p.KeyId ++ keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) ++ if len(keys) > 0 { ++ md.SignedBy = &keys[0] ++ } ++ case *packet.LiteralData: ++ md.LiteralData = p ++ break FindLiteralData ++ } ++ } ++ ++ if md.SignedBy != nil { ++ md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} ++ } else if md.decrypted != nil { ++ md.UnverifiedBody = checkReader{md} ++ } else { ++ md.UnverifiedBody = md.LiteralData.Body ++ } ++ ++ return md, nil ++} ++ ++// hashForSignature returns a pair of hashes that can be used to verify a ++// signature. The signature may specify that the contents of the signed message ++// should be preprocessed (i.e. to normalize line endings). Thus this function ++// returns two hashes. The second should be used to hash the message itself and ++// performs any needed preprocessing. ++func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { ++ if !hashId.Available() { ++ return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) ++ } ++ h := hashId.New() ++ ++ switch sigType { ++ case packet.SigTypeBinary: ++ return h, h, nil ++ case packet.SigTypeText: ++ return h, NewCanonicalTextHash(h), nil ++ } ++ ++ return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) ++} ++ ++// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF ++// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger ++// MDC checks. ++type checkReader struct { ++ md *MessageDetails ++} ++ ++func (cr checkReader) Read(buf []byte) (n int, err error) { ++ n, err = cr.md.LiteralData.Body.Read(buf) ++ if err == io.EOF { ++ mdcErr := cr.md.decrypted.Close() ++ if mdcErr != nil { ++ err = mdcErr ++ } ++ } ++ return ++} ++ ++// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes ++// the data as it is read. When it sees an EOF from the underlying io.Reader ++// it parses and checks a trailing Signature packet and triggers any MDC checks. ++type signatureCheckReader struct { ++ packets *packet.Reader ++ h, wrappedHash hash.Hash ++ md *MessageDetails ++} ++ ++func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { ++ n, err = scr.md.LiteralData.Body.Read(buf) ++ scr.wrappedHash.Write(buf[:n]) ++ if err == io.EOF { ++ var p packet.Packet ++ p, scr.md.SignatureError = scr.packets.Next() ++ if scr.md.SignatureError != nil { ++ return ++ } ++ ++ var ok bool ++ if scr.md.Signature, ok = p.(*packet.Signature); ok { ++ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) ++ } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { ++ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) ++ } else { ++ scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") ++ return ++ } ++ ++ // The SymmetricallyEncrypted packet, if any, might have an ++ // unsigned hash of its own. In order to check this we need to ++ // close that Reader. ++ if scr.md.decrypted != nil { ++ mdcErr := scr.md.decrypted.Close() ++ if mdcErr != nil { ++ err = mdcErr ++ } ++ } ++ } ++ return ++} ++ ++// CheckDetachedSignature takes a signed file and a detached signature and ++// returns the signer if the signature is valid. If the signer isn't known, ++// ErrUnknownIssuer is returned. ++func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { ++ var issuerKeyId uint64 ++ var hashFunc crypto.Hash ++ var sigType packet.SignatureType ++ var keys []Key ++ var p packet.Packet ++ ++ packets := packet.NewReader(signature) ++ for { ++ p, err = packets.Next() ++ if err == io.EOF { ++ return nil, errors.ErrUnknownIssuer ++ } ++ if err != nil { ++ return nil, err ++ } ++ ++ switch sig := p.(type) { ++ case *packet.Signature: ++ if sig.IssuerKeyId == nil { ++ return nil, errors.StructuralError("signature doesn't have an issuer") ++ } ++ issuerKeyId = *sig.IssuerKeyId ++ hashFunc = sig.Hash ++ sigType = sig.SigType ++ case *packet.SignatureV3: ++ issuerKeyId = sig.IssuerKeyId ++ hashFunc = sig.Hash ++ sigType = sig.SigType ++ default: ++ return nil, errors.StructuralError("non signature packet found") ++ } ++ ++ keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) ++ if len(keys) > 0 { ++ break ++ } ++ } ++ ++ if len(keys) == 0 { ++ panic("unreachable") ++ } ++ ++ h, wrappedHash, err := hashForSignature(hashFunc, sigType) ++ if err != nil { ++ return nil, err ++ } ++ ++ if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { ++ return nil, err ++ } ++ ++ for _, key := range keys { ++ switch sig := p.(type) { ++ case *packet.Signature: ++ err = key.PublicKey.VerifySignature(h, sig) ++ case *packet.SignatureV3: ++ err = key.PublicKey.VerifySignatureV3(h, sig) ++ default: ++ panic("unreachable") ++ } ++ ++ if err == nil { ++ return key.Entity, nil ++ } ++ } ++ ++ return nil, err ++} ++ ++// CheckArmoredDetachedSignature performs the same actions as ++// CheckDetachedSignature but expects the signature to be armored. ++func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { ++ body, err := readArmored(signature, SignatureType) ++ if err != nil { ++ return ++ } ++ ++ return CheckDetachedSignature(keyring, signed, body) ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/read_test.go b/ms_mod/golang.org/x/crypto/openpgp/read_test.go +new file mode 100644 +index 00000000000000..6bbfaf1afb4894 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/read_test.go +@@ -0,0 +1,612 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package openpgp ++ ++import ( ++ "bytes" ++ _ "crypto/sha512" ++ "encoding/hex" ++ "io" ++ "strings" ++ "testing" ++ ++ "golang.org/x/crypto/openpgp/armor" ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++func readerFromHex(s string) io.Reader { ++ data, err := hex.DecodeString(s) ++ if err != nil { ++ panic("readerFromHex: bad input") ++ } ++ return bytes.NewBuffer(data) ++} ++ ++func TestReadKeyRing(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B { ++ t.Errorf("bad keyring: %#v", kring) ++ } ++} ++ ++func TestRereadKeyRing(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ if err != nil { ++ t.Errorf("error in initial parse: %s", err) ++ return ++ } ++ out := new(bytes.Buffer) ++ err = kring[0].Serialize(out) ++ if err != nil { ++ t.Errorf("error in serialization: %s", err) ++ return ++ } ++ kring, err = ReadKeyRing(out) ++ if err != nil { ++ t.Errorf("error in second parse: %s", err) ++ return ++ } ++ ++ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB { ++ t.Errorf("bad keyring: %#v", kring) ++ } ++} ++ ++func TestReadPrivateKeyRing(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil { ++ t.Errorf("bad keyring: %#v", kring) ++ } ++} ++ ++func TestReadDSAKey(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 { ++ t.Errorf("bad parse: %#v", kring) ++ } ++} ++ ++func TestReadP256Key(t *testing.T) { ++ kring, err := ReadKeyRing(readerFromHex(p256TestKeyHex)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x5918513E { ++ t.Errorf("bad parse: %#v", kring) ++ } ++} ++ ++func TestDSAHashTruncatation(t *testing.T) { ++ // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo ++ // SHA512 in order to require DSA hash truncation to verify correctly. ++ _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512)) ++ if err != nil { ++ t.Error(err) ++ } ++} ++ ++func TestGetKeyById(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ ++ keys := kring.KeysById(0xa34d7e18c20c31bb) ++ if len(keys) != 1 || keys[0].Entity != kring[0] { ++ t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) ++ } ++ ++ keys = kring.KeysById(0xfd94408d4543314f) ++ if len(keys) != 1 || keys[0].Entity != kring[0] { ++ t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) ++ } ++} ++ ++func checkSignedMessage(t *testing.T, signedHex, expected string) { ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ ++ md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.DecryptedWith != (Key{}) { ++ t.Errorf("bad MessageDetails: %#v", md) ++ } ++ ++ contents, err := io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("error reading UnverifiedBody: %s", err) ++ } ++ if string(contents) != expected { ++ t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) ++ } ++ if md.SignatureError != nil || md.Signature == nil { ++ t.Errorf("failed to validate: %s", md.SignatureError) ++ } ++} ++ ++func TestSignedMessage(t *testing.T) { ++ checkSignedMessage(t, signedMessageHex, signedInput) ++} ++ ++func TestTextSignedMessage(t *testing.T) { ++ checkSignedMessage(t, signedTextMessageHex, signedTextInput) ++} ++ ++// The reader should detect "compressed quines", which are compressed ++// packets that expand into themselves and cause an infinite recursive ++// parsing loop. ++// The packet in this test case comes from Taylor R. Campbell at ++// http://mumble.net/~campbell/misc/pgp-quine/ ++func TestCampbellQuine(t *testing.T) { ++ md, err := ReadMessage(readerFromHex(campbellQuine), nil, nil, nil) ++ if md != nil { ++ t.Errorf("Reading a compressed quine should not return any data: %#v", md) ++ } ++ structural, ok := err.(errors.StructuralError) ++ if !ok { ++ t.Fatalf("Unexpected class of error: %T", err) ++ } ++ if !strings.Contains(string(structural), "too many layers of packets") { ++ t.Fatalf("Unexpected error: %s", err) ++ } ++} ++ ++var signedEncryptedMessageTests = []struct { ++ keyRingHex string ++ messageHex string ++ signedByKeyId uint64 ++ encryptedToKeyId uint64 ++}{ ++ { ++ testKeys1And2PrivateHex, ++ signedEncryptedMessageHex, ++ 0xa34d7e18c20c31bb, ++ 0x2a67d68660df41c7, ++ }, ++ { ++ dsaElGamalTestKeysHex, ++ signedEncryptedMessage2Hex, ++ 0x33af447ccd759b09, ++ 0xcf6a7abcd43e3673, ++ }, ++} ++ ++func TestSignedEncryptedMessage(t *testing.T) { ++ for i, test := range signedEncryptedMessageTests { ++ expected := "Signed and encrypted message\n" ++ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) ++ prompt := func(keys []Key, symmetric bool) ([]byte, error) { ++ if symmetric { ++ t.Errorf("prompt: message was marked as symmetrically encrypted") ++ return nil, errors.ErrKeyIncorrect ++ } ++ ++ if len(keys) == 0 { ++ t.Error("prompt: no keys requested") ++ return nil, errors.ErrKeyIncorrect ++ } ++ ++ err := keys[0].PrivateKey.Decrypt([]byte("passphrase")) ++ if err != nil { ++ t.Errorf("prompt: error decrypting key: %s", err) ++ return nil, errors.ErrKeyIncorrect ++ } ++ ++ return nil, nil ++ } ++ ++ md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil) ++ if err != nil { ++ t.Errorf("#%d: error reading message: %s", i, err) ++ return ++ } ++ ++ if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId { ++ t.Errorf("#%d: bad MessageDetails: %#v", i, md) ++ } ++ ++ contents, err := io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("#%d: error reading UnverifiedBody: %s", i, err) ++ } ++ if string(contents) != expected { ++ t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected) ++ } ++ ++ if md.SignatureError != nil || md.Signature == nil { ++ t.Errorf("#%d: failed to validate: %s", i, md.SignatureError) ++ } ++ } ++} ++ ++func TestUnspecifiedRecipient(t *testing.T) { ++ expected := "Recipient unspecified\n" ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) ++ ++ md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil) ++ if err != nil { ++ t.Errorf("error reading message: %s", err) ++ return ++ } ++ ++ contents, err := io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("error reading UnverifiedBody: %s", err) ++ } ++ if string(contents) != expected { ++ t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) ++ } ++} ++ ++func TestSymmetricallyEncrypted(t *testing.T) { ++ firstTimeCalled := true ++ ++ prompt := func(keys []Key, symmetric bool) ([]byte, error) { ++ if len(keys) != 0 { ++ t.Errorf("prompt: len(keys) = %d (want 0)", len(keys)) ++ } ++ ++ if !symmetric { ++ t.Errorf("symmetric is not set") ++ } ++ ++ if firstTimeCalled { ++ firstTimeCalled = false ++ return []byte("wrongpassword"), nil ++ } ++ ++ return []byte("password"), nil ++ } ++ ++ md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil) ++ if err != nil { ++ t.Errorf("ReadMessage: %s", err) ++ return ++ } ++ ++ contents, err := io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("ReadAll: %s", err) ++ } ++ ++ expectedCreationTime := uint32(1295992998) ++ if md.LiteralData.Time != expectedCreationTime { ++ t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime) ++ } ++ ++ const expected = "Symmetrically encrypted.\n" ++ if string(contents) != expected { ++ t.Errorf("contents got: %s want: %s", string(contents), expected) ++ } ++} ++ ++func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) { ++ signed := bytes.NewBufferString(sigInput) ++ signer, err := CheckDetachedSignature(kring, signed, signature) ++ if err != nil { ++ t.Errorf("%s: signature error: %s", tag, err) ++ return ++ } ++ if signer == nil { ++ t.Errorf("%s: signer is nil", tag) ++ return ++ } ++ if signer.PrimaryKey.KeyId != expectedSignerKeyId { ++ t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId) ++ } ++} ++ ++func TestDetachedSignature(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId) ++ testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId) ++ testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId) ++ ++ incorrectSignedInput := signedInput + "X" ++ _, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex)) ++ if err == nil { ++ t.Fatal("CheckDetachedSignature returned without error for bad signature") ++ } ++ if err == errors.ErrUnknownIssuer { ++ t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid") ++ } ++} ++ ++func TestDetachedSignatureDSA(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) ++ testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) ++} ++ ++func TestMultipleSignaturePacketsDSA(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) ++ testDetachedSignature(t, kring, readerFromHex(missingHashFunctionHex+detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) ++} ++ ++func TestDetachedSignatureP256(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(p256TestKeyHex)) ++ testDetachedSignature(t, kring, readerFromHex(detachedSignatureP256Hex), signedInput, "binary", testKeyP256KeyId) ++} ++ ++func testHashFunctionError(t *testing.T, signatureHex string) { ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ _, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex)) ++ if err == nil { ++ t.Fatal("Packet with bad hash type was correctly parsed") ++ } ++ unsupported, ok := err.(errors.UnsupportedError) ++ if !ok { ++ t.Fatalf("Unexpected class of error: %s", err) ++ } ++ if !strings.Contains(string(unsupported), "hash ") { ++ t.Fatalf("Unexpected error: %s", err) ++ } ++} ++ ++func TestUnknownHashFunction(t *testing.T) { ++ // unknownHashFunctionHex contains a signature packet with hash ++ // function type 153 (which isn't a real hash function id). ++ testHashFunctionError(t, unknownHashFunctionHex) ++} ++ ++func TestMissingHashFunction(t *testing.T) { ++ // missingHashFunctionHex contains a signature packet that uses ++ // RIPEMD160, which isn't compiled in. Since that's the only signature ++ // packet we don't find any suitable packets and end up with ErrUnknownIssuer ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) ++ _, err := CheckDetachedSignature(kring, nil, readerFromHex(missingHashFunctionHex)) ++ if err == nil { ++ t.Fatal("Packet with missing hash type was correctly parsed") ++ } ++ if err != errors.ErrUnknownIssuer { ++ t.Fatalf("Unexpected class of error: %s", err) ++ } ++} ++ ++func TestReadingArmoredPrivateKey(t *testing.T) { ++ el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock)) ++ if err != nil { ++ t.Error(err) ++ } ++ if len(el) != 1 { ++ t.Errorf("got %d entities, wanted 1\n", len(el)) ++ } ++} ++ ++func TestReadingArmoredPublicKey(t *testing.T) { ++ el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey)) ++ if err != nil { ++ t.Error(err) ++ } ++ if len(el) != 1 { ++ t.Errorf("didn't get a valid entity") ++ } ++} ++ ++func TestNoArmoredData(t *testing.T) { ++ _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo")) ++ if _, ok := err.(errors.InvalidArgumentError); !ok { ++ t.Errorf("error was not an InvalidArgumentError: %s", err) ++ } ++} ++ ++func testReadMessageError(t *testing.T, messageHex string) { ++ buf, err := hex.DecodeString(messageHex) ++ if err != nil { ++ t.Errorf("hex.DecodeString(): %v", err) ++ } ++ ++ kr, err := ReadKeyRing(new(bytes.Buffer)) ++ if err != nil { ++ t.Errorf("ReadKeyring(): %v", err) ++ } ++ ++ _, err = ReadMessage(bytes.NewBuffer(buf), kr, ++ func([]Key, bool) ([]byte, error) { ++ return []byte("insecure"), nil ++ }, nil) ++ ++ if err == nil { ++ t.Errorf("ReadMessage(): Unexpected nil error") ++ } ++} ++ ++func TestIssue11503(t *testing.T) { ++ testReadMessageError(t, "8c040402000aa430aa8228b9248b01fc899a91197130303030") ++} ++ ++func TestIssue11504(t *testing.T) { ++ testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130") ++} ++ ++// TestSignatureV3Message tests the verification of V3 signature, generated ++// with a modern V4-style key. Some people have their clients set to generate ++// V3 signatures, so it's useful to be able to verify them. ++func TestSignatureV3Message(t *testing.T) { ++ sig, err := armor.Decode(strings.NewReader(signedMessageV3)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3)) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ md, err := ReadMessage(sig.Body, key, nil, nil) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ _, err = io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Error(err) ++ return ++ } ++ ++ // We'll see a sig error here after reading in the UnverifiedBody above, ++ // if there was one to see. ++ if err = md.SignatureError; err != nil { ++ t.Error(err) ++ return ++ } ++ ++ if md.SignatureV3 == nil { ++ t.Errorf("No available signature after checking signature") ++ return ++ } ++ if md.Signature != nil { ++ t.Errorf("Did not expect a signature V4 back") ++ return ++ } ++ return ++} ++ ++const testKey1KeyId = 0xA34D7E18C20C31BB ++const testKey3KeyId = 0x338934250CCC0360 ++const testKeyP256KeyId = 0xd44a2c495918513e ++ ++const signedInput = "Signed message\nline 2\nline 3\n" ++const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" ++ ++const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" ++ ++const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" ++ ++const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" ++ ++const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24" ++ ++const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" ++ ++const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817" ++ ++const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" ++ ++const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" ++ ++const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" ++ ++const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" ++ ++const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" ++ ++const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d" ++ ++const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" ++ ++const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6" ++ ++const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" ++ ++const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" ++ ++const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" ++ ++const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" ++ ++const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- ++Version: GnuPG v1.4.10 (GNU/Linux) ++ ++lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp ++idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn ++vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB ++AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X ++0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL ++IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk ++VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn ++gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 ++TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx ++q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz ++dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA ++CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 ++ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ ++eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid ++AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV ++bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK ++/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA ++A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX ++TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc ++lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 ++rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN ++oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 ++QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU ++nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC ++AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp ++BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad ++AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL ++VrM0m72/jnpKo04= ++=zNCn ++-----END PGP PRIVATE KEY BLOCK-----` ++ ++const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++Charset: UTF-8 ++ ++xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 ++sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk ++Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ ++AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD ++24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX +++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 ++B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX ++fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA ++FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 ++ex7En5r7rHR5xwX82Msc+Rq9dSyO ++=7MrZ ++-----END PGP PUBLIC KEY BLOCK-----` ++ ++const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` ++ ++const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` ++ ++const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` ++ ++const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` ++ ++const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- ++Comment: GPGTools - https://gpgtools.org ++ ++mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY ++BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z ++tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 ++JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV ++/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ ++K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H ++JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx ++YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 ++b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi ++UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M ++pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM ++AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz ++786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd ++EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB ++=RZia ++-----END PGP PUBLIC KEY BLOCK----- ++` ++ ++const signedMessageV3 = `-----BEGIN PGP MESSAGE----- ++Comment: GPGTools - https://gpgtools.org ++ ++owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP ++q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka ++uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka ++DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d ++iT57d/OhWwA= ++=hG7R ++-----END PGP MESSAGE----- ++` +diff --git a/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go +new file mode 100644 +index 00000000000000..f53244a1c7b538 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go +@@ -0,0 +1,279 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package s2k implements the various OpenPGP string-to-key transforms as ++// specified in RFC 4800 section 3.7.1. ++// ++// Deprecated: this package is unmaintained except for security fixes. New ++// applications should consider a more focused, modern alternative to OpenPGP ++// for their specific task. If you are required to interoperate with OpenPGP ++// systems and need a maintained package, consider a community fork. ++// See https://golang.org/issue/44226. ++package s2k // import "golang.org/x/crypto/openpgp/s2k" ++ ++import ( ++ "crypto" ++ "hash" ++ "io" ++ "strconv" ++ ++ "golang.org/x/crypto/openpgp/errors" ++) ++ ++// Config collects configuration parameters for s2k key-stretching ++// transformatioms. A nil *Config is valid and results in all default ++// values. Currently, Config is used only by the Serialize function in ++// this package. ++type Config struct { ++ // Hash is the default hash function to be used. If ++ // nil, SHA1 is used. ++ Hash crypto.Hash ++ // S2KCount is only used for symmetric encryption. It ++ // determines the strength of the passphrase stretching when ++ // the said passphrase is hashed to produce a key. S2KCount ++ // should be between 1024 and 65011712, inclusive. If Config ++ // is nil or S2KCount is 0, the value 65536 used. Not all ++ // values in the above range can be represented. S2KCount will ++ // be rounded up to the next representable value if it cannot ++ // be encoded exactly. When set, it is strongly encrouraged to ++ // use a value that is at least 65536. See RFC 4880 Section ++ // 3.7.1.3. ++ S2KCount int ++} ++ ++func (c *Config) hash() crypto.Hash { ++ if c == nil || uint(c.Hash) == 0 { ++ // SHA1 is the historical default in this package. ++ return crypto.SHA1 ++ } ++ ++ return c.Hash ++} ++ ++func (c *Config) encodedCount() uint8 { ++ if c == nil || c.S2KCount == 0 { ++ return 96 // The common case. Correspoding to 65536 ++ } ++ ++ i := c.S2KCount ++ switch { ++ // Behave like GPG. Should we make 65536 the lowest value used? ++ case i < 1024: ++ i = 1024 ++ case i > 65011712: ++ i = 65011712 ++ } ++ ++ return encodeCount(i) ++} ++ ++// encodeCount converts an iterative "count" in the range 1024 to ++// 65011712, inclusive, to an encoded count. The return value is the ++// octet that is actually stored in the GPG file. encodeCount panics ++// if i is not in the above range (encodedCount above takes care to ++// pass i in the correct range). See RFC 4880 Section 3.7.7.1. ++func encodeCount(i int) uint8 { ++ if i < 1024 || i > 65011712 { ++ panic("count arg i outside the required range") ++ } ++ ++ for encoded := 0; encoded < 256; encoded++ { ++ count := decodeCount(uint8(encoded)) ++ if count >= i { ++ return uint8(encoded) ++ } ++ } ++ ++ return 255 ++} ++ ++// decodeCount returns the s2k mode 3 iterative "count" corresponding to ++// the encoded octet c. ++func decodeCount(c uint8) int { ++ return (16 + int(c&15)) << (uint32(c>>4) + 6) ++} ++ ++// Simple writes to out the result of computing the Simple S2K function (RFC ++// 4880, section 3.7.1.1) using the given hash and input passphrase. ++func Simple(out []byte, h hash.Hash, in []byte) { ++ Salted(out, h, in, nil) ++} ++ ++var zero [1]byte ++ ++// Salted writes to out the result of computing the Salted S2K function (RFC ++// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. ++func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { ++ done := 0 ++ var digest []byte ++ ++ for i := 0; done < len(out); i++ { ++ h.Reset() ++ for j := 0; j < i; j++ { ++ h.Write(zero[:]) ++ } ++ h.Write(salt) ++ h.Write(in) ++ digest = h.Sum(digest[:0]) ++ n := copy(out[done:], digest) ++ done += n ++ } ++} ++ ++// Iterated writes to out the result of computing the Iterated and Salted S2K ++// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, ++// salt and iteration count. ++func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { ++ combined := make([]byte, len(in)+len(salt)) ++ copy(combined, salt) ++ copy(combined[len(salt):], in) ++ ++ if count < len(combined) { ++ count = len(combined) ++ } ++ ++ done := 0 ++ var digest []byte ++ for i := 0; done < len(out); i++ { ++ h.Reset() ++ for j := 0; j < i; j++ { ++ h.Write(zero[:]) ++ } ++ written := 0 ++ for written < count { ++ if written+len(combined) > count { ++ todo := count - written ++ h.Write(combined[:todo]) ++ written = count ++ } else { ++ h.Write(combined) ++ written += len(combined) ++ } ++ } ++ digest = h.Sum(digest[:0]) ++ n := copy(out[done:], digest) ++ done += n ++ } ++} ++ ++// Parse reads a binary specification for a string-to-key transformation from r ++// and returns a function which performs that transform. ++func Parse(r io.Reader) (f func(out, in []byte), err error) { ++ var buf [9]byte ++ ++ _, err = io.ReadFull(r, buf[:2]) ++ if err != nil { ++ return ++ } ++ ++ hash, ok := HashIdToHash(buf[1]) ++ if !ok { ++ return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) ++ } ++ if !hash.Available() { ++ return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) ++ } ++ h := hash.New() ++ ++ switch buf[0] { ++ case 0: ++ f := func(out, in []byte) { ++ Simple(out, h, in) ++ } ++ return f, nil ++ case 1: ++ _, err = io.ReadFull(r, buf[:8]) ++ if err != nil { ++ return ++ } ++ f := func(out, in []byte) { ++ Salted(out, h, in, buf[:8]) ++ } ++ return f, nil ++ case 3: ++ _, err = io.ReadFull(r, buf[:9]) ++ if err != nil { ++ return ++ } ++ count := decodeCount(buf[8]) ++ f := func(out, in []byte) { ++ Iterated(out, h, in, buf[:8], count) ++ } ++ return f, nil ++ } ++ ++ return nil, errors.UnsupportedError("S2K function") ++} ++ ++// Serialize salts and stretches the given passphrase and writes the ++// resulting key into key. It also serializes an S2K descriptor to ++// w. The key stretching can be configured with c, which may be ++// nil. In that case, sensible defaults will be used. ++func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { ++ var buf [11]byte ++ buf[0] = 3 /* iterated and salted */ ++ buf[1], _ = HashToHashId(c.hash()) ++ salt := buf[2:10] ++ if _, err := io.ReadFull(rand, salt); err != nil { ++ return err ++ } ++ encodedCount := c.encodedCount() ++ count := decodeCount(encodedCount) ++ buf[10] = encodedCount ++ if _, err := w.Write(buf[:]); err != nil { ++ return err ++ } ++ ++ Iterated(key, c.hash().New(), passphrase, salt, count) ++ return nil ++} ++ ++// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with ++// Go's crypto.Hash type. See RFC 4880, section 9.4. ++var hashToHashIdMapping = []struct { ++ id byte ++ hash crypto.Hash ++ name string ++}{ ++ {1, crypto.MD5, "MD5"}, ++ {2, crypto.SHA1, "SHA1"}, ++ {3, crypto.RIPEMD160, "RIPEMD160"}, ++ {8, crypto.SHA256, "SHA256"}, ++ {9, crypto.SHA384, "SHA384"}, ++ {10, crypto.SHA512, "SHA512"}, ++ {11, crypto.SHA224, "SHA224"}, ++} ++ ++// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP ++// hash id. ++func HashIdToHash(id byte) (h crypto.Hash, ok bool) { ++ for _, m := range hashToHashIdMapping { ++ if m.id == id { ++ return m.hash, true ++ } ++ } ++ return 0, false ++} ++ ++// HashIdToString returns the name of the hash function corresponding to the ++// given OpenPGP hash id. ++func HashIdToString(id byte) (name string, ok bool) { ++ for _, m := range hashToHashIdMapping { ++ if m.id == id { ++ return m.name, true ++ } ++ } ++ ++ return "", false ++} ++ ++// HashToHashId returns an OpenPGP hash id which corresponds the given Hash. ++func HashToHashId(h crypto.Hash) (id byte, ok bool) { ++ for _, m := range hashToHashIdMapping { ++ if m.hash == h { ++ return m.id, true ++ } ++ } ++ return 0, false ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go +new file mode 100644 +index 00000000000000..183d26056b11e4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go +@@ -0,0 +1,137 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package s2k ++ ++import ( ++ "bytes" ++ "crypto" ++ _ "crypto/md5" ++ "crypto/rand" ++ "crypto/sha1" ++ _ "crypto/sha256" ++ _ "crypto/sha512" ++ "encoding/hex" ++ "testing" ++ ++ _ "golang.org/x/crypto/ripemd160" ++) ++ ++var saltedTests = []struct { ++ in, out string ++}{ ++ {"hello", "10295ac1"}, ++ {"world", "ac587a5e"}, ++ {"foo", "4dda8077"}, ++ {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"}, ++ {"x", "f1d3f289"}, ++ {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"}, ++} ++ ++func TestSalted(t *testing.T) { ++ h := sha1.New() ++ salt := [4]byte{1, 2, 3, 4} ++ ++ for i, test := range saltedTests { ++ expected, _ := hex.DecodeString(test.out) ++ out := make([]byte, len(expected)) ++ Salted(out, h, []byte(test.in), salt[:]) ++ if !bytes.Equal(expected, out) { ++ t.Errorf("#%d, got: %x want: %x", i, out, expected) ++ } ++ } ++} ++ ++var iteratedTests = []struct { ++ in, out string ++}{ ++ {"hello", "83126105"}, ++ {"world", "6fa317f9"}, ++ {"foo", "8fbc35b9"}, ++ {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"}, ++ {"x", "5a684dfe"}, ++ {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"}, ++} ++ ++func TestIterated(t *testing.T) { ++ h := sha1.New() ++ salt := [4]byte{4, 3, 2, 1} ++ ++ for i, test := range iteratedTests { ++ expected, _ := hex.DecodeString(test.out) ++ out := make([]byte, len(expected)) ++ Iterated(out, h, []byte(test.in), salt[:], 31) ++ if !bytes.Equal(expected, out) { ++ t.Errorf("#%d, got: %x want: %x", i, out, expected) ++ } ++ } ++} ++ ++var parseTests = []struct { ++ spec, in, out string ++}{ ++ /* Simple with SHA1 */ ++ {"0002", "hello", "aaf4c61d"}, ++ /* Salted with SHA1 */ ++ {"01020102030405060708", "hello", "f4f7d67e"}, ++ /* Iterated with SHA1 */ ++ {"03020102030405060708f1", "hello", "f2a57b7c"}, ++} ++ ++func TestParse(t *testing.T) { ++ for i, test := range parseTests { ++ spec, _ := hex.DecodeString(test.spec) ++ buf := bytes.NewBuffer(spec) ++ f, err := Parse(buf) ++ if err != nil { ++ t.Errorf("%d: Parse returned error: %s", i, err) ++ continue ++ } ++ ++ expected, _ := hex.DecodeString(test.out) ++ out := make([]byte, len(expected)) ++ f(out, []byte(test.in)) ++ if !bytes.Equal(out, expected) { ++ t.Errorf("%d: output got: %x want: %x", i, out, expected) ++ } ++ if testing.Short() { ++ break ++ } ++ } ++} ++ ++func TestSerialize(t *testing.T) { ++ hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160, ++ crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224} ++ testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712} ++ for _, h := range hashes { ++ for _, c := range testCounts { ++ testSerializeConfig(t, &Config{Hash: h, S2KCount: c}) ++ } ++ } ++} ++ ++func testSerializeConfig(t *testing.T, c *Config) { ++ t.Logf("Running testSerializeConfig() with config: %+v", c) ++ ++ buf := bytes.NewBuffer(nil) ++ key := make([]byte, 16) ++ passphrase := []byte("testing") ++ err := Serialize(buf, key, rand.Reader, passphrase, c) ++ if err != nil { ++ t.Errorf("failed to serialize: %s", err) ++ return ++ } ++ ++ f, err := Parse(buf) ++ if err != nil { ++ t.Errorf("failed to reparse: %s", err) ++ return ++ } ++ key2 := make([]byte, len(key)) ++ f(key2, passphrase) ++ if !bytes.Equal(key2, key) { ++ t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/write.go b/ms_mod/golang.org/x/crypto/openpgp/write.go +new file mode 100644 +index 00000000000000..b89d48b81d7370 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/write.go +@@ -0,0 +1,418 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package openpgp ++ ++import ( ++ "crypto" ++ "hash" ++ "io" ++ "strconv" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/armor" ++ "golang.org/x/crypto/openpgp/errors" ++ "golang.org/x/crypto/openpgp/packet" ++ "golang.org/x/crypto/openpgp/s2k" ++) ++ ++// DetachSign signs message with the private key from signer (which must ++// already have been decrypted) and writes the signature to w. ++// If config is nil, sensible defaults will be used. ++func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { ++ return detachSign(w, signer, message, packet.SigTypeBinary, config) ++} ++ ++// ArmoredDetachSign signs message with the private key from signer (which ++// must already have been decrypted) and writes an armored signature to w. ++// If config is nil, sensible defaults will be used. ++func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { ++ return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) ++} ++ ++// DetachSignText signs message (after canonicalising the line endings) with ++// the private key from signer (which must already have been decrypted) and ++// writes the signature to w. ++// If config is nil, sensible defaults will be used. ++func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { ++ return detachSign(w, signer, message, packet.SigTypeText, config) ++} ++ ++// ArmoredDetachSignText signs message (after canonicalising the line endings) ++// with the private key from signer (which must already have been decrypted) ++// and writes an armored signature to w. ++// If config is nil, sensible defaults will be used. ++func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { ++ return armoredDetachSign(w, signer, message, packet.SigTypeText, config) ++} ++ ++func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { ++ out, err := armor.Encode(w, SignatureType, nil) ++ if err != nil { ++ return ++ } ++ err = detachSign(out, signer, message, sigType, config) ++ if err != nil { ++ return ++ } ++ return out.Close() ++} ++ ++func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { ++ if signer.PrivateKey == nil { ++ return errors.InvalidArgumentError("signing key doesn't have a private key") ++ } ++ if signer.PrivateKey.Encrypted { ++ return errors.InvalidArgumentError("signing key is encrypted") ++ } ++ ++ sig := new(packet.Signature) ++ sig.SigType = sigType ++ sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo ++ sig.Hash = config.Hash() ++ sig.CreationTime = config.Now() ++ sig.IssuerKeyId = &signer.PrivateKey.KeyId ++ ++ h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) ++ if err != nil { ++ return ++ } ++ io.Copy(wrappedHash, message) ++ ++ err = sig.Sign(h, signer.PrivateKey, config) ++ if err != nil { ++ return ++ } ++ ++ return sig.Serialize(w) ++} ++ ++// FileHints contains metadata about encrypted files. This metadata is, itself, ++// encrypted. ++type FileHints struct { ++ // IsBinary can be set to hint that the contents are binary data. ++ IsBinary bool ++ // FileName hints at the name of the file that should be written. It's ++ // truncated to 255 bytes if longer. It may be empty to suggest that the ++ // file should not be written to disk. It may be equal to "_CONSOLE" to ++ // suggest the data should not be written to disk. ++ FileName string ++ // ModTime contains the modification time of the file, or the zero time if not applicable. ++ ModTime time.Time ++} ++ ++// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. ++// The resulting WriteCloser must be closed after the contents of the file have ++// been written. ++// If config is nil, sensible defaults will be used. ++func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { ++ if hints == nil { ++ hints = &FileHints{} ++ } ++ ++ key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) ++ if err != nil { ++ return ++ } ++ w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) ++ if err != nil { ++ return ++ } ++ ++ literaldata := w ++ if algo := config.Compression(); algo != packet.CompressionNone { ++ var compConfig *packet.CompressionConfig ++ if config != nil { ++ compConfig = config.CompressionConfig ++ } ++ literaldata, err = packet.SerializeCompressed(w, algo, compConfig) ++ if err != nil { ++ return ++ } ++ } ++ ++ var epochSeconds uint32 ++ if !hints.ModTime.IsZero() { ++ epochSeconds = uint32(hints.ModTime.Unix()) ++ } ++ return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) ++} ++ ++// intersectPreferences mutates and returns a prefix of a that contains only ++// the values in the intersection of a and b. The order of a is preserved. ++func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { ++ var j int ++ for _, v := range a { ++ for _, v2 := range b { ++ if v == v2 { ++ a[j] = v ++ j++ ++ break ++ } ++ } ++ } ++ ++ return a[:j] ++} ++ ++func hashToHashId(h crypto.Hash) uint8 { ++ v, ok := s2k.HashToHashId(h) ++ if !ok { ++ panic("tried to convert unknown hash") ++ } ++ return v ++} ++ ++// writeAndSign writes the data as a payload package and, optionally, signs ++// it. hints contains optional information, that is also encrypted, ++// that aids the recipients in processing the message. The resulting ++// WriteCloser must be closed after the contents of the file have been ++// written. If config is nil, sensible defaults will be used. ++func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { ++ var signer *packet.PrivateKey ++ if signed != nil { ++ signKey, ok := signed.signingKey(config.Now()) ++ if !ok { ++ return nil, errors.InvalidArgumentError("no valid signing keys") ++ } ++ signer = signKey.PrivateKey ++ if signer == nil { ++ return nil, errors.InvalidArgumentError("no private key in signing key") ++ } ++ if signer.Encrypted { ++ return nil, errors.InvalidArgumentError("signing key must be decrypted") ++ } ++ } ++ ++ var hash crypto.Hash ++ for _, hashId := range candidateHashes { ++ if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { ++ hash = h ++ break ++ } ++ } ++ ++ // If the hash specified by config is a candidate, we'll use that. ++ if configuredHash := config.Hash(); configuredHash.Available() { ++ for _, hashId := range candidateHashes { ++ if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { ++ hash = h ++ break ++ } ++ } ++ } ++ ++ if hash == 0 { ++ hashId := candidateHashes[0] ++ name, ok := s2k.HashIdToString(hashId) ++ if !ok { ++ name = "#" + strconv.Itoa(int(hashId)) ++ } ++ return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") ++ } ++ ++ if signer != nil { ++ ops := &packet.OnePassSignature{ ++ SigType: packet.SigTypeBinary, ++ Hash: hash, ++ PubKeyAlgo: signer.PubKeyAlgo, ++ KeyId: signer.KeyId, ++ IsLast: true, ++ } ++ if err := ops.Serialize(payload); err != nil { ++ return nil, err ++ } ++ } ++ ++ if hints == nil { ++ hints = &FileHints{} ++ } ++ ++ w := payload ++ if signer != nil { ++ // If we need to write a signature packet after the literal ++ // data then we need to stop literalData from closing ++ // encryptedData. ++ w = noOpCloser{w} ++ ++ } ++ var epochSeconds uint32 ++ if !hints.ModTime.IsZero() { ++ epochSeconds = uint32(hints.ModTime.Unix()) ++ } ++ literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) ++ if err != nil { ++ return nil, err ++ } ++ ++ if signer != nil { ++ return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil ++ } ++ return literalData, nil ++} ++ ++// Encrypt encrypts a message to a number of recipients and, optionally, signs ++// it. hints contains optional information, that is also encrypted, that aids ++// the recipients in processing the message. The resulting WriteCloser must ++// be closed after the contents of the file have been written. ++// If config is nil, sensible defaults will be used. ++func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { ++ if len(to) == 0 { ++ return nil, errors.InvalidArgumentError("no encryption recipient provided") ++ } ++ ++ // These are the possible ciphers that we'll use for the message. ++ candidateCiphers := []uint8{ ++ uint8(packet.CipherAES128), ++ uint8(packet.CipherAES256), ++ uint8(packet.CipherCAST5), ++ } ++ // These are the possible hash functions that we'll use for the signature. ++ candidateHashes := []uint8{ ++ hashToHashId(crypto.SHA256), ++ hashToHashId(crypto.SHA384), ++ hashToHashId(crypto.SHA512), ++ hashToHashId(crypto.SHA1), ++ hashToHashId(crypto.RIPEMD160), ++ } ++ // In the event that a recipient doesn't specify any supported ciphers ++ // or hash functions, these are the ones that we assume that every ++ // implementation supports. ++ defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] ++ defaultHashes := candidateHashes[len(candidateHashes)-1:] ++ ++ encryptKeys := make([]Key, len(to)) ++ for i := range to { ++ var ok bool ++ encryptKeys[i], ok = to[i].encryptionKey(config.Now()) ++ if !ok { ++ return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") ++ } ++ ++ sig := to[i].primaryIdentity().SelfSignature ++ ++ preferredSymmetric := sig.PreferredSymmetric ++ if len(preferredSymmetric) == 0 { ++ preferredSymmetric = defaultCiphers ++ } ++ preferredHashes := sig.PreferredHash ++ if len(preferredHashes) == 0 { ++ preferredHashes = defaultHashes ++ } ++ candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) ++ candidateHashes = intersectPreferences(candidateHashes, preferredHashes) ++ } ++ ++ if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { ++ return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") ++ } ++ ++ cipher := packet.CipherFunction(candidateCiphers[0]) ++ // If the cipher specified by config is a candidate, we'll use that. ++ configuredCipher := config.Cipher() ++ for _, c := range candidateCiphers { ++ cipherFunc := packet.CipherFunction(c) ++ if cipherFunc == configuredCipher { ++ cipher = cipherFunc ++ break ++ } ++ } ++ ++ symKey := make([]byte, cipher.KeySize()) ++ if _, err := io.ReadFull(config.Random(), symKey); err != nil { ++ return nil, err ++ } ++ ++ for _, key := range encryptKeys { ++ if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { ++ return nil, err ++ } ++ } ++ ++ payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) ++ if err != nil { ++ return ++ } ++ ++ return writeAndSign(payload, candidateHashes, signed, hints, config) ++} ++ ++// Sign signs a message. The resulting WriteCloser must be closed after the ++// contents of the file have been written. hints contains optional information ++// that aids the recipients in processing the message. ++// If config is nil, sensible defaults will be used. ++func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { ++ if signed == nil { ++ return nil, errors.InvalidArgumentError("no signer provided") ++ } ++ ++ // These are the possible hash functions that we'll use for the signature. ++ candidateHashes := []uint8{ ++ hashToHashId(crypto.SHA256), ++ hashToHashId(crypto.SHA384), ++ hashToHashId(crypto.SHA512), ++ hashToHashId(crypto.SHA1), ++ hashToHashId(crypto.RIPEMD160), ++ } ++ defaultHashes := candidateHashes[len(candidateHashes)-1:] ++ preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash ++ if len(preferredHashes) == 0 { ++ preferredHashes = defaultHashes ++ } ++ candidateHashes = intersectPreferences(candidateHashes, preferredHashes) ++ return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) ++} ++ ++// signatureWriter hashes the contents of a message while passing it along to ++// literalData. When closed, it closes literalData, writes a signature packet ++// to encryptedData and then also closes encryptedData. ++type signatureWriter struct { ++ encryptedData io.WriteCloser ++ literalData io.WriteCloser ++ hashType crypto.Hash ++ h hash.Hash ++ signer *packet.PrivateKey ++ config *packet.Config ++} ++ ++func (s signatureWriter) Write(data []byte) (int, error) { ++ s.h.Write(data) ++ return s.literalData.Write(data) ++} ++ ++func (s signatureWriter) Close() error { ++ sig := &packet.Signature{ ++ SigType: packet.SigTypeBinary, ++ PubKeyAlgo: s.signer.PubKeyAlgo, ++ Hash: s.hashType, ++ CreationTime: s.config.Now(), ++ IssuerKeyId: &s.signer.KeyId, ++ } ++ ++ if err := sig.Sign(s.h, s.signer, s.config); err != nil { ++ return err ++ } ++ if err := s.literalData.Close(); err != nil { ++ return err ++ } ++ if err := sig.Serialize(s.encryptedData); err != nil { ++ return err ++ } ++ return s.encryptedData.Close() ++} ++ ++// noOpCloser is like an io.NopCloser, but for an io.Writer. ++// TODO: we have two of these in OpenPGP packages alone. This probably needs ++// to be promoted somewhere more common. ++type noOpCloser struct { ++ w io.Writer ++} ++ ++func (c noOpCloser) Write(data []byte) (n int, err error) { ++ return c.w.Write(data) ++} ++ ++func (c noOpCloser) Close() error { ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/openpgp/write_test.go b/ms_mod/golang.org/x/crypto/openpgp/write_test.go +new file mode 100644 +index 00000000000000..8b686789ee5f34 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/openpgp/write_test.go +@@ -0,0 +1,361 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package openpgp ++ ++import ( ++ "bytes" ++ "io" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/openpgp/packet" ++) ++ ++func TestSignDetached(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) ++ out := bytes.NewBuffer(nil) ++ message := bytes.NewBufferString(signedInput) ++ err := DetachSign(out, kring[0], message, nil) ++ if err != nil { ++ t.Error(err) ++ } ++ ++ testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) ++} ++ ++func TestSignTextDetached(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) ++ out := bytes.NewBuffer(nil) ++ message := bytes.NewBufferString(signedInput) ++ err := DetachSignText(out, kring[0], message, nil) ++ if err != nil { ++ t.Error(err) ++ } ++ ++ testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) ++} ++ ++func TestSignDetachedDSA(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex)) ++ out := bytes.NewBuffer(nil) ++ message := bytes.NewBufferString(signedInput) ++ err := DetachSign(out, kring[0], message, nil) ++ if err != nil { ++ t.Error(err) ++ } ++ ++ testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId) ++} ++ ++func TestSignDetachedP256(t *testing.T) { ++ kring, _ := ReadKeyRing(readerFromHex(p256TestKeyPrivateHex)) ++ kring[0].PrivateKey.Decrypt([]byte("passphrase")) ++ ++ out := bytes.NewBuffer(nil) ++ message := bytes.NewBufferString(signedInput) ++ err := DetachSign(out, kring[0], message, nil) ++ if err != nil { ++ t.Error(err) ++ } ++ ++ testDetachedSignature(t, kring, out, signedInput, "check", testKeyP256KeyId) ++} ++ ++func TestNewEntity(t *testing.T) { ++ if testing.Short() { ++ return ++ } ++ ++ // Check bit-length with no config. ++ e, err := NewEntity("Test User", "test", "test@example.com", nil) ++ if err != nil { ++ t.Errorf("failed to create entity: %s", err) ++ return ++ } ++ bl, err := e.PrimaryKey.BitLength() ++ if err != nil { ++ t.Errorf("failed to find bit length: %s", err) ++ } ++ if int(bl) != defaultRSAKeyBits { ++ t.Errorf("BitLength %v, expected %v", int(bl), defaultRSAKeyBits) ++ } ++ ++ // Check bit-length with a config. ++ cfg := &packet.Config{RSABits: 1024} ++ e, err = NewEntity("Test User", "test", "test@example.com", cfg) ++ if err != nil { ++ t.Errorf("failed to create entity: %s", err) ++ return ++ } ++ bl, err = e.PrimaryKey.BitLength() ++ if err != nil { ++ t.Errorf("failed to find bit length: %s", err) ++ } ++ if int(bl) != cfg.RSABits { ++ t.Errorf("BitLength %v, expected %v", bl, cfg.RSABits) ++ } ++ ++ w := bytes.NewBuffer(nil) ++ if err := e.SerializePrivate(w, nil); err != nil { ++ t.Errorf("failed to serialize entity: %s", err) ++ return ++ } ++ serialized := w.Bytes() ++ ++ el, err := ReadKeyRing(w) ++ if err != nil { ++ t.Errorf("failed to reparse entity: %s", err) ++ return ++ } ++ ++ if len(el) != 1 { ++ t.Errorf("wrong number of entities found, got %d, want 1", len(el)) ++ } ++ ++ w = bytes.NewBuffer(nil) ++ if err := e.SerializePrivate(w, nil); err != nil { ++ t.Errorf("failed to serialize entity second time: %s", err) ++ return ++ } ++ ++ if !bytes.Equal(w.Bytes(), serialized) { ++ t.Errorf("results differed") ++ } ++} ++ ++func TestSymmetricEncryption(t *testing.T) { ++ buf := new(bytes.Buffer) ++ plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil) ++ if err != nil { ++ t.Errorf("error writing headers: %s", err) ++ return ++ } ++ message := []byte("hello world\n") ++ _, err = plaintext.Write(message) ++ if err != nil { ++ t.Errorf("error writing to plaintext writer: %s", err) ++ } ++ err = plaintext.Close() ++ if err != nil { ++ t.Errorf("error closing plaintext writer: %s", err) ++ } ++ ++ md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) { ++ return []byte("testing"), nil ++ }, nil) ++ if err != nil { ++ t.Errorf("error rereading message: %s", err) ++ } ++ messageBuf := bytes.NewBuffer(nil) ++ _, err = io.Copy(messageBuf, md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("error rereading message: %s", err) ++ } ++ if !bytes.Equal(message, messageBuf.Bytes()) { ++ t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message) ++ } ++} ++ ++var testEncryptionTests = []struct { ++ keyRingHex string ++ isSigned bool ++}{ ++ { ++ testKeys1And2PrivateHex, ++ false, ++ }, ++ { ++ testKeys1And2PrivateHex, ++ true, ++ }, ++ { ++ dsaElGamalTestKeysHex, ++ false, ++ }, ++ { ++ dsaElGamalTestKeysHex, ++ true, ++ }, ++} ++ ++func TestEncryption(t *testing.T) { ++ for i, test := range testEncryptionTests { ++ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) ++ ++ passphrase := []byte("passphrase") ++ for _, entity := range kring { ++ if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { ++ err := entity.PrivateKey.Decrypt(passphrase) ++ if err != nil { ++ t.Errorf("#%d: failed to decrypt key", i) ++ } ++ } ++ for _, subkey := range entity.Subkeys { ++ if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { ++ err := subkey.PrivateKey.Decrypt(passphrase) ++ if err != nil { ++ t.Errorf("#%d: failed to decrypt subkey", i) ++ } ++ } ++ } ++ } ++ ++ var signed *Entity ++ if test.isSigned { ++ signed = kring[0] ++ } ++ ++ buf := new(bytes.Buffer) ++ w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil) ++ if err != nil { ++ t.Errorf("#%d: error in Encrypt: %s", i, err) ++ continue ++ } ++ ++ const message = "testing" ++ _, err = w.Write([]byte(message)) ++ if err != nil { ++ t.Errorf("#%d: error writing plaintext: %s", i, err) ++ continue ++ } ++ err = w.Close() ++ if err != nil { ++ t.Errorf("#%d: error closing WriteCloser: %s", i, err) ++ continue ++ } ++ ++ md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) ++ if err != nil { ++ t.Errorf("#%d: error reading message: %s", i, err) ++ continue ++ } ++ ++ testTime, _ := time.Parse("2006-01-02", "2013-07-01") ++ if test.isSigned { ++ signKey, _ := kring[0].signingKey(testTime) ++ expectedKeyId := signKey.PublicKey.KeyId ++ if md.SignedByKeyId != expectedKeyId { ++ t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId) ++ } ++ if md.SignedBy == nil { ++ t.Errorf("#%d: failed to find the signing Entity", i) ++ } ++ } ++ ++ plaintext, err := io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("#%d: error reading encrypted contents: %s", i, err) ++ continue ++ } ++ ++ encryptKey, _ := kring[0].encryptionKey(testTime) ++ expectedKeyId := encryptKey.PublicKey.KeyId ++ if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId { ++ t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds) ++ } ++ ++ if string(plaintext) != message { ++ t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message) ++ } ++ ++ if test.isSigned { ++ if md.SignatureError != nil { ++ t.Errorf("#%d: signature error: %s", i, md.SignatureError) ++ } ++ if md.Signature == nil { ++ t.Error("signature missing") ++ } ++ } ++ } ++} ++ ++var testSigningTests = []struct { ++ keyRingHex string ++}{ ++ { ++ testKeys1And2PrivateHex, ++ }, ++ { ++ dsaElGamalTestKeysHex, ++ }, ++} ++ ++func TestSigning(t *testing.T) { ++ for i, test := range testSigningTests { ++ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) ++ ++ passphrase := []byte("passphrase") ++ for _, entity := range kring { ++ if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { ++ err := entity.PrivateKey.Decrypt(passphrase) ++ if err != nil { ++ t.Errorf("#%d: failed to decrypt key", i) ++ } ++ } ++ for _, subkey := range entity.Subkeys { ++ if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { ++ err := subkey.PrivateKey.Decrypt(passphrase) ++ if err != nil { ++ t.Errorf("#%d: failed to decrypt subkey", i) ++ } ++ } ++ } ++ } ++ ++ signed := kring[0] ++ ++ buf := new(bytes.Buffer) ++ w, err := Sign(buf, signed, nil /* no hints */, nil) ++ if err != nil { ++ t.Errorf("#%d: error in Sign: %s", i, err) ++ continue ++ } ++ ++ const message = "testing" ++ _, err = w.Write([]byte(message)) ++ if err != nil { ++ t.Errorf("#%d: error writing plaintext: %s", i, err) ++ continue ++ } ++ err = w.Close() ++ if err != nil { ++ t.Errorf("#%d: error closing WriteCloser: %s", i, err) ++ continue ++ } ++ ++ md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) ++ if err != nil { ++ t.Errorf("#%d: error reading message: %s", i, err) ++ continue ++ } ++ ++ testTime, _ := time.Parse("2006-01-02", "2013-07-01") ++ signKey, _ := kring[0].signingKey(testTime) ++ expectedKeyId := signKey.PublicKey.KeyId ++ if md.SignedByKeyId != expectedKeyId { ++ t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId) ++ } ++ if md.SignedBy == nil { ++ t.Errorf("#%d: failed to find the signing Entity", i) ++ } ++ ++ plaintext, err := io.ReadAll(md.UnverifiedBody) ++ if err != nil { ++ t.Errorf("#%d: error reading contents: %v", i, err) ++ continue ++ } ++ ++ if string(plaintext) != message { ++ t.Errorf("#%d: got: %q, want: %q", i, plaintext, message) ++ } ++ ++ if md.SignatureError != nil { ++ t.Errorf("#%d: signature error: %q", i, md.SignatureError) ++ } ++ if md.Signature == nil { ++ t.Error("signature missing") ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c b/ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c +new file mode 100644 +index 00000000000000..b3ca072d480924 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c +@@ -0,0 +1,197 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// This code can be compiled and used to test the otr package against libotr. ++// See otr_test.go. ++ ++// +build ignore ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++static int g_session_established = 0; ++ ++OtrlPolicy policy(void *opdata, ConnContext *context) { ++ return OTRL_POLICY_ALWAYS; ++} ++ ++int is_logged_in(void *opdata, const char *accountname, const char *protocol, ++ const char *recipient) { ++ return 1; ++} ++ ++void inject_message(void *opdata, const char *accountname, const char *protocol, ++ const char *recipient, const char *message) { ++ printf("%s\n", message); ++ fflush(stdout); ++ fprintf(stderr, "libotr helper sent: %s\n", message); ++} ++ ++void update_context_list(void *opdata) {} ++ ++void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, ++ const char *protocol, const char *username, ++ unsigned char fingerprint[20]) { ++ fprintf(stderr, "NEW FINGERPRINT\n"); ++ g_session_established = 1; ++} ++ ++void write_fingerprints(void *opdata) {} ++ ++void gone_secure(void *opdata, ConnContext *context) {} ++ ++void gone_insecure(void *opdata, ConnContext *context) {} ++ ++void still_secure(void *opdata, ConnContext *context, int is_reply) {} ++ ++int max_message_size(void *opdata, ConnContext *context) { return 99999; } ++ ++const char *account_name(void *opdata, const char *account, ++ const char *protocol) { ++ return "ACCOUNT"; ++} ++ ++void account_name_free(void *opdata, const char *account_name) {} ++ ++const char *error_message(void *opdata, ConnContext *context, ++ OtrlErrorCode err_code) { ++ return "ERR"; ++} ++ ++void error_message_free(void *opdata, const char *msg) {} ++ ++void resent_msg_prefix_free(void *opdata, const char *prefix) {} ++ ++void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ++ ConnContext *context, unsigned short progress_event, ++ char *question) {} ++ ++void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ++ ConnContext *context, const char *message, ++ gcry_error_t err) { ++ fprintf(stderr, "msg event: %d %s\n", msg_event, message); ++} ++ ++OtrlMessageAppOps uiops = { ++ policy, ++ NULL, ++ is_logged_in, ++ inject_message, ++ update_context_list, ++ new_fingerprint, ++ write_fingerprints, ++ gone_secure, ++ gone_insecure, ++ still_secure, ++ max_message_size, ++ account_name, ++ account_name_free, ++ NULL, /* received_symkey */ ++ error_message, ++ error_message_free, ++ NULL, /* resent_msg_prefix */ ++ resent_msg_prefix_free, ++ handle_smp_event, ++ handle_msg_event, ++ NULL /* create_instag */, ++ NULL /* convert_msg */, ++ NULL /* convert_free */, ++ NULL /* timer_control */, ++}; ++ ++static const char kPrivateKeyData[] = ++ "(privkeys (account (name \"account\") (protocol proto) (private-key (dsa " ++ "(p " ++ "#00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F" ++ "30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E" ++ "5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB" ++ "8C031D3561FECEE72EBB4A090D450A9B7A857#) (q " ++ "#00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g " ++ "#535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F" ++ "1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F" ++ "6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57" ++ "597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y " ++ "#0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF" ++ "2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93" ++ "454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A" ++ "3C0FF501E3DC673B76D7BABF349009B6ECF#) (x " ++ "#14D0345A3562C480A039E3C72764F72D79043216#)))))\n"; ++ ++int main() { ++ OTRL_INIT; ++ ++ // We have to write the private key information to a file because the libotr ++ // API demands a filename to read from. ++ const char *tmpdir = "/tmp"; ++ if (getenv("TMP")) { ++ tmpdir = getenv("TMP"); ++ } ++ ++ char private_key_file[256]; ++ snprintf(private_key_file, sizeof(private_key_file), ++ "%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir); ++ int fd = mkstemp(private_key_file); ++ if (fd == -1) { ++ perror("creating temp file"); ++ } ++ write(fd, kPrivateKeyData, sizeof(kPrivateKeyData) - 1); ++ close(fd); ++ ++ OtrlUserState userstate = otrl_userstate_create(); ++ otrl_privkey_read(userstate, private_key_file); ++ unlink(private_key_file); ++ ++ fprintf(stderr, "libotr helper started\n"); ++ ++ char buf[4096]; ++ ++ for (;;) { ++ char *message = fgets(buf, sizeof(buf), stdin); ++ if (strlen(message) == 0) { ++ break; ++ } ++ message[strlen(message) - 1] = 0; ++ fprintf(stderr, "libotr helper got: %s\n", message); ++ ++ char *newmessage = NULL; ++ OtrlTLV *tlvs; ++ int ignore_message = otrl_message_receiving( ++ userstate, &uiops, NULL, "account", "proto", "peer", message, ++ &newmessage, &tlvs, NULL, NULL, NULL); ++ if (tlvs) { ++ otrl_tlv_free(tlvs); ++ } ++ ++ if (newmessage != NULL) { ++ fprintf(stderr, "libotr got: %s\n", newmessage); ++ otrl_message_free(newmessage); ++ ++ gcry_error_t err; ++ char *newmessage = NULL; ++ ++ err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto", ++ "peer", 0, "test message", NULL, &newmessage, ++ OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL); ++ if (newmessage == NULL) { ++ fprintf(stderr, "libotr didn't encrypt message\n"); ++ return 1; ++ } ++ write(1, newmessage, strlen(newmessage)); ++ write(1, "\n", 1); ++ fprintf(stderr, "libotr sent: %s\n", newmessage); ++ otrl_message_free(newmessage); ++ ++ g_session_established = 0; ++ write(1, "?OTRv2?\n", 8); ++ fprintf(stderr, "libotr sent: ?OTRv2\n"); ++ } ++ } ++ ++ return 0; ++} +diff --git a/ms_mod/golang.org/x/crypto/otr/otr.go b/ms_mod/golang.org/x/crypto/otr/otr.go +new file mode 100644 +index 00000000000000..29121e9bb653ac +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/otr/otr.go +@@ -0,0 +1,1419 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package otr implements the Off The Record protocol as specified in ++// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html ++// ++// The version of OTR implemented by this package has been deprecated ++// (https://bugs.otr.im/lib/libotr/issues/140). An implementation of OTRv3 is ++// available at https://github.com/coyim/otr3. ++package otr // import "golang.org/x/crypto/otr" ++ ++import ( ++ "bytes" ++ "crypto/aes" ++ "crypto/cipher" ++ "crypto/dsa" ++ "crypto/hmac" ++ "crypto/rand" ++ "crypto/sha1" ++ "crypto/sha256" ++ "crypto/subtle" ++ "encoding/base64" ++ "encoding/hex" ++ "errors" ++ "hash" ++ "io" ++ "math/big" ++ "strconv" ++) ++ ++// SecurityChange describes a change in the security state of a Conversation. ++type SecurityChange int ++ ++const ( ++ NoChange SecurityChange = iota ++ // NewKeys indicates that a key exchange has completed. This occurs ++ // when a conversation first becomes encrypted, and when the keys are ++ // renegotiated within an encrypted conversation. ++ NewKeys ++ // SMPSecretNeeded indicates that the peer has started an ++ // authentication and that we need to supply a secret. Call SMPQuestion ++ // to get the optional, human readable challenge and then Authenticate ++ // to supply the matching secret. ++ SMPSecretNeeded ++ // SMPComplete indicates that an authentication completed. The identity ++ // of the peer has now been confirmed. ++ SMPComplete ++ // SMPFailed indicates that an authentication failed. ++ SMPFailed ++ // ConversationEnded indicates that the peer ended the secure ++ // conversation. ++ ConversationEnded ++) ++ ++// QueryMessage can be sent to a peer to start an OTR conversation. ++var QueryMessage = "?OTRv2?" ++ ++// ErrorPrefix can be used to make an OTR error by appending an error message ++// to it. ++var ErrorPrefix = "?OTR Error:" ++ ++var ( ++ fragmentPartSeparator = []byte(",") ++ fragmentPrefix = []byte("?OTR,") ++ msgPrefix = []byte("?OTR:") ++ queryMarker = []byte("?OTR") ++) ++ ++// isQuery attempts to parse an OTR query from msg and returns the greatest ++// common version, or 0 if msg is not an OTR query. ++func isQuery(msg []byte) (greatestCommonVersion int) { ++ pos := bytes.Index(msg, queryMarker) ++ if pos == -1 { ++ return 0 ++ } ++ for i, c := range msg[pos+len(queryMarker):] { ++ if i == 0 { ++ if c == '?' { ++ // Indicates support for version 1, but we don't ++ // implement that. ++ continue ++ } ++ ++ if c != 'v' { ++ // Invalid message ++ return 0 ++ } ++ ++ continue ++ } ++ ++ if c == '?' { ++ // End of message ++ return ++ } ++ ++ if c == ' ' || c == '\t' { ++ // Probably an invalid message ++ return 0 ++ } ++ ++ if c == '2' { ++ greatestCommonVersion = 2 ++ } ++ } ++ ++ return 0 ++} ++ ++const ( ++ statePlaintext = iota ++ stateEncrypted ++ stateFinished ++) ++ ++const ( ++ authStateNone = iota ++ authStateAwaitingDHKey ++ authStateAwaitingRevealSig ++ authStateAwaitingSig ++) ++ ++const ( ++ msgTypeDHCommit = 2 ++ msgTypeData = 3 ++ msgTypeDHKey = 10 ++ msgTypeRevealSig = 17 ++ msgTypeSig = 18 ++) ++ ++const ( ++ // If the requested fragment size is less than this, it will be ignored. ++ minFragmentSize = 18 ++ // Messages are padded to a multiple of this number of bytes. ++ paddingGranularity = 256 ++ // The number of bytes in a Diffie-Hellman private value (320-bits). ++ dhPrivateBytes = 40 ++ // The number of bytes needed to represent an element of the DSA ++ // subgroup (160-bits). ++ dsaSubgroupBytes = 20 ++ // The number of bytes of the MAC that are sent on the wire (160-bits). ++ macPrefixBytes = 20 ++) ++ ++// These are the global, common group parameters for OTR. ++var ( ++ p *big.Int // group prime ++ g *big.Int // group generator ++ q *big.Int // group order ++ pMinus2 *big.Int ++) ++ ++func init() { ++ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16) ++ q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16) ++ g = new(big.Int).SetInt64(2) ++ pMinus2 = new(big.Int).Sub(p, g) ++} ++ ++// Conversation represents a relation with a peer. The zero value is a valid ++// Conversation, although PrivateKey must be set. ++// ++// When communicating with a peer, all inbound messages should be passed to ++// Conversation.Receive and all outbound messages to Conversation.Send. The ++// Conversation will take care of maintaining the encryption state and ++// negotiating encryption as needed. ++type Conversation struct { ++ // PrivateKey contains the private key to use to sign key exchanges. ++ PrivateKey *PrivateKey ++ ++ // Rand can be set to override the entropy source. Otherwise, ++ // crypto/rand will be used. ++ Rand io.Reader ++ // If FragmentSize is set, all messages produced by Receive and Send ++ // will be fragmented into messages of, at most, this number of bytes. ++ FragmentSize int ++ ++ // Once Receive has returned NewKeys once, the following fields are ++ // valid. ++ SSID [8]byte ++ TheirPublicKey PublicKey ++ ++ state, authState int ++ ++ r [16]byte ++ x, y *big.Int ++ gx, gy *big.Int ++ gxBytes []byte ++ digest [sha256.Size]byte ++ ++ revealKeys, sigKeys akeKeys ++ ++ myKeyId uint32 ++ myCurrentDHPub *big.Int ++ myCurrentDHPriv *big.Int ++ myLastDHPub *big.Int ++ myLastDHPriv *big.Int ++ ++ theirKeyId uint32 ++ theirCurrentDHPub *big.Int ++ theirLastDHPub *big.Int ++ ++ keySlots [4]keySlot ++ ++ myCounter [8]byte ++ theirLastCtr [8]byte ++ oldMACs []byte ++ ++ k, n int // fragment state ++ frag []byte ++ ++ smp smpState ++} ++ ++// A keySlot contains key material for a specific (their keyid, my keyid) pair. ++type keySlot struct { ++ // used is true if this slot is valid. If false, it's free for reuse. ++ used bool ++ theirKeyId uint32 ++ myKeyId uint32 ++ sendAESKey, recvAESKey []byte ++ sendMACKey, recvMACKey []byte ++ theirLastCtr [8]byte ++} ++ ++// akeKeys are generated during key exchange. There's one set for the reveal ++// signature message and another for the signature message. In the protocol ++// spec the latter are indicated with a prime mark. ++type akeKeys struct { ++ c [16]byte ++ m1, m2 [32]byte ++} ++ ++func (c *Conversation) rand() io.Reader { ++ if c.Rand != nil { ++ return c.Rand ++ } ++ return rand.Reader ++} ++ ++func (c *Conversation) randMPI(buf []byte) *big.Int { ++ _, err := io.ReadFull(c.rand(), buf) ++ if err != nil { ++ panic("otr: short read from random source") ++ } ++ ++ return new(big.Int).SetBytes(buf) ++} ++ ++// tlv represents the type-length value from the protocol. ++type tlv struct { ++ typ, length uint16 ++ data []byte ++} ++ ++const ( ++ tlvTypePadding = 0 ++ tlvTypeDisconnected = 1 ++ tlvTypeSMP1 = 2 ++ tlvTypeSMP2 = 3 ++ tlvTypeSMP3 = 4 ++ tlvTypeSMP4 = 5 ++ tlvTypeSMPAbort = 6 ++ tlvTypeSMP1WithQuestion = 7 ++) ++ ++// Receive handles a message from a peer. It returns a human readable message, ++// an indicator of whether that message was encrypted, a hint about the ++// encryption state and zero or more messages to send back to the peer. ++// These messages do not need to be passed to Send before transmission. ++func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) { ++ if bytes.HasPrefix(in, fragmentPrefix) { ++ in, err = c.processFragment(in) ++ if in == nil || err != nil { ++ return ++ } ++ } ++ ++ if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' { ++ in = in[len(msgPrefix) : len(in)-1] ++ } else if version := isQuery(in); version > 0 { ++ c.authState = authStateAwaitingDHKey ++ c.reset() ++ toSend = c.encode(c.generateDHCommit()) ++ return ++ } else { ++ // plaintext message ++ out = in ++ return ++ } ++ ++ msg := make([]byte, base64.StdEncoding.DecodedLen(len(in))) ++ msgLen, err := base64.StdEncoding.Decode(msg, in) ++ if err != nil { ++ err = errors.New("otr: invalid base64 encoding in message") ++ return ++ } ++ msg = msg[:msgLen] ++ ++ // The first two bytes are the protocol version (2) ++ if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 { ++ err = errors.New("otr: invalid OTR message") ++ return ++ } ++ ++ msgType := int(msg[2]) ++ msg = msg[3:] ++ ++ switch msgType { ++ case msgTypeDHCommit: ++ switch c.authState { ++ case authStateNone: ++ c.authState = authStateAwaitingRevealSig ++ if err = c.processDHCommit(msg); err != nil { ++ return ++ } ++ c.reset() ++ toSend = c.encode(c.generateDHKey()) ++ return ++ case authStateAwaitingDHKey: ++ // This is a 'SYN-crossing'. The greater digest wins. ++ var cmp int ++ if cmp, err = c.compareToDHCommit(msg); err != nil { ++ return ++ } ++ if cmp > 0 { ++ // We win. Retransmit DH commit. ++ toSend = c.encode(c.serializeDHCommit()) ++ return ++ } else { ++ // They win. We forget about our DH commit. ++ c.authState = authStateAwaitingRevealSig ++ if err = c.processDHCommit(msg); err != nil { ++ return ++ } ++ c.reset() ++ toSend = c.encode(c.generateDHKey()) ++ return ++ } ++ case authStateAwaitingRevealSig: ++ if err = c.processDHCommit(msg); err != nil { ++ return ++ } ++ toSend = c.encode(c.serializeDHKey()) ++ case authStateAwaitingSig: ++ if err = c.processDHCommit(msg); err != nil { ++ return ++ } ++ c.reset() ++ toSend = c.encode(c.generateDHKey()) ++ c.authState = authStateAwaitingRevealSig ++ default: ++ panic("bad state") ++ } ++ case msgTypeDHKey: ++ switch c.authState { ++ case authStateAwaitingDHKey: ++ var isSame bool ++ if isSame, err = c.processDHKey(msg); err != nil { ++ return ++ } ++ if isSame { ++ err = errors.New("otr: unexpected duplicate DH key") ++ return ++ } ++ toSend = c.encode(c.generateRevealSig()) ++ c.authState = authStateAwaitingSig ++ case authStateAwaitingSig: ++ var isSame bool ++ if isSame, err = c.processDHKey(msg); err != nil { ++ return ++ } ++ if isSame { ++ toSend = c.encode(c.serializeDHKey()) ++ } ++ } ++ case msgTypeRevealSig: ++ if c.authState != authStateAwaitingRevealSig { ++ return ++ } ++ if err = c.processRevealSig(msg); err != nil { ++ return ++ } ++ toSend = c.encode(c.generateSig()) ++ c.authState = authStateNone ++ c.state = stateEncrypted ++ change = NewKeys ++ case msgTypeSig: ++ if c.authState != authStateAwaitingSig { ++ return ++ } ++ if err = c.processSig(msg); err != nil { ++ return ++ } ++ c.authState = authStateNone ++ c.state = stateEncrypted ++ change = NewKeys ++ case msgTypeData: ++ if c.state != stateEncrypted { ++ err = errors.New("otr: encrypted message received without encrypted session established") ++ return ++ } ++ var tlvs []tlv ++ out, tlvs, err = c.processData(msg) ++ encrypted = true ++ ++ EachTLV: ++ for _, inTLV := range tlvs { ++ switch inTLV.typ { ++ case tlvTypeDisconnected: ++ change = ConversationEnded ++ c.state = stateFinished ++ break EachTLV ++ case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion: ++ var reply tlv ++ var complete bool ++ reply, complete, err = c.processSMP(inTLV) ++ if err == smpSecretMissingError { ++ err = nil ++ change = SMPSecretNeeded ++ c.smp.saved = &inTLV ++ return ++ } ++ if err == smpFailureError { ++ err = nil ++ change = SMPFailed ++ } else if complete { ++ change = SMPComplete ++ } ++ if reply.typ != 0 { ++ toSend = c.encode(c.generateData(nil, &reply)) ++ } ++ break EachTLV ++ default: ++ // skip unknown TLVs ++ } ++ } ++ default: ++ err = errors.New("otr: unknown message type " + strconv.Itoa(msgType)) ++ } ++ ++ return ++} ++ ++// Send takes a human readable message from the local user, possibly encrypts ++// it and returns zero one or more messages to send to the peer. ++func (c *Conversation) Send(msg []byte) ([][]byte, error) { ++ switch c.state { ++ case statePlaintext: ++ return [][]byte{msg}, nil ++ case stateEncrypted: ++ return c.encode(c.generateData(msg, nil)), nil ++ case stateFinished: ++ return nil, errors.New("otr: cannot send message because secure conversation has finished") ++ } ++ ++ return nil, errors.New("otr: cannot send message in current state") ++} ++ ++// SMPQuestion returns the human readable challenge question from the peer. ++// It's only valid after Receive has returned SMPSecretNeeded. ++func (c *Conversation) SMPQuestion() string { ++ return c.smp.question ++} ++ ++// Authenticate begins an authentication with the peer. Authentication involves ++// an optional challenge message and a shared secret. The authentication ++// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which ++// indicates that a new authentication is happening and thus this one was ++// aborted) or SMPFailed. ++func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) { ++ if c.state != stateEncrypted { ++ err = errors.New("otr: can't authenticate a peer without a secure conversation established") ++ return ++ } ++ ++ if c.smp.saved != nil { ++ c.calcSMPSecret(mutualSecret, false /* they started it */) ++ ++ var out tlv ++ var complete bool ++ out, complete, err = c.processSMP(*c.smp.saved) ++ if complete { ++ panic("SMP completed on the first message") ++ } ++ c.smp.saved = nil ++ if out.typ != 0 { ++ toSend = c.encode(c.generateData(nil, &out)) ++ } ++ return ++ } ++ ++ c.calcSMPSecret(mutualSecret, true /* we started it */) ++ outs := c.startSMP(question) ++ for _, out := range outs { ++ toSend = append(toSend, c.encode(c.generateData(nil, &out))...) ++ } ++ return ++} ++ ++// End ends a secure conversation by generating a termination message for ++// the peer and switches to unencrypted communication. ++func (c *Conversation) End() (toSend [][]byte) { ++ switch c.state { ++ case statePlaintext: ++ return nil ++ case stateEncrypted: ++ c.state = statePlaintext ++ return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected})) ++ case stateFinished: ++ c.state = statePlaintext ++ return nil ++ } ++ panic("unreachable") ++} ++ ++// IsEncrypted returns true if a message passed to Send would be encrypted ++// before transmission. This result remains valid until the next call to ++// Receive or End, which may change the state of the Conversation. ++func (c *Conversation) IsEncrypted() bool { ++ return c.state == stateEncrypted ++} ++ ++var fragmentError = errors.New("otr: invalid OTR fragment") ++ ++// processFragment processes a fragmented OTR message and possibly returns a ++// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is ++// the fragment number (starting from 1), n is the number of fragments in this ++// message and msg is a substring of the base64 encoded message. ++func (c *Conversation) processFragment(in []byte) (out []byte, err error) { ++ in = in[len(fragmentPrefix):] // remove "?OTR," ++ parts := bytes.Split(in, fragmentPartSeparator) ++ if len(parts) != 4 || len(parts[3]) != 0 { ++ return nil, fragmentError ++ } ++ ++ k, err := strconv.Atoi(string(parts[0])) ++ if err != nil { ++ return nil, fragmentError ++ } ++ ++ n, err := strconv.Atoi(string(parts[1])) ++ if err != nil { ++ return nil, fragmentError ++ } ++ ++ if k < 1 || n < 1 || k > n { ++ return nil, fragmentError ++ } ++ ++ if k == 1 { ++ c.frag = append(c.frag[:0], parts[2]...) ++ c.k, c.n = k, n ++ } else if n == c.n && k == c.k+1 { ++ c.frag = append(c.frag, parts[2]...) ++ c.k++ ++ } else { ++ c.frag = c.frag[:0] ++ c.n, c.k = 0, 0 ++ } ++ ++ if c.n > 0 && c.k == c.n { ++ c.n, c.k = 0, 0 ++ return c.frag, nil ++ } ++ ++ return nil, nil ++} ++ ++func (c *Conversation) generateDHCommit() []byte { ++ _, err := io.ReadFull(c.rand(), c.r[:]) ++ if err != nil { ++ panic("otr: short read from random source") ++ } ++ ++ var xBytes [dhPrivateBytes]byte ++ c.x = c.randMPI(xBytes[:]) ++ c.gx = new(big.Int).Exp(g, c.x, p) ++ c.gy = nil ++ c.gxBytes = appendMPI(nil, c.gx) ++ ++ h := sha256.New() ++ h.Write(c.gxBytes) ++ h.Sum(c.digest[:0]) ++ ++ aesCipher, err := aes.NewCipher(c.r[:]) ++ if err != nil { ++ panic(err.Error()) ++ } ++ ++ var iv [aes.BlockSize]byte ++ ctr := cipher.NewCTR(aesCipher, iv[:]) ++ ctr.XORKeyStream(c.gxBytes, c.gxBytes) ++ ++ return c.serializeDHCommit() ++} ++ ++func (c *Conversation) serializeDHCommit() []byte { ++ var ret []byte ++ ret = appendU16(ret, 2) // protocol version ++ ret = append(ret, msgTypeDHCommit) ++ ret = appendData(ret, c.gxBytes) ++ ret = appendData(ret, c.digest[:]) ++ return ret ++} ++ ++func (c *Conversation) processDHCommit(in []byte) error { ++ var ok1, ok2 bool ++ c.gxBytes, in, ok1 = getData(in) ++ digest, in, ok2 := getData(in) ++ if !ok1 || !ok2 || len(in) > 0 { ++ return errors.New("otr: corrupt DH commit message") ++ } ++ copy(c.digest[:], digest) ++ return nil ++} ++ ++func (c *Conversation) compareToDHCommit(in []byte) (int, error) { ++ _, in, ok1 := getData(in) ++ digest, in, ok2 := getData(in) ++ if !ok1 || !ok2 || len(in) > 0 { ++ return 0, errors.New("otr: corrupt DH commit message") ++ } ++ return bytes.Compare(c.digest[:], digest), nil ++} ++ ++func (c *Conversation) generateDHKey() []byte { ++ var yBytes [dhPrivateBytes]byte ++ c.y = c.randMPI(yBytes[:]) ++ c.gy = new(big.Int).Exp(g, c.y, p) ++ return c.serializeDHKey() ++} ++ ++func (c *Conversation) serializeDHKey() []byte { ++ var ret []byte ++ ret = appendU16(ret, 2) // protocol version ++ ret = append(ret, msgTypeDHKey) ++ ret = appendMPI(ret, c.gy) ++ return ret ++} ++ ++func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) { ++ gy, _, ok := getMPI(in) ++ if !ok { ++ err = errors.New("otr: corrupt DH key message") ++ return ++ } ++ if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 { ++ err = errors.New("otr: DH value out of range") ++ return ++ } ++ if c.gy != nil { ++ isSame = c.gy.Cmp(gy) == 0 ++ return ++ } ++ c.gy = gy ++ return ++} ++ ++func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) { ++ var xb []byte ++ xb = c.PrivateKey.PublicKey.Serialize(xb) ++ ++ var verifyData []byte ++ if xFirst { ++ verifyData = appendMPI(verifyData, c.gx) ++ verifyData = appendMPI(verifyData, c.gy) ++ } else { ++ verifyData = appendMPI(verifyData, c.gy) ++ verifyData = appendMPI(verifyData, c.gx) ++ } ++ verifyData = append(verifyData, xb...) ++ verifyData = appendU32(verifyData, c.myKeyId) ++ ++ mac := hmac.New(sha256.New, keys.m1[:]) ++ mac.Write(verifyData) ++ mb := mac.Sum(nil) ++ ++ xb = appendU32(xb, c.myKeyId) ++ xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...) ++ ++ aesCipher, err := aes.NewCipher(keys.c[:]) ++ if err != nil { ++ panic(err.Error()) ++ } ++ var iv [aes.BlockSize]byte ++ ctr := cipher.NewCTR(aesCipher, iv[:]) ++ ctr.XORKeyStream(xb, xb) ++ ++ mac = hmac.New(sha256.New, keys.m2[:]) ++ encryptedSig := appendData(nil, xb) ++ mac.Write(encryptedSig) ++ ++ return encryptedSig, mac.Sum(nil) ++} ++ ++func (c *Conversation) generateRevealSig() []byte { ++ s := new(big.Int).Exp(c.gy, c.x, p) ++ c.calcAKEKeys(s) ++ c.myKeyId++ ++ ++ encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */) ++ ++ c.myCurrentDHPub = c.gx ++ c.myCurrentDHPriv = c.x ++ c.rotateDHKeys() ++ incCounter(&c.myCounter) ++ ++ var ret []byte ++ ret = appendU16(ret, 2) ++ ret = append(ret, msgTypeRevealSig) ++ ret = appendData(ret, c.r[:]) ++ ret = append(ret, encryptedSig...) ++ ret = append(ret, mac[:20]...) ++ return ret ++} ++ ++func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error { ++ mac := hmac.New(sha256.New, keys.m2[:]) ++ mac.Write(appendData(nil, encryptedSig)) ++ myMAC := mac.Sum(nil)[:20] ++ ++ if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { ++ return errors.New("bad signature MAC in encrypted signature") ++ } ++ ++ aesCipher, err := aes.NewCipher(keys.c[:]) ++ if err != nil { ++ panic(err.Error()) ++ } ++ var iv [aes.BlockSize]byte ++ ctr := cipher.NewCTR(aesCipher, iv[:]) ++ ctr.XORKeyStream(encryptedSig, encryptedSig) ++ ++ sig := encryptedSig ++ sig, ok1 := c.TheirPublicKey.Parse(sig) ++ keyId, sig, ok2 := getU32(sig) ++ if !ok1 || !ok2 { ++ return errors.New("otr: corrupt encrypted signature") ++ } ++ ++ var verifyData []byte ++ if xFirst { ++ verifyData = appendMPI(verifyData, c.gx) ++ verifyData = appendMPI(verifyData, c.gy) ++ } else { ++ verifyData = appendMPI(verifyData, c.gy) ++ verifyData = appendMPI(verifyData, c.gx) ++ } ++ verifyData = c.TheirPublicKey.Serialize(verifyData) ++ verifyData = appendU32(verifyData, keyId) ++ ++ mac = hmac.New(sha256.New, keys.m1[:]) ++ mac.Write(verifyData) ++ mb := mac.Sum(nil) ++ ++ sig, ok1 = c.TheirPublicKey.Verify(mb, sig) ++ if !ok1 { ++ return errors.New("bad signature in encrypted signature") ++ } ++ if len(sig) > 0 { ++ return errors.New("corrupt encrypted signature") ++ } ++ ++ c.theirKeyId = keyId ++ zero(c.theirLastCtr[:]) ++ return nil ++} ++ ++func (c *Conversation) processRevealSig(in []byte) error { ++ r, in, ok1 := getData(in) ++ encryptedSig, in, ok2 := getData(in) ++ theirMAC := in ++ if !ok1 || !ok2 || len(theirMAC) != 20 { ++ return errors.New("otr: corrupt reveal signature message") ++ } ++ ++ aesCipher, err := aes.NewCipher(r) ++ if err != nil { ++ return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error()) ++ } ++ var iv [aes.BlockSize]byte ++ ctr := cipher.NewCTR(aesCipher, iv[:]) ++ ctr.XORKeyStream(c.gxBytes, c.gxBytes) ++ h := sha256.New() ++ h.Write(c.gxBytes) ++ digest := h.Sum(nil) ++ if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 { ++ return errors.New("otr: bad commit MAC in reveal signature message") ++ } ++ var rest []byte ++ c.gx, rest, ok1 = getMPI(c.gxBytes) ++ if !ok1 || len(rest) > 0 { ++ return errors.New("otr: gx corrupt after decryption") ++ } ++ if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 { ++ return errors.New("otr: DH value out of range") ++ } ++ s := new(big.Int).Exp(c.gx, c.y, p) ++ c.calcAKEKeys(s) ++ ++ if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil { ++ return errors.New("otr: in reveal signature message: " + err.Error()) ++ } ++ ++ c.theirCurrentDHPub = c.gx ++ c.theirLastDHPub = nil ++ ++ return nil ++} ++ ++func (c *Conversation) generateSig() []byte { ++ c.myKeyId++ ++ ++ encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */) ++ ++ c.myCurrentDHPub = c.gy ++ c.myCurrentDHPriv = c.y ++ c.rotateDHKeys() ++ incCounter(&c.myCounter) ++ ++ var ret []byte ++ ret = appendU16(ret, 2) ++ ret = append(ret, msgTypeSig) ++ ret = append(ret, encryptedSig...) ++ ret = append(ret, mac[:macPrefixBytes]...) ++ return ret ++} ++ ++func (c *Conversation) processSig(in []byte) error { ++ encryptedSig, in, ok1 := getData(in) ++ theirMAC := in ++ if !ok1 || len(theirMAC) != macPrefixBytes { ++ return errors.New("otr: corrupt signature message") ++ } ++ ++ if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil { ++ return errors.New("otr: in signature message: " + err.Error()) ++ } ++ ++ c.theirCurrentDHPub = c.gy ++ c.theirLastDHPub = nil ++ ++ return nil ++} ++ ++func (c *Conversation) rotateDHKeys() { ++ // evict slots using our retired key id ++ for i := range c.keySlots { ++ slot := &c.keySlots[i] ++ if slot.used && slot.myKeyId == c.myKeyId-1 { ++ slot.used = false ++ c.oldMACs = append(c.oldMACs, slot.recvMACKey...) ++ } ++ } ++ ++ c.myLastDHPriv = c.myCurrentDHPriv ++ c.myLastDHPub = c.myCurrentDHPub ++ ++ var xBytes [dhPrivateBytes]byte ++ c.myCurrentDHPriv = c.randMPI(xBytes[:]) ++ c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p) ++ c.myKeyId++ ++} ++ ++func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) { ++ origIn := in ++ flags, in, ok1 := getU8(in) ++ theirKeyId, in, ok2 := getU32(in) ++ myKeyId, in, ok3 := getU32(in) ++ y, in, ok4 := getMPI(in) ++ counter, in, ok5 := getNBytes(in, 8) ++ encrypted, in, ok6 := getData(in) ++ macedData := origIn[:len(origIn)-len(in)] ++ theirMAC, in, ok7 := getNBytes(in, macPrefixBytes) ++ _, in, ok8 := getData(in) ++ if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 { ++ err = errors.New("otr: corrupt data message") ++ return ++ } ++ ++ ignoreErrors := flags&1 != 0 ++ ++ slot, err := c.calcDataKeys(myKeyId, theirKeyId) ++ if err != nil { ++ if ignoreErrors { ++ err = nil ++ } ++ return ++ } ++ ++ mac := hmac.New(sha1.New, slot.recvMACKey) ++ mac.Write([]byte{0, 2, 3}) ++ mac.Write(macedData) ++ myMAC := mac.Sum(nil) ++ if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { ++ if !ignoreErrors { ++ err = errors.New("otr: bad MAC on data message") ++ } ++ return ++ } ++ ++ if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 { ++ err = errors.New("otr: counter regressed") ++ return ++ } ++ copy(slot.theirLastCtr[:], counter) ++ ++ var iv [aes.BlockSize]byte ++ copy(iv[:], counter) ++ aesCipher, err := aes.NewCipher(slot.recvAESKey) ++ if err != nil { ++ panic(err.Error()) ++ } ++ ctr := cipher.NewCTR(aesCipher, iv[:]) ++ ctr.XORKeyStream(encrypted, encrypted) ++ decrypted := encrypted ++ ++ if myKeyId == c.myKeyId { ++ c.rotateDHKeys() ++ } ++ if theirKeyId == c.theirKeyId { ++ // evict slots using their retired key id ++ for i := range c.keySlots { ++ slot := &c.keySlots[i] ++ if slot.used && slot.theirKeyId == theirKeyId-1 { ++ slot.used = false ++ c.oldMACs = append(c.oldMACs, slot.recvMACKey...) ++ } ++ } ++ ++ c.theirLastDHPub = c.theirCurrentDHPub ++ c.theirKeyId++ ++ c.theirCurrentDHPub = y ++ } ++ ++ if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 { ++ out = decrypted[:nulPos] ++ tlvData := decrypted[nulPos+1:] ++ for len(tlvData) > 0 { ++ var t tlv ++ var ok1, ok2, ok3 bool ++ ++ t.typ, tlvData, ok1 = getU16(tlvData) ++ t.length, tlvData, ok2 = getU16(tlvData) ++ t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length)) ++ if !ok1 || !ok2 || !ok3 { ++ err = errors.New("otr: corrupt tlv data") ++ return ++ } ++ tlvs = append(tlvs, t) ++ } ++ } else { ++ out = decrypted ++ } ++ ++ return ++} ++ ++func (c *Conversation) generateData(msg []byte, extra *tlv) []byte { ++ slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId) ++ if err != nil { ++ panic("otr: failed to generate sending keys: " + err.Error()) ++ } ++ ++ var plaintext []byte ++ plaintext = append(plaintext, msg...) ++ plaintext = append(plaintext, 0) ++ ++ padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity) ++ plaintext = appendU16(plaintext, tlvTypePadding) ++ plaintext = appendU16(plaintext, uint16(padding)) ++ for i := 0; i < padding; i++ { ++ plaintext = append(plaintext, 0) ++ } ++ ++ if extra != nil { ++ plaintext = appendU16(plaintext, extra.typ) ++ plaintext = appendU16(plaintext, uint16(len(extra.data))) ++ plaintext = append(plaintext, extra.data...) ++ } ++ ++ encrypted := make([]byte, len(plaintext)) ++ ++ var iv [aes.BlockSize]byte ++ copy(iv[:], c.myCounter[:]) ++ aesCipher, err := aes.NewCipher(slot.sendAESKey) ++ if err != nil { ++ panic(err.Error()) ++ } ++ ctr := cipher.NewCTR(aesCipher, iv[:]) ++ ctr.XORKeyStream(encrypted, plaintext) ++ ++ var ret []byte ++ ret = appendU16(ret, 2) ++ ret = append(ret, msgTypeData) ++ ret = append(ret, 0 /* flags */) ++ ret = appendU32(ret, c.myKeyId-1) ++ ret = appendU32(ret, c.theirKeyId) ++ ret = appendMPI(ret, c.myCurrentDHPub) ++ ret = append(ret, c.myCounter[:]...) ++ ret = appendData(ret, encrypted) ++ ++ mac := hmac.New(sha1.New, slot.sendMACKey) ++ mac.Write(ret) ++ ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...) ++ ret = appendData(ret, c.oldMACs) ++ c.oldMACs = nil ++ incCounter(&c.myCounter) ++ ++ return ret ++} ++ ++func incCounter(counter *[8]byte) { ++ for i := 7; i >= 0; i-- { ++ counter[i]++ ++ if counter[i] > 0 { ++ break ++ } ++ } ++} ++ ++// calcDataKeys computes the keys used to encrypt a data message given the key ++// IDs. ++func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) { ++ // Check for a cache hit. ++ for i := range c.keySlots { ++ slot = &c.keySlots[i] ++ if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId { ++ return ++ } ++ } ++ ++ // Find an empty slot to write into. ++ slot = nil ++ for i := range c.keySlots { ++ if !c.keySlots[i].used { ++ slot = &c.keySlots[i] ++ break ++ } ++ } ++ if slot == nil { ++ return nil, errors.New("otr: internal error: no more key slots") ++ } ++ ++ var myPriv, myPub, theirPub *big.Int ++ ++ if myKeyId == c.myKeyId { ++ myPriv = c.myCurrentDHPriv ++ myPub = c.myCurrentDHPub ++ } else if myKeyId == c.myKeyId-1 { ++ myPriv = c.myLastDHPriv ++ myPub = c.myLastDHPub ++ } else { ++ err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10)) ++ return ++ } ++ ++ if theirKeyId == c.theirKeyId { ++ theirPub = c.theirCurrentDHPub ++ } else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil { ++ theirPub = c.theirLastDHPub ++ } else { ++ err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10)) ++ return ++ } ++ ++ var sendPrefixByte, recvPrefixByte [1]byte ++ ++ if myPub.Cmp(theirPub) > 0 { ++ // we're the high end ++ sendPrefixByte[0], recvPrefixByte[0] = 1, 2 ++ } else { ++ // we're the low end ++ sendPrefixByte[0], recvPrefixByte[0] = 2, 1 ++ } ++ ++ s := new(big.Int).Exp(theirPub, myPriv, p) ++ sBytes := appendMPI(nil, s) ++ ++ h := sha1.New() ++ h.Write(sendPrefixByte[:]) ++ h.Write(sBytes) ++ slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16] ++ ++ h.Reset() ++ h.Write(slot.sendAESKey) ++ slot.sendMACKey = h.Sum(slot.sendMACKey[:0]) ++ ++ h.Reset() ++ h.Write(recvPrefixByte[:]) ++ h.Write(sBytes) ++ slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16] ++ ++ h.Reset() ++ h.Write(slot.recvAESKey) ++ slot.recvMACKey = h.Sum(slot.recvMACKey[:0]) ++ ++ slot.theirKeyId = theirKeyId ++ slot.myKeyId = myKeyId ++ slot.used = true ++ ++ zero(slot.theirLastCtr[:]) ++ return ++} ++ ++func (c *Conversation) calcAKEKeys(s *big.Int) { ++ mpi := appendMPI(nil, s) ++ h := sha256.New() ++ ++ var cBytes [32]byte ++ hashWithPrefix(c.SSID[:], 0, mpi, h) ++ ++ hashWithPrefix(cBytes[:], 1, mpi, h) ++ copy(c.revealKeys.c[:], cBytes[:16]) ++ copy(c.sigKeys.c[:], cBytes[16:]) ++ ++ hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h) ++ hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h) ++ hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h) ++ hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h) ++} ++ ++func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) { ++ h.Reset() ++ var p [1]byte ++ p[0] = prefix ++ h.Write(p[:]) ++ h.Write(in) ++ if len(out) == h.Size() { ++ h.Sum(out[:0]) ++ } else { ++ digest := h.Sum(nil) ++ copy(out, digest) ++ } ++} ++ ++func (c *Conversation) encode(msg []byte) [][]byte { ++ b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1) ++ base64.StdEncoding.Encode(b64[len(msgPrefix):], msg) ++ copy(b64, msgPrefix) ++ b64[len(b64)-1] = '.' ++ ++ if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize { ++ // We can encode this in a single fragment. ++ return [][]byte{b64} ++ } ++ ++ // We have to fragment this message. ++ var ret [][]byte ++ bytesPerFragment := c.FragmentSize - minFragmentSize ++ numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment ++ ++ for i := 0; i < numFragments; i++ { ++ frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",") ++ todo := bytesPerFragment ++ if todo > len(b64) { ++ todo = len(b64) ++ } ++ frag = append(frag, b64[:todo]...) ++ b64 = b64[todo:] ++ frag = append(frag, ',') ++ ret = append(ret, frag) ++ } ++ ++ return ret ++} ++ ++func (c *Conversation) reset() { ++ c.myKeyId = 0 ++ ++ for i := range c.keySlots { ++ c.keySlots[i].used = false ++ } ++} ++ ++type PublicKey struct { ++ dsa.PublicKey ++} ++ ++func (pk *PublicKey) Parse(in []byte) ([]byte, bool) { ++ var ok bool ++ var pubKeyType uint16 ++ ++ if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 { ++ return nil, false ++ } ++ if pk.P, in, ok = getMPI(in); !ok { ++ return nil, false ++ } ++ if pk.Q, in, ok = getMPI(in); !ok { ++ return nil, false ++ } ++ if pk.G, in, ok = getMPI(in); !ok { ++ return nil, false ++ } ++ if pk.Y, in, ok = getMPI(in); !ok { ++ return nil, false ++ } ++ ++ return in, true ++} ++ ++func (pk *PublicKey) Serialize(in []byte) []byte { ++ in = appendU16(in, 0) ++ in = appendMPI(in, pk.P) ++ in = appendMPI(in, pk.Q) ++ in = appendMPI(in, pk.G) ++ in = appendMPI(in, pk.Y) ++ return in ++} ++ ++// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey. ++func (pk *PublicKey) Fingerprint() []byte { ++ b := pk.Serialize(nil) ++ h := sha1.New() ++ h.Write(b[2:]) ++ return h.Sum(nil) ++} ++ ++func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) { ++ if len(sig) != 2*dsaSubgroupBytes { ++ return nil, false ++ } ++ r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes]) ++ s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:]) ++ ok := dsa.Verify(&pk.PublicKey, hashed, r, s) ++ return sig[dsaSubgroupBytes*2:], ok ++} ++ ++type PrivateKey struct { ++ PublicKey ++ dsa.PrivateKey ++} ++ ++func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte { ++ r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed) ++ if err != nil { ++ panic(err.Error()) ++ } ++ rBytes := r.Bytes() ++ sBytes := s.Bytes() ++ if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes { ++ panic("DSA signature too large") ++ } ++ ++ out := make([]byte, 2*dsaSubgroupBytes) ++ copy(out[dsaSubgroupBytes-len(rBytes):], rBytes) ++ copy(out[len(out)-len(sBytes):], sBytes) ++ return out ++} ++ ++func (priv *PrivateKey) Serialize(in []byte) []byte { ++ in = priv.PublicKey.Serialize(in) ++ in = appendMPI(in, priv.PrivateKey.X) ++ return in ++} ++ ++func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) { ++ in, ok := priv.PublicKey.Parse(in) ++ if !ok { ++ return in, ok ++ } ++ priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey ++ priv.PrivateKey.X, in, ok = getMPI(in) ++ return in, ok ++} ++ ++func (priv *PrivateKey) Generate(rand io.Reader) { ++ if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil { ++ panic(err.Error()) ++ } ++ if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil { ++ panic(err.Error()) ++ } ++ priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey ++} ++ ++func notHex(r rune) bool { ++ if r >= '0' && r <= '9' || ++ r >= 'a' && r <= 'f' || ++ r >= 'A' && r <= 'F' { ++ return false ++ } ++ ++ return true ++} ++ ++// Import parses the contents of a libotr private key file. ++func (priv *PrivateKey) Import(in []byte) bool { ++ mpiStart := []byte(" #") ++ ++ mpis := make([]*big.Int, 5) ++ ++ for i := 0; i < len(mpis); i++ { ++ start := bytes.Index(in, mpiStart) ++ if start == -1 { ++ return false ++ } ++ in = in[start+len(mpiStart):] ++ end := bytes.IndexFunc(in, notHex) ++ if end == -1 { ++ return false ++ } ++ hexBytes := in[:end] ++ in = in[end:] ++ ++ if len(hexBytes)&1 != 0 { ++ return false ++ } ++ ++ mpiBytes := make([]byte, len(hexBytes)/2) ++ if _, err := hex.Decode(mpiBytes, hexBytes); err != nil { ++ return false ++ } ++ ++ mpis[i] = new(big.Int).SetBytes(mpiBytes) ++ } ++ ++ for _, mpi := range mpis { ++ if mpi.Sign() <= 0 { ++ return false ++ } ++ } ++ ++ priv.PrivateKey.P = mpis[0] ++ priv.PrivateKey.Q = mpis[1] ++ priv.PrivateKey.G = mpis[2] ++ priv.PrivateKey.Y = mpis[3] ++ priv.PrivateKey.X = mpis[4] ++ priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey ++ ++ a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P) ++ return a.Cmp(priv.PrivateKey.Y) == 0 ++} ++ ++func getU8(in []byte) (uint8, []byte, bool) { ++ if len(in) < 1 { ++ return 0, in, false ++ } ++ return in[0], in[1:], true ++} ++ ++func getU16(in []byte) (uint16, []byte, bool) { ++ if len(in) < 2 { ++ return 0, in, false ++ } ++ r := uint16(in[0])<<8 | uint16(in[1]) ++ return r, in[2:], true ++} ++ ++func getU32(in []byte) (uint32, []byte, bool) { ++ if len(in) < 4 { ++ return 0, in, false ++ } ++ r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3]) ++ return r, in[4:], true ++} ++ ++func getMPI(in []byte) (*big.Int, []byte, bool) { ++ l, in, ok := getU32(in) ++ if !ok || uint32(len(in)) < l { ++ return nil, in, false ++ } ++ r := new(big.Int).SetBytes(in[:l]) ++ return r, in[l:], true ++} ++ ++func getData(in []byte) ([]byte, []byte, bool) { ++ l, in, ok := getU32(in) ++ if !ok || uint32(len(in)) < l { ++ return nil, in, false ++ } ++ return in[:l], in[l:], true ++} ++ ++func getNBytes(in []byte, n int) ([]byte, []byte, bool) { ++ if len(in) < n { ++ return nil, in, false ++ } ++ return in[:n], in[n:], true ++} ++ ++func appendU16(out []byte, v uint16) []byte { ++ out = append(out, byte(v>>8), byte(v)) ++ return out ++} ++ ++func appendU32(out []byte, v uint32) []byte { ++ out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) ++ return out ++} ++ ++func appendData(out, v []byte) []byte { ++ out = appendU32(out, uint32(len(v))) ++ out = append(out, v...) ++ return out ++} ++ ++func appendMPI(out []byte, v *big.Int) []byte { ++ vBytes := v.Bytes() ++ out = appendU32(out, uint32(len(vBytes))) ++ out = append(out, vBytes...) ++ return out ++} ++ ++func appendMPIs(out []byte, mpis ...*big.Int) []byte { ++ for _, mpi := range mpis { ++ out = appendMPI(out, mpi) ++ } ++ return out ++} ++ ++func zero(b []byte) { ++ for i := range b { ++ b[i] = 0 ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/otr/otr_test.go b/ms_mod/golang.org/x/crypto/otr/otr_test.go +new file mode 100644 +index 00000000000000..cfcd062b274507 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/otr/otr_test.go +@@ -0,0 +1,470 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package otr ++ ++import ( ++ "bufio" ++ "bytes" ++ "crypto/rand" ++ "encoding/hex" ++ "math/big" ++ "os" ++ "os/exec" ++ "testing" ++) ++ ++var isQueryTests = []struct { ++ msg string ++ expectedVersion int ++}{ ++ {"foo", 0}, ++ {"?OtR", 0}, ++ {"?OtR?", 0}, ++ {"?OTR?", 0}, ++ {"?OTRv?", 0}, ++ {"?OTRv1?", 0}, ++ {"?OTR?v1?", 0}, ++ {"?OTR?v?", 0}, ++ {"?OTR?v2?", 2}, ++ {"?OTRv2?", 2}, ++ {"?OTRv23?", 2}, ++ {"?OTRv23 ?", 0}, ++} ++ ++func TestIsQuery(t *testing.T) { ++ for i, test := range isQueryTests { ++ version := isQuery([]byte(test.msg)) ++ if version != test.expectedVersion { ++ t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion) ++ } ++ } ++} ++ ++var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57" ++ ++var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f" ++ ++var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48" ++ ++func TestKeySerialization(t *testing.T) { ++ var priv PrivateKey ++ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) ++ rest, ok := priv.Parse(alicePrivateKey) ++ if !ok { ++ t.Error("failed to parse private key") ++ } ++ if len(rest) > 0 { ++ t.Error("data remaining after parsing private key") ++ } ++ ++ out := priv.Serialize(nil) ++ if !bytes.Equal(alicePrivateKey, out) { ++ t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey) ++ } ++ ++ aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex) ++ fingerprint := priv.PublicKey.Fingerprint() ++ if !bytes.Equal(aliceFingerprint, fingerprint) { ++ t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint) ++ } ++} ++ ++const libOTRPrivateKey = `(privkeys ++ (account ++(name "foo@example.com") ++(protocol prpl-jabber) ++(private-key ++ (dsa ++ (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) ++ (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) ++ (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) ++ (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#) ++ (x #14D0345A3562C480A039E3C72764F72D79043216#) ++ ) ++ ) ++ ) ++)` ++ ++func TestParseLibOTRPrivateKey(t *testing.T) { ++ var priv PrivateKey ++ ++ if !priv.Import([]byte(libOTRPrivateKey)) { ++ t.Fatalf("Failed to import sample private key") ++ } ++} ++ ++func TestSignVerify(t *testing.T) { ++ var priv PrivateKey ++ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) ++ _, ok := priv.Parse(alicePrivateKey) ++ if !ok { ++ t.Error("failed to parse private key") ++ } ++ ++ var msg [32]byte ++ rand.Reader.Read(msg[:]) ++ ++ sig := priv.Sign(rand.Reader, msg[:]) ++ rest, ok := priv.PublicKey.Verify(msg[:], sig) ++ if !ok { ++ t.Errorf("signature (%x) of %x failed to verify", sig, msg[:]) ++ } else if len(rest) > 0 { ++ t.Error("signature data remains after verification") ++ } ++ ++ sig[10] ^= 80 ++ _, ok = priv.PublicKey.Verify(msg[:], sig) ++ if ok { ++ t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:]) ++ } ++} ++ ++func setupConversation(t *testing.T) (alice, bob *Conversation) { ++ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) ++ bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex) ++ ++ alice, bob = new(Conversation), new(Conversation) ++ ++ alice.PrivateKey = new(PrivateKey) ++ bob.PrivateKey = new(PrivateKey) ++ alice.PrivateKey.Parse(alicePrivateKey) ++ bob.PrivateKey.Parse(bobPrivateKey) ++ alice.FragmentSize = 100 ++ bob.FragmentSize = 100 ++ ++ if alice.IsEncrypted() { ++ t.Error("Alice believes that the conversation is secure before we've started") ++ } ++ if bob.IsEncrypted() { ++ t.Error("Bob believes that the conversation is secure before we've started") ++ } ++ ++ performHandshake(t, alice, bob) ++ return alice, bob ++} ++ ++func performHandshake(t *testing.T, alice, bob *Conversation) { ++ var alicesMessage, bobsMessage [][]byte ++ var out []byte ++ var aliceChange, bobChange SecurityChange ++ var err error ++ alicesMessage = append(alicesMessage, []byte(QueryMessage)) ++ ++ for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ { ++ bobsMessage = nil ++ for i, msg := range alicesMessage { ++ out, _, bobChange, bobsMessage, err = bob.Receive(msg) ++ if len(out) > 0 { ++ t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i) ++ } ++ if err != nil { ++ t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err) ++ } ++ if len(bobsMessage) > 0 && i != len(alicesMessage)-1 { ++ t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i) ++ } ++ } ++ ++ alicesMessage = nil ++ for i, msg := range bobsMessage { ++ out, _, aliceChange, alicesMessage, err = alice.Receive(msg) ++ if len(out) > 0 { ++ t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i) ++ } ++ if err != nil { ++ t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err) ++ } ++ if len(alicesMessage) > 0 && i != len(bobsMessage)-1 { ++ t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i) ++ } ++ } ++ } ++ ++ if aliceChange != NewKeys { ++ t.Errorf("Alice terminated without signaling new keys") ++ } ++ if bobChange != NewKeys { ++ t.Errorf("Bob terminated without signaling new keys") ++ } ++ ++ if !bytes.Equal(alice.SSID[:], bob.SSID[:]) { ++ t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:]) ++ } ++ ++ if !alice.IsEncrypted() { ++ t.Error("Alice doesn't believe that the conversation is secure") ++ } ++ if !bob.IsEncrypted() { ++ t.Error("Bob doesn't believe that the conversation is secure") ++ } ++} ++ ++const ( ++ firstRoundTrip = iota ++ subsequentRoundTrip ++ noMACKeyCheck ++) ++ ++func roundTrip(t *testing.T, alice, bob *Conversation, message []byte, macKeyCheck int) { ++ alicesMessage, err := alice.Send(message) ++ if err != nil { ++ t.Errorf("Error from Alice sending message: %s", err) ++ } ++ ++ if len(alice.oldMACs) != 0 { ++ t.Errorf("Alice has not revealed all MAC keys") ++ } ++ ++ for i, msg := range alicesMessage { ++ out, encrypted, _, _, err := bob.Receive(msg) ++ ++ if err != nil { ++ t.Errorf("Error generated while processing test message: %s", err.Error()) ++ } ++ if len(out) > 0 { ++ if i != len(alicesMessage)-1 { ++ t.Fatal("Bob produced a message while processing a fragment of Alice's") ++ } ++ if !encrypted { ++ t.Errorf("Message was not marked as encrypted") ++ } ++ if !bytes.Equal(out, message) { ++ t.Errorf("Message corrupted: got %x, want %x", out, message) ++ } ++ } ++ } ++ ++ switch macKeyCheck { ++ case firstRoundTrip: ++ if len(bob.oldMACs) != 0 { ++ t.Errorf("Bob should not have MAC keys to reveal") ++ } ++ case subsequentRoundTrip: ++ if len(bob.oldMACs) != 40 { ++ t.Errorf("Bob has %d bytes of MAC keys to reveal, but should have 40", len(bob.oldMACs)) ++ } ++ } ++ ++ bobsMessage, err := bob.Send(message) ++ if err != nil { ++ t.Errorf("Error from Bob sending message: %s", err) ++ } ++ ++ if len(bob.oldMACs) != 0 { ++ t.Errorf("Bob has not revealed all MAC keys") ++ } ++ ++ for i, msg := range bobsMessage { ++ out, encrypted, _, _, err := alice.Receive(msg) ++ ++ if err != nil { ++ t.Errorf("Error generated while processing test message: %s", err.Error()) ++ } ++ if len(out) > 0 { ++ if i != len(bobsMessage)-1 { ++ t.Fatal("Alice produced a message while processing a fragment of Bob's") ++ } ++ if !encrypted { ++ t.Errorf("Message was not marked as encrypted") ++ } ++ if !bytes.Equal(out, message) { ++ t.Errorf("Message corrupted: got %x, want %x", out, message) ++ } ++ } ++ } ++ ++ switch macKeyCheck { ++ case firstRoundTrip: ++ if len(alice.oldMACs) != 20 { ++ t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 20", len(alice.oldMACs)) ++ } ++ case subsequentRoundTrip: ++ if len(alice.oldMACs) != 40 { ++ t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 40", len(alice.oldMACs)) ++ } ++ } ++} ++ ++func TestConversation(t *testing.T) { ++ alice, bob := setupConversation(t) ++ ++ var testMessages = [][]byte{ ++ []byte("hello"), []byte("bye"), ++ } ++ ++ roundTripType := firstRoundTrip ++ ++ for _, testMessage := range testMessages { ++ roundTrip(t, alice, bob, testMessage, roundTripType) ++ roundTripType = subsequentRoundTrip ++ } ++} ++ ++func TestGoodSMP(t *testing.T) { ++ var alice, bob Conversation ++ ++ alice.smp.secret = new(big.Int).SetInt64(42) ++ bob.smp.secret = alice.smp.secret ++ ++ var alicesMessages, bobsMessages []tlv ++ var aliceComplete, bobComplete bool ++ var err error ++ var out tlv ++ ++ alicesMessages = alice.startSMP("") ++ for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { ++ bobsMessages = bobsMessages[:0] ++ for i, msg := range alicesMessages { ++ out, bobComplete, err = bob.processSMP(msg) ++ if err != nil { ++ t.Errorf("Error from Bob in round %d: %s", round, err) ++ } ++ if bobComplete && i != len(alicesMessages)-1 { ++ t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round) ++ } ++ if out.typ != 0 { ++ bobsMessages = append(bobsMessages, out) ++ } ++ } ++ ++ alicesMessages = alicesMessages[:0] ++ for i, msg := range bobsMessages { ++ out, aliceComplete, err = alice.processSMP(msg) ++ if err != nil { ++ t.Errorf("Error from Alice in round %d: %s", round, err) ++ } ++ if aliceComplete && i != len(bobsMessages)-1 { ++ t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round) ++ } ++ if out.typ != 0 { ++ alicesMessages = append(alicesMessages, out) ++ } ++ } ++ } ++ ++ if !aliceComplete || !bobComplete { ++ t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete) ++ } ++} ++ ++func TestBadSMP(t *testing.T) { ++ var alice, bob Conversation ++ ++ alice.smp.secret = new(big.Int).SetInt64(42) ++ bob.smp.secret = new(big.Int).SetInt64(43) ++ ++ var alicesMessages, bobsMessages []tlv ++ ++ alicesMessages = alice.startSMP("") ++ for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { ++ bobsMessages = bobsMessages[:0] ++ for _, msg := range alicesMessages { ++ out, complete, _ := bob.processSMP(msg) ++ if complete { ++ t.Errorf("Bob signaled completion in round %d", round) ++ } ++ if out.typ != 0 { ++ bobsMessages = append(bobsMessages, out) ++ } ++ } ++ ++ alicesMessages = alicesMessages[:0] ++ for _, msg := range bobsMessages { ++ out, complete, _ := alice.processSMP(msg) ++ if complete { ++ t.Errorf("Alice signaled completion in round %d", round) ++ } ++ if out.typ != 0 { ++ alicesMessages = append(alicesMessages, out) ++ } ++ } ++ } ++} ++ ++func TestRehandshaking(t *testing.T) { ++ alice, bob := setupConversation(t) ++ roundTrip(t, alice, bob, []byte("test"), firstRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 2"), subsequentRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 3"), subsequentRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 4"), subsequentRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 5"), subsequentRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 6"), subsequentRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 7"), subsequentRoundTrip) ++ roundTrip(t, alice, bob, []byte("test 8"), subsequentRoundTrip) ++ performHandshake(t, alice, bob) ++ roundTrip(t, alice, bob, []byte("test"), noMACKeyCheck) ++ roundTrip(t, alice, bob, []byte("test 2"), noMACKeyCheck) ++} ++ ++func TestAgainstLibOTR(t *testing.T) { ++ // This test requires otr.c.test to be built as /tmp/a.out. ++ // If enabled, this tests runs forever performing OTR handshakes in a ++ // loop. ++ return ++ ++ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) ++ var alice Conversation ++ alice.PrivateKey = new(PrivateKey) ++ alice.PrivateKey.Parse(alicePrivateKey) ++ ++ cmd := exec.Command("/tmp/a.out") ++ cmd.Stderr = os.Stderr ++ ++ out, err := cmd.StdinPipe() ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer out.Close() ++ stdout, err := cmd.StdoutPipe() ++ if err != nil { ++ t.Fatal(err) ++ } ++ in := bufio.NewReader(stdout) ++ ++ if err := cmd.Start(); err != nil { ++ t.Fatal(err) ++ } ++ ++ out.Write([]byte(QueryMessage)) ++ out.Write([]byte("\n")) ++ var expectedText = []byte("test message") ++ ++ for { ++ line, isPrefix, err := in.ReadLine() ++ if isPrefix { ++ t.Fatal("line from subprocess too long") ++ } ++ if err != nil { ++ t.Fatal(err) ++ } ++ text, encrypted, change, alicesMessage, err := alice.Receive(line) ++ if err != nil { ++ t.Fatal(err) ++ } ++ for _, msg := range alicesMessage { ++ out.Write(msg) ++ out.Write([]byte("\n")) ++ } ++ if change == NewKeys { ++ alicesMessage, err := alice.Send([]byte("Go -> libotr test message")) ++ if err != nil { ++ t.Fatalf("error sending message: %s", err.Error()) ++ } else { ++ for _, msg := range alicesMessage { ++ out.Write(msg) ++ out.Write([]byte("\n")) ++ } ++ } ++ } ++ if len(text) > 0 { ++ if !bytes.Equal(text, expectedText) { ++ t.Fatalf("expected %x, but got %x", expectedText, text) ++ } ++ if !encrypted { ++ t.Fatal("message wasn't encrypted") ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/otr/smp.go b/ms_mod/golang.org/x/crypto/otr/smp.go +new file mode 100644 +index 00000000000000..dc6de4ee0eb74d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/otr/smp.go +@@ -0,0 +1,572 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// This file implements the Socialist Millionaires Protocol as described in ++// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol ++// specification is required in order to understand this code and, where ++// possible, the variable names in the code match up with the spec. ++ ++package otr ++ ++import ( ++ "bytes" ++ "crypto/sha256" ++ "errors" ++ "hash" ++ "math/big" ++) ++ ++type smpFailure string ++ ++func (s smpFailure) Error() string { ++ return string(s) ++} ++ ++var smpFailureError = smpFailure("otr: SMP protocol failed") ++var smpSecretMissingError = smpFailure("otr: mutual secret needed") ++ ++const smpVersion = 1 ++ ++const ( ++ smpState1 = iota ++ smpState2 ++ smpState3 ++ smpState4 ++) ++ ++type smpState struct { ++ state int ++ a2, a3, b2, b3, pb, qb *big.Int ++ g2a, g3a *big.Int ++ g2, g3 *big.Int ++ g3b, papb, qaqb, ra *big.Int ++ saved *tlv ++ secret *big.Int ++ question string ++} ++ ++func (c *Conversation) startSMP(question string) (tlvs []tlv) { ++ if c.smp.state != smpState1 { ++ tlvs = append(tlvs, c.generateSMPAbort()) ++ } ++ tlvs = append(tlvs, c.generateSMP1(question)) ++ c.smp.question = "" ++ c.smp.state = smpState2 ++ return ++} ++ ++func (c *Conversation) resetSMP() { ++ c.smp.state = smpState1 ++ c.smp.secret = nil ++ c.smp.question = "" ++} ++ ++func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) { ++ data := in.data ++ ++ switch in.typ { ++ case tlvTypeSMPAbort: ++ if c.smp.state != smpState1 { ++ err = smpFailureError ++ } ++ c.resetSMP() ++ return ++ case tlvTypeSMP1WithQuestion: ++ // We preprocess this into a SMP1 message. ++ nulPos := bytes.IndexByte(data, 0) ++ if nulPos == -1 { ++ err = errors.New("otr: SMP message with question didn't contain a NUL byte") ++ return ++ } ++ c.smp.question = string(data[:nulPos]) ++ data = data[nulPos+1:] ++ } ++ ++ numMPIs, data, ok := getU32(data) ++ if !ok || numMPIs > 20 { ++ err = errors.New("otr: corrupt SMP message") ++ return ++ } ++ ++ mpis := make([]*big.Int, numMPIs) ++ for i := range mpis { ++ var ok bool ++ mpis[i], data, ok = getMPI(data) ++ if !ok { ++ err = errors.New("otr: corrupt SMP message") ++ return ++ } ++ } ++ ++ switch in.typ { ++ case tlvTypeSMP1, tlvTypeSMP1WithQuestion: ++ if c.smp.state != smpState1 { ++ c.resetSMP() ++ out = c.generateSMPAbort() ++ return ++ } ++ if c.smp.secret == nil { ++ err = smpSecretMissingError ++ return ++ } ++ if err = c.processSMP1(mpis); err != nil { ++ return ++ } ++ c.smp.state = smpState3 ++ out = c.generateSMP2() ++ case tlvTypeSMP2: ++ if c.smp.state != smpState2 { ++ c.resetSMP() ++ out = c.generateSMPAbort() ++ return ++ } ++ if out, err = c.processSMP2(mpis); err != nil { ++ out = c.generateSMPAbort() ++ return ++ } ++ c.smp.state = smpState4 ++ case tlvTypeSMP3: ++ if c.smp.state != smpState3 { ++ c.resetSMP() ++ out = c.generateSMPAbort() ++ return ++ } ++ if out, err = c.processSMP3(mpis); err != nil { ++ return ++ } ++ c.smp.state = smpState1 ++ c.smp.secret = nil ++ complete = true ++ case tlvTypeSMP4: ++ if c.smp.state != smpState4 { ++ c.resetSMP() ++ out = c.generateSMPAbort() ++ return ++ } ++ if err = c.processSMP4(mpis); err != nil { ++ out = c.generateSMPAbort() ++ return ++ } ++ c.smp.state = smpState1 ++ c.smp.secret = nil ++ complete = true ++ default: ++ panic("unknown SMP message") ++ } ++ ++ return ++} ++ ++func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) { ++ h := sha256.New() ++ h.Write([]byte{smpVersion}) ++ if weStarted { ++ h.Write(c.PrivateKey.PublicKey.Fingerprint()) ++ h.Write(c.TheirPublicKey.Fingerprint()) ++ } else { ++ h.Write(c.TheirPublicKey.Fingerprint()) ++ h.Write(c.PrivateKey.PublicKey.Fingerprint()) ++ } ++ h.Write(c.SSID[:]) ++ h.Write(mutualSecret) ++ c.smp.secret = new(big.Int).SetBytes(h.Sum(nil)) ++} ++ ++func (c *Conversation) generateSMP1(question string) tlv { ++ var randBuf [16]byte ++ c.smp.a2 = c.randMPI(randBuf[:]) ++ c.smp.a3 = c.randMPI(randBuf[:]) ++ g2a := new(big.Int).Exp(g, c.smp.a2, p) ++ g3a := new(big.Int).Exp(g, c.smp.a3, p) ++ h := sha256.New() ++ ++ r2 := c.randMPI(randBuf[:]) ++ r := new(big.Int).Exp(g, r2, p) ++ c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r)) ++ d2 := new(big.Int).Mul(c.smp.a2, c2) ++ d2.Sub(r2, d2) ++ d2.Mod(d2, q) ++ if d2.Sign() < 0 { ++ d2.Add(d2, q) ++ } ++ ++ r3 := c.randMPI(randBuf[:]) ++ r.Exp(g, r3, p) ++ c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r)) ++ d3 := new(big.Int).Mul(c.smp.a3, c3) ++ d3.Sub(r3, d3) ++ d3.Mod(d3, q) ++ if d3.Sign() < 0 { ++ d3.Add(d3, q) ++ } ++ ++ var ret tlv ++ if len(question) > 0 { ++ ret.typ = tlvTypeSMP1WithQuestion ++ ret.data = append(ret.data, question...) ++ ret.data = append(ret.data, 0) ++ } else { ++ ret.typ = tlvTypeSMP1 ++ } ++ ret.data = appendU32(ret.data, 6) ++ ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3) ++ return ret ++} ++ ++func (c *Conversation) processSMP1(mpis []*big.Int) error { ++ if len(mpis) != 6 { ++ return errors.New("otr: incorrect number of arguments in SMP1 message") ++ } ++ g2a := mpis[0] ++ c2 := mpis[1] ++ d2 := mpis[2] ++ g3a := mpis[3] ++ c3 := mpis[4] ++ d3 := mpis[5] ++ h := sha256.New() ++ ++ r := new(big.Int).Exp(g, d2, p) ++ s := new(big.Int).Exp(g2a, c2, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ t := new(big.Int).SetBytes(hashMPIs(h, 1, r)) ++ if c2.Cmp(t) != 0 { ++ return errors.New("otr: ZKP c2 incorrect in SMP1 message") ++ } ++ r.Exp(g, d3, p) ++ s.Exp(g3a, c3, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ t.SetBytes(hashMPIs(h, 2, r)) ++ if c3.Cmp(t) != 0 { ++ return errors.New("otr: ZKP c3 incorrect in SMP1 message") ++ } ++ ++ c.smp.g2a = g2a ++ c.smp.g3a = g3a ++ return nil ++} ++ ++func (c *Conversation) generateSMP2() tlv { ++ var randBuf [16]byte ++ b2 := c.randMPI(randBuf[:]) ++ c.smp.b3 = c.randMPI(randBuf[:]) ++ r2 := c.randMPI(randBuf[:]) ++ r3 := c.randMPI(randBuf[:]) ++ r4 := c.randMPI(randBuf[:]) ++ r5 := c.randMPI(randBuf[:]) ++ r6 := c.randMPI(randBuf[:]) ++ ++ g2b := new(big.Int).Exp(g, b2, p) ++ g3b := new(big.Int).Exp(g, c.smp.b3, p) ++ ++ r := new(big.Int).Exp(g, r2, p) ++ h := sha256.New() ++ c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r)) ++ d2 := new(big.Int).Mul(b2, c2) ++ d2.Sub(r2, d2) ++ d2.Mod(d2, q) ++ if d2.Sign() < 0 { ++ d2.Add(d2, q) ++ } ++ ++ r.Exp(g, r3, p) ++ c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r)) ++ d3 := new(big.Int).Mul(c.smp.b3, c3) ++ d3.Sub(r3, d3) ++ d3.Mod(d3, q) ++ if d3.Sign() < 0 { ++ d3.Add(d3, q) ++ } ++ ++ c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p) ++ c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p) ++ c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p) ++ c.smp.qb = new(big.Int).Exp(g, r4, p) ++ r.Exp(c.smp.g2, c.smp.secret, p) ++ c.smp.qb.Mul(c.smp.qb, r) ++ c.smp.qb.Mod(c.smp.qb, p) ++ ++ s := new(big.Int) ++ s.Exp(c.smp.g2, r6, p) ++ r.Exp(g, r5, p) ++ s.Mul(r, s) ++ s.Mod(s, p) ++ r.Exp(c.smp.g3, r5, p) ++ cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s)) ++ ++ // D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q ++ ++ s.Mul(r4, cp) ++ r.Sub(r5, s) ++ d5 := new(big.Int).Mod(r, q) ++ if d5.Sign() < 0 { ++ d5.Add(d5, q) ++ } ++ ++ s.Mul(c.smp.secret, cp) ++ r.Sub(r6, s) ++ d6 := new(big.Int).Mod(r, q) ++ if d6.Sign() < 0 { ++ d6.Add(d6, q) ++ } ++ ++ var ret tlv ++ ret.typ = tlvTypeSMP2 ++ ret.data = appendU32(ret.data, 11) ++ ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6) ++ return ret ++} ++ ++func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) { ++ if len(mpis) != 11 { ++ err = errors.New("otr: incorrect number of arguments in SMP2 message") ++ return ++ } ++ g2b := mpis[0] ++ c2 := mpis[1] ++ d2 := mpis[2] ++ g3b := mpis[3] ++ c3 := mpis[4] ++ d3 := mpis[5] ++ pb := mpis[6] ++ qb := mpis[7] ++ cp := mpis[8] ++ d5 := mpis[9] ++ d6 := mpis[10] ++ h := sha256.New() ++ ++ r := new(big.Int).Exp(g, d2, p) ++ s := new(big.Int).Exp(g2b, c2, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ s.SetBytes(hashMPIs(h, 3, r)) ++ if c2.Cmp(s) != 0 { ++ err = errors.New("otr: ZKP c2 failed in SMP2 message") ++ return ++ } ++ ++ r.Exp(g, d3, p) ++ s.Exp(g3b, c3, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ s.SetBytes(hashMPIs(h, 4, r)) ++ if c3.Cmp(s) != 0 { ++ err = errors.New("otr: ZKP c3 failed in SMP2 message") ++ return ++ } ++ ++ c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p) ++ c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p) ++ ++ r.Exp(g, d5, p) ++ s.Exp(c.smp.g2, d6, p) ++ r.Mul(r, s) ++ s.Exp(qb, cp, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ ++ s.Exp(c.smp.g3, d5, p) ++ t := new(big.Int).Exp(pb, cp, p) ++ s.Mul(s, t) ++ s.Mod(s, p) ++ t.SetBytes(hashMPIs(h, 5, s, r)) ++ if cp.Cmp(t) != 0 { ++ err = errors.New("otr: ZKP cP failed in SMP2 message") ++ return ++ } ++ ++ var randBuf [16]byte ++ r4 := c.randMPI(randBuf[:]) ++ r5 := c.randMPI(randBuf[:]) ++ r6 := c.randMPI(randBuf[:]) ++ r7 := c.randMPI(randBuf[:]) ++ ++ pa := new(big.Int).Exp(c.smp.g3, r4, p) ++ r.Exp(c.smp.g2, c.smp.secret, p) ++ qa := new(big.Int).Exp(g, r4, p) ++ qa.Mul(qa, r) ++ qa.Mod(qa, p) ++ ++ r.Exp(g, r5, p) ++ s.Exp(c.smp.g2, r6, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ ++ s.Exp(c.smp.g3, r5, p) ++ cp.SetBytes(hashMPIs(h, 6, s, r)) ++ ++ r.Mul(r4, cp) ++ d5 = new(big.Int).Sub(r5, r) ++ d5.Mod(d5, q) ++ if d5.Sign() < 0 { ++ d5.Add(d5, q) ++ } ++ ++ r.Mul(c.smp.secret, cp) ++ d6 = new(big.Int).Sub(r6, r) ++ d6.Mod(d6, q) ++ if d6.Sign() < 0 { ++ d6.Add(d6, q) ++ } ++ ++ r.ModInverse(qb, p) ++ qaqb := new(big.Int).Mul(qa, r) ++ qaqb.Mod(qaqb, p) ++ ++ ra := new(big.Int).Exp(qaqb, c.smp.a3, p) ++ r.Exp(qaqb, r7, p) ++ s.Exp(g, r7, p) ++ cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r)) ++ ++ r.Mul(c.smp.a3, cr) ++ d7 := new(big.Int).Sub(r7, r) ++ d7.Mod(d7, q) ++ if d7.Sign() < 0 { ++ d7.Add(d7, q) ++ } ++ ++ c.smp.g3b = g3b ++ c.smp.qaqb = qaqb ++ ++ r.ModInverse(pb, p) ++ c.smp.papb = new(big.Int).Mul(pa, r) ++ c.smp.papb.Mod(c.smp.papb, p) ++ c.smp.ra = ra ++ ++ out.typ = tlvTypeSMP3 ++ out.data = appendU32(out.data, 8) ++ out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7) ++ return ++} ++ ++func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) { ++ if len(mpis) != 8 { ++ err = errors.New("otr: incorrect number of arguments in SMP3 message") ++ return ++ } ++ pa := mpis[0] ++ qa := mpis[1] ++ cp := mpis[2] ++ d5 := mpis[3] ++ d6 := mpis[4] ++ ra := mpis[5] ++ cr := mpis[6] ++ d7 := mpis[7] ++ h := sha256.New() ++ ++ r := new(big.Int).Exp(g, d5, p) ++ s := new(big.Int).Exp(c.smp.g2, d6, p) ++ r.Mul(r, s) ++ s.Exp(qa, cp, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ ++ s.Exp(c.smp.g3, d5, p) ++ t := new(big.Int).Exp(pa, cp, p) ++ s.Mul(s, t) ++ s.Mod(s, p) ++ t.SetBytes(hashMPIs(h, 6, s, r)) ++ if t.Cmp(cp) != 0 { ++ err = errors.New("otr: ZKP cP failed in SMP3 message") ++ return ++ } ++ ++ r.ModInverse(c.smp.qb, p) ++ qaqb := new(big.Int).Mul(qa, r) ++ qaqb.Mod(qaqb, p) ++ ++ r.Exp(qaqb, d7, p) ++ s.Exp(ra, cr, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ ++ s.Exp(g, d7, p) ++ t.Exp(c.smp.g3a, cr, p) ++ s.Mul(s, t) ++ s.Mod(s, p) ++ t.SetBytes(hashMPIs(h, 7, s, r)) ++ if t.Cmp(cr) != 0 { ++ err = errors.New("otr: ZKP cR failed in SMP3 message") ++ return ++ } ++ ++ var randBuf [16]byte ++ r7 := c.randMPI(randBuf[:]) ++ rb := new(big.Int).Exp(qaqb, c.smp.b3, p) ++ ++ r.Exp(qaqb, r7, p) ++ s.Exp(g, r7, p) ++ cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r)) ++ ++ r.Mul(c.smp.b3, cr) ++ d7 = new(big.Int).Sub(r7, r) ++ d7.Mod(d7, q) ++ if d7.Sign() < 0 { ++ d7.Add(d7, q) ++ } ++ ++ out.typ = tlvTypeSMP4 ++ out.data = appendU32(out.data, 3) ++ out.data = appendMPIs(out.data, rb, cr, d7) ++ ++ r.ModInverse(c.smp.pb, p) ++ r.Mul(pa, r) ++ r.Mod(r, p) ++ s.Exp(ra, c.smp.b3, p) ++ if r.Cmp(s) != 0 { ++ err = smpFailureError ++ } ++ ++ return ++} ++ ++func (c *Conversation) processSMP4(mpis []*big.Int) error { ++ if len(mpis) != 3 { ++ return errors.New("otr: incorrect number of arguments in SMP4 message") ++ } ++ rb := mpis[0] ++ cr := mpis[1] ++ d7 := mpis[2] ++ h := sha256.New() ++ ++ r := new(big.Int).Exp(c.smp.qaqb, d7, p) ++ s := new(big.Int).Exp(rb, cr, p) ++ r.Mul(r, s) ++ r.Mod(r, p) ++ ++ s.Exp(g, d7, p) ++ t := new(big.Int).Exp(c.smp.g3b, cr, p) ++ s.Mul(s, t) ++ s.Mod(s, p) ++ t.SetBytes(hashMPIs(h, 8, s, r)) ++ if t.Cmp(cr) != 0 { ++ return errors.New("otr: ZKP cR failed in SMP4 message") ++ } ++ ++ r.Exp(rb, c.smp.a3, p) ++ if r.Cmp(c.smp.papb) != 0 { ++ return smpFailureError ++ } ++ ++ return nil ++} ++ ++func (c *Conversation) generateSMPAbort() tlv { ++ return tlv{typ: tlvTypeSMPAbort} ++} ++ ++func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte { ++ if h != nil { ++ h.Reset() ++ } else { ++ h = sha256.New() ++ } ++ ++ h.Write([]byte{magic}) ++ for _, mpi := range mpis { ++ h.Write(appendMPI(nil, mpi)) ++ } ++ return h.Sum(nil) ++} +diff --git a/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go +new file mode 100644 +index 00000000000000..904b57e01d7a50 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go +@@ -0,0 +1,77 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC ++2898 / PKCS #5 v2.0. ++ ++A key derivation function is useful when encrypting data based on a password ++or any other not-fully-random data. It uses a pseudorandom function to derive ++a secure encryption key based on the password. ++ ++While v2.0 of the standard defines only one pseudorandom function to use, ++HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved ++Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To ++choose, you can pass the `New` functions from the different SHA packages to ++pbkdf2.Key. ++*/ ++package pbkdf2 // import "golang.org/x/crypto/pbkdf2" ++ ++import ( ++ "crypto/hmac" ++ "hash" ++) ++ ++// Key derives a key from the password, salt and iteration count, returning a ++// []byte of length keylen that can be used as cryptographic key. The key is ++// derived based on the method described as PBKDF2 with the HMAC variant using ++// the supplied hash function. ++// ++// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you ++// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by ++// doing: ++// ++// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) ++// ++// Remember to get a good random salt. At least 8 bytes is recommended by the ++// RFC. ++// ++// Using a higher iteration count will increase the cost of an exhaustive ++// search but will also make derivation proportionally slower. ++func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { ++ prf := hmac.New(h, password) ++ hashLen := prf.Size() ++ numBlocks := (keyLen + hashLen - 1) / hashLen ++ ++ var buf [4]byte ++ dk := make([]byte, 0, numBlocks*hashLen) ++ U := make([]byte, hashLen) ++ for block := 1; block <= numBlocks; block++ { ++ // N.B.: || means concatenation, ^ means XOR ++ // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter ++ // U_1 = PRF(password, salt || uint(i)) ++ prf.Reset() ++ prf.Write(salt) ++ buf[0] = byte(block >> 24) ++ buf[1] = byte(block >> 16) ++ buf[2] = byte(block >> 8) ++ buf[3] = byte(block) ++ prf.Write(buf[:4]) ++ dk = prf.Sum(dk) ++ T := dk[len(dk)-hashLen:] ++ copy(U, T) ++ ++ // U_n = PRF(password, U_(n-1)) ++ for n := 2; n <= iter; n++ { ++ prf.Reset() ++ prf.Write(U) ++ U = U[:0] ++ U = prf.Sum(U) ++ for x := range U { ++ T[x] ^= U[x] ++ } ++ } ++ } ++ return dk[:keyLen] ++} +diff --git a/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go +new file mode 100644 +index 00000000000000..f83cb69227371a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go +@@ -0,0 +1,176 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pbkdf2 ++ ++import ( ++ "bytes" ++ "crypto/sha1" ++ "crypto/sha256" ++ "hash" ++ "testing" ++) ++ ++type testVector struct { ++ password string ++ salt string ++ iter int ++ output []byte ++} ++ ++// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070 ++var sha1TestVectors = []testVector{ ++ { ++ "password", ++ "salt", ++ 1, ++ []byte{ ++ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, ++ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, ++ 0x2f, 0xe0, 0x37, 0xa6, ++ }, ++ }, ++ { ++ "password", ++ "salt", ++ 2, ++ []byte{ ++ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, ++ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, ++ 0xd8, 0xde, 0x89, 0x57, ++ }, ++ }, ++ { ++ "password", ++ "salt", ++ 4096, ++ []byte{ ++ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, ++ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, ++ 0x65, 0xa4, 0x29, 0xc1, ++ }, ++ }, ++ // // This one takes too long ++ // { ++ // "password", ++ // "salt", ++ // 16777216, ++ // []byte{ ++ // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, ++ // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, ++ // 0x26, 0x34, 0xe9, 0x84, ++ // }, ++ // }, ++ { ++ "passwordPASSWORDpassword", ++ "saltSALTsaltSALTsaltSALTsaltSALTsalt", ++ 4096, ++ []byte{ ++ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, ++ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, ++ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, ++ 0x38, ++ }, ++ }, ++ { ++ "pass\000word", ++ "sa\000lt", ++ 4096, ++ []byte{ ++ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, ++ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, ++ }, ++ }, ++} ++ ++// Test vectors from ++// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors ++var sha256TestVectors = []testVector{ ++ { ++ "password", ++ "salt", ++ 1, ++ []byte{ ++ 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, ++ 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, ++ 0xa8, 0x65, 0x48, 0xc9, ++ }, ++ }, ++ { ++ "password", ++ "salt", ++ 2, ++ []byte{ ++ 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, ++ 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, ++ 0x2a, 0x30, 0x3f, 0x8e, ++ }, ++ }, ++ { ++ "password", ++ "salt", ++ 4096, ++ []byte{ ++ 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, ++ 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, ++ 0x96, 0x28, 0x93, 0xa0, ++ }, ++ }, ++ { ++ "passwordPASSWORDpassword", ++ "saltSALTsaltSALTsaltSALTsaltSALTsalt", ++ 4096, ++ []byte{ ++ 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, ++ 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, ++ 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, ++ 0x1c, ++ }, ++ }, ++ { ++ "pass\000word", ++ "sa\000lt", ++ 4096, ++ []byte{ ++ 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, ++ 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87, ++ }, ++ }, ++} ++ ++func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) { ++ for i, v := range vectors { ++ o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h) ++ if !bytes.Equal(o, v.output) { ++ t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o) ++ } ++ } ++} ++ ++func TestWithHMACSHA1(t *testing.T) { ++ testHash(t, sha1.New, "SHA1", sha1TestVectors) ++} ++ ++func TestWithHMACSHA256(t *testing.T) { ++ testHash(t, sha256.New, "SHA256", sha256TestVectors) ++} ++ ++var sink uint8 ++ ++func benchmark(b *testing.B, h func() hash.Hash) { ++ password := make([]byte, h().Size()) ++ salt := make([]byte, 8) ++ for i := 0; i < b.N; i++ { ++ password = Key(password, salt, 4096, len(password), h) ++ } ++ sink += password[0] ++} ++ ++func BenchmarkHMACSHA1(b *testing.B) { ++ benchmark(b, sha1.New) ++} ++ ++func BenchmarkHMACSHA256(b *testing.B) { ++ benchmark(b, sha256.New) ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go +new file mode 100644 +index 00000000000000..233b8b62cc2708 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go +@@ -0,0 +1,50 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "errors" ++ "unicode/utf16" ++) ++ ++// bmpString returns s encoded in UCS-2 with a zero terminator. ++func bmpString(s string) ([]byte, error) { ++ // References: ++ // https://tools.ietf.org/html/rfc7292#appendix-B.1 ++ // https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane ++ // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes ++ // EncodeRune returns 0xfffd if the rune does not need special encoding ++ // - the above RFC provides the info that BMPStrings are NULL terminated. ++ ++ ret := make([]byte, 0, 2*len(s)+2) ++ ++ for _, r := range s { ++ if t, _ := utf16.EncodeRune(r); t != 0xfffd { ++ return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2") ++ } ++ ret = append(ret, byte(r/256), byte(r%256)) ++ } ++ ++ return append(ret, 0, 0), nil ++} ++ ++func decodeBMPString(bmpString []byte) (string, error) { ++ if len(bmpString)%2 != 0 { ++ return "", errors.New("pkcs12: odd-length BMP string") ++ } ++ ++ // strip terminator if present ++ if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { ++ bmpString = bmpString[:l-2] ++ } ++ ++ s := make([]uint16, 0, len(bmpString)/2) ++ for len(bmpString) > 0 { ++ s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) ++ bmpString = bmpString[2:] ++ } ++ ++ return string(utf16.Decode(s)), nil ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go +new file mode 100644 +index 00000000000000..7fca55f4e8b3a9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go +@@ -0,0 +1,63 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++) ++ ++var bmpStringTests = []struct { ++ in string ++ expectedHex string ++ shouldFail bool ++}{ ++ {"", "0000", false}, ++ // Example from https://tools.ietf.org/html/rfc7292#appendix-B. ++ {"Beavis", "0042006500610076006900730000", false}, ++ // Some characters from the "Letterlike Symbols Unicode block". ++ {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false}, ++ // any character outside the BMP should trigger an error. ++ {"\U0001f000 East wind (Mahjong)", "", true}, ++} ++ ++func TestBMPString(t *testing.T) { ++ for i, test := range bmpStringTests { ++ expected, err := hex.DecodeString(test.expectedHex) ++ if err != nil { ++ t.Fatalf("#%d: failed to decode expectation", i) ++ } ++ ++ out, err := bmpString(test.in) ++ if err == nil && test.shouldFail { ++ t.Errorf("#%d: expected to fail, but produced %x", i, out) ++ continue ++ } ++ ++ if err != nil && !test.shouldFail { ++ t.Errorf("#%d: failed unexpectedly: %s", i, err) ++ continue ++ } ++ ++ if !test.shouldFail { ++ if !bytes.Equal(out, expected) { ++ t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out) ++ continue ++ } ++ ++ roundTrip, err := decodeBMPString(out) ++ if err != nil { ++ t.Errorf("#%d: decoding output gave an error: %s", i, err) ++ continue ++ } ++ ++ if roundTrip != test.in { ++ t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in) ++ continue ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/crypto.go b/ms_mod/golang.org/x/crypto/pkcs12/crypto.go +new file mode 100644 +index 00000000000000..96f4a1a56ecacd +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/crypto.go +@@ -0,0 +1,131 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "bytes" ++ "crypto/cipher" ++ "crypto/des" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "errors" ++ ++ "golang.org/x/crypto/pkcs12/internal/rc2" ++) ++ ++var ( ++ oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) ++ oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6}) ++) ++ ++// pbeCipher is an abstraction of a PKCS#12 cipher. ++type pbeCipher interface { ++ // create returns a cipher.Block given a key. ++ create(key []byte) (cipher.Block, error) ++ // deriveKey returns a key derived from the given password and salt. ++ deriveKey(salt, password []byte, iterations int) []byte ++ // deriveKey returns an IV derived from the given password and salt. ++ deriveIV(salt, password []byte, iterations int) []byte ++} ++ ++type shaWithTripleDESCBC struct{} ++ ++func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) { ++ return des.NewTripleDESCipher(key) ++} ++ ++func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte { ++ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24) ++} ++ ++func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte { ++ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) ++} ++ ++type shaWith40BitRC2CBC struct{} ++ ++func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) { ++ return rc2.New(key, len(key)*8) ++} ++ ++func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { ++ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5) ++} ++ ++func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { ++ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) ++} ++ ++type pbeParams struct { ++ Salt []byte ++ Iterations int ++} ++ ++func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { ++ var cipherType pbeCipher ++ ++ switch { ++ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): ++ cipherType = shaWithTripleDESCBC{} ++ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): ++ cipherType = shaWith40BitRC2CBC{} ++ default: ++ return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported") ++ } ++ ++ var params pbeParams ++ if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { ++ return nil, 0, err ++ } ++ ++ key := cipherType.deriveKey(params.Salt, password, params.Iterations) ++ iv := cipherType.deriveIV(params.Salt, password, params.Iterations) ++ ++ block, err := cipherType.create(key) ++ if err != nil { ++ return nil, 0, err ++ } ++ ++ return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil ++} ++ ++func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) { ++ cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password) ++ if err != nil { ++ return nil, err ++ } ++ ++ encrypted := info.Data() ++ if len(encrypted) == 0 { ++ return nil, errors.New("pkcs12: empty encrypted data") ++ } ++ if len(encrypted)%blockSize != 0 { ++ return nil, errors.New("pkcs12: input is not a multiple of the block size") ++ } ++ decrypted = make([]byte, len(encrypted)) ++ cbc.CryptBlocks(decrypted, encrypted) ++ ++ psLen := int(decrypted[len(decrypted)-1]) ++ if psLen == 0 || psLen > blockSize { ++ return nil, ErrDecryption ++ } ++ ++ if len(decrypted) < psLen { ++ return nil, ErrDecryption ++ } ++ ps := decrypted[len(decrypted)-psLen:] ++ decrypted = decrypted[:len(decrypted)-psLen] ++ if !bytes.Equal(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) { ++ return nil, ErrDecryption ++ } ++ ++ return ++} ++ ++// decryptable abstracts an object that contains ciphertext. ++type decryptable interface { ++ Algorithm() pkix.AlgorithmIdentifier ++ Data() []byte ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go b/ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go +new file mode 100644 +index 00000000000000..eb4dae8fceba54 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go +@@ -0,0 +1,125 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "bytes" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "testing" ++) ++ ++var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) ++ ++func TestPbDecrypterFor(t *testing.T) { ++ params, _ := asn1.Marshal(pbeParams{ ++ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, ++ Iterations: 2048, ++ }) ++ alg := pkix.AlgorithmIdentifier{ ++ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), ++ Parameters: asn1.RawValue{ ++ FullBytes: params, ++ }, ++ } ++ ++ pass, _ := bmpString("Sesame open") ++ ++ _, _, err := pbDecrypterFor(alg, pass) ++ if _, ok := err.(NotImplementedError); !ok { ++ t.Errorf("expected not implemented error, got: %T %s", err, err) ++ } ++ ++ alg.Algorithm = sha1WithTripleDES ++ cbc, blockSize, err := pbDecrypterFor(alg, pass) ++ if err != nil { ++ t.Errorf("unexpected error from pbDecrypterFor %v", err) ++ } ++ if blockSize != 8 { ++ t.Errorf("unexpected block size %d, wanted 8", blockSize) ++ } ++ ++ plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8} ++ expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247} ++ ciphertext := make([]byte, len(plaintext)) ++ cbc.CryptBlocks(ciphertext, plaintext) ++ ++ if bytes.Compare(ciphertext, expectedCiphertext) != 0 { ++ t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext) ++ } ++} ++ ++var pbDecryptTests = []struct { ++ in []byte ++ expected []byte ++ expectedError error ++}{ ++ { ++ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes ++ []byte("A secret!"), ++ nil, ++ }, ++ { ++ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes ++ []byte("A secret"), ++ nil, ++ }, ++ { ++ []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect ++ nil, ++ ErrDecryption, ++ }, ++ { ++ []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ] ++ nil, ++ ErrDecryption, ++ }, ++} ++ ++func TestPbDecrypt(t *testing.T) { ++ for i, test := range pbDecryptTests { ++ decryptable := testDecryptable{ ++ data: test.in, ++ algorithm: pkix.AlgorithmIdentifier{ ++ Algorithm: sha1WithTripleDES, ++ Parameters: pbeParams{ ++ Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"), ++ Iterations: 4096, ++ }.RawASN1(), ++ }, ++ } ++ password, _ := bmpString("sesame") ++ ++ plaintext, err := pbDecrypt(decryptable, password) ++ if err != test.expectedError { ++ t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError) ++ continue ++ } ++ ++ if !bytes.Equal(plaintext, test.expected) { ++ t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected) ++ } ++ } ++} ++ ++type testDecryptable struct { ++ data []byte ++ algorithm pkix.AlgorithmIdentifier ++} ++ ++func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm } ++func (d testDecryptable) Data() []byte { return d.data } ++ ++func (params pbeParams) RawASN1() (raw asn1.RawValue) { ++ asn1Bytes, err := asn1.Marshal(params) ++ if err != nil { ++ panic(err) ++ } ++ _, err = asn1.Unmarshal(asn1Bytes, &raw) ++ if err != nil { ++ panic(err) ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/errors.go b/ms_mod/golang.org/x/crypto/pkcs12/errors.go +new file mode 100644 +index 00000000000000..7377ce6fb2b814 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/errors.go +@@ -0,0 +1,23 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import "errors" ++ ++var ( ++ // ErrDecryption represents a failure to decrypt the input. ++ ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding") ++ ++ // ErrIncorrectPassword is returned when an incorrect password is detected. ++ // Usually, P12/PFX data is signed to be able to verify the password. ++ ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect") ++) ++ ++// NotImplementedError indicates that the input is not currently supported. ++type NotImplementedError string ++ ++func (e NotImplementedError) Error() string { ++ return "pkcs12: " + string(e) ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go +new file mode 100644 +index 00000000000000..3347f338c18607 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go +@@ -0,0 +1,27 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package rc2 ++ ++import ( ++ "testing" ++) ++ ++func BenchmarkEncrypt(b *testing.B) { ++ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) ++ b.ResetTimer() ++ var src [8]byte ++ for i := 0; i < b.N; i++ { ++ r.Encrypt(src[:], src[:]) ++ } ++} ++ ++func BenchmarkDecrypt(b *testing.B) { ++ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) ++ b.ResetTimer() ++ var src [8]byte ++ for i := 0; i < b.N; i++ { ++ r.Decrypt(src[:], src[:]) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go +new file mode 100644 +index 00000000000000..05de9cc2cdcc59 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go +@@ -0,0 +1,268 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package rc2 implements the RC2 cipher ++/* ++https://www.ietf.org/rfc/rfc2268.txt ++http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf ++ ++This code is licensed under the MIT license. ++*/ ++package rc2 ++ ++import ( ++ "crypto/cipher" ++ "encoding/binary" ++ "math/bits" ++) ++ ++// The rc2 block size in bytes ++const BlockSize = 8 ++ ++type rc2Cipher struct { ++ k [64]uint16 ++} ++ ++// New returns a new rc2 cipher with the given key and effective key length t1 ++func New(key []byte, t1 int) (cipher.Block, error) { ++ // TODO(dgryski): error checking for key length ++ return &rc2Cipher{ ++ k: expandKey(key, t1), ++ }, nil ++} ++ ++func (*rc2Cipher) BlockSize() int { return BlockSize } ++ ++var piTable = [256]byte{ ++ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, ++ 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, ++ 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, ++ 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, ++ 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, ++ 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, ++ 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, ++ 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, ++ 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, ++ 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, ++ 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, ++ 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, ++ 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, ++ 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, ++ 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, ++ 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, ++} ++ ++func expandKey(key []byte, t1 int) [64]uint16 { ++ ++ l := make([]byte, 128) ++ copy(l, key) ++ ++ var t = len(key) ++ var t8 = (t1 + 7) / 8 ++ var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8)))) ++ ++ for i := len(key); i < 128; i++ { ++ l[i] = piTable[l[i-1]+l[uint8(i-t)]] ++ } ++ ++ l[128-t8] = piTable[l[128-t8]&tm] ++ ++ for i := 127 - t8; i >= 0; i-- { ++ l[i] = piTable[l[i+1]^l[i+t8]] ++ } ++ ++ var k [64]uint16 ++ ++ for i := range k { ++ k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256 ++ } ++ ++ return k ++} ++ ++func (c *rc2Cipher) Encrypt(dst, src []byte) { ++ ++ r0 := binary.LittleEndian.Uint16(src[0:]) ++ r1 := binary.LittleEndian.Uint16(src[2:]) ++ r2 := binary.LittleEndian.Uint16(src[4:]) ++ r3 := binary.LittleEndian.Uint16(src[6:]) ++ ++ var j int ++ ++ for j <= 16 { ++ // mix r0 ++ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) ++ r0 = bits.RotateLeft16(r0, 1) ++ j++ ++ ++ // mix r1 ++ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) ++ r1 = bits.RotateLeft16(r1, 2) ++ j++ ++ ++ // mix r2 ++ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) ++ r2 = bits.RotateLeft16(r2, 3) ++ j++ ++ ++ // mix r3 ++ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) ++ r3 = bits.RotateLeft16(r3, 5) ++ j++ ++ ++ } ++ ++ r0 = r0 + c.k[r3&63] ++ r1 = r1 + c.k[r0&63] ++ r2 = r2 + c.k[r1&63] ++ r3 = r3 + c.k[r2&63] ++ ++ for j <= 40 { ++ // mix r0 ++ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) ++ r0 = bits.RotateLeft16(r0, 1) ++ j++ ++ ++ // mix r1 ++ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) ++ r1 = bits.RotateLeft16(r1, 2) ++ j++ ++ ++ // mix r2 ++ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) ++ r2 = bits.RotateLeft16(r2, 3) ++ j++ ++ ++ // mix r3 ++ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) ++ r3 = bits.RotateLeft16(r3, 5) ++ j++ ++ ++ } ++ ++ r0 = r0 + c.k[r3&63] ++ r1 = r1 + c.k[r0&63] ++ r2 = r2 + c.k[r1&63] ++ r3 = r3 + c.k[r2&63] ++ ++ for j <= 60 { ++ // mix r0 ++ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) ++ r0 = bits.RotateLeft16(r0, 1) ++ j++ ++ ++ // mix r1 ++ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) ++ r1 = bits.RotateLeft16(r1, 2) ++ j++ ++ ++ // mix r2 ++ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) ++ r2 = bits.RotateLeft16(r2, 3) ++ j++ ++ ++ // mix r3 ++ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) ++ r3 = bits.RotateLeft16(r3, 5) ++ j++ ++ } ++ ++ binary.LittleEndian.PutUint16(dst[0:], r0) ++ binary.LittleEndian.PutUint16(dst[2:], r1) ++ binary.LittleEndian.PutUint16(dst[4:], r2) ++ binary.LittleEndian.PutUint16(dst[6:], r3) ++} ++ ++func (c *rc2Cipher) Decrypt(dst, src []byte) { ++ ++ r0 := binary.LittleEndian.Uint16(src[0:]) ++ r1 := binary.LittleEndian.Uint16(src[2:]) ++ r2 := binary.LittleEndian.Uint16(src[4:]) ++ r3 := binary.LittleEndian.Uint16(src[6:]) ++ ++ j := 63 ++ ++ for j >= 44 { ++ // unmix r3 ++ r3 = bits.RotateLeft16(r3, 16-5) ++ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) ++ j-- ++ ++ // unmix r2 ++ r2 = bits.RotateLeft16(r2, 16-3) ++ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) ++ j-- ++ ++ // unmix r1 ++ r1 = bits.RotateLeft16(r1, 16-2) ++ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) ++ j-- ++ ++ // unmix r0 ++ r0 = bits.RotateLeft16(r0, 16-1) ++ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) ++ j-- ++ } ++ ++ r3 = r3 - c.k[r2&63] ++ r2 = r2 - c.k[r1&63] ++ r1 = r1 - c.k[r0&63] ++ r0 = r0 - c.k[r3&63] ++ ++ for j >= 20 { ++ // unmix r3 ++ r3 = bits.RotateLeft16(r3, 16-5) ++ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) ++ j-- ++ ++ // unmix r2 ++ r2 = bits.RotateLeft16(r2, 16-3) ++ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) ++ j-- ++ ++ // unmix r1 ++ r1 = bits.RotateLeft16(r1, 16-2) ++ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) ++ j-- ++ ++ // unmix r0 ++ r0 = bits.RotateLeft16(r0, 16-1) ++ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) ++ j-- ++ ++ } ++ ++ r3 = r3 - c.k[r2&63] ++ r2 = r2 - c.k[r1&63] ++ r1 = r1 - c.k[r0&63] ++ r0 = r0 - c.k[r3&63] ++ ++ for j >= 0 { ++ // unmix r3 ++ r3 = bits.RotateLeft16(r3, 16-5) ++ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) ++ j-- ++ ++ // unmix r2 ++ r2 = bits.RotateLeft16(r2, 16-3) ++ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) ++ j-- ++ ++ // unmix r1 ++ r1 = bits.RotateLeft16(r1, 16-2) ++ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) ++ j-- ++ ++ // unmix r0 ++ r0 = bits.RotateLeft16(r0, 16-1) ++ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) ++ j-- ++ ++ } ++ ++ binary.LittleEndian.PutUint16(dst[0:], r0) ++ binary.LittleEndian.PutUint16(dst[2:], r1) ++ binary.LittleEndian.PutUint16(dst[4:], r2) ++ binary.LittleEndian.PutUint16(dst[6:], r3) ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go +new file mode 100644 +index 00000000000000..51a7efe506289f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go +@@ -0,0 +1,92 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package rc2 ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++) ++ ++func TestEncryptDecrypt(t *testing.T) { ++ // TODO(dgryski): add the rest of the test vectors from the RFC ++ var tests = []struct { ++ key string ++ plain string ++ cipher string ++ t1 int ++ }{ ++ { ++ "0000000000000000", ++ "0000000000000000", ++ "ebb773f993278eff", ++ 63, ++ }, ++ { ++ "ffffffffffffffff", ++ "ffffffffffffffff", ++ "278b27e42e2f0d49", ++ 64, ++ }, ++ { ++ "3000000000000000", ++ "1000000000000001", ++ "30649edf9be7d2c2", ++ 64, ++ }, ++ { ++ "88", ++ "0000000000000000", ++ "61a8a244adacccf0", ++ 64, ++ }, ++ { ++ "88bca90e90875a", ++ "0000000000000000", ++ "6ccf4308974c267f", ++ 64, ++ }, ++ { ++ "88bca90e90875a7f0f79c384627bafb2", ++ "0000000000000000", ++ "1a807d272bbe5db1", ++ 64, ++ }, ++ { ++ "88bca90e90875a7f0f79c384627bafb2", ++ "0000000000000000", ++ "2269552ab0f85ca6", ++ 128, ++ }, ++ { ++ "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", ++ "0000000000000000", ++ "5b78d3a43dfff1f1", ++ 129, ++ }, ++ } ++ ++ for _, tt := range tests { ++ k, _ := hex.DecodeString(tt.key) ++ p, _ := hex.DecodeString(tt.plain) ++ c, _ := hex.DecodeString(tt.cipher) ++ ++ b, _ := New(k, tt.t1) ++ ++ var dst [8]byte ++ ++ b.Encrypt(dst[:], p) ++ ++ if !bytes.Equal(dst[:], c) { ++ t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c) ++ } ++ ++ b.Decrypt(dst[:], c) ++ ++ if !bytes.Equal(dst[:], p) { ++ t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/mac.go b/ms_mod/golang.org/x/crypto/pkcs12/mac.go +new file mode 100644 +index 00000000000000..5f38aa7de83ce0 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/mac.go +@@ -0,0 +1,45 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "crypto/hmac" ++ "crypto/sha1" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++) ++ ++type macData struct { ++ Mac digestInfo ++ MacSalt []byte ++ Iterations int `asn1:"optional,default:1"` ++} ++ ++// from PKCS#7: ++type digestInfo struct { ++ Algorithm pkix.AlgorithmIdentifier ++ Digest []byte ++} ++ ++var ( ++ oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) ++) ++ ++func verifyMac(macData *macData, message, password []byte) error { ++ if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) { ++ return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String()) ++ } ++ ++ key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20) ++ ++ mac := hmac.New(sha1.New, key) ++ mac.Write(message) ++ expectedMAC := mac.Sum(nil) ++ ++ if !hmac.Equal(macData.Mac.Digest, expectedMAC) { ++ return ErrIncorrectPassword ++ } ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/mac_test.go b/ms_mod/golang.org/x/crypto/pkcs12/mac_test.go +new file mode 100644 +index 00000000000000..1ed4ff21e14b39 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/mac_test.go +@@ -0,0 +1,42 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "encoding/asn1" ++ "testing" ++) ++ ++func TestVerifyMac(t *testing.T) { ++ td := macData{ ++ Mac: digestInfo{ ++ Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93}, ++ }, ++ MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, ++ Iterations: 2048, ++ } ++ ++ message := []byte{11, 12, 13, 14, 15} ++ password, _ := bmpString("") ++ ++ td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3}) ++ err := verifyMac(&td, message, password) ++ if _, ok := err.(NotImplementedError); !ok { ++ t.Errorf("err: %v", err) ++ } ++ ++ td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) ++ err = verifyMac(&td, message, password) ++ if err != ErrIncorrectPassword { ++ t.Errorf("Expected incorrect password, got err: %v", err) ++ } ++ ++ password, _ = bmpString("Sesame open") ++ err = verifyMac(&td, message, password) ++ if err != nil { ++ t.Errorf("err: %v", err) ++ } ++ ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go +new file mode 100644 +index 00000000000000..5c419d41e32c2a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go +@@ -0,0 +1,170 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "bytes" ++ "crypto/sha1" ++ "math/big" ++) ++ ++var ( ++ one = big.NewInt(1) ++) ++ ++// sha1Sum returns the SHA-1 hash of in. ++func sha1Sum(in []byte) []byte { ++ sum := sha1.Sum(in) ++ return sum[:] ++} ++ ++// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of ++// repeats of pattern. ++func fillWithRepeats(pattern []byte, v int) []byte { ++ if len(pattern) == 0 { ++ return nil ++ } ++ outputLen := v * ((len(pattern) + v - 1) / v) ++ return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen] ++} ++ ++func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) { ++ // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments ++ ++ // Let H be a hash function built around a compression function f: ++ ++ // Z_2^u x Z_2^v -> Z_2^u ++ ++ // (that is, H has a chaining variable and output of length u bits, and ++ // the message input to the compression function of H is v bits). The ++ // values for u and v are as follows: ++ ++ // HASH FUNCTION VALUE u VALUE v ++ // MD2, MD5 128 512 ++ // SHA-1 160 512 ++ // SHA-224 224 512 ++ // SHA-256 256 512 ++ // SHA-384 384 1024 ++ // SHA-512 512 1024 ++ // SHA-512/224 224 1024 ++ // SHA-512/256 256 1024 ++ ++ // Furthermore, let r be the iteration count. ++ ++ // We assume here that u and v are both multiples of 8, as are the ++ // lengths of the password and salt strings (which we denote by p and s, ++ // respectively) and the number n of pseudorandom bits required. In ++ // addition, u and v are of course non-zero. ++ ++ // For information on security considerations for MD5 [19], see [25] and ++ // [1], and on those for MD2, see [18]. ++ ++ // The following procedure can be used to produce pseudorandom bits for ++ // a particular "purpose" that is identified by a byte called "ID". ++ // This standard specifies 3 different values for the ID byte: ++ ++ // 1. If ID=1, then the pseudorandom bits being produced are to be used ++ // as key material for performing encryption or decryption. ++ ++ // 2. If ID=2, then the pseudorandom bits being produced are to be used ++ // as an IV (Initial Value) for encryption or decryption. ++ ++ // 3. If ID=3, then the pseudorandom bits being produced are to be used ++ // as an integrity key for MACing. ++ ++ // 1. Construct a string, D (the "diversifier"), by concatenating v/8 ++ // copies of ID. ++ var D []byte ++ for i := 0; i < v; i++ { ++ D = append(D, ID) ++ } ++ ++ // 2. Concatenate copies of the salt together to create a string S of ++ // length v(ceiling(s/v)) bits (the final copy of the salt may be ++ // truncated to create S). Note that if the salt is the empty ++ // string, then so is S. ++ ++ S := fillWithRepeats(salt, v) ++ ++ // 3. Concatenate copies of the password together to create a string P ++ // of length v(ceiling(p/v)) bits (the final copy of the password ++ // may be truncated to create P). Note that if the password is the ++ // empty string, then so is P. ++ ++ P := fillWithRepeats(password, v) ++ ++ // 4. Set I=S||P to be the concatenation of S and P. ++ I := append(S, P...) ++ ++ // 5. Set c=ceiling(n/u). ++ c := (size + u - 1) / u ++ ++ // 6. For i=1, 2, ..., c, do the following: ++ A := make([]byte, c*20) ++ var IjBuf []byte ++ for i := 0; i < c; i++ { ++ // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1, ++ // H(H(H(... H(D||I)))) ++ Ai := hash(append(D, I...)) ++ for j := 1; j < r; j++ { ++ Ai = hash(Ai) ++ } ++ copy(A[i*20:], Ai[:]) ++ ++ if i < c-1 { // skip on last iteration ++ // B. Concatenate copies of Ai to create a string B of length v ++ // bits (the final copy of Ai may be truncated to create B). ++ var B []byte ++ for len(B) < v { ++ B = append(B, Ai[:]...) ++ } ++ B = B[:v] ++ ++ // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit ++ // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by ++ // setting I_j=(I_j+B+1) mod 2^v for each j. ++ { ++ Bbi := new(big.Int).SetBytes(B) ++ Ij := new(big.Int) ++ ++ for j := 0; j < len(I)/v; j++ { ++ Ij.SetBytes(I[j*v : (j+1)*v]) ++ Ij.Add(Ij, Bbi) ++ Ij.Add(Ij, one) ++ Ijb := Ij.Bytes() ++ // We expect Ijb to be exactly v bytes, ++ // if it is longer or shorter we must ++ // adjust it accordingly. ++ if len(Ijb) > v { ++ Ijb = Ijb[len(Ijb)-v:] ++ } ++ if len(Ijb) < v { ++ if IjBuf == nil { ++ IjBuf = make([]byte, v) ++ } ++ bytesShort := v - len(Ijb) ++ for i := 0; i < bytesShort; i++ { ++ IjBuf[i] = 0 ++ } ++ copy(IjBuf[bytesShort:], Ijb) ++ Ijb = IjBuf ++ } ++ copy(I[j*v:(j+1)*v], Ijb) ++ } ++ } ++ } ++ } ++ // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom ++ // bit string, A. ++ ++ // 8. Use the first n bits of A as the output of this entire process. ++ return A[:size] ++ ++ // If the above process is being used to generate a DES key, the process ++ // should be used to create 64 random bits, and the key's parity bits ++ // should be set after the 64 bits have been produced. Similar concerns ++ // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any ++ // similar keys with parity bits "built into them". ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go +new file mode 100644 +index 00000000000000..262037d7ebaac9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go +@@ -0,0 +1,34 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) { ++ cipherInfo := shaWithTripleDESCBC{} ++ ++ salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff") ++ password, _ := bmpString("sesame") ++ key := cipherInfo.deriveKey(salt, password, 2048) ++ ++ if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 { ++ t.Fatalf("expected key '%x', but found '%x'", expected, key) ++ } ++} ++ ++func TestThatPBKDFHandlesLeadingZeros(t *testing.T) { ++ // This test triggers a case where I_j (in step 6C) ends up with leading zero ++ // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int). ++ // This was previously causing bug whereby certain inputs would break the ++ // derivation and produce the wrong output. ++ key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24) ++ expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1") ++ if bytes.Compare(key, expected) != 0 { ++ t.Fatalf("expected key '%x', but found '%x'", expected, key) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go +new file mode 100644 +index 00000000000000..3a89bdb3e393bb +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go +@@ -0,0 +1,360 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package pkcs12 implements some of PKCS#12. ++// ++// This implementation is distilled from https://tools.ietf.org/html/rfc7292 ++// and referenced documents. It is intended for decoding P12/PFX-stored ++// certificates and keys for use with the crypto/tls package. ++// ++// This package is frozen. If it's missing functionality you need, consider ++// an alternative like software.sslmate.com/src/go-pkcs12. ++package pkcs12 ++ ++import ( ++ "crypto/ecdsa" ++ "crypto/rsa" ++ "crypto/x509" ++ "crypto/x509/pkix" ++ "encoding/asn1" ++ "encoding/hex" ++ "encoding/pem" ++ "errors" ++) ++ ++var ( ++ oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1}) ++ oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6}) ++ ++ oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) ++ oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) ++ oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) ++ ++ errUnknownAttributeOID = errors.New("pkcs12: unknown attribute OID") ++) ++ ++type pfxPdu struct { ++ Version int ++ AuthSafe contentInfo ++ MacData macData `asn1:"optional"` ++} ++ ++type contentInfo struct { ++ ContentType asn1.ObjectIdentifier ++ Content asn1.RawValue `asn1:"tag:0,explicit,optional"` ++} ++ ++type encryptedData struct { ++ Version int ++ EncryptedContentInfo encryptedContentInfo ++} ++ ++type encryptedContentInfo struct { ++ ContentType asn1.ObjectIdentifier ++ ContentEncryptionAlgorithm pkix.AlgorithmIdentifier ++ EncryptedContent []byte `asn1:"tag:0,optional"` ++} ++ ++func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier { ++ return i.ContentEncryptionAlgorithm ++} ++ ++func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent } ++ ++type safeBag struct { ++ Id asn1.ObjectIdentifier ++ Value asn1.RawValue `asn1:"tag:0,explicit"` ++ Attributes []pkcs12Attribute `asn1:"set,optional"` ++} ++ ++type pkcs12Attribute struct { ++ Id asn1.ObjectIdentifier ++ Value asn1.RawValue `asn1:"set"` ++} ++ ++type encryptedPrivateKeyInfo struct { ++ AlgorithmIdentifier pkix.AlgorithmIdentifier ++ EncryptedData []byte ++} ++ ++func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier { ++ return i.AlgorithmIdentifier ++} ++ ++func (i encryptedPrivateKeyInfo) Data() []byte { ++ return i.EncryptedData ++} ++ ++// PEM block types ++const ( ++ certificateType = "CERTIFICATE" ++ privateKeyType = "PRIVATE KEY" ++) ++ ++// unmarshal calls asn1.Unmarshal, but also returns an error if there is any ++// trailing data after unmarshaling. ++func unmarshal(in []byte, out interface{}) error { ++ trailing, err := asn1.Unmarshal(in, out) ++ if err != nil { ++ return err ++ } ++ if len(trailing) != 0 { ++ return errors.New("pkcs12: trailing data found") ++ } ++ return nil ++} ++ ++// ToPEM converts all "safe bags" contained in pfxData to PEM blocks. ++// Unknown attributes are discarded. ++// ++// Note that although the returned PEM blocks for private keys have type ++// "PRIVATE KEY", the bytes are not encoded according to PKCS #8, but according ++// to PKCS #1 for RSA keys and SEC 1 for ECDSA keys. ++func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { ++ encodedPassword, err := bmpString(password) ++ if err != nil { ++ return nil, ErrIncorrectPassword ++ } ++ ++ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) ++ ++ if err != nil { ++ return nil, err ++ } ++ ++ blocks := make([]*pem.Block, 0, len(bags)) ++ for _, bag := range bags { ++ block, err := convertBag(&bag, encodedPassword) ++ if err != nil { ++ return nil, err ++ } ++ blocks = append(blocks, block) ++ } ++ ++ return blocks, nil ++} ++ ++func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { ++ block := &pem.Block{ ++ Headers: make(map[string]string), ++ } ++ ++ for _, attribute := range bag.Attributes { ++ k, v, err := convertAttribute(&attribute) ++ if err == errUnknownAttributeOID { ++ continue ++ } ++ if err != nil { ++ return nil, err ++ } ++ block.Headers[k] = v ++ } ++ ++ switch { ++ case bag.Id.Equal(oidCertBag): ++ block.Type = certificateType ++ certsData, err := decodeCertBag(bag.Value.Bytes) ++ if err != nil { ++ return nil, err ++ } ++ block.Bytes = certsData ++ case bag.Id.Equal(oidPKCS8ShroundedKeyBag): ++ block.Type = privateKeyType ++ ++ key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password) ++ if err != nil { ++ return nil, err ++ } ++ ++ switch key := key.(type) { ++ case *rsa.PrivateKey: ++ block.Bytes = x509.MarshalPKCS1PrivateKey(key) ++ case *ecdsa.PrivateKey: ++ block.Bytes, err = x509.MarshalECPrivateKey(key) ++ if err != nil { ++ return nil, err ++ } ++ default: ++ return nil, errors.New("found unknown private key type in PKCS#8 wrapping") ++ } ++ default: ++ return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String()) ++ } ++ return block, nil ++} ++ ++func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) { ++ isString := false ++ ++ switch { ++ case attribute.Id.Equal(oidFriendlyName): ++ key = "friendlyName" ++ isString = true ++ case attribute.Id.Equal(oidLocalKeyID): ++ key = "localKeyId" ++ case attribute.Id.Equal(oidMicrosoftCSPName): ++ // This key is chosen to match OpenSSL. ++ key = "Microsoft CSP Name" ++ isString = true ++ default: ++ return "", "", errUnknownAttributeOID ++ } ++ ++ if isString { ++ if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil { ++ return "", "", err ++ } ++ if value, err = decodeBMPString(attribute.Value.Bytes); err != nil { ++ return "", "", err ++ } ++ } else { ++ var id []byte ++ if err := unmarshal(attribute.Value.Bytes, &id); err != nil { ++ return "", "", err ++ } ++ value = hex.EncodeToString(id) ++ } ++ ++ return key, value, nil ++} ++ ++// Decode extracts a certificate and private key from pfxData. This function ++// assumes that there is only one certificate and only one private key in the ++// pfxData; if there are more use ToPEM instead. ++func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) { ++ encodedPassword, err := bmpString(password) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ if len(bags) != 2 { ++ err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU") ++ return ++ } ++ ++ for _, bag := range bags { ++ switch { ++ case bag.Id.Equal(oidCertBag): ++ if certificate != nil { ++ err = errors.New("pkcs12: expected exactly one certificate bag") ++ } ++ ++ certsData, err := decodeCertBag(bag.Value.Bytes) ++ if err != nil { ++ return nil, nil, err ++ } ++ certs, err := x509.ParseCertificates(certsData) ++ if err != nil { ++ return nil, nil, err ++ } ++ if len(certs) != 1 { ++ err = errors.New("pkcs12: expected exactly one certificate in the certBag") ++ return nil, nil, err ++ } ++ certificate = certs[0] ++ ++ case bag.Id.Equal(oidPKCS8ShroundedKeyBag): ++ if privateKey != nil { ++ err = errors.New("pkcs12: expected exactly one key bag") ++ return nil, nil, err ++ } ++ ++ if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { ++ return nil, nil, err ++ } ++ } ++ } ++ ++ if certificate == nil { ++ return nil, nil, errors.New("pkcs12: certificate missing") ++ } ++ if privateKey == nil { ++ return nil, nil, errors.New("pkcs12: private key missing") ++ } ++ ++ return ++} ++ ++func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) { ++ pfx := new(pfxPdu) ++ if err := unmarshal(p12Data, pfx); err != nil { ++ return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error()) ++ } ++ ++ if pfx.Version != 3 { ++ return nil, nil, NotImplementedError("can only decode v3 PFX PDU's") ++ } ++ ++ if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) { ++ return nil, nil, NotImplementedError("only password-protected PFX is implemented") ++ } ++ ++ // unmarshal the explicit bytes in the content for type 'data' ++ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil { ++ return nil, nil, err ++ } ++ ++ if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 { ++ return nil, nil, errors.New("pkcs12: no MAC in data") ++ } ++ ++ if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil { ++ if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 { ++ // some implementations use an empty byte array ++ // for the empty string password try one more ++ // time with empty-empty password ++ password = nil ++ err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password) ++ } ++ if err != nil { ++ return nil, nil, err ++ } ++ } ++ ++ var authenticatedSafe []contentInfo ++ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil { ++ return nil, nil, err ++ } ++ ++ if len(authenticatedSafe) != 2 { ++ return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe") ++ } ++ ++ for _, ci := range authenticatedSafe { ++ var data []byte ++ ++ switch { ++ case ci.ContentType.Equal(oidDataContentType): ++ if err := unmarshal(ci.Content.Bytes, &data); err != nil { ++ return nil, nil, err ++ } ++ case ci.ContentType.Equal(oidEncryptedDataContentType): ++ var encryptedData encryptedData ++ if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil { ++ return nil, nil, err ++ } ++ if encryptedData.Version != 0 { ++ return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported") ++ } ++ if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil { ++ return nil, nil, err ++ } ++ default: ++ return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe") ++ } ++ ++ var safeContents []safeBag ++ if err := unmarshal(data, &safeContents); err != nil { ++ return nil, nil, err ++ } ++ bags = append(bags, safeContents...) ++ } ++ ++ return bags, password, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go +new file mode 100644 +index 00000000000000..68476a822fbc7a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go +@@ -0,0 +1,141 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "crypto/rsa" ++ "crypto/tls" ++ "encoding/base64" ++ "encoding/pem" ++ "testing" ++) ++ ++func TestPfx(t *testing.T) { ++ for commonName, base64P12 := range testdata { ++ p12, _ := base64.StdEncoding.DecodeString(base64P12) ++ ++ priv, cert, err := Decode(p12, "") ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if err := priv.(*rsa.PrivateKey).Validate(); err != nil { ++ t.Errorf("error while validating private key: %v", err) ++ } ++ ++ if cert.Subject.CommonName != commonName { ++ t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName) ++ } ++ } ++} ++ ++func TestPEM(t *testing.T) { ++ for commonName, base64P12 := range testdata { ++ p12, _ := base64.StdEncoding.DecodeString(base64P12) ++ ++ blocks, err := ToPEM(p12, "") ++ if err != nil { ++ t.Fatalf("error while converting to PEM: %s", err) ++ } ++ ++ var pemData []byte ++ for _, b := range blocks { ++ pemData = append(pemData, pem.EncodeToMemory(b)...) ++ } ++ ++ cert, err := tls.X509KeyPair(pemData, pemData) ++ if err != nil { ++ t.Errorf("err while converting to key pair: %v", err) ++ } ++ config := tls.Config{ ++ Certificates: []tls.Certificate{cert}, ++ } ++ config.BuildNameToCertificate() ++ ++ if _, exists := config.NameToCertificate[commonName]; !exists { ++ t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate) ++ } ++ } ++} ++ ++func ExampleToPEM() { ++ p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`) ++ ++ blocks, err := ToPEM(p12, "password") ++ if err != nil { ++ panic(err) ++ } ++ ++ var pemData []byte ++ for _, b := range blocks { ++ pemData = append(pemData, pem.EncodeToMemory(b)...) ++ } ++ ++ // then use PEM data for tls to construct tls certificate: ++ cert, err := tls.X509KeyPair(pemData, pemData) ++ if err != nil { ++ panic(err) ++ } ++ ++ config := &tls.Config{ ++ Certificates: []tls.Certificate{cert}, ++ } ++ ++ _ = config ++} ++ ++var testdata = map[string]string{ ++ // 'null' password test case ++ "Windows Azure Tools": `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`, ++ // Windows IAS PEAP & LDAPS certificates test case ++ // Unknown OID 1.3.6.1.4.1.311.17.2 should be dropped ++ "Windows IAS PEAP & LDAPS certificates": `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`, ++ // empty string password test case ++ "testing@example.com": `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 ++HQ8CAggA`, ++} +diff --git a/ms_mod/golang.org/x/crypto/pkcs12/safebags.go b/ms_mod/golang.org/x/crypto/pkcs12/safebags.go +new file mode 100644 +index 00000000000000..def1f7b98d7de4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/pkcs12/safebags.go +@@ -0,0 +1,57 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pkcs12 ++ ++import ( ++ "crypto/x509" ++ "encoding/asn1" ++ "errors" ++) ++ ++var ( ++ // see https://tools.ietf.org/html/rfc7292#appendix-D ++ oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1}) ++ oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2}) ++ oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3}) ++) ++ ++type certBag struct { ++ Id asn1.ObjectIdentifier ++ Data []byte `asn1:"tag:0,explicit"` ++} ++ ++func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) { ++ pkinfo := new(encryptedPrivateKeyInfo) ++ if err = unmarshal(asn1Data, pkinfo); err != nil { ++ return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error()) ++ } ++ ++ pkData, err := pbDecrypt(pkinfo, password) ++ if err != nil { ++ return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error()) ++ } ++ ++ ret := new(asn1.RawValue) ++ if err = unmarshal(pkData, ret); err != nil { ++ return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error()) ++ } ++ ++ if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil { ++ return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()) ++ } ++ ++ return privateKey, nil ++} ++ ++func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) { ++ bag := new(certBag) ++ if err := unmarshal(asn1Data, bag); err != nil { ++ return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error()) ++ } ++ if !bag.Id.Equal(oidCertTypeX509Certificate) { ++ return nil, NotImplementedError("only X509 certificates are supported") ++ } ++ return bag.Data, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go b/ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go +new file mode 100644 +index 00000000000000..dd975a32c988a1 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go +@@ -0,0 +1,91 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package poly1305 implements Poly1305 one-time message authentication code as ++// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. ++// ++// Poly1305 is a fast, one-time authentication function. It is infeasible for an ++// attacker to generate an authenticator for a message without the key. However, a ++// key must only be used for a single message. Authenticating two different ++// messages with the same key allows an attacker to forge authenticators for other ++// messages with the same key. ++// ++// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was ++// used with a fixed key in order to generate one-time keys from an nonce. ++// However, in this package AES isn't used and the one-time key is specified ++// directly. ++// ++// Deprecated: Poly1305 as implemented by this package is a cryptographic ++// building block that is not safe for general purpose use. ++// For encryption, use the full ChaCha20-Poly1305 construction implemented by ++// golang.org/x/crypto/chacha20poly1305. For authentication, use a general ++// purpose MAC such as HMAC implemented by crypto/hmac. ++package poly1305 // import "golang.org/x/crypto/poly1305" ++ ++import "golang.org/x/crypto/internal/poly1305" ++ ++// TagSize is the size, in bytes, of a poly1305 authenticator. ++// ++// For use with golang.org/x/crypto/chacha20poly1305, chacha20poly1305.Overhead ++// can be used instead. ++const TagSize = 16 ++ ++// Sum generates an authenticator for msg using a one-time key and puts the ++// 16-byte result into out. Authenticating two different messages with the same ++// key allows an attacker to forge messages at will. ++func Sum(out *[16]byte, m []byte, key *[32]byte) { ++ poly1305.Sum(out, m, key) ++} ++ ++// Verify returns true if mac is a valid authenticator for m with the given key. ++func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { ++ return poly1305.Verify(mac, m, key) ++} ++ ++// New returns a new MAC computing an authentication ++// tag of all data written to it with the given key. ++// This allows writing the message progressively instead ++// of passing it as a single slice. Common users should use ++// the Sum function instead. ++// ++// The key must be unique for each message, as authenticating ++// two different messages with the same key allows an attacker ++// to forge messages at will. ++func New(key *[32]byte) *MAC { ++ return &MAC{mac: poly1305.New(key)} ++} ++ ++// MAC is an io.Writer computing an authentication tag ++// of the data written to it. ++// ++// MAC cannot be used like common hash.Hash implementations, ++// because using a poly1305 key twice breaks its security. ++// Therefore writing data to a running MAC after calling ++// Sum or Verify causes it to panic. ++type MAC struct { ++ mac *poly1305.MAC ++} ++ ++// Size returns the number of bytes Sum will return. ++func (h *MAC) Size() int { return TagSize } ++ ++// Write adds more data to the running message authentication code. ++// It never returns an error. ++// ++// It must not be called after the first call of Sum or Verify. ++func (h *MAC) Write(p []byte) (n int, err error) { ++ return h.mac.Write(p) ++} ++ ++// Sum computes the authenticator of all data written to the ++// message authentication code. ++func (h *MAC) Sum(b []byte) []byte { ++ return h.mac.Sum(b) ++} ++ ++// Verify returns whether the authenticator of all data written to ++// the message authentication code matches the expected value. ++func (h *MAC) Verify(expected []byte) bool { ++ return h.mac.Verify(expected) ++} +diff --git a/ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go +new file mode 100644 +index 00000000000000..cf3eeb158a9c60 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go +@@ -0,0 +1,124 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package ripemd160 implements the RIPEMD-160 hash algorithm. ++// ++// Deprecated: RIPEMD-160 is a legacy hash and should not be used for new ++// applications. Also, this package does not and will not provide an optimized ++// implementation. Instead, use a modern hash like SHA-256 (from crypto/sha256). ++package ripemd160 // import "golang.org/x/crypto/ripemd160" ++ ++// RIPEMD-160 is designed by Hans Dobbertin, Antoon Bosselaers, and Bart ++// Preneel with specifications available at: ++// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. ++ ++import ( ++ "crypto" ++ "hash" ++) ++ ++func init() { ++ crypto.RegisterHash(crypto.RIPEMD160, New) ++} ++ ++// The size of the checksum in bytes. ++const Size = 20 ++ ++// The block size of the hash algorithm in bytes. ++const BlockSize = 64 ++ ++const ( ++ _s0 = 0x67452301 ++ _s1 = 0xefcdab89 ++ _s2 = 0x98badcfe ++ _s3 = 0x10325476 ++ _s4 = 0xc3d2e1f0 ++) ++ ++// digest represents the partial evaluation of a checksum. ++type digest struct { ++ s [5]uint32 // running context ++ x [BlockSize]byte // temporary buffer ++ nx int // index into x ++ tc uint64 // total count of bytes processed ++} ++ ++func (d *digest) Reset() { ++ d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 ++ d.nx = 0 ++ d.tc = 0 ++} ++ ++// New returns a new hash.Hash computing the checksum. ++func New() hash.Hash { ++ result := new(digest) ++ result.Reset() ++ return result ++} ++ ++func (d *digest) Size() int { return Size } ++ ++func (d *digest) BlockSize() int { return BlockSize } ++ ++func (d *digest) Write(p []byte) (nn int, err error) { ++ nn = len(p) ++ d.tc += uint64(nn) ++ if d.nx > 0 { ++ n := len(p) ++ if n > BlockSize-d.nx { ++ n = BlockSize - d.nx ++ } ++ for i := 0; i < n; i++ { ++ d.x[d.nx+i] = p[i] ++ } ++ d.nx += n ++ if d.nx == BlockSize { ++ _Block(d, d.x[0:]) ++ d.nx = 0 ++ } ++ p = p[n:] ++ } ++ n := _Block(d, p) ++ p = p[n:] ++ if len(p) > 0 { ++ d.nx = copy(d.x[:], p) ++ } ++ return ++} ++ ++func (d0 *digest) Sum(in []byte) []byte { ++ // Make a copy of d0 so that caller can keep writing and summing. ++ d := *d0 ++ ++ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. ++ tc := d.tc ++ var tmp [64]byte ++ tmp[0] = 0x80 ++ if tc%64 < 56 { ++ d.Write(tmp[0 : 56-tc%64]) ++ } else { ++ d.Write(tmp[0 : 64+56-tc%64]) ++ } ++ ++ // Length in bits. ++ tc <<= 3 ++ for i := uint(0); i < 8; i++ { ++ tmp[i] = byte(tc >> (8 * i)) ++ } ++ d.Write(tmp[0:8]) ++ ++ if d.nx != 0 { ++ panic("d.nx != 0") ++ } ++ ++ var digest [Size]byte ++ for i, s := range d.s { ++ digest[i*4] = byte(s) ++ digest[i*4+1] = byte(s >> 8) ++ digest[i*4+2] = byte(s >> 16) ++ digest[i*4+3] = byte(s >> 24) ++ } ++ ++ return append(in, digest[:]...) ++} +diff --git a/ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go +new file mode 100644 +index 00000000000000..a1fbffdd5fcb5d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go +@@ -0,0 +1,72 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ripemd160 ++ ++// Test vectors are from: ++// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html ++ ++import ( ++ "fmt" ++ "io" ++ "testing" ++) ++ ++type mdTest struct { ++ out string ++ in string ++} ++ ++var vectors = [...]mdTest{ ++ {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""}, ++ {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"}, ++ {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"}, ++ {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"}, ++ {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"}, ++ {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, ++ {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, ++ {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}, ++} ++ ++func TestVectors(t *testing.T) { ++ for i := 0; i < len(vectors); i++ { ++ tv := vectors[i] ++ md := New() ++ for j := 0; j < 3; j++ { ++ if j < 2 { ++ io.WriteString(md, tv.in) ++ } else { ++ io.WriteString(md, tv.in[0:len(tv.in)/2]) ++ md.Sum(nil) ++ io.WriteString(md, tv.in[len(tv.in)/2:]) ++ } ++ s := fmt.Sprintf("%x", md.Sum(nil)) ++ if s != tv.out { ++ t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out) ++ } ++ md.Reset() ++ } ++ } ++} ++ ++func millionA() string { ++ md := New() ++ for i := 0; i < 100000; i++ { ++ io.WriteString(md, "aaaaaaaaaa") ++ } ++ return fmt.Sprintf("%x", md.Sum(nil)) ++} ++ ++func TestMillionA(t *testing.T) { ++ const out = "52783243c1697bdbe16d37f97f68f08325dc1528" ++ if s := millionA(); s != out { ++ t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out) ++ } ++} ++ ++func BenchmarkMillionA(b *testing.B) { ++ for i := 0; i < b.N; i++ { ++ millionA() ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go +new file mode 100644 +index 00000000000000..e0edc02f0f30f3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go +@@ -0,0 +1,165 @@ ++// Copyright 2010 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// RIPEMD-160 block step. ++// In its own file so that a faster assembly or C version ++// can be substituted easily. ++ ++package ripemd160 ++ ++import ( ++ "math/bits" ++) ++ ++// work buffer indices and roll amounts for one line ++var _n = [80]uint{ ++ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ++ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, ++ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, ++ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, ++ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, ++} ++ ++var _r = [80]uint{ ++ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, ++ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, ++ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, ++ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, ++ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, ++} ++ ++// same for the other parallel one ++var n_ = [80]uint{ ++ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, ++ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, ++ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, ++ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, ++ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, ++} ++ ++var r_ = [80]uint{ ++ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, ++ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, ++ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, ++ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, ++ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, ++} ++ ++func _Block(md *digest, p []byte) int { ++ n := 0 ++ var x [16]uint32 ++ var alpha, beta uint32 ++ for len(p) >= BlockSize { ++ a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4] ++ aa, bb, cc, dd, ee := a, b, c, d, e ++ j := 0 ++ for i := 0; i < 16; i++ { ++ x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 ++ j += 4 ++ } ++ ++ // round 1 ++ i := 0 ++ for i < 16 { ++ alpha = a + (b ^ c ^ d) + x[_n[i]] ++ s := int(_r[i]) ++ alpha = bits.RotateLeft32(alpha, s) + e ++ beta = bits.RotateLeft32(c, 10) ++ a, b, c, d, e = e, alpha, b, beta, d ++ ++ // parallel line ++ alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 ++ s = int(r_[i]) ++ alpha = bits.RotateLeft32(alpha, s) + ee ++ beta = bits.RotateLeft32(cc, 10) ++ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd ++ ++ i++ ++ } ++ ++ // round 2 ++ for i < 32 { ++ alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 ++ s := int(_r[i]) ++ alpha = bits.RotateLeft32(alpha, s) + e ++ beta = bits.RotateLeft32(c, 10) ++ a, b, c, d, e = e, alpha, b, beta, d ++ ++ // parallel line ++ alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 ++ s = int(r_[i]) ++ alpha = bits.RotateLeft32(alpha, s) + ee ++ beta = bits.RotateLeft32(cc, 10) ++ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd ++ ++ i++ ++ } ++ ++ // round 3 ++ for i < 48 { ++ alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 ++ s := int(_r[i]) ++ alpha = bits.RotateLeft32(alpha, s) + e ++ beta = bits.RotateLeft32(c, 10) ++ a, b, c, d, e = e, alpha, b, beta, d ++ ++ // parallel line ++ alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 ++ s = int(r_[i]) ++ alpha = bits.RotateLeft32(alpha, s) + ee ++ beta = bits.RotateLeft32(cc, 10) ++ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd ++ ++ i++ ++ } ++ ++ // round 4 ++ for i < 64 { ++ alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc ++ s := int(_r[i]) ++ alpha = bits.RotateLeft32(alpha, s) + e ++ beta = bits.RotateLeft32(c, 10) ++ a, b, c, d, e = e, alpha, b, beta, d ++ ++ // parallel line ++ alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 ++ s = int(r_[i]) ++ alpha = bits.RotateLeft32(alpha, s) + ee ++ beta = bits.RotateLeft32(cc, 10) ++ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd ++ ++ i++ ++ } ++ ++ // round 5 ++ for i < 80 { ++ alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e ++ s := int(_r[i]) ++ alpha = bits.RotateLeft32(alpha, s) + e ++ beta = bits.RotateLeft32(c, 10) ++ a, b, c, d, e = e, alpha, b, beta, d ++ ++ // parallel line ++ alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] ++ s = int(r_[i]) ++ alpha = bits.RotateLeft32(alpha, s) + ee ++ beta = bits.RotateLeft32(cc, 10) ++ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd ++ ++ i++ ++ } ++ ++ // combine results ++ dd += c + md.s[1] ++ md.s[1] = md.s[2] + d + ee ++ md.s[2] = md.s[3] + e + aa ++ md.s[3] = md.s[4] + a + bb ++ md.s[4] = md.s[0] + b + cc ++ md.s[0] = dd ++ ++ p = p[BlockSize:] ++ n += BlockSize ++ } ++ return n ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go +new file mode 100644 +index 00000000000000..3fd05b27516987 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go +@@ -0,0 +1,146 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package salsa provides low-level access to functions in the Salsa family. ++package salsa // import "golang.org/x/crypto/salsa20/salsa" ++ ++import "math/bits" ++ ++// Sigma is the Salsa20 constant for 256-bit keys. ++var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} ++ ++// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte ++// key k, and 16-byte constant c, and puts the result into the 32-byte array ++// out. ++func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { ++ x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 ++ x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 ++ x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 ++ x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 ++ x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 ++ x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 ++ x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 ++ x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 ++ x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 ++ x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 ++ x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 ++ x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 ++ x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 ++ x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 ++ x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 ++ x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 ++ ++ for i := 0; i < 20; i += 2 { ++ u := x0 + x12 ++ x4 ^= bits.RotateLeft32(u, 7) ++ u = x4 + x0 ++ x8 ^= bits.RotateLeft32(u, 9) ++ u = x8 + x4 ++ x12 ^= bits.RotateLeft32(u, 13) ++ u = x12 + x8 ++ x0 ^= bits.RotateLeft32(u, 18) ++ ++ u = x5 + x1 ++ x9 ^= bits.RotateLeft32(u, 7) ++ u = x9 + x5 ++ x13 ^= bits.RotateLeft32(u, 9) ++ u = x13 + x9 ++ x1 ^= bits.RotateLeft32(u, 13) ++ u = x1 + x13 ++ x5 ^= bits.RotateLeft32(u, 18) ++ ++ u = x10 + x6 ++ x14 ^= bits.RotateLeft32(u, 7) ++ u = x14 + x10 ++ x2 ^= bits.RotateLeft32(u, 9) ++ u = x2 + x14 ++ x6 ^= bits.RotateLeft32(u, 13) ++ u = x6 + x2 ++ x10 ^= bits.RotateLeft32(u, 18) ++ ++ u = x15 + x11 ++ x3 ^= bits.RotateLeft32(u, 7) ++ u = x3 + x15 ++ x7 ^= bits.RotateLeft32(u, 9) ++ u = x7 + x3 ++ x11 ^= bits.RotateLeft32(u, 13) ++ u = x11 + x7 ++ x15 ^= bits.RotateLeft32(u, 18) ++ ++ u = x0 + x3 ++ x1 ^= bits.RotateLeft32(u, 7) ++ u = x1 + x0 ++ x2 ^= bits.RotateLeft32(u, 9) ++ u = x2 + x1 ++ x3 ^= bits.RotateLeft32(u, 13) ++ u = x3 + x2 ++ x0 ^= bits.RotateLeft32(u, 18) ++ ++ u = x5 + x4 ++ x6 ^= bits.RotateLeft32(u, 7) ++ u = x6 + x5 ++ x7 ^= bits.RotateLeft32(u, 9) ++ u = x7 + x6 ++ x4 ^= bits.RotateLeft32(u, 13) ++ u = x4 + x7 ++ x5 ^= bits.RotateLeft32(u, 18) ++ ++ u = x10 + x9 ++ x11 ^= bits.RotateLeft32(u, 7) ++ u = x11 + x10 ++ x8 ^= bits.RotateLeft32(u, 9) ++ u = x8 + x11 ++ x9 ^= bits.RotateLeft32(u, 13) ++ u = x9 + x8 ++ x10 ^= bits.RotateLeft32(u, 18) ++ ++ u = x15 + x14 ++ x12 ^= bits.RotateLeft32(u, 7) ++ u = x12 + x15 ++ x13 ^= bits.RotateLeft32(u, 9) ++ u = x13 + x12 ++ x14 ^= bits.RotateLeft32(u, 13) ++ u = x14 + x13 ++ x15 ^= bits.RotateLeft32(u, 18) ++ } ++ out[0] = byte(x0) ++ out[1] = byte(x0 >> 8) ++ out[2] = byte(x0 >> 16) ++ out[3] = byte(x0 >> 24) ++ ++ out[4] = byte(x5) ++ out[5] = byte(x5 >> 8) ++ out[6] = byte(x5 >> 16) ++ out[7] = byte(x5 >> 24) ++ ++ out[8] = byte(x10) ++ out[9] = byte(x10 >> 8) ++ out[10] = byte(x10 >> 16) ++ out[11] = byte(x10 >> 24) ++ ++ out[12] = byte(x15) ++ out[13] = byte(x15 >> 8) ++ out[14] = byte(x15 >> 16) ++ out[15] = byte(x15 >> 24) ++ ++ out[16] = byte(x6) ++ out[17] = byte(x6 >> 8) ++ out[18] = byte(x6 >> 16) ++ out[19] = byte(x6 >> 24) ++ ++ out[20] = byte(x7) ++ out[21] = byte(x7 >> 8) ++ out[22] = byte(x7 >> 16) ++ out[23] = byte(x7 >> 24) ++ ++ out[24] = byte(x8) ++ out[25] = byte(x8 >> 8) ++ out[26] = byte(x8 >> 16) ++ out[27] = byte(x8 >> 24) ++ ++ out[28] = byte(x9) ++ out[29] = byte(x9 >> 8) ++ out[30] = byte(x9 >> 16) ++ out[31] = byte(x9 >> 24) ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go +new file mode 100644 +index 00000000000000..7ec7bb39bc0494 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go +@@ -0,0 +1,201 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package salsa ++ ++import "math/bits" ++ ++// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts ++// the result into the 64-byte array out. The input and output may be the same array. ++func Core208(out *[64]byte, in *[64]byte) { ++ j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 ++ j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 ++ j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 ++ j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 ++ j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 ++ j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 ++ j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 ++ j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 ++ j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 ++ j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 ++ j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 ++ j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 ++ j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 ++ j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 ++ j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 ++ j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 ++ ++ x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 ++ x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 ++ ++ for i := 0; i < 8; i += 2 { ++ u := x0 + x12 ++ x4 ^= bits.RotateLeft32(u, 7) ++ u = x4 + x0 ++ x8 ^= bits.RotateLeft32(u, 9) ++ u = x8 + x4 ++ x12 ^= bits.RotateLeft32(u, 13) ++ u = x12 + x8 ++ x0 ^= bits.RotateLeft32(u, 18) ++ ++ u = x5 + x1 ++ x9 ^= bits.RotateLeft32(u, 7) ++ u = x9 + x5 ++ x13 ^= bits.RotateLeft32(u, 9) ++ u = x13 + x9 ++ x1 ^= bits.RotateLeft32(u, 13) ++ u = x1 + x13 ++ x5 ^= bits.RotateLeft32(u, 18) ++ ++ u = x10 + x6 ++ x14 ^= bits.RotateLeft32(u, 7) ++ u = x14 + x10 ++ x2 ^= bits.RotateLeft32(u, 9) ++ u = x2 + x14 ++ x6 ^= bits.RotateLeft32(u, 13) ++ u = x6 + x2 ++ x10 ^= bits.RotateLeft32(u, 18) ++ ++ u = x15 + x11 ++ x3 ^= bits.RotateLeft32(u, 7) ++ u = x3 + x15 ++ x7 ^= bits.RotateLeft32(u, 9) ++ u = x7 + x3 ++ x11 ^= bits.RotateLeft32(u, 13) ++ u = x11 + x7 ++ x15 ^= bits.RotateLeft32(u, 18) ++ ++ u = x0 + x3 ++ x1 ^= bits.RotateLeft32(u, 7) ++ u = x1 + x0 ++ x2 ^= bits.RotateLeft32(u, 9) ++ u = x2 + x1 ++ x3 ^= bits.RotateLeft32(u, 13) ++ u = x3 + x2 ++ x0 ^= bits.RotateLeft32(u, 18) ++ ++ u = x5 + x4 ++ x6 ^= bits.RotateLeft32(u, 7) ++ u = x6 + x5 ++ x7 ^= bits.RotateLeft32(u, 9) ++ u = x7 + x6 ++ x4 ^= bits.RotateLeft32(u, 13) ++ u = x4 + x7 ++ x5 ^= bits.RotateLeft32(u, 18) ++ ++ u = x10 + x9 ++ x11 ^= bits.RotateLeft32(u, 7) ++ u = x11 + x10 ++ x8 ^= bits.RotateLeft32(u, 9) ++ u = x8 + x11 ++ x9 ^= bits.RotateLeft32(u, 13) ++ u = x9 + x8 ++ x10 ^= bits.RotateLeft32(u, 18) ++ ++ u = x15 + x14 ++ x12 ^= bits.RotateLeft32(u, 7) ++ u = x12 + x15 ++ x13 ^= bits.RotateLeft32(u, 9) ++ u = x13 + x12 ++ x14 ^= bits.RotateLeft32(u, 13) ++ u = x14 + x13 ++ x15 ^= bits.RotateLeft32(u, 18) ++ } ++ x0 += j0 ++ x1 += j1 ++ x2 += j2 ++ x3 += j3 ++ x4 += j4 ++ x5 += j5 ++ x6 += j6 ++ x7 += j7 ++ x8 += j8 ++ x9 += j9 ++ x10 += j10 ++ x11 += j11 ++ x12 += j12 ++ x13 += j13 ++ x14 += j14 ++ x15 += j15 ++ ++ out[0] = byte(x0) ++ out[1] = byte(x0 >> 8) ++ out[2] = byte(x0 >> 16) ++ out[3] = byte(x0 >> 24) ++ ++ out[4] = byte(x1) ++ out[5] = byte(x1 >> 8) ++ out[6] = byte(x1 >> 16) ++ out[7] = byte(x1 >> 24) ++ ++ out[8] = byte(x2) ++ out[9] = byte(x2 >> 8) ++ out[10] = byte(x2 >> 16) ++ out[11] = byte(x2 >> 24) ++ ++ out[12] = byte(x3) ++ out[13] = byte(x3 >> 8) ++ out[14] = byte(x3 >> 16) ++ out[15] = byte(x3 >> 24) ++ ++ out[16] = byte(x4) ++ out[17] = byte(x4 >> 8) ++ out[18] = byte(x4 >> 16) ++ out[19] = byte(x4 >> 24) ++ ++ out[20] = byte(x5) ++ out[21] = byte(x5 >> 8) ++ out[22] = byte(x5 >> 16) ++ out[23] = byte(x5 >> 24) ++ ++ out[24] = byte(x6) ++ out[25] = byte(x6 >> 8) ++ out[26] = byte(x6 >> 16) ++ out[27] = byte(x6 >> 24) ++ ++ out[28] = byte(x7) ++ out[29] = byte(x7 >> 8) ++ out[30] = byte(x7 >> 16) ++ out[31] = byte(x7 >> 24) ++ ++ out[32] = byte(x8) ++ out[33] = byte(x8 >> 8) ++ out[34] = byte(x8 >> 16) ++ out[35] = byte(x8 >> 24) ++ ++ out[36] = byte(x9) ++ out[37] = byte(x9 >> 8) ++ out[38] = byte(x9 >> 16) ++ out[39] = byte(x9 >> 24) ++ ++ out[40] = byte(x10) ++ out[41] = byte(x10 >> 8) ++ out[42] = byte(x10 >> 16) ++ out[43] = byte(x10 >> 24) ++ ++ out[44] = byte(x11) ++ out[45] = byte(x11 >> 8) ++ out[46] = byte(x11 >> 16) ++ out[47] = byte(x11 >> 24) ++ ++ out[48] = byte(x12) ++ out[49] = byte(x12 >> 8) ++ out[50] = byte(x12 >> 16) ++ out[51] = byte(x12 >> 24) ++ ++ out[52] = byte(x13) ++ out[53] = byte(x13 >> 8) ++ out[54] = byte(x13 >> 16) ++ out[55] = byte(x13 >> 24) ++ ++ out[56] = byte(x14) ++ out[57] = byte(x14 >> 8) ++ out[58] = byte(x14 >> 16) ++ out[59] = byte(x14 >> 24) ++ ++ out[60] = byte(x15) ++ out[61] = byte(x15 >> 8) ++ out[62] = byte(x15 >> 16) ++ out[63] = byte(x15 >> 24) ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go +new file mode 100644 +index 00000000000000..c400dfcf7bce5c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go +@@ -0,0 +1,24 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && !purego && gc ++// +build amd64,!purego,gc ++ ++package salsa ++ ++//go:noescape ++ ++// salsa2020XORKeyStream is implemented in salsa20_amd64.s. ++func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) ++ ++// XORKeyStream crypts bytes from in to out using the given key and counters. ++// In and out must overlap entirely or not at all. Counter ++// contains the raw salsa20 counter bytes (both nonce and block counter). ++func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { ++ if len(in) == 0 { ++ return ++ } ++ _ = out[len(in)-1] ++ salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s +new file mode 100644 +index 00000000000000..c0892772045a25 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s +@@ -0,0 +1,881 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && !purego && gc ++// +build amd64,!purego,gc ++ ++// This code was translated into a form compatible with 6a from the public ++// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html ++ ++// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) ++// This needs up to 64 bytes at 360(R12); hence the non-obvious frame size. ++TEXT Β·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment ++ MOVQ out+0(FP),DI ++ MOVQ in+8(FP),SI ++ MOVQ n+16(FP),DX ++ MOVQ nonce+24(FP),CX ++ MOVQ key+32(FP),R8 ++ ++ MOVQ SP,R12 ++ ADDQ $31, R12 ++ ANDQ $~31, R12 ++ ++ MOVQ DX,R9 ++ MOVQ CX,DX ++ MOVQ R8,R10 ++ CMPQ R9,$0 ++ JBE DONE ++ START: ++ MOVL 20(R10),CX ++ MOVL 0(R10),R8 ++ MOVL 0(DX),AX ++ MOVL 16(R10),R11 ++ MOVL CX,0(R12) ++ MOVL R8, 4 (R12) ++ MOVL AX, 8 (R12) ++ MOVL R11, 12 (R12) ++ MOVL 8(DX),CX ++ MOVL 24(R10),R8 ++ MOVL 4(R10),AX ++ MOVL 4(DX),R11 ++ MOVL CX,16(R12) ++ MOVL R8, 20 (R12) ++ MOVL AX, 24 (R12) ++ MOVL R11, 28 (R12) ++ MOVL 12(DX),CX ++ MOVL 12(R10),DX ++ MOVL 28(R10),R8 ++ MOVL 8(R10),AX ++ MOVL DX,32(R12) ++ MOVL CX, 36 (R12) ++ MOVL R8, 40 (R12) ++ MOVL AX, 44 (R12) ++ MOVQ $1634760805,DX ++ MOVQ $857760878,CX ++ MOVQ $2036477234,R8 ++ MOVQ $1797285236,AX ++ MOVL DX,48(R12) ++ MOVL CX, 52 (R12) ++ MOVL R8, 56 (R12) ++ MOVL AX, 60 (R12) ++ CMPQ R9,$256 ++ JB BYTESBETWEEN1AND255 ++ MOVOA 48(R12),X0 ++ PSHUFL $0X55,X0,X1 ++ PSHUFL $0XAA,X0,X2 ++ PSHUFL $0XFF,X0,X3 ++ PSHUFL $0X00,X0,X0 ++ MOVOA X1,64(R12) ++ MOVOA X2,80(R12) ++ MOVOA X3,96(R12) ++ MOVOA X0,112(R12) ++ MOVOA 0(R12),X0 ++ PSHUFL $0XAA,X0,X1 ++ PSHUFL $0XFF,X0,X2 ++ PSHUFL $0X00,X0,X3 ++ PSHUFL $0X55,X0,X0 ++ MOVOA X1,128(R12) ++ MOVOA X2,144(R12) ++ MOVOA X3,160(R12) ++ MOVOA X0,176(R12) ++ MOVOA 16(R12),X0 ++ PSHUFL $0XFF,X0,X1 ++ PSHUFL $0X55,X0,X2 ++ PSHUFL $0XAA,X0,X0 ++ MOVOA X1,192(R12) ++ MOVOA X2,208(R12) ++ MOVOA X0,224(R12) ++ MOVOA 32(R12),X0 ++ PSHUFL $0X00,X0,X1 ++ PSHUFL $0XAA,X0,X2 ++ PSHUFL $0XFF,X0,X0 ++ MOVOA X1,240(R12) ++ MOVOA X2,256(R12) ++ MOVOA X0,272(R12) ++ BYTESATLEAST256: ++ MOVL 16(R12),DX ++ MOVL 36 (R12),CX ++ MOVL DX,288(R12) ++ MOVL CX,304(R12) ++ SHLQ $32,CX ++ ADDQ CX,DX ++ ADDQ $1,DX ++ MOVQ DX,CX ++ SHRQ $32,CX ++ MOVL DX, 292 (R12) ++ MOVL CX, 308 (R12) ++ ADDQ $1,DX ++ MOVQ DX,CX ++ SHRQ $32,CX ++ MOVL DX, 296 (R12) ++ MOVL CX, 312 (R12) ++ ADDQ $1,DX ++ MOVQ DX,CX ++ SHRQ $32,CX ++ MOVL DX, 300 (R12) ++ MOVL CX, 316 (R12) ++ ADDQ $1,DX ++ MOVQ DX,CX ++ SHRQ $32,CX ++ MOVL DX,16(R12) ++ MOVL CX, 36 (R12) ++ MOVQ R9,352(R12) ++ MOVQ $20,DX ++ MOVOA 64(R12),X0 ++ MOVOA 80(R12),X1 ++ MOVOA 96(R12),X2 ++ MOVOA 256(R12),X3 ++ MOVOA 272(R12),X4 ++ MOVOA 128(R12),X5 ++ MOVOA 144(R12),X6 ++ MOVOA 176(R12),X7 ++ MOVOA 192(R12),X8 ++ MOVOA 208(R12),X9 ++ MOVOA 224(R12),X10 ++ MOVOA 304(R12),X11 ++ MOVOA 112(R12),X12 ++ MOVOA 160(R12),X13 ++ MOVOA 240(R12),X14 ++ MOVOA 288(R12),X15 ++ MAINLOOP1: ++ MOVOA X1,320(R12) ++ MOVOA X2,336(R12) ++ MOVOA X13,X1 ++ PADDL X12,X1 ++ MOVOA X1,X2 ++ PSLLL $7,X1 ++ PXOR X1,X14 ++ PSRLL $25,X2 ++ PXOR X2,X14 ++ MOVOA X7,X1 ++ PADDL X0,X1 ++ MOVOA X1,X2 ++ PSLLL $7,X1 ++ PXOR X1,X11 ++ PSRLL $25,X2 ++ PXOR X2,X11 ++ MOVOA X12,X1 ++ PADDL X14,X1 ++ MOVOA X1,X2 ++ PSLLL $9,X1 ++ PXOR X1,X15 ++ PSRLL $23,X2 ++ PXOR X2,X15 ++ MOVOA X0,X1 ++ PADDL X11,X1 ++ MOVOA X1,X2 ++ PSLLL $9,X1 ++ PXOR X1,X9 ++ PSRLL $23,X2 ++ PXOR X2,X9 ++ MOVOA X14,X1 ++ PADDL X15,X1 ++ MOVOA X1,X2 ++ PSLLL $13,X1 ++ PXOR X1,X13 ++ PSRLL $19,X2 ++ PXOR X2,X13 ++ MOVOA X11,X1 ++ PADDL X9,X1 ++ MOVOA X1,X2 ++ PSLLL $13,X1 ++ PXOR X1,X7 ++ PSRLL $19,X2 ++ PXOR X2,X7 ++ MOVOA X15,X1 ++ PADDL X13,X1 ++ MOVOA X1,X2 ++ PSLLL $18,X1 ++ PXOR X1,X12 ++ PSRLL $14,X2 ++ PXOR X2,X12 ++ MOVOA 320(R12),X1 ++ MOVOA X12,320(R12) ++ MOVOA X9,X2 ++ PADDL X7,X2 ++ MOVOA X2,X12 ++ PSLLL $18,X2 ++ PXOR X2,X0 ++ PSRLL $14,X12 ++ PXOR X12,X0 ++ MOVOA X5,X2 ++ PADDL X1,X2 ++ MOVOA X2,X12 ++ PSLLL $7,X2 ++ PXOR X2,X3 ++ PSRLL $25,X12 ++ PXOR X12,X3 ++ MOVOA 336(R12),X2 ++ MOVOA X0,336(R12) ++ MOVOA X6,X0 ++ PADDL X2,X0 ++ MOVOA X0,X12 ++ PSLLL $7,X0 ++ PXOR X0,X4 ++ PSRLL $25,X12 ++ PXOR X12,X4 ++ MOVOA X1,X0 ++ PADDL X3,X0 ++ MOVOA X0,X12 ++ PSLLL $9,X0 ++ PXOR X0,X10 ++ PSRLL $23,X12 ++ PXOR X12,X10 ++ MOVOA X2,X0 ++ PADDL X4,X0 ++ MOVOA X0,X12 ++ PSLLL $9,X0 ++ PXOR X0,X8 ++ PSRLL $23,X12 ++ PXOR X12,X8 ++ MOVOA X3,X0 ++ PADDL X10,X0 ++ MOVOA X0,X12 ++ PSLLL $13,X0 ++ PXOR X0,X5 ++ PSRLL $19,X12 ++ PXOR X12,X5 ++ MOVOA X4,X0 ++ PADDL X8,X0 ++ MOVOA X0,X12 ++ PSLLL $13,X0 ++ PXOR X0,X6 ++ PSRLL $19,X12 ++ PXOR X12,X6 ++ MOVOA X10,X0 ++ PADDL X5,X0 ++ MOVOA X0,X12 ++ PSLLL $18,X0 ++ PXOR X0,X1 ++ PSRLL $14,X12 ++ PXOR X12,X1 ++ MOVOA 320(R12),X0 ++ MOVOA X1,320(R12) ++ MOVOA X4,X1 ++ PADDL X0,X1 ++ MOVOA X1,X12 ++ PSLLL $7,X1 ++ PXOR X1,X7 ++ PSRLL $25,X12 ++ PXOR X12,X7 ++ MOVOA X8,X1 ++ PADDL X6,X1 ++ MOVOA X1,X12 ++ PSLLL $18,X1 ++ PXOR X1,X2 ++ PSRLL $14,X12 ++ PXOR X12,X2 ++ MOVOA 336(R12),X12 ++ MOVOA X2,336(R12) ++ MOVOA X14,X1 ++ PADDL X12,X1 ++ MOVOA X1,X2 ++ PSLLL $7,X1 ++ PXOR X1,X5 ++ PSRLL $25,X2 ++ PXOR X2,X5 ++ MOVOA X0,X1 ++ PADDL X7,X1 ++ MOVOA X1,X2 ++ PSLLL $9,X1 ++ PXOR X1,X10 ++ PSRLL $23,X2 ++ PXOR X2,X10 ++ MOVOA X12,X1 ++ PADDL X5,X1 ++ MOVOA X1,X2 ++ PSLLL $9,X1 ++ PXOR X1,X8 ++ PSRLL $23,X2 ++ PXOR X2,X8 ++ MOVOA X7,X1 ++ PADDL X10,X1 ++ MOVOA X1,X2 ++ PSLLL $13,X1 ++ PXOR X1,X4 ++ PSRLL $19,X2 ++ PXOR X2,X4 ++ MOVOA X5,X1 ++ PADDL X8,X1 ++ MOVOA X1,X2 ++ PSLLL $13,X1 ++ PXOR X1,X14 ++ PSRLL $19,X2 ++ PXOR X2,X14 ++ MOVOA X10,X1 ++ PADDL X4,X1 ++ MOVOA X1,X2 ++ PSLLL $18,X1 ++ PXOR X1,X0 ++ PSRLL $14,X2 ++ PXOR X2,X0 ++ MOVOA 320(R12),X1 ++ MOVOA X0,320(R12) ++ MOVOA X8,X0 ++ PADDL X14,X0 ++ MOVOA X0,X2 ++ PSLLL $18,X0 ++ PXOR X0,X12 ++ PSRLL $14,X2 ++ PXOR X2,X12 ++ MOVOA X11,X0 ++ PADDL X1,X0 ++ MOVOA X0,X2 ++ PSLLL $7,X0 ++ PXOR X0,X6 ++ PSRLL $25,X2 ++ PXOR X2,X6 ++ MOVOA 336(R12),X2 ++ MOVOA X12,336(R12) ++ MOVOA X3,X0 ++ PADDL X2,X0 ++ MOVOA X0,X12 ++ PSLLL $7,X0 ++ PXOR X0,X13 ++ PSRLL $25,X12 ++ PXOR X12,X13 ++ MOVOA X1,X0 ++ PADDL X6,X0 ++ MOVOA X0,X12 ++ PSLLL $9,X0 ++ PXOR X0,X15 ++ PSRLL $23,X12 ++ PXOR X12,X15 ++ MOVOA X2,X0 ++ PADDL X13,X0 ++ MOVOA X0,X12 ++ PSLLL $9,X0 ++ PXOR X0,X9 ++ PSRLL $23,X12 ++ PXOR X12,X9 ++ MOVOA X6,X0 ++ PADDL X15,X0 ++ MOVOA X0,X12 ++ PSLLL $13,X0 ++ PXOR X0,X11 ++ PSRLL $19,X12 ++ PXOR X12,X11 ++ MOVOA X13,X0 ++ PADDL X9,X0 ++ MOVOA X0,X12 ++ PSLLL $13,X0 ++ PXOR X0,X3 ++ PSRLL $19,X12 ++ PXOR X12,X3 ++ MOVOA X15,X0 ++ PADDL X11,X0 ++ MOVOA X0,X12 ++ PSLLL $18,X0 ++ PXOR X0,X1 ++ PSRLL $14,X12 ++ PXOR X12,X1 ++ MOVOA X9,X0 ++ PADDL X3,X0 ++ MOVOA X0,X12 ++ PSLLL $18,X0 ++ PXOR X0,X2 ++ PSRLL $14,X12 ++ PXOR X12,X2 ++ MOVOA 320(R12),X12 ++ MOVOA 336(R12),X0 ++ SUBQ $2,DX ++ JA MAINLOOP1 ++ PADDL 112(R12),X12 ++ PADDL 176(R12),X7 ++ PADDL 224(R12),X10 ++ PADDL 272(R12),X4 ++ MOVD X12,DX ++ MOVD X7,CX ++ MOVD X10,R8 ++ MOVD X4,R9 ++ PSHUFL $0X39,X12,X12 ++ PSHUFL $0X39,X7,X7 ++ PSHUFL $0X39,X10,X10 ++ PSHUFL $0X39,X4,X4 ++ XORL 0(SI),DX ++ XORL 4(SI),CX ++ XORL 8(SI),R8 ++ XORL 12(SI),R9 ++ MOVL DX,0(DI) ++ MOVL CX,4(DI) ++ MOVL R8,8(DI) ++ MOVL R9,12(DI) ++ MOVD X12,DX ++ MOVD X7,CX ++ MOVD X10,R8 ++ MOVD X4,R9 ++ PSHUFL $0X39,X12,X12 ++ PSHUFL $0X39,X7,X7 ++ PSHUFL $0X39,X10,X10 ++ PSHUFL $0X39,X4,X4 ++ XORL 64(SI),DX ++ XORL 68(SI),CX ++ XORL 72(SI),R8 ++ XORL 76(SI),R9 ++ MOVL DX,64(DI) ++ MOVL CX,68(DI) ++ MOVL R8,72(DI) ++ MOVL R9,76(DI) ++ MOVD X12,DX ++ MOVD X7,CX ++ MOVD X10,R8 ++ MOVD X4,R9 ++ PSHUFL $0X39,X12,X12 ++ PSHUFL $0X39,X7,X7 ++ PSHUFL $0X39,X10,X10 ++ PSHUFL $0X39,X4,X4 ++ XORL 128(SI),DX ++ XORL 132(SI),CX ++ XORL 136(SI),R8 ++ XORL 140(SI),R9 ++ MOVL DX,128(DI) ++ MOVL CX,132(DI) ++ MOVL R8,136(DI) ++ MOVL R9,140(DI) ++ MOVD X12,DX ++ MOVD X7,CX ++ MOVD X10,R8 ++ MOVD X4,R9 ++ XORL 192(SI),DX ++ XORL 196(SI),CX ++ XORL 200(SI),R8 ++ XORL 204(SI),R9 ++ MOVL DX,192(DI) ++ MOVL CX,196(DI) ++ MOVL R8,200(DI) ++ MOVL R9,204(DI) ++ PADDL 240(R12),X14 ++ PADDL 64(R12),X0 ++ PADDL 128(R12),X5 ++ PADDL 192(R12),X8 ++ MOVD X14,DX ++ MOVD X0,CX ++ MOVD X5,R8 ++ MOVD X8,R9 ++ PSHUFL $0X39,X14,X14 ++ PSHUFL $0X39,X0,X0 ++ PSHUFL $0X39,X5,X5 ++ PSHUFL $0X39,X8,X8 ++ XORL 16(SI),DX ++ XORL 20(SI),CX ++ XORL 24(SI),R8 ++ XORL 28(SI),R9 ++ MOVL DX,16(DI) ++ MOVL CX,20(DI) ++ MOVL R8,24(DI) ++ MOVL R9,28(DI) ++ MOVD X14,DX ++ MOVD X0,CX ++ MOVD X5,R8 ++ MOVD X8,R9 ++ PSHUFL $0X39,X14,X14 ++ PSHUFL $0X39,X0,X0 ++ PSHUFL $0X39,X5,X5 ++ PSHUFL $0X39,X8,X8 ++ XORL 80(SI),DX ++ XORL 84(SI),CX ++ XORL 88(SI),R8 ++ XORL 92(SI),R9 ++ MOVL DX,80(DI) ++ MOVL CX,84(DI) ++ MOVL R8,88(DI) ++ MOVL R9,92(DI) ++ MOVD X14,DX ++ MOVD X0,CX ++ MOVD X5,R8 ++ MOVD X8,R9 ++ PSHUFL $0X39,X14,X14 ++ PSHUFL $0X39,X0,X0 ++ PSHUFL $0X39,X5,X5 ++ PSHUFL $0X39,X8,X8 ++ XORL 144(SI),DX ++ XORL 148(SI),CX ++ XORL 152(SI),R8 ++ XORL 156(SI),R9 ++ MOVL DX,144(DI) ++ MOVL CX,148(DI) ++ MOVL R8,152(DI) ++ MOVL R9,156(DI) ++ MOVD X14,DX ++ MOVD X0,CX ++ MOVD X5,R8 ++ MOVD X8,R9 ++ XORL 208(SI),DX ++ XORL 212(SI),CX ++ XORL 216(SI),R8 ++ XORL 220(SI),R9 ++ MOVL DX,208(DI) ++ MOVL CX,212(DI) ++ MOVL R8,216(DI) ++ MOVL R9,220(DI) ++ PADDL 288(R12),X15 ++ PADDL 304(R12),X11 ++ PADDL 80(R12),X1 ++ PADDL 144(R12),X6 ++ MOVD X15,DX ++ MOVD X11,CX ++ MOVD X1,R8 ++ MOVD X6,R9 ++ PSHUFL $0X39,X15,X15 ++ PSHUFL $0X39,X11,X11 ++ PSHUFL $0X39,X1,X1 ++ PSHUFL $0X39,X6,X6 ++ XORL 32(SI),DX ++ XORL 36(SI),CX ++ XORL 40(SI),R8 ++ XORL 44(SI),R9 ++ MOVL DX,32(DI) ++ MOVL CX,36(DI) ++ MOVL R8,40(DI) ++ MOVL R9,44(DI) ++ MOVD X15,DX ++ MOVD X11,CX ++ MOVD X1,R8 ++ MOVD X6,R9 ++ PSHUFL $0X39,X15,X15 ++ PSHUFL $0X39,X11,X11 ++ PSHUFL $0X39,X1,X1 ++ PSHUFL $0X39,X6,X6 ++ XORL 96(SI),DX ++ XORL 100(SI),CX ++ XORL 104(SI),R8 ++ XORL 108(SI),R9 ++ MOVL DX,96(DI) ++ MOVL CX,100(DI) ++ MOVL R8,104(DI) ++ MOVL R9,108(DI) ++ MOVD X15,DX ++ MOVD X11,CX ++ MOVD X1,R8 ++ MOVD X6,R9 ++ PSHUFL $0X39,X15,X15 ++ PSHUFL $0X39,X11,X11 ++ PSHUFL $0X39,X1,X1 ++ PSHUFL $0X39,X6,X6 ++ XORL 160(SI),DX ++ XORL 164(SI),CX ++ XORL 168(SI),R8 ++ XORL 172(SI),R9 ++ MOVL DX,160(DI) ++ MOVL CX,164(DI) ++ MOVL R8,168(DI) ++ MOVL R9,172(DI) ++ MOVD X15,DX ++ MOVD X11,CX ++ MOVD X1,R8 ++ MOVD X6,R9 ++ XORL 224(SI),DX ++ XORL 228(SI),CX ++ XORL 232(SI),R8 ++ XORL 236(SI),R9 ++ MOVL DX,224(DI) ++ MOVL CX,228(DI) ++ MOVL R8,232(DI) ++ MOVL R9,236(DI) ++ PADDL 160(R12),X13 ++ PADDL 208(R12),X9 ++ PADDL 256(R12),X3 ++ PADDL 96(R12),X2 ++ MOVD X13,DX ++ MOVD X9,CX ++ MOVD X3,R8 ++ MOVD X2,R9 ++ PSHUFL $0X39,X13,X13 ++ PSHUFL $0X39,X9,X9 ++ PSHUFL $0X39,X3,X3 ++ PSHUFL $0X39,X2,X2 ++ XORL 48(SI),DX ++ XORL 52(SI),CX ++ XORL 56(SI),R8 ++ XORL 60(SI),R9 ++ MOVL DX,48(DI) ++ MOVL CX,52(DI) ++ MOVL R8,56(DI) ++ MOVL R9,60(DI) ++ MOVD X13,DX ++ MOVD X9,CX ++ MOVD X3,R8 ++ MOVD X2,R9 ++ PSHUFL $0X39,X13,X13 ++ PSHUFL $0X39,X9,X9 ++ PSHUFL $0X39,X3,X3 ++ PSHUFL $0X39,X2,X2 ++ XORL 112(SI),DX ++ XORL 116(SI),CX ++ XORL 120(SI),R8 ++ XORL 124(SI),R9 ++ MOVL DX,112(DI) ++ MOVL CX,116(DI) ++ MOVL R8,120(DI) ++ MOVL R9,124(DI) ++ MOVD X13,DX ++ MOVD X9,CX ++ MOVD X3,R8 ++ MOVD X2,R9 ++ PSHUFL $0X39,X13,X13 ++ PSHUFL $0X39,X9,X9 ++ PSHUFL $0X39,X3,X3 ++ PSHUFL $0X39,X2,X2 ++ XORL 176(SI),DX ++ XORL 180(SI),CX ++ XORL 184(SI),R8 ++ XORL 188(SI),R9 ++ MOVL DX,176(DI) ++ MOVL CX,180(DI) ++ MOVL R8,184(DI) ++ MOVL R9,188(DI) ++ MOVD X13,DX ++ MOVD X9,CX ++ MOVD X3,R8 ++ MOVD X2,R9 ++ XORL 240(SI),DX ++ XORL 244(SI),CX ++ XORL 248(SI),R8 ++ XORL 252(SI),R9 ++ MOVL DX,240(DI) ++ MOVL CX,244(DI) ++ MOVL R8,248(DI) ++ MOVL R9,252(DI) ++ MOVQ 352(R12),R9 ++ SUBQ $256,R9 ++ ADDQ $256,SI ++ ADDQ $256,DI ++ CMPQ R9,$256 ++ JAE BYTESATLEAST256 ++ CMPQ R9,$0 ++ JBE DONE ++ BYTESBETWEEN1AND255: ++ CMPQ R9,$64 ++ JAE NOCOPY ++ MOVQ DI,DX ++ LEAQ 360(R12),DI ++ MOVQ R9,CX ++ REP; MOVSB ++ LEAQ 360(R12),DI ++ LEAQ 360(R12),SI ++ NOCOPY: ++ MOVQ R9,352(R12) ++ MOVOA 48(R12),X0 ++ MOVOA 0(R12),X1 ++ MOVOA 16(R12),X2 ++ MOVOA 32(R12),X3 ++ MOVOA X1,X4 ++ MOVQ $20,CX ++ MAINLOOP2: ++ PADDL X0,X4 ++ MOVOA X0,X5 ++ MOVOA X4,X6 ++ PSLLL $7,X4 ++ PSRLL $25,X6 ++ PXOR X4,X3 ++ PXOR X6,X3 ++ PADDL X3,X5 ++ MOVOA X3,X4 ++ MOVOA X5,X6 ++ PSLLL $9,X5 ++ PSRLL $23,X6 ++ PXOR X5,X2 ++ PSHUFL $0X93,X3,X3 ++ PXOR X6,X2 ++ PADDL X2,X4 ++ MOVOA X2,X5 ++ MOVOA X4,X6 ++ PSLLL $13,X4 ++ PSRLL $19,X6 ++ PXOR X4,X1 ++ PSHUFL $0X4E,X2,X2 ++ PXOR X6,X1 ++ PADDL X1,X5 ++ MOVOA X3,X4 ++ MOVOA X5,X6 ++ PSLLL $18,X5 ++ PSRLL $14,X6 ++ PXOR X5,X0 ++ PSHUFL $0X39,X1,X1 ++ PXOR X6,X0 ++ PADDL X0,X4 ++ MOVOA X0,X5 ++ MOVOA X4,X6 ++ PSLLL $7,X4 ++ PSRLL $25,X6 ++ PXOR X4,X1 ++ PXOR X6,X1 ++ PADDL X1,X5 ++ MOVOA X1,X4 ++ MOVOA X5,X6 ++ PSLLL $9,X5 ++ PSRLL $23,X6 ++ PXOR X5,X2 ++ PSHUFL $0X93,X1,X1 ++ PXOR X6,X2 ++ PADDL X2,X4 ++ MOVOA X2,X5 ++ MOVOA X4,X6 ++ PSLLL $13,X4 ++ PSRLL $19,X6 ++ PXOR X4,X3 ++ PSHUFL $0X4E,X2,X2 ++ PXOR X6,X3 ++ PADDL X3,X5 ++ MOVOA X1,X4 ++ MOVOA X5,X6 ++ PSLLL $18,X5 ++ PSRLL $14,X6 ++ PXOR X5,X0 ++ PSHUFL $0X39,X3,X3 ++ PXOR X6,X0 ++ PADDL X0,X4 ++ MOVOA X0,X5 ++ MOVOA X4,X6 ++ PSLLL $7,X4 ++ PSRLL $25,X6 ++ PXOR X4,X3 ++ PXOR X6,X3 ++ PADDL X3,X5 ++ MOVOA X3,X4 ++ MOVOA X5,X6 ++ PSLLL $9,X5 ++ PSRLL $23,X6 ++ PXOR X5,X2 ++ PSHUFL $0X93,X3,X3 ++ PXOR X6,X2 ++ PADDL X2,X4 ++ MOVOA X2,X5 ++ MOVOA X4,X6 ++ PSLLL $13,X4 ++ PSRLL $19,X6 ++ PXOR X4,X1 ++ PSHUFL $0X4E,X2,X2 ++ PXOR X6,X1 ++ PADDL X1,X5 ++ MOVOA X3,X4 ++ MOVOA X5,X6 ++ PSLLL $18,X5 ++ PSRLL $14,X6 ++ PXOR X5,X0 ++ PSHUFL $0X39,X1,X1 ++ PXOR X6,X0 ++ PADDL X0,X4 ++ MOVOA X0,X5 ++ MOVOA X4,X6 ++ PSLLL $7,X4 ++ PSRLL $25,X6 ++ PXOR X4,X1 ++ PXOR X6,X1 ++ PADDL X1,X5 ++ MOVOA X1,X4 ++ MOVOA X5,X6 ++ PSLLL $9,X5 ++ PSRLL $23,X6 ++ PXOR X5,X2 ++ PSHUFL $0X93,X1,X1 ++ PXOR X6,X2 ++ PADDL X2,X4 ++ MOVOA X2,X5 ++ MOVOA X4,X6 ++ PSLLL $13,X4 ++ PSRLL $19,X6 ++ PXOR X4,X3 ++ PSHUFL $0X4E,X2,X2 ++ PXOR X6,X3 ++ SUBQ $4,CX ++ PADDL X3,X5 ++ MOVOA X1,X4 ++ MOVOA X5,X6 ++ PSLLL $18,X5 ++ PXOR X7,X7 ++ PSRLL $14,X6 ++ PXOR X5,X0 ++ PSHUFL $0X39,X3,X3 ++ PXOR X6,X0 ++ JA MAINLOOP2 ++ PADDL 48(R12),X0 ++ PADDL 0(R12),X1 ++ PADDL 16(R12),X2 ++ PADDL 32(R12),X3 ++ MOVD X0,CX ++ MOVD X1,R8 ++ MOVD X2,R9 ++ MOVD X3,AX ++ PSHUFL $0X39,X0,X0 ++ PSHUFL $0X39,X1,X1 ++ PSHUFL $0X39,X2,X2 ++ PSHUFL $0X39,X3,X3 ++ XORL 0(SI),CX ++ XORL 48(SI),R8 ++ XORL 32(SI),R9 ++ XORL 16(SI),AX ++ MOVL CX,0(DI) ++ MOVL R8,48(DI) ++ MOVL R9,32(DI) ++ MOVL AX,16(DI) ++ MOVD X0,CX ++ MOVD X1,R8 ++ MOVD X2,R9 ++ MOVD X3,AX ++ PSHUFL $0X39,X0,X0 ++ PSHUFL $0X39,X1,X1 ++ PSHUFL $0X39,X2,X2 ++ PSHUFL $0X39,X3,X3 ++ XORL 20(SI),CX ++ XORL 4(SI),R8 ++ XORL 52(SI),R9 ++ XORL 36(SI),AX ++ MOVL CX,20(DI) ++ MOVL R8,4(DI) ++ MOVL R9,52(DI) ++ MOVL AX,36(DI) ++ MOVD X0,CX ++ MOVD X1,R8 ++ MOVD X2,R9 ++ MOVD X3,AX ++ PSHUFL $0X39,X0,X0 ++ PSHUFL $0X39,X1,X1 ++ PSHUFL $0X39,X2,X2 ++ PSHUFL $0X39,X3,X3 ++ XORL 40(SI),CX ++ XORL 24(SI),R8 ++ XORL 8(SI),R9 ++ XORL 56(SI),AX ++ MOVL CX,40(DI) ++ MOVL R8,24(DI) ++ MOVL R9,8(DI) ++ MOVL AX,56(DI) ++ MOVD X0,CX ++ MOVD X1,R8 ++ MOVD X2,R9 ++ MOVD X3,AX ++ XORL 60(SI),CX ++ XORL 44(SI),R8 ++ XORL 28(SI),R9 ++ XORL 12(SI),AX ++ MOVL CX,60(DI) ++ MOVL R8,44(DI) ++ MOVL R9,28(DI) ++ MOVL AX,12(DI) ++ MOVQ 352(R12),R9 ++ MOVL 16(R12),CX ++ MOVL 36 (R12),R8 ++ ADDQ $1,CX ++ SHLQ $32,R8 ++ ADDQ R8,CX ++ MOVQ CX,R8 ++ SHRQ $32,R8 ++ MOVL CX,16(R12) ++ MOVL R8, 36 (R12) ++ CMPQ R9,$64 ++ JA BYTESATLEAST65 ++ JAE BYTESATLEAST64 ++ MOVQ DI,SI ++ MOVQ DX,DI ++ MOVQ R9,CX ++ REP; MOVSB ++ BYTESATLEAST64: ++ DONE: ++ RET ++ BYTESATLEAST65: ++ SUBQ $64,R9 ++ ADDQ $64,DI ++ ADDQ $64,SI ++ JMP BYTESBETWEEN1AND255 +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go +new file mode 100644 +index 00000000000000..fc781f76f96107 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go +@@ -0,0 +1,32 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && !purego && gc ++// +build amd64,!purego,gc ++ ++package salsa ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++func TestCounterOverflow(t *testing.T) { ++ in := make([]byte, 4096) ++ key := &[32]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, ++ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2} ++ for n, counter := range []*[16]byte{ ++ &[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // zero counter ++ &[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}, // counter about to overflow 32 bits ++ &[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff}, // counter above 32 bits ++ } { ++ out := make([]byte, 4096) ++ XORKeyStream(out, in, counter, key) ++ outGeneric := make([]byte, 4096) ++ genericXORKeyStream(outGeneric, in, counter, key) ++ if !bytes.Equal(out, outGeneric) { ++ t.Errorf("%d: assembly and go implementations disagree", n) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go +new file mode 100644 +index 00000000000000..4392cc1ac74024 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go +@@ -0,0 +1,15 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !amd64 || purego || !gc ++// +build !amd64 purego !gc ++ ++package salsa ++ ++// XORKeyStream crypts bytes from in to out using the given key and counters. ++// In and out must overlap entirely or not at all. Counter ++// contains the raw salsa20 counter bytes (both nonce and block counter). ++func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { ++ genericXORKeyStream(out, in, counter, key) ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go +new file mode 100644 +index 00000000000000..e5cdb9a25bee76 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go +@@ -0,0 +1,233 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package salsa ++ ++import "math/bits" ++ ++const rounds = 20 ++ ++// core applies the Salsa20 core function to 16-byte input in, 32-byte key k, ++// and 16-byte constant c, and puts the result into 64-byte array out. ++func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { ++ j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 ++ j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 ++ j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 ++ j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 ++ j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 ++ j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 ++ j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 ++ j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 ++ j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 ++ j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 ++ j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 ++ j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 ++ j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 ++ j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 ++ j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 ++ j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 ++ ++ x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 ++ x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 ++ ++ for i := 0; i < rounds; i += 2 { ++ u := x0 + x12 ++ x4 ^= bits.RotateLeft32(u, 7) ++ u = x4 + x0 ++ x8 ^= bits.RotateLeft32(u, 9) ++ u = x8 + x4 ++ x12 ^= bits.RotateLeft32(u, 13) ++ u = x12 + x8 ++ x0 ^= bits.RotateLeft32(u, 18) ++ ++ u = x5 + x1 ++ x9 ^= bits.RotateLeft32(u, 7) ++ u = x9 + x5 ++ x13 ^= bits.RotateLeft32(u, 9) ++ u = x13 + x9 ++ x1 ^= bits.RotateLeft32(u, 13) ++ u = x1 + x13 ++ x5 ^= bits.RotateLeft32(u, 18) ++ ++ u = x10 + x6 ++ x14 ^= bits.RotateLeft32(u, 7) ++ u = x14 + x10 ++ x2 ^= bits.RotateLeft32(u, 9) ++ u = x2 + x14 ++ x6 ^= bits.RotateLeft32(u, 13) ++ u = x6 + x2 ++ x10 ^= bits.RotateLeft32(u, 18) ++ ++ u = x15 + x11 ++ x3 ^= bits.RotateLeft32(u, 7) ++ u = x3 + x15 ++ x7 ^= bits.RotateLeft32(u, 9) ++ u = x7 + x3 ++ x11 ^= bits.RotateLeft32(u, 13) ++ u = x11 + x7 ++ x15 ^= bits.RotateLeft32(u, 18) ++ ++ u = x0 + x3 ++ x1 ^= bits.RotateLeft32(u, 7) ++ u = x1 + x0 ++ x2 ^= bits.RotateLeft32(u, 9) ++ u = x2 + x1 ++ x3 ^= bits.RotateLeft32(u, 13) ++ u = x3 + x2 ++ x0 ^= bits.RotateLeft32(u, 18) ++ ++ u = x5 + x4 ++ x6 ^= bits.RotateLeft32(u, 7) ++ u = x6 + x5 ++ x7 ^= bits.RotateLeft32(u, 9) ++ u = x7 + x6 ++ x4 ^= bits.RotateLeft32(u, 13) ++ u = x4 + x7 ++ x5 ^= bits.RotateLeft32(u, 18) ++ ++ u = x10 + x9 ++ x11 ^= bits.RotateLeft32(u, 7) ++ u = x11 + x10 ++ x8 ^= bits.RotateLeft32(u, 9) ++ u = x8 + x11 ++ x9 ^= bits.RotateLeft32(u, 13) ++ u = x9 + x8 ++ x10 ^= bits.RotateLeft32(u, 18) ++ ++ u = x15 + x14 ++ x12 ^= bits.RotateLeft32(u, 7) ++ u = x12 + x15 ++ x13 ^= bits.RotateLeft32(u, 9) ++ u = x13 + x12 ++ x14 ^= bits.RotateLeft32(u, 13) ++ u = x14 + x13 ++ x15 ^= bits.RotateLeft32(u, 18) ++ } ++ x0 += j0 ++ x1 += j1 ++ x2 += j2 ++ x3 += j3 ++ x4 += j4 ++ x5 += j5 ++ x6 += j6 ++ x7 += j7 ++ x8 += j8 ++ x9 += j9 ++ x10 += j10 ++ x11 += j11 ++ x12 += j12 ++ x13 += j13 ++ x14 += j14 ++ x15 += j15 ++ ++ out[0] = byte(x0) ++ out[1] = byte(x0 >> 8) ++ out[2] = byte(x0 >> 16) ++ out[3] = byte(x0 >> 24) ++ ++ out[4] = byte(x1) ++ out[5] = byte(x1 >> 8) ++ out[6] = byte(x1 >> 16) ++ out[7] = byte(x1 >> 24) ++ ++ out[8] = byte(x2) ++ out[9] = byte(x2 >> 8) ++ out[10] = byte(x2 >> 16) ++ out[11] = byte(x2 >> 24) ++ ++ out[12] = byte(x3) ++ out[13] = byte(x3 >> 8) ++ out[14] = byte(x3 >> 16) ++ out[15] = byte(x3 >> 24) ++ ++ out[16] = byte(x4) ++ out[17] = byte(x4 >> 8) ++ out[18] = byte(x4 >> 16) ++ out[19] = byte(x4 >> 24) ++ ++ out[20] = byte(x5) ++ out[21] = byte(x5 >> 8) ++ out[22] = byte(x5 >> 16) ++ out[23] = byte(x5 >> 24) ++ ++ out[24] = byte(x6) ++ out[25] = byte(x6 >> 8) ++ out[26] = byte(x6 >> 16) ++ out[27] = byte(x6 >> 24) ++ ++ out[28] = byte(x7) ++ out[29] = byte(x7 >> 8) ++ out[30] = byte(x7 >> 16) ++ out[31] = byte(x7 >> 24) ++ ++ out[32] = byte(x8) ++ out[33] = byte(x8 >> 8) ++ out[34] = byte(x8 >> 16) ++ out[35] = byte(x8 >> 24) ++ ++ out[36] = byte(x9) ++ out[37] = byte(x9 >> 8) ++ out[38] = byte(x9 >> 16) ++ out[39] = byte(x9 >> 24) ++ ++ out[40] = byte(x10) ++ out[41] = byte(x10 >> 8) ++ out[42] = byte(x10 >> 16) ++ out[43] = byte(x10 >> 24) ++ ++ out[44] = byte(x11) ++ out[45] = byte(x11 >> 8) ++ out[46] = byte(x11 >> 16) ++ out[47] = byte(x11 >> 24) ++ ++ out[48] = byte(x12) ++ out[49] = byte(x12 >> 8) ++ out[50] = byte(x12 >> 16) ++ out[51] = byte(x12 >> 24) ++ ++ out[52] = byte(x13) ++ out[53] = byte(x13 >> 8) ++ out[54] = byte(x13 >> 16) ++ out[55] = byte(x13 >> 24) ++ ++ out[56] = byte(x14) ++ out[57] = byte(x14 >> 8) ++ out[58] = byte(x14 >> 16) ++ out[59] = byte(x14 >> 24) ++ ++ out[60] = byte(x15) ++ out[61] = byte(x15 >> 8) ++ out[62] = byte(x15 >> 16) ++ out[63] = byte(x15 >> 24) ++} ++ ++// genericXORKeyStream is the generic implementation of XORKeyStream to be used ++// when no assembly implementation is available. ++func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { ++ var block [64]byte ++ var counterCopy [16]byte ++ copy(counterCopy[:], counter[:]) ++ ++ for len(in) >= 64 { ++ core(&block, &counterCopy, key, &Sigma) ++ for i, x := range block { ++ out[i] = in[i] ^ x ++ } ++ u := uint32(1) ++ for i := 8; i < 16; i++ { ++ u += uint32(counterCopy[i]) ++ counterCopy[i] = byte(u) ++ u >>= 8 ++ } ++ in = in[64:] ++ out = out[64:] ++ } ++ ++ if len(in) > 0 { ++ core(&block, &counterCopy, key, &Sigma) ++ for i, v := range in { ++ out[i] = v ^ block[i] ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go +new file mode 100644 +index 00000000000000..f67e94eba41793 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go +@@ -0,0 +1,54 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package salsa ++ ++import "testing" ++ ++func TestCore208(t *testing.T) { ++ in := [64]byte{ ++ 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, ++ 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, ++ 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, ++ 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, ++ 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, ++ 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, ++ 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, ++ 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e} ++ ++ out := [64]byte{ ++ 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, ++ 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, ++ 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, ++ 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, ++ 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, ++ 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, ++ 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, ++ 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, ++ } ++ ++ Core208(&in, &in) ++ if in != out { ++ t.Errorf("expected %x, got %x", out, in) ++ } ++} ++ ++func TestOutOfBoundsWrite(t *testing.T) { ++ // encrypted "0123456789" ++ cipherText := []byte{170, 166, 196, 104, 175, 121, 68, 44, 174, 51} ++ var counter [16]byte ++ var key [32]byte ++ want := "abcdefghij" ++ plainText := []byte(want) ++ defer func() { ++ err := recover() ++ if err == nil { ++ t.Error("XORKeyStream expected to panic on len(dst) < len(src), but didn't") ++ } ++ if plainText[3] == '3' { ++ t.Errorf("XORKeyStream did out of bounds write, want %v, got %v", want, string(plainText)) ++ } ++ }() ++ XORKeyStream(plainText[:3], cipherText, &counter, &key) ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa20.go b/ms_mod/golang.org/x/crypto/salsa20/salsa20.go +new file mode 100644 +index 00000000000000..8f4f896c70d3f0 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa20.go +@@ -0,0 +1,58 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++Package salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf. ++ ++Salsa20 differs from many other stream ciphers in that it is message orientated ++rather than byte orientated. Keystream blocks are not preserved between calls, ++therefore each side must encrypt/decrypt data with the same segmentation. ++ ++Another aspect of this difference is that part of the counter is exposed as ++a nonce in each call. Encrypting two different messages with the same (key, ++nonce) pair leads to trivial plaintext recovery. This is analogous to ++encrypting two different messages with the same key with a traditional stream ++cipher. ++ ++This package also implements XSalsa20: a version of Salsa20 with a 24-byte ++nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply ++passing a 24-byte slice as the nonce triggers XSalsa20. ++*/ ++package salsa20 // import "golang.org/x/crypto/salsa20" ++ ++// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. ++ ++import ( ++ "golang.org/x/crypto/internal/alias" ++ "golang.org/x/crypto/salsa20/salsa" ++) ++ ++// XORKeyStream crypts bytes from in to out using the given key and nonce. ++// In and out must overlap entirely or not at all. Nonce must ++// be either 8 or 24 bytes long. ++func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { ++ if len(out) < len(in) { ++ panic("salsa20: output smaller than input") ++ } ++ if alias.InexactOverlap(out[:len(in)], in) { ++ panic("salsa20: invalid buffer overlap") ++ } ++ ++ var subNonce [16]byte ++ ++ if len(nonce) == 24 { ++ var subKey [32]byte ++ var hNonce [16]byte ++ copy(hNonce[:], nonce[:16]) ++ salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma) ++ copy(subNonce[:], nonce[16:]) ++ key = &subKey ++ } else if len(nonce) == 8 { ++ copy(subNonce[:], nonce[:]) ++ } else { ++ panic("salsa20: nonce must be 8 or 24 bytes") ++ } ++ ++ salsa.XORKeyStream(out, in, &subNonce, key) ++} +diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go b/ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go +new file mode 100644 +index 00000000000000..0ef3328eb0a8dc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go +@@ -0,0 +1,139 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package salsa20 ++ ++import ( ++ "bytes" ++ "encoding/hex" ++ "testing" ++) ++ ++func fromHex(s string) []byte { ++ ret, err := hex.DecodeString(s) ++ if err != nil { ++ panic(err) ++ } ++ return ret ++} ++ ++// testVectors was taken from set 6 of the ECRYPT test vectors: ++// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup ++var testVectors = []struct { ++ key []byte ++ iv []byte ++ numBytes int ++ xor []byte ++}{ ++ { ++ fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"), ++ fromHex("0D74DB42A91077DE"), ++ 131072, ++ fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"), ++ }, ++ { ++ fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"), ++ fromHex("167DE44BB21980E7"), ++ 131072, ++ fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"), ++ }, ++ { ++ fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"), ++ fromHex("1F86ED54BB2289F0"), ++ 131072, ++ fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"), ++ }, ++ { ++ fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"), ++ fromHex("288FF65DC42B92F9"), ++ 131072, ++ fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"), ++ }, ++} ++ ++func TestSalsa20(t *testing.T) { ++ var inBuf, outBuf []byte ++ var key [32]byte ++ ++ for i, test := range testVectors { ++ if test.numBytes%64 != 0 { ++ t.Errorf("#%d: numBytes is not a multiple of 64", i) ++ continue ++ } ++ ++ if test.numBytes > len(inBuf) { ++ inBuf = make([]byte, test.numBytes) ++ outBuf = make([]byte, test.numBytes) ++ } ++ in := inBuf[:test.numBytes] ++ out := outBuf[:test.numBytes] ++ copy(key[:], test.key) ++ XORKeyStream(out, in, test.iv, &key) ++ ++ var xor [64]byte ++ for len(out) > 0 { ++ for i := 0; i < 64; i++ { ++ xor[i] ^= out[i] ++ } ++ out = out[64:] ++ } ++ ++ if !bytes.Equal(xor[:], test.xor) { ++ t.Errorf("#%d: bad result", i) ++ } ++ } ++} ++ ++var xSalsa20TestData = []struct { ++ in, nonce, key, out []byte ++}{ ++ { ++ []byte("Hello world!"), ++ []byte("24-byte nonce for xsalsa"), ++ []byte("this is 32-byte key for xsalsa20"), ++ []byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41}, ++ }, ++ { ++ make([]byte, 64), ++ []byte("24-byte nonce for xsalsa"), ++ []byte("this is 32-byte key for xsalsa20"), ++ []byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6, ++ 0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70, ++ 0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf, ++ 0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26, ++ 0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40, ++ 0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f, ++ 0x3a, 0x58, 0xe4, 0x76, 0x48}, ++ }, ++} ++ ++func TestXSalsa20(t *testing.T) { ++ var key [32]byte ++ ++ for i, test := range xSalsa20TestData { ++ out := make([]byte, len(test.in)) ++ copy(key[:], test.key) ++ XORKeyStream(out, test.in, test.nonce, &key) ++ if !bytes.Equal(out, test.out) { ++ t.Errorf("%d: expected %x, got %x", i, test.out, out) ++ } ++ } ++} ++ ++var ( ++ keyArray [32]byte ++ key = &keyArray ++ nonce [8]byte ++ msg = make([]byte, 1<<10) ++) ++ ++func BenchmarkXOR1K(b *testing.B) { ++ b.StopTimer() ++ out := make([]byte, 1024) ++ b.StartTimer() ++ for i := 0; i < b.N; i++ { ++ XORKeyStream(out, msg[:1024], nonce[:], key) ++ } ++ b.SetBytes(1024) ++} +diff --git a/ms_mod/golang.org/x/crypto/scrypt/example_test.go b/ms_mod/golang.org/x/crypto/scrypt/example_test.go +new file mode 100644 +index 00000000000000..6736479b196153 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/scrypt/example_test.go +@@ -0,0 +1,26 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package scrypt_test ++ ++import ( ++ "encoding/base64" ++ "fmt" ++ "log" ++ ++ "golang.org/x/crypto/scrypt" ++) ++ ++func Example() { ++ // DO NOT use this salt value; generate your own random salt. 8 bytes is ++ // a good length. ++ salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b} ++ ++ dk, err := scrypt.Key([]byte("some password"), salt, 1<<15, 8, 1, 32) ++ if err != nil { ++ log.Fatal(err) ++ } ++ fmt.Println(base64.StdEncoding.EncodeToString(dk)) ++ // Output: lGnMz8io0AUkfzn6Pls1qX20Vs7PGN6sbYQ2TQgY12M= ++} +diff --git a/ms_mod/golang.org/x/crypto/scrypt/scrypt.go b/ms_mod/golang.org/x/crypto/scrypt/scrypt.go +new file mode 100644 +index 00000000000000..c971a99fa67982 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/scrypt/scrypt.go +@@ -0,0 +1,212 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package scrypt implements the scrypt key derivation function as defined in ++// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard ++// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf). ++package scrypt // import "golang.org/x/crypto/scrypt" ++ ++import ( ++ "crypto/sha256" ++ "encoding/binary" ++ "errors" ++ "math/bits" ++ ++ "golang.org/x/crypto/pbkdf2" ++) ++ ++const maxInt = int(^uint(0) >> 1) ++ ++// blockCopy copies n numbers from src into dst. ++func blockCopy(dst, src []uint32, n int) { ++ copy(dst, src[:n]) ++} ++ ++// blockXOR XORs numbers from dst with n numbers from src. ++func blockXOR(dst, src []uint32, n int) { ++ for i, v := range src[:n] { ++ dst[i] ^= v ++ } ++} ++ ++// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in, ++// and puts the result into both tmp and out. ++func salsaXOR(tmp *[16]uint32, in, out []uint32) { ++ w0 := tmp[0] ^ in[0] ++ w1 := tmp[1] ^ in[1] ++ w2 := tmp[2] ^ in[2] ++ w3 := tmp[3] ^ in[3] ++ w4 := tmp[4] ^ in[4] ++ w5 := tmp[5] ^ in[5] ++ w6 := tmp[6] ^ in[6] ++ w7 := tmp[7] ^ in[7] ++ w8 := tmp[8] ^ in[8] ++ w9 := tmp[9] ^ in[9] ++ w10 := tmp[10] ^ in[10] ++ w11 := tmp[11] ^ in[11] ++ w12 := tmp[12] ^ in[12] ++ w13 := tmp[13] ^ in[13] ++ w14 := tmp[14] ^ in[14] ++ w15 := tmp[15] ^ in[15] ++ ++ x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8 ++ x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 ++ ++ for i := 0; i < 8; i += 2 { ++ x4 ^= bits.RotateLeft32(x0+x12, 7) ++ x8 ^= bits.RotateLeft32(x4+x0, 9) ++ x12 ^= bits.RotateLeft32(x8+x4, 13) ++ x0 ^= bits.RotateLeft32(x12+x8, 18) ++ ++ x9 ^= bits.RotateLeft32(x5+x1, 7) ++ x13 ^= bits.RotateLeft32(x9+x5, 9) ++ x1 ^= bits.RotateLeft32(x13+x9, 13) ++ x5 ^= bits.RotateLeft32(x1+x13, 18) ++ ++ x14 ^= bits.RotateLeft32(x10+x6, 7) ++ x2 ^= bits.RotateLeft32(x14+x10, 9) ++ x6 ^= bits.RotateLeft32(x2+x14, 13) ++ x10 ^= bits.RotateLeft32(x6+x2, 18) ++ ++ x3 ^= bits.RotateLeft32(x15+x11, 7) ++ x7 ^= bits.RotateLeft32(x3+x15, 9) ++ x11 ^= bits.RotateLeft32(x7+x3, 13) ++ x15 ^= bits.RotateLeft32(x11+x7, 18) ++ ++ x1 ^= bits.RotateLeft32(x0+x3, 7) ++ x2 ^= bits.RotateLeft32(x1+x0, 9) ++ x3 ^= bits.RotateLeft32(x2+x1, 13) ++ x0 ^= bits.RotateLeft32(x3+x2, 18) ++ ++ x6 ^= bits.RotateLeft32(x5+x4, 7) ++ x7 ^= bits.RotateLeft32(x6+x5, 9) ++ x4 ^= bits.RotateLeft32(x7+x6, 13) ++ x5 ^= bits.RotateLeft32(x4+x7, 18) ++ ++ x11 ^= bits.RotateLeft32(x10+x9, 7) ++ x8 ^= bits.RotateLeft32(x11+x10, 9) ++ x9 ^= bits.RotateLeft32(x8+x11, 13) ++ x10 ^= bits.RotateLeft32(x9+x8, 18) ++ ++ x12 ^= bits.RotateLeft32(x15+x14, 7) ++ x13 ^= bits.RotateLeft32(x12+x15, 9) ++ x14 ^= bits.RotateLeft32(x13+x12, 13) ++ x15 ^= bits.RotateLeft32(x14+x13, 18) ++ } ++ x0 += w0 ++ x1 += w1 ++ x2 += w2 ++ x3 += w3 ++ x4 += w4 ++ x5 += w5 ++ x6 += w6 ++ x7 += w7 ++ x8 += w8 ++ x9 += w9 ++ x10 += w10 ++ x11 += w11 ++ x12 += w12 ++ x13 += w13 ++ x14 += w14 ++ x15 += w15 ++ ++ out[0], tmp[0] = x0, x0 ++ out[1], tmp[1] = x1, x1 ++ out[2], tmp[2] = x2, x2 ++ out[3], tmp[3] = x3, x3 ++ out[4], tmp[4] = x4, x4 ++ out[5], tmp[5] = x5, x5 ++ out[6], tmp[6] = x6, x6 ++ out[7], tmp[7] = x7, x7 ++ out[8], tmp[8] = x8, x8 ++ out[9], tmp[9] = x9, x9 ++ out[10], tmp[10] = x10, x10 ++ out[11], tmp[11] = x11, x11 ++ out[12], tmp[12] = x12, x12 ++ out[13], tmp[13] = x13, x13 ++ out[14], tmp[14] = x14, x14 ++ out[15], tmp[15] = x15, x15 ++} ++ ++func blockMix(tmp *[16]uint32, in, out []uint32, r int) { ++ blockCopy(tmp[:], in[(2*r-1)*16:], 16) ++ for i := 0; i < 2*r; i += 2 { ++ salsaXOR(tmp, in[i*16:], out[i*8:]) ++ salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:]) ++ } ++} ++ ++func integer(b []uint32, r int) uint64 { ++ j := (2*r - 1) * 16 ++ return uint64(b[j]) | uint64(b[j+1])<<32 ++} ++ ++func smix(b []byte, r, N int, v, xy []uint32) { ++ var tmp [16]uint32 ++ R := 32 * r ++ x := xy ++ y := xy[R:] ++ ++ j := 0 ++ for i := 0; i < R; i++ { ++ x[i] = binary.LittleEndian.Uint32(b[j:]) ++ j += 4 ++ } ++ for i := 0; i < N; i += 2 { ++ blockCopy(v[i*R:], x, R) ++ blockMix(&tmp, x, y, r) ++ ++ blockCopy(v[(i+1)*R:], y, R) ++ blockMix(&tmp, y, x, r) ++ } ++ for i := 0; i < N; i += 2 { ++ j := int(integer(x, r) & uint64(N-1)) ++ blockXOR(x, v[j*R:], R) ++ blockMix(&tmp, x, y, r) ++ ++ j = int(integer(y, r) & uint64(N-1)) ++ blockXOR(y, v[j*R:], R) ++ blockMix(&tmp, y, x, r) ++ } ++ j = 0 ++ for _, v := range x[:R] { ++ binary.LittleEndian.PutUint32(b[j:], v) ++ j += 4 ++ } ++} ++ ++// Key derives a key from the password, salt, and cost parameters, returning ++// a byte slice of length keyLen that can be used as cryptographic key. ++// ++// N is a CPU/memory cost parameter, which must be a power of two greater than 1. ++// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the ++// limits, the function returns a nil byte slice and an error. ++// ++// For example, you can get a derived key for e.g. AES-256 (which needs a ++// 32-byte key) by doing: ++// ++// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) ++// ++// The recommended parameters for interactive logins as of 2017 are N=32768, r=8 ++// and p=1. The parameters N, r, and p should be increased as memory latency and ++// CPU parallelism increases; consider setting N to the highest power of 2 you ++// can derive within 100 milliseconds. Remember to get a good random salt. ++func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { ++ if N <= 1 || N&(N-1) != 0 { ++ return nil, errors.New("scrypt: N must be > 1 and a power of 2") ++ } ++ if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { ++ return nil, errors.New("scrypt: parameters are too large") ++ } ++ ++ xy := make([]uint32, 64*r) ++ v := make([]uint32, 32*N*r) ++ b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) ++ ++ for i := 0; i < p; i++ { ++ smix(b[i*128*r:], r, N, v, xy) ++ } ++ ++ return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil ++} +diff --git a/ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go b/ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go +new file mode 100644 +index 00000000000000..766ed8d9050250 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go +@@ -0,0 +1,162 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package scrypt ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++type testVector struct { ++ password string ++ salt string ++ N, r, p int ++ output []byte ++} ++ ++var good = []testVector{ ++ { ++ "password", ++ "salt", ++ 2, 10, 10, ++ []byte{ ++ 0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f, ++ 0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb, ++ 0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a, ++ 0xc5, 0xe5, 0xa, 0xa1, 0x5f, ++ }, ++ }, ++ { ++ "password", ++ "salt", ++ 16, 100, 100, ++ []byte{ ++ 0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18, ++ 0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e, ++ 0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5, ++ 0x7f, 0x91, 0x96, 0x3c, 0x37, ++ }, ++ }, ++ { ++ "this is a long \000 password", ++ "and this is a long \000 salt", ++ 16384, 8, 1, ++ []byte{ ++ 0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70, ++ 0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09, ++ 0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f, ++ 0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98, ++ 0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50, ++ 0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa, ++ 0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11, ++ 0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40, ++ 0x18, 0x79, 0xe6, 0x41, 0xae, ++ }, ++ }, ++ { ++ "p", ++ "s", ++ 2, 1, 1, ++ []byte{ ++ 0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98, ++ 0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52, ++ }, ++ }, ++ ++ { ++ "", ++ "", ++ 16, 1, 1, ++ []byte{ ++ 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b, ++ 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b, ++ 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa, ++ 0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d, ++ 0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f, ++ 0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, ++ 0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, ++ 0x06, ++ }, ++ }, ++ { ++ "password", ++ "NaCl", ++ 1024, 8, 16, ++ []byte{ ++ 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78, ++ 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a, ++ 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76, ++ 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9, ++ 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d, ++ 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, ++ 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, ++ 0x40, ++ }, ++ }, ++ { ++ "pleaseletmein", "SodiumChloride", ++ 16384, 8, 1, ++ []byte{ ++ 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46, ++ 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8, ++ 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43, ++ 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55, ++ 0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24, ++ 0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, ++ 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, ++ 0x87, ++ }, ++ }, ++ /* ++ // Disabled: needs 1 GiB RAM and takes too long for a simple test. ++ { ++ "pleaseletmein", "SodiumChloride", ++ 1048576, 8, 1, ++ []byte{ ++ 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad, ++ 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56, ++ 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee, ++ 0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f, ++ 0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c, ++ 0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, ++ 0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, ++ 0xa4, ++ }, ++ }, ++ */ ++} ++ ++var bad = []testVector{ ++ {"p", "s", 0, 1, 1, nil}, // N == 0 ++ {"p", "s", 1, 1, 1, nil}, // N == 1 ++ {"p", "s", 7, 8, 1, nil}, // N is not power of 2 ++ {"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large ++} ++ ++func TestKey(t *testing.T) { ++ for i, v := range good { ++ k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output)) ++ if err != nil { ++ t.Errorf("%d: got unexpected error: %s", i, err) ++ } ++ if !bytes.Equal(k, v.output) { ++ t.Errorf("%d: expected %x, got %x", i, v.output, k) ++ } ++ } ++ for i, v := range bad { ++ _, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32) ++ if err == nil { ++ t.Errorf("%d: expected error, got nil", i) ++ } ++ } ++} ++ ++var sink []byte ++ ++func BenchmarkKey(b *testing.B) { ++ for i := 0; i < b.N; i++ { ++ sink, _ = Key([]byte("password"), []byte("salt"), 1<<15, 8, 1, 64) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/doc.go b/ms_mod/golang.org/x/crypto/sha3/doc.go +new file mode 100644 +index 00000000000000..decd8cf9bf7491 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/doc.go +@@ -0,0 +1,62 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package sha3 implements the SHA-3 fixed-output-length hash functions and ++// the SHAKE variable-output-length hash functions defined by FIPS-202. ++// ++// Both types of hash function use the "sponge" construction and the Keccak ++// permutation. For a detailed specification see http://keccak.noekeon.org/ ++// ++// # Guidance ++// ++// If you aren't sure what function you need, use SHAKE256 with at least 64 ++// bytes of output. The SHAKE instances are faster than the SHA3 instances; ++// the latter have to allocate memory to conform to the hash.Hash interface. ++// ++// If you need a secret-key MAC (message authentication code), prepend the ++// secret key to the input, hash with SHAKE256 and read at least 32 bytes of ++// output. ++// ++// # Security strengths ++// ++// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security ++// strength against preimage attacks of x bits. Since they only produce "x" ++// bits of output, their collision-resistance is only "x/2" bits. ++// ++// The SHAKE-256 and -128 functions have a generic security strength of 256 and ++// 128 bits against all attacks, provided that at least 2x bits of their output ++// is used. Requesting more than 64 or 32 bytes of output, respectively, does ++// not increase the collision-resistance of the SHAKE functions. ++// ++// # The sponge construction ++// ++// A sponge builds a pseudo-random function from a public pseudo-random ++// permutation, by applying the permutation to a state of "rate + capacity" ++// bytes, but hiding "capacity" of the bytes. ++// ++// A sponge starts out with a zero state. To hash an input using a sponge, up ++// to "rate" bytes of the input are XORed into the sponge's state. The sponge ++// is then "full" and the permutation is applied to "empty" it. This process is ++// repeated until all the input has been "absorbed". The input is then padded. ++// The digest is "squeezed" from the sponge in the same way, except that output ++// is copied out instead of input being XORed in. ++// ++// A sponge is parameterized by its generic security strength, which is equal ++// to half its capacity; capacity + rate is equal to the permutation's width. ++// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means ++// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. ++// ++// # Recommendations ++// ++// The SHAKE functions are recommended for most new uses. They can produce ++// output of arbitrary length. SHAKE256, with an output length of at least ++// 64 bytes, provides 256-bit security against all attacks. The Keccak team ++// recommends it for most applications upgrading from SHA2-512. (NIST chose a ++// much stronger, but much slower, sponge instance for SHA3-512.) ++// ++// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. ++// They produce output of the same length, with the same security strengths ++// against all attacks. This means, in particular, that SHA3-256 only has ++// 128-bit collision resistance, because its output length is 32 bytes. ++package sha3 // import "golang.org/x/crypto/sha3" +diff --git a/ms_mod/golang.org/x/crypto/sha3/hashes.go b/ms_mod/golang.org/x/crypto/sha3/hashes.go +new file mode 100644 +index 00000000000000..28b94b633dc67e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/hashes.go +@@ -0,0 +1,116 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package sha3 ++ ++// This file provides functions for creating instances of the SHA-3 ++// and SHAKE hash functions, as well as utility functions for hashing ++// bytes. ++ ++import ( ++ "crypto" ++ "hash" ++ ++ "golang.org/x/crypto/internal/backend" ++) ++ ++// New224 creates a new SHA3-224 hash. ++// Its generic security strength is 224 bits against preimage attacks, ++// and 112 bits against collision attacks. ++func New224() hash.Hash { ++ if h := new224Asm(); h != nil { ++ return h ++ } ++ return &state{rate: 144, outputLen: 28, dsbyte: 0x06} ++} ++ ++// New256 creates a new SHA3-256 hash. ++// Its generic security strength is 256 bits against preimage attacks, ++// and 128 bits against collision attacks. ++func New256() hash.Hash { ++ if backend.Enabled { ++ if backend.SupportsHash(crypto.SHA3_256) { ++ println("using backend sha3_256") ++ return backend.NewSHA3_256() ++ } else { ++ println("backend doesn't support sha3_256") ++ } ++ } ++ if h := new256Asm(); h != nil { ++ return h ++ } ++ return &state{rate: 136, outputLen: 32, dsbyte: 0x06} ++} ++ ++// New384 creates a new SHA3-384 hash. ++// Its generic security strength is 384 bits against preimage attacks, ++// and 192 bits against collision attacks. ++func New384() hash.Hash { ++ if h := new384Asm(); h != nil { ++ return h ++ } ++ return &state{rate: 104, outputLen: 48, dsbyte: 0x06} ++} ++ ++// New512 creates a new SHA3-512 hash. ++// Its generic security strength is 512 bits against preimage attacks, ++// and 256 bits against collision attacks. ++func New512() hash.Hash { ++ if h := new512Asm(); h != nil { ++ return h ++ } ++ return &state{rate: 72, outputLen: 64, dsbyte: 0x06} ++} ++ ++// NewLegacyKeccak256 creates a new Keccak-256 hash. ++// ++// Only use this function if you require compatibility with an existing cryptosystem ++// that uses non-standard padding. All other users should use New256 instead. ++func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } ++ ++// NewLegacyKeccak512 creates a new Keccak-512 hash. ++// ++// Only use this function if you require compatibility with an existing cryptosystem ++// that uses non-standard padding. All other users should use New512 instead. ++func NewLegacyKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } ++ ++// Sum224 returns the SHA3-224 digest of the data. ++func Sum224(data []byte) (digest [28]byte) { ++ h := New224() ++ h.Write(data) ++ h.Sum(digest[:0]) ++ return ++} ++ ++// Sum256 returns the SHA3-256 digest of the data. ++func Sum256(data []byte) (digest [32]byte) { ++ if backend.Enabled { ++ if backend.SupportsHash(crypto.SHA3_256) { ++ println("using backend sha3_256") ++ return backend.SHA3_256(data) ++ } else { ++ println("backend doesn't support sha3_256") ++ } ++ } ++ h := New256() ++ h.Write(data) ++ h.Sum(digest[:0]) ++ return ++} ++ ++// Sum384 returns the SHA3-384 digest of the data. ++func Sum384(data []byte) (digest [48]byte) { ++ h := New384() ++ h.Write(data) ++ h.Sum(digest[:0]) ++ return ++} ++ ++// Sum512 returns the SHA3-512 digest of the data. ++func Sum512(data []byte) (digest [64]byte) { ++ h := New512() ++ h.Write(data) ++ h.Sum(digest[:0]) ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/hashes_generic.go b/ms_mod/golang.org/x/crypto/sha3/hashes_generic.go +new file mode 100644 +index 00000000000000..c74fc20fcb33b7 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/hashes_generic.go +@@ -0,0 +1,28 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !gc || purego || !s390x ++// +build !gc purego !s390x ++ ++package sha3 ++ ++import ( ++ "hash" ++) ++ ++// new224Asm returns an assembly implementation of SHA3-224 if available, ++// otherwise it returns nil. ++func new224Asm() hash.Hash { return nil } ++ ++// new256Asm returns an assembly implementation of SHA3-256 if available, ++// otherwise it returns nil. ++func new256Asm() hash.Hash { return nil } ++ ++// new384Asm returns an assembly implementation of SHA3-384 if available, ++// otherwise it returns nil. ++func new384Asm() hash.Hash { return nil } ++ ++// new512Asm returns an assembly implementation of SHA3-512 if available, ++// otherwise it returns nil. ++func new512Asm() hash.Hash { return nil } +diff --git a/ms_mod/golang.org/x/crypto/sha3/keccakf.go b/ms_mod/golang.org/x/crypto/sha3/keccakf.go +new file mode 100644 +index 00000000000000..e5faa375c04e87 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/keccakf.go +@@ -0,0 +1,415 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !amd64 || purego || !gc ++// +build !amd64 purego !gc ++ ++package sha3 ++ ++import "math/bits" ++ ++// rc stores the round constants for use in the ΞΉ step. ++var rc = [24]uint64{ ++ 0x0000000000000001, ++ 0x0000000000008082, ++ 0x800000000000808A, ++ 0x8000000080008000, ++ 0x000000000000808B, ++ 0x0000000080000001, ++ 0x8000000080008081, ++ 0x8000000000008009, ++ 0x000000000000008A, ++ 0x0000000000000088, ++ 0x0000000080008009, ++ 0x000000008000000A, ++ 0x000000008000808B, ++ 0x800000000000008B, ++ 0x8000000000008089, ++ 0x8000000000008003, ++ 0x8000000000008002, ++ 0x8000000000000080, ++ 0x000000000000800A, ++ 0x800000008000000A, ++ 0x8000000080008081, ++ 0x8000000000008080, ++ 0x0000000080000001, ++ 0x8000000080008008, ++} ++ ++// keccakF1600 applies the Keccak permutation to a 1600b-wide ++// state represented as a slice of 25 uint64s. ++func keccakF1600(a *[25]uint64) { ++ // Implementation translated from Keccak-inplace.c ++ // in the keccak reference code. ++ var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 ++ ++ for i := 0; i < 24; i += 4 { ++ // Combines the 5 steps in each round into 2 steps. ++ // Unrolls 4 rounds per loop and spreads some steps across rounds. ++ ++ // Round 1 ++ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] ++ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] ++ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] ++ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] ++ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] ++ d0 = bc4 ^ (bc1<<1 | bc1>>63) ++ d1 = bc0 ^ (bc2<<1 | bc2>>63) ++ d2 = bc1 ^ (bc3<<1 | bc3>>63) ++ d3 = bc2 ^ (bc4<<1 | bc4>>63) ++ d4 = bc3 ^ (bc0<<1 | bc0>>63) ++ ++ bc0 = a[0] ^ d0 ++ t = a[6] ^ d1 ++ bc1 = bits.RotateLeft64(t, 44) ++ t = a[12] ^ d2 ++ bc2 = bits.RotateLeft64(t, 43) ++ t = a[18] ^ d3 ++ bc3 = bits.RotateLeft64(t, 21) ++ t = a[24] ^ d4 ++ bc4 = bits.RotateLeft64(t, 14) ++ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] ++ a[6] = bc1 ^ (bc3 &^ bc2) ++ a[12] = bc2 ^ (bc4 &^ bc3) ++ a[18] = bc3 ^ (bc0 &^ bc4) ++ a[24] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[10] ^ d0 ++ bc2 = bits.RotateLeft64(t, 3) ++ t = a[16] ^ d1 ++ bc3 = bits.RotateLeft64(t, 45) ++ t = a[22] ^ d2 ++ bc4 = bits.RotateLeft64(t, 61) ++ t = a[3] ^ d3 ++ bc0 = bits.RotateLeft64(t, 28) ++ t = a[9] ^ d4 ++ bc1 = bits.RotateLeft64(t, 20) ++ a[10] = bc0 ^ (bc2 &^ bc1) ++ a[16] = bc1 ^ (bc3 &^ bc2) ++ a[22] = bc2 ^ (bc4 &^ bc3) ++ a[3] = bc3 ^ (bc0 &^ bc4) ++ a[9] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[20] ^ d0 ++ bc4 = bits.RotateLeft64(t, 18) ++ t = a[1] ^ d1 ++ bc0 = bits.RotateLeft64(t, 1) ++ t = a[7] ^ d2 ++ bc1 = bits.RotateLeft64(t, 6) ++ t = a[13] ^ d3 ++ bc2 = bits.RotateLeft64(t, 25) ++ t = a[19] ^ d4 ++ bc3 = bits.RotateLeft64(t, 8) ++ a[20] = bc0 ^ (bc2 &^ bc1) ++ a[1] = bc1 ^ (bc3 &^ bc2) ++ a[7] = bc2 ^ (bc4 &^ bc3) ++ a[13] = bc3 ^ (bc0 &^ bc4) ++ a[19] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[5] ^ d0 ++ bc1 = bits.RotateLeft64(t, 36) ++ t = a[11] ^ d1 ++ bc2 = bits.RotateLeft64(t, 10) ++ t = a[17] ^ d2 ++ bc3 = bits.RotateLeft64(t, 15) ++ t = a[23] ^ d3 ++ bc4 = bits.RotateLeft64(t, 56) ++ t = a[4] ^ d4 ++ bc0 = bits.RotateLeft64(t, 27) ++ a[5] = bc0 ^ (bc2 &^ bc1) ++ a[11] = bc1 ^ (bc3 &^ bc2) ++ a[17] = bc2 ^ (bc4 &^ bc3) ++ a[23] = bc3 ^ (bc0 &^ bc4) ++ a[4] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[15] ^ d0 ++ bc3 = bits.RotateLeft64(t, 41) ++ t = a[21] ^ d1 ++ bc4 = bits.RotateLeft64(t, 2) ++ t = a[2] ^ d2 ++ bc0 = bits.RotateLeft64(t, 62) ++ t = a[8] ^ d3 ++ bc1 = bits.RotateLeft64(t, 55) ++ t = a[14] ^ d4 ++ bc2 = bits.RotateLeft64(t, 39) ++ a[15] = bc0 ^ (bc2 &^ bc1) ++ a[21] = bc1 ^ (bc3 &^ bc2) ++ a[2] = bc2 ^ (bc4 &^ bc3) ++ a[8] = bc3 ^ (bc0 &^ bc4) ++ a[14] = bc4 ^ (bc1 &^ bc0) ++ ++ // Round 2 ++ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] ++ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] ++ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] ++ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] ++ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] ++ d0 = bc4 ^ (bc1<<1 | bc1>>63) ++ d1 = bc0 ^ (bc2<<1 | bc2>>63) ++ d2 = bc1 ^ (bc3<<1 | bc3>>63) ++ d3 = bc2 ^ (bc4<<1 | bc4>>63) ++ d4 = bc3 ^ (bc0<<1 | bc0>>63) ++ ++ bc0 = a[0] ^ d0 ++ t = a[16] ^ d1 ++ bc1 = bits.RotateLeft64(t, 44) ++ t = a[7] ^ d2 ++ bc2 = bits.RotateLeft64(t, 43) ++ t = a[23] ^ d3 ++ bc3 = bits.RotateLeft64(t, 21) ++ t = a[14] ^ d4 ++ bc4 = bits.RotateLeft64(t, 14) ++ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] ++ a[16] = bc1 ^ (bc3 &^ bc2) ++ a[7] = bc2 ^ (bc4 &^ bc3) ++ a[23] = bc3 ^ (bc0 &^ bc4) ++ a[14] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[20] ^ d0 ++ bc2 = bits.RotateLeft64(t, 3) ++ t = a[11] ^ d1 ++ bc3 = bits.RotateLeft64(t, 45) ++ t = a[2] ^ d2 ++ bc4 = bits.RotateLeft64(t, 61) ++ t = a[18] ^ d3 ++ bc0 = bits.RotateLeft64(t, 28) ++ t = a[9] ^ d4 ++ bc1 = bits.RotateLeft64(t, 20) ++ a[20] = bc0 ^ (bc2 &^ bc1) ++ a[11] = bc1 ^ (bc3 &^ bc2) ++ a[2] = bc2 ^ (bc4 &^ bc3) ++ a[18] = bc3 ^ (bc0 &^ bc4) ++ a[9] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[15] ^ d0 ++ bc4 = bits.RotateLeft64(t, 18) ++ t = a[6] ^ d1 ++ bc0 = bits.RotateLeft64(t, 1) ++ t = a[22] ^ d2 ++ bc1 = bits.RotateLeft64(t, 6) ++ t = a[13] ^ d3 ++ bc2 = bits.RotateLeft64(t, 25) ++ t = a[4] ^ d4 ++ bc3 = bits.RotateLeft64(t, 8) ++ a[15] = bc0 ^ (bc2 &^ bc1) ++ a[6] = bc1 ^ (bc3 &^ bc2) ++ a[22] = bc2 ^ (bc4 &^ bc3) ++ a[13] = bc3 ^ (bc0 &^ bc4) ++ a[4] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[10] ^ d0 ++ bc1 = bits.RotateLeft64(t, 36) ++ t = a[1] ^ d1 ++ bc2 = bits.RotateLeft64(t, 10) ++ t = a[17] ^ d2 ++ bc3 = bits.RotateLeft64(t, 15) ++ t = a[8] ^ d3 ++ bc4 = bits.RotateLeft64(t, 56) ++ t = a[24] ^ d4 ++ bc0 = bits.RotateLeft64(t, 27) ++ a[10] = bc0 ^ (bc2 &^ bc1) ++ a[1] = bc1 ^ (bc3 &^ bc2) ++ a[17] = bc2 ^ (bc4 &^ bc3) ++ a[8] = bc3 ^ (bc0 &^ bc4) ++ a[24] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[5] ^ d0 ++ bc3 = bits.RotateLeft64(t, 41) ++ t = a[21] ^ d1 ++ bc4 = bits.RotateLeft64(t, 2) ++ t = a[12] ^ d2 ++ bc0 = bits.RotateLeft64(t, 62) ++ t = a[3] ^ d3 ++ bc1 = bits.RotateLeft64(t, 55) ++ t = a[19] ^ d4 ++ bc2 = bits.RotateLeft64(t, 39) ++ a[5] = bc0 ^ (bc2 &^ bc1) ++ a[21] = bc1 ^ (bc3 &^ bc2) ++ a[12] = bc2 ^ (bc4 &^ bc3) ++ a[3] = bc3 ^ (bc0 &^ bc4) ++ a[19] = bc4 ^ (bc1 &^ bc0) ++ ++ // Round 3 ++ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] ++ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] ++ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] ++ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] ++ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] ++ d0 = bc4 ^ (bc1<<1 | bc1>>63) ++ d1 = bc0 ^ (bc2<<1 | bc2>>63) ++ d2 = bc1 ^ (bc3<<1 | bc3>>63) ++ d3 = bc2 ^ (bc4<<1 | bc4>>63) ++ d4 = bc3 ^ (bc0<<1 | bc0>>63) ++ ++ bc0 = a[0] ^ d0 ++ t = a[11] ^ d1 ++ bc1 = bits.RotateLeft64(t, 44) ++ t = a[22] ^ d2 ++ bc2 = bits.RotateLeft64(t, 43) ++ t = a[8] ^ d3 ++ bc3 = bits.RotateLeft64(t, 21) ++ t = a[19] ^ d4 ++ bc4 = bits.RotateLeft64(t, 14) ++ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] ++ a[11] = bc1 ^ (bc3 &^ bc2) ++ a[22] = bc2 ^ (bc4 &^ bc3) ++ a[8] = bc3 ^ (bc0 &^ bc4) ++ a[19] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[15] ^ d0 ++ bc2 = bits.RotateLeft64(t, 3) ++ t = a[1] ^ d1 ++ bc3 = bits.RotateLeft64(t, 45) ++ t = a[12] ^ d2 ++ bc4 = bits.RotateLeft64(t, 61) ++ t = a[23] ^ d3 ++ bc0 = bits.RotateLeft64(t, 28) ++ t = a[9] ^ d4 ++ bc1 = bits.RotateLeft64(t, 20) ++ a[15] = bc0 ^ (bc2 &^ bc1) ++ a[1] = bc1 ^ (bc3 &^ bc2) ++ a[12] = bc2 ^ (bc4 &^ bc3) ++ a[23] = bc3 ^ (bc0 &^ bc4) ++ a[9] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[5] ^ d0 ++ bc4 = bits.RotateLeft64(t, 18) ++ t = a[16] ^ d1 ++ bc0 = bits.RotateLeft64(t, 1) ++ t = a[2] ^ d2 ++ bc1 = bits.RotateLeft64(t, 6) ++ t = a[13] ^ d3 ++ bc2 = bits.RotateLeft64(t, 25) ++ t = a[24] ^ d4 ++ bc3 = bits.RotateLeft64(t, 8) ++ a[5] = bc0 ^ (bc2 &^ bc1) ++ a[16] = bc1 ^ (bc3 &^ bc2) ++ a[2] = bc2 ^ (bc4 &^ bc3) ++ a[13] = bc3 ^ (bc0 &^ bc4) ++ a[24] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[20] ^ d0 ++ bc1 = bits.RotateLeft64(t, 36) ++ t = a[6] ^ d1 ++ bc2 = bits.RotateLeft64(t, 10) ++ t = a[17] ^ d2 ++ bc3 = bits.RotateLeft64(t, 15) ++ t = a[3] ^ d3 ++ bc4 = bits.RotateLeft64(t, 56) ++ t = a[14] ^ d4 ++ bc0 = bits.RotateLeft64(t, 27) ++ a[20] = bc0 ^ (bc2 &^ bc1) ++ a[6] = bc1 ^ (bc3 &^ bc2) ++ a[17] = bc2 ^ (bc4 &^ bc3) ++ a[3] = bc3 ^ (bc0 &^ bc4) ++ a[14] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[10] ^ d0 ++ bc3 = bits.RotateLeft64(t, 41) ++ t = a[21] ^ d1 ++ bc4 = bits.RotateLeft64(t, 2) ++ t = a[7] ^ d2 ++ bc0 = bits.RotateLeft64(t, 62) ++ t = a[18] ^ d3 ++ bc1 = bits.RotateLeft64(t, 55) ++ t = a[4] ^ d4 ++ bc2 = bits.RotateLeft64(t, 39) ++ a[10] = bc0 ^ (bc2 &^ bc1) ++ a[21] = bc1 ^ (bc3 &^ bc2) ++ a[7] = bc2 ^ (bc4 &^ bc3) ++ a[18] = bc3 ^ (bc0 &^ bc4) ++ a[4] = bc4 ^ (bc1 &^ bc0) ++ ++ // Round 4 ++ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] ++ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] ++ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] ++ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] ++ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] ++ d0 = bc4 ^ (bc1<<1 | bc1>>63) ++ d1 = bc0 ^ (bc2<<1 | bc2>>63) ++ d2 = bc1 ^ (bc3<<1 | bc3>>63) ++ d3 = bc2 ^ (bc4<<1 | bc4>>63) ++ d4 = bc3 ^ (bc0<<1 | bc0>>63) ++ ++ bc0 = a[0] ^ d0 ++ t = a[1] ^ d1 ++ bc1 = bits.RotateLeft64(t, 44) ++ t = a[2] ^ d2 ++ bc2 = bits.RotateLeft64(t, 43) ++ t = a[3] ^ d3 ++ bc3 = bits.RotateLeft64(t, 21) ++ t = a[4] ^ d4 ++ bc4 = bits.RotateLeft64(t, 14) ++ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] ++ a[1] = bc1 ^ (bc3 &^ bc2) ++ a[2] = bc2 ^ (bc4 &^ bc3) ++ a[3] = bc3 ^ (bc0 &^ bc4) ++ a[4] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[5] ^ d0 ++ bc2 = bits.RotateLeft64(t, 3) ++ t = a[6] ^ d1 ++ bc3 = bits.RotateLeft64(t, 45) ++ t = a[7] ^ d2 ++ bc4 = bits.RotateLeft64(t, 61) ++ t = a[8] ^ d3 ++ bc0 = bits.RotateLeft64(t, 28) ++ t = a[9] ^ d4 ++ bc1 = bits.RotateLeft64(t, 20) ++ a[5] = bc0 ^ (bc2 &^ bc1) ++ a[6] = bc1 ^ (bc3 &^ bc2) ++ a[7] = bc2 ^ (bc4 &^ bc3) ++ a[8] = bc3 ^ (bc0 &^ bc4) ++ a[9] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[10] ^ d0 ++ bc4 = bits.RotateLeft64(t, 18) ++ t = a[11] ^ d1 ++ bc0 = bits.RotateLeft64(t, 1) ++ t = a[12] ^ d2 ++ bc1 = bits.RotateLeft64(t, 6) ++ t = a[13] ^ d3 ++ bc2 = bits.RotateLeft64(t, 25) ++ t = a[14] ^ d4 ++ bc3 = bits.RotateLeft64(t, 8) ++ a[10] = bc0 ^ (bc2 &^ bc1) ++ a[11] = bc1 ^ (bc3 &^ bc2) ++ a[12] = bc2 ^ (bc4 &^ bc3) ++ a[13] = bc3 ^ (bc0 &^ bc4) ++ a[14] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[15] ^ d0 ++ bc1 = bits.RotateLeft64(t, 36) ++ t = a[16] ^ d1 ++ bc2 = bits.RotateLeft64(t, 10) ++ t = a[17] ^ d2 ++ bc3 = bits.RotateLeft64(t, 15) ++ t = a[18] ^ d3 ++ bc4 = bits.RotateLeft64(t, 56) ++ t = a[19] ^ d4 ++ bc0 = bits.RotateLeft64(t, 27) ++ a[15] = bc0 ^ (bc2 &^ bc1) ++ a[16] = bc1 ^ (bc3 &^ bc2) ++ a[17] = bc2 ^ (bc4 &^ bc3) ++ a[18] = bc3 ^ (bc0 &^ bc4) ++ a[19] = bc4 ^ (bc1 &^ bc0) ++ ++ t = a[20] ^ d0 ++ bc3 = bits.RotateLeft64(t, 41) ++ t = a[21] ^ d1 ++ bc4 = bits.RotateLeft64(t, 2) ++ t = a[22] ^ d2 ++ bc0 = bits.RotateLeft64(t, 62) ++ t = a[23] ^ d3 ++ bc1 = bits.RotateLeft64(t, 55) ++ t = a[24] ^ d4 ++ bc2 = bits.RotateLeft64(t, 39) ++ a[20] = bc0 ^ (bc2 &^ bc1) ++ a[21] = bc1 ^ (bc3 &^ bc2) ++ a[22] = bc2 ^ (bc4 &^ bc3) ++ a[23] = bc3 ^ (bc0 &^ bc4) ++ a[24] = bc4 ^ (bc1 &^ bc0) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go +new file mode 100644 +index 00000000000000..248a38241ff9cf +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go +@@ -0,0 +1,14 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && !purego && gc ++// +build amd64,!purego,gc ++ ++package sha3 ++ ++// This function is implemented in keccakf_amd64.s. ++ ++//go:noescape ++ ++func keccakF1600(a *[25]uint64) +diff --git a/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s +new file mode 100644 +index 00000000000000..4cfa54383bfa83 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s +@@ -0,0 +1,391 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build amd64 && !purego && gc ++// +build amd64,!purego,gc ++ ++// This code was translated into a form compatible with 6a from the public ++// domain sources at https://github.com/gvanas/KeccakCodePackage ++ ++// Offsets in state ++#define _ba (0*8) ++#define _be (1*8) ++#define _bi (2*8) ++#define _bo (3*8) ++#define _bu (4*8) ++#define _ga (5*8) ++#define _ge (6*8) ++#define _gi (7*8) ++#define _go (8*8) ++#define _gu (9*8) ++#define _ka (10*8) ++#define _ke (11*8) ++#define _ki (12*8) ++#define _ko (13*8) ++#define _ku (14*8) ++#define _ma (15*8) ++#define _me (16*8) ++#define _mi (17*8) ++#define _mo (18*8) ++#define _mu (19*8) ++#define _sa (20*8) ++#define _se (21*8) ++#define _si (22*8) ++#define _so (23*8) ++#define _su (24*8) ++ ++// Temporary registers ++#define rT1 AX ++ ++// Round vars ++#define rpState DI ++#define rpStack SP ++ ++#define rDa BX ++#define rDe CX ++#define rDi DX ++#define rDo R8 ++#define rDu R9 ++ ++#define rBa R10 ++#define rBe R11 ++#define rBi R12 ++#define rBo R13 ++#define rBu R14 ++ ++#define rCa SI ++#define rCe BP ++#define rCi rBi ++#define rCo rBo ++#define rCu R15 ++ ++#define MOVQ_RBI_RCE MOVQ rBi, rCe ++#define XORQ_RT1_RCA XORQ rT1, rCa ++#define XORQ_RT1_RCE XORQ rT1, rCe ++#define XORQ_RBA_RCU XORQ rBa, rCu ++#define XORQ_RBE_RCU XORQ rBe, rCu ++#define XORQ_RDU_RCU XORQ rDu, rCu ++#define XORQ_RDA_RCA XORQ rDa, rCa ++#define XORQ_RDE_RCE XORQ rDe, rCe ++ ++#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ ++ /* Prepare round */ \ ++ MOVQ rCe, rDa; \ ++ ROLQ $1, rDa; \ ++ \ ++ MOVQ _bi(iState), rCi; \ ++ XORQ _gi(iState), rDi; \ ++ XORQ rCu, rDa; \ ++ XORQ _ki(iState), rCi; \ ++ XORQ _mi(iState), rDi; \ ++ XORQ rDi, rCi; \ ++ \ ++ MOVQ rCi, rDe; \ ++ ROLQ $1, rDe; \ ++ \ ++ MOVQ _bo(iState), rCo; \ ++ XORQ _go(iState), rDo; \ ++ XORQ rCa, rDe; \ ++ XORQ _ko(iState), rCo; \ ++ XORQ _mo(iState), rDo; \ ++ XORQ rDo, rCo; \ ++ \ ++ MOVQ rCo, rDi; \ ++ ROLQ $1, rDi; \ ++ \ ++ MOVQ rCu, rDo; \ ++ XORQ rCe, rDi; \ ++ ROLQ $1, rDo; \ ++ \ ++ MOVQ rCa, rDu; \ ++ XORQ rCi, rDo; \ ++ ROLQ $1, rDu; \ ++ \ ++ /* Result b */ \ ++ MOVQ _ba(iState), rBa; \ ++ MOVQ _ge(iState), rBe; \ ++ XORQ rCo, rDu; \ ++ MOVQ _ki(iState), rBi; \ ++ MOVQ _mo(iState), rBo; \ ++ MOVQ _su(iState), rBu; \ ++ XORQ rDe, rBe; \ ++ ROLQ $44, rBe; \ ++ XORQ rDi, rBi; \ ++ XORQ rDa, rBa; \ ++ ROLQ $43, rBi; \ ++ \ ++ MOVQ rBe, rCa; \ ++ MOVQ rc, rT1; \ ++ ORQ rBi, rCa; \ ++ XORQ rBa, rT1; \ ++ XORQ rT1, rCa; \ ++ MOVQ rCa, _ba(oState); \ ++ \ ++ XORQ rDu, rBu; \ ++ ROLQ $14, rBu; \ ++ MOVQ rBa, rCu; \ ++ ANDQ rBe, rCu; \ ++ XORQ rBu, rCu; \ ++ MOVQ rCu, _bu(oState); \ ++ \ ++ XORQ rDo, rBo; \ ++ ROLQ $21, rBo; \ ++ MOVQ rBo, rT1; \ ++ ANDQ rBu, rT1; \ ++ XORQ rBi, rT1; \ ++ MOVQ rT1, _bi(oState); \ ++ \ ++ NOTQ rBi; \ ++ ORQ rBa, rBu; \ ++ ORQ rBo, rBi; \ ++ XORQ rBo, rBu; \ ++ XORQ rBe, rBi; \ ++ MOVQ rBu, _bo(oState); \ ++ MOVQ rBi, _be(oState); \ ++ B_RBI_RCE; \ ++ \ ++ /* Result g */ \ ++ MOVQ _gu(iState), rBe; \ ++ XORQ rDu, rBe; \ ++ MOVQ _ka(iState), rBi; \ ++ ROLQ $20, rBe; \ ++ XORQ rDa, rBi; \ ++ ROLQ $3, rBi; \ ++ MOVQ _bo(iState), rBa; \ ++ MOVQ rBe, rT1; \ ++ ORQ rBi, rT1; \ ++ XORQ rDo, rBa; \ ++ MOVQ _me(iState), rBo; \ ++ MOVQ _si(iState), rBu; \ ++ ROLQ $28, rBa; \ ++ XORQ rBa, rT1; \ ++ MOVQ rT1, _ga(oState); \ ++ G_RT1_RCA; \ ++ \ ++ XORQ rDe, rBo; \ ++ ROLQ $45, rBo; \ ++ MOVQ rBi, rT1; \ ++ ANDQ rBo, rT1; \ ++ XORQ rBe, rT1; \ ++ MOVQ rT1, _ge(oState); \ ++ G_RT1_RCE; \ ++ \ ++ XORQ rDi, rBu; \ ++ ROLQ $61, rBu; \ ++ MOVQ rBu, rT1; \ ++ ORQ rBa, rT1; \ ++ XORQ rBo, rT1; \ ++ MOVQ rT1, _go(oState); \ ++ \ ++ ANDQ rBe, rBa; \ ++ XORQ rBu, rBa; \ ++ MOVQ rBa, _gu(oState); \ ++ NOTQ rBu; \ ++ G_RBA_RCU; \ ++ \ ++ ORQ rBu, rBo; \ ++ XORQ rBi, rBo; \ ++ MOVQ rBo, _gi(oState); \ ++ \ ++ /* Result k */ \ ++ MOVQ _be(iState), rBa; \ ++ MOVQ _gi(iState), rBe; \ ++ MOVQ _ko(iState), rBi; \ ++ MOVQ _mu(iState), rBo; \ ++ MOVQ _sa(iState), rBu; \ ++ XORQ rDi, rBe; \ ++ ROLQ $6, rBe; \ ++ XORQ rDo, rBi; \ ++ ROLQ $25, rBi; \ ++ MOVQ rBe, rT1; \ ++ ORQ rBi, rT1; \ ++ XORQ rDe, rBa; \ ++ ROLQ $1, rBa; \ ++ XORQ rBa, rT1; \ ++ MOVQ rT1, _ka(oState); \ ++ K_RT1_RCA; \ ++ \ ++ XORQ rDu, rBo; \ ++ ROLQ $8, rBo; \ ++ MOVQ rBi, rT1; \ ++ ANDQ rBo, rT1; \ ++ XORQ rBe, rT1; \ ++ MOVQ rT1, _ke(oState); \ ++ K_RT1_RCE; \ ++ \ ++ XORQ rDa, rBu; \ ++ ROLQ $18, rBu; \ ++ NOTQ rBo; \ ++ MOVQ rBo, rT1; \ ++ ANDQ rBu, rT1; \ ++ XORQ rBi, rT1; \ ++ MOVQ rT1, _ki(oState); \ ++ \ ++ MOVQ rBu, rT1; \ ++ ORQ rBa, rT1; \ ++ XORQ rBo, rT1; \ ++ MOVQ rT1, _ko(oState); \ ++ \ ++ ANDQ rBe, rBa; \ ++ XORQ rBu, rBa; \ ++ MOVQ rBa, _ku(oState); \ ++ K_RBA_RCU; \ ++ \ ++ /* Result m */ \ ++ MOVQ _ga(iState), rBe; \ ++ XORQ rDa, rBe; \ ++ MOVQ _ke(iState), rBi; \ ++ ROLQ $36, rBe; \ ++ XORQ rDe, rBi; \ ++ MOVQ _bu(iState), rBa; \ ++ ROLQ $10, rBi; \ ++ MOVQ rBe, rT1; \ ++ MOVQ _mi(iState), rBo; \ ++ ANDQ rBi, rT1; \ ++ XORQ rDu, rBa; \ ++ MOVQ _so(iState), rBu; \ ++ ROLQ $27, rBa; \ ++ XORQ rBa, rT1; \ ++ MOVQ rT1, _ma(oState); \ ++ M_RT1_RCA; \ ++ \ ++ XORQ rDi, rBo; \ ++ ROLQ $15, rBo; \ ++ MOVQ rBi, rT1; \ ++ ORQ rBo, rT1; \ ++ XORQ rBe, rT1; \ ++ MOVQ rT1, _me(oState); \ ++ M_RT1_RCE; \ ++ \ ++ XORQ rDo, rBu; \ ++ ROLQ $56, rBu; \ ++ NOTQ rBo; \ ++ MOVQ rBo, rT1; \ ++ ORQ rBu, rT1; \ ++ XORQ rBi, rT1; \ ++ MOVQ rT1, _mi(oState); \ ++ \ ++ ORQ rBa, rBe; \ ++ XORQ rBu, rBe; \ ++ MOVQ rBe, _mu(oState); \ ++ \ ++ ANDQ rBa, rBu; \ ++ XORQ rBo, rBu; \ ++ MOVQ rBu, _mo(oState); \ ++ M_RBE_RCU; \ ++ \ ++ /* Result s */ \ ++ MOVQ _bi(iState), rBa; \ ++ MOVQ _go(iState), rBe; \ ++ MOVQ _ku(iState), rBi; \ ++ XORQ rDi, rBa; \ ++ MOVQ _ma(iState), rBo; \ ++ ROLQ $62, rBa; \ ++ XORQ rDo, rBe; \ ++ MOVQ _se(iState), rBu; \ ++ ROLQ $55, rBe; \ ++ \ ++ XORQ rDu, rBi; \ ++ MOVQ rBa, rDu; \ ++ XORQ rDe, rBu; \ ++ ROLQ $2, rBu; \ ++ ANDQ rBe, rDu; \ ++ XORQ rBu, rDu; \ ++ MOVQ rDu, _su(oState); \ ++ \ ++ ROLQ $39, rBi; \ ++ S_RDU_RCU; \ ++ NOTQ rBe; \ ++ XORQ rDa, rBo; \ ++ MOVQ rBe, rDa; \ ++ ANDQ rBi, rDa; \ ++ XORQ rBa, rDa; \ ++ MOVQ rDa, _sa(oState); \ ++ S_RDA_RCA; \ ++ \ ++ ROLQ $41, rBo; \ ++ MOVQ rBi, rDe; \ ++ ORQ rBo, rDe; \ ++ XORQ rBe, rDe; \ ++ MOVQ rDe, _se(oState); \ ++ S_RDE_RCE; \ ++ \ ++ MOVQ rBo, rDi; \ ++ MOVQ rBu, rDo; \ ++ ANDQ rBu, rDi; \ ++ ORQ rBa, rDo; \ ++ XORQ rBi, rDi; \ ++ XORQ rBo, rDo; \ ++ MOVQ rDi, _si(oState); \ ++ MOVQ rDo, _so(oState) \ ++ ++// func keccakF1600(state *[25]uint64) ++TEXT Β·keccakF1600(SB), 0, $200-8 ++ MOVQ state+0(FP), rpState ++ ++ // Convert the user state into an internal state ++ NOTQ _be(rpState) ++ NOTQ _bi(rpState) ++ NOTQ _go(rpState) ++ NOTQ _ki(rpState) ++ NOTQ _mi(rpState) ++ NOTQ _sa(rpState) ++ ++ // Execute the KeccakF permutation ++ MOVQ _ba(rpState), rCa ++ MOVQ _be(rpState), rCe ++ MOVQ _bu(rpState), rCu ++ ++ XORQ _ga(rpState), rCa ++ XORQ _ge(rpState), rCe ++ XORQ _gu(rpState), rCu ++ ++ XORQ _ka(rpState), rCa ++ XORQ _ke(rpState), rCe ++ XORQ _ku(rpState), rCu ++ ++ XORQ _ma(rpState), rCa ++ XORQ _me(rpState), rCe ++ XORQ _mu(rpState), rCu ++ ++ XORQ _sa(rpState), rCa ++ XORQ _se(rpState), rCe ++ MOVQ _si(rpState), rDi ++ MOVQ _so(rpState), rDo ++ XORQ _su(rpState), rCu ++ ++ mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) ++ mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) ++ ++ // Revert the internal state to the user state ++ NOTQ _be(rpState) ++ NOTQ _bi(rpState) ++ NOTQ _go(rpState) ++ NOTQ _ki(rpState) ++ NOTQ _mi(rpState) ++ NOTQ _sa(rpState) ++ ++ RET +diff --git a/ms_mod/golang.org/x/crypto/sha3/register.go b/ms_mod/golang.org/x/crypto/sha3/register.go +new file mode 100644 +index 00000000000000..8b4453aac3c332 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/register.go +@@ -0,0 +1,19 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.4 ++// +build go1.4 ++ ++package sha3 ++ ++import ( ++ "crypto" ++) ++ ++func init() { ++ crypto.RegisterHash(crypto.SHA3_224, New224) ++ crypto.RegisterHash(crypto.SHA3_256, New256) ++ crypto.RegisterHash(crypto.SHA3_384, New384) ++ crypto.RegisterHash(crypto.SHA3_512, New512) ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3.go b/ms_mod/golang.org/x/crypto/sha3/sha3.go +new file mode 100644 +index 00000000000000..fa182beb40b509 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/sha3.go +@@ -0,0 +1,193 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package sha3 ++ ++// spongeDirection indicates the direction bytes are flowing through the sponge. ++type spongeDirection int ++ ++const ( ++ // spongeAbsorbing indicates that the sponge is absorbing input. ++ spongeAbsorbing spongeDirection = iota ++ // spongeSqueezing indicates that the sponge is being squeezed. ++ spongeSqueezing ++) ++ ++const ( ++ // maxRate is the maximum size of the internal buffer. SHAKE-256 ++ // currently needs the largest buffer. ++ maxRate = 168 ++) ++ ++type state struct { ++ // Generic sponge components. ++ a [25]uint64 // main state of the hash ++ buf []byte // points into storage ++ rate int // the number of bytes of state to use ++ ++ // dsbyte contains the "domain separation" bits and the first bit of ++ // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the ++ // SHA-3 and SHAKE functions by appending bitstrings to the message. ++ // Using a little-endian bit-ordering convention, these are "01" for SHA-3 ++ // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the ++ // padding rule from section 5.1 is applied to pad the message to a multiple ++ // of the rate, which involves adding a "1" bit, zero or more "0" bits, and ++ // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, ++ // giving 00000110b (0x06) and 00011111b (0x1f). ++ // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf ++ // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and ++ // Extendable-Output Functions (May 2014)" ++ dsbyte byte ++ ++ storage storageBuf ++ ++ // Specific to SHA-3 and SHAKE. ++ outputLen int // the default output size in bytes ++ state spongeDirection // whether the sponge is absorbing or squeezing ++} ++ ++// BlockSize returns the rate of sponge underlying this hash function. ++func (d *state) BlockSize() int { return d.rate } ++ ++// Size returns the output size of the hash function in bytes. ++func (d *state) Size() int { return d.outputLen } ++ ++// Reset clears the internal state by zeroing the sponge state and ++// the byte buffer, and setting Sponge.state to absorbing. ++func (d *state) Reset() { ++ // Zero the permutation's state. ++ for i := range d.a { ++ d.a[i] = 0 ++ } ++ d.state = spongeAbsorbing ++ d.buf = d.storage.asBytes()[:0] ++} ++ ++func (d *state) clone() *state { ++ ret := *d ++ if ret.state == spongeAbsorbing { ++ ret.buf = ret.storage.asBytes()[:len(ret.buf)] ++ } else { ++ ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate] ++ } ++ ++ return &ret ++} ++ ++// permute applies the KeccakF-1600 permutation. It handles ++// any input-output buffering. ++func (d *state) permute() { ++ switch d.state { ++ case spongeAbsorbing: ++ // If we're absorbing, we need to xor the input into the state ++ // before applying the permutation. ++ xorIn(d, d.buf) ++ d.buf = d.storage.asBytes()[:0] ++ keccakF1600(&d.a) ++ case spongeSqueezing: ++ // If we're squeezing, we need to apply the permutation before ++ // copying more output. ++ keccakF1600(&d.a) ++ d.buf = d.storage.asBytes()[:d.rate] ++ copyOut(d, d.buf) ++ } ++} ++ ++// pads appends the domain separation bits in dsbyte, applies ++// the multi-bitrate 10..1 padding rule, and permutes the state. ++func (d *state) padAndPermute(dsbyte byte) { ++ if d.buf == nil { ++ d.buf = d.storage.asBytes()[:0] ++ } ++ // Pad with this instance's domain-separator bits. We know that there's ++ // at least one byte of space in d.buf because, if it were full, ++ // permute would have been called to empty it. dsbyte also contains the ++ // first one bit for the padding. See the comment in the state struct. ++ d.buf = append(d.buf, dsbyte) ++ zerosStart := len(d.buf) ++ d.buf = d.storage.asBytes()[:d.rate] ++ for i := zerosStart; i < d.rate; i++ { ++ d.buf[i] = 0 ++ } ++ // This adds the final one bit for the padding. Because of the way that ++ // bits are numbered from the LSB upwards, the final bit is the MSB of ++ // the last byte. ++ d.buf[d.rate-1] ^= 0x80 ++ // Apply the permutation ++ d.permute() ++ d.state = spongeSqueezing ++ d.buf = d.storage.asBytes()[:d.rate] ++ copyOut(d, d.buf) ++} ++ ++// Write absorbs more data into the hash's state. It produces an error ++// if more data is written to the ShakeHash after writing ++func (d *state) Write(p []byte) (written int, err error) { ++ if d.state != spongeAbsorbing { ++ panic("sha3: write to sponge after read") ++ } ++ if d.buf == nil { ++ d.buf = d.storage.asBytes()[:0] ++ } ++ written = len(p) ++ ++ for len(p) > 0 { ++ if len(d.buf) == 0 && len(p) >= d.rate { ++ // The fast path; absorb a full "rate" bytes of input and apply the permutation. ++ xorIn(d, p[:d.rate]) ++ p = p[d.rate:] ++ keccakF1600(&d.a) ++ } else { ++ // The slow path; buffer the input until we can fill the sponge, and then xor it in. ++ todo := d.rate - len(d.buf) ++ if todo > len(p) { ++ todo = len(p) ++ } ++ d.buf = append(d.buf, p[:todo]...) ++ p = p[todo:] ++ ++ // If the sponge is full, apply the permutation. ++ if len(d.buf) == d.rate { ++ d.permute() ++ } ++ } ++ } ++ ++ return ++} ++ ++// Read squeezes an arbitrary number of bytes from the sponge. ++func (d *state) Read(out []byte) (n int, err error) { ++ // If we're still absorbing, pad and apply the permutation. ++ if d.state == spongeAbsorbing { ++ d.padAndPermute(d.dsbyte) ++ } ++ ++ n = len(out) ++ ++ // Now, do the squeezing. ++ for len(out) > 0 { ++ n := copy(out, d.buf) ++ d.buf = d.buf[n:] ++ out = out[n:] ++ ++ // Apply the permutation if we've squeezed the sponge dry. ++ if len(d.buf) == 0 { ++ d.permute() ++ } ++ } ++ ++ return ++} ++ ++// Sum applies padding to the hash state and then squeezes out the desired ++// number of output bytes. ++func (d *state) Sum(in []byte) []byte { ++ // Make a copy of the original hash so that caller can keep writing ++ // and summing. ++ dup := d.clone() ++ hash := make([]byte, dup.outputLen) ++ dup.Read(hash) ++ return append(in, hash...) ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go +new file mode 100644 +index 00000000000000..63a3edb4cea70b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go +@@ -0,0 +1,287 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++package sha3 ++ ++// This file contains code for using the 'compute intermediate ++// message digest' (KIMD) and 'compute last message digest' (KLMD) ++// instructions to compute SHA-3 and SHAKE hashes on IBM Z. ++ ++import ( ++ "hash" ++ ++ "golang.org/x/sys/cpu" ++) ++ ++// codes represent 7-bit KIMD/KLMD function codes as defined in ++// the Principles of Operation. ++type code uint64 ++ ++const ( ++ // function codes for KIMD/KLMD ++ sha3_224 code = 32 ++ sha3_256 = 33 ++ sha3_384 = 34 ++ sha3_512 = 35 ++ shake_128 = 36 ++ shake_256 = 37 ++ nopad = 0x100 ++) ++ ++// kimd is a wrapper for the 'compute intermediate message digest' instruction. ++// src must be a multiple of the rate for the given function code. ++// ++//go:noescape ++func kimd(function code, chain *[200]byte, src []byte) ++ ++// klmd is a wrapper for the 'compute last message digest' instruction. ++// src padding is handled by the instruction. ++// ++//go:noescape ++func klmd(function code, chain *[200]byte, dst, src []byte) ++ ++type asmState struct { ++ a [200]byte // 1600 bit state ++ buf []byte // care must be taken to ensure cap(buf) is a multiple of rate ++ rate int // equivalent to block size ++ storage [3072]byte // underlying storage for buf ++ outputLen int // output length if fixed, 0 if not ++ function code // KIMD/KLMD function code ++ state spongeDirection // whether the sponge is absorbing or squeezing ++} ++ ++func newAsmState(function code) *asmState { ++ var s asmState ++ s.function = function ++ switch function { ++ case sha3_224: ++ s.rate = 144 ++ s.outputLen = 28 ++ case sha3_256: ++ s.rate = 136 ++ s.outputLen = 32 ++ case sha3_384: ++ s.rate = 104 ++ s.outputLen = 48 ++ case sha3_512: ++ s.rate = 72 ++ s.outputLen = 64 ++ case shake_128: ++ s.rate = 168 ++ case shake_256: ++ s.rate = 136 ++ default: ++ panic("sha3: unrecognized function code") ++ } ++ ++ // limit s.buf size to a multiple of s.rate ++ s.resetBuf() ++ return &s ++} ++ ++func (s *asmState) clone() *asmState { ++ c := *s ++ c.buf = c.storage[:len(s.buf):cap(s.buf)] ++ return &c ++} ++ ++// copyIntoBuf copies b into buf. It will panic if there is not enough space to ++// store all of b. ++func (s *asmState) copyIntoBuf(b []byte) { ++ bufLen := len(s.buf) ++ s.buf = s.buf[:len(s.buf)+len(b)] ++ copy(s.buf[bufLen:], b) ++} ++ ++// resetBuf points buf at storage, sets the length to 0 and sets cap to be a ++// multiple of the rate. ++func (s *asmState) resetBuf() { ++ max := (cap(s.storage) / s.rate) * s.rate ++ s.buf = s.storage[:0:max] ++} ++ ++// Write (via the embedded io.Writer interface) adds more data to the running hash. ++// It never returns an error. ++func (s *asmState) Write(b []byte) (int, error) { ++ if s.state != spongeAbsorbing { ++ panic("sha3: write to sponge after read") ++ } ++ length := len(b) ++ for len(b) > 0 { ++ if len(s.buf) == 0 && len(b) >= cap(s.buf) { ++ // Hash the data directly and push any remaining bytes ++ // into the buffer. ++ remainder := len(b) % s.rate ++ kimd(s.function, &s.a, b[:len(b)-remainder]) ++ if remainder != 0 { ++ s.copyIntoBuf(b[len(b)-remainder:]) ++ } ++ return length, nil ++ } ++ ++ if len(s.buf) == cap(s.buf) { ++ // flush the buffer ++ kimd(s.function, &s.a, s.buf) ++ s.buf = s.buf[:0] ++ } ++ ++ // copy as much as we can into the buffer ++ n := len(b) ++ if len(b) > cap(s.buf)-len(s.buf) { ++ n = cap(s.buf) - len(s.buf) ++ } ++ s.copyIntoBuf(b[:n]) ++ b = b[n:] ++ } ++ return length, nil ++} ++ ++// Read squeezes an arbitrary number of bytes from the sponge. ++func (s *asmState) Read(out []byte) (n int, err error) { ++ n = len(out) ++ ++ // need to pad if we were absorbing ++ if s.state == spongeAbsorbing { ++ s.state = spongeSqueezing ++ ++ // write hash directly into out if possible ++ if len(out)%s.rate == 0 { ++ klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 ++ s.buf = s.buf[:0] ++ return ++ } ++ ++ // write hash into buffer ++ max := cap(s.buf) ++ if max > len(out) { ++ max = (len(out)/s.rate)*s.rate + s.rate ++ } ++ klmd(s.function, &s.a, s.buf[:max], s.buf) ++ s.buf = s.buf[:max] ++ } ++ ++ for len(out) > 0 { ++ // flush the buffer ++ if len(s.buf) != 0 { ++ c := copy(out, s.buf) ++ out = out[c:] ++ s.buf = s.buf[c:] ++ continue ++ } ++ ++ // write hash directly into out if possible ++ if len(out)%s.rate == 0 { ++ klmd(s.function|nopad, &s.a, out, nil) ++ return ++ } ++ ++ // write hash into buffer ++ s.resetBuf() ++ if cap(s.buf) > len(out) { ++ s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] ++ } ++ klmd(s.function|nopad, &s.a, s.buf, nil) ++ } ++ return ++} ++ ++// Sum appends the current hash to b and returns the resulting slice. ++// It does not change the underlying hash state. ++func (s *asmState) Sum(b []byte) []byte { ++ if s.outputLen == 0 { ++ panic("sha3: cannot call Sum on SHAKE functions") ++ } ++ ++ // Copy the state to preserve the original. ++ a := s.a ++ ++ // Hash the buffer. Note that we don't clear it because we ++ // aren't updating the state. ++ klmd(s.function, &a, nil, s.buf) ++ return append(b, a[:s.outputLen]...) ++} ++ ++// Reset resets the Hash to its initial state. ++func (s *asmState) Reset() { ++ for i := range s.a { ++ s.a[i] = 0 ++ } ++ s.resetBuf() ++ s.state = spongeAbsorbing ++} ++ ++// Size returns the number of bytes Sum will return. ++func (s *asmState) Size() int { ++ return s.outputLen ++} ++ ++// BlockSize returns the hash's underlying block size. ++// The Write method must be able to accept any amount ++// of data, but it may operate more efficiently if all writes ++// are a multiple of the block size. ++func (s *asmState) BlockSize() int { ++ return s.rate ++} ++ ++// Clone returns a copy of the ShakeHash in its current state. ++func (s *asmState) Clone() ShakeHash { ++ return s.clone() ++} ++ ++// new224Asm returns an assembly implementation of SHA3-224 if available, ++// otherwise it returns nil. ++func new224Asm() hash.Hash { ++ if cpu.S390X.HasSHA3 { ++ return newAsmState(sha3_224) ++ } ++ return nil ++} ++ ++// new256Asm returns an assembly implementation of SHA3-256 if available, ++// otherwise it returns nil. ++func new256Asm() hash.Hash { ++ if cpu.S390X.HasSHA3 { ++ return newAsmState(sha3_256) ++ } ++ return nil ++} ++ ++// new384Asm returns an assembly implementation of SHA3-384 if available, ++// otherwise it returns nil. ++func new384Asm() hash.Hash { ++ if cpu.S390X.HasSHA3 { ++ return newAsmState(sha3_384) ++ } ++ return nil ++} ++ ++// new512Asm returns an assembly implementation of SHA3-512 if available, ++// otherwise it returns nil. ++func new512Asm() hash.Hash { ++ if cpu.S390X.HasSHA3 { ++ return newAsmState(sha3_512) ++ } ++ return nil ++} ++ ++// newShake128Asm returns an assembly implementation of SHAKE-128 if available, ++// otherwise it returns nil. ++func newShake128Asm() ShakeHash { ++ if cpu.S390X.HasSHA3 { ++ return newAsmState(shake_128) ++ } ++ return nil ++} ++ ++// newShake256Asm returns an assembly implementation of SHAKE-256 if available, ++// otherwise it returns nil. ++func newShake256Asm() ShakeHash { ++ if cpu.S390X.HasSHA3 { ++ return newAsmState(shake_256) ++ } ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s +new file mode 100644 +index 00000000000000..a0e051b0451e59 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s +@@ -0,0 +1,34 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build gc && !purego ++// +build gc,!purego ++ ++#include "textflag.h" ++ ++// func kimd(function code, chain *[200]byte, src []byte) ++TEXT Β·kimd(SB), NOFRAME|NOSPLIT, $0-40 ++ MOVD function+0(FP), R0 ++ MOVD chain+8(FP), R1 ++ LMG src+16(FP), R2, R3 // R2=base, R3=len ++ ++continue: ++ WORD $0xB93E0002 // KIMD --, R2 ++ BVS continue // continue if interrupted ++ MOVD $0, R0 // reset R0 for pre-go1.8 compilers ++ RET ++ ++// func klmd(function code, chain *[200]byte, dst, src []byte) ++TEXT Β·klmd(SB), NOFRAME|NOSPLIT, $0-64 ++ // TODO: SHAKE support ++ MOVD function+0(FP), R0 ++ MOVD chain+8(FP), R1 ++ LMG dst+16(FP), R2, R3 // R2=base, R3=len ++ LMG src+40(FP), R4, R5 // R4=base, R5=len ++ ++continue: ++ WORD $0xB93F0024 // KLMD R2, R4 ++ BVS continue // continue if interrupted ++ MOVD $0, R0 // reset R0 for pre-go1.8 compilers ++ RET +diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3_test.go b/ms_mod/golang.org/x/crypto/sha3/sha3_test.go +new file mode 100644 +index 00000000000000..83bd6195d6cd13 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/sha3_test.go +@@ -0,0 +1,490 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package sha3 ++ ++// Tests include all the ShortMsgKATs provided by the Keccak team at ++// https://github.com/gvanas/KeccakCodePackage ++// ++// They only include the zero-bit case of the bitwise testvectors ++// published by NIST in the draft of FIPS-202. ++ ++import ( ++ "bytes" ++ "compress/flate" ++ "encoding/hex" ++ "encoding/json" ++ "fmt" ++ "hash" ++ "math/rand" ++ "os" ++ "strings" ++ "testing" ++) ++ ++const ( ++ testString = "brekeccakkeccak koax koax" ++ katFilename = "testdata/keccakKats.json.deflate" ++) ++ ++// testDigests contains functions returning hash.Hash instances ++// with output-length equal to the KAT length for SHA-3, Keccak ++// and SHAKE instances. ++var testDigests = map[string]func() hash.Hash{ ++ "SHA3-224": New224, ++ "SHA3-256": New256, ++ "SHA3-384": New384, ++ "SHA3-512": New512, ++ "Keccak-256": NewLegacyKeccak256, ++ "Keccak-512": NewLegacyKeccak512, ++} ++ ++// testShakes contains functions that return sha3.ShakeHash instances for ++// with output-length equal to the KAT length. ++var testShakes = map[string]struct { ++ constructor func(N []byte, S []byte) ShakeHash ++ defAlgoName string ++ defCustomStr string ++}{ ++ // NewCShake without customization produces same result as SHAKE ++ "SHAKE128": {NewCShake128, "", ""}, ++ "SHAKE256": {NewCShake256, "", ""}, ++ "cSHAKE128": {NewCShake128, "CSHAKE128", "CustomStrign"}, ++ "cSHAKE256": {NewCShake256, "CSHAKE256", "CustomStrign"}, ++} ++ ++// decodeHex converts a hex-encoded string into a raw byte string. ++func decodeHex(s string) []byte { ++ b, err := hex.DecodeString(s) ++ if err != nil { ++ panic(err) ++ } ++ return b ++} ++ ++// structs used to marshal JSON test-cases. ++type KeccakKats struct { ++ Kats map[string][]struct { ++ Digest string `json:"digest"` ++ Length int64 `json:"length"` ++ Message string `json:"message"` ++ ++ // Defined only for cSHAKE ++ N string `json:"N"` ++ S string `json:"S"` ++ } ++} ++ ++func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { ++ xorInOrig, copyOutOrig := xorIn, copyOut ++ xorIn, copyOut = xorInGeneric, copyOutGeneric ++ testf("generic") ++ if xorImplementationUnaligned != "generic" { ++ xorIn, copyOut = xorInUnaligned, copyOutUnaligned ++ testf("unaligned") ++ } ++ xorIn, copyOut = xorInOrig, copyOutOrig ++} ++ ++// TestKeccakKats tests the SHA-3 and Shake implementations against all the ++// ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage ++// (The testvectors are stored in keccakKats.json.deflate due to their length.) ++func TestKeccakKats(t *testing.T) { ++ testUnalignedAndGeneric(t, func(impl string) { ++ // Read the KATs. ++ deflated, err := os.Open(katFilename) ++ if err != nil { ++ t.Errorf("error opening %s: %s", katFilename, err) ++ } ++ file := flate.NewReader(deflated) ++ dec := json.NewDecoder(file) ++ var katSet KeccakKats ++ err = dec.Decode(&katSet) ++ if err != nil { ++ t.Errorf("error decoding KATs: %s", err) ++ } ++ ++ for algo, function := range testDigests { ++ d := function() ++ for _, kat := range katSet.Kats[algo] { ++ d.Reset() ++ in, err := hex.DecodeString(kat.Message) ++ if err != nil { ++ t.Errorf("error decoding KAT: %s", err) ++ } ++ d.Write(in[:kat.Length/8]) ++ got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) ++ if got != kat.Digest { ++ t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", ++ algo, impl, kat.Length, kat.Message, got, kat.Digest) ++ t.Logf("wanted %+v", kat) ++ t.FailNow() ++ } ++ continue ++ } ++ } ++ ++ for algo, v := range testShakes { ++ for _, kat := range katSet.Kats[algo] { ++ N, err := hex.DecodeString(kat.N) ++ if err != nil { ++ t.Errorf("error decoding KAT: %s", err) ++ } ++ ++ S, err := hex.DecodeString(kat.S) ++ if err != nil { ++ t.Errorf("error decoding KAT: %s", err) ++ } ++ d := v.constructor(N, S) ++ in, err := hex.DecodeString(kat.Message) ++ if err != nil { ++ t.Errorf("error decoding KAT: %s", err) ++ } ++ ++ d.Write(in[:kat.Length/8]) ++ out := make([]byte, len(kat.Digest)/2) ++ d.Read(out) ++ got := strings.ToUpper(hex.EncodeToString(out)) ++ if got != kat.Digest { ++ t.Errorf("function=%s, implementation=%s, length=%d N:%s\n S:%s\nmessage:\n %s \ngot:\n %s\nwanted:\n %s", ++ algo, impl, kat.Length, kat.N, kat.S, kat.Message, got, kat.Digest) ++ t.Logf("wanted %+v", kat) ++ t.FailNow() ++ } ++ continue ++ } ++ } ++ }) ++} ++ ++// TestKeccak does a basic test of the non-standardized Keccak hash functions. ++func TestKeccak(t *testing.T) { ++ tests := []struct { ++ fn func() hash.Hash ++ data []byte ++ want string ++ }{ ++ { ++ NewLegacyKeccak256, ++ []byte("abc"), ++ "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", ++ }, ++ { ++ NewLegacyKeccak512, ++ []byte("abc"), ++ "18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96", ++ }, ++ } ++ ++ for _, u := range tests { ++ h := u.fn() ++ h.Write(u.data) ++ got := h.Sum(nil) ++ want := decodeHex(u.want) ++ if !bytes.Equal(got, want) { ++ t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want) ++ } ++ } ++} ++ ++// TestUnalignedWrite tests that writing data in an arbitrary pattern with ++// small input buffers. ++func TestUnalignedWrite(t *testing.T) { ++ testUnalignedAndGeneric(t, func(impl string) { ++ buf := sequentialBytes(0x10000) ++ for alg, df := range testDigests { ++ d := df() ++ d.Reset() ++ d.Write(buf) ++ want := d.Sum(nil) ++ d.Reset() ++ for i := 0; i < len(buf); { ++ // Cycle through offsets which make a 137 byte sequence. ++ // Because 137 is prime this sequence should exercise all corner cases. ++ offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} ++ for _, j := range offsets { ++ if v := len(buf) - i; v < j { ++ j = v ++ } ++ d.Write(buf[i : i+j]) ++ i += j ++ } ++ } ++ got := d.Sum(nil) ++ if !bytes.Equal(got, want) { ++ t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) ++ } ++ } ++ ++ // Same for SHAKE ++ for alg, df := range testShakes { ++ want := make([]byte, 16) ++ got := make([]byte, 16) ++ d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr)) ++ ++ d.Reset() ++ d.Write(buf) ++ d.Read(want) ++ d.Reset() ++ for i := 0; i < len(buf); { ++ // Cycle through offsets which make a 137 byte sequence. ++ // Because 137 is prime this sequence should exercise all corner cases. ++ offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} ++ for _, j := range offsets { ++ if v := len(buf) - i; v < j { ++ j = v ++ } ++ d.Write(buf[i : i+j]) ++ i += j ++ } ++ } ++ d.Read(got) ++ if !bytes.Equal(got, want) { ++ t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) ++ } ++ } ++ }) ++} ++ ++// TestAppend checks that appending works when reallocation is necessary. ++func TestAppend(t *testing.T) { ++ testUnalignedAndGeneric(t, func(impl string) { ++ d := New224() ++ ++ for capacity := 2; capacity <= 66; capacity += 64 { ++ // The first time around the loop, Sum will have to reallocate. ++ // The second time, it will not. ++ buf := make([]byte, 2, capacity) ++ d.Reset() ++ d.Write([]byte{0xcc}) ++ buf = d.Sum(buf) ++ expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" ++ if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { ++ t.Errorf("got %s, want %s", got, expected) ++ } ++ } ++ }) ++} ++ ++// TestAppendNoRealloc tests that appending works when no reallocation is necessary. ++func TestAppendNoRealloc(t *testing.T) { ++ testUnalignedAndGeneric(t, func(impl string) { ++ buf := make([]byte, 1, 200) ++ d := New224() ++ d.Write([]byte{0xcc}) ++ buf = d.Sum(buf) ++ expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" ++ if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { ++ t.Errorf("%s: got %s, want %s", impl, got, expected) ++ } ++ }) ++} ++ ++// TestSqueezing checks that squeezing the full output a single time produces ++// the same output as repeatedly squeezing the instance. ++func TestSqueezing(t *testing.T) { ++ testUnalignedAndGeneric(t, func(impl string) { ++ for algo, v := range testShakes { ++ d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) ++ d0.Write([]byte(testString)) ++ ref := make([]byte, 32) ++ d0.Read(ref) ++ ++ d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) ++ d1.Write([]byte(testString)) ++ var multiple []byte ++ for range ref { ++ one := make([]byte, 1) ++ d1.Read(one) ++ multiple = append(multiple, one...) ++ } ++ if !bytes.Equal(ref, multiple) { ++ t.Errorf("%s (%s): squeezing %d bytes one at a time failed", algo, impl, len(ref)) ++ } ++ } ++ }) ++} ++ ++// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. ++// ++// The alignment of each slice is intentionally randomized to detect alignment ++// issues in the implementation. See https://golang.org/issue/37644. ++// Ideally, the compiler should fuzz the alignment itself. ++// (See https://golang.org/issue/35128.) ++func sequentialBytes(size int) []byte { ++ alignmentOffset := rand.Intn(8) ++ result := make([]byte, size+alignmentOffset)[alignmentOffset:] ++ for i := range result { ++ result[i] = byte(i) ++ } ++ return result ++} ++ ++func TestReset(t *testing.T) { ++ out1 := make([]byte, 32) ++ out2 := make([]byte, 32) ++ ++ for _, v := range testShakes { ++ // Calculate hash for the first time ++ c := v.constructor(nil, []byte{0x99, 0x98}) ++ c.Write(sequentialBytes(0x100)) ++ c.Read(out1) ++ ++ // Calculate hash again ++ c.Reset() ++ c.Write(sequentialBytes(0x100)) ++ c.Read(out2) ++ ++ if !bytes.Equal(out1, out2) { ++ t.Error("\nExpected:\n", out1, "\ngot:\n", out2) ++ } ++ } ++} ++ ++func TestClone(t *testing.T) { ++ out1 := make([]byte, 16) ++ out2 := make([]byte, 16) ++ ++ // Test for sizes smaller and larger than block size. ++ for _, size := range []int{0x1, 0x100} { ++ in := sequentialBytes(size) ++ for _, v := range testShakes { ++ h1 := v.constructor(nil, []byte{0x01}) ++ h1.Write([]byte{0x01}) ++ ++ h2 := h1.Clone() ++ ++ h1.Write(in) ++ h1.Read(out1) ++ ++ h2.Write(in) ++ h2.Read(out2) ++ ++ if !bytes.Equal(out1, out2) { ++ t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2)) ++ } ++ } ++ } ++} ++ ++// BenchmarkPermutationFunction measures the speed of the permutation function ++// with no input data. ++func BenchmarkPermutationFunction(b *testing.B) { ++ b.SetBytes(int64(200)) ++ var lanes [25]uint64 ++ for i := 0; i < b.N; i++ { ++ keccakF1600(&lanes) ++ } ++} ++ ++// benchmarkHash tests the speed to hash num buffers of buflen each. ++func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { ++ b.StopTimer() ++ h.Reset() ++ data := sequentialBytes(size) ++ b.SetBytes(int64(size * num)) ++ b.StartTimer() ++ ++ var state []byte ++ for i := 0; i < b.N; i++ { ++ for j := 0; j < num; j++ { ++ h.Write(data) ++ } ++ state = h.Sum(state[:0]) ++ } ++ b.StopTimer() ++ h.Reset() ++} ++ ++// benchmarkShake is specialized to the Shake instances, which don't ++// require a copy on reading output. ++func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { ++ b.StopTimer() ++ h.Reset() ++ data := sequentialBytes(size) ++ d := make([]byte, 32) ++ ++ b.SetBytes(int64(size * num)) ++ b.StartTimer() ++ ++ for i := 0; i < b.N; i++ { ++ h.Reset() ++ for j := 0; j < num; j++ { ++ h.Write(data) ++ } ++ h.Read(d) ++ } ++} ++ ++func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } ++func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } ++func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } ++func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } ++ ++func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } ++func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } ++func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } ++func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } ++ ++func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } ++ ++func Example_sum() { ++ buf := []byte("some data to hash") ++ // A hash needs to be 64 bytes long to have 256-bit collision resistance. ++ h := make([]byte, 64) ++ // Compute a 64-byte hash of buf and put it in h. ++ ShakeSum256(h, buf) ++ fmt.Printf("%x\n", h) ++ // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d ++} ++ ++func Example_mac() { ++ k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") ++ buf := []byte("and this is some data to authenticate") ++ // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key. ++ h := make([]byte, 32) ++ d := NewShake256() ++ // Write the key into the hash. ++ d.Write(k) ++ // Now write the data. ++ d.Write(buf) ++ // Read 32 bytes of output from the hash into h. ++ d.Read(h) ++ fmt.Printf("%x\n", h) ++ // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff ++} ++ ++func ExampleNewCShake256() { ++ out := make([]byte, 32) ++ msg := []byte("The quick brown fox jumps over the lazy dog") ++ ++ // Example 1: Simple cshake ++ c1 := NewCShake256([]byte("NAME"), []byte("Partition1")) ++ c1.Write(msg) ++ c1.Read(out) ++ fmt.Println(hex.EncodeToString(out)) ++ ++ // Example 2: Different customization string produces different digest ++ c1 = NewCShake256([]byte("NAME"), []byte("Partition2")) ++ c1.Write(msg) ++ c1.Read(out) ++ fmt.Println(hex.EncodeToString(out)) ++ ++ // Example 3: Longer output length produces longer digest ++ out = make([]byte, 64) ++ c1 = NewCShake256([]byte("NAME"), []byte("Partition1")) ++ c1.Write(msg) ++ c1.Read(out) ++ fmt.Println(hex.EncodeToString(out)) ++ ++ // Example 4: Next read produces different result ++ c1.Read(out) ++ fmt.Println(hex.EncodeToString(out)) ++ ++ // Output: ++ //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b ++ //a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0 ++ //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8 ++ //85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109 ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/shake.go b/ms_mod/golang.org/x/crypto/sha3/shake.go +new file mode 100644 +index 00000000000000..d7be2954ab26a8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/shake.go +@@ -0,0 +1,173 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package sha3 ++ ++// This file defines the ShakeHash interface, and provides ++// functions for creating SHAKE and cSHAKE instances, as well as utility ++// functions for hashing bytes to arbitrary-length output. ++// ++// ++// SHAKE implementation is based on FIPS PUB 202 [1] ++// cSHAKE implementations is based on NIST SP 800-185 [2] ++// ++// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf ++// [2] https://doi.org/10.6028/NIST.SP.800-185 ++ ++import ( ++ "encoding/binary" ++ "io" ++) ++ ++// ShakeHash defines the interface to hash functions that ++// support arbitrary-length output. ++type ShakeHash interface { ++ // Write absorbs more data into the hash's state. It panics if input is ++ // written to it after output has been read from it. ++ io.Writer ++ ++ // Read reads more output from the hash; reading affects the hash's ++ // state. (ShakeHash.Read is thus very different from Hash.Sum) ++ // It never returns an error. ++ io.Reader ++ ++ // Clone returns a copy of the ShakeHash in its current state. ++ Clone() ShakeHash ++ ++ // Reset resets the ShakeHash to its initial state. ++ Reset() ++} ++ ++// cSHAKE specific context ++type cshakeState struct { ++ *state // SHA-3 state context and Read/Write operations ++ ++ // initBlock is the cSHAKE specific initialization set of bytes. It is initialized ++ // by newCShake function and stores concatenation of N followed by S, encoded ++ // by the method specified in 3.3 of [1]. ++ // It is stored here in order for Reset() to be able to put context into ++ // initial state. ++ initBlock []byte ++} ++ ++// Consts for configuring initial SHA-3 state ++const ( ++ dsbyteShake = 0x1f ++ dsbyteCShake = 0x04 ++ rate128 = 168 ++ rate256 = 136 ++) ++ ++func bytepad(input []byte, w int) []byte { ++ // leftEncode always returns max 9 bytes ++ buf := make([]byte, 0, 9+len(input)+w) ++ buf = append(buf, leftEncode(uint64(w))...) ++ buf = append(buf, input...) ++ padlen := w - (len(buf) % w) ++ return append(buf, make([]byte, padlen)...) ++} ++ ++func leftEncode(value uint64) []byte { ++ var b [9]byte ++ binary.BigEndian.PutUint64(b[1:], value) ++ // Trim all but last leading zero bytes ++ i := byte(1) ++ for i < 8 && b[i] == 0 { ++ i++ ++ } ++ // Prepend number of encoded bytes ++ b[i-1] = 9 - i ++ return b[i-1:] ++} ++ ++func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash { ++ c := cshakeState{state: &state{rate: rate, dsbyte: dsbyte}} ++ ++ // leftEncode returns max 9 bytes ++ c.initBlock = make([]byte, 0, 9*2+len(N)+len(S)) ++ c.initBlock = append(c.initBlock, leftEncode(uint64(len(N)*8))...) ++ c.initBlock = append(c.initBlock, N...) ++ c.initBlock = append(c.initBlock, leftEncode(uint64(len(S)*8))...) ++ c.initBlock = append(c.initBlock, S...) ++ c.Write(bytepad(c.initBlock, c.rate)) ++ return &c ++} ++ ++// Reset resets the hash to initial state. ++func (c *cshakeState) Reset() { ++ c.state.Reset() ++ c.Write(bytepad(c.initBlock, c.rate)) ++} ++ ++// Clone returns copy of a cSHAKE context within its current state. ++func (c *cshakeState) Clone() ShakeHash { ++ b := make([]byte, len(c.initBlock)) ++ copy(b, c.initBlock) ++ return &cshakeState{state: c.clone(), initBlock: b} ++} ++ ++// Clone returns copy of SHAKE context within its current state. ++func (c *state) Clone() ShakeHash { ++ return c.clone() ++} ++ ++// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. ++// Its generic security strength is 128 bits against all attacks if at ++// least 32 bytes of its output are used. ++func NewShake128() ShakeHash { ++ if h := newShake128Asm(); h != nil { ++ return h ++ } ++ return &state{rate: rate128, dsbyte: dsbyteShake} ++} ++ ++// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. ++// Its generic security strength is 256 bits against all attacks if ++// at least 64 bytes of its output are used. ++func NewShake256() ShakeHash { ++ if h := newShake256Asm(); h != nil { ++ return h ++ } ++ return &state{rate: rate256, dsbyte: dsbyteShake} ++} ++ ++// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash, ++// a customizable variant of SHAKE128. ++// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is ++// desired. S is a customization byte string used for domain separation - two cSHAKE ++// computations on same input with different S yield unrelated outputs. ++// When N and S are both empty, this is equivalent to NewShake128. ++func NewCShake128(N, S []byte) ShakeHash { ++ if len(N) == 0 && len(S) == 0 { ++ return NewShake128() ++ } ++ return newCShake(N, S, rate128, dsbyteCShake) ++} ++ ++// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash, ++// a customizable variant of SHAKE256. ++// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is ++// desired. S is a customization byte string used for domain separation - two cSHAKE ++// computations on same input with different S yield unrelated outputs. ++// When N and S are both empty, this is equivalent to NewShake256. ++func NewCShake256(N, S []byte) ShakeHash { ++ if len(N) == 0 && len(S) == 0 { ++ return NewShake256() ++ } ++ return newCShake(N, S, rate256, dsbyteCShake) ++} ++ ++// ShakeSum128 writes an arbitrary-length digest of data into hash. ++func ShakeSum128(hash, data []byte) { ++ h := NewShake128() ++ h.Write(data) ++ h.Read(hash) ++} ++ ++// ShakeSum256 writes an arbitrary-length digest of data into hash. ++func ShakeSum256(hash, data []byte) { ++ h := NewShake256() ++ h.Write(data) ++ h.Read(hash) ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/shake_generic.go b/ms_mod/golang.org/x/crypto/sha3/shake_generic.go +new file mode 100644 +index 00000000000000..5c0710ef98ff88 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/shake_generic.go +@@ -0,0 +1,20 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !gc || purego || !s390x ++// +build !gc purego !s390x ++ ++package sha3 ++ ++// newShake128Asm returns an assembly implementation of SHAKE-128 if available, ++// otherwise it returns nil. ++func newShake128Asm() ShakeHash { ++ return nil ++} ++ ++// newShake256Asm returns an assembly implementation of SHAKE-256 if available, ++// otherwise it returns nil. ++func newShake256Asm() ShakeHash { ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate b/ms_mod/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate +new file mode 100644 +index 0000000000000000000000000000000000000000..7a94c2f8bce62c70664cda859a30845cab713c24 +GIT binary patch +literal 540828 +zcmV(+K;6HL{JXAoOO7>&`TZ1$v|B*%8f1CALcUB{4XE%-(8a0WYv|pDSP8W?6T3cR +zuXFY}-&~BC|M_44{EvV9@Bhm`{_)TM%l|p(|Aff@{EvV9U;meX +z{No?L-@ZTp{J;G_{>Oj**Z=(IfBfU0nmmUXN%eN-rPKjo;XRWO*(`q71M*xOT1g4b +zy8rxN|NqbWfBonG=YRaq|NB4x;~(e$_|^aWKmY5${$R|hx@TP+Ts2$!oSCMCvA10((sNL)Vn5#o;pgjssqOvK5IFO` +zgAm-s71W6!nyI!H4l1vKs2sY7&q0f$$zmUd@TX@YED%S@{mYac!J<D)t{}(ue3|m?qPlW2FAw@(##l1Du~**Wd$q)=M{HXPhY%};Ky!}8 +zl_NI}Oly1?BcIL+;1{UMXlC{=a}JPcb>AcANlEMsvjdtY=fZe~v%z&oJj|~Q +z(NDMK;KhS%EP#Ug=l-Y*^)clGUIyC~c7)^xC~jX3ptzN*yQh`pfb{t?=;C)AsYWuG +zOnWL_`OBmc-NKL%yT=bf@4>)fjdoclF&exqN=Nv#wcovmz7X!ym1p`gBH~q`)D@~f +z{RsLR72P5X%nK=pvm%acos&wwurYV6AMR5Y`yPfbqduK_Vy2~fx6ONMSY+WZvxMso +z=Tco7aEu;A>YXrM?88y(LJD{ZTx{+AjqDGz{L{T9hpGH5q8}XIv1x4j%dmS#pe8yn +z0xEM|qS_G7v6MT`y4U$2QiAU(p;7$uD>$E?9+wp_AsQeq85AY!@ZX!})8f-0GJZjL +zj^2&45z5oi~)9GJQxKOR&r5;KteCBZh{L}pnl18+4W^5eD +znsNs@^H%jXr<^`%6#y}}IZwHMT8E$hzkz6%v+AhX^|4uiP~USA|4jcN7jjx~glCrS +zZTH@r!&$0^#YA=&b3LjYd-d3U+V>d>f}zJE5vsZ^nB|7t>A8k*|HQOoho$yfBUy|3 +z#f36C44lP>x3nt()_xAzhqx3zcaT1#!te##@L}q%2AoQ-2=iwYV^5__ +zK%xY8#3T}jwdrh +z%$=0(32HotyjZ=N0}6E%4Ji_>N)B8Jx5v^y(<?!ks~vq9(846)UORlO=zd!I89i-Xwmq9&^Y&o4GIp*p +z-;8-!L<$GvZ*m*w0kh!TYP?80hyyJbd=RKTr~^9Phj4bc&$52mdcU*FJtoh;fe|zk +z4z>~8Je5Qi*R*Aeu(xxl|xK;XH&%ZPu2&cPI7vN#crlp33lz!3{M6ND>=_!A@6A +zPhB+XFRa6FB_A*FXv}3-;^eR)^Em?61`N1%WkZf24C)qdm%g-^OXXU)q|_TF7@C~bUZdzeVQk03FBlmWpL} +zM17YSd~vI8`RO@+TGMXzed5ImCbSX(z_zfZ$M;dDPK|=`fAf<%i;F$o +zzeqX!XKug7CHCHx^nx; +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 +z_j%i*ha^J*rDAm7!rz&Uuemq*?lfe`6LAx +zM%9jDc;w03hZ?_wE{ +z+0)L3$EdK%h`jGqJijrMk{J0_wL9(H9F#ow9HRGZr0kZ2rU$M%;K%FWziI>tNulLC +zjokNKcKv%ovM!fTCeC`eA%-GaHh^hYF#}|YPdQmH-Vx4YpGQ{pyPJ`@?L-aRH&>ja +z?lKA9+Xc6+B_wUQf!eik^`SgOW($Ob#l&UEsmktzd$T5vAk$=@L$y6Ic5hX1hqIpN +zoa*4y>;_iZYAc(A#AR4aRk#2iRv&(@U!{GE+7+Ys1D=k>Inz2#A27}8noVsK;gHY7jv +zxQ7S4@Da9N;=63kp{<7wP$4b6><%q1lTmd48|P^sRN?QK8d3L+5TS_&ZlmIL6Zs4b +zT9zuFV=Vnyuh8#~i836S3R4o0!ZWuvBTk$&JAPO}dFgViLv^;wLx9Kv17D9aPQi>V +z$g^`_Mkx_aJyr+G{BWsy+hZXbziBcqwW%TGDGB!7PVssL9_Iwya0uL@VWIziI)I{V(iQh=_)^b}M_vQ>8Jwg89PI4QNE(1iJxFv4Ke6V!D+Ab0&SpkOqFm?E{M<8; +zV1@pq_IO|5Zt+!t6-=|FbF9RSNrde&l)x=6H~?Vfu!JIt$RT`sboTkw%VM*zc@8n` +z(&XH>xet*d7t!jV978pgY;R%PPOi5(>ID@}UyFsJA7V1&v*foco&< +zTNOjyo1^y7QCk8g?3fJ3c(v3Xcd%PmwYrCeDwhmI1IV5}9jU8g +zPl#@^#XX+n{1mw9=MH^$e*7fw&T_Ndta}08^5P;A)MMDI`Pizi<(hcg6-)ED)ueFb +zy?3%c+F_K@vZ|B;5VE=oi=^AK_9TXk`GV1lzfzEtQ@7M$9=C+!yO$kOsu0n&{_Y?M +zQ#_h*r?-sa;U6rv$Zw#r)5PeoqP@rWxi`r^Ps!?cuV^k>&ri{ssGL*$Q*metSZ#-w +zPSL_?(oF;}sW=gIE@~wB8ChDqKIanky>n4-!6Q8PX}zZkf*Xb&9dN~~WS!AZY+>CB +zI)v)ezy~<-Y4i6Mc%n??Pu@d%?Kk=3Vr|b)QM%28hx}3i&`5*A=?#(OO_umnl=|IW +zQes;~pPSGRs_&_Lg?R*2=NOor4Ja)$Q1854SBLSX5Zb83tI-;#VdJKprlHiWzWx~5 +z<$D}Y+{kIZjb^)MG{_YQb=MAPI%Rskt+wp+d#LdtZz|}Y8I8g2PE0>(N-amiHLUfh +zTA0DbdD7WfAUMx~3xS +zxnOG^JHmkXHwScJjv0$Mr(U3=aZu_vrjoi&d4gOJyX;=3nliESIa<41rJPr= +zTrS!jiL;LZ9VyRU^G4eCgH6bF-48uZSZQm^FHg~Mce0TW?2DbcSZlW`oEV!MQOzFMWO)(k+jHXuJ +zkl@;T=<~9V@1B=h*_yE@;2E7$?&=|?8Y>QA=;^rh6k%`>xVqc`wqggeM_~8m6nN=L +zrYFb$byEXOS>_|UUR$Bp`WQ_3llfPgyz>!nYrf)mY78x%=OQvJaz7Tvnj{!!{=}-) +zMSGDiPa2oE%h986&knzTAU{<-$YSwCOCHmlPu}$1B};2jzUab3uqixfTXC7z9!o4@ +zbEp*M=Xb~U<^?6~M-jLJrhf(HEh!p4hrPxPGsEi6xrYwDJpIzOx{UW+O@YIUo5eyh +z^*dESl!bTk<;A!3J9d!rY^JU#)!+MN+L%D5dGHzg`)p}Bc;3r=M)0XT?KD|MNf=+4 +zb-(*+r{!0hkPTyE96dEVLy!k2i=m5}Y@b#4``w9yD>B&llIjy>Aj+aCj +zIoP%O;Gj&uq5oDAN&{hKC;_bwR7DMS5wUASJK_XB-b +zPQXqNgu?qXbHz9V>#g93TeVz{x_91NH=zazI8eG0I8t_?Z<}oCW)4yeX}4j +zh!)B%cMt~fkrdF-rwK0~d-$^pH@Ep +zp63LP4}kd2k#jG|T~`AV=74)x9e8~JK-WVJhqfQQ3-g@a7XxwU{VxW5I(ij9U0wp +zIid0Ti|k`_6K@RdLLM&avq`f$;t>>Us(L=L?cdxdqcgQG8iLBccCVlTYY$N`vOiID +z2Epj8%J|u{C>7o+e71*=9zr_v=!BjH`1MawttSItx+j^>m*`SRYJ38{^;vp1^4(qLPR4<+(JxEem*v4uP7*5So)YniwpVZEqD?pczBPzr^u55@oYO**tj8r*mbI5i~i57X@ +z#}2sJK$b+U`0q}->mfHBPIl-ydd4JWpX|C<_XxU@w^t2k|9yYJ&gPiA47!H*4EG}h +zz%6kHh!2aBhbCMt>`OYInD^c1R9}zGP!WGg0Xn(sIZsBud|_LM!ATF^_kVClpwb~~ +z@nax%^LXa4_eu8hC+rZ7PvWk$mw?Fnm9@osd+MjIG!BOyK0D;Alo^|RsC|B;{%Jag +zhn&Ofhpm!LWwPOW>Y9W8JzG=f;3ZsLvPdICbA*+xqm3;1P|fvD#IGDv +zZp?n)J}1GG8j=@o_|Fsbfpv5aj#PXJm=aTDMP3m%x-z0_#DD{`t@Q!{f>&m +ztwEtNe>}6OE}$VY))Uf+$GockzSeTKiz)(f=HW>yVRNan)X*;OvIGi~LK(yrZ +z3eeA-!bBx>2nZDUAqcdo1sy}-D`S1K={)9(2zJPAxq=xf-4Hl6C!!F_?EIXT*2*cH +z@#*4v0#Ivu36Wb~Rx0#s%*>1UL~&#pHi<)O{)U=Hsz>El1-V7{^WM_$4sY0{IilOh^O_N{kq5*&zkeEGRl(d(aZ9vz@L4YMC7bm +zsW9!$pb5G-i0W5P3Lzh#I8UfzbBdA7*O^HB?g^ix4mXw8yLzFq?UseYeJfuTyP!69 +zHp0#tw(ydBrP`+u+=s +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 +z!*$qQN%*AzZkGovMX4jykx5 +z`v4yI-SBis`9m@X2CiV~+p<|VBW9;B)oS{5LVErk=~rQ{$JaE6JPGPxIH&%2RJ +zRlN_bw44(wXW)UKxv~kEr0exV%!7pY9#hicvR$U1#rz2 +zVGYKp$v4S~3jLHOjUP*kxTXQ>%BiZjF^75K?uD4LJ)#ju4hl5ygNRJ;q+c9mRFmUZ +zg5NJ-5f&};z(t&+`$~oLxq5>p>TM-JxF=hrnd7GTywgNYdFF`mNhp{{N|53d5w#W} +zibD6m0*S=_dFxlB2jHOlIv($=baGfDfR)1sJQTNSH5#cGdiUf{(`)z-^D`68>?r#h +zA$M}kYtKuxE}9dk_~4F>k55p!P;@@Jd&_(iuEo*--0nSM$Y!>R7N?}pE~j2E9uB7F +zM*hY&PFJNKD!5BZSER-)aNCYRb>iRw3c7pD0Z08U>{oBQW2~G3Z;QHBaqC4@e5@hW +z?sXTB2L*f}d&`?M=1#BzU*-7o!fM*nvt?{3$mZQ&Kh<+VIsBz^gkXdx23x^}@%e+)|HP +z`E3+*ORh_W``rv(y1Q>bbRW7dY<#~EiR|{h_KihZ4N1gtO!JCuhh*;Is|U5`>zO4J +zIjLxehbsnEb|n@u`k)962#-G=_XvbGp7-^uRy)D|cB9J^GuJG{lIP)2-0lNlBbgz$ +z>vB=kCTR5aGW9Fy8iXiZO +z$iA%64!JQVYK!4#eRztNUm5`DK8@YYS{?eSlCyTKq2kQg=3;df*DP>tBFxajGJKW(P9r7fQ=RR-a#d2m~Fs1$pc&H+_Z_*2@k=i~lf +z-U|uj-lnB@j)TCwKi#bh_xMFg3rK(b`R4}w*2+-ZX`g){T(|e(bO@kS!Vt1PRX%nq +z>l}iJWSVntSK*)_WzXkpe%W$gyeEZ*#-Z;8r5=>?IV;*Lc@5+bQoq_u1yf6|#4?kU +z5B(4JLyC48WG)!J0w8L7wIA%j!*6^02%JlS8OzS3fGzRh>p2R1$d0WgzY@M6`t~

*MP~@|g&eKE{jR5*iq?f6HMmz2&am{(;1ohr`PJV8|e~fj2(+b%% +zXR6BvjB1(tn_+52xs9>>Kt^|+`r6IOADrzu#KI^72&O5KFXra!t{|nrzJ8WWH3HJC +zh#mC8C)^&oI#YRR2!%H7d^aD)?OpiO)n~ym(ubs2n2RQ>~ +zUieTuF(CH=W(v`ezL(t8!?9s5c*QrI=Uwgts4F1Xc!w|5HQLf2~JXU#cioz)5xd65?DxSe(ic|0GCAwC1 +z!6@ej9e8{TXylzuoo)tvWCy{pal1xtoGgB5hfZ5#fY1W&+ywM8DOhz8-|;)WudaOW +zL#_+(E)nrjI_xcdg+3aMe5{4k^L;QC)Kn`(xe*LbQ|#Bw&2UGM4fpRUj!ekjm*%`A +zb`N(2jFOUtGqhb74FhbYwAyA;{OP=f@E-#zBB~)Q5?|FUWu0w;H5so?AOGG9#bpm; +z&PcBp&YZxgl2hS;W-IRg4#MpPv=*T_kDlBRodqw45A-TELHish9h;gs( +z;xRqFl!yJN=REw!Aor}L?{Mv-!d@9!w<(yU1nv~+`3ylWUa?vZ-fJgBP{UuL1{q%N +z8?k|mvxcH``xD5d;f63Z0o~HNypYF8Z`BFX9?VnO`d~O5pz8AiU^H6$@Lh$M6#&Wj +zGN^Fi*B6P@L%eiO%XP#9;T5(Iit%S+#l}TvGp!>LNEgL{4dP*}nafj;#`op-o+3@!DcZ0aK))$E{v9Zq+SMyCqlco`|%T59ndGFrn5- +z^KqmmS$zcsOo{111|%2AL;J$j`ca_c_Lch1I4Pe&#pC7`pmhJX=rTDTf$k`GLCNWG +zfbKVIQ6Gnr1hzSI6jJV^V3AP2H{@plZ>E#l&{=h;BGAs-0XulZ0760g#77Vm?|!QMy6wTU5oL5}y$KsF)|7-#%^+~mG2()KDk +zU&ref=Lq^$0txEF1+Q)sQOjmS5>#3Bx~!bi?6w=aFGe>CuV0!1IJZm1XlM@gJsWLu`@wG*2)>An(O-l3 +z0q*#0H+Sa|7sfsS9&M=RVW&P}_b@}o=!kcl*O;6}LDRaXEutbP;Nuln!jH1^_)Sk5 +z%G|WD_SGOM_**Fz9rzgOISXVL<)jW^raO>KF7jzFoqyfjc}EhDqoGN6 +z%^3%S6G4W01W`C@3)F@M=G=7mi2JbTL5z30fGkvRGC7FT!Fw<|*Ef*57Qq+JJ?mi1 +zfbDo~?#dGBRC5zkg4UzcDHmdwBC#upj^yyE`_R+%`5L39%})?b+AC^eeWEBYIv_jW +zhAb>w9!HJ;!zbvtf8$zYs;&G{Qp~v%@L;Bz9bw=lK$wj4He1ntZp&|R)h*j^!fcs6 +zvP=Z=k}qZ{)6h?(q@H#gx!{O5ZD!*mSwfX-NCej=?L3{-2A&Cba{{K1VO7MSO7LD{g?3 +zn9N7H35wyw(p=`7KgV|<{?=n5e>z`NXoqC-VNxxT**Fuw##2mdpXUV(y%4QbX?gi|#LI1Heza?B~et{4l +zCL|Evgv2uOsndH>4Y8E)E}U<^3&us8fT*T)C)JEvN{fJcrvkh@cz^Zi(a +z0_x4``^jNz#oph1#8h9(U!Av+U)$_WeYkt<3h1M%GIXP&&*+roxMc5%S?Q99^zY{F +z8)aVqN{{Nm3RUXCrKBm9+wu3R +zc}WcqauoVL_DVE*SS9gmyVCu+Ilon3DebqQ2S;R6vhld#!`v-SFuf1s`+O)>Aiuf# +zuU0Qd?#w6Nv{(U?a~;kNwh})uj?8SWK+&wpa9+jthgBYp%x|`h2)bz3%bX1;vwN?W +zV3*FY@z1G+lrdR{_}1>Wmxyp+Rn{9i&mk47$Bm1w`iXkQa0M}fipH#K_LZepF> +z9w==a=9uodW}1hEii9oZ{;kP_d%hM>P?uxZkbxe+y)X6LJ9o=NACarL=A#KhKd~A9 +z7K&{NZ1D6q{Fa0U-Kjg- +z%XevZb06~_!PBw#_zB~=2sZ@o8pfkaANZTncerkT!&a_+U3(CKg_JTUj<4Cdb^pGQ +zJc=v?|J(#*N&@B;ZxTs&c2a89bg$J4`&`5!@^^Cktu1>;PTN-${Fc98y;*}bqD~} +zd6`vtmFKiEsFLCF$)@J)^CDrG^d06teLjEU6QOo`cJa|6dS5#+BopIs*uR)$ +zV$YQ?>wrh@CE)8F7$rZiWbn5fE!di+6;=E@qjyETWMTMn$0bOFn#ke@uT>`v4jnzz +zP7jmL1E7__%7h)}z$J(eoQv7fC{4FCrz(Rw8r~s+XCD|>r9u;RPmff<9p$3}osVYX +zWoqbyq1qrTA#wA@+|BJ1iP)R!f#sUV>!g#EBhcwpH+O3vW9s4ju81F9_a(CT(V8iP +zr<+^H!?6&rDmy&#A)|k8lHVIeQH=yH2vmD{Z^uh#A#Lcy&O}9h{Xx2y`tJPRq~CMv +z#yzAYk;<#J4jVyz6LaceA)mwZ02f=G$;)R_uHv4ngiUC;7a=ZTK~aXPXW+m)7i+Ue +zw9oZ;DfGUi@P2a#o?~L5VQI3bUSjOiz2kb1C+RC4eu_FCMs0}Hh+A-D&~{8R8f8?^ +z?7p1YT#3grRt_gu$Hvw`klv`Xy}Oupt{}lT;143 +z&>ndZ+K)@)J_IU#aUkzn;VtA(BVf0-_E=G2Dijj_eV!=W-V;vHl}zv$XJhE%AoA`5 +zu@{Suc?;=)#@YLOqkik;woQ@m7&gP)E`3$VH{hlm6pe(0xp)E^&!x41h%;~LQnL$= +z1|JRma!)nX4$OU=D1>!eX-|I9HtY52J3J@7_T?qkjTwBW4(x5xT){BYc{F!lVr=nS +zGIc$!?3&u$A@;kn+g-N^Y~N|^1G`e|`2H`OuF6e3Rp;W}zQ=)y1COz_GoNXG=;t=d +z64$+WE%xx~xvrC)Ire|d08E~Ri6gAa07pLOG0jBEv*kjtkALOMui7h2jnu!lD*ppQ +zq`WA*dd`XnnI0LC^Cfz`?-a}QHKJ3O1@EGD+KX2kc`M)shvhzc*x#J4qhA@KcuOj0 +z7MLtIfCj|s>=HSzOaj{ajl)ZD^Hhk=3Yn%zA|kX=-x +z7h6LQ@aU@tH7RWGbcG%1!#O@3z`lo@%o}`I%*aIYz>GGWLvxAn`pU3Kmh|Rl#Y0Ee +zyziwXX7zLSmCBxfiY6{D^`^N=@s@U*+}y_I2B<{>$eofSxMf2JN<4DhK(BWP$2k$) +zT!+_yeBHI@l2HT-1>|RJcvD}=gVZf#Sm;cS(#LE^$rP^UpS_S6xWs_hC`&ELvD*dC +zJ41*2kk&MMZq|dF834IQes9-LSn(c1r<3NErx|@0FUiN!3Vh}=Rn?iBFAv}}$|EUpP<_2W{rbVav4OZ(VXb?*oSDu8UsVLcqMWPK+7D?aYHvp&W=2Ox*uu^B +z3fPy~vHSp%!_9L4Tc1`#0Y!+DQIDeD>2}OZ3d^fyT{OuR%<1-kHHz;~i6H%!2--+P +zfj`{Ft4{2`@c>%Om5+`O$ZV?;JyNU+kDF6o2PY>YvzNX{BFZge;8<3vJsx-2 +z|2$_yA(IS`bhRDInJSM*3`Vf)e2!jNC7UUMWxI6c=e-5}78NSCpMGSA?%fvhN}Rc? +z^b(c8Tfz1vakV3F4UVdT0Ysl6KWGAw%n5c+UWUE*9EkuRIuMBZC{10yZF7_#J8r+N +z&BZ;v;=One7m>%*M(I6!}9Uum? +zsSkcbtIKQk42U)bpMpmWrt1XHAX8E?>SeU)tTd^Ra+dJf`V<4(^57N33K1+szYEvbu! +zC$z-q1gt0sY~mF(9dH@p&m)ur7_nk{kLFCQj3~x__nq_D8&35#>wAN@nk(SzNB{ZPz(4RB{8Dfgx8(dBO2it>Tmc8r;p3D$8&w#BHZjF$Q?#D$qU-%#`3(|W$! +zYAdIxHnR)9pl$~vCttR{O>m|pYv^#kl;a%wxAa$RPmz7^mpf6S1=;{*TuUGxAv#A~ +z;KDhYSX0XVQ$s|*rH)f>-#89Utw6URLkF;sFjo~nym1wV2wz>k2{y1ktI#3__-L4e +zs8?=yuIK$QqeYBEu{aw}h(FqWtV$`_wr;FOVSi>kI1aJ|D0bLB`D`fno;;hqcT+8E +zqH2r1^0p&qVLi;CEPm$h13wchDvddfQyQ2sZi~ +zPyWXoHMb5uV=jb1dQ3JM-h&=TYVW#!8vq^c0-b;JkYH#cX!x;Te6-3MUueSKxE_1s +z&=pg7Y4sbl&DZ6Deg7V8CTBIo5N;y{iO4d%)ChL1WvfKN`m-y3GBP=1W9 +zU`Rhn(jJWm(@Z45?t2uOU1g)#?^?5s8=5&b8JDrchon(#?0|rQs`>0*{U#(od_<2o +z=8^I6E7QgEIeye6-u!zaQ#ivA=3<^a?9*PxCFdN~S5>Eh*xq7%lHJcaB>Sh#n10JC +zNjoM7n6|9vIP<*|j&ZxG6u4w7zEGNDf~?wyA~Tp6`0<^nd00BN?25#z4&hld=Rs!-ORVJa0~Lqk5#vX#@YJ@%$k0Wd +zx!QRY;s!Gh)7eKTvE{SDBf}2Wd1ZA5KaWxvm7{>8j|qdXwY~^OG>BN`)DU47ld+sMEizzEul*cm4CvUBd)tX+6 +zk0|LYi>s~rxVv7`UfO`l_%wrlQS|QgHXji$9$B#=RFWChImhTKVRcePms3Z2rj2Ab +zIb%k9vHQ}ZgWPtB)IeS^*9*ri)})#4YL09bT7-x +zt?Fpl`*O)W*e%Hq5pY3V230;lJ+zKxIO) +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 +zgxP8ne3;pXZgbl;&k;Rt +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 +zIk$pn|6o21SnJG(ZVAy^T9$L$$Yg#0ljaP +z!9E6Yql+can4!jd8zZlDi}rC5J6Mm)B2|4R1ZeA0r>$^b7DdJ+`rCFASc(M!$?;VR +zT__&;JiHzg{wz8{fbF{bnSGC$ejb3z@8Q^6eHrRu6H7I$FL*Y9FK$}w-?fPk$-@S?#dFw4I2wxM>v(a=mPG+M#JV(h87gUw+Z8-u%^mO)GmsaoBFHfr~b^lU|_=P3^sjOH|qpmXzq*Z&FMcI6zg +z)-;YAvxYYhT3Q@b$m>ybkAy!)5WX^xG3hx=lWHVc!WSSN(J#|EFGSrxf!HdHG@i0;%mp^635ZTrK-j +z#f!AEEV0{XPYwxoW(F)*GM%0Xduh=+fa?5g;Ftes;5Qc!olmC8^p!{hqRZ#&{1|j{ +zRa`usS_Gm;%}q;03*+{uOK2^4W|q3x;W`cs!eaq;q9^xKCL>VFG1rZA1m#XMq+CC% +zwt^<|zy(|j{$wm_umh9jwuX+@ryI4n3G>g3d9IrRj$cv`H`+dW8DjWzS1Tnvv{4WP +zumNkO{^GX`ClXnsJLL{uGG-m`dwedOyq}x$D;W`!3msICghFe-C$oKGhi}r0bl^~& +znEcewn|mL#xjoC&{Ot+k1LiNOyoBp|68=7O(;1$axPV$OIn~_j4rzN#VCRv`rGy8l +z`{+<`&VMX{|7iLDgaaOT__oW%E}2WPK$CgU^@wz@ojqU7Yz54nORJYs3V73#)d;9; +ztj_EtMY)_)E89-$korwfO%%LmM>hDi+S@lZ)+r846fo>Z>+h*xC-`BQu@(u)%{Fen0yr@o$*3D2~wO +zA%()$yWj^G+6egeI=@05w?seJn;HEl`l+TdgP-Km0N(0)wAblfYFB2_)#0OiD#kGF==SHsl9ujD{InjGC5}Ld2 +znxz$sa0$#?%4>Aeyv}{)AY@HN$NV@wS|d=#@6}u5TkAxyOd@S(mCzrqyF%T4@l^M) +z(%HOaeHy#+MS43nZ@!S!I`PnXHiU(`#C{gN=v%k0I74;k@w2PdNGD40S|s0dw<^P@ +zr%&Ju4d9tm#C!7PxTy1S^j9Hr%xCge`$Lp|VykwMxV7??A)j2a>QiFAc(S8-eb1n+ +z%FrAhN$Sa(do* +zcR>ARw20z5?SwBfF+<+x{@mV`|IqUO&LgwL!$gl9xPuv^JD-(h4*}{(B)&zbkM;8^ +zt=&U#?$oE_3ilqH#r|Ai6JJV71)$s;dQZk3uYqEFHTsjhseQ$>+4ytXTFEp5p>OEG +z=9O|9y=xgdb^i$f!ddZ6&h$Ko2@GGF&;|5QVe8&yKH_sg=YfS=ISdakza>$3;?vVU +zhb-ZsyBT**5x8d_i7w}HkpLk=@cK3!rq9SCAbz8y%conk82LPUOqxo=fIDY{^$_4` +zty5QBaTlIx`oC1&TM0UQdN$c*WcQGgNhxnYU5=vqqxb<~nKY;{TM +zJ2=QS1I|UZIMDpESjnS?kGH(?MPGYX=p?k-;@A6?{BnpIM?}Ua93Ho~q4#cp2mmpR +zqDD;{R6n59{1JWb~ +zXkWX#M}zV`p_(j+Aq8es)HkZ^&V`Hj>J$Ty2ON$t$0HQ@ehb2tFp-RE+gLlqA>Ez| +zcUj{YSRK#28H*Sp=V9sO3cRo)su$e6F*e)my==8;K#RThIP1|q3tLJh70QRjAF(EM +zOf(p$tVz9)J&FiLA)?1drXKpl>aGamsYOzxs^bnMpW@!1gz+c?-7Am4Sdbiq2kDI+ +zPO@9AvLPKgmk%<%lurTmGs)(xKFp@f#C>(H)oV6WmC<yBCX;9TJ7QF(d-PtUttQASDBWI@`~c{IdmcJ +zQM^FF3>jZE(B^n-$Ky${5Tl?-_NR^BR(-lG_ZZ>Io{gQpWDwh;J3u6xn@3VNVb4)% +z`n_%Zdpts!#XuVn6@WO7RCcHWc6h&OT0{2Nu7cm?Oe18Pp6<^p`S))vw~=g05wfeI^9w-Ly? +z#)hp#+7y}kxkK#OJqjEi-`NEW;5p)UPxl~4n$jooo0n_#-LHh6Rpjb@7-Q)3kNZSb +zFFclo@jhu;;@jxI2iabonyYu9T4gVZ#KRF2uk;9X8BqIs2obzzp?&Q`{Lx-o*Ck$6 +zqxYgE>*S+zlHW|^->@IV#Yvif=_nD&X +z?SY$G`4Uc{UE#$TH~99`|iqy(H|nG?v_4rBl2{E~WzJ1@G^P0{4iD +zhV4{+)2XCGg>onlJ|1zEU`!tDFmkG^JpwmP=&&K@CXftKE@Dz3rT?QE^&VuT3Ap78 +z(!{K0;eOu^R#8c~eepsOd>tnx??HzK2A3~Qr9lmeNb{a(zPJ0aZ3{o--g*v$yA~x1 +z@q=XY61&G$fJjJ(zTu4sm-&;$a;3_?CNp}Oa$DcJ4_uA$O0>_P=a|Cn2T5_H;IVze +zZ))#`pD_StdR(y5_Vgoyuk^hX!+Up%?x}kh1^0dfgyr{d9hlUCEp9TR>Bqp}ewzI& +z|7*{5^kLmfYH#Qi>~-I{SjMj~uT|+NRxgP;79DJ*$TAfiw_3KEm95<_zQKU@VE) +z2a1cxe8Ib~XRnJ*4%!d|?+&IcSeP0?ZR&CP4mLkgLxfJn417W9iCsu9nRK{NsiWwH +zoll(Y8y^TJ8Np=aP(|7sNTQ?+qCs43DEOETN* +znxA;${vPwFZ&N2<7K%Kf4*M3qjb#d&oQwB=xc+hU_)NGA38-I)!v@hliuqsz3ERsy +z7IVv{?nV)^)SZ_C;BMf4dg1qOe2N&TXkv@~Iewnvgi%!^nnu&j-VzFJR|bMqQw3ZT-WY>Y*9{+e*V?0B^_3CP!bFz4Zf#!A_mOHHx +zoqhNKayTEJI2I5m_-~{68C<7NxPaT$x+$P?Euo`W$&Q|@Y4#`*J{*>Qe(p!y--99i +zO_1$Ian^*Ovd%Wl=enab{9bg9gOpjo?g+Z)$#cX=gKy&E39qDjsW5z~Q+#5kuIJYC|exmm0E%dyGpQW9<6(L-L%jh<+u}zSX +zS-UCD4{4ZT=*(uBY{FxOs0`bAWXq@PUDJdPFJ#mlP#$ +zCtTx2Iw#!HzcD&#)LlIs`_P{apnkL7^KJYwkcR{V5NtzVqFbo=Rx#`Di&nB++;cFt;w34d9ps?ELf1$Ir7_wnXcQ8`q7a#M+~elXZ`TE1hF)V8woqw)Y?!k6y5aw3s$h+tNA=d}gC_UYf?EwI8tw1lHQe^?ZDf96kr>zP +zrfE`l*9e!Hp3O(FUopRe2kAHN_z!;rbT^lOQvzR;H30NV4V`e8Om!T*C(n?EB(yW` +z*NFqcQMmUuJ6dZrsV?^s;mYL_q(;~;d8_wb&KJ5}=?N;D^pz*3~^HCXLSBZ^x +ztLeD{l1=BlMMKTMmx%rcH2wTL(A-loNN$EmF86-(inlu7jZU&^HW+dEdQ=wiiAT>A +zeQ{miPh2=TXBT815xOm%43|0GzMW;@vvqj|BM$9ByJd0tTs`M%7|#Lqx8@I%bwVax +z=-C-1(1XAzYliP@cpGM0b<2d(z=Y*3(RiiVSpAL|mEO5K%H>fgrV;#@*qR+)+(|LI +zRh$(0{xe1oQTuFW#od<>87IYO>C_8{$b#F7o&8YZMLMkI=H_eGz!Q5g6ajPKPGKK) +zgNSf<_U<*GYCl92s*lxxn}uQIYUwN3__tBwBM0VrIZvt6d7xk=Q4F`$OQZdSSow?D +z_1qAt-~P+@_Ylq3{bkYPNp?z&=K-Og11t0=+mLxW6Y0Yf?WOl0ZgoR%XJg|z#)P>&^KuF0kkf16Sa05EVCAK+job=1da +zL$K?ZC&_jT(tG}!nzt<`TP{_=#uX~5gV5V|#qrEtuzZv!r*dC0J7_>e(+@np;(h%Wd!FIi{RSY>u=qm4{^Ul3w(DK1~8#}30Y36_%1qu$NI^eM7) +zwUirs)kX2C@G}_d^GH!f9nH^@LpK<&-hjT>M9&=ZOQtDVFNViHW;*?V3^1U^ +zx9`&ZJ*Y!z<65#?*f;oWXpiovH+q&5u$<3mB!dvbpwC>#-Y9j?bG+O?r$arqH4lqf +zNs-KB>i3(Kn=URs$xT4_VSkV8_HS6#8{nfsN7(PqjaqapE(}<`$%o>B*dq6iHA%kF +zFZEsI2N?SrT@}rqkE{A==|_lf0ojctRM*&>i2~z^Z96JltZbNybCR4V^3z`iy!%L3 +zXkVFhYVnoik|;i_MM*lkbe$KS@r6gMeGWG(UhSO=FU-!%So#@xs8#gmwEgH*YtL}# +z5sw^qFjQbSO8;hVTURcV_-)?5t;*H9Eocdky^z|6d(!%Lk_-?9++mF%{Q$wI`}q5e +zR)3H75ED-kB%Ci}?o6G2G}C$PtY&yufX^O%6g$s*tr!ov-r%e+dNSSx2AJbF!M&f( +zRlOo>Ao57aJT{Vr*a&QLr)9%Qxv0)dv~M*ZtU~aszE=X|-Yq4#%T@GfNPulJvv1tk +zfE(0_S&V?QE97;x7L2bQ!z(0WUiyH!Qts9;LB4g%j-!{_QC;qd2(n4+0uBUhMOt?b +z*neW|+zl)OH9T4uAu&Sk;ec}vIDxlu6GA1oFMp?3$1_EOd6Dv^ +z*%pBtP}j668D?=a*Q@^d@%>4NQ;wi2Kpobe)svvLcs|30c~AvjNf%TpRO2E))Iat4 +z_4hE4mby?Ilrpm6x0+sGcE_^^yYP#sBCGu +zF~I41?zJ3HF7tlqG?-!p7w8+I@-pM?i$V9nmU@_E&mu7MN?k=XP( +zyyZyl32!@PBs6y=K8be%8LmyvDCt;rc-ZWA5TLyh(4$jiTXjn}eJI||R2%+Oz_ +z7Oer^YiuPCwn#+Z14AT$DJAQ=6!A@~Jj@ecmSCZXugy|0CJGo;dpA)6fp?Q-T+G%k +zr0dl>x`W*1L$^EnZsq6W*7pvir4Nd%;~G-?#Ezb~q??=QI$|})I)6%&==+YK3>Z)P +z1_f`!TkTZJ+0`M$Q5TR=?$Pa1b2llzjswCE?8WhJ%|kCda0=BhvD{M|6bXnzUL8eF +zJ2xS({OuoMdNW2{db95XX6*iRVsDl=X;U +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 +zGf(n&;vHKKbic!N! +z77hXmc8;5L!i8485|_I{;6C;0b^x&e{SfBfqr~r}J37C5|3rK}0T4Q8?Qw^^=L;_0 +zc;yNN$Idl-R1IsTD?UfMr}H1RM7*oPR8`r`>v6PJ9M6R>s|%I6F$MXFb&lfm6l-lC +zDi^_5jsj&wrSbrY_ +zEk7R?R&o1i={~8`Q{oMN1#W_gwhZlw#GBMhCjm4fWtZH$Xh}b;7bb99alUPInARC<9bWd8l;%S8UN1`{u)^5kq%_F1?`sEcx +zmv0Q8E``oyQa}4j`aD*5NFQ2k3cZ@6wiFlrRwm`@^r=1cErTzI0xbab>|8lw8Mo4| +zsoj*|ppJ91>>OW#DSjF`I30lO7~YY1Km`%kUHeNqIJfe&$I4#Ip(VVx$yO2P=6P(N +z8oVzNJ5A8V*`n3lzP^3A35^uaeirUW%Q39~tW%ump$sd0-=4&aPGWIdpl1Ux0ltp} +za)FaPn<)GT!DB+-1TTYo+(fAPVOol_r*t&%DNB}MPV?!``&w303{&!knGyxEpL3H +zRv+xUec%6ED=&!wX+gkjj^DYmM5XT)N#q^OYwQp7+}Unw;``-V5k9Y$D$Ii1G{=W; +z6^FZv2%aFn9+~o`;{vP`Jw%G69R-$uiMlnYyCkH2^{^WW(4%ATDY$2SE@%^}E8Ea` +z$68E21L{;Q$b}-PcF+YMP!!dGcFgODW`4gmFS>N1LIJ+c$~(a$V8gF$=iP|VQ-1#Z +z{zT$Z?H%u}YY5d$NWoj5J8e(6f?}y>{Ts?T-;wUmW%YYZu>E`Wp)02IMV$bOEPv5t +zo41{pH6svlT1>r{`q4*1!eL^u%CmB&C&(5(mfohxu+4rO7gp+E|BK+T9Rd{nnzhPG +zYvacIA<$~dE0^mEQrI^N{unLQ2@1Hoc-@9>FWpn$U{%gQ)b*`Rb>~rPVtdRF;XJ&& +z2)NjOm36pbdYnBQ^m(7oy#{tyR4qmf-Y_oVn +z_AF58`DRSzuq*Q92@~i&G!yV$21;gRRqX0vI^7eURRsug2CKDB-Tvl6^PEfk)PjA< +zMW8{azliKMcblU(VEn%N4S73en(*(w>(8a)iib3a>%CHPxX602R5Muc3;DL?o5%a> +zYnk5*>nBm?L|PZ{I&hh;ofA}#`94zIcjpB9x#nw(7R!w1GuUS~EzhgYEBV=Q@ToS6 +z0(#^YfL7#I`}p1{nTwNJHD5~G*kKg>Qn!!1as(_J&3(VG8D+J27&2DH2I@@463myg +z?V94~m^cI(x~QM-rALIS*YZhjroEnNAm`rW{yDiNzEz`g_3{iBXAfgg?jewqo`G0C +z4;<80`e+9)j$IilbL1P80y@I(y4=SAtAd+S9kUVQ`jLRA`W18iRe+eU6z%8O+#t9aVf4FZ{T@X`SDf#=?WSa-{d3`;9Psm562OMN +zYW}J~?>L`&%;sVanA)K`F{CC)_pLDf7j`ST@a|KyHcsBj&kLFjF3UGqWPWtZ&vIV7 +z^xlIMZS80GNp}PZnX7ER;2Z$4`dp(<7xT5-6&e{ais&IK|6hQGeq4Y;TtEPh_OSH +zA~Jc*DtV&Lxwi%UvdJM<#N42HK>Wluihcfaf*A7|I2t~x96Mh#OKj2^xykc%6r3** +z)XVYvR(Dk&i+kl=mvOiE>!G-D86#Sw5`7V8>J&#S$gr +zXCPht9$o}**zMueIkPGXKB-1?oZ%_3!)@qx@6*D2;^5tjJaS~YzTthDsT!)saH)># +z&2^Fcboh#2oHI|+cKT2&cj%yO`*{pu#nobYxrRcIJ(ORplJbtRsTak97v7 +z95k>#7QknWQ?ngDE8K7h%?0yC4rag;-1>OE;X1p}j42YHbjyfbbxU)1LmdHflQoryo*m0%*fy-1g`u +zAF_k`nao{e>m#zn2!=OrU4O3`CCmNszJncFR-SusK&p;@{VzxAJEne^JEqVhe`>>! +z`-t4VqC)Sd4BvVDD~Z3rFB}KOEx=*-`gq*Z&vB&qJ?_}%lvPG4^_BpcSPf9~9I4SE +zh-h5^cw6Us%Hb!0TBk0Er0pv((Crg-`M9u7-^`&wdf+mTLO-O!;zyV6c`E$U!Jct~ +zZE?jg5$dnac~W4{k^Fqf-edFR7%JKY>F(*Z2gE(ANKJFv@e_dw_XZq6-N?ha`sA&! +z3!0};jNm?!h6f$|ixp}sg`1bO>hm;0k9W7Mv*vI}uN<2=X$8KYufyJx>?E(qpOpvA +zfV#BhwSp?sNZ+SR!(q)6X{>Kq#boka=K~sr^~Kh{$5H$ikzAmw2P)RozX{?9p{JVf +z-nP)4b4m0D8l&r_FJosJjg{kcC0{nQ}udrgOjR|^EREsIbGFC%iCwd>Ij +zB?xW<+@Crzeh)~>-f@ITmd{b)KsXPgfBuX9u<0`&Cx<2RyI+&HTRjj7n8SDrqw>`} +z<4U;l#8Dvsn-DpD8;aGuG7l}YENz02S^^y?zJ{I>hl=Z=)n@oZ9FoMNI^LEFY~Sfv +z)dJ_HoZI$6Rex8oqa~X|#ytJW`Fp?mNt7H&%51;1f +zdc~a?WMbt4M~92XuvwX;LDt)u*h?DadA@18166?~X0OyWU;Y-`*#xafyF=$bj-2lr +z{vJK}bcP(3b{&j*glHNDuZ=S7ICTfL8JszI94JwLFR`E0UeRbV3{&SJnW8~%Wrwuv +z+=$wLAuMXAE?T!aAS%i{%{{uJN$&^NJ_0L +ziqHrKGlBPdC+pz)!PH1gb$T>#oHY(MVaMANxfd5Iln3wE${9RJCozS4@rv6q7;(of +zIh}(A?FSaFZ!{L1`>-YPvo>t+$NhjIl{gbc*^4_O=^lXH$8zX9xXg8LDz<%VTlHdo +z&n3y5o89w%MugU~uoiP3q>HdF +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 +zfr&>%W)q$Ut3La{PL0p@oFhBOjvE +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 +z6W|elJ2-@DPV2+LbvX859jEHE3WpEx%i +zwXUd0SGa`JdT>>C`KH6hjZtBh5n-%U1e4D(Ax6Gxe5Zrupd=Uo(fip**)4gRUJ%wf +z7w-E86`?s#QfS@%guM-nul_xWii@Yg+VX%p<&CmXn!8m7wRhdE@`CKmT_Hk|gYJp$ +z@^g+$|3eWiw=YqjZOfI*QMOEiW?jeHTSC%@`_W5nT;(x4k=b%W!ehet(4y)dC&uvej7b}~bKUc;}b^g}u0t8$*V~3%WKjCut7tc1f +zSA)HRs7bNR-%TIyy!Gv`$j|rlyBYvse((KfS(5%q5Q1ub;w|F$kjlcANgebTJ>56t +zY~Pm|+VfDsX}K~PMSm}d +zCw_8Deu3?=Vf$>|7a@tk!up&$9L;ogKzGkB#sOW7r1+Js^mpe+`G8D?E6I^U7^}?) +z2uOFhzDR=<^`wTLzL=me<()do5uTQ +zO=}2wN`mihr`$N%8h9}R{+?OSn>SNk3i+)6^95h%jBi)Nz$CgYgFym!cPv^GX#h|C +zVh8%WSJbS+Iq!nrrL=Pj8}J?X$CRqX*iMT&1iTL~#A{?&c4{KhP~sa2-&$_(N7igB +z=u;}&mtplx)jM#yhp(TP6Q(s%lKJ|a)p9JY7~MMTEJ^i0_}%+^=cE<^bhN+G&ZTo( +z5XaAQcs33mc=(L)pf1PDHozIb>J0k3yL7NGU3PZ@iMl$EKIFoj{KPct!p?0w-2G3# +za0Syn3BXI-nMBwh!U^2sI&jYMx@TX2R74J8=+W7C#$MK&J(~c;XXTUrtM_s=J5f$j +zcC?6A|2?UC=Zkolh_~A0>cJ4f)2L$ +ztKasW&LJ`6`uV1Qcd#xb@6K|wSeDs2?=iy==~UpOxcSiUr@i8GKY`x#8&*wvK;AhZ +z|7R{q87-?y8RvxT<3Ed}+p_+si;UkrPVZip9!Y_+Qa|%B>Vdm!d{0UhB3>=|TNE|Y +zWYNRW`5O%&nmR-W`lJg~tsoY8>p)4z5qa=Z34F%TjJ7Iayi+@8(=7DZcOK +zT={vjes{@~*cb7R<>?pF4eEh<9yzK5eq3PVl$QI^+i6^;!#H`JHY(9HS_ArQSPC@F +zgSgdp@6+ilA=Rw;Z=`o@>>QHDGNJ-H~DawQP +zBpX;?$BGFQSCPKC$3I(?5k6?&d=#7kca|4Z)eeCMpwta1N!?2cL01sF+>FU`II@BhN{tkrY#p=1VuMo(1dEsYaIRpwK`h!Y4e}B +z>USp&ob`PB@Vi{4oF-UT4BbWo_JI_TdIZ34BW+*6CgievfgZN3^!4SJ*J!vq*-0)n +z$^rnn>h+cAv5n}5F=e~nQABf@kkfqM^<&8h>N2oFWOc89dU>Ab{5?7N*_#vA+}L_w +zX$|K)SIZBARQ6st+MI>Noa0SbgYUUTKiSOh-ko~+y7SG0Fgj3=KZdw!tlSfhH!m(x +z^$iX>SFczc_TqcU=M1it>3Qi)rYGlKd8zeG`O8(7x3)sf8~jY%PZ(T2Ys3fSz1id< +z)Hr%x9>a$&k^7-I)+E7z`7@TS;2gja!%J>n=!>@}+3X@A@32THZW!}kn-fvENfEpZI@*ucaL&?FTKm;!J-9?=2}Be(b&G +zI%bBK4Hys*578lKy)w7QH01y&D0g8`g>d7Z-jfE +zv`3UDSWodwR>O|>pe)O`z0?z({+Veh3vxlkEoDgSgIH|8>~ +zsp`AKU3eH=4)`+gL~8r8UT+XoZ|s3^g0PUv|r +zalf!|ew{e`-BCOyGT1oM=aIf6%A)y+bJ8v!)o-asua6r5cCCK674u!FMdiNHa!>Es +zp0VVUI0=AGB{7-A=MYk=;Y1vkl7n*m->HLr^c^?>2_L|nP*I>IzRUfuiG|(7daM3^ +zcV!$gxWo|1$GkG$0SB&(6H(On9HJrsJ2K%|=c^GHi0Dt9s^1lxLYRBl&%Dhl*4Ijm#!=58pnal4KnWnY;#uvML40O$r1N+yP^$+ +zmWCS1UbeJr7u7>LAI=%@xKmarcFkX4-#UBG-<480V#OKEdc3F4nd<I(YYr%KtMf!(9PbtB>yM~s2Ht!98WT5Jtu8?B{Vgr0E +zeaGVcw9pTp%HN*ek9>5-0gH%AXT(-jTQzg1yM9&Hhsz&bmxIn#_Z;;{)PK$9+kb33 +z8Eyd*!|c81NWOEi7YojC!6R>S@9IlKQb`Uo>RKt2aPBy0t1xU2g90JJJQ$*|=Y0KORPV_^P*6HEasTc7ywgnEB8HoTSL{wT +zdlrSa7EW?#q7J?PDVyIAGBC$XutE5~ko&hF-e;XEc&vi+h`Py{#o=n=(|3w!jw(Rz +zV;fky=aE+D#$SCy``t^m=z>(eG7c&!uzoJYFQClE6qWi$AC@dk}~K +z<2D>Y;``ZC9w6htE4Ot_`u4?$xbu-{+&?e^)sE-!ZY~q;DxZes +z2j{#H`C4ezx$A8)_8r$>H7NVt;U$j)L4p+$(;GhLma@6E&ni~F6-g!~pa(x5Ucy$ut?@Do>u +z8_^dRmqgzmqX8ATewP2-Ewc$fM@N~sPDKD;(A$}PQ(yS(diSn1+%GXTC90qU +zf%*Q-Gymb~)?PaNxvG#7?>S<83)$;f^(+$vSL|I +z9lV_bkhf-`$oMwR+~!l3EdcRybakopbUt*F?h^9y1z|uzgPWruoFO1|43IiAo6Q(9uV{;cJt45I72( +zj5lNxJOqt+9O(LT1v64!$HS>P5rwDR;XA~%UYD{NAMdV5EVZVW5V_@Lufl82%)E$? +zu82g43u6ktvs_IrEvpwScI=e2u_7V|?d>~4V*}3G^{q|*iOd5Y#%htO$^n_ON7aq; +z=(ic17eG~IrczP?sd0i{*c0KOZ}evt3O5=kwF;&C-AjEy$k!s2kejbv5qJ=G;9uG1 +zQ4tG*JZyoy^jQT!7`7c^pB{r#i+yYmg^KvSM|xDJvu1JK?tV%hr`QS7?jiHKa3&39 +zLh2aO(b87XfmrM1UR%@Q3)KXP8NDnII{cZB5dBIkMJNz#`6As<^V2^`s|SYj7=+y& +z%VH#j8i7Gc`&Fm#-@R=By~k2{Z&&YWY`5~zWA6>DirY~ihmCMp$9CSYZ9no2K7X=A +zHHu3&bdya7&Zpaf4{zPmqj+AJ9u?pccrP*HC2hD`zGZq@<$xSgX`Z=YaNtbcR0r3^ +z315$VE$`H +zTE95B|L%tGp}K}8SV>hJ+>2h<7JJXB0l(=-ST)Dp-{GZ6I$jw4IN-6$1E2M$To*nM +zrC!UM=Ut*eI{ql8ai3m1#<7Rp`S8uSiOc*B<9&P!YKTPcz4EwYIk;)x0GD`I{eor5 +z)sqOh?^#2$A` +z|9t4v(avl4#zSZ(B+cEaPPIg{q-IA5t(J>J{F|uzG>lwV^{&J5+rkeVD{p)rvyZ9@ +zPZ^#}ipVQnk2Si6#>OQ_?Yu~GY%coyWwaSC&@8Gj>o0DbMpbNJ-0K!7oQJG*4nyG4 +zd**;%KIHtTh6Xg{RNgtsF=vm|ow;s=$#!+_C%bT8m}z^oUOke&A=oqfYah^mcifey +zzTTp^44mE3rjz-ej?3<6DA|vw`BCa*H?!iT6L! +z3s%3S9N!<_INWVXRRn=dGJ(8{Wxwty{P(T?73y9fo +zoCMxsTD{Dwdhchfm!}x{0boO0kS*!p=ceD*!uq);PxQ)_vTznHnt<-P6_iZ&m*)UjKxeUc`%p)Ywp- +zE(rrPF2}3ThRyJ$s|Nkf9s8&H&423vF5`Ng8w*M}!Z<|94z)6oHKI4Sg}dgxn8#Te +zHXo5b=fFzgpd7IplKV}~yBTOVkFRO~YS*J|_kQyJBV?zzj*B>$VC&; +zUay&!MSsw!=&E}H=g}(i{>>Erqa#;*lkcXnzmO^@ul-n3)jmQNY&?(f_ZY@!4Jo%H +za6HuX&MY?5-^HY1SCum7%yA;x9p~PJV8y*W$q66AnlUcFhe^uWg+>p)#>h0rP6c +zt(KDn_{fp^cQsF!zk95o@A$XY;Jgz2%~d;b{HO$d^J(E+xF4mRVPbKfHa|DQGq?vk +zPwQSkb8yKqe~bzL9R!j0a)b$gNK-+2z7u8W3x@$|J)+dF;a +zK$>*xQDINS^t}^f@7pPUzvbT@a~hDyly$VocW&yjAm`C@&a&YneSzS4Cz@qyh-IO) +z^qV}n53-rasR5v)aF~n!9c1CU`im_4UeF5=+LLu(F1km+<)Ll(GM^NcyVxdU$)@h< +zzDbwU_A>h;rDNk?lXiwSP9;GCQF3 +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 +zKjNqEB~vjsEa(fCe&U||ABr{Z3wr=m* +z`4E09i-P&g>O&azwLQF&gQ;)(>DhB0OT9OaKnuiN09|i67S64LondZ)CYhDc!m&;R +zkGBE!aR`&HV!%h55EKiyvd{I2s0o(^k#=!t;9H#ox>Edtiur7PxxgtF9?5y+yEk+OophzI!UaY_81V +zVfn(F0~qB*ryHQ^9y5CzQe+&_%Pm-VO~9E@9kael$1k;So{n +zas+!IaOckj$&0b!K5R>3HhJ#hqii1EI>>uRx4UZ)dZ-m|&3C(xPQStIZ~f98j0H^R +zE!}p6@7{;H{MJpnT@h5mFGZFeA0j;$2!<;Zx^VOnOpHK*hFan-lKiJogneTb>gL +zkXskfr-N>39@s-+20wlE;Xe!lBA1}_+CFM+86J6yoay9&+etE?LCwW`G?$(C>i9V* +zZm*!jXHx*q}=&TEv{_|}PsD{A_|;EUgIrtaLkYIMyaC_8@__5V;w*{;K>xJ;j^ +z7b{tK85JZJ4O8IsmcODI$|BC6QiqGlMNt^9gGE`SZiIt@pn$6$pgWDG4dP+T5~*F7 +zmj6F^d+UTfsAVg;*Wl&34jp7JGN(X0X!{+pNy%af-ecoCwr38I+zp?0t7udr#aF?3 +z5GYn3{GwUIa9|hf6auxL$(#@md9?-9`){BA#Ms@SDuS@m^PPuFn1$z~=^JHjtmPn) +zbw|x2n2b7IwM%5vLT{cc +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 +zf=VvzZ4Ww^RYvV|hL5G%{#3!C19fPCB2{ylIg +z>#U>!KR9aFb4g)@yI>6h&-Drp&&u?J*BtEPF@>Y8=l)!{-@-*d)Gf{eN8Yp3*mt3~ +zjINwt^L~paR4RS4^5jc*koK)JOxq`Nr%0HFbo+*qzD)PH0#313%oJ06{&J@>_hrh~ +zH3D3GU-%%aE>hI!|+zl +zXQsPi;H#QIm=t}bOX?xhK&dTH#0W1hcU`zqmJa(eKBf&I8Qe&-zx8#F=$HD@+>0bI +zbw2M-=X(xak7A0^y7pKt-r*!N?_5v0 +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 +z>t+Yep9~L;{khctVG4aJbB@iG +zxaRZ#bDskJ*N+O<#XKdYa`qvexm-R%t7>G(YPvnzv_42FkBUY(fRFR%J%B12a%=*+_gcsvfp)oYDVi_}f+ +zH6!PUmW>7q?im>32yu!WJqHWVJgSCo;~EYP@hR4uA#E)Pw9)JHpoE_UBN +zJ}0Bu(%bgbEdY^kd`mKm+de_~L3V?i(57RhZ`W2;*XK2BXp%DLQgk~()O-3Ct=bp@ +zvvG5~hsE$X9C(0hs=|xCFx>eC^x;h9i!5sZ+Yl@GKZ?uM@c_R<{B4Lf-g1;ec_5wn?IsCu3<8K$Ikl-HgTG!6}E2Vq$vcU*xK7u +zT|92~Aot3{mW>cfN(_y7378}t;YtT%Pvj9h5kgB)E}!#kVX3QpDTbA@n@zs9Ogwfe +zhT6{}9(l`yR(~#dBDko<$!5kJ;kr9G6hPx;B1Kts$>J85d_Nw#YA@J-Tu{jGhH-r{ +z=WdU@-px;?F)mrNn%O<)z?|@x1^W72hKI>pL&EuUjagIw-1Z^DdG`)MeA+EL8BubT +zZUdajOI#ZBP5ZTqOo`#N;l=5d!-v_~N%o@Jxyf_fA38Wr351HHGk~KADU9WQH1=V^ +zJWH#$@-))zcvZl@{xjb=bvk$tFy7nLm=&pF$LT#=pL*eYR1pdJVw-0baq2gRN}mOg +z=U%I;G%nrbF?-=g#>;ehfs=f5i#g4JtM5I88i>Syk5(N-xX#`inkc7N<`idVS%`f| +zKM#>l_NUAVNU>6{3JTocOa9w%+|Dd3K{KR<_`T^5l?>}0(Ngpq-3TzkIYKvpHu=@8 +zuT!gG?Djq9bF?t3rdyvZZQ`YG1jb4e8I@k8J+C;a%!6Xp$PTwCb!+bR={jog0tn^a +z&aq9C7OS>>fFzLUN-?dDSsZRJLlj5J(l&@Ia+63~e_tx9SCC1+{W5>Z$2YmS0 +zs+Yp6^M{0_Yq8;{T%r7KW9LC-g?8&RnOYuwZ_E3b^{FN}T;{UyJ?WXb5QmMtW+UE{ +z(;+U%*30O85h=tE^XAuQD+4CC+(Izvgs1owRlbd{sD>n+D~Go6-rT7cWfRl0s^4Yz +zT!PC{_ljc7CdJ-urao=^aI&q13bewtf_o;5lfwvAum_9-tAM_i{7uZu^!_uE&_8Lg +zD{k>1-#J8q9HVmT+NY;>QV;t#M)b0(KVo+=&(YHmNk+|wYr-54@7mFNa3T_oJ+DCH +zshGd-r};LGQfOel_b301*jUfdrxX0i5h8rojJVL=c0&s6_ysf0~IX3(S5=cf@%1~>=cXiVx4&WC{J^>zxD60#WdipSK +zh1Pgd^&EO2u+hxEoACqu?KZp8U25uEtsDKQ=%1}beOMl%w0!Z`i4V-aXI2XDh(b*B +z`>37uVP)V`NxVnMf4Ahy?^bzl>fwdtw|=hg@%TDu;!BdYaIqT70v-cJ6<9i<@%f*< +zSY^ySQg&Epn(?e6qtETnud57#A_F8)oIi0=)=%D@Jk4Iv;CMXzBvzi@C!pab2{z|k +ze!LN?9=x~94G@ajMfXyrZJA(41sV!t$GugbZIs_dxHbM2GfeiY7^g_?Y +zanV})TL+!sLdU=sy%@?{z}=6*_$2N&*BX@SUhlJfUo!RVc%L7C$Nlf-`jR7=9ZjaC +z(AC#Dk3MFDH}8I$w_{ii_9~ZTQeDC>#?5Lk-4gZVF?ZHAPu+CRjF+~YhybULtDmW_ +zb8M4bEwnMH;eKT;WLS!jK+p!3^t#Oer1NvaQv+uU3Yx%$$05;*{~}<=6;d=;fYFK +za^mG2RqWg45hr9?@chR1zuWP@So2H|Q)Aj8BS($nfe$lA@ZRxn +zj<(}NN=K9g9p7eQG6z!2%^NdyVjsOBA9brJcn=VCl~Zr@aabu5O&b1`A@#m0{OLV$ +zC;K2zC*9P76_7o#;{{V}3=&1)3zwG~uK_lGNWXJSx(P5PM3@ +zKNHy~9!UTD9R8KtqE82pDbDc+__ZGoQ9~-=Pw;BB>epBOVi&C{0~pK +z;Y)JM$H#z7Ae`dEDW)x)p#NMyKve| +z>mNJ~2fhHk4(O=BF74V*$h1fdaH1&YYxV*PVB0yd*+-|sO5~b#bC=1A=NSvkZLNBE +zmt>@s=2EtZs*8_Y@`Q=G@QhVM*a0ahuw=0A!!<@hUuW +zX{6C32NPM<{i;g1^Ql{_oNez>jjdJDWhO9^S9!YO+9`4U+iL8luA@`)rbI>_9;**B +z5BSj-Z@bx2iW2P?t#w{Coc5n1wN-^BF{5W(~ +zU;XTU^okq?{RF@50%M=4h`YzMkr3yy-W;cM?qlPR>xQ@AZuX+GgWU~NP;=*+UK6Id +zfjKd7sJabb0^XJ*h&SiXxs4D1*|ycd&?EFvU!bfQ>QIIF>|IgmBH+3Yp&#WmGH_Pp +z_1W|@a!ZjjO&^^EeVGs!3pDf96hpdwsvP$*juTy?3FA%{&ak7ew5v5-RR^lafr+a= +z(+KjtTF_p!FRPMJGXKf<_c-A79{S{D;Q=bR+s;UROzH+HbP#2HtY`#$&r-qTI6n)4 +z{vHwlyKu^luB9J)?@%AT-_NVeX^9e5Vk`Gkz+t?L3F^|X@<5R#Kg5G+D@Y}a=_C$g +z5SLgJ=~aKY5E{&A8k9-i{@$i(%?|UL1FzSR-D8h13r<;=F#IkV$Onp|uYDTx +zXOGb#*?OA`YjbLVU=G|zqQ9_dFVTb%EvT& +zh=J1Smd?cSsn3-#jD!58PV|n@Lz#$ +zW7PwGCJeF|fv8W&K2C7^;g%s_D7=hV^=d0QlKn?6_&rvj?sFwCs6-Z_-`;c6Ggw$K +z&8l0;$Na!(&sK!pgt{S0(UMLP3@0Dh{h#n~SANbHmM(E(*6AdWrw5Q>o*TsnH11;% +zaaZRtEdyAdG-u6HIf!|Q?hyufNo#gYE)E~FqM96VqPcpi@yIKpRL4t#n7+xVJE$0f +zC*>Y~_`#e9*!QHg)?GwcH#|yZapZ>O_xY>pEHxNCtOHzyA3{52=Nn{(w@QhPc>G?@ +z_m^Au1RhnwW5%MMQ$`8Hw_e#sLN?!tl(F;YJsu&R14l|J)xB`aCQdJ2c)_GMqvhTd +zgJtlblV|vC!X5pOjqo3X2!8d3%_no^_DZND^AY$uQHCyGGg^X9D@HXiziy>!MREGm +zee_m>ndL6IcrFbN;bRRB(UW^PQwTW~{MrV9lAZ@+Q_qDpUnN(4-~*3`d@>(3)IlkF +z+QP=_)7@Iy#QEplJ?FY1%{^?W*LfT42*$|grdP%Uyipi~xPj|s_r-HLO(cm$cj_5B +z>>@U|58OEjd7xeaK6)Z17dyBfdBwJVZ)O`}M^5sKe3USnnEX`fTY4W8Iz21g@|`Ip +ztNBYZF9BbJ#J}(OKymP1IC5mlwu>K{9nP9PERQJYbWUhI4jLqBYj2Mpzw`5sPyb_d +zAt{JuMZe>C^}~KOM6ua#@VOCrZ|y96F|-vpXAZ9&PA!zpwIzL5ccJot9%#bpj0xnOnVb0g^>p1MxP2+45Z`h#N<<_ijRs8dr# +z6ZOtpkgj-Xi6z~Lh0}!|Ws9xtZ~>j^%!eHw47umC<bstQ@RY6Ft?ZQN*7_LYtX7Xz?){;3X0Kf0|_4lwt#TcviRuHQ +z^S1UnL;5W^uS|rlo7(t=%a0Bzmdo1$-t_i9Gp?{|JFGF?hyRXpcOQc49x;Z^Q{K?j +zl`r!9Qp@HGQ7edt=Cd(8>}u?1;Y@ey)X^(g-3b?Vt(q93l#WNrfwNT^cX}FL25mr@ +zfnr(6m-C|FPv`L?RsD`|m`_2Xv8m6pG4iaX_{txJgaPOw;W6D5&yQp5NYv`XAcr-#uuS-f%Tgz%!IFw)0t<_Aru-Mw02{M9nN~yncWY +z&J?RMyt3xA)So+WlH@=dBIlm410TGt!4iKp{F4Z(eZ{rK<#SS7&2&cPZ+ODzm3kgK +z>lrq6{s}80tlmw@ya^zTPA_fPBHd4+?3@(=y#r|Tz{IH>K|lAttx;zJupQTRhS4P?`bKA0pj)kk1RkwsOXCrw9oP^9MuN72I(Chw +ziTS~;WPl(#pklPa!5RLyAb7Sr!A)fV^l<$Y37D{L#8nY1P?68U#qGfjI4cME(`5R+ +zA^f)vr(YbUffhwaCWNn(nKk(aaGbO-MoXg45b;rh-neo~K8hHXnco4ypt>yci=HyN +zE;fOJO4)}kxnU{UQ?fPpmR&4$heM7C96XU3)1zaEqkQLtC)LumT2?GDPucLbWv%aG +zBG(-ym&60Uz9@hB9CaSgd1Z~iwz05DZ1bhBCoSdW6myA)j8Dk@VY9~Gvw`m|v)~x% +zG>zL{H~#c#^1LsM5ji{V^NvLR +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 +zN6_Xk{rrMVj}>9Lc|pUGZ-=Kc;quV~`r +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 +zF%dtJFcsY=7{!O&$ayq3@?Sr?5YO4TQkna +z@!ivgLh-K_wuk*|LMX*2-j~11)>^SU75ev)pq0i0Kl$2S&JzU>Ntlch_kJ@52r`^V +zk3J+6~TkAHzMW+p +zw1R2n?h9@itzgmUuN}PvmsFWSwEf1e6>}s`=dPHVK(r6aaCgw##hv;3#mn--pEY=2M;b&XW +zx4kIhbGG8AJmnFOZw7Apv6=G!eyhhw+Kfpa-&e_pn=nEwl#AiPVLFol+P4 +zUg1wTs~t037OopC#|SUD)UgCEx_pgEmQ9-<1nibGJ*`j&>9-d9-Ik_RZRBdh-(cPx +z6sxXBArf4U7HT%n4MoKY%trK6xNDle_RVyMouN2+_$577v=;?aK7}}sLO4_%!>H=44zA!C5)92Fx(>knUdZebSml +zl;qxX9>J!%tGxi0CvSKm9=nP;7fZmX5KeHgbHw^x4b3PHv6URj{8x3#M_!h1A=H$u +z?SmYAQn)L)=dPmOJ&S+W`|+H6%<|{}x;6G30D72BLPz84{^928Edv)N9^Seu@%Y%! +zK>FRtCf-44Rj}RqQmEO|4Laxtyk7ob@|(72f-lc?=C_02SM~f(^?OAj=&^j#J28R; +zdcNz;)x(1O>1DC3we4lhe;_`xm +z&>NLe$7-XdhgqAQTxa&DMvMPyecQz~->ZBeBhn`E>#OLA2n@7ys#(IQ+g_5e%k%xs +zeQ>usGWC>$2IQXEG&46CyJ~n;iK7X00={a5JNGWT3_9ynDKm=qRvI*&bERZS6 +z`m?!yQqz1H&mnWn+o2>nPc(F-*P*GeNG!4PyC==@MK>!E^v6IH0q}6_@uZYGFJYa> +zhfL=|?ITgcU1(VsG%EOO;6eY&n|K57Md#iFNiHUvJuiven{upfwLcDVFPD+uzk|s) +zLH6FSYnSv?)8(V&65)~dFk#N#$4JTN+7lBjglyjDKZ5CZ9dexkPsg*HoynQsxHX(O +zFHy;3Un)_d19E{~QA&di7m}@RVn+K7jybnv{pCra?B=!4C3{YinqD@ygGaBuy*w}4!m5bx3=c%&V!DW1 +zl7ISoi!2SXCjGk_OEsXDoyLsi9lkBtf(j<|wx#HO3Q^y#(>YOu2~ydQd=1>)YWMf= +zzF6kQGzGu8%%@mQ=ug_sB+33&`!2rhgX(}Txxntt6j+-_yVZ1TsXre9rnX*?pR_xE +zx7QKZk((uS?5^l}7J=ZUiokjd +z_|%>ZsHWpUYI3MA>Rvh0`5=FrNMc~%G+m1D9eGRw=SkO!^pwYy_GrLv(vv%>XQ@hP +zj>hBYr?s+=x@qUw%&Ny%frYv;lcZHhy&nU)20`AE(CxE4Q?^tne4;n4`XulKk7jw| +zr7;SWitK=ZdYA)hah9Y4>KdZw-jEBsH2@re9;dAgec11g$~l1PP*Q^5i964n`!s!b +zNwuGZ8a3r_q>QaRYMVPtID=k>#~1+r_Ls?!Lt||_U+b|{jVkUzYl{u- +zwR0q(@Ef^N4^~VKN6hJGL0SB6$OCkG$VwD+awOvMHP*N+Nn~*PCVn5V4_@9|cBJ7x +zqTixRLUk_WqS78CmWzFFRCS!uZ=!VA#W`JhKn48JrcTAg;(=O^d+AP4ae3YYr@%oST5CASF-0@94k6(aVDy +ziC+6s{5>^q%YC#8aqme+Igj(bCo^aW6Hv(_I!%0>vA)J_QmP>Gf+33>IR=0RW*)Ph +z^k+$H;!DGOXwK26O-p^~dI{bnn!_~eRJUjCg?`83x;}(Fb)>RL^}zK<5ok8A#<)#reFnMq;5jwO`htu+ +zlA!vKQy(Mj4wB|4{Pwn9?}owLgg@(x(&rR{LWyY`+{D|L>{8aW7KIgP(0%*+<>F4j +zRH5WG{C(~nznlJC{2VOJz1x*id0hMR5NDX92T#L!n?BiaG9)C`W^|tZUBi$ki+Jkf +zeyvi2r|vo1Yl)f1&ZU;eF^gA*O5e6G<^pi_m9L^tXB(7Wrmyt6U=}5h;dQE;U0R!w +zIQ$?@a1$4#-~q)ghouqEBBSrI$KzHt7dPPNLFm_GFlW|bQiwgH9*U#iKB}CwX8`x* +zfTvN-IOO-9>2Gyc0dpF_rSvc`&Yw_%0aQ +z&pLtl4?i!tXmjUtPfnn&T4wsEYlsc7XG~U|w+g$R02AZ0BW=70s5o`QbqWrQ@zFdy +z0}AJ<-f#iL1`HvrJz~V~;|B&m9C+ftpHN7*7E*Hn`~= +zk3xQ-Sn@Cy0wJ~H((%>BI!D6OS)co~*EfHLO~XIhx=#|#ZH<9A +z3a7x;MlY@8V0n%6g@xwf)`f&RYee5A^U*}+D-{wK6u%i!w*rrC|5-y2!zFq8aj4Eb +z*$ed5!gmAu$(kh<&tVneO2;ee;nz9N{mrj_w<7up)Wae7URa8_=aQe7b*UaJWF&9! +zJOIufeRS~J(VN!>kF)yIk^Pl%Vjans4XD*}M4aBY7U=GXpj4x$GtK770vbn4d(bBr +zQ`PU|Q!@8TJV{2B0J_PwLr2Od3}q1BkK}BDub)Y=Em1Oln{S44IyNuMw82y{S;zu7 +z-N*Wb?4ih((#t{SOL;I(S5d9qkzS!M96sL<^aM27`!)Dgo-RLbeoB**CgoJSNbFY# +z^fYyH1pv7?o~!u)3^GrI&F3f~r%NVsb&uDjB|K-y*AVY1d8&X0Vh#}p-K2weo7QUQ +z#5XdU(8)md8;vj4f$8&S06jp$zuwwzEvUxg{!BmAYWlMZ#@m?>j31+9PzK~fuy^MX +zkk)hNXB~I^ZeF~Uqc8enzWxoLyzj9^P2=9r$c2jbc*4pW#N?S4DaZ%DDIIaYK5^Mu +zJ(41{$eoBs^(%+S$4B)^pG+kWDN;->&Cf9m#FQ1D$P0<>o~^)!wB|MR`~w7SC!@ER)f2sr#$fCUZ?O( +z(_7KHC$dUEcVmDJqK8yjwAX<3pCfW#v|UoNIVK!V3iRmOTZM?~Z#vw~veg|JJl98E +zzd_z*)=&#g&=X(_aluf{5+<-tAiBr-%FO7HWTydqm7eD&Uj@JX(s-TCOp^}z^Zd%1 +z=Nx}LL{Epl-E|yWKz07rslNTaPowc|-~yrhZBjiae&?>=?T!;)2&ApL-OpkMP<8pU +zjN3XBylj<;hM3ufZZzIEM3(h~w6W>dKYG2V< +zds}awe7^+7+;|@aIEs}1wYop%OD#zWXBSWSr87%M`fCiUdm;P8_LfEPH5y`n%n(5y +zjvfSDoH)jIdEm|sjvCNI;9tqo*0_mMdcOU;l(luwoxx+=F>GhqLsT9&FfSK8{ytG# +z^QNvWP@8-`vnm{hd`r?5W`*ue_#OkbDyutpO_*fn=2SmW0+owB*3xH=Cqs!G;-@P7 +zbB+Q_lKCvp$0PiTorD|b<#VVrdG8SZ?W;IAU9qSkb>0X5rqPq$gItF~;3Wt%Nz-a0 +z`;LsCveAkAn|J+gkmN$zP>2>dOvgo%`Z453p6Be9#E|2$&gi+!D4&4=vs*_!HL+TX +zi^|gDlnwMqFaWLU>4_VAvftC+vhMr2=Uo>@#m_}u^ra_Y-5j3tor1LYqA*mhsb6Th +zl}m6x-}JE3z`(*wP-%-svElTHQqOulsm`<~svK0#k%(`?UEzx!(_@G4#pasJm{cnS +zDixK89rs|6h3SY*^5XTQm)ZmQB$a|)J>} +zZe0lZMlZmozbyZ?qh&UggbtA7jK-D*vFSk4m<;ylQq@aV=uI~F7-N{KQawwX;qVVW?#oAV? +zg=ayjp1qmZg>I?p{VcSLZ??!eqY#H(h1d{llkNlPC(cp*o4coodHZp0$9Xuo_bZ~w +zEt0FJ_&&V_LPAdo1%79J$Lz7Zm+oyDcW1wvjgv?J46?Td!c?k)hm1ImZRXZAH9bkO +zrzRGpM-F$E8NsPWGP}Qh-}849Cd9z*TrRtE*VG_xnbVbEc#7=>FNUA)Dm`TL-joUz8VLwT;{~7xHQI-c2Rdi9)q}g=qu=MfEs(cbG&M& +z>SV*3ab2rwQNhuY_AgI+5j~5C~T6;&W;05g#`|55) +z`@0T*SbW`JuKsO9rdkCrqcjpqTvpeok1!TNlNHfEHMhybLJQS<3W4rZ(m%uOciZN8 +zP<1<%_6r4a^}ayESG2EPg3Pf6fVY)SlnOt|Gz!{$e)jy&~#NO0~Af*lRRbXA(K4EvVCifDav+1~O+ab9ZL1)Z5Y>kpvkt|1Lw +znZS>a7MznHindw8wf5w&awvL~QeMS;7gsVdQ&Tw!0o6WJkqs +zN_j)={qnD~HrhqBDja`dmPthhK2fE~!t96PrM$BQc?|Vg+6Mmi|u&&>M_Pfzj_uN3pV*MsZ2xRa@jBie5Jk0ur +zxl_QB#@Vk3J-i>dBwS%UjoA;`$+-)TJ~5TZ|2kS^&Oozybd}ID>(Uk|nHP{i^Kp#Q +z6l(5=Vp|yxiAW2@?8bN*uz$C2-3we>DrfwI%ze9`^cK`6&;qKd=QRpOiFW6Twtj~>zjEw +za}T4_+-MubNyTUS@(=XXGgWg;{z&ROedD*>P%c1)1P@E;pj*_oiP@p@p +z)%~Tu;lp3h$re~=`MD(Lap-!_@VB)h9Q|sjnJBpgsW@-q7;Bar^IWfg{aYL{y%gcfuO}xRDfBjwp2c=)!tlc~Gy)YR!$MmexSL +zoYnvQ;o?bApk(XwIY@VMpF};MIapzj7nGo!miEFrFJ;FnjORznoKdbTtPjvuY4rYi +zfrQ8Yh3Eq+_rb?GkFbwM!pUGQWcaG*;rc=kzc?E`y2q%x^fz6awTvw>UPI^EUz^?_Xg +zS2}XJ0TRcZ`>Y(47IvTFySqWsc={z?GvZqCYfslVIie^lfA9<0@NENI&9! +zyLgEY9>MdFb>Ln&h;l9cA(G|;s(o+%g2K%&#y9&YF6SfS_K5tYBp7~~aN#BxzGQ1> +zueM*NHh>kK<*MRLrseY4)Hc`(M=B!6J++*O=Xxt*|5;lhQSj0)NgY*<6)ewHdc3g{ +zgX-yR5FKHUyqd`4eFX&K{LXE^+fRYVNF{<*o^rXo;aV1V_AJYnQmo=)^+Tf3qY_qW +zL7xN#^`J-yYASosbic6_(ZZc@q2|2oa;zR+>xqb)_Y7fuql)UQC+CynZ&u~2t=G{2Wrr`E{g6#q} +ztwICboRL$fY)&)E06ZG8j<@Kk88%!dJ^>H7tuOmm*Iy1=ZzSbqtm6kPMxquB+vyK}w~3 +zB- +zaL-si5a}lwF!Y$>@J%N>mN4wj +z_X*EXge%nOF4WM#?$_s9$Esd{ijwKadCt8y4Z)z4Gnj_1fOGy?U01!VgyI*6?4k?zIE}KT#W_z)ouN|-C*>`teYIY4`H6G> +z*SP@RpGVFq;i!L)zO^T^)QJ-)_B>v*qug;nKZC`WMD6M5)zg{8HR+&n512c^IWBgP +z{Bx}N^9qWpa-eXsvn{cu!vwFzXTL#{hvi)1(pH^$iWMB~(Mdb|a|C?;ZgEX$in1!) +ztIUbor{f0Ru~TObLK?My$m6mhdT)oNy8)ba=&uFmvZtZEx09DB&kdpCD1CJBCNN-e +z&pGUlh?0wZUo*sFY4(CW3a@d +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 +zgADGj;J~FjOZ9oXaf>bs3^U +zVvrH`oAn2w_@4PLC*Aus)3ifl((E#q) +zSUZpE&amrME03H*nwycEmavt|gr8QpuL5D8v(yobo`4pKKgIKY%PEvBpG>8>f149| +zJqY@6Q9qibq4%5n{aP8n<_J-!TWLF%p4Y<36a +zETOI_In0`C{SZ%JNxge&x^A}6jNQll@zG)` +z*Mq2t>gVW0F8l4<7eMAXb|H4XY%b*UYrTJu7{iK0(r2{qDX4#%x86^7<+4L_p_Sn^1v(jxX49so`shY +zZ#QkPy?7Al +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 +z_a{4_=D-3R+MY1if^(@ndo>hu`xy$T6) +zdT;hG%#Xic=yP0*a`Ye_lY@%oMRqe7bj*FrAmf8gT+*snUHK&p$grGMv+CsfXlnTj +zQ7aJB?CaWpJ7fecHUuEJfzvjBgws&j3u5o`L5o?1>L7mlZk=CFTntvoy +zpigtMSBTNizPjJ&aDe;fH_TKaXXR6Th(y)?XJ45hJt+bC0>Psoa}V7$Z&Z`{Oy3V< +zsj6{=kN91?ut1^vclEHrcfK2kSxtuhLf~4Zpx9BD+jL?*_-Gex(7-m?2^rf*|9Jyn +zph$g0e}-5JguZHA|6Glq5!2&>=MXAjHme=r@$C?)^P(?4tSFeO66uS!IJ7!@uUFC| +zOSBpELED?14`_^|!@1W@7|Qs~S0b#L_2d4ZS%neGbeJva|n +zXWt%3{O5ZDI6JB>e!_KZb$|fm +z49I@!&?xK&TypHZ&-NF9XF>?pGXXqtx_7n>R1cKhzRTCr?oVb-ziShxix>Y0QM`eYa>F`uaRDO=>7Ab)&FR)!rZxMVgWc26lg1E#!qW4EYfGzdFmGnVBJQ5&dOo?l`j(G97&n?1BBd +z&M(B};5@mdxTuoWFV;0S#WmDG^xoK-%@osCk6=dOYYANwiUM!%~v +z`uHNuxj7J8@yMN-h^$?Vp_xU$3X63mxK?ZCa8?+Cz!B-Xb3qgF^e5AOP~Cf_l?={I +zf1~9^k?xCfNdC;)3H|QjVXbPtCYo?_&v_UZ*0dinIvWxl9ZQ)It$y~%R3swR+qnFPkB{qyNO6?k5h(i#6bkVe02MWrtu +zJHZn49-_E@^?Tyyq$JV8&(m^`n?+p4zE07dou2|&ou+#%;j}xuUEEV=k0OcDIWK_v +z>Tx$cE4lp8UD)5NRMs$(!(_Y#4|*XkK(L+29P@mz>K$UP1cHH<&jDO^E*IXFPgmVk;fabL%n^PuUupA>afRk?+Z%@ +z+l>|?DK4H%Hy*XKMzJn_#C)WY+?o*;9*{f*O@F^j(ZvivYRpO=q7$E&>@A({42;3- +zUU(Rm4;Og#T#{&&xOw{MMGvNdK8{qLZQI{#}n6zY-4_#>y~)O6P8U@2zGf +z*(#3`dt-xI_(P1d7y$?+F!(?%-G?TZlDc|WJ@8TbGn=!_?_d^G(joLV +z9^J#6;#mfb{(dT!b77_^e8TTP*Xm~+-=a%1d9}a-;3c9@wvO9UE$ncbbw1X6gYGoX +ztuv*lpE&6ymbNo#JOGcg1g<@Jn|`FRKwYSkmPaM87pQQ5cNTI`|DGz13(4HmwqK>^ +zCOB@8AG#+j-^3YWi|Y`yvhC +z+lWWo?&uv-Gh_FRzxzlDa#&R3@Jv6xcELrw#ZKmeaU#^>)$ +z-t(X!re3At9MXUF=wIvgAL?qdzVA})t$5*A(bI`qW*0knGJ|!ry$IOtMa&_zvsf=k +zsXsDF)(3cZeoaxqkB~$Jt@o +zbiR3OOv9<(tw&N|-%siMUO3oIT~t>%HRhYpt_t&_lZ-&95x?G7`FABQvP@O5VxYn; +z+ltd}J$ghh_gs@T9TzxoErxo;qMUnq@Oq&f1J%~N$=hXeg`zKl +z`*k;%bJR?0&RSQ~r-usakOfY0){fjG4|!nvHK?2T5Nhc4nsW@myYYyOqgqr~@d>xE +zJNGD>os&}CIlSZY0I&4l{V{YMtT%JeUX_#}Fxm$yB~- +zu^xm^*`?rJ({pep8;-{PIr07<>Vq@wmGK$loEM*_n2)LA`)(%H3IH8x79Wx1PX;(k +z$PUz8ejh^*fm~@;P7B%mx*2dA{87B_d4F?`0zY(Q`_XBNnF}{;>)VKc`NfinmXq;T$7&#p5AhBazY+BMN9a +z_PKzpKFE0(ZSZ2}OF%-DYI&Qi2jW=#iT=d{Gf|fBr0^*jyL3Ab3p*>u8bCmBrytvQ +z282hc@#;(E{Fq~(ZqGit?}+x{GbB5%Kat1p8swRcE1$Uvf@oJ%q{++D(*k#eU)D}L +z8~%a}2@mt5yK;~6=YSQ%U$yCzBF?#-=kYdtfA@Vfh96sgNkRtvc%A$HbW=iNNcn!o +zEP9k&{+<-*i@tXQL^&W1!rYayU~HMYsC^8o^P%ahiBZ|Dm0Q}#2H9gTlvsoZo)ZH% +z^%BD+KEF<${0HUQ+;+r$ +zK{adQ@Fkq=bFj82##F0KE#-o1FS?s;Fl?mLdRotFc@*1ym!;a-Kx0!Il3sMvLjzv-0pngI +zU9zT-mh;b;9~U0#foA8)DEwPMM}cx=?>f?)lx^`rzwI7XZv4<5@Q?)v>Xp0xPynC% +zDf^HbX8NK+shq-joM@sq`}9xIc==r!6@tT4VS)@?_l(wN#EFw;#}5ezEh@G6yA%E5 +zZ$xB)fv-myCEssGFVBv?3|h>Ta;y%N`Js9s-yVvS__~p)#HI!>O>vO#cD~b+Eph!u +zod2TRJO~m%Noe&U7Q17BpG0Ez#hr5+z|X^b;CnU6PwMq#$qeri@^`V_Eakz4gC+t4 +zg+FJ*<##Q$Ntkl3+1rv-fVzF|yH1a(RBbQd>_1 +z>sH{WRJ#b*1*Ym9SXp?i{N=1^iR2`58(1m3B^4uEKt`Ncf7`LB>LWEm(%0-d=;xHe +zOA!xdhEP0KgGbz{TDbIu-kwLI89-|&)jQ^&9^a^cuHtZ^q|` +zYtO>wIY_Xa55Cr0Jju?>keD6KEY*MFXRc{XMKQM9Ej_tI&=R|CFFTl1GJGBQQI&DL +z*f~+=;$!cTlo5G`!J$p&z7=q3x$_?+gns4}Q;5?VyeNeo&|AYA)fQ=FT36}oDv&Hd +zoov}9VM``0=-S8^H6KG{TjW`IpFxqMUk~vL+m+QEF-T5n4w$fGJU7Oxx%Rk&sRaTg +z(*s2kd-43Og$8HVBh%U~p@atjL%@Oaj5uNzdj~?=3IF%~|j=wtKO1a7q*T0Hf*Qlo5M@ZyRSfk&@If}i2Vz3Oumu~kQ}Xn}q#;67du +z9@H@SV3NyKLFP6?725A!KP$#?@t&Y#Z}ahm_Q=57Zj6)fa^x}7`JHioSCIwD_Ff-N=$CTzlqwSq +zgUB2M^=zLAg4DQ5Lw6q(|HB +zR!m$rVQ$X_`|JRR39f$qmj~vU5wlZ%<1Z5Da(QrZ$~xu=biTLCR0%bQKl$a#$A4=y +zQk2y3VS>UF6Y=-t!uAd=?Q&2e9&7OO=`sIb?ySfhpi|(SH9Z=SaPbS3;?L%UQ4KaGZSz@^E?Xnm@GGes1HX(zlfl +zdso`p(#y*@)SYC=j(vI0`JkHHa`fm%^uyr1UGFGgHJ)H-@^`(7GXlHx=-f+UR{wOL +zE#bd#f^Cr?5RPEt`*5pywnv;ZFEYvE?d_sgc>!IR4Iib62oSm>xir0(_TX8bnLWBe +zXZdHpul%lUi8Ho^ +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 +zbN;(q^*9Ra>)AY(h&bTYCnxc*Q*-$ +z)uI^TcmU(=--kL&pOJ!b +z9^_HL()O{mS?LQ0!_xVh8{Z4!4lX8LbP@2IHpeQ^!k_Q{x0_4|SC%04Js-O&nYa{+ +z4)Dk!DRGV|xqz04?8E6!qI8J+ve2#MBs?&C7F7n(4<;GB{Sl8h3CaMl8#lBb!V@6dgc+bddC&up9h5Hy4 +zHCiURr>p<1r!V1A4^`FWCag1aSOn)>MYTYnqiR@X_pnckywc`Co~(Y8VK1jQ5`9+h +zk0;_Q!JJLMx?BBspUgeDUVLLg2}ceNQ67g{naCQ^o7-}_=DoO^MF%$3@BwjHDI663 +z1Z_XL`@HkPAFj`A3i3WKXLtkC_0F5p1WzsUq}{|*M2OsY9FDEV`p@A +zdJN;U{FmDiI38;Ha=1w}B?JHk(k<|XhjdKuXJM0D-q%0PoW3Uq14zzXMY?8%7g`SO +zsqZJhT!q)K3Lt7of?J-K2X>S`R0M^=wpIPX4FAhHl@#(&D +ze1JFT^Ctj)!SOlZ&Y>fIrp@_Ac*g0$PHx@nJdD$hP0esWahY9xxJIo`O(lSQeh~3e +zmx={?AE!0LIR_z-sN1Vxapg4c89c?OmpKfsEHqd=j$`vygQLg96kY-;lwvmVSl5RD +zwQ!^N@4j3X%>fMXMYm4sjkV;-9XEeOFCL`~rV8Msi7karKMlr@Qaww)~W`8 +zSb@(e`gahC>*_Bu?R$YR7POpoU#`0>;PTi8j0?LImAlyH!IDi~?!HO)r0qS&0aVAv +z!{Sc1;^Y2jY~6J>`4P^1brWO-^l#SNq&3+ryqNRAXuv=Vy>t?xs)(g(2avn6lX&Po +zx1RlcA0kfWnMb}o%wPj(fW7 +z?yGS^X)TKfZKULd=#j0okyKcguUB(3tB+i1DoD6=Ea+g!IYj-pNZU={~Qn +z+SrXpE$(+u9O0uEK6${0=fqEpN?HO3hTe%IdH3GgQn6~kq4hQ6{+f@C-yK4=H%p99 +z=-BmA16g{H?nRC51XaX)E?4eZe?b0i&1;AEb0!$gPgj0tjxf-9w0WJx1$MdRA;7SZ +ztUKr2b711mCxot4ReDl4U1m{gKUul!L%>NMq9C!PhaTcpoLjIe)nM74C~@3J`jFWY +z89kOL_sU91?%yY#;L^7I6&?m0m +zQkIADT!2$QrM#cYLh&D}@+*$~58TA4E1N4(FAKD>lR}3KR`MyoQ4(2SpIIDspR~hz +z_A+32@!Jgr1qR;@;=kSvy%*!tfljzg<#}Tb6ED8)Mip=U{pCH2 +zAUcH~OF5Vb(xnL$m4>S;t~M?y!V%cV=bnze{(;~~)6bU{`{k;9%LM)4C*HC|8l>F6 +z^)-4J>d39HJ%|UC@fyB0vR0G_(LPaE&s>OmMBFUloKtd8pd9CDOB1u!m26h}hi6uP +z-j&Diz9rh17~))UxxAxSue(ZBE|J41eZeyI39lq7t3Oe1{# +zFhm~$$wWn&Vg|9P2&Bh`x|o#sRZ-!;^(YFNnHWIAK05%>LAY{it%?DtnU%Pi*P|mU +z1c@HSF};`E8OViBEG^%}C;VS{27j{wnWGe2dS?Q>vMdax>e)E`y(8{tCa +zlzy|nI$NE#=bs#$0U%1G*tT~km1&!S9ciiVR*Ol^;#HnN8F;i%xX+zLETLcBeet_D +zifJQ~u0!s^0w7r=@i*;=3pj_9xiB38jWizbk$^sM4-#zo0g2BY$%9j}Lt;7&dx`KR +zra)!lb%`Mx^WgJ!_ZYo=?R_5l%G=w0h>AUvK#JmV*l}?c%F3=0_v))%{i--TfH_KZ +z;}g43N0RTbxgyg`{Q@9AE${EQ6H +zZFaQY=OgBcHQMAQJa-|5KB)-*b>9&3AMV~!{F22h0-fu7oX+){Vlul2%b0s<3k@E( +znAW-XJl=UZZh6un=sq>q7m_w9a!$&FO{g-2k@NKhq6x`a8f1UOO79HNQlB}=B|Hjy +zlI>&J7I<1T~1oj*%2aK8YM8>C|(inHeBC^3JWF*7v`4 +zb#Ya=%(_q>oHq-@RGu3vbGS+KbdI)NtphM8W(xxWf;BKF6GCda@;jdh$S`GcJu)Js +z_iV6Uo40m6)!(%IsvKrSw{*Ob)9;B}E(upVi58&v6;?abjdbYh2Kv@*ZNXl(&3$=y +z;)?Ay*WEx^)W~aIXO?~N*j)ZBpZ`2HB$S44RqMFtLyfBNUT|dy@>vBRl+J5R7W&HM +z&CiEjL>00k3$M!Y4-DP2=}~JVc<;}Z`Q5Qades{}HS!ammdI$@#Z? +z<=^v0GvUG|tPn}mHk8I~+y|u3K8Rjkd`Zv!Y~eN!kcZ=Ljkfp6qed>Jf$h8Ubv;_o +zCw3FIIMIYkP~ZJzjm&zG+-o@7daFT|I7^Fg4~65I4H$foXKr~UIui8v9gfKS?eY&x +zmX+f|BB@GfMpQPuaHuZD)#H^LDiv{k^L_&zcpoN&Pjlq4tt<=|B3})gef&!1{^TjY +zd%RRI_15Xn;=@|K6%f^A6@s@!v##7eAa;oN@q9BU0mU1aY%PQJoUBKuCEm`~kXieJoo#F-9bYS^IH}uAbh2vbc#r+Ph|TISWhRv{Y~tiRPHp*=)Td +z(-oSXTyWA4*Dc=28}7YbmvSYnDSScfQ% +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 +zy>9jXTVGWS=2cI_j%7c(2C0|Wy( +zCjOnz|6a!54WXM1>!%C7P7+h&Tbu5IGMAHlV)C1gjlQkZ#}ng92V~bZ&AqYtIm6#m +z!h3CwZdvbRLLCo(G~#E;UmK_4EWu~>d!!-D@e|iB{1kEY-gEsk8kyF_-7&rb{37aA +ztAO_wB;BZD&t2->SZ%dtobtV6<9hlcTxYne=#OfCV7F7=X1(!=on8H=ufYKmDY(bS +zR&_q>{y&Aa0*OtidpO&O^I<7D1)s?BrKvGBiu<6ovKMZQnPc2TOKG#PDD(|;4$Z4E=9sTET*tyjvZ`n|Q1#Q?D-()ZC4!HrXON?z5% +zM7$!$;E^(J`ExOs_XrgZO}OQ;_Jc}s7h1DoUq(B!3@?J^GM}6l&d|N5<2$(3?#r69 +z*D;zEjt0IQ;=c*U?@rZjdu5jcDJ@HKjuPajY?lxFS19_9yVcBq_I~Od?-znBSJI2`mIShcLO#rf +z_a-VW!fK%Q=4V{{b2)!Ew|?pkta$GwgChRu#9)4&Y81@5DI4In#d%^Yv`YF^=7n|j +zb|Ia^z&98kC;A#vv*q4;ObbJ-gw8%R#W;58^a0v5@Z&}^@@Ru-a6XcCK6jt;`25Os +zI~9TZp$C7g*6S`>K*%9CE8Q1U`6iWqlVxs`*h18{@)#h@0zTL)_K> +zF?JP +z`}3r96zw5PULx7E%I0@pENvZEBPqvRVo&Bw47G16;9al#Gz$oo7bYq_h8HTbxf%1b +zSmOMyhn*BYv?V7AYBTs{Ngadr+vl=5IMkjt$kU4>24-DviJd(InvI%`Kg^4Sn1b4; +zDeV$ZGERHs&8*Sj$Px8&jd^%TJXUqyE(UoYv-Tbn;bN_v2grGK<5sNN-Wg$e^pJGt +z&Sb_0g3R0f*)Vfs^t}J_#O1qwI->XNfOtlf_+M%KSdLkbGk#9Bvt +zpI{PIR7z?MSj++LR@}a4LJAw=s(Govchz8I-DZ>&O(TFhs+_ebXm&0d_&3mfonJ}@ +z=ZQlwknUu`-?$(~VOaJ*d)oJQ7$nLjkE{;&&eel9GvM6!>4%!l(I-AOTsNGNtHgBQ(x7+OG94j86!n4 +z52sv~3QQdK=nP|V;VWT>L3B$)4afz(uV3rKI-1ai(kIu(4w7c15*|9Z9dVoS=)LP^ +zowB`f`Gw+k1-z +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 +z5LC;73)wsmG9}SXXj1n8O?Jq+bt +zffh-qzqTeS8lbdg6X~bkcE+0^c91z7 +zU5?SCD?Dq%_o67n#A4N*M+~zYNdGyA3l(O&n!o&f30w}@swh6XNaxOO?^|WMsDm9U +zex3xs=0xv(aq=smsmCYbZX#P0ZyNSf<91Y|WUsQo(cS&Kk4ROe^Q>4-F!uKNlDxi8&MKG7X +z$%6cZz2*b#_*#BoR$s^)hd*ANKpY_Q%|N{C=-DpzZ_?{iXTedAu0hu13$8wp;1+ER +z(4GQME)>PNu~MphPTLuZFuT`HigH5sihsvlFGo9?ST!#nxlgdD+b&$Z&i5PplfBaq +z;*%T_wCOW@{?2WmGRtikvm4NzqW(meR`ryS-G`}{FM6NzQfeb{=ux}~_|~~z44>tN +zxHfh#cLv)?C6>*fcVI?)@5OUw=z#+4uMqU9ZR3ufg$`{OjQ~e|>*lvk4Yk(kOm4J9FFk +zI4x5$$fNw{Ngpnz5HU%%c@*$?u%-(Vo#}Bq*FT;@=UCYBj@v2<5-(Kp&grLm6Q)sO +z<@8~gua1eG`=UrdwyyBW|8K_Gqh5i=m*Hs#9J|N++V*CD#?*f{pB-X5?EmWgpdh`K +zzA^o=9hcB7OA$y9{JN +zW2NrCcRKU4R0F$v5znP?!tU<68b=dSU)t3r4fh7MubK8Ub8hqxg6p`3Vs7Na)jAlk +zb=7oR;b?2f(F>0^e~zc>NBkkoBifn$G<2ommQqCBm+s!~U(BYfy7G8=e#Nkh4T +z=a%e*-c;a|h*F9O?o*GN#T87Wl-TYI;CStG4A*^JW;nohv@I{wBN%5gLo{0%ak2U7!&#CMe9EqUnZc%IE9KH{(YHOGl4i0J +z;s_`LrGBcq=dOMB^5tKrjz({~-Wi0K5%=pG`P2T`OrM|- +z#;8^7D%<8mG~Bo14yj0_o7Rd<48Qe(LB_^y40B*)I3h?h;tzBk46PLPx1Rr9z@G<- +zpLQGSif(D;Ueks+Y%ofPC_J?RDxIg!i_NQmN=P}%hb_63ED1HHVcz*-gr)qdC!YO-oNX^16+xf1Oh>%ILuB^6o1|3&o3MjnuzC5OvE>Y)+QY+?E94-QQOpdOk1N)CFl9yh?tM8_dpJs*?uy1eIC1>IM!z`t +z=_5eDn*?&Q@1C%`^&S(O+`R{{EBpGmU( +z4hGV%(zUp3FROJ)woLKWJa5wsC$i>{gdV(eK%kDo{#_5J`a~S0pCz2nA>9h;GYw-q +z3;EE-zoy3~K{Q}Yif=lBJT~0NTM@2F(C&4OD@tkiLH5sU+55Y#fTMyXfZ~wa%`QUo +z{ziwZzrDxbh}+M1%CQroBkm$dGoURVT2U+F19Q$?cpSxbq^&q(t;ko(SGiw~Dz +zD3Kk_;8DRU(QBiR^O|A+Pe8E0x!qQz@=VHebkbbt7!yD|gb(5Bxz3NFU8#GG?QyxP +zeEU}l^K#9)P!plw&T$3Fx8D)>q}HwG064W%$Y(Q-jUv|PP?hIF@v*!sdoA2jZc>46 +zJ=OKSSijF0sorD1qW@RJw@M>Kq`MnPD{wH2kbfLm|j_qgFkCN7>A +z8b&~KuNq(Q`&m}=r31qSFTFU`?DFlm8hM3~+6kf)w2rcS5+?&M_`KMwVE@LiE8^FC +zyPpSz4}OQuvwg&bi%xP;^Es4naUj2*2H42%fVbP3z9MObC-Wg+hJkVc(}%aR(VWy| +zpW{$e2&84 +z*Vfd@G>knyU%XjB1*^8z2M|fdu|=$+md7xx1)WOKWlFt-!B5p{N}`7OP~XEXC%^;das>ELMPnhZ7EX0 +zVHmcKD}9!S$Mmx69xkJUx)1~xf0t$6-|Z3J{!L)6=96zDvEnu~n4KXYhu%~J_tP=j +z-=KLpZ=v1It1}T!>#wf2oicrO?hwJ +z5v)!d#+SibYwRK;e0#f&E%?3IY6QGv94|}ysJx#by@u1cm$ds(;?#kQv9;b)T{Ncp +zB*WgvefvN#G7|JTjzDgx|@_=npwAU3lwSYn}Slh`S2vSv$CC4r;(Fbf_W0 +z=`7cKpX`jE=ZW`sLj}J*Yo<@U`@a4CxshoTtE!6#jD$TDX}58Lrzx7_hS4{*?Q49e +z+YAv#yFLi4q5?v${qVWQN~xr@V#40z3nf| +z=inhft(H|t$zLBj;*`9wb}eTdyWMCp>)?^`kTM-8(Kfe;QWdD$UGQ+6gY>t5^{nJs +ze1d+mE{n0*2x_Bsvv{zDJw+_KHqdD%@$4#Tu#zD189U^~+#7`>8 +zDzo2>HbH7!b5DD$X^4F;7a#NJJ^*tm=b{JTCcT{bRSGtYdb`Ls@ky~7y*}IWJdR%r +znil7w!}v12*kqBM)oNX0LrOfDz`3*>>YsBh +z;@xghXd>Rq1G3zXMSf-PeSuyXgP$uRKb||H>`R2Hl4BkpJjB7`YfoGT&39(h*GZP< +z2mdzOa%WY-(SFFp43AdKNCPp& +zykAq&@>sHp0N&a?PlIpS#@A-5=zPb9qae{yxNOyUlz!_A{*R01#l!fSp%H7D-uLmk +zRY#2+xv5n?Uycn-z8F|UOMUtr?ZaMsmDcbjKbD=jl +z8w$V~phsoo{j9dyihWGiWG^n*u=Bzc9wo)}rxB`z@WIs!uA$Gx?+JRKjE=+C8i9*0 +zMZrr-VM6%%&r-g>wS-TJPuL_OpFgjm-C8M$nO`^n+dh(VF1Pu{)Rj64?m>KK$>;{c +zx!CzY8phsca;s6l=d+o(y;}7+>C=lp!{T?F2hCw(Xw#O-V_HuT_YW^gTVnJh{Q#l!dXfKr?)z^`Rx +z^Q05L|ICBOK5Iq4rtv7L2x1(H;Vb1D*$>%S$i6l{I2iVXtDh8MX^2F{CZW$d{Rr)< +za6LK`d6X>uLLaG^zsJiv_gsg)^n%mG$#F9L2;3;O>Oy0hJHl +zQ-mXD!{zqd?=n@}|A8038$*h$<-2s$N@mQt;1|9b65z9xkn99n=kk$9paM|=9nk=q +z?Q@$Eda;Z;!&eJVzNb_lbK8PpfwdT2IXQcurtZ{B7p1V#qjIM?VipC2R +zJjw+3O2|T-oAKR_p|o?hpyp>P0g4Tn0-dm}^Odo(6%J(J_fIeM_!+xgtA7@+nmw*N +za3M!-BgKrh&bT0=y{A#5^UWjN99-lDRrCcYEIB$UuDqW;`q6H_Fg96V#kl_tj^BQB +zS8irUqjE8HwHu}IQ*Ou8ca7tWo-)vvId3MG)NXYYmb63XlM&)C9q1PT4{nvJ-QzRZX1>XHoJ3`hlL)_c(_)>YD!GimCy?W9kO~0|@ce~2BS0DO>vJ&om +z#Vp(d)y_QCUYoN*`05myQOt_AjtO?2iR}es|PKHixDYJ-J{n+?CH1#bE12Wgxz%!_D-1>iD!0 +zy`*Iq8gG_zf}}l>*WWJ`zPI^6tkiu1!H}Y8ApdS~K{#JUZk$@badDq!-pW*@UB9;a +zc}zpll6w^2j>pvB%9D=_x_TWcQ#O%$V%~0rF7{9H%D)?2B;lBz2ck=2qZiMfET~%k +zZ0C<%vMX8EPb-(_YWr8YbM49ZT%#A6_txETx&*Px)yEu3oRWvN$XhpK?SPTIJ=d#^(0PD{_{`VWf?F4uHwi!e}8A967~@vO+vbLHeAW;18L +zVV{9vEz{=#ysV^ON&B6N6G_W7-QX&9jsNzi{XDOT?NZ-m8`X-On<0XEH?oe>dzOuL +z#+hk_eGI83+;&9&H5E#nCt-_o`nD$={aruFzguF;`6;5S=Vsp=(lQI`IAAy(@45Q$ +zE&2w$eP;+&?fi|)W4~9P=nC{z2RbcN5x%0_2hSNN_8dbI5A}LlKdjBW$qGy5bT>>v +zjgKq4Uc&J>IWZtu-FhCtZ(q6Rc#e;FpT|#iTWetOfIKOj5V=DsdQTTS0X<#g*lIby0|VEg5}bL*S?^C%MN +z^+nhqUZ#M8>^OU%PaFt9kIZDq-&%%$x81PW_)Q1Ck%h;+S3E6)F5Q!=)y-(5CNSKy +zFBCnWc)E^PWk@lmP;IA#v`h9 +z*>XxTVaUrD>);`^oya>Xe;4gbQrU?hw=z2(TX)g0H*4_jJ&uV?P$(K|q}0gtO&IK| +zyI(0QqqETV#UR?o%Ey=Z_fTX0k47DH_R#rk{!CvAw?iZszDlM+Cs)Nq=+vUa3Xei- +zF>7H+f4;lcj4-p*b^VCroWb){k3sb03T0kAlnmy&0l>&IeNVDDtlBaf^CLe;EbeDB +zRD&Ium!&myv_9X##mzJ0kowY(>A`U!J?uu?pmI;l{iflT5&~`1i8*KEtd;u1gEE{* +zyc*rfGALyC>UazI$bl570eh(`VscLh)f4BZwcpBYL+o5hddP8ZC{9d%Q&0N#J|!nT +z`-sJNrjo>J52PM|yF#A7?`T7E`C8=hU4fQ(*uNpTU7qYnYL}Ee_AzZmqG{5bwF&`8 +z4~pw8>=T5DZSCK#W(ee;E&2Q(tv!i>bocUi9l|DL&T;uPnFonSqEzvLCZ$|$OzgE-uH{A+%@Z9S1S@W;>zALln>M-o^{9EOGCXU3y +zpLJgu+Fw6{_`PLy^iU$9*#QA*VCXOeJU6mvu6!f6`QY$vn#Y2Ks#-!G14gN7!H-hO +zemDEd?`ELJn-jfoBC)yau31{K2$$fzt+7Us<^}iBP{^8!jy*a4?4Dp5za?UQ-rga? +zWfEzFRXYCk=@shkd!V|9m0?Er{nvvN0^wCHCBXGHL796=$sO +z1czO%J_J#6u0`^NyHy!JJq>YE8jxq8h!^rHI&$+|LiDUUzlU7GBm&=Nj+I}L4*CavGvsrO?ISHifL-wBBGBn18pjBv%|Uh +z&;Aj%3UPcI89VP|8qLvCU1R*FTqD6@Bh^5!J{wehW{NF|w01!2IPAF&(d?uC&0<_1 +z`Pn}r|B=n{-E(J&$5TZDc;{q{?tGEwJ%mR`BF}f6M@_`5w040I?i7g-;Jsk8r~A(J +zJe&imh?ILnFJ#>D8Z5S_A-)l3wU6AJjlU$*l}sZP`kISup46bx`(?{c-G75?5mtPY +zGd%&A(9VM$-Dd^fqPcgOL42MId}8KS4x?T7w{+@G0G2NRSt1;FGwz%sbk78dF6VKP +zKp{Hl^&Qwu!^j>y=WBgmhHlZ~!_aO`no7fXc3^`Q2oJOt)K%9reZJn1Ndky-E(q&; +zt3es|XR`q(8GC}`?dSRvP3{+sYsJW=a{9cNbxwlND1x{3Sq_KsuE750@! +zwSA|nZGJBp`#lHQ97oPTv!Edzgs)PcB*_CPZfYo@<~d)W@v}6&;e3lf3mlc1-vP;> +z7%$P=eWk~ZbpjdXWM9&xhCNA^oGrOt>R4h1_ZT8j&_rfTkBs7%*f%#UPwjE7{bKRe +zk~eI1N$R^8$~8mIJ!}EkZ_7Qtz<;xM9&OTBmKZvTt+wZ@c}#woq{b1E@dbgz?QQJ6 +z8z_QEjH5@U&zP>8(l;L~@B51}jFb6ie)ae+)JPJ@3 +zk3IBZa>E?Tr)#k_5Us^a=jLUnu)B7jad@)**w?P&(WrdkK`qNUA%$jC)HkZ^&c%D~ +z)p;9gJPDAGWlieE?9p?uC`1%&Wa_EtQ{5F| +zJhg}PP!+f%$u|M^Pb013R|Rla4QGqWTU=4StSV-n;B9}P9ycVX1@WsJ?|)~H7OZ<} +zVj*ry>N#(pv@BNVZ({o0)T9s$xjF0SJQ|E>J$q9hj;o?;@nkcdd#!fr=`8oC$}0%> +zX@y;sTaZVI?zOiH^SxxR?e>n<=mSh--Co?thzvv_b&g~s?miDouB4Ueg5G;*>k2=Xk}tyS7|^|q=U*MuRi>q)yrO3qfG)-bJr@a? +zG2`1cv^gHz@qA${#wh9`>%U{;j7&2uXwvL`i{t}$gz>FdG0|@xIMp!rQ+bpvUvlA4 +z6UXR4eRroAnr(eV;8Y|d|89Gb-)&IJBzKs7IoB@pswVPsU#+~^Uih`ei{67RX~++R +zPF|^d#iU}-uw$~x@c<0sKIb;mb@3-q-v2|(H6Qu}vS@YG9k8Z7-?8W%fD6#~WPj%| +z%VxcHgIQs|+6K62XP6Bf!0mqHCk=|JwJ*ohGaHHy%Kpt&OL~Z0MrwA}?0kPD7J5MO +z+#sGjrG}<+CO~H`ZDx;lnE;%k_w5%$AZKnoP4*NPsw@%St8c%!5r1K7adDpXzD7Yl +zLxq{q~m#q9~*s +zObFiJ@kJf&bIY-kc{o`CPJiXa8Q;0<&qC9Bn$G{T*y^6m+oB2(~26C#?Ryr?hU?C)aSeUN@lk&SN--$EoZo6 +z;bY7C)w}FXql&2Yn9Yl5xwWgqoU_+SC%elW?HYONpCigS%Con96}17y&A~GGZS42r +zR?G0vDk602c78L!XKqCuz_8R~LB?}0**6ETx4Gvzz59FV*zb{va&wiSc#T|41h<06sQ@6;?vo+%5V_*yVrw-pg+A2WWLuPZsL{C2;x<1C>;7)e%8SJ7 +zMdR3Q0H6#F59A)qG8kgZd&t5!TsbSznwT%2jF4(^pjhJ;o01Gv0&JOreVe>Nz$=rs +zX?Gp4b1pVH$A&O?cTUQpg{cwN +zrh?0N5&jL?JzvRj#(A6E^K>10;MCzlrG7*&?tH^NzxJPCl97{qI8+bqjYFcOjG{qY +zZAT7$V~_*$(6MuCb}*YpVYg6%aI_vgAN1A*V7kY-5zW7AH`gq+2%)$6&)4eSYlSm^ +zUQ2qZdb{Cz>eC9lb}i>^PTlZcJv|~|h=*VCm&2t{<%*#TL=o3rA++h#2@D +z{!LrI+qvpHJWH?hCH1M}zKvvKnQ~0vp8G!^lT#F5D5)Jn>IWIPLA1|$KUqV<_Rz~> +zZrRk`C^{^4=RpeIjkAKqc<;tHVd&^Fu|54IxkE9y>0W*)z^1Y6)l%e+H6}K3;;W{< +zaV3Zu*{?W}D@7fCX2yra@j`0#bn)5agAk5>P)(i*c)nsFiTwd)*Y15TS|CZaFSv;N +zp$0dujtc;GJRNW3HNV&Cf#5;+q&jD{O9UWL(vBD(7(%Yc=LG;+{M0PX?Y2|yv_=Fg +zbsKXypWXor3<&LW7zRhvsjeb$>U2F}u(1Mse1J9Q}Sb&X)$LH2fAsj-!-W;O@wAPe=eU(%_qC +z4}@1zJqQjTD!Cj-9|F~lMt{qLfbIjR9SqyLZ>QHmlX7KWk;cbY# +zcD^WJcPl!02`?YF!HsRgjLa`R*|{9etnPWb+}q*P7G%@*bvE7hd+=!X)Hmry5qJ@@}yep8{2wjo0W0fxk>R2^Ded4QZI +z5Ngg;x^%ZlL2lQcj86ZG(KR>xdO^g`CG@*xZ01Xi?+xy_2NkyA>e0RaKGGWP1$|iIz8i)`sl6# +z$37KngGav^7IR0I7|BC|5ec`kFVU@|=dE^9Fj!zLMPmG{SBgL-$AP%rdBf&Q9XyE- +zPzXx?jahsiO_QCozry>FXFB6;JVJ5EJ;iXp$wDo*4mVE2pT=Erq#IPEo=rRt#bWyI +zKYzlzM(gWSgEVkdYV>r;??v=`kk#d-;i$)6jMi6n +z>SRfOCkNdu249fNP(tss#s06f5pGYcoW2>4+it~osJteJo*1|4IZ0mS9Krkr+v=RK +zp_TA22=WQ;#%t!AU#mJez2&%K`$ID$!tmQq=QI`(X@jHo4+|+e2y;4I}ojpBe@VB10$mtf<0!HAXmGObk#HpdYeOsc +z3)HNfnd2HoH6-x)B&xJ@3Q-fRFNScqqQXsOtYM^&1Dmqv* +z({7GF*h0-5QQPI`A(=br!hACit^yv1(fd_LpS!RITo$}XQ74K=dwfsrQf7(7qanQo +z4aejHow(Hq(Z~L7dOZk}g(CNPi=z{JA!LUJ4UweeON|-YJs5i$I49EMJfpUI=?t~1 +z+Irju0xpbNy5d3gb0PglUeR$kmw#P8j9lMk?Me+nxJ#z`nR6jwNJA3a`Rq8LVsO;i +zdz<}OYc#1YH;8cMa>=1SxF2b#_g&5h1zqWhD%OMQpA2q&u1E+8hT86D7k3zXwk-$-Ty~@vFsJ!>+Tu-o~>%}alo*?T)1IJSD!vK +zLAuD0E6qunN$r>Ww4vPf{km(K9zhx-g#ErUz4{*#`^)z_=AL?j7Bcy +zTpo4AG=iV=Tr=Q3J1IuDijyMW{}~?-QKLa^ardQj_)Ln=64cu^k%hPQbasO4Jp`=f +z=H_eG$P)`E^x(-{< +zk8^P1xI@{kR4UH?0(p-Vl2zQBCj*RGh2c4K)86g~YO+}73Y*Mn<^DP6?f!0-`>Gx- +zdOXRX)OeoYPQ5f9aX|Jm0m0Qte3s6sSNi$8l{f>C`gJTCSnuI|Z|=Nrkwf2H$K25rZF*ovS<83;R +z3ZMB(@!+Z=lQ;y=F4TKs=#cOr9^>EPA0r|T!k#CH*h&59^Z6mC3(S*byX6ok)TZWb +zi^-Nt6}WMQN(v74_FeGERDtrVSI{g>20)EX;lT?Q%EhDgb!C=aP53gW?3C +z>+K*(&GPpt_%}BFZm)|$@udx-iw^KeBCEzKvs?Sv$h7xGAr_b7@_qUYPIxBaQW9Y0 +zHV4y}h{DxUZtPX}h);#XoKT-<0y7FUzbG!<;B)l`_Pr(w1LT)XQ?ec=jD3!M`Ux#` +zEQz0qu$LcP;dpGq4t$q_JpI9)-mj@;>uV&w!H-(G +z0GDWiOm+RJa*lm9M%*og1z#OY5O*E6I1BUVd6MThPRzP$4nNu_0yiRTiubDQV2snb +zqeoRDhPd&)L81Pp)?adv+P)zCq#U1QVSump_~(N9-H=CV<65#?r*AN9Xpe5qmcvrw +zDQ6gsWE46$$7ime-Y9iX05A8h?o_a?d79Enie%=b-LJ=Xy0{pU`|X|Qbv&}$zovO_ +z#LxDDu-}~T6`tBB#Pm?4<{X6y3UVY&f7-+ +zj{aa)yxKb#-*$wDfcgbfv8cMlf$KKTKetL8>akCii+_2~wW5wO$wkbY0|`!|LJ1Nra)fV|PNmyhqyD-!+P +z!beOzMVJU5QtwPbKl|-G2CEs~73i~|vN{Rx^`CeO{Ki+2-FP1zqX(LwZ{oy$^9t*U +z07H>yy5_mBtaJJxo80-Tr%1V|-~s$w^>C^V`c>a6fpYJb65i!1%70NUo6PJRH#YDF +zb)L7S@XW4|*VS4yz6N%#kcfHdGZ;#_Tf>C;);IeZz0`ix}$47wR!Gi?z9?A#X +zErK_&u4z*;&YsO&ulkoe{O3VI!IR=NIw39y+?)jg)|F)f{46wd+tg2W{vFwQ>OeEU8hhsvd%A$-r1nabihu6`ok<%Zi= +zX>sp2{V_#g#s!W*Z(hfV%9fTJgPg8#ujQa}nfFuK!4xBBk&w?NFEif0C+G|Jt*4n5 +z_Hcal=~;Pn4lXO{M&47Z6J%N6BU#4%H*2Vnc5)Qu%&g3^hZ`^Y)l&2@I$51>9s>A5$78Tg+1+WbjAV@mTS +zDD_u)cvb!6F`j$$PZ3j{Dbb_PADTNu1=ke`UymKAu2$Z|??*BhYS; +zjEU-MLD;REe0PvKZBBK2*JgZkJD>P~(6B*~HC)BhHokNDE&ZlGrwlQhe2svK@|^E{ +z%m)38naM=T$S6ua#>+p2Ar%tj&3>i42^06$8^OZo|a` +z=eRsvMhfK$h?2kO=TuDc+VSu&qK5IVR-)=Om%AQJ6O0sZIj-Nhq1)%}{JC(J2_aGL +z;q}(s(A_wAz +zDsCDURd_b#dxb8Tkl#K0kvPtijbL=m4DOE116$N>9ty?=DD$zc<)G)Qrt=vz5gTf` +z4|?DvwY^_pclv1R1)^un2|K<}>3@Bz6A_wESd<;eeC9a?Z}(-Gn36c!Alq93OOg~q +zcoLYHTryL$5PbllrB6+-;YgylzqUv;b;%WXR2 +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 +zK?(R}(&?E#{%evrTNqc-L4?F()X +z;JRb2^~;T9QeH59U-MW$OaY)LF;}h#U3m)hL;EkXntM^>oHOq!lzK@dBEEH~XTM0H +zJ6Kg((?Uvj%kGmOJ~cTv*TBx$-|@ar@JwvOob}RW9)np}=@hmL;W~@;HH_-%Ll1sj6aOx|*P;B`wm>#-eqU{h*pP{ZG +zv!i|KS%>CLI*&mFfb%5HxnLN!3s!ymB-q+$>i8Evh0|YR9X8-GIj7EA?#hktBG9k% +zIW&xFrP;CC6VUizZ1Fwx7KfqHN`HYO;;nk;YqL}}Wv3JMWWyh5T +z{T{`^@f)BhKHK9H?YG&u^Pk3rask)+3jZ<6sH(lz{xVZyL`Y=B9FX-_{(#RYmFlCC +zU(R9r=NRfNnk#Wmt@y>vjJ|ixNpjf^6?_?;NAB$td@dh=>v`!Z^xP&)V=Fv{T5lEb +zo(9j8pu$~haURlC(8F*rI9buXag+t0?hw+6`Z~uc?d!YNYYqb1AkCoh`Ac14(~maq +zlWaZ7)?md@0m{-mxa568qxB9fg?q4h3 +z+SvzcN^y@q{_>ufYQe{}8S!Jk +zM|HLAa9yLBfkm^aL9JKSF&=BZ2Q@*x0Q9P5ai5Xm@sU2Im-Xr3%w~fVMgFP@CW|+b +z;#&&@nQ3O|EckS?NI%(vtw&rQw9*`B)_Hu6dgjUdLx>K*>o>NsD6~xu^?~vO47pd&7d(E=#WW1WQZP-=tm)iBXTuVa-F7%S71OZY99FSqHa +z!x7pkCf4xE&{EL~_UqVA6{&CkGfZ9@55HjmsHCTc{Q)GnmzngJ_(PRJZN9vvF}QfD +z8g=EIsi3D?u)(?zui-e>nN3`Y?XvBB{w>cYS+by!*fYp+hC06)#?lxFk!G|={PkrUybn|@9)n+b_OzRc&CPwWbk +z*`7z@QajIy!}3bKbyrm_!(j)%guJVJDy>f+Bx(4XJqS!&G74D%CBb1f#%hWeG39+q +z_NX~gdhLO&+0~D}y#G6w`O>S+0<*vsYUklgq@f&kKixeA7JhAnr~QtN8mEF +zK6XDxc9BuKgsv$v;G>K0Eto}q?vvvo%ln|MMw^wtpo0)eh=oMRHjo7yki#MlZ70gk +zQMLNo46%?rT>!pL;TpfgpmQG#M6J6ErIG&K7G6Y%sC%HuFE?SK9|F2Z)Ew&0oF!)I +zYmK0yV+0se)cUD$giEM0{z}#X?2$`@Z*Tlue!s_o+rA~@vaB*+gcuy=y_>y~;F*h;HG`IEdi*_-`QqDz;kwbU5WsTM>3@+`x`S|7zNW&|lw2== +zf5|KDa+m97@j=(mYT_|-OmcLn-BYH6)r&>>4MxTcc$RH$h}j*%#;cE+9-xQQb>Qp( +zNkF#0X)C!hw_$qhS~PGW=-0Bg(JJ({;7|H{fY_Lt?o)Ep`bzCpBc{haL__J6YCJZa +zcb)gaQwn`E=S;~kj^2bkt$OHx*s`h_4WyifJ$ +zmmCPX=a$A}F8TI#k-@!W +zj?Qjg#NAjQeQst;$x@TZgM3z5gc5$&zuyDIHx8~bSQ6C5QX=xzOm +zoD3E-FV^;@j%B&GXe6tDFTvj<$H%_z(0L4sqmTYenVA?c`m9l4T_1|Ps?s}lDIfEy +z6Z1+lVT})p^1*s5QT~PXb1b~~A(878HSuK*T!p&)4g9H*Y#Qy2`T{v9IdOA8duOcS +zgXi8%ol`Unz?z@C9(CSZTAeN)?t}JSzb=14zhD0676W*DqFd)U;&oOG71W3Vj2zoL +zH%TuY-78Iv4BSUjS#=+yEN`bkg}~k+h9@V&RyLf))B}RKcHBn^CzyGHR5R{)5>+*W +z)m0|Ea!#z{JOaR7cvwGQPd>*dgS_19LjKIUc9BFg(^NZ3s7v +zP);L2>!DXn9vyyUijI8do^`G^F)!W&dMYZ*WPlDwnmt}hr(M2~rG4v!GfBR_D&qXw +z6&}`)3iR-wT6p-2Y$k%>nE?#5pnu?kx)dZ!4As(|wY!WwL-dbYH=O +zZX3_KWPD}1A_nK+1GRZl;34G6`{-PeG(+JR^=t^+Y;s(gvA;2Z35F%&_$SK( +zn79kv-P5a&0Q9UJY#eGkpXd#!db|9{deDuPC+GPZAGP2|bw}EjSH}Zo&r^|&r!ggQRmzKtu8xM$Wngv9+Sc^h5AV%b*9M< +zI|cLp+@C&0@Yrqm!H$qNm@eVt$?#OM6U%jK&3<4{5?j7?+HXLz%fsz;#zUwV9r|M4 +ziP@F)|1g;2zXzdtYwUo><nqSc}tH4J7L~@D7oSGkPbNxiHx;|z}4^e +zGjrj_22-_uki4&YT%O?o?ieh@zOLEMa`_cxvJhQ|IjJ{dtM3|~qYFnwSid590633z +z$X+`AX}VyWLawDE3%NLk1oXgut80b6}S) +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 +z5F& +zLXKo^huzBzyqVArNp%eR1m4T}Mcd91vGsK!)b~#e^FE3NJDA<*_lbftBXm46l8My} +z8aj6orcK$F3SmdtXY;-lSqo#1Y`XKM)AHt1wkE0b3aHD$@+-Xsw^3&^N6SR-9s$Yb +z&u;zN+lm_bY1GH4jVBNK*)Jhw^yvNjsJtvZkVt6p?c^sJ5gwSIu#cj3J<{=jx@%LU +z@%TQ<@YOeQELKc;WXCQAflPffAaQ7a-e3FgQFaM9b|Lnf`70N8k*KGV!Ls2X-{$vU +zBI!w*gA|)f_;uLLqf9iOEcmEzL*Oe&`@{eRbjQ~ZuSbRhz_9LhJ1cPY!6^?s#(HKE +z?QU8=kPbgo+)i`^H5BomE+fW44xJFNmRCdR`VCOzKI(ECE`804$V{&+$FV|}bBOQZ +zbAie4Ia{C$_u!`5D|LD=J*bQ@z5iyqoW;#uCh=V5NlcpMTZae^g7zfwqn$R~?V+`< +zV~>5@d3%(S#1F1rqF3d&)(SIZAHeZ`IWr)bg2C3HB3sh=wDvauZ36T;O1CL~7wZl- +zSwKhSd^fsk%qaE9yxyIt8$y_QefgpCBlxZgbv<drxR1wdL4bVs2a{QIv5+ABahSfKH3m3kSf|LdPEL^(yq#JY +zQnGjY4yV%TbLlELD`>Is9B2!Kv_c@UUFSnv`=|<%R~vTCu+@{o%hwY9gz4Pt(E80m +z1}GT?_uU68WqY^=o|+q8d*AA*on&uO0yl^Nsjz@YA6O42RS!2@9LGrWg_u9jGiw`o +zz`&heG1r*Iwvr)w`)eGQ1Md-)fsKL2v`0+8>}e1^$OfNn+~Rho0vWQ0t=#VMf;f2TTr1SA>VN&p)Qq?PqN;zN2kqp?u9t8QG=qnn_G7- +zIFxRC7z4}MD>qts!t9J9(HeY)eSpog8YgJ20q)DGXh@Y^XAdcoa;pn|`nhW-h>YVMmEGgIQhQN4b`g;t3 +zdh)%qNnF^??utW+Dn8M(ay08cvUyro+z1(G4vu_RK@i1w&p>&Wa1P>a>uslE_#zfg +ztZz%f-_po7P`WvozUD%>`V`F+*WCGLMDz|E&D&u#Fck6|RkTulDPL6FPz7B^mC69~H;Q=e%)MO+C|LU+WX +zw7jtm&~XGV+lA>g|I)$Vx&T-#yjzfm-{*oh-hAu`itZ_SG9-|bPsN`8^Z`Tan&;+) +z$NFKPz^L8Zay_yLne&?1em%~1hV%Dwe+TGB9rU@Pn@ecPs&K3y5K8s9?;CxVXLi( +zH^?eqN!6Z;IFn`X%c|V@CRN1h? +zX%K~Bao;{y18&9RyCP+~f9F)&-ImiIO;VgCxVc{MDOA1_VWxG!B3I`=wG6T_gK|eR +zUj0?fF4Cut&xRf+WL@m-__;`b5AoY8*1LQasBXmZ@h2_e@^xh|lKzrFg7GOHk2WE& +z6u+0l)`AvT|&gF4uGJ+|=ai3-lI8WWR0W-PH1={?{kse%CSK +zUZz)`8Ieyh$q3P<_PVXaUp~tdp2LBSdo~X*l{_biYy16iK|7M3wuRyi)A;_SlWi++s?PTYc?*#!eC^ +zAn`E7;mfx7O2dsgwjxr>dYieP=(1DjBURfYcjEGXjRt01k5b-O^DuF!8|lgS)VF!$ +z9)+4!Qnzn_x0+aK0y2Yu%v*)>3GMgJMe>j(1ynoZzpKAy)AJdJ(lK!e?p`=Z5>N)8 +zEd{{$KI}d~tL>nJk05_1j^vN{Oka?FDp95GCe#^Z5j~HG?^CH1jLS*aS8)ib=kwEf +zYTab1XwqU*_Hv0dpoD}V{=E@*aYo#HU2uN`nj?J{&e5) +z>s#;lf31E8nXu!YuuH>Tb!Bh{Rv4oc2T+hUa5#FVO1r;%bAzX?spVW#kS!Slc1`{) +z1@J-w2%aiTM0cMr`0~e-{M3x~KL`{8M-vVLacV!x)LAO;Cjfpm7*S01u{7sOODg;7 +z;*M2|10zd>Cisq{GR=hs|K{SZnyE}UEP^TOq)x}ftn)2zft?wFi; +z4g8#Q#4NvjZL&In3k?ERH(2?|RXz)V{kYa+Pb+%tQX)2jv7g#+y-n@VE%H}L`R2v9 +zRrl#;_LE7w@5B{AKK_} +z3^amcGSf_lqqX+Bcs|_0j&CYmC31(!bA;7OmJVGx8novZXZg)o>P&6#pAW=FPwg9x +zsSBv&o}-TlruP|Km!PECbM`00s0sD@_O1|U5_XWGWg_mE_kfsSNd<28oO_w9Z?((h6r%aExw_;<=Z +zfSvN2t9PoHg7+=|twU=WGoAC9_5nt@Q9anSYi=glAe50$^Hs``Ng9}M_#N}h&}ja= +z(Ho2N8`vCxk-hHUmHqyBsNYr`=eV9*W%sGYKgknAt7*Sqq!SFWhJx@uP5u<-;)Rr*5ND!hoA5pV?%lB0&3a(jLx`61#$~xIcF)2TXZ98qn +z7CtU>i6@A34RRzgHnIX7kb)}Q-KOLZxEgnGAWcz-F)T`B}F}JNP +zv!rE*%>xj5^0Y+g=S6VnKzaDrjD}U+5l1i99W>QVZoK%GKK=^hw*O$&`e3Abx6ONM +zh~E%1u&yXBQjq)U=vXy7GJsdb%TFIaz*pDn_*Rd=7lQ1l +zZrIJsuCPjP%VGk-ie9p~*Qw~|;Kc8-TF!^<4vXl3LpwH&f17g{#JNYO_|o)up<(9^ +zWChd=JhbM(FV+e#NchF+VzTtGJ+=!+`M|? +zYi<8Uo_^14hLYfCMR^eS+Nql)Lw|onrb4B<-HXzOv|mPDUh)tCbAY#pa1aoYxH2uf +zpz*UIe2mx@@c7xt`XYTDO^-32Q@$*IF3w2zP+b=hOUh)3*}A{5;QSs4y!C0Wmg6NJ +za+3)rIRyVKGXN_3DyLpX=96eQY-*|0QE9EHCYW#J!$Cc@h@ZpDBhL+3W>5S&E}jdl +zm!OP;?^C9@Z;=;3$*lxttFJ4hrHw{^=WhOjoCYtPtc@khWME>}zxA>cp)1BBU9*MQ>pLY;gQN +zCu2B|$P&=)u0CIAD!O>XKFT-!cURnXce)OWwiJG?SMwsg?Qr$&HY2_ZyQh0RFukq? +zYQV~u?jZ2_@WJ~H2@7(U*D|#doIO8-L1gcM#bVtcfMjsvpAJ^PhcJ{s57A_nLr{$P +zWw6UQxFw$WA6SCKiU$d!*3t9W+rPu$3^bqaJ~P#E?(jW#NJMSY0Ay6I8^1E6&^t-( +z@c9by`P{Y#xkC0hCwK)1SGflDXRubvtoHNE{_gOHZ$N&C;qu7Yh@}VX)YfMYR=Cce +zwdwe&*;5h$;CUiLlyWfdLI)k&ULOgaTFfDg$I~Cr1-I{%n5;3HYKD~ +zBy7J~HGFtaDaT-r>Vf@2qLzjyEDJNNg}{A>FwFv;=iqj1B++SAED8^8bxQnqj6H#R +zSWf_5;6?uFD*n4Sx$U#}n$529CK{@Y9W^4&n1?}M+Qgp?*Wg>xt`oOXQn%!=K@YfC +z<9+Klb@c3GQ5G2(;Z4zL%&qcodE>cORp0e8S3o*GRw_7;^~cfHTYbONJ~UR4(ybG} +zlL&vaB?aScokMse@&LBoqY0JwTBu3$*2T8Jz4g9bkzi2k!K+N533dW*&(eM@;{;~f +z#j$#-J_pJzZ%y7+F8>+>vl-;+>7%Px322t&VEVUh$DbmV>hK=K&(09tc6)k}U-+E$rla?4Sa=R~_AC=sjK>2&7_~&zfUe2iO`vvF9 +zR)VEc9Zk&zPfqqPh1u>soVK4Sf6W~dW=J(``CcSAnth@O_b*}&Dm0wd-YPQ +z3)->pz3GxycT{N$rRQsGHGWIcyt(@sc3JK^M%P;|_FZP9Kh+|hb8+jO6(ETI9A;1f_1{z_x*g%CuQf-F1^rOU?Guj2?NPIA7rhZm +zzE^jtWllasjDzy!2j$nyLj(6rt`y<0h59d4!~c+6u$HfS*S5Dmz$uUEz8iTe2lexGQ^D{yzrd6xrn$dEoCd}}*&a7}rG +zf$ni2|@QMT4wJ;TIa2U +z&#bT#&pEb*%{{(P+H^|P8L#svBWeuiM}}apm#v0LQMaI+P%kIg%6o3sW<2t97L!# +zs}^a)Zut0zjp?u@#Ecc!)n$NqpO9U(tmlX6K +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 +zTdLK$f2)06Iy=}E)w+!KQ`as +zCS0$Yrr3K8dy&Q$bW3~X-VIXoe-?c`ibJ#HWH+O9DA%e-S=Mg +zy?%z{a=i~ka>6ca9qt+{m()ju>!#mN%k4z-j9`^+|La5kd1HfDuH0)EL(8q+IrpXe +z&WFbRoIxOUyvMK}t|od=&|rGW_&w#2i?ppgXb0~sB6l0Y2?LCi*7mJ(31eKV`i$(L +zM1QfQ^ScKrEt{*lOb>%IVl$23bn=sD?nB#{k~RWc6r#mlnHJlsoosp(=J9Wo1Gr7) +zg5G)rXwhvFPi=<)n}ori^F7y*jzQ5ymeRp$XqVfdLbb8lv@v7w>Vc}EV|T22RNLL? +zj)(#`R9DZb2ttFFz^g?UNO;tZ?*i>jvOi +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 +zMpIrpN1@d6+x!1me1zb6RATM$DY +zw6TYy=$w12ej<(EGZSOvcfK1e7nN66zuOjaMe6HtmZ5nOF6$Oyv~)rygOO%oz{v8F +z#U~DR&BjQr@d0MLg!ZjSS?6>k}{L`sP1}2TUcmPk)a_@VaXR=-7@0%Y| +zuck8;9CUA@n*Cd2U_^{K$LXR~UThS|c9+FV(G0F)t+Ds4^+@Q;Fxy>0aI*{GLeDGS +zIuozP>gggF4Z4BXf1m8%Qx?j{mng;x?<x-2gj4#J?rF@mUPigBWMi_S^Q+!x!h; +zv9#bY<@tbE5jIx{r~vl8y3LD;Db* +z*bS%7NfK9)8@1@49r(yWvTwc{aKQbD#3?mo&;*i>l$O#BE=Ud`y6t9%twuh3k*;Nc +z9?McY7W^ODB4^jkb-)I}UV=xXVq!AVcK= +z{46fKhbRcBtg7{Zd~Pbd`_4rcVp1*>n-O+&|J?l2-;*5RM{xnPcTcyTGNBGJavMq5 +zhoIpx{0Dq4@!kNsOs6dZ_;HgiU*Gd^1%CD-6nj}{9h%%8bD&$#Tm9;ZfV{V113igDKqN5~*U +zgli&8R65B$2l)8Eq~ +z;o*HJ`~>zVw)y@Dj9QgV^&JVAZ!~^CX;z=?y!EVhD=xO;bO4nQ(*Wo +zjl;eCYc9fm&zHbMl>N^k{_vqu=-C;@!hDe776dI4-EDP-0Q-C-_l2#mn7hP-wWnw6 +zq>)b?WjaAtYSQ=YdHjC$+~S+P;{uKMqT4xbr>FbI&bdu^zy-ngz?m$)zDKC!9Ln?e +zj9C_KOXT4sRqY^nc^F@nAeYe(HbUzn;zopsj-%kflwYKJcrnt(ir23$`>PM3W-@uu +z*5vGp&|qbg;iE(TDfg8B;`8=QzqD(x}f+XnwPCYEY6LSiP=@Fz!6$M^C +zvFH99LZEy3XmtPi>_0{KTtDyEVzhGj{Bw8Mi-g?Bz`tGGs1TjUl(Rqfxn}JsuP{Xf +z!&p9W*kUDN4E8O5os1Im^XbSMQnERm_vYwa|EY8T`^FU=?qDju|IPdhJnHu(K*IZq +zooustr_hBjN+MwEO1=-`fY+|e?GSQJbU5t>Rj~kj&+P)vbS5Vg6nBiM6G#P95-!X=@S-b8gRV+`zv(HTYiBk)u3SH<;QO=6j%x;F+$UR*{;^g7oQe +zSRQAfb(^j3!YqI9?*aP0a$GLE2vCGPv^6w~Sl@{lV7)dE{hsCc`SgEp+AfQ8*WG)% +z8V!^S$8JCY?JK%81F{j10MVIuD1%;tJ~kj=hGHA)$Z}4i!O_6;l4j}orqQ_9^2E-o +zlzIBSJcgHhjI12DBGMlj?MA$vg2o^=aNfz?v3%bx^@g;F{5jdr`%-wIq&W?D>*J7> +zgz-3L(xbb5Z5d(_UYs!dsc-Tr^3#I7H{=_yZVSZ$t(|f7hr3%!mZ{Yqd8d3N@@%s2 +zr>XR-n`8f>wqUdk#0O?0@O{W@v_TCxry;mPB366*NEbWIybo0}1sLO?Sy5MHlus5y +zrc#D{Qgmw6m*?IRkG8v1YTK8YV)d&l=iqd@C3E|V+&rH?lJwHc6jnarT*a8Qd8bY2 +z?`b4KD$>fS1(aU0~F0&?dQvyF*QhF~U2F~IkWWRBcA5Dj& +zDzoP_2q2b*48&Q%Fy&n+Z7{y~BL>pRX;z5IV!Z_q(tp +zopDtT?41J&Oy8Qjn!+M}^GKwAr;u8;IwM +zz8A_(Htu5&pWXvEQ>embal)gGaGRW669p +z&PhqS&H&-~fF#j6N4B2BZnfC~t||cj>87-}?0ZNRubk6WNvaR+H5+{EqjD8KPaWJC +zs`tB1U@%7EDQ^*#f;5t3uE-S_}D +zVrhnab(gs#yIu6^MeA^+2b$1a0Qx>GQ4--7UXtx^--5$ua60U6;Ai8%ovwP!75%54 +zfc=Li`8%8$PTDCF3M2g7}^TC!Ij#WVQ0Q3gWYQ~-tXmv^Of&2&NjnO#Nqoca?H +zwY&hoCXRZ~L;AJ&*vnBHc=#y7&&7Y%wDB1^O!M^47GP34orKjRCNHv-uYCGF=9Jq- +zMNRlmiu1H+gs%lCDeE@=d=I}_Z){{$sz|)zi?`10cbF^d)n(s?gTV@9?<>yDBxPW} +z65uFq1yMC8F4Tz*C%Hs^py;vpXhD$;ll7&3?1jxdolS>zO7Ejzt2KWSfu#8@=L!0kDN`bBs +zbzcci;!)waJO@M42B{MxhbrIk<%qS6D{zZ}P$!I+>em#j{hknFPlRNlPRY5OJ{bK% +z%Raj?PLunRrK_FVEQ)&nqES-${#*0WzL+|C=?J~7A8M0%J@Rz;IbrX872~7MQihiC +zMMgn=i_2xuRb76KiqhyafrZGtK?~;$l;opI9bKpiowSa7;_tbaEO>_m^r{Z07~##68$nR{-*1 +zq`s|k=hj1)0xf$oPf243B{kp#z8S={$$H!U<1lO=c6eJA6UJ>m6M8P(e^P)=Nfr +zndn@3)xRms&pBs_9$gm66qiFK^kS(mU%9dxFMEt(%eA9Kbdoo2jPTfiAH7|5dj9tQ +z@RNrh&*v_pEr~UEcriW1!+E*j9tM&Jj_f`{^fI^bD5$Q(9@C)nXf-Gu{xoU~sl{4{ +z$z&b@sg}T7dYfRRzE;`KH}bQJryCEnekxM&D<+w_}nqT{#Fi#NVxgD_rQ;8-|AUfx7ah~j(wb=ERfAR0H=&(@>7pz +z)Yhw@1G#n|ow7BZ6VR8TsPgWS2i^YmpkaU$wkqHf{dI&b+@-G^w$#(jp)X(G?ok<3 +zL`BWmFbr4@WT+G-h*MYT=y~j;gedG2*(8gi4p(S+to9wd$msj4p8N0FC;$z#((_sR +zEMB^9?Wy?LAFj%`Q9b_Xj>9@#Kl_c1jeLt|pDc5a(sHD39n%5)bTjGU<-j{ic>ejs +z!fAo`5;7lXg3$JD(>N*!f~<1SOn?Ex1M#H}u1k}?o@M2Tlm5B+U+GU5R3VSqpSf!Y +zg!~~|B;x<~u5M(Z^Sx+zpQx^ibEWfKGR9tg8P>>@jLHMk6#Gu=_52i8na4FJZY1$h +zr|Pj3c2r`~pi8|@zwoaAo~Byl4x<+8;_j1=+IxpB-9_vHk8+fwTI237czBA@oAMUs +zLF+;|$nX5Q9DFP#tfH_>Dv8nSL9cW1K0JAH@wgv6Q5i*h&I^Wkd>?w4MIu71eA>ZH +zzeyg+m#PBnWd_9}sFl@D@hdlrJ#YQ3z^rK(=9OR>S;*=_eWd&xOdyrZBY?5@{t5X;AeO|WCB!P%4886O*dzI?f-Jt)TzZw>Empgu^{F|u%G?-miHP!(=uDnoXJ)8beQ~s00X(O!S%nG?Z +zb<#C8H-nwNlF5QLLH>RiZ>0;|BdRbT;&IdL&dpCX*plQF@=M})APF^a5Ht?5pFcGu +z4?1tCNsKip`O>yy{IfMYgot^#uG}hCmny=4l3E3G`J$dXz2wOmfyKas*B)u2LX%Hg +z>qxqMULC>ci&UtPIOqP1nBNmydZvM}LtF-Mcl0t=y{B{9qBMf9k(#6Otz##S|emu^;>Lw=n|Hh3&Eg1~yK@8yhl!ay%ZpT!;KIfawc +zjPk+t!7&DYlIlV+7m9wmG5YTrF9|u7 +zB}lzYc2!GmEQO*2JaSD+C$A~Fz{i#5@f0UfVmiG?Xx}F#WVpkFDi_filMG&bh4p*_ +z4V0lPaP86Vho6$vd&4K->Ip4KRg9GMeh1-YaZo;YTid36G8*7P9CacLUb{jf-;uG5f|z +z;JHkr%dD!q;y^b~JJ#)i3**{wa_^bjFJaWdgAW-?>4GUoVZ`Y$zLAmJ!#6IgxV{5? +z!Ug$JWz|bcF^uPior9`Y0Cw<pbdnGJ4b%J32XEbV*n@pizo +z4sx`4-cljt3|e?@Bb@{Ui<_F1iHdN12kcZGGMEDFfmMLC-gp=({Sv +zQSsF-)rABO(u{<3%}QbxHPfP1p>y +z&EumQfZBDuarax#JVJJg>lj-MKpytPkJ$mHh~TF~g(Qz%XZGRi`uKl6WIAmL4sdH{ +z;84&6+Y&Z_EZRXl#&G^NfDTTGK#312TbUHPUm@E*x5(`gq`mi6N`6hv)BFBg%Qt{l +zeeeMhPII3e6v|1UQ+@g~9on|?d=OJ#a#MkXQ-Y2^)zADt6oJGic_)qi9qD>7eLj|6 +z^-?MZ8($s0eGNk<-DNuhuZNnx8e$Sn2?0QXv;{u!kecb9K>ZXudff``rO~_?K*Dzw +zY0U~3T9}6G`_3;H;`$>Xh#K-BP_oRNnUP^W%^KHdfmq-0!RQu8yw57udaL6$iui(ZA;q=d^y@9o^?>H-Y({N@4 +zN0NJ;?DKz&ok@~rDXxXLqy}|Eb?kphW!#wlXdZI8U3O8{rw;gPo^!uRmou?by@@E}xRx)u+qU +zifbwXgj%k|ON}ZP=*>=RhQo{yNYw3Bu(-l~mIt{G_ns35SN4Hi4CUCo)jE$H#T5Ff +zLXZeCMWqtuZ`$ +z&RI5W{pS66-icr*Fs+m!o3qRe`{Xd*&{E3pNw;1kpik`kvGe|#=0Kf>l`@ZrQn>}7C$)?sT +zm9};ePKQgjXnA+!BQ?ESb9!DvFJvgVmzbj4M-jL1Og5<}-B@Mrh*{D2EYx#g&k5S&TPtx{~U3rCY`bLdS_UAvO8Z3OrFAv$E4c~oa&#rE|o$Tqqrq#vo +z4!YW#C3ZM;?0TtzEWJZZ#qN^S0@ULS&!pT8VPEGg4d^onx}R;3y&+Y=@D +z75!#1TOy-J(Q>b>l;rmRF%jA#U)d3;zy&p|vJ2XrZ#gXtH%OVUZd(!2_eO1w)G0|ihjb$PGnP>O*-st+;o7s}c>amA81?VMnyB{( +zv>hjf4jHV++mpk_QC-Ngr8EO^#<-&Z+2+a|Vw=9tcDfjRBOJ~pYi9Pt1>*RSr +zJ>PrueN}t{nXvDGKQ +z>+73>_vd>3)E2Za@dRISxo1bOUiUA1@3GVX&+V~36#J0x1?}QMC!q690!-+_Z+KWe +z0nxB}uPRu62e2Er5UZcqVmNnA?(Lb;mZqgVJ?~fM4y6GEJpvCc@&!?4K)KDMrRv{2N*m$Meds)1>&_J9y}!Al*lI3*Ycm +zi=^|t_QnMqK6y@IIszJL5H?6aGh9Z3EoYFpOtKy)CHqBKr(rJT`}cI3%Zv2A9ve47l{*mgd3TRU(Aik>70#P9=@9scLcU=QXdp;9inhX6 +zbSpn!b3H5@{^&ZlLS_4e=pFuwEs{SGr~2#kJbrf@az~w)j9wAyTwiwL&pz#t*<~y{ +zr@zh%gU43WI`^{XwR_^0Cow@c*IZvn+N8+glqdU8We6kZ>$^o05?&fS9vh{12Ix`G +zaGsJg3d?!yJEgEdZqX1nPu2Gy7=8UDd0&>i!S^VdZe2L1kNG)jZ2-q$prH=5C%Ctx +zIR5RRo6O)fGP7T2gYmmRad1^mnRR_<`~AocQ_tL389q&#+&S8IwHRPH +zW(xxW;%Hz_CWL&33*Y%qK!)idSC$c>7sPS&+Pt+rQ~gaVSrtA9(JdWsDHq0{PoOqve0eOA>9p68;e^1S6Wy>aeA +z_liULG;x%CZOOU6SMGO5Bk5Id{H!ch0#G8OkJbW@go=h=nrxmmi}LS#L?6P1OIRV2 +zsBI{X+qe%DcuS9zzo=Ed3aYTlKpu{}HQL^stVS-Sf$h8UbroCBH!Lk|aiR&8poF!i +zMrJ)o?lqiky`Lp6oh&WFWeP{04H#T8np+-;js*Sv3{OMQpSt9j)7;KdfwlC>jRb@) +z0Ga_du3N)M$8Lt}cL{Cx-k}j|7P$m+x@hm#kruZnM9w{0Kw{y19=TvVDCRRLDDRK1 +z>Yw*n@w*371ygTve->-j>aBpNCaVxv(%mH@X@oF)>@ +z`9wgr-jV4F&CXN6>3r(e*~lC2y0p$GjWEYq&Z&}f +zxEI^QRs`SI%u9rsp^nNv3zCb)M8W=Iv-cqpm)Q2y%h^gsBr#~=v&gjpi?DZ_2JHBm +zD8ghnSo$7?XurRM20Hp40&qx&44hrmKhGZBn1&8ttOwXP0OlSBm8i&yo%oDab6C0v +z{CqdokJhA)5poV8f6Yz@LQhMQS`+KQvcKIya?SjueYSZTnbX}5lJ8H2`Mb|j_y+nN +zfTu;UM&Kdwddq1OIfDm^ +z_n`sP%U~B<7)8(6Jr4{icWY+8pCQUq +zzd`1yYKOY*nOG5XYY*oiCoda2cjRWL#cb+n6v9~~sC{Ch-179%796I-}hQEFKxA7V3~GW1!SgjBAG{UxXzzK-Cmh6-$;2 +z?d6Kx)`Ilu))$^xFHMb7Hl+4b>?-rf&=AWsmhbFSs|Qf;y-wLjZ~8?G8~)ycXldy3 +zY>F@(j(iC%k2IxVH9yTKq5^-mCZ3yh#6jyQIjA4;l7XZ-brG=qzX6u&Zg3b +zuhEkja;;8F2}=eFGE|{|_vTqjL=JdX&Rh$4T7omD)|O*2elFzio>6*4YP}EQWNRPi +zfdhpQ`XQ~!wARVU83OlU>bbWvvGE{9bBrPL|(8y25e%^E5^-JdKNwdZ8~g6R@7r98aKvP$h~iQqu`FxG+Np +z*AdRV-#2XcZbC(8Jx!M9m{fSKM#I(09Zin(FEC9(7q_vGJVXV_l?LE22HtCS|CrQG-5EeAeS#j=MNKuWQegpRYD8;PwqbOFgf0d|nJ~w`*VB{qA+I9pGIedg5Z(>eM~-9Sb3k +z*7I}1;4fHe+(>i&jMEu +zeCi~HrT3c=ciOVT+P-^ozih6|;bHl<7Y8uPiB2~_)jekRHs-Ab)H;WJJnT_4=?jT< +zR8nNSXt{l_Vi`^C(lkLRx&BKuM+t8wMjwI$Ep3-Q8>|j2tjSjYW926dT}I{ig8uG*y@RoU +z>Aa=ej!<#LsmpKOq}vriC9HmK+3_LLbAe#ELZJ&s%bSlkm7I**n?}r!Ju@TeJgx`m +z!%x*25G$rXqHywZVf{=(Xg?DIx(g~|sO<4I1@6tG+D|VYKAg^R&_IkMQaL#&YVk=} +zkcV%)GB6NocLU&PXo@P|^S(D)0BBNgnaH6r8U6DufE_o~GY8!5wGsoglk%zHWTZ%Yim$(eZQDX!m4`HhwuLZhiA#^<|qq=l$TDa8(B}=jW3C +zhrwm!5|mzBsHfw@BX5y2ork-fB=Z?$U%W?i*?F&ypM&D|1QDF(<+|?c$k?lRq;Gu< +zo}svY_%mm_DS3GzMoDhwI7v0eWR$cv!2o5=3#5MHv4-yoSlt)y%9lY7JAU&?kgAE7 +zX6jr+9B@n5ebSjl_{-JwSIFO&i3+mL*cVFf9wzUVPLEds5d{a<9S5(;Yg<{0%$^wC}<@P*_S9OYj~W +z-?4q$hU9Mev|B}^5-C0f#DhSw`s6Ro8ioVASf>!E^-Si3c*v`*px*uG4VH;X;;nN# +z(r+{z)f)LugmkdWTtm$`2`S|&4bb3O{*E1k(rqix0h@95U?F4116Dfu{YV7gbL!(! +zYIcHq<@2JA-|6>vV{Vz@Nbke*Jea|QqKC)OaVTjoq_3ZO988yBhwy&6<{DF7PKCYa +zeJeITLK))ev+!fC(dU`e0MY*gl_%G +zqqG!{FM()|M`*9_{rXqWeq*xYB%XeeB-w*7uqCgsP;|~se$_VrjlD=hVOVjR{$4~8voGqT-``iE=kHq +z64&_&h-P=#D`4=-Eq#tG4S7MJ`^iCB5h-GDTR3BN!;zK99NHK;G34Br9ZR2b;%j(K +zedeHDAvjJoobdD!5!Km^sR5L8teEBP0fEa|hmN((KP&f9N}ugbz~ypludmz{cx|z% +zo!0BiPgR}2yR?1rl$zMREBw-=+{aOoR@w)S9XL4aJSP?ONIL0Qentwod%LXclv1ar +z;CUNT!$w@{Zf`GAFjg(jd3mX>71XN2{#@GM?Z0pi!ZLzWo^Lwc0lgqE@up_2ojsEh +zReD|a?V0t&YnM6!=2psiaMeR~XT9{?A{>JT=Zg=t>Ki~cz~$K4vfB@Q8EXK{OHtHZ +zCwX+dnIXKTk5#E<>zTrXDtT4v964tkJ}$k-ZG?^6Zdg!L#D=<-tvKOYKglZ2DD^6> +zsM!SRWQ!GFqDePy1q9TD`P(eRR?jYslY;S_`{?GPxPDX1zn-y0_PJ9k<>mFD+9sC) +zHg%a=={!6qYqfK?2t!RIj%2;S?2Xv0K=CvY^lY*|{PSEFe|HRfIc`+WERbG26ViYY +zW#PgJ3f@t%Bo*QQ7ejjrTqQBh^q%LxU +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 +zk?Jc;ecaPDykRslMX@$6+n@VB>WEt3f +zSLh|+18*hDmX3+edEatG6coT~`ay*rfM5>LJ8}61=FD*iAR2H)c}Sd>Z)uOP8fDon +zDNe4gJywf%IEl>r^WVIq*m#()4ZpN5GoLGg9qpXX$FmF8JIb40-2(3Em9|E~ZIC*YIpYk1iJD3m +z+U9a(=6RKrde8j49;N@V_GgLsLQ@pi>2VO|F=E$hy7%m@Ige-`x6%7ZFK?f5Fa!!m +zxUx^j`$bd19`kyPhQIp~#GM2?C_=?U>KR;gGD1Wf!W!&)h35U!sH~Mb4A( +zfUqmaxf_{+l2Klce*05eUj>0cJSy>L@;|&Wu<0wL>r8yc>KmPN&P#oTluOy|;B>?F +zZ3^{^fTCiD0no^e{r!MoX(Xg{=;+!o^};oBT7W(xbQK+5uuH(w{tkfOm#4K+S4cbN +zvo#i#8N|KH6&3^PDo+dpX@l41$%~5Pl1FJA_6Qu8}Rz-GT#PqHmiEiK1 +zN6^>bYW1Uke6m-y?seWQPKWOWBrrUs6aw>=6msq0#O?K<*jI*HmaBBr(;9B+C^Ib+ +ztYP=rI!Z~Yv{ZM&FLdX8CUUh?GT*I|rjci<>IGX6)4_*nuL|8Fn9dW~G#oDl8oT`c +zBKzeb)BB&*$lP%YT0lWD`k3($UmO(E!wstBD*NUcUlOgirt6fN%a> +zuRxunfDhvhj#$RJ#ai4?YGlrumDU-xsw=XVYRuz&Kf!>6) +z?=73nB3ift(f}(>?=_RAyLcogwI;E+<&4pnM!7(J?vl}Ref=4j`?6Z-H=Xxq5d6nn +zZPRj@Ry%}1GI}-`-Uk~)DyzJ9>*XcX3pD@c$U?tBrDlY^_^@0H-&TRW{^;cT&^;>f +z%Ef0$#@Eh+Je#j)x#Q(5&-)z|v`4?ZOYHdFSUYovf2JRX5A4W@_v^Sh>B5ir6Pn~} +zVcii=>bKt<^uAx^^scay?{{rb$_2&j8;r|XZcV4~XzRcM1rfF0y%GxZ=}_uA8gts* +z?&(VI&&f7B@W$VhY^zkpjf +zoBoZyNkmihcudOQM`kIJN14QZI&eo-uQZX#6PDjwy +z!s)2=Z*DKRMRt#*7P*_nVV_W+#Ktm3tUnx +z7wIQEx{)N=q2-JKwhY&Rt(Lrekpo&q{={>J7B%i7+B8+V7>t07a<5-__{D~h1u2B)tj>TRHKAtg;)APG#_2U~- +z!XD;)^~(Jo_Wlfn-wzSKDV0rW-DQ^ZnRVFFR(;4@FKHh-0hRIfynhxF_e`JW74hPcBQ}IeGNU@X57iS^CslNP +z4oIG9kFhs7V@7-9bzn`?G3Ja4ZNa-AUSY7V$~QEpX7!@0Yw +zcd=WNAM)aYc&u4@U;3Qs?m*=|;vknE{qH^Jf?$fp0o_$p^_g#;v(hl3d*-pdGxrjX +zS?`tj#9)N{A#y>u5f6`+_6*YyTo8}$tn@;%`&LUu@d3L>8N^VMVL@d=v1S2t{%+8E +z+t|*55pPoL?2zTD +z#oKFnQgEgAam_6nZNi@0H{(dTS5sZQe7BgGFFaHm_u;ZXxdX<92B&&36QXQf2u>vS +zVNd-87`yl&xlNE=tn-lS#cw7k>R@sD+y$3MB9`Pj0$jxaxG3@%(v>TrW$JjSzbP%l +zpDM!0zsDm^LWtKfPrp4M@UXR`5d-DI>!hzrltSBj66>QmlybGpR0@^NIu15PY{*sg +zAb}uH*K*??(eVc12NYFvuSkS~9)KLq5E#2x4k#ISEnoyyb?1!^DMo@fe%>9LyAM$clZ17 +zlXmtFxzwo9g1C$Uix+szks&?tXFyPB7NhCqnAY4QiPQAB35&gSN*zEnawr7J!NuGj0rLe5Tw=4W= +ztDJQ_a+hm#!2Ivl?WDk7;Kzzp^e7Wn;){j2!HcH=$DPB*QIq;11YQmR(V7_nSDr${cXq6A+$1bIXw`=(;v8pW1~vma_%}N?k0Qiqa}FpcToI3cdR*#)eS|5$vj1tuIoY7uL+=?RmQ$oim#wQfJc0% +z7}}X}vzg~}`!)ZPL)G~veH;wVz3Fkp#rnedVVE@pfnGf?C0kR5@oB#Zd_J>m8KL~9 +zQQAr-2!$Bbq(Idl9tS$mFN+a7CMjJP)-_o|IESk4=!>lczV&%RTa3b8{q8=JY_AvS +z;S!qrn5Npj`8X;!u+5FejEsS4mIqy7kcKuoTUD!K-cQW@#^zq};J$;yF85Ob +z>jtR)eILQU$2?$TA?xLsi-4S#bM*M>&%?av{iRzU#_>mV@lfwW?++gcLmF~iH>U?@8Rgu&cTACm{Lq$LqP3Dl +zGQa1g(_aJDJiH5Xn>1?lcF<}p1iIJQ6;}iFd+*;O!!2@#_HE#WGs4y2-(B94DC=dW +zs3jh~aYy*7diJ7iNOwUrF*mdxl0($jrfAPSHHFrl@lTBOlASXT@Tb&0Vjy#W9!&A? +z!H{A4I`Ho_!ZigcR(yc|KC<^EoYZ2!%dAN4bbv<4dgN +z=p+P$i#spI@#=+=I4`kpm&UPanmB*nVLGGbg+BDEvmSYYcEwCx`KaE9(8W%}O5l5& +z@%f&1qHN1PVB&*R}%#D +z3`@>q91?)}z{k8gpx@l?&bbXycWlX0ytn&qC?;R!R(>XRU=waFMC|-WpTguctm^J1uErl|}63$KOs`ks8tNVa3 +zf?kT9`#-d~3grx%kn%t(hgl%&*Cu+m$8#$V-abj^m1;Z9VC0%_AHGD_!q@9nC-(bt +zeb1e|1ruPD$sa0m9~?gmciakfFSz~=kKg)rvN#y&1r=s<)WlfZg+AYtw7xWcO<>n! +z{ZLJr9c;rfp>B9wS=s87h!4b*eWm=p-Sf8YO>eQ%3+E~pI2JW0#$L2WCB>}6?soIy +z+4|RA=RW-T#hO68W#ESyL{=ZxVE~{P+O;fz56L~kyeKXmhIFZ0;kH%ut4drd>$`_y +zR!dY-`v%o +z#RVQ)x|L8^bQd^FuuVb*&{&SEhrsz}%v*}sj3qTN>E3>fe{T^f-@!9Y_@V&VAfp}S +z7+vp6ZRy&0Qg2nh@=oRa^KzVj54beK=;Nk`cWT$xb#M4Wp#~ghWUg#qfa%mTm{(OC +z$eFm0D{3_24QM+kG*%wU7-5?r-VjF>kLxiqJf82b&DMdW*JpDs6K(eKRljY9V0q~k +zUhj6zS;v;MUM)DdLUvlqW@+)303$w%o}_(RXzNV$az=3{AQ&1}*uc@8*w?`9zEqHNsSfLCHhrf##( +z7~FTwta1GBwkj!`6s*jLK+|z4StE1=aH9q%vvP2GN$K3~O;eWs(GLvO^?}5k= +zL3gAMxDP^^)@3_uR#DYd9|ytt)+$wv03mohv7;ijYKv@=Bho(-NN%4eQi=vn_s79Wh0Erm336 +z0aj@7G)I32Bc0+bQKIpx=8pB+85M7Qo9bwjdLOoOBsmE7>Ob7S`!SpClv=m-4cNrb +z{Z?-XWF2eY@Xrx5Q2Ud>kQr;hM`sL8JSx_e36P+KLJz*d3c67n^VVMREI +zc=Kfd9K6w1)1S~Waut2&+oPysuPAb$cjG(It)(#H^Rq8CT +z-~%3?tpB9i-mK+48^kHm9+D%MQDIUa|AlWf`%$>FZr6@*-}4>X+inIE{-y9F;>D1So$-z=j-zX}GE2H|{B?bd4Za(s$uvy*+Su3~PJQITJPNUJ8D +z;e5dTJ%xfH4y+bK!2216eKD+hg;Gr;`hBR`lt_oA40i+j)8R=m33ZF5=FS@JXH7W! +zH~^apKCCumj*kk2sdnTQi6(BOSgw882@3m_X@HX|g`aAKqQ9y&CBwd-ffgKSr^Ad7 +z#{HDqkl&*{VAFlfPfDc+J;Jg!pk7$okRcu|Ez{>dqP77y92akW(8CsJwZb2e`*%@rpQGCBrn2qAC#_t!mk +zub;;Fj|M>bJq&bllwz(sXSg`{%EsG&pB|PwTJC{X$B4be+_V#=&5ye3wou}3UW;R0 +z%ighmZE^razVT`49$x3B|ZuIg#Z$z+I``)qK!NmD#rntS5{$ZuQ#8aI}W9r=YINV{VGVW +z=cjJwo)TPG0KF+Qcu-O$b?Vxz_!#j+Tf;%0v#}PevWIzmoxJn5sxvducPyALMiJpF +zLZ#>C&#^)IJwBA1m+Q-W*l#1MKR&+@frlR^+S?wGiCf3Fxy23NLO8~;o1e$}Q6aJ+orcP^T8 +z%hrKh5l#}A_v>oEmE_Cn?rCOltm0*%%{a;MIMHfJ1%Ixo*EN!5 +z6{>>o%|lS1_TD{RHIhoX0CqZwN9%mk`l}*m#9t1@#Isk7jX5|-Zlbzn^RbABjx4Bw +zQ1R$FfJYHp7$@S<%7>-fE?v!O+wWlERWTo1>bPZNTYL=|GnW>7s#V;A-m|UEOCP3+ +zNXUun(KE!YpAH4l8GB)$KB;sN^iKT`2KWPUVv=BD3S6y2F}BbQB|N7Xcp3K0;YQxB1oVuTyp5 +zcy5|~j)+dPl=InIG$wr`pg!7<+R;NA7PnhJKk74!9FRk;cTT=^Jf;qB1EXYaAHVJL +za_{(Hkvs}F}CbIr?4?batA +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 +z=dj^1I0ks`)mU71vJ;~zC7Hf +zPDcRPune3G8AY(`+f{t~t@GC7we?Bfp%cgc$@P@hcl~}D8GFjxQ9f#!d)3YEJ{SsL +zM9BJ*~auD9jnNy+oaw|QI7Dyd)t5l8k_xaQBF+mqr +zJ0f}IkxG&4-Y8ez=WFZD!B5sg-3V7ZP+k(FHXSn!ow{@+u_ctU0E=JH+X`E1K7jQ8 +zgH?+>`~i6N+3#FGmM?wB%7*|9V2yge^QbEkd&5e^;e5R-U>I~n0ums@KKb3plzDwk +z>fxzdjtMUL={`1>RZp--(2bz)k1WbB(L6Sb)HEI#e&`hVxzTaXCEp1JpyBuQ7fYef +zv3i*BAv|=w%xLCsKV`6dW}szw9yPGw;yj0m;njCICGu*b2x1+blL-t;akE+;6u5sL +zB2?5lLghZ$#^F2ZjNhEP=4NkrEEviIrC^_+nXKKAW${C-;br5a#*|HaBSvi;0nRGc +z9BsYsv8M7d>YTc30~z-xuCm{Qg)!_IN3q93g4UURxw`#xLA)mn9Hp|>SrrcwfMyu% +z9+K*C{>)L@WUjyWrsZ&*WcEG`cKGwh|I8l@AG@Y{Kk16rcadg560iOqb2~WedW}`< +z;jB}yr0SRj&R-5Bvsr9Ngzktym=ttwVKkbAoQot)M2s6axS=L5J +zE{m0(*bT*@P|uG6U2R%NuhSvU2nVm#zngaYt{z(?L+hH_Qv2lN?NNE+ihuo1*E)Er +z=4PGSh8TUn`5Tc(|C9an?nGi(aJK(#A<=0#(rv(cymyNZ7PsA;Ra$(7(hNjKDoHK5 +zPsJl-3u464eOit$Hy9joiU2_Y=U2@W>pP8mMblc=2O34y +zBS+@_IC^In(~gp2Gk%qGeclU8OG@cjzFm%e`J6MdkRz%y(g>ab9A9&mV1zXn9hQ@! +z=OwI2HN-5ez|o8$LKXSO!G>|ysGoaHg=@#&`bk>L8(rj|FD|&D&ZGWxPvcwVOkY>N +zX25ks5$?gSF%{;b#Y^cA@?>>yvqGyb9a{Yc1a#=18w?ExPw6QYDBk@y%!2aBO8eI1 +ztq^5fVx+1Ugohg-FJE{H_3;+z`!2jrSxLi{hpT)sNddhk?=)YsiG~qrzBsM~__IJo +ze>X3dBFjee4V-ZRFo6Mx_diMkj`)DG@Q7xZR2TZNhzeEa={W(M4|0#+K9y(;IOjI( +z1BrnH@ubTR?{1*cU~n$1IlTuv$o%x9$Ov4xLaan~if8~^n%QG9W;ALxj^DcE_pyoH +zOLZ1K-JG$v4B~u+4BwD)!YQLldLZ#KKodW3n~cM4LB|yLe#4Ew_O}#1_fQE*nh~!i +z@iG4VeUqif=@5V29f?IuPTF_xW5U;9xA7$7wSMqU7-I_{tQ0bc9^bKNShacPVPy~c +zMp4Xq=+1~xp1MEwm~ +zRDJ>}AA<`x_nR251IC~&CobXRGFS8a!k^*wyWO$B&BcnQ&xzIo_bo)fUUkS1DCz%n +zSl#CQOud~Lc^>58CiAvYJX*y^{Gp%c)%M%E*-Ua;?}H@NP1=JksJi)0C?g|3zBCGK +z1}zY7tMX7p+;ZiieRDjH>BnzUe%1b(dXhy@LQgPLYxypJYVhNqym6bRG?<5hidQxQNoDgCR&?52Of@; +z({UlVjM9%UGyqh~J%W67#;GHCof-DD4%U@=d<#4=A?44_2V^y3KH$eLupRwQ*g*~^ +z`87mE46<@$eK*JVs7)*SE^9FY7+Z%qRF@L^zm0Jj&@xAh@K6Z*MN)uZ%*>%~{v?t~U-0;^+mi1PKv*nN~-*Zf?j +zbPy5Fqq$Hr`?&kD`%QR8KQs5b_&3xT=H7c%Gnt#NP8KV@V28J0N}WEd{RnR+R7MpF +zzqq->SXtG(bwWDO-CODDhL`}`DdBI-#-SLUP(s={C+pIeq3iB^EmnTusm@^Rxj7Pg +zORuB@AJ1-c6&n!#J4LP;awZTa$f2`#(1bCv#`7$9AIBAHzes~;)NiWL8RflyBU4zb@YmG^d)?`+DX5*j?MVPvaeVBe?~r7hL=kwl*)6u|pL^%K5@v}|-rr%+v%7$Czd5;4Ap +zja>uDeJtBAl6^C3uHLgO$dM-nk#Pq{nYGF2tp+x5SP*PO7W|}RodaEx1gSHn=@%$s +zsqg_3L!W7{4$>#!8euT7)vX?a!B$44x79+TfFoc>N5NKQqZ@OhW|uowO!`ZdeRK8VF$KCEM_kt;q_op{q^%k16*q};bB`=oFt<-Ol|$o+bM_wZSrt0xB#e$H~$-));iUEkgWFmK#I +zj>AX}&d%Mk(2wL_x7+Fh@YU*S@ur4L_VJ0&8_j3#$uI`+arBl@u!*@uF4rCx!1BD~ +zY_#=0XpWroNEZ?8*ZugwP8bk1qQb_6KYv=xyL_IkFFDg47x~G!Z#3_{7?5&ziaT%F +zaxlLqy2@G8c8@)Aj)rX)b4Vdy4l#d(c95-JhO7fw9o-jZm$P$Htg2k=+Jil`s(Z|L +z|Ubw26BI!JrUlA+yfxi&YJ9!09^a}w>EX~O{dQD92#LC7Kh +zyQ%!!Ss0P?ouQwx;m+`5(UlqBY_frlb1j%ko~}k)0$b1Iz@ybdhpnJ30M8SS+%)P< +zEqqyNHU=K!K?_5r&*MgewSU&F>woy&QH00&*X1TC-H14Q`Z8q1sj{F;3I&%fPvL~n +z-T*XA$);5u3G%TVHd`4uN4i$}5D(#gNy%b#r5=<_R}|Xu;jdJhNobe5^v>1fug&R9 +zakb!uam9LKQ0MkHI4N`>9{|h|nngPo>*6uoI+Ry+>5&lHN4N6Zg6_(eGzrSbd-&cb +zm5=25GE#9-9y2>|`ECsxTu<+8Jdep^yiZTAlo}Y*YcFs2x-buOo)~gl?+zlC2l$2{ +zScmko$K8S}P@3q)nXAXI(;a+l>}6`=lIB}v&6~Gf{~z`3yRa|@onYE2(tJ3%)w~Jf +zw8tt&)#3YZ%f$WCqTB;pjiPCF2>B>$ELO}>JMwXivQdc1z4^&{;Azva4AjpDZ_ur44((p$K(h7tejd +zRp(3zsz`-@CoU+kt+IzQffvZNJyk#rKrLPFTRWs_Ana3E#fo$HUSl*M6gulp@9#+G +zaaFTzKU|J}xj<=zR2TI&4Olp4W<*HLtj8nbz|3j( +zR49gfI%Tc3Jt9K!|1eN^i8|xKSxZpSCYTT6@pUBeS%1iz{m4QNr?xUbYzDX`jzhs# +z_ufd;cDd8Dk1&MY>1*H%<_Co+?YwY#gs?G?`u9Hn?`G1ks@8LE6o00pa-Se5)6Wo+ +z;H(M*gW4^8k~Dbs%+sfPk}g2m*YWG%vn2c8ENPe3{U^R?6ArXKFoKsY

r46_VrdCQ_>b^q8k=CXV-{AK%%}5RO9u(dzXPu +zBUfuF=6fnrIBcV)SK_K2xiQ-x|LJoVx$;=MoI&}zn@?U{P(yiF4BRXvhPKkQwL0!^ +z73*W^_H8Ym5`klyzr*eK7{ZGumN%Id1K=g0>b~ApGdAS++=)>0Vw +z&Lesl_~@z~u~lSap!d$_=5(FI%0tXeA_7ZoJXHr{zirx+9!huTtkR(d0b2~1y_;iT +z%WVKQ8s83+i$|W)`U<+Q#fIKvkfwny8hLe$v3H~;j2?hmT3}CTDX7jr#(n_W^vYiIb_Y2@G$KehU1qH +zPB|aD+jzm_I488ghjqEKW7KPZ1aj7Ab8|M477+QZf +ztaAC28fW*h!W7uFxwd_`1C|S^L*QDLyc@tvajyo=W?Mu7L`O`|)C1kVkMnw;=5sHV +z>(|46r=U8K;wM|-Na$Y8UJ7byN?g+t;Cy1CIbw4ClxWU_VkLRR +zeAHR(Sk3+RC<5k;0A6im*DNLr%hf76c%x{1uN`SIaVnz=#UVHA^NB&yeIhw+^xO)b +z6MIVfWDBe{7u&UE4Ot4Ix6JbCy>BRe^u*NSTdwdB)IMWJ^UlGMfAV*1?v*q+k#!@` +z$xy<%qGLqH_Ned)9oawk*K%_S@I^f{YGYbC!XiQMhG3O`E?>%@7qc)6@Hitsu!pa@ +z&CJ8|eia78bx5v0o=kodMaUm4C?Xcp!~d>3XtpCi`J4T2ab;n-%~%LuCfIu$X0#^c +zI;>U3bYk2EJ8QS#g$LzR2%1v;t>#K_j6@ImCdTYHPqiNjaXjaV#{1M`HPH}?AH8!n +zgH4(nUIKZm0;roX)ME7{9@TAQ)Rk_2vN6%OL?rgD%tTF|q9?47?(X4ewO({lhp)l! +z9FMjqfQ)OmuQ1k&e+jy#JV6#mAv4);(KJdD(irhZNaFr8v62~-bFi;mYb7koJPMKs +z09fCSh=(P4f@sa?$ANv_}znfyMEe?-k`w;jJc9=Sj_&#C_z;bl1g4ih+Ft{r& +z*34Wc$4=qCUru!W4AD<=xw7odO_oX{@2zWisP?J%tdr(@SagKDO|VPXsH{93 +zmefnVRw-+?@R;QxVc&P{CmyzS$5}8Wa#3jO^X=?OKIA^`_od1HbDn2mAHM4PSs>S0 +zUie(EPb*Pjx(1U{L}O*APb3Zzvt!;hpTWd(y))L)|Jmr^qCZ@OYn>#$+7t+!n4y@xE()f+N +zDsO2Ff3>5CH5}^ymAYC9@$iDCA`l}W7;mm@#d;3nX#LfdB3pz+AoPH<6uF3brf`x +zLT(L$v${Lz-g9m7;=}yQDL4S_aeaFw`RT$t^#ta5w>(E5bOF_4B315shpbHD-M1s- +zWWg!<*Y|xh(<<@Yc7m!;)E(3r6}Wl(B-y~(*-ltK#d#PBUuM=v_Q{@<`4Vq^D~d(K +z&eTi$QQuba%Do6GkABjm>fGCTSiYIp@{;UVeSOGlhv^37N>5Y;__6>}9V)3Wk9xP~ +zQ{9yX4+Q;Y4bsJg#HNb|_s{w@#c!qzeNzmFkG +z(z|T&uGtNyCd=j696v1x%6RIq>EUS}vm1C2V1;mspT4Z0Tfz3bRhPzvOqd5+acM$( +zuR|~1V4}ye0$I<6ng|Zoxn>pTDE8gIHyQ?RI|_AldKc-g7Y~UP9Q;?5FE5QS17*Ws^MF +zLkfaM!n~HAkEdv-BqfsJ?R~sttnPU%+0O(a#5c%tTTg`jJ4V5F2)U5FcZWi;xnD@@I5aIp(f8fPUm$#8;7gl7hP6{GmG$Em*S07AzrBH#`yF}Nr? +zNF`rRyYVD5?dCmA`|Y^rNp5;ffYz|a5Qn~@p3#(3j70#zM;ve5ds=dqvZ7)0KoQ3a +zj6csN&ST7e)Xe0n3dlB7Spr^crL*l!?}I;Ye(T`J43)h=8p6b%K8d4xl1~x(;9(TR +z<;?T0%&wmC^9^wH$2NvLh63Pcd8Pes2YwIPG)t7f{$97fTt0FSLNhVkqX8GFxPgq40p@0)Y~*K+H3fRy&mQ>fW%$;y!v@gohUir&w0w0EZ@AAEN}V_ymOFy2}A!nwK`;8mlkyHJdL7 +zcAm>E_beYZ@+TPNV`A1GFzHq8@+8bIiEzlkh{usIH$7Jpz7eo%u+#}oYMk^g$9<~r +zB9a;Tc#p@+G$$Un0qXm2D8HW1+8^cC6}8RtE!UBdr)AZ~BxCk8+}1q|T}$^W_IDWY +zR5Q8C?4ILnro}kxZM$8HLjJFozlQB=0?UK+^>luf`MIKZ($C*p%1shH`iT0bmKX)| +zovSkV8HKGGE1y+ul_U4q6$?K3wCt&nBR+YWHEOaAMemV)%ZYc?q%YI@#KD7YUCo#4 +zp?_WY?Ky70TaImKbNWNi${~Kl)W6XKJ&AeOjuAaIW^{+g&h8T)lkkKosa_(vj?^4$ +z;e6$s&%rrysqXULI$8;V1b0m-&|X>zcC`>cVtH@40t~{qJ+=?}ZI?aSsSo9Am1S-1 +z1i<5;t_5ZVwO%HWP9j!{6|wg|irnXxsy_g^4DJgx1AWw;1>Xy5W+IyRs9;4nrIvTqoV5R~F*(qr+NC-rQG%p&zfZLDS5M0#!thHo +z5cCF8XzzgdI-Xex2lq@2@5HHF7)9?Ry1rVYtqh!(nekAR*El`#omg2%Q}PkH +z5ecPP2pyjnNlzEvWqer07hy5i5feY#u)1YQ?w>O+KjklmrJsjFT5HY%ULt_vF&g*e +zyu%34?(|3k-fcDw(1kh<(;jERVJD9Xez)+a9C<8dGV0y&k<hHVma#ThHhAXumTC!(`eG5eum-iw&s&r +zN_KSkGlqyk(X4zFD!`;q;(0f6{o!spMj=`!?&=9!{XCIiXUIF6AL#NyeNi-NlZf*q +zNaTzelzQp~$9^c6&;U{ZH9*S0d##6@YlZW;PX_LRD6+ShzeBL6ewOcr#XTxwY(WBf +zvT)06r&FRBo)oEc{dZei@mSSk8K?c>)dK0w^Q5a*V15#B23apY;5|{7PE7bcE;!%$ +zxdJncyi9$s)nY=D$RWA6KkpsNyQdaFqvN_IV(UE^b1?;!5}}=)josJo9zWs9F1ivU +z5&x>@x#eY<62cR*xz)(d9m18)HFpo5yS?~#y|J?$O7{*tBN$AfMrUsKfsTeVbVjQt +z@~O7FpyYac?+wMd@t($1A;V+l!qiml5ex*ra^OM&k?NDHAUverMRILhexHB*ZiE&q +zC)7;Xs`FBS>e6*;vxw{+^~s!TnF$Q`|0o$Kuu2eB<*ggWom+a+w9Q=-b +z`^gscD0JTf}R$h$^BA#a&=#qVJJ-G`AqU}4z1 +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 +z9=$!5(vWeF$A!3<$#YrfxSo)C8Cs4) +zY(_gb@05G)-_S`>$~xMu2It7(VYrW5v!qF$(9`&K!NBw$i_+8vN4V~o^JE|e`*E?D +zJr?K6Z4s6OpTozDpDOD>nX^VG#6v^uKAJp+;&l3+_II>m>nx-T&Z)1o-Eq#PIKkL^ +zicLvj*z9aFbv!2DMzBz}-Y0?T<;*yr^>tf6ZVU(^7b6Y}T4KA$EdtnmEbxAX0kLL% +z6LsGi5vdd3y2Q1{MzbhlNZ00t)hDOvC^NDo<_Q*;go}$F`8QwM`boI!C|R!fjp5Jo +z^TZAN#L3oxphK0E8Yk+d3|od)|46Cgp;3m_hWiq%<^J;lRI*w}3)#2ZF<9R3bKQEZ +zfaLgt#38~cE1#EI`2cUmURBj&J)m^ytsCNQ69&TxVscPbHx39mzTh90&Qg9`;2G@zd4oSX$)Kosup +z>wX^$vqc&vGPyG&{p;f$0OeaWm;ioS6|a +zWBkHWY3HOMXDQQ0W!n=zlYx7&PSL5y3>s#j&Y=-k)Ma)p$bH}Z1(k}P|e$-*~=RjwzOm`Z;%?`q6E(n)V3m>kn&qnQy9J +zOH|_$X(3olrC30pK2|^9p8U6c0bt8zGDD`P90%8wLu`6$kv>S1usM-0lQtLAHzvXE +zcLe~fcFnzs)4S +zVA@(;?Y2r{%=fB`R-Q=G^OVXA=ETGG&Ue8NDeSyH74F*!^ +z;*A`1b1qOh*L-8!4{2m1T$Z!=G*8XrDtPBmg_&0D`T36TzYP!WbX~i<=`VMkW8Lr$ +zFkqgi^aUMwu(EG6Ottt+g83xZc}Ip%Ki++%#Gz3Y=Lvt~14B2DD&2$xR2}V+v}GQE +zu%OPz`D#Ww!4UX*_cunD;dGsGWRG~Lct{6A<;f6*A~&joPZQ2(4wT3vhOx$1!BG?* +zoMBtQmiEg#l_8nuCa>^(^)Xz*E#+h_@-;IfS@vHTftCHZ#m_w^`t?zI{4SQ1)ATC$qGV?zmL9OgAbYehJ+j;#OQy|4Qg~dj&;Rqy1^0Sp%;Q +zAM5ITQZzrCprf-vs2+uFCsr2E_KYq?+e<30~!+L+NXF +zChDD?7^+K0TOF?$ +zoBg|xPmnGpIEe4Vr*B9F7;r>`ZnF$Rrkx|nq!Q!sjY*s`DokP&3!hBgny?o3#|bVU +ziW}?!GBO|u+Fuo%uCnCTF`N6}1np1JbzL4A?W0T%PZNIA@fi+v&fXDYD(AIt+8E@H +z735gYWvZ`q0#Eu-kC#|^^pX$Fcz*Lc!M~!95^ZmDU`jOj5nDtyzuad +z!j-d{#N{HXyr$eSq-Xp|<7({VP +zEsw*ciK%5{<;aV5^*9(}T`}b@SZIbMi3u+xY`YWM54j$PPyi-=EUaTwVj)Qo5Flb=zyuQG%)0Wk)UQ)O}pV1o8~oR-^8?+tww!k7trq3_PM$z4KOI( +zNtUAgGmDxt-(`Cqd^r~fiJ=;A`zI5gc8%<0=&*^)2M_TPDvXqT%!p4BS>L7vd-PO; +zz3w$`7TO~nG|eNR)Bf`1JtVscv$)uaV4Fy{mnYdT1=(fUQo%zfu9_VxyDcq9#;Q#G +zSmR(AmR^MK1@17xXW{iV(Sr{nhY81x0VmIUhE~ZoE%+>vGR!>~w*NG4;C%X!iR9`= +z^n_iz94y{}7|O*RQgy`rN)IqgDC%dz0UA$a7IuOHEw|`a7FEiPD55(LnMLE)5hK~t +zjQzE!o8I{8i|)UT8zfDj(e=ChOmfTAL#&k4_?1s60jbyum5}98K8cL+NrJkCac#oE +zw-@Llq7a;bJAza9F}bf6<6?>lWhy-NqNQ=xro7+ouu+8cQ~U7^&27Vz^dicGIv5;p +z(`<)+XJY6en8O@?8ArY;Thg)4Ds=A+KgaY5lidmO<_30oU@OP7uY?@Q+zvxz2Hs3) +zhom|Ned2rX{zjkA5wZ1kp{wsFhIzj}wEf(xt|LGFHY0TWX%8k=Gid1Cy)bRcwp15( +zlzlewMQkmM`DN3cZ+baz7OR@1&I4eVbIVbB3$U-wW{$qy$2|g)&EL2Pw0BfB^3%|d +z(Hl>m>u0|SQlm%l-%kmS5J@+Dc{#tbwR`KGgG*`wumpwq^uK9K>ooLNz_0{cnYTn( +zWa3IR1Ra%^Y~#`0p!1bFo>dg>cbG9xUUE2gX~TbCdHuF}kbq+dv1sNGZVWF`PbGt8 +z!?}#j?;nx$B-gnVn@jhru$)KP=;aN$dCeN)K0wA`v& +z`^<$7F&;h$OpfPlfiB>=n`#d#6_H*ljxfc)oRV^f}tM +z>HP{D9Bi`Sg~a(@%+;8$)DshmJ5d-yHxqps`S24Mt}o?Zi`9SPF4zTh!eYAzzBd-}e9+CKACRrD#e!^?m+K1=v=2NxFY7(o>()S9qC2z>RNnbWa+PVh;Vhk%nWNGRgE +z&y^034vD+y=^MMc8N@2)>2=}}jT>k9b0=0V4G5t;y>=1xVR^Ih +zl-x_1SN-YTjO!v}_7b|G3fTF^Rf&zp^qF;-Y;cIN@8z_*;v_A2xO!P{-4kR_V`FvZ +zm7;z!XFowWcikAK`>ClQkyA;2&K}{W6r8=B_C1eEWA92ND4V-S^gYy|*|Y~SM3J_K +zh<8Xy&q?w4NXGqV_{ODf2?j*mYftlXHBBAk4tJ12t7{sF-bFndPZZ{zz#Fm>^ODPx +zTwC@I>KMqr9~d}32h*5Qs&O{rh9|qzRt%}x@9_O8(+uM)&G4#ZLfFYE(6HkSjj)s= +zOGb7jc1GzbE6^8NbH0&*tdLx#Q?icmzHKh&Y`2zV$oSXjek^VxWpk}xjWl}e5CoZR +z=jGDJ-p~#l3FXhmu@|{T06>!`davJ|*;M2UI=Sz!XCF1B)!cwNQhAR@Q!Iaz1Sard +zYlO%*J^k^dEeMeBePuFh@YW?re;lb1w8r30*{xILStqB+3f@Vs8&a}3jl-#Q`XHf# +zvx0t;eh+-*qiJ=4#CDwzZSA8%m%Q3;*9==h+*n4->nBVH(V_M0;|)+U3U1t&mdf^U +z4Lr3uy!Q6$sj*~lQ35xJ0I9HmM^9MKO{yMlz&m~;%@<<+d7oQ-=5djg4Q%4C>ij@T +zUOjipOD4ZAYDH=@K4+Sg9eB>gX_*zdwD-bygv`IvLSHXFB5_sktcoSW_;uJkO)6(9 +zq<#nRZv%?ZX(J`CDwcfsl)-wA_f>B?H!a-6?CC355PcEvV@faJLPsq>kQY5r> +z=H$g*ld-}cvf0nbLp4B)(qi-*3!{Di{W$KeJGDc8GTqu2D +zw-2Wrmv0zXUWK1(X`y};Yjn) +zk;I;x8NkzaXI-^?CDRxFr=<|ZX!HY0{a9|?P3dhd}CWV(Zsgst;QMBr&}WFyZ$Rh +z?&UsRC;AD)*`hX-G^U#Ir{^62P@V|V9cZK2UHqGq1y=Whl-wdEL}hR~V5VA%X_}Ww +zc7P`iYR;2d4{KcRgGUc&X6mrFx%Xm_RX#}8o{Bh=W%)F-;QSeKTb(?qhwD_kPxaTm +zgO(sbZjb0hJCZ(qEWL}jRL_1ik4=Lp>=rlnK@Gr)$G1hwcK>;Cc60Q6D>JvVwh3GM +zdxC$s@O_!GxG#S7G;Ev(AV*a6`S$!pjHv4X)uSVv`_!q>o__eka78bR?gi?BQGDq1 +z&D83jLHyg~!tjXhGV1$75y!`$GzMgJWiOI$0zbj`DKd{XA+QujWH%o|y$R|M++9V#!7)d6h|aLcdD-cn!+2_{*1jtHvf=ZVM2+W(ahvuy#V;5y +z?Wa5Y&N*b|w_&Iq$Z8{Fe?Yn35FcT-uLD6#ks`0NMCn`%th{h&0zls|~n{KTZD20V86gd<1n1Kkz3cZ%@$*z*a>$5AB^o_T%hp$t^i!f*E3BY^bF-6b3 +z303uU%FC`xG2fMSl4JqMzstnO(z1_pcC&z($6h4MF8yqa`a!FuKiP54_!sxCSGI%L +z&%Qiy-w#E_e$TfVU*cOIg&PWHa>3w;)ZLY@1R_6U>-#f|f7@bU;N!kUHrw-7;Lzp* +z%(3tCllBlFjJ(=VN1wR=x<&Ae?$_#^B6$%>RJqaQ<2ZJU9HTS0n9>8Q(eN`~lQ;qS +z6?z^XGZJ +zu#2GG{y1a@rxs1>fbn^3n>-;C +zwIMQl1uM@?xVZ1o2yX2RQ&VjP5Q=i>!V(_^z +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 +zqXc_zS=N&D)Ali{Tdg6Z{z`Ibd +zH*(;W3UgtJ@%~406rY!h_^W;$wk46okXZyW4;+FkRJK%vg13$$hFS4trD~{lomyi* +zYiB{n87ep4P3^vHHnj_2mIhA4qEp4+3e=njzOD7s*81ZRB%DNXNe>nj7~a$Go}JIU +zU}|BfDA6vQ-fscrNZ-8Ddfa)su`aD#zg7BB62pQPmm@Q8Y8(UZn+uPF7Tu8s0}3`C^fw9TxA(x@XxH)yS;fF4!x` +zhH-=vTL_OAcE3jQ*la|jm%S&e35;zJ-wVuPgTtnU!FQumFXiU~g|A~7zFf}ETDwpH +zzR4u0c_(6_;Vi<)gGPvGgPt)8``FTSDe76%NMXVUJ?X+d_4*hdBRaF_HR0FRqI%=t +z4f_I@7GOR*b%b16IUAGa3fFipC@40gk(4(*mb9M`ci&X4*_5mHYggj8O~_{%e2^~- +zpy0o^_Fse^7S1_jef@0C%YYgwN6g;5Xx~kGK?qqlDaM6`gkE2-lk|En&7Zd1S>0^z +z{zQKk_PlS1>OFi@?q5Ka4L-)X!ocE4@?3rJ__5&{ERwH5dg@698`+EA(^zUF}K@5T~QNb`xy`neK}L${b1 +z={!d4r~A?kTsUKBGqQ5qSUuVHm8Ne)H}1uAi`kjZ@fZudhg!t+ghq3gjw{p)Wc$p@ +z`&fsP9e;$7aPZrnIdHGOs+UF;d~aSp-*&F_!|VExukd;>%!ZR5XjJ-klHOw?viSr7 +z0#d&9y{7lIsb2Z1tX>)mcE0B|%=fE*9n}7|c!5=oWVkZzsbuoc`IM6Wj5JGL$LV@l +zcUFyQN(v?J2_xlMLlwShegC_y3K9{YixiS!)51D)?TI$x%~nII?!E +z{Ya(4S86!lkCkIMkH0W7;A2)=*SY%D)c439k9n~t)Ot{OdHhR52~vYZV%1MJ3_1G) +zZ~U6|Yqcs5kyG!dlR`Ir+ZGV(zNWh;^vX2!jr!wF}>nQ>k?@9uw1!dNA+4azP}{iQkpIlIyQF!AGT8fQ0si +zM!b(o&_s)JPPHXJ?efVnJZQd_I@SQ^0)+<8BO>LG@dZrhQKEq2RquhzxlABk{+_JR +z7UBdvq7t$qd`tSXwO+WIe2VQ-L~!;%+2*38R33xZ3icBQWs +z^&X8QNn|wl3Tpe@*pBTxYSeH|4PX~nZ)9{@MYFK%>0RZ_@LN~g81XxH*!Nq$^)}o+ +z3ihgwCik5D3{f^PKgGom!}rK1D**JMBW0h~#7FuJ4orWmPR;l1U8BM1y$Fek;;mgm +z65-rb(FSsRfqw~1{6nl#IFZcj(Q;7l1WWIKM#~`_$ZD +zi;L*0PMRy*lkMkF!DqzX``Tl**BIM%>QaEo7gcBR8*@i?xdUalK!okQ9(i9|S#`x} +zJ6n5ktGd@WH})K)4cM{Q7UhPt`sinLJrDVbFg*g9;o5xYP{|?Qvbe7y12$iAzi~x7 +z#qhz_yr02Ly`dfyt5_YeMG0C;pseMnR9iVT|9vY_K&2NbD_Rd4Pc-cKZ +z`z9T`jV-))h2zTXX)`c6AuS*P{GA6!KIWqvP-`~VjmFJ#3a(DG?B`*_GCtsP@H-lM +z(0u6uoQ +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 +z +z+~=%W#6ttE6|LWNiPh&=XjLYAsrhE_x6PmY+pGMy6{O(z{xlJ)x^FOxh1m4i>zV(Y +ziJ?~fW}F>!KeLeL3pM>sfMb7hD^q8j8`gd4&*~&$McOSofEvjV4!4rC4ozCgY5PXB +zBTkFanMZXpE4BLJ|5^U526*Ig-wx+H{Q0-07kjeCgEf^c6pm7N@`J*>Ei|>n58c{9 +z1=6{-OLg3-0OnZB6)z?Ua;bs0SWt^$UUT1cWbNmGm +z?1=iXykEH8n52j)>45cO6~Ebt@l#gB_zlWjX(Q&YrMcdZdoJNQ2TJe=PxP50ORgl* +z`rNAT?R~Uf=^`PV3Np3G1X85(j0w+?sl1(eo4VZU-qrk*HF^vo&KVCj-HvvO4qxSl +zZ(yTr2g(4ok(kb_QD>d^Bz}OYWs}#`Z&ylPfA=E}_2>4{!bAG%zr4(Q3Cev8IAVRk +z_VY42?sqjlqH)IW74vO>h(P(9D}_|6xwF4MvC$0py6f~c1hMb)-`^Yfp~)>q-(lJbO;3_b+XtoOh-Wr(8I^BNX0r2?)? +zmxvIboUtO5jqUaWm-uN!2ps^s&A3I~-9U)d1TO;K)h!rb)UzzHbVDrS_NUyR +zo#h?{-0(Q^_@@E_rKON|;-@p>Zy(S5$Q=$JrtW&=uU632`|Le7^G}D}K8kf05bi?1 +zi>r{reGh^z+tM1>BR4^Xr3Eqsnp(a|8dlKZg>s4d)q@wwwY*nw$VKuS?9}C|qD{{! +z<@e~MFWW98Cy)~5=8)<+z{RdCfv?FO%55j?Yo3UDa=9K?o_U#;U0w%AkCS1; +z7V;-{No?YdfmVWrXJIeG;+5Qn_Zid9Jaau<9~M_0W;d9V8Zq^vzOUZ$H83eFr15*A +zW8>->^)ng3X|Oi)`O@eC%b<;|xvqFuzr)rA%!$+GgoryEM#RLyW_QoxN}Ud5@{$rW +zVo7l`h;J%dbh4uSy29A(jiGl*?L5Jr4TdHFfd}wSV7 +zk*?kz6M2|K7HTe4li_H54;+O1|Hz9lTl$^Fn|WSh(VVkds(*!9kIs&LgH3 +z_O5Fm{ZhS%XdL-6Ls51mZarlVdTC;U~+_8A$o30T>$-eXG +zTu*Y&!qp{HrI<^J)o5rMf2!(dKF0_1d)N~MhQ9%a1gi(l)&U=otd^*6Y`yj{`ul&m +zLWEpYLZ1EE8}TLwWu1FWS8zTVm&XNw9`o+n9KNP<*mjxq^5KiGaq$&5UVaVw3aijn +zzY~9}uJTKK7k-Dg?qmHCiJJE`~RL$|{dk$^)?#kyLXdXtL`dHPvrK*q1(9z;tn>n&QRFzPl3nq(oF5LSpqcn +z4w3-eGj!yj@S)9%iX#1qeZ-#mM36DojuBZ`zj6}i?i?Dge%(m|1ZT;%`8uKM7Yioc +zcn8bi;hA&Y`!(2J>4{fl00>BrKja&kk0h|i-8v7BRRg6SvUSfsZ5S^;^d25yo%`s8 +zM_;B3)KMwAecSzb`1QJmL6x9i=9BCYL` +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 +zJPP|Ny-_fUE=|GL`VWow$D5IK>H&a`yI>N +zwifKTboGpwerF=25(qY#L5yXC`X1SCbqH^?{Tb{e^tI!Xx>!t65sYmfY-C6nj3Azm%@fE6k$iQMz~c6K|d_N}18*;jvVck;$1a@)s;JQI0_ +zx8wTX8uP#&sd~M|UYe$Omu3Yiwa-2Ly@D`R&hb|Y4^qB}%(BzPvLIpSw#2Ddt(O(* +zqO@GQY<%&uA@;(%B?^ZcE%55Cqdi-5_q@snM&T1y-j)IJ?nUqoJKxLpIY;{BoYIxv +zd)>Y_pOC_8+}&`4&Oud-@1+er$hcm|^yE1=?vXKi-Kz#~4!---TfryylZ-V5$(zR$ +zmD9tE<~{VYFMw0<?_m$aKPhT-6zGI);=Tgz&r(*W1&}Yx;_rhr2P3VLK +z;5OFrQ={vvbvzy(V$GL*G`}71e^#E@E=Q(*JnguO+#o$wXm$H4?#VIgl({!T{`n?L +z4jil`-_7>BujlRxIq-LeHq3k~ZfYx}`C~Nv7%NlX5khC{qakxRbn1?{_@^*^?%lZW +zp_~LdXPSH10_UF77ciqk=ne^d$B^Chok*{W6~`=dSRROZ7WA=oqnZCWkO$>SQQrVy*S8oX&l0Ju4?AK0*rO|AxY+4VtIw7kP9g0JR&m8*nOa`fcdEJLoT+1gR!vE +zkU}aup!FC_$UYn$nr+}nC`bm4bQ(|34b!;riOumtMs_~eko;)UdzQUd{0IbXZNn`c +z+R}3*9^2LPI?RNf&&>FqTv||k;6SavwesrEnf&wio852eRWPm0^1j>ETbc5SfbQ|r +zw>kVeH6liu33@b?`Q=iNpKMq2oaK;+X>i8e(to%1((VY +z$#*|puQh@X=MlQ>k9>1ecHh2vq7&<&IjPx|ha8h#FHjqH^Ji>5;-9-fOb+DdptCQH +zk{`FwD3u&=J0n+Uua#I%;q`Hsjqu$CjmR?+} +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 +z<(~VvQKAF{B<@ORDWaaoX9#(7g9QOsXxcB +z_l$2pG%v9CuN{v(*j?Fe9fGO60E1?8h?AXR_>{RrY&40~L`ij07b}E|15#n4?yKQ?nidG?6T8cBY|6S4J)Bgvv@^WD!fP}ud++Fr^>3yFd +z<$OFJHWyB^sWg`C07;-vpUp=nodLyPL77n-lWO~8wo&X(gxfX{dG2RBwR7x##m5&P +z0+4|14G$ti*E)5h6s6Lw>WMAfGu78wZV0wtR(Kykj~d2P=yR>^UXSi-d4R1wx2HL= +zcX8j6fW`o?xK>=iddcc%6#97+ZL)bV58mFV@T&4O5UnlQX9tf!OfAF&`;{H$RI%~N +zzn$*3dZLY%y?Sfby)YwFuY4BMBvHpjMT665^6A^&?1O5;i)Y=i%^I5ur-jb#x68JFm}{tlb-Bi3r0AnJ`40X&hk_R<>fy0HLj7sc>&c#8auigZu99qZ3ib~ztR1` +zX@KWJKiwyT`y1%;*kP|}v+U6WJC}#mAuPV$NH|W1yE!t?#;qf@I`^udCJ8CY)ooV0Uuk*i! +z&GsvNKe%6G$5Zi#eRvmzmtFGYm40A+#x-tm1KBpp>f>^pd?BFgD^n+t8{Zprim~bZ +z-iv3pJxwiY@947~xQ8LXBCg=9Dea!DdD7?`iiuWU6qe2!!dR9_xZ$q5o^fgpk(;Jo +zi!J%=k5vmQmM(cKft8#~meergvR`)dA6Ot2y-A;pX+Ejzr{Ble!W^$q1^g(EjuN)7R$t+})w +z8(F&V)A1cl3Ie7V!tnS#G5JXP>k<$GlB?IgYHY#oS|K_182fG59=Hq?FkSSvxvbj9 +zAI6sguXlCR>|S$}m<@3%II#;Hr-C0htRhB{JdN{yPZ=PbODmuclQA<){KdUTZQqPo +zIkF0USHQ6$B#SDvZt`H=u1k8nSL4Fd(%H#hGRqxhe=P$uzeS~F86l(-ZR_LHf@TmNDkc|>vH0{IOx2Ma!ZEn5|zI;uEKQ^!iB1Kn)c +z8;S2RQ$=THg0Ecedu@iKfj~s9MLih`an7WkE3xl;L_VN8YRbb0%*}2o+fikz1!;q$MbMs?XD9Wd||qt!)saw5U_3+$owoR!j#u +z;pVNqogYa>Ui8N)bAiqpoC^9(18(dT!Oy#)-|l!lwwSyTk{9HOhNE1ZHph()SHaP2zc>v9Hg?TLX9MD`301Xo871kW}-m({~Hin(Hca__JKB1KTcdKUe3= +zqp)xgc9tWjZ%P&8VHtZ+(*T>usESV&Fei!o(ZQo9=h7T8o-Um;4qxwk(ttT0Xim-x +zyURou83%d;DTu@hR9?>F3$!IloAmZ{Z0A>>JiYj2!-=^1@E4k~G#OBS*i=b(Krv#)vW04o3ks^D98 +z>N>Vl(c$5PLZ>6Y0j?8(TySQ&RS&=LO0KEy)xk(Z(Tg&@33+T7C<}1pC<~T2P#Jtd(aiqK3s=(pN;T5a&n5UWs +zu$a&mW>2sFR_ +z17JYUX%NG>O)s7tYv-8%IynFC)wsb!wO66_-bi_AChHoLgpH7?4i$=l-4{6?Fraw9 +zvs}gdnWr!S9OHH^g{LA@`Cfb&bx%U);{Xcxcx#CFrIg?s9d!kxz4lV>i(F@qF^A%EH$(C^8- +zFCtvIqv*5I(&uf}unj{CSjm@j{fdyoJzoRB0E)0y&D^`IE_dg}Dm{$({=61=8Rw-@;3X4qtILzNxgiLVJZm&N4${5!zXBzOScriL5AQc2j)oes7;B5$7``-l&W# +z&}Q!3b#JdfH8^!7v|}0N^WXjE`ywpOEEPZgWss#gdbC$X=bWdaaU>}t_$|S;b1R7L +z?m-RcF$GxsyszM#P9(zkDh`H5;;Ci?N`;)!8%K@~3>C}?2%5*h!O@6$n4cOK%~E*U +z&>G3N)OE!c&Vr*ja?8nn4;DmUW<1|S94Q&h`KFd#ee2WqHF+I2{^c@3zdiW!Dd+KB +z^r0lKxgGTQ?KaPuy7d{xS`fvQ>pfwnd~HzX@^q~ +z#wQONGTrOaNrNc>_t8t6hqyHfMMT)<0evEvV&w!@gH)2G>-3sP1mC)~Pt~xqa>P7@ +z87-W{x7OxZ5j@H|Hv-hIKLnf*b=ID34Sic%Bhv>LBo)an!rt>3c2zDYzC0LF^`eWf +z3<4Ox(=NCI8`<OVHwo4}{23Pef|JlvSI$ZaRpj+Q`-&7AHlICMfm& +zyzO7Eu*(O0C&&l}59pMr0Oe5>kQ_?cg0Ndm<>}>VFBxZ_dk!P-!!^e`jX0#+=cb+z>RHZ7xMkLexB4Y% +zK5?&j`c2%219hjlDFWlkkH?Lq%l+luD)hkRCp+`eWWxlSN}X`W3c|WnsN9g6@lD>e +z*}4%gE@f#mpHZ?y(H+TVj1eGRLh>Z*V8t0o>hP&Ld@Rg-;xnJ=&BN9Xuu+eip4cNp +zIZs`cL{JVZ>p9a}RdSoSDgs_Mg)dSLmEKR)mA#aYjTL(X3uuz-L1UtMya+wxkHzp1 +zKka~U5|~k*T6mE4=xp+Q)4&4xc;!o(c|Q*&l+W7|qG@CkDDWB#OQ-41a5giK1v{1pXnNYJ=vxw&eZ|>Mk&yD(eP(PdemoN(-h@$ +zYz=^F@sg{Sbu19b+i=raYj>OREaSvAtjp)6e9zH%oV2&UNgM!vp(XV)u0!8b0bfgS +zk1(`_eD96lgL$D(v$mMOnv)tEw73ulhV%MKdrFPza{4^3vG)9M>c1MjmjLv9jNZ!9FHaQIB-8bJxeUDk9E}cnnc*m0#dh0D>nn$Ud)qARQpU}d$ +zX~po0J%Kis5s{z0XxgLMCqczaMxg)zZ7LO;s_C?u;Ac6JpI=s8sCyk(*Iq2ZJUg&t +z-AySI^8)22l||Z_xq;si$T=qYw*8F{1Uex +zzK%8-rIQxljVgL|!}2$=?JaG`=}EPTui@vdr%uWC;~Dz~7D)0zdLl_A?%q0j4-;Q) +zzZi2s^aXq@d$Q0!)8!Y`CEmJ=#^noq=_``YM@mTZC=hM0E6t+_wpk2SPgPE4tz?pE +z11pZ*p=CcPIn}52$i-83mghXh??7I-$GjT)yj%}hFCN1%vT{;?OW1Bo^|7g0bpC}0sV4A?v=?oYOhTF+;5b|CR+eG@U^ +zb2CxSOPY3wZk&y_+?N*TY65+;TKD!-t=!&hWkyf_>A5@SxW0#T?^CX{E2!}ep_id~ +zLZeQKhsCfRjKtp_IrM*={*XeOoJQ|d(!Mj5`;_fxa~k)E$$q0=ALLNNH=MJ&h1pA! +zW@L{18Iw%8TMi2i#tN<)6|&8|aOBEhiGDfx3e@Cyk-N8`L&B-6{Qlmj=v-(SKek57 +zrMz$!U#j~Ca?ioBm$1%m1HLscT860&qtdU(ID%QDV(QqwwAHfmd76GH5+WHm8sIW( +zo<|YpqkP7xZov}OOUmMzauw&AZV$|Td}g0BEhWD|irRA+=5BAKoF+s~M!pFdnpr16 +z-v2*0>74-43yl5brvZIgcOf{dlUQ2j>-5aNdspTglrH^_gWLz;G^%@B&b(mn5nrFv +z(OA8GgSyqViLqaH^gKg&XC)jlNKy)rqV?jTdf1R_CwF`H8zDfRvG<8=T7b_tA4AIJ +z8(9-&GEeh(le&$n@#O#v8k=5)^}21GA$aEfZnFYI3K8%)GXzg_KJ_-7Cs@te&Nr{7 +z4{F)Hdqga?`m1#56*&O*>Dz+};7WXFi(YD@K_!0_uBxnnD)(WH_=yKpZ;gS=pshbU +z(agMWi#OGQx^8z2fTKW&zR`qlk2N{NIu{Br8Ax|03m?ZC#CLdeTHp(|aLFdmJ?hf3 +zN_poxd_$t)1cSOF91I}z4e_C`CS~k?ZWc9OUh#GKcP#++l0MQE1Ls<>nd4NdP1()Y +zztRV%d>&*f*>N+bywKq456d_Tb;%fc``PrMz#M8+IuL(WMejrVQ#;2(%ZU +zS@_8gpmP=dPCca;D9&vwn}3oLo=oVs7Iyje%b|zI7vRuz9=a5I*VvRl&*8jo6^?!b +z4g&kz97LnL{t?ttj-2C1U(&oF8-ie~0G%Y)fG*NBsqHs&As&r1AS%hZ_OyPE=Rus2 +z_}r=QtOv0SqT;GMLUTdgmq9xv=k0A$2qP>lQUSMFIzn}3rA+PUf+!rj{F`K{nJ+imszOCkT%vGjSx&A(0gOrcxKx6Bp**9!^#ZRFns= +zw!K8Ik{P#My!^^2@(Sju!Bo5H*f~>^sxcW>W7j=dOxo$3K40NxCt$n6#YeTaVRZs+ +zcI6K9w?|W$J^bPfIsr)SIXm3q5 +z5`6_~_V(sugIx=D$6=>O)&;zJ^D*FYVrqcuW5|%nIZk{A%kQ_L}ogvEQU8CUjM>;OgF& +zj3P+71ZxhElPrU!KUS~KaqFAd@`ZA@!jpFXeS +z@0j1C>^5BkZ%616f>UQ-}T6_+c79I%FB#!CEIo<(1xq~I+PE%xL0R*}T8k~O`NK2Q)t@7r#T!-oWC`v}Q< +zuJvpBBLDUuypa(|Qxuow>Xi`@6o`RMJ>Fo0j|!*SS|`ToY`g%bXSsmEhFnC`=5LSp +z&)4tXD+wOHx%nQ+BiBY-$FD&?K{Y4#z=h^(@EJ?kPEJ6)eA=<4E;fZ5uKQW!EH^$} +z;MqCk^5TAxDbsdO$3eJ0o)xEXcKqzstd`?!tm&oF_Vmp(P&8bnPaxvng@nsC@Y2LL +zC9R{Fkksm0%WXT%4%=;undINhWp!3~r^EF@Wy{Vtq!tX-+4`tZ+Ff9g9YOmhqE~>b +zaOeXIr>_|3w)WmYWj+TMu0Anw?^hpks7x;}Z)>?hYxX;?DGzUliTZ_<+kwW8P%Bx@ +zqEh{t`I7NmC%|(!7dU}zM^{YA53lJdMX;>V`{ZJt16+?2eC=izBkavlybb+Ppf +zYOH^qAO}rNa=#fm1ofd~ANuNhvK6ldFnP;o*01Lt@#>nsQ|m?V;|RKNZ1s6$f8UQR +zt2{;SpT$9@?IPtpF1uH4W3~Id9_HDDV=IC>o{PWU#0rMS@6AQTa#ykiJ@+Oziu;Dvzi@3nk39<;QoAJQ0rKFt` +zzuvY-e`b;Kv;g@a(QH@h{ESRLZ@bIh!n@Pe>uIs_@^)p^l5sl7KD~q$b>107H}KWd +z$KbZ;B~F45bBi;Fpl=H|k;?)x>*YRuXAU*j|1Bj(CRs+fHemC3*fbXbG +zoLhC4L66qaP+hXIr$)}(DN95Gi0Bxf|0+Ka#4qZiuv1>i%~G&qbJ63QiZ)ru=hEqM +z#n~H%kq$M2P6#(ng-Jx_wxeft8eMq&;q%RskRlpn2wV_-+Uth=d$p3%u`$fIa63=F +z96rf}7o?7zR;J3l0mA?0K5Et8bB`U(^MvR)1>2>iJk8~DURLL~U~=EKx^8b#&3Np< +zu@iS=2q5I9+HS@iNxa0?52H4yoUgdhAwDK;XHo3J5F21o%YI}`f36SeQ=))?c=e-SFT{&miICx=U4Ia +z@HucI{E&Id%Rlq*>p))4Cwrq&Bj^Nn`)PxK#c$N#H(_tl4)`%gvqsbGbpLu(1cf+b +z9|94=^mn+e)kM^N;Rc({Jh^I}VSsdXwJGAd9{94e6Gy5jK?lwwN0IBW{@KQ8@VTBI +zZ`0$$^{~-lna@-B1hei(nL(hZb%g$J_I?&l9Ya#(S^jCZ4z9xxQKWw<>QLmt8lK +zhT3n;CdX7AbSB-6%)Zl8ts_`5E=bu~Wr +zuC|xb9{OtdrBg`J#FA!r`;pG~9_ql&Ix2g7XdrCI{B6GoK0;4m0X3$tEq?=i%M}J6 +z;>wOnpH)H~6?9*2)g8&E@8%>Q(IlIrio0bGnrzNK_8^=Fvw>6a(rCejhfT +z%JO%#@-8kv%$Y~WZ>jT~=)jkFisFeneKBA(IKyweMT$#w0oCC%qr2Y_<>WQawbN(N +zBT-;!cOH7cqI+KV<9=sKIQ=PTz&6XyohHlw~66$U%ii1)mN_c>Yj4@b8_w(6QM>YTQ<|_VLfAg6{-;%)CRWbuqqrWXV42 +zzj{mfw<{vQ^!NTN#8PQS_=qmvl6gYY9*Q=$_&R)^jgrP*G&(1n@CY<{#&@|q3?A|~ +zJ*n2A!00;;mP_zvvQ+X2>3D^ERT2xlx) +zj2}5&-Eaa~e?ssq9+-%3XUx;)XPyG1Z#fyZ-SNw}vbP?f0t-J93Y$|+w|3CqpIpfn +zIN^;(^H|)262MDsR<2u!y6R_b`$$enw;P^ff|(~XA-NOme)becwjb4BbdR^89rn8B +z&ZS<2do&YaKA*=>hLdU<Oqi^Rs5qoVM;d +zkn#=c^WsLAd!EFLxw?f2=j(pH$ndg>4_l@t6 +zHJ6GsPMNLm;6(^MWj4O +zTS+YY)J0mkQ^QMs7^Gg!&3l;_3^X1d6vO8*8R7TClx7`^1oXaR%ytgBPkz&U57H)) +z_Vr7oVv2|H{gA16G1dq(*k_F9KK-e{vsI_c&l75xGp+Oz4)^<9_bHH3fwUqB{JgG? +zu%|DdRyf=lqDf0nWEzg2OP3&5m;9#tNW6ACs0AOnH+>l{)R`$`v>EeKjE#* +zvs0Q(d2F)SwkR|m`M8Gt{kHCjdk;Xv!IKlBVXlMG-=#hW~ +zYR$I_tNc#y$w$Y{_Y{!flNa30-+3OOh6BgO?&E)s6-o{H_oZb1W?DhR0V|aGjl4<;DnUrd!=Ja?G`*)50D4 +z^IUmsAwxj(U2rn@i%~G)Pbq|58NJI_#lrjvvwJ+SQ#W+`6v{n%*!DrD==;V6seU=` +zaVo0?aBP-~SH{|pJeB!%|JCp}}_69DHifmY%ze1`@wLuJ+EPPWLUPK@2kg1LG3%vjgyMoSdSdgQzCz4LX6 +zU7AjwQ7DU$&$Ok5gqh?8$dvQ}sOsr^>3nv&5q(7s%^>RPNy34b&HWsXn*BtU#+?iA +zu{kQ&*M_vDUzr7WD^CgiHBbn;yBCaDpBZ#A)3p8 +z#(ZpD&F86!ga)s0CvjkYkwx~azIl2*4dAJ*P7}wkKlc0F;3=9>FJOt@+ms{5VFo;G-Zy#gzKT7 +zC-}Nf2W>#n7GCWaJVHC>mOr7Acr#vzk%RKnH1_RP1;ta_)f| +zqynYOoP9YjDjU*l%c0$p>b5zG=&tj<0gGcKbz&qkkH=H30!P{Ph;gb4-^96xADn3< +zW8~YJ$FS<*cwDW$6npzXDKe`!3U=@gN$K$L1nvxk>sf-n +zpHI$)G`)#L+T;ASkB-f;%MGqwA`Sg^oD*u-F%F5Rnf3^OElAM-B-5veXEbYl1&lA7 +z9u(tozFv;N2j<>uk2v&d@_wm-Z)QXnK`#hZSN7ND{5Z0Dg%c4?sFXU+R%m#3?c$`Hzw+Or&I0=OOy%s`<|{xjWi^3A))T%tso +z%lA6zpww)R9sgX#wB|IsHWUFe6FwLPwR;%fE;>O6Tg|L0cwK6|O{wIZ#5pJ#H0slY +zy0^oH$a0<@JMUR5Eqowz$LkpPt_1ki_`6@_v&j5*+dX#ByEu9Ob5dc^ +zkuvBremqcp*bul8;o`L2u2s5kQJ*KHCpFz+?Yp9gOc|xnc2a2nnjC$_ZO`_Xs{B^? +zmorvu*W%<#bb|_kbUsp1c{G{sUypIU`8ZFE(th#8A!*;~-zY;~L)v~?^pVZ?tLf!} +z^R$P9a>L?z5ApsxZgdCY>q5d2-?_f3g$;4HZ*-a{HmJh3sCY4{e#h~7Txft2^Wqoi +z>grhMVO`yaF86fZK1ZVj;lqyeh!id5ZICqGSvzR&55uuW1dlVeijWeEe8#)I@<&fD +z=c0dg +z>TKT2w;2pb9}MxIsXW@zX~47Lsv5Pc#`sE(M}nR2(w!E4J%Cwgq>pA7F!uup#TFBi +zFOZQO%8oJ)++Qg5JKgaWi1?^$izDHyZ?ph(zHFH{59`TQy~;piY}E9yU|;b&S!>j% +zN#DAl^jzo2_j{iI?9cpirEetHrDlxEH=!dT;W(=k +z(e?ty@7`q5;{%_Gzuys)WvnoH1V!37Cwt%&5$XB*=;S^jd)4O${wY&8H;Q5)QTIYs>$O)7o}Rx8uQY_f0@h( +z)apHPh-eqpvJl^T{|d-sLWy5k|BO7bVB=)qDUV4ZAN6wHGclxh1?%`*NpR%M_zKE( +zKEQ_r0&Xi?S_iq|V~u;6k^KSH#TWqcCnw@tAQtbqI_9caYGy``AEeO=+fb1mRUmh8N+qf +z`H}%u4}SMt^h*J`ZoLJcKj+-<8gmSU0b+EqGbWe=ia*VbP{0CDVt&bBSH5$1EwRt( +z>R8Ho+VOn;7X>4v-%UG>C7B>EpQ2qs7$&-(yWgQNnFa3A@*6jxY~xY$lp~maf#S;$ +zA6p|bh%25#cxh_FiKb-pJ{bVWc0jxH>MiCFsyznll|?>xx1jSN@@r?0(bL1iO% +z*Z3jVtf0o#>SMLc^7TO2!d#@*(gjv@o5-TB(YCJ(Q;^;){1d5c)B%ok9PoQzshJc$ +zZ@Zj3pS1$x7yG+7W>3&q?~@guIXh3B26>CQ02=O~KP4FNsXn)Cv?OQ?O1)OQE$G|S +z+T0eUN%uVVL!B4$T(s*@Z{2xcgAr*0`%dIEDn<4J27#$_ofh7XkU@?>GJu0v_yn?l +zaXX}_G*$9HO77}aKu6q($t1<&k3OCj4Q6eO#^?UQl)bj+zj{ +zcgv88w(zLh+xWUSaQ_7|I&)hwv^ +zK88mho8Br{={fkssrOZ%BO2j(w{A%F>1=J-l3Nt@1xS1LeUp<;!B5G%X@P!SN~0Rh +zqErPxJyP!P1j)x!jB@l`Iwt3Vo);NrFz73JTLu|lTPK&aDyl!S-UJzzvuakITuX9Z +z$$`=ph-rTHqW|gn9qngXw|4V$B9KZq6K6O%M6w3&_h_#!t6yI`_PBf}jZl~Fwetvj +ziq)c$+6f8Xy^zqX*9k{KNskhaIpi^#x59~_QCBy{Bn;Kw8at5QWcNh-#*|)r3&|t` +z-Gy)AJSB+tPGH03)8jj_p|WZIt>bvy=`D+UcU?W0- +zNVsP5*qI4kqg(QQUdDR0L*=BmTI=CdOPmIBJL6;C@&(5D=W^(n9)*VT7Cp3+oYOWu +zZ`-qH4An|eT)TYJ&*P#`A)(m=tMhHGslLIKs3^g_Q|IeERo+KWXCvKwmAeiB-nS*M +zyEpK;1eXBc1`-7qk3Q`hV&5H0)=)C&i&>RDQ)l$8ZJHPpW-2WGM#Q# +z#r?h`-oQD^?)Jn#K*)I|USNZ5%BOemcm=qA|HKzOF;>NeqiAKO4jSzJgJPv7Im^)L8&Z%Z*n;_WRF +zKKNcIulpGZbN7cST89n?RiuNdWQv@P8H>7SJAZZ}(C^Gi9pJ|F38e}-``HI<TsM;<$#eK%vX<&y-5bLnq%p!YsJ`-3A_` +zFTd|j9_y!_4Jrf;*txH#eH|JFyk1SGojUp)63=}T_T{dYkQX0F*0^_R@_OjDii$r? +zdDbXv-MAzw(O~FpJf037!&?`|X$gj(;y&Vbp0d1oe2MIc>Q~fED}dgk;(HU#_Sx$m +zcaQCpdt>5J`t)b=<%{X6UoyU=J<^hUMPp6RY00;wwyTII>2O~i4{u%19c0i=&R|3? +z#RsAorFJdP{&qG&)*{HsoGOM0>Ou{f*uwC<$`* +z;UiB0uDIK)+&fkGynnA$jexI#e3mi$D4c`IeXk(WRcbR7!Q)*g!Oz><}INLQPPF`AZ*@?Gu>O#GZUM@N-=7v?rm5PS`ju +z9rudN86Vw#baap8ZGJ$l*|Gf!grev1BxRzEyZ3=o&(`gkTmAS>zWRQ7Z}g>>0Xcl< +zv*bvwY}(4K?_8Of5Mmz_k~ziv*{4vIgZ3LvYuc~nw%^7-u?e@dK1X$##%W>cqRv99;?vv +z=(nnq|3s^wU(`JiJcq8r&E|)uJiZ+w^?1JBiekB`Dv`d|_71JiB6=m!XPlKm2WAuV +z5yGkQ$1FcTWQMYT_IdUh5});yh?h< +zHVMobE;x$_lqxxu3dVfO*8dmsy}XBNYsi0*Saj#0Be-0`7d*^n94 +z3-@C3skn{VNBp}aQDUM`9J*fTDh7JAWPOF)zi4$NO-iKhJ +zkE_kwP&j$%RZwMnh-dn6_3C(+cMz@MCSVc3QCDN%~30H-uKiZ|7WPj%w;8* +zqgQTv<=1=LdG38%VOOyBoaK +zY!;skvqvJV@Wws;_-J%B)R*jd?L79M_wevT6Yu)vzCyoqEz1`3>vBC0AorD?$u7j` +z{Vw1*f6dk_SMl6IyP0)SOzn)CwpgQ8-3RTA`_yrSvEHi5#aA%#pQnK^G2F{Uk3;M3 +zxo#|MYMh*(m1cAI-pL!V^LbgHIa&vlwimj`!yXG$x3_ocF@cNBEQWXoyH9<0VIuOo +zL{m>xkYA~0Wwq;!W{;}%A?@$3jiEUnEh$kv?`Jr8KZ}cq&Ouk4xX2)H8{GOVI=>j< +zaH?%VFw8ej^O>_8kTRxYbQ&i5y$@Tzp&qTLiWzo{pUOw!_--ABKYyy0PQ$?!bXCAyvTq)+S3U^*khS8{gnDRb_K +zb*M=}t$kQ|QH%Q))~M?_>iqr(hn0LO`04!c1E`mH_)M60?`QLbk-$gL{c65vpD$PB +zo?|kG9-BSPNL_G*qWzP{ZFk~5hSpPdwdg{Wpx*M%Mo@3G_D +zO+p!L&56ynejkjf`XuJtQ=od+a5IW-f=zHf%=;Vf_Qu#=frE18zFAi1K=yO5%z!ap +zqrpI_CymDRNX$MCtne7d;8Q`ECm!$2%kiEJ4Y`ciloP*$dZX()7`FlWafA!E;B$7V +zE|IIC5^THjr6QcCY2}tsAOvgxY3!Mr2N&C4P*0kFDzfpjSI$RX$`$VT33_EU>z)U$ +z_i0>9xWn7OzFpDpB+NHG?h5eskp#xkXnWP?I~kN3St2;>+bB--_GzG%)aOEkI1@$Q +z+~!p06*mN5tYhPSK4$~y;eYx`g~in-j;NHQbpyLygYF>Cs{;TNfzYv=_Gp|AVeet> +zE+_Vh!Dy&Mk^MHoeMMb9o9tH+eXdwF_9V}>uY>Q)quTOG0x0lXgxwa<%&Jj=CtvOT +zQb^B2up`Tp6CQCqB(X}-C9H>mYJfoRh<&I|qTi{$O`^9f!&|A8%V3JH6bljzU9h`S +zDhQ^o)+;$Or9MHyaM8=0VO`-Qh-#F57jq54!a-hnq(Dhw~Lw~Ob)ah`_ +zo=Vd6BbSFCL*%%^IBt=GQD#*3eoBsvE%8nBj85RykMaBLqtXb+*kkMHTO9%0hST;q +ze(doh$)o%=MxFOUO;v19F5wY>^ySd)E|U9Y!T;xYW&|}C+MNb=uG;LA8|&)%G(ezH +zgyo|l6#!$_KqYiW4E9a|*=5wSU+c!gp +z%jRv^)pj0cMj7Aed2gBqhve#7>2*5hCz9w5&4k)Li&@7CWisCAB_upibHc%4uSomJ +z9SEujopU?w@|UE_wht`wbH0*m@+HpahIA$mhTzSx{BE+Q29+{@x!h0(@4}9DGk;zB +z8@uOxaYzN^1XmqE9~eH6By7L@9XKSKe|{e34I#H*NjYTss~41hXJ?)+`rLP~R$L52 +z#2t;BOStuavuyU-6~26^<$NsQ)j8d5Je8zP;!=Zvk4R>Iw~Q?kN?cP~;{MY;0qFFG +zn+rx#i>Dm9pRGs_54G@6ofDn|`)Z~dJZ1pU(0Sl~IT%5Bd1b!(nD*u66~zh0>ujD> +z2Sp6D>wfn*h7)hlNj@R%4H+XNv>kY!Fw^yWV@w{6usx?ghYW*hKD`&%$I%4#0m4zWLA{j9la-wGHz1dgE%K4p8lAm#@jg9hg|7PiG=| +z-h%I)cN{eQ#+?>vn0saV_qnSy(fzY@dv(ua;?|Js|53G#$mWQj_ +zl~D38%LOw_8~o{5c$@2$lYV9W5tFQ?oJfT@D6f8DwpEqE%-~xd`}tHTow?%)^DXOm +z6_B3xp+51(E49kJE-OphKD>}IF~KME+UdJ!aL7-D#SCs=BP_u{mbZ;Hj;yIU&FE2F*ds^slq3m>$cToGYb=ifH)H +zODx?lF?B2*eoXz>9UJ8jX!JFbbD#R1tV3e5?m<#- +z3!Zc-Rx)HZ95Z;#_4BLN-4a&cuZ3;@+0}lwSOl9IEiYakdU&bFUd^aTJ}Ojn38ap716GT^#s-2wuvP9j_rr6pH`6)D%B*-ENY9H>~nr^+!RO +z{OY~;@OSrqzBq$wP@j#2ho2f-wQ^KtF1Rq%JbGRtpYw7~NfE~ri`lAjBg64rpzr&% +z&VXMs8YU7bvG<#f*s+d>Hx|y4e3m1N!4)ymXhdG+@O^$Cxqdwk-5cJI%Id*0c2YP} +z6C~;|-g?8`2w~g^q;PR}F`z_lCWsi&e#I2v-;AgT5 +z?64x^L;LTm#8X0g5$fSiJPYP*ws)p;n1;m%M +zQzR??iChtNb=UU|Cmr&nRwULk&6&HOpBho*oP`F2>qrOk(bJte_KNe|OXnj!{K~g? +zg+D$?aq!c2=@;`p`pqDIp18=;3mZXBh_#FlK9F85Ip5{Gn^NaX$Me$FD?ydQ7{T)$ +zJonaM4ZyuPeDTT*t-wvRa|&(Pk2cnu$cI880OYcE*a`f0)p?3*?nHu$2k&=_Kk`wf +z{4!-cjsjC7)V;!8c(Pl|r^4_MAIEtdl#|5-zVBgoFQO@Ax6phQ*I1ROHSWT3eo`m9 +z0yurr7t;hUxoD?}#W4&Z3A(N%eqb`VBm2$6z3pE1WgxCT)GyftWy@O$V{Q@$A1^Ho +zYgvf52SvJX5i|iJ=#d~ps*RGTRK({tup$vUr8jc&s~8E}>yB==ci%3DZ8a60s=kch +z0spP1;g{`*kZaK{WAG<&$3cKY3(x|onM6a +z*%A+3MI>|hd@%JX4m;LD>ct>AQ; +zrVJS&=#si)UXAtdrk@I19)64_746!c_mIR%<+F^VvWr*ZbOe;I^d-z)!+UtE%+?a_W-3znj$W+1H>CM~xkh*M +z^7-ikO20Eext>%I*^6`5Ev(SvG%d#*f*t5jSSk~44)0n>pk +zOk=PT;)4sO6Yxga`8)xyhyVGltE^1uCTvKaM$rE55TNmahd$g*L(IKT7Z%N{*`Gzq +ztymRO%N_xEA#&3Bz(GEYH*3D6fPX#k#jw)QcIxhi_UywFIXd$8?r +z))UH)7M@Lo)iI>mUet@Tx8Fju;AlPO_Vk5U?%w7jI(xW{eb?_}sKHUZ@>Sn5^*uTJ +z)O58bAK|D3FJWHY!k(aRjlTB9g%iXhGcZZ^{s@he;7S3W;{UsxFX$Zr`4qhJv`8S&0+`JC3Eb+**NoUwscDU93eiN +z9og*pP8y;ZPAWeM-AQ~V84>IuP)m9r@4FSCunh;4;>~)IwgU@z*Xbi|ELt>X%6$-| +z$4g&j*M3~Jn;#aUUNbS*Ygl8W%AXkMS8Gn1?p9pOPSGd8?#`+28d_x1PV4PzK7{7; +zMOmJ=))T&bzWn-pt}@{(d$+y_{(Ii4TIE|FS8U%Nf@B~*nK|mTXitq?;JbEr-!`d9zMuHKET&@wIilE6=%xK1iQ}Xtqq9RpN>V^%A>!~>vw9Xg6O~;%z@Af +z@m4btd6*gVs{VC+#i3AwYqe(H{tCNK*o$=GAZXrudJO^2Rrg+LC4)25S8jAsr2F14 +zZt$P@)p4zt5aOeqA&yIKI-me>2Oh04?tCj`GPjRrign@@fBL)nPKkO-KH5Y_ar{hW +zpDzw-i`tm=2Mhl=L`W5VMj +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 +z=zXp8kvTPW)qx +zxpj3>(foY*&ovx^SCj3*GtKOze}O95i|1?M_S8-%(%v;{x|G;reFN~?TD-Spx3+`s +z23_hsQSeXCd02oG4@8|D!Td>o>2W{nb}Sz|KXo2=H_8CNWmr!PoSI8{nbd8_mGTQa +zmPV1_0-U#&`Fh@YEh4^ADDyBzkkf+?BFl_LP$KuZ?~_u=+9}-@NpL~eg3dq!L3cPn +znW;{)4=m@wV&ftq;qNZ#GLY$X-n)eXnV1nbI;Qy6S=pvg;CV144J9YmzFXl>On)}3 +zS5#BTJt1)XC!~_&UImNqquY3;oWx +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 +z$4f4t38gyOsk*U87*e?&>-z4?8$}FfuAQ@8 +z7LP4f!p0kH)1flC@EVbPr>;lmyXAE=Boo^G +zqkqXQ-$b6U;;=9``D5%@>;ju3$@GPso`jYo@U$dr+TppXqH|Uejrfcy$Z4rtf=1A) +z4JN%1cY3C!ecU|G_E0p|RaEer^ORi7YnSXipDg9TyNE%_uTKwtN2W^Dd-vhg2H}kb +z(Rpfg)W#;$Tp!cmQvhKXlkwOWkvnoW``WGYdd+3!roMi;Cr3vgh2uW`lu2w-N!*I=sRFv>%inoc(){8 +zdAP>8b6F)n3&CTW&a4tw7aoVPr52Hct2N89GJekiPyUQx>wuh@Bj?e&C)R}av$Kt+ +z8-yd#+XR5xoT7nzA6^$)!j~JopJn3{hH{*T5c8%v6+e9j&bX>qvY*~l_8ho*(Y}lT +zx(;LO$LY16r<>1?(DHVUyxZ +z7NPeE;LG}`wn%*!WiHqwu;01C#5{h0yfM`GUgws1x`7{s;pmxA21IW|a#PVuUOUoH +za@Lu?m-h3_tGIQ`U>@596S}xpMIE!wV|$-vUcGhw-JFdrl77{f-{z^J&n!)xGZ%dC +zTRU}u4wr~t{~DFHZ@b55mnCpicf{t_0o_nzJ-5!IK1n^V@qrrShJ42^LOIq@;OH1| +zRh?Zp~75I5jBYj9kO9|YWs)7|s_ +z<{Uc$UDx*;Hzy=}tRU~9YY`s*yq9)Bq66SK93?t~?m;3Q6~?INXuVauuAmSnR513V +zp_;)0JW}ds`BDUP=7YFvwcovT`pk{=94sR&)SeM`eR!gBIoCp1Q||SN1E@QRaEG8N +zi9vyBjrlGGSxe~C77$i9xY>Fz +z5lDf&nffZhIA5ld7PM9_MEAO#4Eo|10qzAk%CE%V_w~oH0!{Va&#kCtt7Fgc@b4JF +z?%9Ax)i}P0U%ZF-HGh$Be-EmrIM^Rqof1l-e!2l$R_)Njo_*k=@4J4twNkYGk)nF~ +zX%;w^tIyJSq`7I2Qy+RvW$4Rrx+~yMloClZGS}z2d#UAwwN|tQemC}m^2*Hnze|Zz +z+NpxB9)84kqmAylx7Z$6zQOki6L<{44qqc57xjcmO$$K5*C&M>UHc%$V_KmP#WFJZ +ziWi8XqKqv&S@vFoPQ7uNM#^DiuYa~;kJG=lP2eh!t^;*2pcZ!$(2uhxI=t^H2CeFR%AWr~7! +zW4@@F_G224$4Ei-PLf%201;=Q^vFr8;vwVdPP&XKi)? +zg#79LPFXBv{*n-zz2`km{Cj$UY|m+RGEi>1#E21u6#}1?8T9+Q*XDNbk>p2Bo-%Gs +z7eceN%G2`l82}^hoY&BScHld*hUABS;}%?G3%$#8e=@ws^4bfM~0r +zu-#rLuH)aEJNLxhZ>p<4ckL`R<5T^#U8!`Mo$d#G=!##T=~Hy*eP^UmzH?n~Fr`k# +zCJ^|w2ELC^5m=d;yTIYKuEev&Wg}m3?OX{swl|`QZ|)qp(VkV+e>ozihmK`i8juED +zc>R#WZrB40+(0=Pl8y>+`Ebsoxg2O!6bpLoc*j)d@IHK}I59jYZlVYK>J_5V*_v;! +z0NQ+lj{w-UJU-`AT`w_?*9#imZif;>`{aNvYH%rPTO{oKbsaQxNO{ +z0rQ3E3b#jcKnrT^3mv{zhYCt%+u2T*;51k}Tqvj7&0l_I@;f6JW&<@!)adgpj#pa> +zmvCC2ZjxQT>9BEQR9NM)#?NN_+X^@(G4iFkbvjrMO1?fz^!{$7?3Skn>vHLw3s3I7 +zKi!-sDfDxVM{Wb-tMJbggaBathPq>ynLv?7o^lcu`GUFblP|e`?lr)v?=+kpaBRs4 +zJ*3)V`3O}b(4{B4FWW*{r7hjJzSOpoTrX$6SIeKz$|>gg-0TshniKXEDjSm@skL0P +zOEg{NMR8cj1&0!!kZVDuRx8J_QQX%~kn1L49f;Rav2z2y+@reIQ;Gq?Pk?HrhzM)& +zcd-s6yYVyd-M^CuQ50W^yV*j5rg4;v|HN;LgbZ775uXzWefjgVP1;4sr^Pw1m> +zE=ykDF@vSsiZizltI7k{1F?0`AP*nYd#GD9O>?`aqL00QT4=MR=)895bA82u^w`PV +zTDvs|Tu;5FPE3wS_X_JAfD*zC9Dzdz^_mV~nK^ywY)oZCvW2~?k%#^LRvEb>b>EeG{}QINR&^BYyrw4;}Je>-z*~2_?DbUXfjy8 +z6vKFHeA`Usj8x?1@&OWt?d3ib7PI4c{X1eg9-r_ynXe8kk^CTl3brIpY-#vi2mJzd +zAOGU1d1SGQ#t3hh?{_8S$?XS3m2x_L^+?NQ(fF(;Fn@JHp+n1=%_Gd-IQMUXl +z!n%&Nx4ix{+~TNx!A57n5W~W`rf)^ +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 +zM<3N1Y<;PVsV1Ui!iAOP^Ss+mz7xmsQ +zJ&%Pa%MO7?ru)67PTqZT>DWErL^SfEUs(et-q(woyIdER;LcolQnOx%!Gg47=(qLC +zFaT_Hfq0yA`xa- +zwI$AkgUevdt(MyN%iTQad`u~{H5Tcg9!Ks)_bi)xX9g+xYuUDT>@x9P3O`l1kFnMl +z!~p(r)B1=|9sKghW`j-)!-UCqCGbiI%HD-qmhUl)?jQ@H!<3>>Zk_gS!?`D)Zmz9F +zhSJ&OalDr}XIVk-H;(+Rsb1HxMU_MXzh5F}o2BR8S4YlMn-%B2-y75XjTW)j0W<$@ +zSqiT^_@yl9_1pATrFVchNG-_*`$*X+^fLbv!_Ih@r@aq$~<($is2WP!cT;G{=V +ztL8Q98X7|`dV2F!3>-Mb(Zj`@$NOxJEBd9Um*HHAOPYBGsi5|HZ#17#02|S|AS<2T +zbtpyWXb}q^)}m9_RTbSxQ=TrzM?H6kmHMH@QpX;k{@l`PB?E%{a;dkTR63XZnx5Gc +zu=s=*pTAt@do+U05Y3iHPE&aAJ@++kka+UY>#1DABVz=X{M7ju=f9IPpI}&7TUCAw +zXcw)#y8;opCfJBNu}_>rUoRjCB%qrOayVKY+(9%e~hYWWMR=CNfv$gX@i{2e%U|H8Pq^aVNb@ZPM?*gL +zX#+hE`h*?(o86Gd7melOQ-V#jyWLJtiWOpA<<~84=oh@h-`4V+#ps_%_d9|3Lh|k` +zH;ZMNowHwF7$Thtlvqt11YOT{x$P#Ne#5HigWE(QZ_o~>{M)#vjB`R(SI;8pwyd{M +z$@tyl^mJ{#dJ-rr{jQ`_AGrHC%Sow1#H;ns`Fe!)t?(>HVBFRO3$~};=_o=Sq!GU^_M;1+PWL<5~TkofyFA2_yq6V`dUeOKR`ix!e +z*7|LH@ap&;6kd~D2UNvHm#Z+TYAOmUvQaHyg5IvkMqgsmT!Rt0Pg%RITP(-tgtNG3 +z7~%}P4^2_<1k@?TX_J#rSo;xKjHh3Y%o8Lxc*JFy5zEBZ?`yvRyrIWCR5;%!;nFZY +z{2Bceymp>gT0J+tY7yhiE7}u8hIB7R4_!t^K^G8`4teWopQ7)3{eOgATe4&~3fvO! +z$EQHB|0Oweu0JcHXC}sO`*wAmBaviEKu-I);kUomT)(bbTlw}$-_9AOI;g$ni$Zx& +z_bGMr{jN;po5fQH?ZVxA>^f~V9+6~vl7?=)#|V_C<38`vfj)4#6jG}nIWB7gP#!t- +zC^m5VsYH^08X?#$7+GL&m~vy<#t&yxwB=C{o>*i`mjUX#zE|415Uj+8C?z<#a% +z3NFrWNR*1|?`g#x5CH7z<{XE-u&7DjjD;H%XFux@XLy8;w1$#g^_)Ej(MVV%u6&paryz; +z!{(&-^LOt`!BU|5c8-6iwz~RK^`p+4%0^brn#7$%+wgvlQvA=HHE~pCS++F89c2AN +zvvr +zZ$5pWO4_*schV2HklwdfT4F9s6A-)O+&xd_JsMeFr)=*vq${WFHs=){dq~FMbK)dx +zp6fi2rW2v(CgviIwTU*|&Lr(IU0t4f(B_a(cUOp^3$4BqIzJy9N=nJcEuTU+>wXF_ +zdol7>DWSNZ_ei3h?4foiRGWd1&a^t+16{BhAB;I3)Efl}j*17wy0I{MRM#g2(*PS^ +z@+_sQT}C1DM_aE^tn$Gadl~b|t%iKO!MoH>-8`#_J`LWiwG$VYBc{{+goSS_b{nCo4Bpd4Zs*#8i+j8jE)SP&U(cLQ7l$M`erm4x +zrHI`K9+E!v*h&D}H!M5rL1xsg^e0iu1Iy6{}2$ZbeMo!OV|5>B5+y+S>=60&KR +zFGCS29NxTxIG!n7dCt-A^2OPP^3keIM%01^%J+OX+%rHRxOoY&Y}gXl+nMN;TQ&i4v3|jQ-?UlB^kTU +zp1moSaLDyjO4yX^_;g|S>6S?q-UUqnLBBroLVHU@rTE_R1J!^Pdf-gg-6W@(t$QNy +z(svATZs(#OvR1fba-TB1^fZOP1>S6vNd1zw+9V6{%hJoEW*04n^pOf?L-%A~vHJ+? +z`_8#_XY%W_xg=ka^eu-WuS^=&MRpU-ZPaqx+uU}udF^IOF@O*+>Z3jNB%|p0W(Fzy +zm&zY04koMGIFXNuhrR5fHH^hk=aTha=^OS<#JNH~J)ZHF!XDcSP9$XbtHcNIGvrj( +z{4y)HOkbgOz1&x{s0)!1Jx?y-M)#vR!4@ihPj_Fne82D#Ft0EzAd5zR8BkmEddt*H +zrO-ab!C^4dyTcHN=826sJ@22&p~%?XZ3SNd#Fg*rtMgh~s&)*uZ<(xolLX)TZD#lk +z^@HE?fTx@TUbf-k3^zV)X7L1d&NAHlO!a0h#zvkU6(pCSI^S6R5Y=zqC^Faq +z($0q`Wt;rCLMqYia2NI(Z4$PwWq=+(->G!6Y;QB1$G7dDH7Dj8Z_$N3xEC(Qp%!^C +zqx@8(W4#Z&__?@HEL>BQ!l$QU>p*cL6 +z(%q(L+iOuzQ%dj?Ie1Jt>7r|wO@*_|9U*gu`AV+a6V$<~^!hNHY>HJJFcc%jyijB7 +zR6qpsO-r)2(H=r4BPJf%4!pJdl2V_i)xvMY0##`f$$O!UAZ(9epa7ecH}#_DE;0%B +zTuA)_As;IS3UZ=W}ihQUBZroaMz2`vIxx2+Rnv8K@mTZvm(h|-}8sj=V^;FI|6Q8kYU_Z_bPIDwD +zw3L;zAATMY6N#0}Mh{3hW*Q$U@&hN`i^V`P&tqhhibztQYuZRY=2CDB9(`86tX>+r +z)G5Fjh2L$pk2Bn(YHy3F-H_3S8fqgQ-s7Y%;`Nh3@^oPcIpT4U^B6U@)5=~Nl|Cb` +zjE{@?#l6*rA~vjMhW??c7wOTRxs9Vcdr8GtAQmP+CtW`m#@M!>#6MeyRmt_7zA#jK +z&g8C_E1V(dpt$xmE%<%8bRy{U+e`@^r!;T3$Vhk%Lg=GKmu75A +zANPFR0>82&E$n4}+;9?#m-HNuqL_Wu#7@!Gmm$;boY*Tz4Guku^35z{17xhy#f`m= +zKP!iSJ1Ikm;XZA?E8Q;!lseTZeDuIRZ3x;~`<+Vh-UPZ#(w+%i65ACUPZHwt$h{@O +zntbUo7~n9=SUq=q&$*L^y7$oqCJ&vXcqN~F6|FBbJNOWZMYIV-SrpA=IpLjX(6>Y{{cyT7F^wsY}fotv7qJim+ +z(IdVudBA4yfanzjDW4c6vZJJ6`;Wx?=m37^9a +z?+eT4*}wU8leKX7sB=utJU)A2DeZRM61>HlB-8kQACaPvyOKph9OJ1$66k4Jpmb8= +zj`ln9Xg)tyKv-AUzSUk<-3D>KURN%UU4}WLJbULfrw!Z&UQb&Ghg`%+f{o*L<%Zrv +zrMD?fP6Rzs`cUhu>EAv#RUG=hRS@Q@eTqX!{`P#(;Lcrlx25a8wBHaG-$jIP`Cbwd +zqD4&R``xA8yZ96He%@DDbZmrVA;H){XIdT&vrqG%pqE;gxo;jhjE@`pL5Y?`j=`_; +z(+%_3)wxrXsi$w?bW~+~Wp5w*$}(|I4(a*k_TB;+j4Q55&=VAuGEOA8B)9zQ(`Kau +z^Ut%q1o3zqLQgEW)X41@lxWeWvzPA^pfyP^hOMwGbD1@8)o_4L-cT3Vc6!MF0B_Tb +zlTsf`F+?H>ynYWmnbF&aB~)LBXoPz`o%k?EsV%bj9#>;8r3$RXpgB*@z)-{43zytP +zE<8; +zlH-t~)^&_pxb&q4(QB)shMJ%I(j$E*y$W;X2%cao7=r|R0{1(BI8|SDoV!cB-_gxB +zw)e^o>%h(D*EM +zY09v9Uuq2`D6yRE>KC$nc4(hEheG`3NKHk(4Xhkz&kevX*DFPZIf5IuJJ9+nb6U(q=yhgV%(5A%b~w)}GytW3E3B;ex@Cuk3m-MW>Z +zLt?%+^=NCDvS(T|TzL528NW8c`@Cz>@QVuPvg +zKCTn?P{AME5Mdr7Xx}+&4c87f%2`?j0>YO<&r_aZ$I;`3#NI-uLJG`BQR3RACvzy1 +zZZ79{E4Zj5GB^@@)mbhg>|RXsfs8e0Niqg-xyvjpFPC&a4fBYrr+5k`K3>-JqIZu} +zS)v2oR$UqE;EOHcr-}j>o^C=pI5kGLpbK^(5Bmc=85c956=ku$XW_A@4d5Xu&+aXQ%(&|XN&l}=i$Cv8oj6ZcFafmd!TDd0lb<(qEGfi +zAnepvTSV$9!|58688V+S&CH2Ygra?E$RM1rC_M&z;`0VS@D=U0HJgrq29SPA>JjYx +zM(xA>+(_}T;C3>hKGoeJ=QHIg$1z7PyjdC~iKhHmoYpAgH`J9JH8)$^_e>v<9ei=p +z*m->X0aHANTkxbOd7ZQg)0bFwoQIQb#AkDH4l0JfV8*kGPHzcS;k$gCrsGX5ec9wu +zptnONq5ACBydaunJyyW@^;#;}9$$jv;OB}v?gH8MD!Aq2B0GJJJ?P26d_4OJHs7GJ +zqas$Qsq3?W5YlJPBt9Ly$3PA{7}Bv?v8Q33rtiHgMxjT*uLtW83CFw-r9QB@cm1mj +zK-~w+ZzUA7VmT6s>Vi!czXjS*Syl{`;l3N!g +zPWcSov`6j|(u2n3e4|nlF3?W&`EN&P +zbk+F=wp?s{pKPL5`r?y!11(Qu`e1=Q-H2y5}*|sOi56}un)1y=9dPjFb%9Ebd5+&qH^kO+*Q^_L( +z8U@x-dNwbK$GP~O`LlE70>e{sw|-uqB*?98#bhg(1Eo-e&-qG~bhHFpD~g^Y(nl(!Ob5bGTCWIx|=ptev3+aA$F +z=k``R$PtjUA%t7}B;n3U&ovd)9(bGeq8E(@X;LEUJ$qvE=%c;+UD$HCInaQF%9S`x +zs9A40&#}UClk>#t`m_*t0nB@bYU3jRJaa=S`DDdq~uk#cetv`;Z)%*6B=(+rK#5aoKf+dN%l*YpwF{lE9>}%hY3#Qq;c*kR* +z0^ubcX>!~brH-B_q?YXrQxskZqctr#wYv=?We*MRP{flKEZrpHr_MP;{ITQ2H +z9R1|Ew@!ZbYh^5AceWl}1~BnheYUofH%IvG4IPxZw(z1hsYwt|%sIY)HQy!sR8w&;y~??7{iJWaYg +zJC!u&+H}$RiG9C4qzeP?;4ysvnQyPvp?*jNn$cIkdO`op??U;a9t3P#J@kzz#p^fp +zb}EHEu_YZ2^+F!@%IyL^Czyg42a0Ra9jg9mhybHjaY=#U;y_#!orxPiogWw^*Ms?LAh07^A +z=B(VI(#;{)UML`bcWBsn6oqfTfJ}Mno;SsM$$=X(_$l^t`s}IDHYc4p+2?!{$0N}* +zTMcTh;&Z7rm-k_C=L`{4-9t)aY%NOfncf5I9dyR;bnb!@?6J5-pT*}Bp`(rs@v>|* +z3Hu1TT)b9FIh@i0U*YIU^^^H9?jjy8F{Q`shB7mO*C17hO3q_Y;!Az6FksclQ`nBH +z@y$KA>s@>MC4UlnL~uhd+^?Z@jzNd3=|~(DV_;CT&SAM5L3uRxu(`v8;WZU5h0}I~ +z^HhTou^lk|+#c<*EPt;$eYuC`XhGqPQa6yW(4%~hAA#JqMZ$a7P7~LY!b{&p>b&o} +zXE(2C%?Rgbmzfsh>=ThOv|<|Geb +zjh~xGhy1dK1NMGhMC?K!m%~x?(Ix$fem`$GdRc?J?q2C?bTBR)zX=7jFg9;D>b}J5 +zLo$z)B`NEZHlW~+>YEnGDss?4?CF=BEqki&5chtJeUuIy=?9(+Py0G~1#V@Yc=Wg% +z@%B-42K50!uh{YPKJ5uSZB^ZW&cj3V>LCeJGCKF%ei9Y&q(Oi`+1YmC%6EGGXmiO< +z21c?&Qe8f+gt@TSP0Ns%rhM3r?su0x{KUGs3T)C#oftx!+S3ar(MY2-J_kB&*GV2f +zkoO1Q>qc7daV$*e9$M;-^g_9mskb@4JKLp~|BvyU%C(eFkDu_J&jJP0ZYRS&3eCg9 +z$dPjRzSkXAu)S`K&U&cLxVjv_Igc$xll~d|Q+eWfT)Zl5eG8ZgVPr?+_V{CS@bbd+ +zm-BgN>Ec}~2w7r{{ke2z!hP5S1? +zya(Txe?t!Bbx6hD(EjFtg9%?4pLMWg>Gz(yH>L36)08;ybqF&b?ZJJSnXCO|_X2eE +zPTexvXj2K$*3NG2qo^BsrC +zD5dw-LZt|?!*_HyJB^tHIAP}3a7QY82zgS78I;pt=5V<32!gRwZ%9@H8=l7tZH^?mdrTo60wZe8>FMOW_KKkoT{<+a_nm +zU#5Fdv3?(3NRs9^6L$a}>3=J~dyOTa9-f;wgv?WPV-1g7r)4eJkp7zY>A!ud!D$Mkf`a8_cOM&%LFQ +z?RTln_vuo~weMU}1m^|wVeVMfdt|H5)qabv4revM| +z{3lY*z4mz@7B+T#<~6L+(vLz-j@pTj#zYhmm#+mra#~{NK8{#ln#I9{u9wZB +zIEpzQEjfMo%A9VpuWi7wrFaIFU{1)viby~HzFf{;Q)IXk52hdZ;!00`eoV51eN%+< +znm)1+WvNG(Xj&2IB`T8UsTB%=7AhJR-FWKqZ8F1K^0{g~{NE*sgq)|k?^hZG$b34S +zfjhoK&5$GkD^Vfo3+*Ue{dAPwTUPXR|K1g?w7S^Eyl9OfU;l`nsKvEck +zdiTSKJ0#wh9V^cbh@IZ6z~oQXVN`P;o4b&8=X3erWv4qaH2A)Guj=>&p4NLEy(L#( +zBE}*iW}Nyuk{4l6uUA{%nfzL)m>U01Vikhtn)2m%gx$sUn?yFk3vg)P^;kgoP#T^R}_T-Vrch +zVwgVW28;Ol@sq`!Is^vBICGK;clWVLe(KO^>oH!>kAqk9iEB+$a;(UP-!FA*sUbj~ +zQaR#qVrl80was#07Ew`VH}QjHM#m2_m;&LkOYpV>vS{Ao$Jkc+YtKozXICuEeGKo( +z^T3l{$jiBHemt)5ReWdGYfp`hL(_`RzJXIE#H;_*~BrC;$x3lkg+HKHU{6gck +zE{Ay=`|B)ZHWPZ;t0^_^%;9UZ&9E(_auW9TvD%{(R|Mg5^zhQ@z~4V_ul|fK1=@%W$}I&@QQ6?fS-CA|sWJ(Rn20eufZZk=;C>cW?ne +z-qu?eI2=Y+n +zp8f0+opKa)hX}USA@#Tr~*^d1+C?XN=f +zbP6=Z+Yax;iE$o5jO5u{aOb9rKUy{6_a@lxP7=TG+ZXJccxET!`bZuiZXPGq5J>r?Sb{TZ#uedKa-a>Ep2>k +z^@?{E+;zKLaFp~(R8ADg0xxJp>PK{jCdq1hxA4rvIZ|2+ey|{!bdBo}qA1W^I4tpv +z8eXx-j`CnVvC196w$kS?U^%nhxP9rHa%t44L%%#N{I?gjpW9Go$z#}Lx%A{>iX1(3 +zg8?#d1b}FR^R$U@cs+6qVWt3~O?_KKKU43@`^4WhJ&(H|zs(K;IIGv-UbuvtZ?nOk +zNleCkiYZ#v^pP3v*$VQjiv-MH{T-k_ejG<`A+Z0m?ho_?CZv^?1uG=cA#OO@@y**pz5tx>r{Dy$y?>)ihh&xx-0`b!dTMyO&$#fp%$)k-H~?%lG?{ZzOOJHW +zj%!d#-#(Y&t4LL!+CI=kAYbdrF^^grz4}n)K^D3c8YRissh1>P_CzoWp|{VSRg6XEvbxn{_~6sTo4M@*O!vcxh}RbwA7c$Ml=*=~^UiX73t!nDx{( +zUqNvXxR;=4pwR<|PfT0F@?~27xKNxi`G)E}wf7jvwRofm)q?$AvHMM}(XYZUf;Lhu +zzA+upa|(;2vx +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 +zNYZckOxwImW44&T42A5g& +zoTGkYDj@t7IS9=sl@ItWJ%*RyuC7&T^n)~x?E6o)NHQ!(`$UG**$A+6i_~LJJPtbC +z&KDWZyYuR^dbA0Bq(kw}ETDdi4|vaw3dqKbO!-+}u8`u(j0)|a|8uS77Qjo#8cP^5GO-!mx~l#T5J&~lIBad_*u +z9QrzX+`vG;aHq0r=D1!yHpU#hz*_;wYi#DEA+_?{QYU{Z(M71Dbg5&!%;DAJ9TFVt +z2543@K~Tf)}tYyie19VZW)YzC!bDw)cZ +z6W+_2_h{E#c`C?q^Kg*$J;aJWhvI!1@6AwXQ8Sngz9-xsh1jG#Cp<~zB751OKoZ)) +zL9ippA@MI{tQ#t%iB*=eX&rj_HZXyOxwCJy%W1mp$eKOSp16dzpHZ5Y#M|bdgW8rmJtB07* +zV;mB4bQF5Pz8QTuNs_tfa7$9)VwLjb=d|c?zLO(nqxY1spjYZ}?wKRNHhN-g!Q=>7tfZbmeoD+P +z!24A6^EZ`Q)(qXbmorX$9#w-E<}=iJS_`flP(zxIs5TvU2Qpo!4r+Z0(fQ#yRqngK +z{5&Rks)K~N@7GmpbIah7I6Ae!Dp407^B{xV5LB|(WT)#TN_d4p=agYkII;Ux`%D~4B^^&k +zPDg+5D*6f3e)ZZXo{mb_<((UL-m_e9ieJe1J2Bm43JB|H=m74H^_Oe%^g{W$b`H0b +zd7yD$aXI1%%I0Et8Z`jziFo1FidM)xv9gG4D!-0SXb0fK4%e$x@lso;KmNpdKRfglCR +zrkDoXCtr|RX=SCr!94GmoqI`pM~z&K;w{uOE5_6I=~y{+j|tDY6 +z-a{KtjE{5S7$j>?Qv{i7S^5#|*@ZqVkA&770PXG1I&Cg2M3UE&U1>(|%PsP7(UnBu +zQs?-b=jc6Zh3cHo+1ceYxSV3u`-NP;A9Xg*`Z6g?Wu}uOK~W#}n!#__)A%oSCV}rGK`uf< +zoNPP+^`v&5`xmtw``z`t-i%oc_e@r2{k6%896-CXI$5x>o4d7m>B#YV;bD&Kgtw=NcHbgxjwvGg2>Ca|$Dke_>*tHV1 +zeUiEw&-fFW1fuc?|34>Mp!3{4La5sxj3wK5>mfc9@_|!_6eUAs{K$jSB=$xu@gf0+}-2%VOmOR*^L|gzJ1*>C$YQh=m8ZUJZRZ +zz%en-Wm>^nD2akObXN|!k{@c&VUq2>lj&hS)m$(ncew8MqQQz*hu8WywEkd7%s*$o +zGV07hJOhBR9ij~I^==QIM>NCs+Qdx6T8Xb+afDGfSpgjnHH(|Hae +zuEd(o)$BOTZ$)B_&0SOxm+h&nc?2cylh1NPOLpOFy(C +zp!GgwPx)B2T*HW+orf$E-Y9NFm*+efJdCGn-`?0)O=YL-^pmQc^-vDrbAXU4L1E1R +z?oL}QoPzQ8>T0OjVZ-W@hq!Agj!`r=S6F%^FOt+ODV+q$s +z)2>b&+^@B%>JlOAdDqEsuw3`!n4nV+Kb-Wj6M`JYEICF{md$R9oM=gQj?mZQS4~>9 +z7Ag1e=lL{enxmXTFS&az6NC5HMP8*39Iqb*i&H;OrGKZgKl-tUE|r=(oKy=ZNyyy; +z8_VJ=e1Vu_k0kIk)7Ubb*}m#Uol=2My+Ff+6-aK&bkSB^LBY2?^xA?OpNp?@9p^rI +za_j3qW79AKU^$`4cN5K;jLtAhf1Z41{-~OujPq&VxeGg7O!dWKL}Xa}(+x~-p^hK~ +zX*=Q*{s#@^VCjNI7kR^dwIY2XS2pbF89oI3wT?Ei?beyZqllTpo8;Y8as$X3T<$jn +z=@{~H^XRLuyk^K82Gc#6as`k$a~XrxDsKW7K^^an`KCly?Wv4IUJkm}*NVpE+83Aq +zn0tqL!D{ML_x-u6*+s>6fDu-C8YQ8M20_WrBf5E;Q6e0xnlJ5VK7kF2PnJ>atA+K* +z#Kwg +zG3&&9AAqPU^b$GE=d>?G!FP3D{iG){zJM~}ZUrGEsdp>K$%Nzm(U$`j5FDIP%o#VcY6IUMLHo{hZWi2`2j`qphYMWE~x$vBeo0k|S?d^FH +z7`=~$i~4QSSJy!{5BjFWm_1oq_cPks!od-x2OC$M{n3>aj<09M08>@*8?{4H;L*$y +ze*4}MFVXQSPY8g%I|D+8=3~uR0J`XcD9#}N&IF}6pD`2c>8Ipb_i+qH#_YF4DB$`7 +z%0UaF{@mhVzE)}9lH-GX;5`|LGOM?q+olVyxG3bS4k=uyc!HLu=WGz3hf2bM8_roa +zgz(DVH7UZx)Gj^WAxp2Cp&mcc=FSOc%h|8h;@yF2sB;gn*diV1(RqTnaK+@|$0$)R +z=7~qf+lx}@Vj7qyi^SHRkuMjCHF<>GE;E!6#*v#Zgmo=t}lbyen!DdcM?$d$4LxvVLz|_&dNYS*!qW3Kc>;bO$KvdTT%Z@QNPhH8Tz} +z!Mu;4qaBcUvCyhdbdUmCf3u{RL#BtWmKcm69jmvi=qp%J%1^s;K1x@{qcRI^v5BKz +z29mVGK-Y6YFF{j`I(@m)XYwygzArYdkH*X$dEgmzW#n4xyj`=9B|_KZO0W^ltv)fE +z%Aw>f1>>Y-Un)5+@{kzv9pLm+LxyzmwAZ=Dr=MQW_iH{s>(J9gax@Cija@Vz9DJ|c +zpewIohG1azlN_1yWH&WOFgQ%~qsEUA%++yhghJPW_D4gHc;nvP$R}ltIGDe8(1nL* +zi+h7t^IYq0<#x7Y6>c$(xD=wsQ~=++p`$(>iJ8pbl)RiLMc>wcG^y(t!~L>iwB`%? +zy6T92mYXXTs5<+ib|c04*6pLZiZ9SjS7_A(sI>)WeA(Rl>WE(4XFYMR}lp>I5c)|dE +z{2K-zW8hbWOk2v&7gXfs7JlQiBg2V3Y%=%Ep7R-Z9OHW8bMwsOccG4}yXX4*B8)F< +zNVbZ|eA$V&%~Qz7zn=RUGkP_X**tIJ-P1JVQp|S{LnP<}r@ReSt%K1V~Aub&{{^DZG==>l$6J~#C1aKWqc +z0O%kS&B6mLEtH-;cbslqp(C>_`K~5ZiVp68T+>5-@13+lsYy;*bpWFQk +zrSV8qJ(=6(ROi6@(JHI1S626+yKsI9G51y`)tVqh&ncndc$xt`kFR4j-gs3y7mt`r +z^<^DkyP}oFTB37l+HRkXta}9L&KdP@tbQP`m0qTqdrz2$M-i`(YZqm>3cs&!)FH4O +z#%pjNJdv*tr8<_-XU`>H>|QwP<4k3vKF4#SL?x|70ghOttloS)}2zq8`S%La*elaWp +zzO1j?3f)Ys!CfA*=X@`p8!M%3Hlzi+p13K2eYEz@*i#thmv7$$P%2$LPntiffl(YZ +z?%2!-=kex>dtq>tzs4uzD_kRT999Pk{4{+6EWfw;?dk?acrWS|ag8%!6YX|!PEG%F +zhI${Xbs#`oNj`YI-A-DrF}^j_C!nuGeED&?bzLO?Tnq5_NxWupC6A>Q7wsfZeW6^3 +zkiT6*HjMZl{XM#fgcx=7h-;=T^%esR$JqwM{jzlWvK14kJ{}Hd_UX)w9@%pXv>zMS +zdbP4q)j5{Gi1--3hLOJe3cs}Zo|WFJ2-y)%zcdX +z8(n;g5chP=u{BJ>rW;=*kUu_U%}e)wbB#51%^pS3lX8qwcL4nm+Z`9OIdv{2+~bXS +ztWTcI+56b1wF0pjzMm +z%}m#z4(!{_{>4Q>b1)X*bkse#$&wna7lB+BI3@jw;*!FBs#g>9;!~8k;Dd*419!)l67n19A6h!hvUqU<=!_3izKZ#I +z{}8MdPVT{r@)i^A$Wya)%N*$FtZupItXoUE9t#`O+Dy~=OK0E>+DJW7U9B`wQfHI +z8I5D-o5ymKhWxVVu*Q0>LwDPmpD6kBq-O0vB2!+mOEJA^;)jCUL}b{p-j+v*+&-Tj +zRnx0<*RJhK$)v`(s@w)3F%afUe?~euVey!qe*g#X8b@f|~p9)!?KofaXXx=-XZYo|-wqWOryCS=6SE)e+o; +ztMRbykt=bL@bz$(iUvi=?GdKKe>1Jj`@qq{8|Of{I+ca^$@xxyHZHvtf{&9tI+{R` +zetBO>v@P1Sb5JDC4C1SZ_w?r|9ZHX39U`Wyv4la{7)auD@8WqcGvx7Y+5VnXM`z;db +z#B-=tfbpKFhJ$ASo3*>kIoguHMmzy{Xn1_y4ZJH5M5+-?O^o&(eJ@%n%Iud@?0IyL +z*Hiw<%oR@!o}A6Ww=R;*tIk$lxXw-2N0%?aXMCgDP-3QaN_i_VQhBORL8rUTTs|NI +zuWs;V_I1@N_u$T_`H`<;IYCj7IpQu`pK#)e3s4fuGmV#rHg2@b)MkUfD)AVxX^#Tq +z(%x11PD=Lrt4Dla?V+1UU?ZgZAcyg3lblJw#ba7*l^Z8%eebvXU#;<>>tJkeLrnwh +z*E;h63{Jkgrcd?z*Fa}ya)F-UF0H5f;~mV_GLAHu2-Iu>SvnYf|U;= +zU%A)lC#w#BZ&$bz>_X2@f}e>kY{lc|>T^=QQO^>+aZHb%r1L?>^?B;g?1llICfZc^ +zI--Sv^V&r-04A9|7+;3gq9KtirZ3s`UN&(jCuzBudlT_$AwHqMr<1jXoyrg76IhWvSh$ +zIytw|c5X{`YW78j3%kU0s-g{XE=p&SMbe%z<~pZ``5fO#!BR>u9c1*@tDV!VbJJVX +zU_=`?eKK$H=OJ?;;p;ab#-q$cCI6hc?kCy=j6aJOl%#r6{L*J?71s+*x>9aEB$Y9} +z0lsw7c1k@~#LG|n+AN`o_b+gZ~@zJb9Wyh*qku9xneI~!J2;#g&cJjb? +zR;AZBxQ3H;WwyR<@6HC>F<=-7YkA8-@0{M#*DTp|^?lCzCCzX^1-i{vEqqd{kf>AI +z<6;NXDlj8`XLRi}Jv6UyK5Fxn)a1QQI5Z00BU6&|SQfme$$pf(`m}!%Z5?6b-g*_X +z3bU54=au<79?beQG@Pn!+_lfL^+M; +zY03Jm_L$+E3?zYjh=X25%w;=K@%XB%1OQELP3j}))R)s04C4&%z0#f5d$Eq*LAIx6 +z63OqQp()8>om~9>7bii#58>o-YJ>JCBN>IR)yxb6;VtL^x9^N}YCZAEo9jx;=YFqS +zvm?^`vGE6aYxsFmLJaLS2$c;$LcoBB-s0+wqT{G7L+$7N`Ft;E@VNJWDVmfi#0lC& +z_oM#YIG=qUp@ixkuREt`jF!^T@h+e&FSuuu$mZQssIQ>olUH|AM&e7?fSi`CdjL|= +zwOBC@2Lzot6rdxo=$}eHvShR^?{UiMW)&b-v2TVd6lSCp=}Q6D +zyxYvn41M++q8g)nuW{OBXb6L*vYM^Jxm>Mw*doMh=D)6jG)WZ?2Z(aEi +zIfbq1u8w|9Xa79MF;LSaxenzf#?_^K{Pt7(e%-4aYTs6m1U5@A1~eSPVp`g-ulNfJ +z{30{#JQ0Dwh*LaqlnzH7Z0Bsp0KUWPc@2g#pG3qq+5)FT=V_G-jNPq=Y~6L=?IEqu +z!Fr(mHszlF5+=r^P}9$Yb;Z5&q4{YIyVn&5uYa^8AFGQxWk?xmUUHK9{W$=t(R(U* +zyavHD-2g`pY;(;#cF4z5`wZq$3yyc=__*H3@^nZ_h_x;oenDiO_j=bhQ9c@b?&>_e +zK1-{iNH_9=tUNFj7`xcAdk+D|lN9jTVRtCnqEHFhavZ*PW#x-WH3U7!g6&*xX1*?a +zQqLCy{WWY_u6%LK3UI$Upr-)9B@X1GoHYF`8xSlk(xmvPukaU))qD9tn!wWyk-ZJ` +zh=a?3ucZlwsj+aAjEDj9=S2n@B##!ZRtqhuZOn=C)b)ExYIwEr)aKa9js8^FUJdZ> +zfs)kDLV-iaAL)OBqTW-D{f^3S39jQ3=6W6D$9xn>AOAgVpYPocP2~8&tDxlVPkYx5 +z?{g~;p7EWo%dg^Me(56Q`3Vir@v7l +zAEY?vJZd)MVA~R#9SstvGD;nzmYd!tF-DJ^SNMKmPJbNzyKg{?-cqQ2%;+m{|IiqvRRKP>L8#?vT2Q1m#Bc*Ewj%h^Z&^r19R(ltE0 +z?leVO07Z7jcM+yI?%{Jzcii&JeFf@HIMn@?Go*!3I_>eed2-FYRu)vfxor9lY +ze>^JxZl@fsQL2)2LoXQNTfTQfTn5{kdYU$ySZR$=%xY>Fc7BG~+8esU_Y1@rM8g@R*X7d`BA1;o6w2y0!|^d2^WH4ooNwXI;Mpo2n?b=Sa(<;pE#g*=0MlU>*(CS(DHv$^7V6N$oXof6k6lMzkL)3?~+x}&?X2`o>Pu} +zzbWhPQ@+g8`B<-i0S#4OxbHYi2jc@Qf(C2dIGt4z`bCJz#?$rwy@R{>b!jptg4VSJ +zIyW81-s<-bO;tGui=&t8%*NMbbkdFC&U*lPD<6zP@i~QiJ&`_tuC0GgC>C(){qjHu +zHDK8Tc?{rtoA<@uC?V>B{|LL1WXE+JcqI(Pw8X^wAE|?K$6vjO+P*4VvP1xxB#`Oa +zmf8$%OYB3&m_YTpOMV8Ar)DR3G$dw#>s5w)Ypj!CLtPGh!Z0sW+(bh!PSmK?R|9X7 +z{S=*44UVRQQfBnF)YBDL2lySNxgdU8aPy4z{xx;ux>Yh#;G%7`Ua< +zJ-(bvF0>7-a=P%)P`P}DkHT~YCCDz%3(P|InNn3*aES+dCcaZmNR;bqet}xk3EHBW +zh%cy68Co +z(s@3wAb*emyYaR;iHcH>_VB{q_t!57p2s-1j5|#LPx4-K%!y +zd}b{>iJx!HyvG?0@ChKP1}-a}Uj6JsGauw^|^>-0aZam&$RAq#;&k-tbyum%J(e2axjojO(^_pm(6%_x3Fv&202AH{O`#|o%ZB$jRKfBSz}UEj +zSbcek;oLR3w`WFMnwIkPoVNr!lm-y=2#61>7#=vOLyvX6vU>Q8X@sxyf%wjdGf`2d +z&H=Hh2qea#u0#4?zw$p%!zXu0gY5C}i}Y!QMISqAdA5Wn4i-ElJlX>__bL#U=HdhQ +z^nyu5=^E6!pF@^jIug9lWpE&8%1xD5?#omdL5HQOGJE|o^bcO`&mMi!}9xGWeB1uz5KAh7%HO@Az-AR +zP8y1vVxrQULLA3W`F^f}3kJt);F^?xKT^owaa)HP)>-uvLUSY4aiMMJbK|)JN-%rJ +z37NJXuYhp`ejs9ACKf6Q?a8~^QaV8(!n_w{kS+1W>EeBSHHBqgk+sP-~QX$CdhMxBXEWOJf8>+IAxS}?hJO1u0-g~?aTM2ko=lx@cWrVv96yi4Y +zY2uXNsta=YIwTxRu=Y>>Hse;Pb;T=WgYPj6qySYws=r-hM5fFs9t0^oCN0j@a~`h& +zlzSBJZj@f)g5fG&S}W_f2D5#yy~6w+p>3bWS>G!O(v)~GGzUOGFVg!B_<0&w!_8qI +ze)S_p1w`|FZW||{xL*PW<+1scI_ch`g-L!C5rURr(opLj`Abne{&wP@EPUy<;Mf#A +zNc(c|m_`v@w-iQ1|T-AgrNBmM=7G3MPcL(Khom)nTP<6!x5R8U!xx +zA!V#S+y3d%!g&!p{x!UZ$1A8=fM44KDn1r7Zd}+m+5HX!%3E-coS|4n?LEZb5oUd2 +zCBrZ(Jy?}K`b|;)GiN^JPy(MK59oXv?VJL?I<%?`05Pr)BPSF?JGPw#wn&KxJ^1aG +z&wYriKC!9?fM;wfvBd#XeQ?-<5P!2p6sgA_)&c5-qilIA4jIr3f{m~GR^}N6dJp}Q +zSe1P9qG{1FH-eK-uQa_3Ze +z_18Z8b)NW^&IPum*wJLVEx@sj24^uM?{zly6~E}>J9cnp`kJg4DPdJDo6Jh)fddLd0)+?qZeT)c8=u6U)4$JP)$gmkVXp-9(wXrdWlVT|<1h{&Z3 +zJ#}j@*$~}2L`uYy9oqf9UZ6dWB^d768d2>F~K(?H3J{mT3S1$^GJ^+i~R^#S*dD|Q~PS48r;k{1qs%k7j +zlH2!lAk`r-J=j0{NjPi?7vc&j)vePa*MR4owWUXJqsc_IRBJjUg`~p0_Cd|VlMTIB +z77l)13EtD8z(OG1EuuMxiU@8O?5jAss^bq&!jb$0jPJb<{=`G3L92Rh@i)A=-cW3+ +zZSHoaUFP^*Rj=$dg>Q&|9>Cs{y^kX?cko385NkM(#GV6)*hkH*V5vjqs_M3Virn&0 +zD&KpAcIC5|#W~YtFLVTbUt#q17fQk9dgvRnd@S1%e9WL|Fc!R1joL$;9>Zk#IvRUF +z>4#K)q0I@mE*#g7lZmu`)Q6BusivLE@n#CE>J4noQ%i#Z<9RiZ{Dk5`S{iU$!WX?Ie> +z!A-;qzw<=Dg`4EUz}xru;X>cZt3PW7J7hdNpEuhbUHzKVj%{cryAVrYD8Qb&U&k%g +zyt1LLkYB&v8ZSR^$OhjofgO%ykcv%z*sw$>6~&N_;Nav5NnfA}W6s2DWeZhD$`=?15X`)6gRWBbzK!9=KAB63ayt8)=MAB^EEuP7AqzK8G@(o5kF)gj!S +zf(B&nZ?h#~W)Je65G19A?ht>N<4>gdx7$B=yjLsGaH(^B*@>^$)FHFWSawb?ZJ~jj +znrWSTSzn-?xaCPq(9Jd17n1fH4y=IS{uMI7-*;i?FpY@zc}i@Ps~F; +z-3y@kwqmm7YEOLHGYfs2?6BA=7P>FpKbFff1hq&v?Y-$a4?c9FcK|3fc*_G6#cQBS +zl=NaT2XE=#V3J5FhafrdxM0|Y*ki}^#>7FyqMLWgy5P)i-g~}j;iZ&@Jtwnunm@@> +z_Rx+tpii5vO7Sti{(8Rcvq0NyV2ocs)D4dgV|cvH?h%8_a?VNu@TIT0i$V;9056d2 +z+Gt79i-Jm#xVN0%fBm+QbcE02*Kqr+$em1>SBK2dd>*2p2|uW*3sw3PZh^GwMM@X~qQd8(bAbnku8i;A@-nRNUPw2K$O0;Ti7TqD$c^m;BNTLF7O$Q8i8 +z$G*8<;)@aUpkv@&!?`8;pwO#KuERBG?KOKnEv)(uZ}rG3^^Nz^4sco2ivhTO&rR#E +zRZs0a`k&WjZ6J`(eYmpMS!9>lZeG1`RKbKBGju{i&x+eMx^PqK#fE%?c4u=69c)_F +z>}5w3%1wU6NC~Jt*^LaOd +z!r^RGhE}O7$bRKo5QOa4^1$cP22#@u*|F;8|N8kH-C{D<02hF@j;1so=8uqEKTUR>A_UL8f +zI7-x~K;@^l`I3?0UIRm0Z%ud02_ZiGYS@O>L5kvw9<7XNFGS##DmgHFa#SA9S3Y_B +zGBN^~;n7#09*#6HjjW{_Rp1p8b^4?;sdqMKkS5rpTxaw=esbay@=RsBx^!9`<3%O5 +zqa|mDKb%8zz*`-)#PZZj#&8GQvQONXZL6b+2K6mxP)#);A^CdIJ~gBTxh)pppPVwc +z23Z~D0Q`DDUpd3;b9e=;&qJJcSu2hNZX$mhETj(+R!5Fr>2eH>IM-%g$^;|WnfMBb +z4xx-wKwluTSpX};btn}EoXAE{?XwCq(boO`sKPr23F%N75q#cJlGL1-x7L5xUlO@B1>)={iLh-gQU0Z}-J< +zhk2F3R@m{LBl^%|v07_Xxg845WyV`%qqdCvLg$u-hiu^$l*k +z_e?D9S5v!VMg-{&+xatd{&^atq*uMsQzKOZP$Hv`)&h@&iiTgBY@RiX@-H7nAHs!8 +zSRs;ciJ~-a;}Z4qmL4gub4mFssKO=#c{uLYXnS+Aekw{D*uE<-ZKU-ep+!8B7EP!G +zC9hJ}$gBs+y`STo-s%V6PL>woGJTq{8!)(HH21~fuN&;U2NoIn=eZCW?CROWXQJ=t +zxmhHd>ECgFLu@Hm}7pfN>6`~~=9cA)bX=A$fX>+xRL +z2$JOCq(^AdoveF1w^O_NUCYZPuu!TN>LPrDuhPJ%Hu<7pFSLNAaK8}smi2BPo+ +z@>J%|mp##iWaBh13hb6wvNmU*_0MBs2V^2G1fzE;y?i&n-l4}S-mC4R8VT+y7OtTy +zW}T%V;FAT8H53G}k+H#IVcv~$&!?R0+$WF9H#_p3JOjo^b%Bt;**o<4@(n)7SU{sU +zPj)O016!GtrS!dSK=+YfyVUE)6Do9@uC-E4;SxVa6nPOLU%CVd8^!iV-~q_=wiRa4 +zRjz(?JptOnK*nvBkcH6q(xaBa-`+(;GBwcDNgcDec7u8CS{}6_Ry2Q~wTmnF3g_2D +z{iyZ;ma%Pyv?_ay9F>7aq-N{d6Gw8 +zwXt{QypMMbf}O@VYdtd!rqXuTTJIbT{uXCj_%2CjbC}_fws~78xRgEZ?^j!mY8$2v+xD+^agy^?+EnBi2dw7u>`oK +z;xxTXHYUZJ?}5p5g=Rkl!s&eK*4fA#?!8@?awV)QAT0ikJXI*Q+y>SR0-`FD(C9Ii +zffq_(B{s2rj6*lN^T1A-)}tc}>G!1v{JK0xsbu5RK@^4i?tAE9QeOHD7=db1FQnv4 +z*YYXE^}XNJ%_r6PRg@TxB~q?U +zZRj}}13}s970Cd6jzXgcCVLEMQZ}Q?z8Y}}_zTDq3~IlcNh>#N7R?hLQa$O(lK9rl +zfbU$9d-kAmQ`IZ`Ko8pq7hg~c(!rk+F!?@khAi8Uti(0yb2=uf +z4$XT?j~m4d8`(WWne|rUWBYF@quzF{1TelQZ!+sksUtF(_glym9ELz0!pRZQWKM0#Z(QV-^f6;^ZX7Q=munfzSmBclt* +zxfRoN%zMu#gDgirw6d&)Tuiir^=WBZgVHkjyGgiiyYAd(3J*T|OKw(`#;BagCh{_0 +zei|2>$`R`(HASI1hb)*!b)5RV*PT~;ZuKPVg;2r|6xZ1bPO?46LVK{$>}PGt`vS`M +z&%RCn^MuGVFBsikPnytbgyMc!5Mnp@{bRitOuGnK>71Y1jyJ +zoaLN{uMhWP`+GBjFPr5h!pwN2i+vU(7vG}|_WLbpK{;Gv+f%1Wl^&dmK?|Qnt_@g( +zz1yEgm!FAxkH_tsu!;R#Rx@d!qwgUAhjhrm*+u=gW22!aCt=iRKt;h3=!UxIf+6?O +zJ`H5&T>pSDef;EW4|Gu#=Q%TQdc=5N@iT3_B+jP;hhNIMoD7)z@~ncBzdwEY+ku(^ +zJnf)DJ}gJz$?TfNWUlHBY)zQQ8SpCqB(nC?gsGbYo)(=PStoAD6hP4Ir; +zC$o==ULe1XnmP*38Ty{@me4T`8NWI!*ua{0cxcLw!+f)}M1Jqwyhu@fVPNE%p7Zkk +z^}J@D^C*|_$GTW?y +zX$T4U0j+#M(b5)x4X@~9%>}DqBy_%BC&p-wb8Ne;-+R?VXY4HV7;&y}gci$+$U!GS +zIl=iDUvA5TZvb-~dk(`rMyzK25Yp9syyp>efK{D(7-XtnDuvm{MjqlV^2B|VJdsoB +zQK0G;`#O(V`ID~=Qx4qFV2etw(yALlhL>07=FHTEDyFH}9u>bZNv?d?@9|zrWZ}me +zoJ<=Y;(v%JGbSkTBN6P)`!GTXt*GnrOIUDb#||tUu@@G*aXiXajticNjY*Lw? +zx0Jw9$dk_PGzr-Ul(BPPvWzQQNMtA4&O>6}2Zv7pIsFXR@Y9l}#F7&FW@fI*C8obL +zIwJl&D-yneeg~k?0KZMN`;kcp&hF177rjNlE`+8;n{V&l=0Og>D*nI-hlt>M5A(v^ +z`yF!b9C4pBc%XRCc?3vYezKUI!2LNWlw_d&E5kaH%XU-SlT +z@*3(scC#lN@N`}T-TPL}+=_h+M2;k^@G@m3ZJMV(st~Mk>{>Y55Wr;u;dLAYWF+&h +z2bVb<_WeORqEJIG>9B}9C4${lxp}_x@1Qs?8akqLV%YFAZx~kihSt5LtlIjkLTdgA +zyY-RqQYbBqI%a|OVGJ8IQ>!2+u3r08K2DyoRz7mC@qL--7D<0*NBk(#F);Q_wI0%;t&p?# +zd@de1cSk(Y4(?@^^_*f#aX&(4=U&o+v$+)8n9ZNRE!_vJ@=~7n6GJ>Qoy`Nr46z&X +zn!fahhj#a32b_k!RpeG#Hw4Qc?{ob2(CWn4H+;bYZHn}`CFoGqD{P3#))|?J{V6q_ +zUss@0N}?`wTOCqRxt#YQi+FFegsSQS*joo>fiMGYaOi+u#g)CK`+jD&>3;RfwRJhg +zK+C_~|C)K3aFG;^&JCN4GI!&MvO9eX4-<|jsya7LE6S#~v0tdG@V;JLoB{w@$ap5D_9bK6rL-`Q9&^;$x)p1MbKvrPmyn1nW)Bs!TCCKkwsmfa) +zPsLkDOf$LUq6os&v=G|H9uplavF>k5((>F2L)i7WS6|7e +zm*XG7Fv&sC@iX6%Xz^Y?OlDAzQptn1kH#~~#T^3>>FPdh-qO%>3gh;U9N7f8u(a`s +z*FQ!hv#ldgZ#BI&HjW*cttGq&J_)A}%?Ttq`NGQ&s4t&hx(7&aDfe5WRDlmf(#=En +zTD~8_L{{d4(N`;)>8*jK)K$pShJukL9aE;<`xgq8TJ{ +zjg9G0pYT<}wTrrzSM0LJ!{zv51;s(bXooDMBI$Ctn%3p-9{tW?5?3CH*quE#ZCwGRm^G_Bi89Kb8vboK&&awp$8bpJ@1 +zXxgg*Xd3*gBkl+VUV1S7LFRo6DY5WKt1$swF~c!IxjC~ +z8TZ_LxEfHclh03H8Y84+MxZgL4p53Duk^WAt6D`rr}$6Va;{x)C%sa#Gg!(V&o6>vDl&@Og?Rv8=1acY={H%T~d1q>;S7p@Vqjt^l!ceD4vKilhr40ivREZw +z?yrY94u6 +zh3&yOSLqc|^-o0U0x?diW_j#OX*-{@2!FbAhK;MZ2jUx1Q39&Cp|3o2v+d2aaBg|H +z_g#wVleUywk7ZY!dXU+TX%+Ibxs9Xip;>bluZH<6y-59ScN=xeDZRe8_yCoMJA0Cj +z2f)?f;1wOpnFq=C+upj$uaS#S9aKNd!h;py^hiZC3G>|M?yO(|H-Gy@_k@K0-US{5utW809W(Q9!~^eul9lwbT6~If?Ik>Bvc}o*xSO50 +z&BD8DM9^6W?zz^qFGjKF#dUo4@a~)MN&?Z3cHVvz3vQENQ05Y?tU7|9{OXq=RN|Ca +z;Y%(z!Di0&K9(i-Ru1q3HTeqFr;=hX>Ck%iBMs3LxbDxV4uf_pFA|F4 +zOWvvTiGvGT@ddyKfG$T>_(bN1RY}?7p>C12dbE5@b{5WCsQUmoaFj2Le&(82kJxoS +zCnct41j+9w!BqZrD$o>KxIHA7P-LH#tYGiehjGtaZY;g^ATV)qlo(^_H+x#;pIOT_ +zbc}f%i2VI2_N_WlGry~p4!M`8D;k0z*x#yRNP=7Eu@M?*m_s8lYBx3QYsHEVmsb8< +z&5e`m9t6+}clCWFs2o0w-G)+O%d#9deLE$Hpj?~!XhkdTRxjA(DLtJ-$5IWEuFCOD +z4X)cC=gc+7bHuP~tsLJ&b7u-#qP`t&Ux=A+mRH~ +zMtVNmi*p4nfIZ8g10M9f!mo%P_D@_;WSjj;#bjBY=1PCnF+qYKfR1qVItqZ&77$!G +z`e!1gKhKq@bjo_iRb^{qw!ncx2>p=OWLoQFp +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 +zv{Cj%Jw1u?-9^5wd}^loXnrOuw;e +z@HeTQn<>;#88^VQJ@=2FgZabfmapNle6(gAI7Uv| +zMdrtul<0y!oT#j=gRQvYH|F}t6(HToxF?>YLnAVj$BGw$^63(Gy5pDuPn(@m0`v2A +zo#(frP7_$1^Y1B2{a91m<(hl-lUCh5b6>sA<%YP63aSQHK2ImF4r4xj-uK&vu29G7 +zws|x{VmJj*bRF=P9!{ZjJrdXBj6RgkVPnrJ1K!4CNB>T)A(c9kN~_DvAOnh@#qg7O +zKiYm)ewyGL-P4H*Bq05y=}~&cSMj|0u`2PK_dbnP^yKV!j{KC$q&+ey7!9o&>yuyL +z+yl%)41_m@-gV^uJT>z +zU3!*tRGQ~#5AD>6b6Mc*TklYk_j&4&Rt|a~g2OPX>lH#cI%u63mV|O?edQhtXB)^} +z%0R`~4SsS`@p0}=ex5!IV9E}FpFA1Qdi8_L_gwx)vG13}z2XO#SUS|7)`3g>`0Pm> +zn*L^siuXS6nv#s1{%DEu?iVKX{8|ViO{l?G&Xc{aF;Q*CI-?zIYhW9-m}inUVi75^012id*S^mQXD;C5$?%(@Yov6S?1npKp5*dp1kDg +zHN}zwrbs~vrkA~2b;{GWEUVl4_gYrY42=Oy+#fxBy|0xGlo;ZaWxm +zob$CE_k@jFvD>FfQ$@mHMOuYh;>!m<_8sY1eS?V(<*lx47pr`ViN3ga1@ZIB?OD9> +z^1KRc^khMui(lmWM&GFhO4BNMw#l54gn2*_zsQYCPr>Cg*%t8}Vc+9lGCu&51Dac3 +zscKJi-OzPw7meky>%_+>fEpud;ZTbr$1B&H^GN%;<2;<{fsE5}6!6sy1>4L`G;Pbe +z0ySDDbTi<1pAg=1YXjYHZUWs=;-iV@VHRP!Rg3SMtUI?}pZ7S;`T+3W5AsEiG|FsW +ztaEqXZ%$RPK!Q-=5leC@+$Xf`3X&G!B!Y)3O4i)lK7^EUZybi_{m*w1+m@bU2cae3 +zL$2_!Nl4UA@}3A9J}YuC{TY<;&hA3{^6e=mU%g^nx}lHyiFLJK{o79!tE=C8T)IJ0C|Gab0Ma)h_MUK`6Ba=U(7l#PX{dAe5L&$A1`L+%pHL$ +z<%$wtqfGWod9mzL&0>J}_+jQ-#Y|t=xMKOTqx(vT3-q|tJi`q#@z&|HxTZxT^^K`l +z27_Y{`1}%<9d2j5dC|Uro?etQGSZ$*q)_qx1n#uo%=FTuDz}SG?#0Dd4WIV&J*&0- +z@X~s&ej}&CRo5Zzt8>S=Rs97-PDF}laDF_ +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 +z3!Q+v3eW@k;9; +zyh{5l--r%e(yC{vxJ9cJmin#Q*rCL2a?y5&=b|-ELxr8#63$4z$s&y+q8DLe5in6oc8MI2k2d?=|MY8oLZ`0qK(~{z1 +zxbc|Wy{t4H;X+q9+*MjCNVIwg5Dsa42((x7yoIPZl{B>3QrUSoqkCMb^u8}Lsuj)g +z?MG%fFXj`Z+RA=M92oO_x3aoR3pg&~32)i=>%MUv^@xoV4_t|OR8NHbzPxSmMZX3a +zdi8=Kvht=i@R5FYa69|J5yXoL$?t87KlhW3uUf4zm4xF&*fl&~PY_~GPkgCy39=a5 +zgLzc4`Z_F7V^4lFmj9YCPaA;Vx9qGCsvjMGcM(LE6{s5X8lAtPyyxnXyyLN23TZAi +zF*R=)ChrYI7`U#m&p6YCh=C5jw>Irr5B+k8kptep>G!%oNXCA~OC!?n`&Qjji~S(< +zfa4iHweQW!wDXxL+sC;T>dYd*7I!}Da{73y)J~gJ +zNKd~o9(|wM@7D)q;X<;5t8=>DvR1+$Yiuq3u$D+2fKEex961gF%T$pGA2ONU855$ArkbIu*LFKyM@=&2iyW1~*q@ +zWG^{DQTlDKVIAdWOQRrtzgrJ#=qR>7YGsE!N55Go$;bUYd(0!l{AlI2r4{F_Rm_cf +z#r_>zgJYCW!uclLNU8PizH$+alXtxmnU%JbZy4+5t~|XSv%rzGyL*zo&x~|lGgL`? +zhV(x3TyMFz2T!9!gdjcvIVI?i-+Nkm?3DWRN_$``$n2_->muhg*EbmfwXU%$g%8;7 +z8Iv2bHyQ@4>*n2BU!Q&w{Q5k3nC{gQSV#ODC;4cXB{O;FGRgL)gLz$iJfP%yeTD`x +z_rS^*xkGbr`BQb?3K3VmoQVA!{apv&GXuvJHa&(L8O6`RWe4q3Y82w|^eT+ghS4B! +z#@=%ZI&2F!>7p-dfj_s$bM=dKy<+`Rkr +z_ZeiLBJ)Jj=QYbBdd0uXn+z?oD|@o#9#7y&@1;D-&Kh*@^*o5W +zW|yB0%=_{2<3HsD(i*dv33}h%jEEQ;W}B$2={9koN541n6~Pt;YMj +zr^73s-w^xrXp7K%fe_;yBY1KEM?kp02olT0Pu-rIYKWzTJ8(@V6l2kzxvi#jC)JD^ +zN{fJcDiypuWBu^i^EZDBr{`FFqXIXp*Qct#866q>7)q1uj-Cg|QoOmTEY0W3+H7T$ +z^S9-HkDmIHxwGd!CDkPnuRf_JgyhuU)~tS0Jiilu9Lg_6Y+IgK-adJ5_<08)+ +z!}EVcdoR&H`&|X!tI=EYg%cO#$g`!{PTR4^q>MI@dA_5Et9J}?hV?$qXreglo$AwseHSVF{YPoY6MauVB*OoBBiWI(K^`^ +zqTYaE&U{#DRB$pb0%Nm +zNLX(k_H;q4>qc*8r<=j6q@s-h+0s7VogjUOF9P#lv0-5^06 +zN9{H|H*IR^$@C&RD4wv#jS;ra@}X^yX1RR6VD3X|wPlS&*fyL>LkRf=cZ=u8hY +zAD>;htbV>dAcVX+-%*b^9yJ}Tx(W|7fHJ0@q`7XEI-40^vGkGa)%dhhur +zp}C=|yeB~YmOiM5Nq84AdDyds{a_I4aYtVSn5~f>&Hd8uT#hMDOy|=r_eigPm)Kw7 +z#r+--X>f-M +z3k%FGTS#dl&lK5n2}50C^??M@A&To-*uQlw|2*VMY2SiActj>88?PJsWo&VR)8mic +z&(|IGmhk4$|;Ioo7 +zC%XaV%-n%3C8?zhTik=bMeSr%-Fu-$`e#VNUuJNylEI;Mec~C#DTt@HEu$wyo3BeS +zJGSsvHtY4!f>%TD(ZGq%ZgKE3cr=nM{+*90h`$3k&6t~v7 +z@?}QTQ<2c(U;`WG{-6}N2uQ^iJz6oSy +zesGEquvg3QJ5ADhHRuQT)dv&|c;GW^m7CqqN3sr`LgCuo}%ES-^X3@^SEoC +zZ3sS%@t8vB;KR;yF0_Yo3FobT#xBo(qurx0SI^g~v~D%;QLzi{a;wbxlU40!WEW3X +zb05S!yVkF4fQKMFm{|{02eS8QBb~IbWh)2E>K*~)9@e_I_|SXMA&}M +z9f14Yb@Wh5k1S&cRgCytCEg%e;zU(-1G7R9tL_?4C&EYFSM$5VnA@N`tWV5r1?=sX9k^->3!_Pj9VKF;NLx4MaB0*)6LE|KR=a#BSd6+9`=#i +zHuDuSkOx8KT(6{N0FLoLuO7gf#~Dh86EcPPKH_qwvXUpAZ&_q+7wgCb&9K5q# +zM2oK7JHpZ?42R@^EwHS09nFhiTyp!XTwyd?wkJN1elz;GeC)e#)YY(jV@bXwKfVN$ +z8gy~;LhX04{KU!no7X~LgN_N$GhpLbjqVISx0~(}L(V%_Y3rhBmLQ_cMC>E_d!MWU +z5TGIUFV@z-om8LweBhzD`3Sn>oVV=71whH@xotUc4xM9$R+naVU=KcP$xfT|EoQTG +z1&?7(L{bPMsHAe=)Ic637@+EIr9P5pHuEfGAO4d3pO^SX%DBZtniIx<<5WT!50n50 +zg&cHw(%vH!8ffIHc7!84O(es2;6$FWY_PjCd4{Sdo{)naN=&KKc9d-DNWy(IgWuH0 +z!Gq;zo#o`WHs9N%Fq$54qIm_Ue0L|Llu9%^4_+v9e`XT)k&ISr`t%JIseP7U)6cL8$_a{3#6n^4L_Kfk>5_=GXyupGIt)_`6@b@oK<%~lqv +z;UjzAXA&@02zgI0dI(N(6MftvuRKH_O9=Gja8o=HkeXkndD}Nr{}gMNve7Iw&DmRD +zYu?U-4CfJoDXe~9nXjx=e5d`iyCLjI-*hIcbHqkEz6ji5L%L6E?(LL4WLJ+sAoU{x +z_j@ySudGtgV8CH7cs^cWPsH?og9kaU=3C4))seC!FjsmQ^7+)|hM}u$%Xc=szl%?S +zp3(ucGyAIbvI5x?tszM#fgsM41rg`Fyj_Uc-S=>}S`}f;#TK)%0rYRgC8xs1GrhKq +zT$W~fg?s53W`sPV3%-w4p34mF4ZHM8*_fA!of_=fMpcLNSjP>Z;i*n!-hGwdF8o-N +z#nhzeY6eK&q|GB}5YBacfKj*)*HJc`u_H!!NUIJG)X02}O6%S)R}=3A5luGA13?BH +z;=T0A)&~`O51#N^c$Ft={LNI|iXoZ#s3o0a-`m6Sgl|HajA*>C#&dAlM5rNjgLXUf +z3S>XiN)^+SRcGnTC^G`tfkg{;7B|jE;NhaA+W~Q?6BhUA^0k#^DykGfRK_zs%N|EveEm+lwaqG`?-8N*x2fxT)rn|73Z!JHlg9{mmmD4nq{bZ +z1|E1ib?nR)?YkayaFzh>`^_DA@6#$8mL_xG+M2%IbDr<x2Qw8-(yUT*n*9N +z_VqJIqa4+HW|;LfSK_sdk;}=|F){VtuWr&BfD+rx8}e}b8x#c#v@^Po9lsdEat3qF0_+8 +z(=wzw{^c3J#| +z{WM5DT?KW&OP^u!V1;G?uN3Iv$XCrOU#qdOCOQ$QoYUZH?=z{Ga6HpX%>#NJuH!K0 +zNH~Gbc?GSj2fnq8tl+Q;m!hNgCQi{4v7NWSh6URB=1A>he;p8CU*T00lg>+VrlT=? +zSr+)<$&2^6SL}%ElZ~V}UITT}@!+0#T7cHqnSs{(+Y+98oG$0l^rzz0DJjcFHs3;| +z7M$~4EbOCWdAj{AIz`H`%SC*AMRj|0F%pk|JA#+1oa5*T>4Pb*eA65|mS;wbzoFKs +z-&r9#@;#xKc%Zz+TlG%R352|j1EjM4pm-`9j%Y(17@tZPb=*R-?xeHDB3 +zhQrDV=aNRpeGa0yE$%r9V9tH9kl7NAM_VuVQIe3{=gDIMkDus>lP3ISUXc#+eO_FT +z(IaR}9vTod-ZarCoLjoqNnkfe^wcc6A>WOX6^qelDo9cL2sb{sQg6#3mWxU8oP^+Xm`2b@^*5aq +z@1CYRM~mUCUz;%BXdQ@eLuogjcyeNx-`duH9*aF(Z!z3ma%hsTUF%})84t>*ZAvF0 +zd|HZgI;~p|cYRxi7AKVKvcM}((D5Ai-a5M5k-eDetxx&+eXq!w_%P6v!($Y>S0^0Q +zo;A8(Qm__wq*m2~)-nV+K^CF>9KsHILhB;{nWH04&-i_@o?~cb&SAeDS%ckB|5iDb|-bAfIJjfx@x_^pySW +z7b~0&G{4(ORLp((t{X0UvO1?fV8q9@*zL(bNHQe~JE)$IRawhr$R|9#WLyqxpKVQf +z43!zru|iXqByT3uzx@Ro7=?u@bOsy=X=GtSxD%8?TjJ45>s +zn7ZXB82Au`Y@!>c9K!?nwR-L}zxouqa70&n&uS7r4t6guF1Od&gva~IWQ{H6)#@6O +zyw`fP9EK@AJFfs?4R1b#e6LwrJf-sVn(Zm%UWhwizY%#1$W7XVcR)#fAh$)HQa-hd +z+HLDI3?@Mia=$iXcmm^&{as%wQo5i}vl4ZZ#5!HCea938aUfW}j|QxyE$|8teK% +z^tP#1U!WmZ_8G&?F=@c??tFih?!o2y5*%WQBs1LN1RDAhbbR_5N*}EnHv2CAay}AJ +zEQ~1^^w`(kyGL8z6kj$hPwJW}A=wL&CyMDKJ5OjkZ^qYM`LG&N7A&gp;`{M8V;_D? +z184F3y=0s0;V%eid=6D%oWhhu=_3rY8q9=}M)RBB#_t2NGDY4ttOw<3$J&%3Yn4dnL^YlLJ +zL^nPb4EDgbS1`=9)!!gWRf%s(=X$KnnA%Pg`;N?1<>n(%k3H9g8Od>czdA*$^5%Qy +zUEHa?4ov*HOItbf?c!Ru{kje~cX2J|@~vLiK6Osp(*MA5-x$(i%?v*1r!JW}E4`9c +z{oQM^{BBAd1Piijbk$~n0MAp1_Gjlo0pSPI*ZenU)OJAYK{_r|t8@mYRMn>|syPp^_6>@S14003UaiTmAqr{u}UNE_-=9JDg4 +z@`C8HG9~Z}*E>X*auM=NJC^S-jy8{}Q@n3-{0rp()AzLy)bU(Wmee;vOg|gX{(5|l +zGO4b+_u3x1%%YE??U!J}Sq-o)cKbm)sQO(mi${Z_ljCdBAQCl?fc7ojy;qB*xMJo> +zb>4)BRrhOJx5%cH!`z1$^$|n7hUNzolj_c6;1B<7(n=D(mQja=*&}=}iDAgRVhtE| +z?hLhT-a0&eDP#kK>`tZ$v9BHH3C1(Cf9XC$aJY(w;qko{rmHtIa>I?Z-fU`P +za(|pQzFy@DxIM=rVuzf7E5U8FqQ0|o#Y;I)&SEBrDgsxFZgL`gDjmLQ?(AVo~R-I6s_HxQAHBUuc`V5H@ +z(M0m(l!3jOM(-0?7b4v_bKZNrfb;WzTy728#y{iU1pv^E7^Kg@1mfeB#ZX +zOZ}VUp8q&1JMviH>V36Y=q>$zwfP<=+~r~ES|hr-EV!Sen?3&cn9kz5!DU%G_9c&; +zxcY6=Qaoss+k;NB1f{aq?<(F$FWDcBQ0oAd2YR)N4~J%gD)SsVj|@sTMmc=!qC@6x-t4*I$YY#Pr|J#eKEGi(?%vy}4F)KNw| +z%=Yx_Ddkduyv@SE_kq;#qjwbYh(&StBY39O9PJMc7iR;_VEYYTD(kd<^Y1aP*|Zx1 +ztL!ddu8GrVc%B}x%7d5d;3YwCxu}@C)T<^|@-e`( +zYC5o#jm*Sv1U3-SzfOsa((JzbHb3(G^)wTlpbaE*~LOzTl6=|LJ1Ybbv>s8(p=x1|!0p;4ms$}L!Ogw~kNFVs;IgVdg{!=XFfU_-E1Z3cme5E~UU&8!g +zJYa6M&R1bc;EasRE3t##wi|)Nt8iA?Hr4{kVjOeQ_)T?Ry>jj{@o7_c#dFG{<4Kx} +zS01`$BRrrI+iUrR)0KghsHDFO9Kp!oht9D8ocGz#AFGn2xv52TOcfG&IL05rvOP=b +z6{qoD$ghYGmAjxeCu@BfUFR)lW@c4+ +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 +z2l;$PL-php-i5vw +z^95C0YGCsOJNKFl-Mu^4pU4)xR3WWpY3D189KwCd7v)Qy0{$#e9SZ9(oiAQT6W>Zh +zz*9DWx3KNcHvJUAw2Y#DUbA8op>(tfav;%V-Av`1q_^vgd`6^nL*Bo`#pBC%t%N7I+0cu!4`m*9J5LhDQIiY%CN*iO +zm-Vc@VzqcU^FAQa)%Drydm{?-F%*E6?^;!=9C67|68J7m7b@N(*hfx{AS$LK!+kXQ +z3wd~y?dFj1n2Uz#BBY9k53jiH$fi80q8Z>nTH6whU +zs_Itws3Oe9dd$Y96;l95IQiJ;J`Qrm@0Xe0M-NQoeiwy1PCwmG9LUk4!Q3ahCB^Zn +zme0QVOPqMa&%FT&P5MRn&ecfjVM=RQU1`)$RxiX>(q+@t^W-}SQEODC{D|G1M#a48N$H=oKc=-Fx{ +zgGkQVs}GU9o|cbWDY%pd4U55)Iq*mphm@+mqF#eO*n!PtPl@lY4pV&wen~?}Sm1Pk +z>e9CLfPM}$wRFkxAboO#bq~+RV|%HlLiwmA9Zj+h9jV-?P?2~u;lY9{UjgmY1C;w9 +zgYipyi@Zn)UYGBefnDvnZ?(apOWb}%bfXAw>FJX;fv?2p-Z^-(RACQG;|o|u9^dS|dUdY6 +zVvCzqa?e^))8mnGb&7onMG)8ZskfmyJt$8jq-+*czjX)Lu`p4e#8)`o|+IGX76L;8nXd9NLk?nnVNqg&{F{p+8H2j~Y>UE=dc@F3{l`@#P6 +zIF7X9OI@Z(t2a@3x5F{Eic*17CS(2aGDJ6wvv!0*7IrNr-o(b^6?~4m%9$nMRPwV; +zCRSG(;FMjQJGJyAJw9Sr(&s!LfVWR&99(q>KiPdXtuUT;K5yAV#^u=0;`ub*r&6Ln +zo~Yfc^~7gvFmp5A@$kSB427j{-Dy9W)s3Xd0j+ZNsoTqSABQM?l?c%wVw7JU3@$*! +zq13qG9t#HvEVHiWKN~UZGCD8gD+qfG_lcyo@5oZ8o$%UQ@RtU$@jRg|i3bd(bWHAz +z%_eBKjB^9AhYYR*!F-;t-5yhX`ye`Y)rG)#>_)Dmlgn*f%8w5P_1Kw2>=8 +z{N|-+s`~Ac`&sklb$J!xJ#M{~;lY5#g;(A*r-Ea>dSB@b#5-fV?8>0p?pxGypw`dO +zcfI7wq0v)%UHn8M9KCP7@w_7a|M^3DFNdg{lPXVmoV<^iV})pemKHxv!iqhBQwVi1 +zE*`pQpaGO-;NPw+7c=dR0ekvHf( +zg@1P=-kLzNU{SRFt`&uR7cJ&W%Ys<(>4aKZ^n`FLecI`3`A5{CBi5 +z`xewlbo95)WZHwO$q7>R1@%Wf-EPmN%>E +zbGGs=Hyjk7&+pD$nQz%BbR=#ZVT3#~-!AyQ(P{5J1sgW~N#U`!9Mi?-zC#@iHymvHv>TQ0?6i<5T0LmD1EL5jBLIOoxaBRyN?EC-U2#}_9!0F +z7<{RYQ77vj+(%3)=M-!v$q|u4BKkrYTp@)D_n_IT#N*y!Rx{spwZK=4uHj6oH%&;! +zM%M|lA;?RG!tTY$L|O`oB`0@3v%Zr#M3-xFE(*1VGMYVhk2j)Kg635ZV)qAlwB+~6 +zxM8>#k3L@UP&wC%z@3!Z9q@|F#!W#vS)%uiM$ehXUihwoSr&57Q?etViFdA^uh-b( +zvf;_eLmp@1DWds;XlVs#@15r1QP8bSK2}|Jw>1n$j?b#wA}zt3}W +zbNg77Gro6nP;>5PUtsXH| +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 +zD*E1@HM_(BTi}|5UWXh!wNHzCJJbvb(1amBV +z2+X84V|$KGrhkXV+6E%opWM|gS#ZuxQlMVub0}cd^gzh$GH$e;yXo0D{^&|y2>P9r +zf6v`zU;bJ+NFMdxC +zUrSf`x#D8A(0&&&QKxfhHPd%7Jo)kG`{0i-m*LB_ +zd0WO*%d5xzC|O-IKjPU#_r3QC>#Hcxfvmnc_cPw;5)l2ASNbLS&9^da*CQTVFW~#O +zZhJ&^29iB~bYB*Fz+`KU&z3-g|R(JICiU +zOQ_)XZa!|Fs>3j>qWa>64@{kwhC3M?v3B;Tm3gmm5Z4>_P@Yf*Hk^rK5KnXoFaUEY+EV0mp9NKfg +ztCgb(UtuJjtVcv_z6h~OaShTBB&ub@CxNIeiaUPz+YJdX1)`nGn)Fd?Tz{8^&ZR_h`fWb +z2*_d4SFhhkZ4M{BzjUk1_$t;BxfzJow>XmMRv7>TdVO;0FR0Uu1drnJsk1MssY#u} +z2CKEBBfd<>?j%7SW<9GBLm*PMpocf>jDI2b;HZY-VPa^#d#=7H^sg&`y5$u{t{Gsz +z&N9dN;i>QwB~8NLyzf~zrzR#wxx2G%iu`qrPr3!#XXO*j@B7k&J9DMi;ec$Bz7X9y +zGOY0y6Lje=X3oQc3?>vGt_=|RfSyV1#pzc9z))}RSxuW%{T8%3Nw5(tMsL=ucE;j +zw6cY>pJ?1t>y4{@Jh~pnRTfmd+>wknV4snC`2v3aIqX_$veypB;NZeT7Do0B^<=o5 +z>gj{R&K??@Rh{<*CLv#Y*s$(S%E9;bEOS2#9Wi`V&3q6&Yz>{8Ut;3`_F}xZBaeX0 +zg6rd5WH#LX-4UdB*1E+0N&Jk94cwS5?NfD&^zx#8W1qvfpiyP+qtb9%_T&kF8{BbS +zMDgV9mtukL&9@le^{I6P%BxrBj1}}f?#CWbLdciyF-$%Snd6fHN{5!W4{fYMrXAb| +zCimij=(zNGEyPu9x+i2E&u87giEk5&XYmRz_~SQzIBqbrMVb4j%!_WaO0AEyU4G<& +z)cmZ|r&hrI7*5+~SPOctLo*7(r)lE%ah@21u=*2`KJ=)E9oc(h`;;0s@BPg64-W(t +zzS7qyeuk{%G`C$1Pp=1ifWA(#Bt}2Ox!vY3AmI_o_WSbV#hkn@ccE@P@OT3si~1Df +zyNmekPTC{KurF#5#NPF{T#1&)F*D*Cr{cqX^vP!X73!C^eAeD7qBLn-2eyKpr{Eu(RZOQ*W|+-A_uB(ebTZB1#xnY +z!sC1fpMNPQemasLftiDsGtUu;$5`s7typ~Hav0J<$4-x~qKUorjMz;&yj?gGLHcj@1EPnN9bsZ3dJC5whytUqmvL24o<%sgR2WE +z=N=KANbu=_GuC8IuMHz5IRf5erB>9vCcz(oiBm%!>C-b +zJ^@>a{6g++Zw%DX9QitC(LmbseN+qjqO6u?V_AT5*qxBk_kY2c1oYSq{SHEh#Tc4t +z8y(}itJKOOeI2)fcc({aIv?4eRNHX9Rd7aQUx~xpxAj4)>%cINTH5Usz4LIG&|dI_s>Lfr4H`@D?qWqyy|;~BBL>92wkJ@C-6%E0#%%6b4|#ro5>Mts#>Z?)!q +zTb*b%2q%w|X=Cj1#mnB^geSWKzT?Yzpt0Ud3nA5w13{7?kIY8qjn*@@Gr1++k>iI+ +zhFn5#&R#RUr#^x7tCaJ_Eg_)n4bjZgv|L|%T*P+>LW35K+%VW9=UXF8bcfj&$G5vm +zVB0+4TC`!uZM*RYYt`>f%ABuH=H#K>8QNiLUSkdu!)qbJ%ccFI_6at +zVjw3x@2zXazPM1n-#vcBg5$z%KllxMH@&P(=Pc2F_>9E0FPh?TmpLXFYi07}-Ex-W +zd5{xC&dm>{^mjuo?x9t%vU)sby|hDVp8fdDd0dS$R&gKDVpO`_!>Z>z_7qlyA%clA-o@p&XvKSXt>)}H*KABQ +zr6J$i*0Fd*G?2bAq7s~<4?5(bK3YGJW`6YnwNJ3 +zGy7y1S3zCuf%7uA`J4%a$8L!5emV$jU}9^k-+>0`LvUvr=7N?9#%-49{5lNbb7IH- +z8Z-CnAL_dWC%0|LLcFGG=O_lRaw!m;( +z8W-t*4v%zs;-2M_3{p7vWfwYrmj%3aF%_2#V0e+6P?Bv`_R$eO{*r@zO>_?BbmzOT +zzkpRCXW)(-(2Y+rVsBE-NQbuHp^SphrT^;j1#1BDczDo!?0AA0fkP?wCrpC5{(!ihy?G1OQ&L1u +zS>#1DQ$Gh}_=poERi^5KWufndlGOWeH4R0 +z+`{#a*w<~h_W?-G_rG+6f*&7OIgC +z2EX4w{Sle^TnZ$8`C*y?f4D2eP3R28cf`>67zNd4Aq(|;mD}RS_v>;QPeT`wxG7xf +z9-ml~i_^=?6N1xqXxllnMf2oC&r3Bd?rXTi^;joRVjVI`LTTHZF7N$d5m`GCM7)ZB +zIK`+Am*vg~JY;n0B(bl7?$v~|*XNWd(>MNJmF6`L3H9AYZ%Ad9FKdhr-kS)zbf)*8 +z*MI?M+a4o}i#Q_JtH05{$8jy*<_;bNB-1^lb*vG*Kg%M-Tgm;XOB}9_O3s5b^{SW; +zT}F=Z?1z_9JU?f3uEtcmw`sHKK!;7_l&TlLq}Dxx@h(DcB_zF+$KJ@g>U=Ot)%k;RQ=B_axqk-CxNM1 +zgD&y~C&9dY7HZ4A9{h7IdSuVoOLAVGagWn$pW^@|-{e;k{X5;nlQZG^qxJilus4rJr{*FkFMXdUZI(yLoZRe!%plT +zwKX&Aqj8L^OGQAolJ)DDR=pjL>u?b+#AZRBb2&QkIvyxF6px$G&7On(3h*)4JvH)Z +zQooN2qBF9W)V{NhN}ObT)tL!I(HEjivPQ+?ECRyC!}bl`ezVZK5NMUX4uFvGxqiU) +zxS=WMr9giv8qB35w->*Dq+x7(<%aYzC(&c|Qi9d3J4CLOpf#8?iejHG&<*P;kwG-X +zO*0(0*$4-whICdjsa-#vp!;%ZT`l)0Bn1Li3FaAn#3GA`nkKF +z$oA^*GCNFJ4*UH)So9&f=T^EQCh{Pm?{mEV1Z8wbF34Yh&Xwd3%L64I6Bkn46}Vh@svFxFOFce+cRDvvkN +z;>r}#*px(7hw;aR0n}mLm +z`;mUQujCu*XSeyu^KU7@HGHV`IO5vpWn}kjK3e0kLyv0CdFbGUUC`zC!$AcpaIUt# +zg6i$565#sHniI9pH|u|hDIIQOjk(U<8-MLUUB*0*ZbfuTe1n-P$6*WNYmq((`Dx)( +zCe5Jfg9Pz;>)8MW-`ZO>i})~bZ~$UJz3AVKKHgEXHxO+GFZxTf$KCGUa$LhWyO|S;vT41Dyc2~DC0Rc0pj(RS@F7FBl`&JQ8pU~k{a)cUM8BT>!ZG9 +zhG4NI2fqpUN0J;%ia%r0rdbpM8)RGea&70StLNNyUy4tz_MVvg>V&TS +zD@C6Nj5`mMb0l}q!$F#>l +zA6ngcTO|@6b;4tZcCi~STQXoI8SEtN6^4RCBKoz;tXe8ui#%js7qe5nxO0SLO-)Lo +z&Hda(uUvkxC=z!>nq-*oUiE;DO$VQa3)UqMzkXD@=pm5XeCnv_uspP58Xw$6n8W9w +zTV~nvJi=dwj$G(E%EF;XFxH#qvqvtk+c}L{XZFgmyA@~n0S9~q3J%Y`NZ*t=6_c=! +z>vj$ES@$Yb`9v-u;5+e{BGRu}T01E3gC6(*YZ}QaLs0nACePxdB`23HaVZfYctk}m +zq#0!7SFUTqvmX=tUDrAI8P=%~G(olod9g +z!(aO`O&di*z&4D$=kLCEgm=Q!Z!sSQbleyln#aHS_-BLQKAmVi{hsHc2xc9c!@ +z+*w!S>yx6;65JLOejncD{BtCm&(EvDsjs$1Wu+H%8cUEB&L~HpuAC$Z^YNUKiQ~5Z +zw#NB`FMYS>v#EGsjrEX&cE2Ce8cJbD+iS00*?>lGsaY|b)JWV5j$Siy5N1&3Y|djL +zHJ=_-v3J|6yn87RY>5iiLmHzoeMQ~*WDL()6U;r$J2r_%(`eg(`As9GB#>&!5Mx7K +zg_Q>i>uYw;g>MD+`oh|StB0gNwK*kIm9w|TGDlnQowb*aJXlUNN1Yvt`GiCNDRK|q +zc?-V|qXTz>NL?!DYY*2jx}AkbTn6(H{Sl5Cn7rD3Q2=mXC|uHg_(Qt6$*#^hN&5B& +z@UHlSaPp`@%Ah@b#G3NrZHE5TU~)?AK%d=57jx;X=w}eL@#zBdCG*m&N80mi((C;s +zReN8F3OzFq#MX)7T@r_$D+=y&U0IJnLG35(nycH%J@M%0&BLwhrKcZMWuP=il}Cxx +zIB%3jVRGHz`YLs*9H}Jf7Kjsu5IySocD=K|buZHtQ?OSCx)U8H9lMogS2kIyrNSeT +zAICG}?xwRf58amaATS|iSRF?wiCdGs@{M++9s~UDres|g-2KzcLWhiVZ@4Rwmv1VDy>$khzyod@>lj8WUi?^unWesq*sbDPZ-6;_42#}SK=id +z8~$`?wY`lqKf+>t4lL*LTIV_`);w}q4axnoDAlX&G9_}4f}KZ)7ZetR>QgT5BRGB5 +zZ&CWhP$S%81Kv=&3{EE+jpgfKF*(gvuFH5cupLR~);^;abvpe{=pi5Z&s<2j*kXp+IV)IB}VfQ$~xOT4Jj5YYY9pjA8o*+F~ +z-xwQMzKZgAMKdE>d6UH}qJXfk?A?MwF#AqLZw;Q@*j2|*@Sfw!()9!MsP^2(J9d2^ +zD_8fgCz|^(e>Tbwo8fO99ltLLZ;dSGk?n^7uZX_ruK^nSBu&eg$?#>Sd6d}WK^@C0 +zm(JXnlUYE6QO%cjE{-Yc%N=2FZ_8AMutTCuRng$cB_Lv;FM0_+*@o>oN+;*U6`MXB +zH)GcDyj>iUR=fOOx06*~==WPk>MBhd>A7@QZdfKEi3oj?EvsE}YS@N +zNOc!wu{gj84c_8YUt{!xDJ&;N&z(m$tj2Duc;PE*S05;>hfd#;T?B(hhyAx7A6D{J +zJM<}vHYqTh_XcePRodQ7>j(6mbmBs4df0}*oofdKXJx_JcEi&+uwKqis#ADyyq}JzF%lX@<}Fzz@u3c9-C&Lmk4CL +z*Ok6qJT8kXSWKOWS^ecPkuadNUx;GqES?X=9BBQL>Z +zn_fr2dS!^WzRru!7lp1cQ(R}8_bLPKiULy~y7Z-T!oTaNfKrw0XxrU;aOhyyQq(G_ +zHCSKj$-q;^9eY+HL3Dq-S8lP>G +zPnz?5`q#&3S6U=+XY}z82yl8KU@a}iFA@s_hd`i~HO1aY7gw6^_AO~2D@MbN&0HIWLQW#FlIiEfrr8pIh +zPA4CV{^n}l_ku?>ZdG^gFxvgbkfS;>&wQdbj#?BBRF#pJnA#86)rJPjn|2InrS!29 +zEAooBB+1jaZeJEX^s~)Q;OBLrW~W*LC$b-@>Cc8Z*yNMV&7+M(ZY5FQm_bgaEP;&z +zoh9ToKh2785g-3(X>8n6mR;!iSWhN>^VO}WZIsS@&?`T0+ir7tB@f1qQ^%2U;*KgV +zM89>y7?1KNBUPKG52S^TzeR45^B|3GcRl=TO(oiQ!+7{}D5@I{Ru3=J*W%UEqX~e$ +zw@Gm;@mwcryV&1Uh`oIzYbz(?lu2=eZy!thzSw{q$nqGuCa9$Zi!DdSUT*uRQ2w5Q +zECz$pw3l0zC=X|23e(KPZDZe2UMEVo%HDnv_sLmjH-AWmP@46gCbgAAe#@5x= +zm(?hb@r{MJLH;P3)z=c(&b^=IV>tpCtGxV`uc(7{`$+@2|2sy`XOedARqfcB!&v+2 +zWGho%{S(T>noAYNMkAL2Q7=+Xx@9Nm4AR*yCF%SM=aOio@`T@N&ekMV^d*&i>C{qy +zQsDuv$#r;0+ajk>^kgiM%j(e=fbro4BwjP>PJJ%Es +zSgrsfVTIg0Ugb!udg(Sq?)?tkyCT2o_HzO)QB%TZ&!ZuG@AuOdnr(C` +z7TGWBD>!A}bokYgE5h3RNa#I=&Z|)mvw6Vh-ESkUW0Rj;=}X!DoGX}BqD;O?#zy`Ep&(8sg`eO@zFj; +zq6?j@xH%6JpU>%Bekbam7l)~tk1m;5K5U@9o$b6p+b=OL#-YuJbqHVTJ`8+C{HQ=k +z&-QtI3|=)^g9z@st1>TJl^7FGFnnCT(KVu2OF`c*c(tKZabhhV%Nn6j({t)QR8PnWhoLy`1_u9Z!86j^ +z&etXsUqyO5q&5ocL4ExJ~+XB +zpnFgdOvu#Z(<+NlKgzUGGUp=J#YkAl!))8NScPK~NaEASON|>jViizi)p(B{o@#=F +zrj1}~ep_)r>5_@1tn{y0cd7BSVw4*|KF%ihrLX?(6VMw94j0`^E%)p2GCo~Z;n>|@ +zH$gwR66ix`STH5}WxC_!=+UP%tU;6yUAz7rChCZv10^XwJniwd*ae1gc=K(5iA-X; +zW>!g(m>gaAh!;ITDSmQkHP-pjucZg;4hqBjlm~(_e9EqUe%9=V>hbJPfy4LEBEMH< +zZ(-|U4G3~y`edAjVJhr#cD1=3~2X0jMdB77Mgl&GWy?2&0r~0#`^t49= +zKuhDGI_7>7{c(NxPrYSNtiCFds&2S-Y388~W`;xXjTteGr`nW9ruW0{LrRJX{iG|JHMLHN3LhUWCWVkX*tHBoTw!X?g>Ls?hNu+gr?U3`Vd +z@zN!>W{pa@K@XRbrI+tM#&A>e#%F@P7wtPRz^M0pkYW9({#M7sI9K2HAhg^LVB&us +zfarE5G4SL|&Zj*2J3rv@QLkF|hXGw{4>JshzRFKF=WBFX-C;wZ`UpReDib@Vk(i)w +zNGdrIV93((%5OfG?XcxNGRGgOFqg%8AGNu9hZ~49EE_MJ0EPB&9oe#(L}bu$UYe){ +z-ky@2W^84(ON@FTH!g9VY>%QN@F>@PnPgfgPMa&7JCE-lcGtrf>=Q!4&_ZZ~O~Xor +z^igS +z#fRFZ_Z)-dl2YL-N8r_*X{$4zVMVIOXW)PK^4QF!J&BeY`C#&catxoTGnF6t^l0~@ +zoWiU<)KFQZwjI_W-iuszo0)?iq8}dN0_SSJA`IKvD9^v57Id3nv8r^db`siGT +z8-Z7fvlaq1&@JwJUxW{re}?Dcy4<@Z{;5_oZGlsXAD-TqXT^jjf?*+&F1N(_kFaaW +zk}OA+TjC>rLlCh4CB35?^=95DPY*gPD=OTtt^hL$%uW*2pXON8^dmZB0tM^9eLOIc +z-1w1|UbePjnB=oI?WhkVa8E16wLJ{CcyZc}BFqC`EIlAoIwk~#cU3>zLe{=9pFd@K +zO=)N@C0~?#Xmnqo%-{rkPF}+}9=N)p4^Is}ivKqLaXR<5*4Sg2x?4V}_l%UM-o?wz +zcrNhIWKF+)0Pza>T{8~1V_<#SAN~wqyJo1-10{y;y~JG9*HemdI;HDSV0Y}}M3v1} +z-nM$<0=$h;Yp3eI)PweU(zro<(u8B5+#lb2`(hDXLpyawgRY$LQG;eV)`^Co(AD~vQ5)OQ?5McXccT0TNZo+Jx30l{c#W(9!qTZ6a?(z1L +zAHLw3ef6HzPc&E_G#?lIw5$VdPO@4_c5u5LM@sC`&l};kaQ3G%^>1&KJ;A(`b}8H| +z9z&o57pH2HeL^x3CuXT!<+`ZHIj(63h=fj}@cmR!&dz6MN@;#NZr%qUl1^o| +zHleKZ8ufQk3Xh%wsPZ}6pj7BA@`?9e+*WLPaVEP`0cWKP_@3F)ZzP)@UUv?v7$u2q +ze|z6TNU!JvP!$|9Oo+;c#SagXIrhn}Oo+5tPg~IC8!Y&c#n~*Q +zBp_P!FyqY;J1u-@riva~wG*}s2*elh@GU-$a|>pSsqvVN*1FLoG<@=woN^&YUdeTr +zE^NMd6H<_y=6%K>*R~UWO3P_UwF+>WAaIl{=%K3yDSWj=nWeuYnu@fQ%Xbe)z<4i^ +z#%5F%?nm(TYNgBD`MfcA+%x!o7<7HrZ=Qx6$FQ5nVs?PZj&hcixw=%I&nS^Z{LU3= +zui#^(2uWtQ-SI<0@L}VN +zz7Xe7n={CcOWK)FjQ;%u+i`jn|FCuABh(k+Q10F6xqW%uY#yXI2%3$M@-_tY-*^|D +zbc8saj6GR;OfwHH!S(af_+Gr?az2R9LeX*Ji|c8AZ@)Dxc;F0S^ug5ke4D3Hk1FcM9l0d&$nU~9ZtUoJJ;>WW+Snu}m0!JL&7ad`r +z01Q70Bl{Ng0`7zG1GW}_3TrKQzLIwjd@XwP=_8hYEx`#NC +zw2r(K$ECxwaku_@Z=^QuBwFyRc8KZ*QkJB%NS6+s3H5lWuHKg;dnt|YplWy7b@m?A +z^MGj9V;%eulZGBCJSX{759a|x`t(PE=EcQ<2CL-0X9YVwj**@7YRr3GBqG6&(2I#| +zhr4A=UcYf-3};vl9u)YDhJlXV?Ax7jX^W27@xFp_Ip(^XT~{!Q4yc+fk4IYY>^C#c +zMlyj1aBhyS##OsHa6ft2<<@#jZ2UR>a7iE3)}+&)stw>(J`Xs`BXz!ylU?Fhr@yfS +znm_+k;fv=5wmO`@gIam1c0nGdJVF_S54m#dac6%O&2+z!IML5P0bAfal$YvD#^1e_ +z?!6s!n#kVozngz%_=m8z1^M7)Wq7C9L(+*AWp%{;E+;g;Qi1xQTLoP1VUFHKdMY~^_88l8$zE$1bNN|L_S_U{V73^Z|!9+GvM11N+^j) +z{Lc}XQrB2Sj}@BSdx3@5a=RStvE~8gq22>$xsmbY=@EMo9%K`H?kALX>N>rr=cLuE +z7T1w(bn2_Cjz_Wb6YS<`gtn$DhUET<1g}1j*1Mj`w+@i|^>brd?xw-Y2b3Z1^6eI{ +z)08Ucc9-4BD;%e!($_`;!C*hxP|?rcrO!PgJ2!Cdr5jE$0LoFTcd$EW&P(ahk?6cI +z!OGySD~L#v8id}iR{-1;#%JI*MZl~1n4k?!DFc>}44u})AdJXbpLV?*rGWFGCl_j5@7HX~6;(p|<JFUZ +zrk023UvfG`(8=sR%r5s<0LBRkAcNqHho_G(%Wz7;mjd#S=M){fUnkkt*xCSGfYz+u +z9MbL^@`y?rA@hd48l*`!&240dxKy%tB7FL)7(4)r +zC!*iOmz_TLUMPzb7a`hv +z%S>fjn`!A2tjog}91iOWzW`?&J6D_8qk1KefSr4+t`$K+96w;G +z+AcEmPoKh>UO#y9R&p@j`zrfq7dr+Xr1z>{L1ue|OJ3a8l<9p@t9U;vKG$^&A=Id^ +z4;AI$a2N*Ntf11b8Ri?obVNXV$WYi7S2ROEGg91QsKyDzX54;nbyVF+=sP^4lX?jC +zBInHeO%=*>Z^UPHMHku6Esi2vnsO;Y^WaYl07+MDf_r+d`E4@rp=;>RL-fe$%_^@_|bvSHcLjXpDv~&uw1bz +z=Xz`d?})o%`FQH}%Wd?L0F?x)fPsT_&s(Xw@0ka`OUyNw0-8NkP*c@%7-uA25*31a +z$p)&~wEnJY+i>y1jhyp9`XFg%KeVkjbjL|b)-lPuH3%o`LU#Nc|APoM>?M%lVkL2lx>LRjR&sg9%MLH#i=r$g{nl +za+g=)8OH)WKJrM_OV{@mm;g%QhDswimqdHiUS6Sx!RaA_E_j?c@tc8Vffwk|JrnVG +z-$3_0qZPdwupKo}V^F)bx{z-z^t +zz9vZ!P3>Na`o=xik(~n`+U%HnO{?xt)7T^bL&$Uqg*ML~7Q1feCD(4V`A#LJxlJde +za+699C0*u+^cv9`<;CdZ(!>ZXx-;hnWQ=^G-0MrnB~+9@2l`;gO*%5AZ^J4tL-4}& +zs4yDU5^jkDpKuW7B-na!Day@zW=?~w92#rr&(B%y-g}!i#xNz2HABu|{y)QIq-#Xv@&fuo!DK%kiUPI);!)((U?QuyG=>dX5}({=IHh6?%R7L|r6B-#p_9q_bB9+`zu`E4jIYv&dq41ZB@1 +z>S3`C&X>D;$A{Af5DySiKB}K{>x4cw9+@BuSH3$47>0B4&(RT1$Qe5Dz&K#y+NJ&U +z3muVQKS>bXqWIKGu?p3c-5+^aCfjD+#nWCM4UduJM4zHMD<>%UfJLLl5k<}fHbVs| +zk~l|I&t?x%5U|co@i_O)^6ZP5sJQF^D +zl%xCk8Y!oLH@Mbk9%AXBDVcm*LdZ6yE+08Zq}1F32TWX%_|7BWheN+s8LE63l4Z2H +zlGcj083h?HEPyv08-1+$2usJY1@(vA{DU)xfmtO2MyZY;Nglf$pLIURrB89Bob?|1 +z9DoT*PVXzcN==2ZJJgDGL>B@+1K%q=xPtwb^8uruXU +zFi(-jqe_htwR8Ij+cD7<`NXa#=#i5faRhU=C^xp5T0c{dy0(_`AR~lb2%WlI{D_Dg +z>;dD%dx6%rU<+See19yY$2-qs2X0xyq52Jt=E%_-mesRbqU_L*Q6i8BsbS!nDP2O9O}zvmmzh!RD(K+KE6X>SA`5=S>Hh!%s{5%IggO1izA +zbiZ@Ji^ABvK?(FZH}Za#%^fgJpJ*iS!%i#u?P?mg<}euDyKTj-!j{ +z_t-i5%HU(XYZitr@i??Ne$B+^^9sBVwI4j42fDWzgym6H)Z8ib=6lBe5_1 +zhqf(BlksyaF`!=kw0A(@41KnxC>JiK(5nky?oq>S0%M^1#!WN!V1=DZMT<#P!#S#O +zudgJ_8m3oN=I0dq^&OFNfl`-(#MU8`Cg-;a3r^9{SsX6zd+tn-K9G&Uhg--_>$!tC +zaLHU>-sBrt6K?t{7aqFCu&MgyaC)WnRK?Q6rA2AAS)<3TP`eWD9+dT-@Vws2C;Yv+?mt;vVhX#j3sgY+U}#9uf881bIH>umW|F^ +zTqi}P_g1oydZr9TXbZC+Q~sO|*O}TGoAS|pO-^{R#CGv~Q?c_?1oasG)~Eg?$IImN +zKc|`labWHMK+HarFTwDByP&!*CXoRJkpr}N-LX{Gi$*ph$1Y$I9p8ZH +zHG3Y{%GA&b!tL+QvcG8pnV4?UPgABM+~K-Km>~iXz^C5qY2VP*%Vu!$U_QwC$uiHw +z3EfQqj`1NEdrT;K=KwqcpZHynVbZ3jcEStATW6@H;gg=~dmO+6U&uKoWL~=gR-&zp +zdsFUs(d|)!M(l?(K4okL{;Gw=>3+b@_qJ@d`Tb{q_HuS-9(GE_yPpHGGCw+QL8Ol# +zzwl+P(}&J0eYb#e$8xG}I`@hPf$w$lS#buK&^)isJ`&gBdf;}R8wP{<-eVqwy!V>i +z)h78)5D@xBHhdb&qgCS}JmN@qYW<9kMTL+$)VXi7d>YAW2QMFI_IPkTDWLHt9yFI% +z@b1^VbNGrn~C`w@;XTP7`&Nd0u_{I^RBZ +zjc99Ww<{LxJ +z7e7q{Ka;ugau-RyPq>h>d3wn}8RoMkgPrBHcuQGDa3>MM;4J{5J6KmOuY_ +zCFxCH2SD-5zb-F5aX3ifLsz!&q6V%d)JGlw9@?LccP4us^kkkFDLCpAj}UKnhAN=0bpoKy^;?(ho5d121&Z-qB^^y& +zNIaFFdK77gR4Z8-fm|?Zpn3=qwrxI}Tk%T+mGu4Ug`US}|9qzYiMvbh&Fq*3DHSVq +z78UuV)Nz_$%$UPBpMR4vM8jY@d`unIN1EF{nK3LC7SSRFKa2e-4E13zHma2Q?P@a^c +z$Rt%1Z)S_EI+s*J@8vNJ`TT@Pz}|*=T)%xb#au{^Iu5=%wJQ0Fc|=1WkK5lVU$5dq +zCzl=w@m-#4k8w=H`v8);dK%xW_Ud~4U2X4hZls~D1a`kCzwBENaa*AD1AaK_0GHb@ +zOlB!Q5&-gPY!$%RE0+&Wy&89@Lh=$=l7*xCNlVg-YXh*B6^{V<_YnuuP@`^yr|3X3 +zYA_$kE4)W4(i(&*?{ydmRytSsAmcZoG@s>AfgueQ;&(m0auXjpi&&0xU0@2>YaYnP +zuYHTlZWsj_(}wPO%=-3LwmxjTB}SNX4nD4Id-v8iB|+MgchNE;$>wuh_V;_u1pV@% +z@(B;Ra}FKcIOXoZZL>y0I{x7DH*lOQUOw=R?BA3+0)ci4?1txb6g +znEG?nIQG2J$bdBhWEso8a2woE{L42#D(ZMG3%oApN8R(CneCOj;IyM*_Y@?rIT +z1-~OuPvr068vl7YdCy}iolPcJpl^qBsbnKy)F+|)3E^G`TP8Sf6@#!ZxzEj>ZvO^j)!a_JXwyLD0d6?b^_W>m`N{gl+L;^7}jJEpRBz7hBq3 +zbuR1H*rSBL^+}WSBQqz@+mjMp?@NGFt~%>%p$hoPlKz_V{!|DK12+ab-&%O+d!ltE +zAmUa0M?-m?F3$t&smAM**Z|jMwq5NJ>Wze<5apM&i2ZV;5l%B;A5<^mqlG9DP8OBm +z(A>&t>nSyZFFZb89p5ox!Bs&_&Z3)kXHGHTgJ1AsGDE215rXLYCUGaF-H#sak$4q| +z^ETfNlUp8cfIgo^f9W+ir{gFhHVG8W$R1#d*12?u8(jK&`aTk$>@#P1PTLS@X=8v1547!H2z0lr?1lEkM%04BbZ# +zd}M3@U}_scoyMsf +z&T#3o;plI_!knY`8ufVuG39dBCrWHMd0rI>t_QI1XCWLgGz8Ww(SSI_W{+L*CsxN^ +z{Fo$&IQsn@Q)8h|gPMN!&QafORR2uh@$;JU!@6GOY4XbNkddQ2N`^PCWHQ#lo<|ab +z=Y5jA%!J&`cdBDvuBi&?B1H|;^iP&!58}#dU0wS|cJh8r#$*Ah8!sYUJa1f!mmhXt +z-BdLb#+Q}Fs7Bgx>hs2=gN`rRGnoU4)mG%p)%?2V$w%C7UU(0X6vB_%wL0v%bfjo_ +zUhI9~y>CZb71v82#9)Ri<_DTiU6TT>ms6m> +z4^(*!6Cqdc+cx9G`SwNqvpEna{9!E_?;ybRv9r<&JB)%^a_M{~2J{l$&<#){SP$>d +z#0479#K~^(L){%Gb`{UXUVALsEsFKTy_@FHM9A2;1P9N}wTR=71vlg=zppqDi{Mpn +z_kJl^KUYk4g6&TnF7$++&02-p0Ei%4lIE#9!^f_i;<1X1N9}GSWTQ0XL!+5@)KHW; +z;{bHJ6SIxW*CUH0Sesak5DIWc=e@6mPkPNGV_Ukb)*dL;MUrTerHiI@9_ae|w59@G +zc43ZyZ#N8x<(@rFy__h$DF-#{=7Q^|3s8fZ_Da)tppO-b1W|US6Ir +zpRQjeRD#Qvz*}4W04pG%m-PZ{Yi_?&4=6hRo!?`bMYD-5j~s%bW|@LLj#T32ff%Y@+0*p +zVsA!7mI|+w^sLgEiGV$d-vGY}u88yFYuFDkX}y9aa;f1S~JcR_wsbr64cVt*!55dwLqX$7(XNRisGZp`-Ln83=!cq&+4dEPJ)|V#; +z7wf{kD@q*~{jeXc>mA;Bqt^O?tXs!xFV{L3YoGHdeehw(x2lZ+)t}(q2Cb{Dcsg(Z +z^g5v9+b5@8+6kE!i2*b(<$Pv`KnZL+np>?h4@I35X8lP?oIU=6CcifPdr#k208R@{ +zQ1v+?etb@RZu5D)?3nKGy};v2nWuNpG3eT9?Rh_rup|(A+~)3ON;0yC`~`@Mj3oQv +zfWptvEksVbKbmw`xZ2*M8e5B?pP9rgUg7D6FulkB*>fW34zzt^Qz$77wreRD>wLZt +zM@OQ*K2wZa^494%d^(zf?E3z9`?HHV+$!IITzFEtMPhP?@jaRd6H*O3h^ +zqV1eLMg5q4JKymTMXy)3NAJ1R6q4k!BzWmX=q*%z-#O2?K2RjUH{(7Av@Tpp_`bzK +z1PMf!(Ccm?kI3&M8KPjdPURQLKkN5{tw7*48V+c<3g@HZ{R+m~hv +zPkW)-$OiC6|EX0&764wZ%XMW&L));k7-0H0TbbIJ(}KZA`qdDT +zWTthyx6+ztF=|2}%-(8+fo6jZLy#-SH>pprp6D)d!Aa0jdH^lJC>dk?ZPami3@hn< +zky8#8$zk_MUEEJxfZ%*`A8<-*`tijoEOWL80A~VU6(NE +z4QfM)c_{6(o4qWE<>$J%${#!3;z!E~f%cnI&2w=|6XpiIj2&&xk45?Mdb`Pq;MxM6 +zJnZfjajbD-gz`PW{fxJcsjL8}yG_2@bzf2T0K`Z9z&>9}i>q6Talvcp7M%gosjDbI +zuPz0DUtNaq$yc#X^{HWdbd5V7eV+d8n;Yd^hG?s=hx*6&6c_;cY-Oqje1O%sVVIp1tW8%}R;A3gZ(s?lil +zw6txz1CN#I!u5izJ%;kQ*YVldBd0F`-%u4*;W9FC7JOv>J3e?Z{({fMiwop2k*_OO +zs+cbuK306M<6_Qg_S<_f{@GhF?8uS3VhthUKo`-P_}+R?OTI7g+Ar;6HFT($|Jm>T +zaO49xE^@AFW^{1h6Uhuy +z?IIn}wSDNY_&+&Bo8>Hx_t7Swk0k+o>g!s{pDm@HC7c&QuT&<>;GUf0Su_rZ&PAxv +zD$6uq?~VKNoo#-n4Ru=lkgxW9b8-}f2Pe{Yr-K)@v03jUlP46$Zu#E!3Y^_XtLS9| +zaqasaRZv6+-!p%PYUyzFp>#5_)`)t!h3$}r^W|7RpS#qiUhwm3@>S;2OlG_?0_4@` +zlINxDDY$v=<*+`Ej}4v!d$QVwRW +z)L->;H@O%NZ6p&2pb(W3VyCQ#$bFFRu@KvD#qVDZwy)O8CXZ5_j{@G$JGreNBmtmCw>Z1dDc>x7$8h#T +z71ec<56^0xyUon&M&|Q=@*LS37$tJCWjnIleghH}*Y?Dun^fT~;`51&!xb4}NTYg) +z$P9KK7oZG0k7DA@5`vi^x>UL)amz#gu& +zf%xgvJaEa1>E)8L{bmam%jr0bK?boD(%gp^Az!6OlcXy0e%a;oQ{G`-bKrfT$3l(p +zZJ7lcwd6YMC%K|;Zp7&!1}dkxGL!0a&%wR*C}ZPid^&Ich1UW+5KGx|x&wD( +zJ5RS+J#>6BFhu(0y6k`UqI}g_ug_aewS^5`KvBF6pD%V5<4)T{V=YTg4?e>=Uxv^m +zSUgK|zRr(Feh-l{vD-;}%K|Gz0^m2eRmb%zBK6cxgzPv2&p`(l5hZQmlxImU7&~O&te4!0FZjZ=>gke$A>x> +zB22d*cR?hPL!5T|=I5Sy9xyyU1Je{{dof6imzMP^r3l9z2fI{&j~x?SMUH+2ZeAK? +zTe_hiz$Q6XSA)n-i&)mhu@=H_Q{F2|3Juq0&*hm-Z8_+)gYhBkLXkpB%?);^wAbU#I`MW1Vl>hj;lC +zCW~>KS?j`+J9lKo=7=3d<9Yb?@#-MTlH49+FfFw?M-vu8r>U;n;AigfRw)-JkZz5~ +zaV{CC%knq|`&umHMbR(lm@w$m0U2FZwxX+&*OZ7uhz@h6;M9YtiFR&qYVbw32`jG6 +zbNzlEaDtR}mUPz6%+P7xL$Yu$$U<@|gM)5`!eLvTF1m~b2wWV@;g98h+9aeUa<(Gh +z3dxa^=;9547pHpdUD2TW5Yz-P#oflt^4~p>E?==2<*3y0ARDhhUOX$(7QC_ds +z9W1lkE#zaaFw(O(ANzY$^$2C3a>``T8b881Wq114fOuQ^NzK^@u^#B~eBh=u^0IqBDH%B_4W2bDYZy-imCC$&L_70ynzG{h*JLJ4vbm_^rlA9)$&5 +zdmK1aL+O_nFXp^t*8nhkt8Jr` +zci<4^R3t(<7TDZ7uWZw2di_FfsK_iG4BrRU$^)-aJSkuA$(385ZtJ1@sT`So)>Wd{ +z-fIwTh|LA$JwR=G=Cd#aGB|P1tN!gX-ew&yeLSuTU0!6TaNW(b?UNK-!mKOwp1DZX +z%VM40n|g=_IaQNPcHOD;Se)Va-Ra7tz71m-J6HC0KYA?|baXcF;)BelJ%o9u2$6Ln +zGi!;_;B7`r)uV6Yn@%3R2H)v>+D3ro@l&m!XR!7q*BM0N&*h0lbxj|TEQ);WQC%Ls +ze-+b~nm+%ahEGw*F*o{PeB+=uOkcV2@0=@Cx+LnYCc4_jQk~kX_wn2deovPlj?Y$t +z_Te{O7~oUlJvz6`Fl8PW-@u#B;d9BA%<2;i5_EXkT(ewH7+yM$NZn-z+Y|41J)gM>#P1Q>MQafr +zlo_qi^NJla1owN$q1#|`Ww=bCS(hs)$#q|86#MK-fF6JjqG>_^9gw7lRliR6_xV5l +zZiIi&UwTNS&8f_BJ3;QqtOq_Pn4#b>qb2CF%P0os@sN|)qv|bLqp#M$%)SQ+)S$s3 +ztlRF8J@w7<9YX%vQEd}INc7KgP6O6_h5Qk^&ptL!sp{ULPO2l?mNs_LvSjHI*9j<# +z(QreW&{y2Tc^ga*=A1eceT@lt^JNaiO|;56qw)C3h+(#c__oQa3KWHDN7ny4|Z3XFOWYSIN~#gyN`j|r2sQjl-EJJp-7eVq;-}O +zbUNqL43ZV;=Y6N7ddjGlL%+FmI`Jr(Q7Rp|O~WVz^X@$*#C%>5!u38=Rhaw|)C>c^|5;}&YJCP{@o8{xd=eY=5hbfV +zE&ilKk>64XyAxJtR@vfmB@C5JW9jR_s*fp@8v5(~ZT2LXB$Mhf<11{yumhcRzH=#b +z?-yb7xedEMSuO`3#lOK9jb=16!<2;6ENm0x5$Y3VTyw^s0D1fv3m%CG4&6BS*gA9| +z_(8Qgj?^&fn)0-mKCxnaha%r|n20?6ot^V;V>sscd5y@KMao*3>wbLj0e^Rn{LRVv +z&n?bMj3-}NK06XIC36WDXfh8{k4X30dC#^U?F<+lrHAGDg!ZO?p1eS1^F8cIigG!p +zR<@n4LtgXI&nV*cK(cxIvdZRc`9pJ9qJUvPx0J&Xy8~&;4KKm@l4IQD+r7WG=aoEm +z$`daM;`176S3FrjoOY3z(iltb#MX8gADQV)w%G^$uC5IvejQ1Q;s_}ZJ+SYq`mNhB(oVBY+&Lb926~G?B_Fazeh=6=~ +zc6FqvZl{HZ);Tellq}zoKPx)^6staEVU;z321XS +z-w4?RT@z-Z_D~{CKWC~Q)r?v1;nG06#oTAuRNq46wdxUqJ2MC1+k*)Gnh3D^Q;Hc! +z?$t8|eW;b%EBHiI-`X~XFGPpDx-XUoJYn(f$;jy<)8?jYqsR}Tu<1R<&k-G>v3$KT +zEQ{lAJ|=jb&bZZnLxKo-%Uju4DXlOTy1^w3ZoMDWc?7or=t88?nY~;k^NK>Wv;NyuuLLtXD^|PUsic^NbxP1;Y(*z%lb5StBfDF48v=43O_htXTCaF<(5{kCghJLE9@sb9f}FCu{V{S=au;P4C7{b|9<^ +zY1g(zw8{W=%$CAeniiB352=)#j^c&;uoI1>(Q +znb@f3-CGywJ0uEc&s_w+w@0DsvCN!2YUz4;lkXs$Nd6{oi +zVYA8TBN2x4bg*k(J^TLYwozzs3i3JM9HDaH6SVE^CGK?Odb5Bk*pB=4gd>VcvZyuF +z)&m)~}4;I0&n} +zb>#pn$zwgjr&suSRu65w-=MiPWMj=Gj~vj! +zjJZ2<-M%4oyd&T4{96(Ipykq<9)hD&Btqxi1)IfgeRYkTbMgXEuEy1qq2o1BZ0iH2 +z2e8&PpxM~_O0Q%ZfsozpYvTj*n$B9rou}dLJ8!$6(?q@}beO>K(e}H5{>^@?F7pwe +zhjEDGS~(1+?yt4iqnA*==a3~FbT{M9DFXM*BhlqNE)pO_2wvZT_31OR2#A*F!t&{s +z`x)D`Thq-;!+<+ygYO~0^HBo5esLO!MtYLYdGz84-?yZKo{aqGK+qm7qn66LSIY;V +zh#GgwGI_Zq4i5t3GXE^PXeKx2NfecJHxs +zLN%lX565d~`44Nt}Q`+Ues?@aA^^cuXV%XaWb^_hJ^Egp$2@V7L!b#Rv+ +z^Cl5da2)am)dxha&a^%u$$F*b^Tj#??6<)0DRjJYG$k+G#?IX;U&T04L`HndiZ8tm +zm~IC69uI!8^^6+z%_9XIQoD@OzSoHW<(^%w>@Nd?YA(44nUL9auz1R@zlcu>I+Q-D +z_4)G(rag_+VIu=#j2QZ)m-%DnMQ6QjfInBqx*Z{T09jB~6)up{c{8Kv&tR8IgeTx5W=Zf3-o|G4u$58$I=qdy$?>TMZdKq +zQ0H3mhV5OF`ixm}&46=}Exzf$F)g_u6MRZ(FMY9V@r@u~Tl_NJk{_qP#u1TE4HL&x +zme8vkAOfFL{6(3@w?f@6-KxB)?+4$bRKEAEo5Py>%_`Y#_-0moZ{ina*NLxjkDOb* +zz_q>dT12I6`f%hwTY6Ngl9kZG+(zd0;)Upm!%wMUb(W*vvskAbNHXjS=kD~XB5bnd +zJ$N1W!WYnRPDV8ayhfso_KlY1l|H6123iAmwV$%m@74NthSz1<@*#Z8--sJwzY`$o +z_X}0=qhADmzaGB)o>Rm0p$ba9{hCTVTw{NahgJG2u&g|?Fx|MeRL9>X0(sFluv5xx +z*A<6m$Oblj(KBUhvF~xGnB_a7fm-)8p7Yt=iv=ffwiDjYsP{y#aNCipl*Z-9cn8UP +zF6!v+HKbScI0qk=4L7e=J&3$~r-E+sUJQ85BJHg^>OAi+MCKW>^W?$luDtVPT%rpC +zMBbYH#%!o_>GklzyNYk|eGUoqMNb^L`h|aqqwRM@)EzDS-N@wKIN+Vp>k${4?mVe* +zj=(pL*MTj1hlcGQC4O?LBUp~c`8u>{LxZv^nr`bThF&*=*RnxL8I0~V( +zj{se|c#c{5cEvTCXxJn_@%iPYW>?)S6&^(xP?@coZQnsd5G=ogE|DbNllQQtUwOnO +zuCqIt;1a|Gq9bUHuOqOqxCQN(>+F}(YlK?{!w%qM-t$C`ZyUOIv}B5^qVMa$)8A2N +z?PG=bRyQnLrX4=6kC%Qo@1~t7oanuIlf2NEI!8ofRaxmiI()yF33)Uk!a$VIE6Fb| +zrsq3s#S*s|SeRO*Hjs!;ei487+hf+@qr6=wlci33F#c&pEBDW>(CxnAOt0r~Y-Hb{ +zkRg^=6g|1u#yD@BJQZiGw1u+IlXpXqc+V*Xw8!3=+@6R|1bY250IbF9j;69xn69Y? +zC`kdDeAz0|a9K~>n=FVS1!h##8davFps0H1-HiF>J|fKV2nD{sf}j#6^4gPatR3Qz +zZqEz4eB&5c9naK^MU0R`bu_sG6;|Y41vh_ao^AG;_OREZE?)%( +zH&frPCyIj(pJ}-8%!rJEAZ6+P3NPtQr@9f}I7~5Nx)lt;A +za|d|o$pE&U1FhV~u;5lEHF5_ukM1(;_EY~_4=3LOY9V_+g5D(|@pNT>d%I1`RbK`= +z-veVNPfcoBzbpCQ@x%LwqFw>yGcd0ycflOxh~-qx63}(5 +z_DpP7yCW`5_(&AiCgZ;9@D3fi-|I9Oek_IxG1<@<5RqaU%~`K;t=`lccL$sAb^3i0 +z9a-Fm=lb|LpplI#gWtKqBZi!JGyQY1`wV!_`sYArYcv-gEmQ5n0m*(x)hCxZUlaD)ZtvI|jfaVz+9+;d06s(^g(%qoi*QqxFJT8fflce=UqA9*%TPh5)BhZis?YtHP_{*8l$6cu?RW1&nLyydyiwXq%`DHv* +zqs{Ty4nKQiA?Ct;)bOAF-0wo3D+{Ai +zj>mKQ)he(9-QXN3<+D6x8X}tTs%e2&ibxr(E8zW&9JmI(mA!@E$@zm)-s#^6kl0f| +z&Nm=|F1G=G5!w)GeO{pn-aT??!He|>E7br!nmzR9Pphz)ZJq}0398qxQFH)jxnv64^mR>8Q +zZ3k|_M*?=k;d^5sSV^f55YC}~tk09`Cc<6`;@ZsZVB% +z$PkR2%|&y;x#xm7ZyUUe*!W)7`IY;S?e(kab5Hu6_fV~Fd)Hh#jh}&5uJLvB-7^S& +z_z@9Yr}o194j3D$0rbEt*VCSHN%dm#xg+EVuEa~|qEq!}TlYV=M?Y_bVfN+R&lBO^ +z1YT~v^@Nibti+H!;A%;OPuXIsl&Y9iEPk)B*yOWah;I~7n@RnND|+(MPK%lkeH*CX +z&Q$3fYg+uqDhJQeb6PR`JCD9>)@vHf_sr*=dlU?Z*^Zy%rdC||#Oaly}J +z*K_P9g+`XqHN!Q-?>|3-cti1FFoY8>d?+rg( +zSt3xq56}ETF-B-8%=8I03i27kZvf#7gXQqO%m6X+NYbGvCD$X_>-zrl5TlOweM`_1 +z#qijU7L=SC_LKV{$a)f!`GB4CxjK#W_4vY)lZ!602X>vafT!#6FyQF#6)YX5+nNXb +z?36^r%59#<$*!g8P4w5QZ1l2?NpsaOMn)_wKEV&PM&$F9=bGpzg{k~o$JaSe8KYbpoLii`Z{2=| +z?@43J-hSZAM=S3x1vuk2#BdaD2l8%)#2qODrvlBVDYVwXyLCZ2NbxRXD&kiNxnKez +z_sntMp|rVuS?ft^ip!U|8G(f8^R)5!j%LU=E5sX{j~VZs%krR@k?XO~1Sbq1_S*;m +zQQ~*+$oV4XL~jWo7z<2M11t1n3BoI5SGY{Lnp=-w%sS3*S#qSQ^mZI*sQXPOv*%`a +zgJ)K|jKybbCFrb{#l`pCJ_!I%FS^}W-!Q9;mb><9&!!>Fh4NX9_eskVpOK0lWZTFdy*f~RWtBuCXksFV +zQlQI#+Bb0`c+WyVz~jCZ?R86CVvLhs!DpI2DJNSVP9T +zO`y=^x=VMiB=&_Hlg5|e46Fw0C+k1!nPhg8SQTx|Th2$v!e4>k&+mLSjVhwn*(*eHnOHUd5@o@%d~7=62$AJH{?;l5WG(%(>EE +z*3_U~t=$RO$NVG|>x8sqe7nQZ+l*Puk4J(W)Eg5qa-J?fo?%^kPXNWv +zt9C$;L$y2CzUWMfa65gr`j#K#quW^R6~of+GJ%zE&*45)fWYN?1Ne#>o!HPdigu__ +zZSRruL>L>byIc%3&V8NkF_KAs?BR9ya}DdTDD{40MJ}4ba=&+ty#Z%%wZEw+2Kj~` +z^Z^KBdVO(5{1n5fFG=Vr@U4y`H{`8Pv17n*C5$m`7(qPHwyUgJIrkuX(9Eq&I?f{w +z`@JQ#v*r=$t3h)QHe!V9o5ZwpI>)% +zK;If-$u96I)Vo)W?~$4%?ssFW>X0GMju#}oKgM_K$%m~QH^q?8Re7WhE-~ykZvD;F +z%28~4DCb~rxo_kMyTvtD#8+4yr*n_?mp83|N7rq#6Xj;&7MJO)&Mkf9|6b9u+D8G5 +zu{zwYwW8eVzKe(B91kA|c3g@4mMEJzAps#@w6zd8?<)!D;NPwN&n?pp(cDX?c#Xc) +zD=@G3VVfwRN3PtkohpL$OLwSH4&^~TkGK(xN#7tNr_$RaplL#f4LSG0+Ysd_+$=K;rKb2*=O +zwnsVg7MOjJ?|stCS1cRPwY7(F;LCdC^VmLz9?7v;E~ow89&0Z^FB-X;z5CV=majH^ +z+yA{p?seoXVCWRacHD1ouf)Ug?)i>RT6COkmrid&fqHV;;j#SI2aaFf!wq~q6eMu? +zT8>bW^Wy`!hX>^XP2u1`3$&8jJ<7Oxkm4c6G4Y^p%iHDPyP&BB&-Lp^2i_NUVP!oh +zPk!%I?BtW=Vx{HQ@EP;$jTB|q3EbTn-E +zNSjKzK?Vqt8rs}pl$DMu&P&z2til_*Fgzuf!rjSi>)8eTiPo +z%9!zx{R!z<so}6k~zj(ExlGS^H19@%FiTv&gPR+Y6k*Q&ca+Re#JyjU#-s& +zvnijv)Dqj;*t$_&kf%0;_Q@7?qTArtr%HcEd!7nYCT*0Eg7lzj+P#+V5X2ep*Xn308 +z@gHsXRjIO(8a&nhnQ;`u)l{_x1A3yhjVnhjt=uqd%~&r~HG1ANn{ibtIlnwxAiw@( +zKQZ@hF!ZJP9bF?4OD-4tyq1Q?HPLcVlmYNH{I`g&Jx+GG{k&i6hE7HFI>49cHT)}^ +zQ+hP$%f;@e;GVY7Y+6u_2Ew&M#9;|L(xAGJAc{7d1xBiVJQ3-8u?PO030LWk<~9T- +z=im;AIsSzpzvhC+3+x4 +zgKppo6u+k(DUUPWcd3i5hweSa$L+52W6^9kmc3ev+@Z$g)lGb9%Ni;{%<$#g68WVl +zWVy$DNF4O!t)4E%MISif;0V`bH7_F1oFw)qIDSr00x2iy-qzzH?nr&yxcaf1W9W~G +zMyk20(-RR0?n#BXw@c)l07*kJ#xn%`mUz}VCyPfIXtdj~Ub8Zyvr^iS!&%q&SU{X$ +z{db_VY%W7zFrGcrkA$8)*Yj#{++0j}&-0Omu|^!+6PAj0MEvOy9$vM%-*y#$=eXrn +z({#z>6PJHTY#jt-=H=8As#K~JqV%M%YV{PR)Zz0rB@g|Oq<$vh6Wx7FYROw4^v +z>++Y0@|w?{N5m8}H^=XL)EuM6R1;6h#W@qgof0Au_GJM~ndR43eZCG+_K3$-V%)F{ +z2xg1Dm7#qW%9Ur_AZGD=<7-*)?WOER8n(wdusVU$MbW$7Px<1+ygRZ9b4Dws_o3eL*1!(AhwxM= +zfA8ystWLgl#AK3*&gY|NZgZ9&qh~1@-rDEwE@C^YG2=!gt67 +z-SUer9=@2nZA!*7kk^t^RCuY2Y=`-rnw3Lj3w^(l^3rQC6$o@{DW3iS-eNwiDI|GD4^bHz)w|(`kmqwvr7W%VTFE&1 +z1ucL{8cpXHr?z;*{aX;X;bKTRI%g}9>y!&&nm*w>Na;Gm~upEGL>6-`Zku#9|fuOvfg?a@P +zc~9*ZLWHtbF4Yb`PWM&!l5+W<<^f87Zm2T5&+bNX*2Mc$UoO({;`wH7?29{ekTMI{ +zokzf4GdW^(gEevSgjZ7O=)*)RQT~Qv7V5#dzxGXEbhqRVgl*|#%7tJuuL6Nf&REiL +z-D%f68i&-t%UNmc^`N(WP4}8S0cnquQHaK#zE7gzes(qCv`aNkXTe*Q@(we{%I+2nB;QAp}wX31nM0bxxU}= +zEC&D^1cgFi<M^x;q-E +zmc>SzEfa3Yy`aVC!~Ncb?z?jARzC?hk_*8PR}U36-T~+D|a}DrWEj=#m8z2d-Oh#KCh3nm7{p`cxOjqJHI6f +zd`SJWyD$gr*VVt7X2cFQONH<|PP9|s_A#1?VRO*^QRhd<>6CC!Bpxsl +zh(D_Fo$}t#KG)XIqjBe-2O}{u3{GBwSNfE2-CbS-F{WJdolZ$tN4+g8ETKmtGig7o +zT^Bj}sM=6b+8h^ed7x#M2FySq?VRTTY*`kw9M>lr*&ARJgC}4X7Qy#+PaR6q`*fL0 +zw{3Rb0DU+9w1s?>kOt+3a0N}usV7(|OXPh^(tXRQUZwjthos&lbe5ht2TyD1N;~G~ +zkfJ-Q6qOgt7JJ+$pC7YV2cW1!UD6Q%nx$veZtv|RVLZ^$UTqAlxA2bciR_i>fVI5J +zN-E)$abaFD)VIGIDHC-3i;%+5fKYN3l-DNWfu?$iCJ9~xIIQ~6^ouvY*JDUXAJxTx +zQ;7Lhcn=?_hg*-s2z`%L(30G`djtr#o@NlS8y=L@52Mz4xkScvUyGu1&D!RiUUjXi +z?|s~>jQbSJAOy?PL?HbdNl#ON!kiVCS-xxk_i0GEpEW&c!;yvPN3YA_?t%6)+c*ag +zu~&uVfxb6(2dRSJZ%2M%-WTa-%b9{P1eyb`S2A~8H2UTPGOcb +z1|9me_|Mq=7g>41kN=|Ej`qaL6RcrKpcUUx>Y5;30ki7CB(HLgV0O6{cQ9;dCA`(f +zK+_(*GvBN;`IP&Ei&Z*A@sue(D8BT_25M_I$_(q7fmyN56B~|ILcUg4oB9L3&`_F8 +zPcggGOSR|fK`Y5@N$({5`6V^&0K$X*TxLXH9++B*^Et(2aLZ@I@d#uhexuJRp(unD +zrMmYhEPoc_WyE}8PQ7MI3&;4%4*F@P(KsS8^e$vmFC(r2hgxwCjnzNnq)7~WR_Z*$ +zdj&4u%HEZBQ5bq(eD)DVt8W|;e!2F6fQl*`W(ATyLD5p%hIDPOMY&~!OzU-ZzBKJ{ +z?=0{#XCRz>SiKcq)*W}g_&ha(h_RVdhMeEnX^~Cb{9IL$>W=G!DClvtI8hnmPY+t& +z*v~6bCLK$1vV8X2160T1ysxF7;A5&WbU32@5xjzW|HfTX= +zgEN7S`%*>vqgrcuo&tY0g%gEMez(8VTyu1z<$PfiTZj)6@&QD@N|5U(`5@Gd9i2sK +zL=rfv+*3+T0%Go7UR@nm<*3{Rg9-Hvqi>y +zn>SQt=Q!s>C!t%{`QO|-opD(HaP#)ZJ&SmbxI2RQISSu+X6sGtj +zyEAz^uK`KV{cg>^F2p>U={LW#9|hO^@Cw#tgXFejqe}gSD-x0zb4}3eOq5wua77=# +z`sSObPXP~b)1Pf#{@iYDto+VK9-{SeAQu9(^Sz5I-c#Y`am- +zTWu)3CDcnp)a`#s4sM2L|BJFGuPU;#;ezxX5ITD`oNtMD+&)46DC36FIo=Ll98Z-* +z52Ev!f-j`sX(z+Y_eL!&p9du3*(b>R!9LRg(1;A{m*)Hd@|`6in@pCjiUI0PCTH{+ +zcq@Ollj=^|QV;=HuF}me8?l@>m7!idYSeS{h}%=(+(4E}peg5OMb(_%rCYZzTmCwE +z+QWXZd<)xmSs09b`q(Vu8v5qPfM)f^pLf-_G>n}FKtXrGfyuUbA8YbVUu3MU}MvuI7 +z`0c-&P~q%sr9Ev4y;8~Dcjd{4^tknPB(s1Qjm#>~{M?2;pI9$@biMFja!1l;XD9n0gaL-QE! +ziMgBc)V%gr5wM_B-_OwGQ{5oJb&6qUu(!%pcN6wIWOyN*Nxq_FZKJ`x_v!p~*##~j +zGK_p#7X=0{R+2wKwlTWCXJ%3N!UemIkALC=xXXDX`#rWE)@jL8`#`L+@MQOWZwt7W +zInRYR61s3|&uDfKq~0CGyBN++o7^l}HL-0`a-#+(iC&`3WHp+zlh~kUd-Q@l^z`G} +z_eS+%9^YA@lVw3bOd8F^-2Ai}Jy|*FW_^0z7haMleC2We=gh^AdPuNt02PfHryUi! +z&7QNV!_C20Uk-wAaAx|;kpq@NK +zb|s;MaVHKKT)u^?+8p@x2`97f6k53Q$w#Edr)^}(qIEeRN_S->n0QlCs1h>nQl(Ch +zUec?3q?583=Cms$Ij8oNc;*T1a~}Y|HQ5U$134fDn}T;#7u)sXsw3Y=6OS2-uW{h* +z!$dO)pOwk_5@1r|6*H4FG@DI!#;?~c5Jz!{_wJYSa`tJ{G4Q^%&O}XgB^uq!t*UAq92FV>Zw5Nxk4n_X)PogrcF$m0%kwxjt)vqP@&GzO#lM|X +z4(oRxdlSkM{D!S~->)%X+;KbS(qIFjO!j=;V#4;`2I_QeUnUp#+c2Rze64Tx$;+4G +zd`{Pmi4tMp=`Qx-543T>Jum38`WNMBa%4oF#+-dC(?!%ETFFFo;0Q&!K}CA{<+r@E#WO7p%P` +zaI)6!C8Q@7FTMsbv1*}On%LXUDv2iPl_*@Kb!&uy~ +z_b(Jq&e;W-&M0l^WKiY||8D#PpDlgT<=#Vk(6#(3AGLGTuJatQK)rUDyc04>p=W1| +z-gE;-S$BMYhuSdPW?L@rdAYEBX1iU1&K5f2RHmal#`R{RxZTTozml}Wk400Qw2G5% +zzW+O8TrsBsYl)}v5gF&nw53xot=)WS)v&YkgelTttMKqx_XeK32d^Pu&VwZEW8rY` +zjR=nJ^_c27MD!M0@xZrFh&R{D>MmjYyTAMUl9g|LFwOl;ycRH+1n4FY2Ou6gsLLue +zt6#geP_J#QdRp^JzA0?Ss*P~vyJpA0PwdLc?WQ#Zk;k5hL0Xtip8Wz15U@ +z4nd?I#PLM{8QmK(-ht!a4cF^mV|Q(_&y@=uPei9|X5FJ99+#%*_|r&-%2$g@Y95N5 +z79}x0;=Vm4;bz}*c(UI3H*r#f7(IlCA{y_d4DHr@POlTvFN6?e6MG$TWrCCZZQU1 +z_U2@E>|7Q-x6;h@#f-1#Ns~L|-0*W0K95$(+RtW`{Z_8V-iAZx9M8Rm@#t46l*sk2 +z6eiM{7*b2~;snEd-^FH`4&np!c^c0E&<&y=FRM~}U_Hs}?xRn$_UE5_R}cv@sBg>z +zOi9iI($UWPlI%I|1{p$*Q|7)Yjt>O7-HDIzC*BZ|eP8-I*K9Z&uN1>q;fGOYa4M#0 +z4vodoI&xv@z)Y3l1$un4tV{DgR+295=U2KCC0YY=glyU}Jl4|h +zBff@aKr9{1Xej!kf09o>)}V*NwHbT|1YgD-`y`&ftWcj}_kP=wS#@#+4rZ}x6Z_~v +zTlt#7Y;=)y6k2h?NH@isp0&uRG0J3n0l17)3-oY)Hl{1@{qG!2$c{gQz5jU_`?kZ(y);b}tS +z&ks#g;&N5di%N80o$BPz?(Qu1f&06h!~g&TXK{IegDlWQBCcT9@ko;G79@VEF)g+I +zPQEx(A0^8RJ_n(loSV=W66B091ZU4vrC(LZOBurVJL#L3B{zH;M>$~V3w%=2&Y~s-&8_^}zI~R~#P_>nm&NjOv?a!4q64Bi#$JClGV^t!kF^izqq+ +z3^NaSw;#Wf`W@~bIP5rX;=``81dJ^+nw`{y4PXiPLRAHxRJ@uD$U;k7ZwqihZL=`dNnG_n>OLGP|wO +zN2a3{gjhm~E0(GF;Em69neuB1w9S{Ph6}k`Dx9NAQDW-G`TBm&f!(}yEbkd$+smk? +z_o+Pp+HpK6aZAa1Og;WpL{3Bcg@BUFCTy!fMh9Qa?YUhkLQ0K9g`e3wmQiO4#D3SL +zQRI2PT!a_Xo6tVBG?=AlXQ?V2d% +zB`MwY6JHHQgNi?mTOsXNFVjrE#lJ7OeEKrbjB~zS65xJtT<7bPe2Ke|{ote{~`xvi-E_cacbggjD*KrN60?H201w5RtiJ$vsg7rzo@3DoRq +zpO>nmvaR$efaZ#xz4bz9*@)|R4Fc50nU8BLdsaSC0PJ;NMjEV(jYT{!X+A+x6}3-0 +zAeu}23ZdO)$Qy5kcS~H9{cZ+q>*P}%yZW7^Kf&5Pl?__sd_t>B@5t4(z5T?`>Ug~b +z!Fe1n?I~?9Nfi97lfE8}hgrv%Edjz)@wJc^<91}Ore3mg}z4qBxNA$%>E8Hx|Q +zb%=N$LisuMghXGy3gN>iP4}$Un3Hf;RuLWeK%t1*Zk)TKx|~f}SeeJi&l6R)bfS%a +zHdOT0te|s|_%6bUY%Hvq(s6kTI-Rb4{v6_1H1uKc4J-(~0GGn>&_0w0dUBvVzYdg$ +zv5#&Jp9{v1{5$VcqauZNZsON9ps$~a7`PTW2g>jb8Cdsd^iemVjbVOqo8(Q2w0q^d +zN!NB^Dufujznk;j6XKLk?CpdZrim{|A@V5+v_`(?961|yi1=PUTtd)6iXfnU(_zlG +zhXNFmw+la2)Mg7er7f`}|LhO1@#g_8rB7JNZei=?v)6iTYqsJnC13@gu_wXbq?k7g +zHL&-VMdUeA@i?W^j&F@zFfS>R8BA9&V4AK6kjYIzs<0e4yW{JY84d82?Hu9I9lf;} +zSX_8vze6IrZ&-`sbDNQ5z5S$!J}y#gb$Zy8JztGvoR;RtRRvGeCZUDh)l3waNNnG+ +z2ernI`Se&)@Z2;FP{7ahe%>^bd8$=nCAs7lpS7YS8(Y%g#o#9}`L37mnWrH;I-lnD +zIZr`+9zttxtwHmz{HLvF_}Y=UIT7G!z~Pip(adct$|Rx9`_KA%GWBB5J=mu+?(Ms~ +z*@%7_AZ}^e^{2SYxD0rnM&rDEkK)=yC}wzl-7-@`{qxv>3h{VJVH|Hr>B$(+Yi=O! +z#|!J6oJ%=~>dwU1)5Z~|( +zKzQjsP(`&kqJ-Z1IdUg6tfDx~&&Zr}Y(^y1z{Ya;>wWxLCiO_#Hlig+JgkT)gN4O2 +z={bhjoiFw4=LGUl`Ah;(NY37ag%Wb)g7X?kr +zc=c+CoFYvok5e{Cq2g(MwXdnWKKKnKq8wwyn^sSh#7Qg)qn9L-haxVP>;V?lp?uKr +zUGw1!?0xYKfoX!hkmmT5!cDDv^4=5P$B2(ZSqr`|;2`Jo%1!@{G?>BdB}P4@LjgW= +z@vHr`Xu}XZD4T*4#4aa(R!$6fy}STk*l4j!*Q|sUQK;M=aF7SU%TmXUu(P{LTQ9tk +z@t2wH&(cdfe;(Bm6HgH&oNp&$XXU`4m5z4Mmlv*t~s~<-d67jdN0oo{cYnUMU=RG>6)PWYF=iW;`iCw_= +zNhL$t2)?kRqPzSelnB)DSSdo{y`qQj*FP@5icAl?==b;uDZ&Q>7q#)JS(DsW{<;I5 +z$P~HEihQn#jLn8nT9sPEdi(LW0@=LYwELUB0}Lmg>SY#$^5t1t6+juD6C +zFs*am_{{w8y3cz(A;i42+aqZ3g`XJ8Ilo7r}0a@NqkID%srUMjooy6o^4 +ze(za%q^&c!Q>Y}w%(KN{d2>LEC3{XK<!GZS~LlX2rtR% +zTkBmWuzpim{G3zYW`LidZ*z|W&xy|w3%(op{p648?AItq;VdGs@a^spfj9=`R}JRg +z&1nb^|%)CebEZ5PAhn6z7^X+ +zSb};?iNzXCp3d@|uOac?3)chl^GWX;TTn@@Cm~(>k!4LJnE^a~p8oZw(OP5+5Xr|U +z=zgeS9(d23J%~uTpbyJwbPVDJpbH2+@@+vitcD6 +z(b9X(F4R;C(YaaVzteG#uME$eK)Uh1!CoS1@Ro|F+m&H8d(G627fmq +zE(@V{C~rKz4Hc#i&0ky9K8IMeM-Q8%^RY9_&Q>qG8jDH7zJGk*)K_MgOK-S&=U$SK +z`{pe!zyGw>RCvFgdWPV|J7y}sL^G}Zm5Sf+uamE8p`fM6nF%>4r#CfVZe>f0-T}_A +zqv|Zz`7AycJ#FkSxPm +z-&8K3og4$fTzTRy<(jV$Yco|DL#3`^T6*|dR8RF>#hbkeVs-_YeBXDMuYq4x$Q}bk +zXFX*lUu8evr(DE+Y!T{TVc%%fa99(Kn@)JdE|!DqUB0o5ZeP3F6Xl`^#8x8H>rL;6 +zbPD7_Mg_n5*7un;sddmox~F?D!tIJMtz~;SW)r}9Zyp>j?D7+J8dvS9shGev6R8Q6 +zxtx4hTETGOp07nMe{Bq9i%jlS4+iiHIp_#aQh1}Rgeg%ykT*?gknhUQ6a8!_ZeKh@ +zRp8ik4ksMUt`$-Jjv7k@;Bf3zt)J$rh0s<{fhBT(|GTGep2A%|bL6X{_?j7YlRO}4 +zzFgO{8w`Wiww36?z9ir5hr-`+^pz%Mma)&3cW%B9|GdrYYm7v}(bw6J9MUvXQh%(Y +zh`nUn)Qq!zbP`(Xw+C!sE6_-9(t&Zf0DsWGEN-e%;}AW_FN>*U86Pctd88;L0|#2$|$3k|m2 +zpV!Mkp7GxIvPd4Y6Iu5#-+s!AH)g^B{bgZ1wMu5C>=W%G5f2L;H7tE65uCvjW=~iI +z$(;QS0X99g6e2?S-7~&^3+837_wee*;(Yh-?`7z;$FGDgaZ-aN?6W($8K*52gCZiY +zU;IiWpD=i|IC7pwKUv!{-3o>J`SldZx4$Xz2nNodVITiIzO}2Dm$yseLL(A6+>yH+ +z-o|MtIJFXAX(0#DQ(AXMQOB~w!yYyT9z%3+Ss<+I{Y`?&83%om^3;6l1z?W2GPG34o*hud8D +z+>$&0Y+~Fir0t150eemwoStfUIl%HWlXJYYM~Q65DUZZKF)fZmsq=&OJj +z_#A!qO|X@C_!d44{*^c;n2y=Xt}mR&)7@DTFQWNN-tnk&B#mr@Oi$$36BzmvetC#g +zsl~OXVR>9T0_Zc#yI&c)Lu1d2p@)Wu?qZRi^@s2saY1!y)Ay8|@65dS5s8A-@o~rZ +zqNVCyjB_a~=5gUt2es*x^s*wDOqcX9!u`4p>s%|wskz8AWqbgDu+X-Y_Mu%Q8#8@1 +zFV;h3iYqT_L0I?1-5UWI=j@`8(QMKET0+bTAUR)8x5&y}?NnjKCSSpXl(CcD3bDH3ik@BNy(>^(1>-vLWIa{cjZO-wrs +zZ<6t(GJTb0I@9b)VnHBTNm!%b_CHQbR;w?96ToAUT|Ia9g~Uz&&Z<@Gd?g%RWRt@k +z_GK9U^6Laf`gPiNGVhoZcDM3n^*6@)a3aQ6gw?}~QxH(O?mb77w(32<-P;9$VuG`5 +zed#=j+D`~5-8-!JJ +zcaeh1_iMr19s*o=Qo&BwW%g~fzXSiD2e}#F%w +z{{6gp)+nOS)oTWu4n=h%oAQO&c-WX^WrUNdlKaAi%Dr^^>!(l0 +z?QV)b;&Lj(HT`(KT??J(vq~|^I6Z;^5w};Mzl2Ehv9z4$Qh8N~a1HPr` +z*cB{ZZ1A+W(5?Hp755Q+8rA)r7_)Y{DfKcG%kii1tRu;9N%_!$vdhP8y869NAD#xF +zFP?`-^K-$^2rJ?E(wKCIra(Q#Cx$O8<1kQaJMD-wL4lxy-JG3X} +z(zMj6AbJu__iTahHs{@-+>peAgVg2L+{!RnI#6?UOmtbcam1g5!e#n=e-8WgEWq-l +zgqS1XN5WF-T0H##rRiJuVNt=ItF9cJ@q#B*n0$W5AhzMMC<*Erv~wL1{Nh{f>5;Q> +zGW3Y6j6i$C^Ye{hW1E&lC)UEUWP9rAPd=#=Q*tomfyf32e^{ +zM^uOR`$)ob#UCfHf0bwF+q3kHR8TwV|Tp2hn +zaLgX43?nAJz?18~e|k_xx-xhZelabw8^@UkgyxQ+JqNw~$_VvS6j_{42~*WZVA2H^*Z0jCS9U(L +z2*1PU!5GHNwn40YWgmSk=!G7-sXb@eti4_J1o+W2{+?h=)KgA)>=32fb->OC4%`&O +z?s(v=V`|MgvOd16J5=;iP2me;m`-=o4in20eup>KmBbCc)7U#`W%tBAJcXy{ +zyPZnk<{g5WfqWNmK3WB{$^pdg%_tdv7{bvsc)<-d2Zt5iOro{XDcl97@l8(iOwO0O +zUo5b5zUFoA*4T#*qfhJ9T2JM?FnS{45<-S5=*CCiRdKR#ryqR2sD3XJi_oECyl`$_ +z$xaDf%9JelZgq;s4ZJtrY>Dq88tfD?p4Q7(#=?&ucqk9aPh?)Ro1y+)%xxG)yhlgF +z;lS8%4?Hq?Q|3JNjdfCyA+G8fxWzkj68aPy34<26*wJ7A@y@I(iXMe*GGMoKug8Sm +zd#|@F7`Jx3XqtRAXE^m}pEQpR#tZ8$U&{c$tE;`4-<1m8)vwQ`(7_-mdNMkWXXe-1 +zGj3PNd(3fAf}HPJ_td->w(lEAdE#jjcg`D%muc_$tTq7pMN@3EDptwV0jGE{1ho(H +zQN`ao!Q!%z=h}CD)p@u8?}Xe(duolJ=l^5gvp4|ME{qx1>h_6`s_( +zSU8S;Z9nD&k9ht5FYwArtL)v~mTtE?>NW +z22=Ymq%B8oop$L!I3Z79ZmC3AGgBdypWr!{cD6ATvc7u`eFy{Y(ANe*ql09{_VD%#QT-#w0~`ikMCFBF53oo +z@iKBwy;<4cjJwU{69fSuDtg_(no^Li`mUeDD4r2g6K +z*Pr6ii(u6pf;n*_2LK|^lYLr#4Mfg_P|mqEWP}8v+zRP&#pJFyK8a(QzzlPr`ja +z*bW9D1FY3*cE+(2VRgBGwSFg2L1JyG_LiX_GSsn9qH0HfVGTBEtx~~dt7c$`)h3R; +zgg(JkL62JeyIhu%a^Ws*X&yKn5))4dXP*6C+S)7jqTz`LM1_;*rgP1ZsKOH0o*sUQ +zM)J{Sq-9V(=jTUE4-Rt$_-XXj*+Ob(6ISn#y(Pud<(|cGw`N-Ms7fQqKG6NOY>T!v=hvCo# +zvcpx8c1%fP&@W`1;P|?ICcqI%{`7su6~WIknjcaKAG#~^)r%`Oe3w`4&Y>r@PVbfj +zVerdgidr^u9%O!JS?LE34I|~Ab4yGhn4fkys4rSHe63oxtIvVQ0?PZ94C;42Fy}o~ +z+9U0o8nqrkY`uH#XO){N%}-ArsK@ScPRj8M^i9j|vn#x_S*3OKGq55u#ufmK3n`+N +z)#=y1iz!Sgf7b7t{CUj#f}H71R`SO>ZZ(wNJOZZ(>5OQcc{xi?P(tGq%;(KKhY_8* +zXEAic$)dO7__?bwMlWDRLjhCH__+gLt5vLly!J4LjMX9^epHj6Ngf6Idc;S#9d1QC +zaQ6oA#zi|)okzu8R!$%P3O>Hpe&-aq0r-nfxHQ@qCfs|I;Fd`nsRzNZG*H0B&k1Us +zYVv$lNpDr1L{N3fM>Vl>Ug(8`oZ#jck1)T;vN6}%E$lKJy!3RS9Wr%%B2ealm490q +z=dymMmzP9^$Ldln6`7>ZdgYi9cb4+kO=LD1UYt8qfveOpV-)u93tZZgWPMrj9y!6< +z%tj`2xu=3o%+qVBW&1MPTN!B&^#b7=89{Ygg +zEvzc0d&`do!&k_8sx)g1cO_O&xul%XY@6tZ?v3P{M^H_ +z*74B&CFQefe2?y&htlA8MAPnEJ3{EkKFb@(3^mgem5bDI@0ME`Q$eoZfVr#&_s|F{)B=s^P=Q%g$D6uG +zWN!M{5fPmw8=9tk{Gc{L9+Bc+XJiGM%>>P~> +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 +z;r0Es@Cm`O3QVY`op#>IprdFkffZu4EryIKoi +z@#5noV%t@Wx!-a5r-I|`eAs=@U3CplcCnQhiTJrTa({9QC4?HXxz)(d9m18)HFrM& +z-Cq13{I>4r;WUqoQmZEpD0gpWk|USVr=cxx;d%)?OnMXjv$#4WBe#klVdn6@L4cji +zt!o(qv1F9{Sl2=vs0)UE`#k9R$=Vhze8MT3p=_J;is&txV5#_ZjLX>`oZ1rD2@}`N +zd6cv58l{1oEvf|I6`^m6{~BoYd6eS;X{*ahc32pWKzx^Z^uEFgHO#BShGpmTRp@;G +zmAU)tcECGyytL0)^6@#y)hco6#OZv#8Ah%uLzozEM*>> +zn5Ci9`(U7a@?$PRmsajuqxCpwbew~aGMp7nFEV7_#Q|CbxC=Uq=1Fyd78*}K*0{t8 +zTdk{XEeJtesE_=osh(iHpQDxOBc8D)tLIXA-|?ZI#}n_2&Ley^+3jvn^Du~p-@7P= +zF;b0KmN#$dAk;2zj21zir7S0vc}(?~CPE_V4WDD=iVI4H^C?);qXlpbk@D@N=H*m_ +zBlo*_ombzxaHZ7m+q&41-EvIQ+#FJ1JG&1CxtYt}S9xiXOW!kiW^J}P9_e#Y`GhqI +z(20WI|3vlgOl^u4GHs=|uvZeE9u4akA}k +zzC8CZKLq`<@`+Csq4w*-?#BZ4t-m0F_9xHwjr~95vDt-_VyP8HT`h56VRWk=cU(T0 +zp__PKxm*KNjJyfECq@%d=%ZHmEOKgpC)bx;1z9W*G@Jto_hw|>7lzeUwR9fv&3$a` +zg4P!Hqj+&{!mBL%xk_$bHxWZL*ET%K1lA|dW3!U&XeVOr)%bm1BbI^t%B_SL!bf`% +z2(b2Hjyfa&sd5r8z-H8W8P4T_X_mZ;_(`K5nfK?4$1w&kZk&lkY6fJwP2ZwNO-}YC +z?RcGkYJ48c$7CImicKy|5p>Btc{4x1@J}KhZ{cS==cWX&8aA*`E&lp{8|M+`Q+*zJ;Gkol^=IexycB*epnu(#(8jd%f(Vd53xbM=B=1!Q +z=i_E^6Jg*+o(k2v*jN?!?3(Loj$2j_*n#1a&-=E;oaIC72*;VUW8eOFu%Rxa0N%$2 +z8!7v-S$(J+SinIK*1d7vxUtKl3-BA=eSCW`?bAA9$rBS6hStp+57tomv9L&GK1H*_K?#YpG>G|BqOw%ptvb1S0CI5 +z_s&-&BaI(tw;FpARH`MzIy*E1rC2+5qt0AH?ptX5bj|U$i^Nu?vDPJ +zFpI?>udxTx?ect|T<&YT5A+<4qYkk>8)kM4#;zK+DzO)Vj>D&BeCOWfBZG%^GL;$S +z)MgkIbzezYQo&OkM&%?|tc*vv|x>1P>0H +zA^`Sho);97{Rl(fQv2FA30+i%E72k^sHZbBd*k`+4R{^z#ly7?K}SqBY7Y6_8`2Ll +z)yceeFQ?JD|3fi=nPXSsA@uKhPwvEg`+wnT#kS6d67OlsdrQzenf!trIOs|b_BZVV +zKFF_9K{u`vfukhTJ!Qz& +zUsH8skC5%xWDmHIbw1++hZ9$h;da0O^!W;u)ORqG=a!{jj?nyW{(QWY)e>Cl^AkoC +zI9@QqZF-V;A>PiXF|hP}oaB!At*SOoB-_fGWy6=clcV0kGZjzR3FjT7``P`A0PIP7 +zDBOVQQ@(we=`7#r`wh8*eS^9Fe&AHrF`?FRn*VNvI=GyzR3#+p^S`W5e^@RYeT*`v +zPNinY>Z9u3oN2}Y*&9jb5@zZTl>>k%1+$<9AsW44GG>M1ptWf``Za+9f37bO4)?-6 +zLhO$#%yt@ve#R|E3JwsjTxn+oKJvJQL`;udoVrkALXT?O@kbcsas6|2GhURpj-E&9 +zH@~;4QYYs6y^+BubAM97Co>OOFJQ*hOQd=d&iX)jk&E2E9j-P!Ug$A^RxB;~O*JtF +zeoe?!B5T#(GF^jsWZ|2IhwaV5cvS^Svi3V)jFmOhhmK_slD>86d>F=t9GcAGhFDq$ +zkxtphNw-ZF)N~o8T~0{U`6i;zVK4Y8jWN`yRUORoxEH}6>!|Y(Xkd)qw$tKgqJ1`P +zh#w~p5=W3_ex=$d71ff{%tHJnhe_mt`MVhW?ZcZraN<+pj*8%TV89#4``6D}SSp^b +zFNpvj#Sb$Y$UT0RDS~PVAErIodOd@km{sX8GNBS>>2-BhLo#?l&A0B|<66WixZ`^4 +zC+sKbcWj(!BtA=S9VL56AMT+AF9+-QO!jd>Xq@lv<%05V!^oo?yNUTlv;L9pcw +z46k#Yefp;Cc|1iZJ`3`yUYZV4)5~_OvGv;hSY^UKq(FRUc)$Y} +z=e=~OK9xBt*>9L>d52%7EkOkn((gp?{+dNvRi`}(10gsHr_d7wZ@mxav)E!SfLGELKMz0(L-I8O-G~#_X5y +zOuhgP?rkDcgmeo5o)#;e6K?Y2+_F{xY#Hk^%dGd~z9-Aut|{@ne8P6F)sbTWU*Bj# +z4U0pErj> +zc4C0y^cs}h!nJLU*=nu9qB~ac7|JRAoZ@|uANBc6Ir;G%l$&Ebr1ujU3QKKLpG!PW +z*So0lCESi`4NsK~!pS)_{y@Q<9p{LdDfQ20 +z`I@z-#~1zINb%LT7s=ePoizXS_Hz7tc9^ptuMujyE85I#eQmaB_sn&7>3JJAkoGRT +z;{LNCU~TkR&fz4sI9ZeaT`IU^LVI^^heHl4PwZotu$u$G?s)vg +zi{TkQcSofgFb+IsiQmLC&-CX*T9uM@I^dJd;qc*OD~#yT*Bf6JLZ-cWExiX%8n%7b +z(f{ltx~JzFLk88Ld|q%4aJc&d1LmWAHlLup0HBKl0(xcEH4Dk*1f`X)x_FrW?-w7r)zR7c$JL3DT^`_-)nLEY{yJYI3{ +z(2;!~Z(%3BC)$xLHe#@x`Ix3=|nK!UcbkpM5=CtN*)oZO<})_l~kXuEaF8( +z#l*u_5B3pB$Vl=$O7LFQ=Rot8SbEI*{mcgnFEe;TeNrnyuXb2)Wf;pPj0^XE3V%L} +z@r^Fx*_eZ=zBnOzfwxIN1kHwYS5O~Q)PNxBvGloi4u@MndVXZx60p!{A532O##>NY +zg|^guk@}%i?GIl)G^8quZ15liHRvET1*a!J79N3jZIiGE<5dWY-oq*UMN2qmxDV!P~)bfeY(it>zDR^ULSnuHdi3heLU^E0OmM#)D^xy-&cdn +zMHC;%dqEd{ +zFM$)?or@(SC&`{PF`~r2MDJtQKCyi*%x9_Y1@e9V%_TxJNBquFLAp#T^S83aGExB(#IDYavw;eJ5I@Y +z;x=@_f#9%vjWVZP)>Gb3Jr90x<9D*hKnZWoAjEBuhNaM;SP`S!l=Y*Z_l>VyOUeyEO>V|%etR!Lc^Q`W^0f-8c5*Kvm +zv7mGF^5A;lr??}2JLi?m?^*$IZ^zrkf-LWw85Fn)s6-NV5%*!tzDJmp(uq#Oka>)> +z0ic1|@!1OcrzK?QF=ML_<#Xz>q8ZsLhM;{5eqM2qo=I8fd~pBmc`dycSX3CoClZV| +zJHB)O6mveUU3SCv{M-!S+_atXTrYiC%*_xN6=ih3x+3%vTU4|wn}J5%;hWkIrY72z +zu@LRkp&S>C<|=N|bJCi9Qdta6cY9 +z@%_`iK*tGxq9G5RZ#+uX%cETfj@H$*5roCh3aP_td6!fisl|nO+4;&G*)6^EIbBQJ +zg|Szb&We(IO03R}Y?Ng@HR47Wm-I4w0z({*_L=!Ee#^7C;324oWwdYR!<3T+6&Cc^ +z8Eoe#Ufd!&^0*)=wgi5v_OJBLrwd3f;A9sbTXAEEudVeq>^ye&(9diYj5~B4hjS={ +z8%mmq&uMP&``8r=(rWX?&v@}xgTmn>p?zM=L551rdHmbUb=F1SRY)N;yw4Id?Mf1JH-rDX{M_=_TtC!I4 +zmjpJx2Bv%*c_lOvy7(pedsI>n)aGN;T;9-)a2D?D9_tGysh9IRelC%V50r6Dt;bab +zoVPUzY(!7I^hK+uqiK12<}vZ?OF@TxKhNr!98rBxu~3<6_=>%^g$9pmXs^`82dXq@ +zVG2~M>ILlkSix4yk-kIa$IoHfejj)hTbJTbt9R!=uaeo1R**n1-!BP7o4N|@=fR7; +z=q_RRv&{K!%|1gF3IQ6+qoQ0dPbj$zxU;SRC?;i?KXO6273>c*VjwYoQ@HW)h~%`R +z?d>YqXc4R9TB`&n%muHypHE0kefU;Eocw&RY2Y%MN1l<237DIO`fG27tVo!DcaiTc@^wy@lh?Y$A`}& +zN6@4f?_I}oj*Nq!c7%)}T!1^S-pA{~HI&n3Z~NN&BCUIS@@HmLjCon>z8c$nodT{c +zJ@C6ztW~42PvZPDq|wy^s+tNuZ5WX&Wc42H{8mr +z5?{M99n^r!o);}~AM%sPvD%j|(RboiYf_+-#d!QwEc>HAYKWXp=??#WJ8hf`g +zB%_a3x>++!YhxGm1Kq)f6D}^HHlu?nu!b(Vb$PO5-&ga&&fC4U78udimr5Ffl2?XO +zAM8%%1UPzDK1VH`t(SWkG2`R~Gfz43SxX>-DIsIr#%^LLR?-g^AV +z%#K0$BM39OK4))b3LjbUL!a{4@MoyXh?iDPl}&SGKDGo`8)ROxAfo%;LZ4{OLc~`m +z4sBo$*u!Cc`i}BpdmQ}iycNH7U*Lh$_53GSNbY$!2;<+h94eMTpK`XLelU4Uu!uNqUMlXulnO8V6rPGd5%Ot$uShFV>@2;?W_`ou +zc-?yg!OvvpTZRico$N0mMIN?@?C{4&^-*9yUq?ZnqXk)o1y{36_Qb*-oi4iPlJ+BX +zV1-66F?EJV4leFv4(f1)=M@Snbrvl{a8-RN;8enJs1(%QPUnz{!2qIRp0zlR;`FvZ +zS|53(S`{DDCBv5_e6LX3LuURpp(Qh%T;@aKF@E;~w&v9n8N?CgB4jo%M@qRLWuF5> +zDUaB;>Erw_rp`h9H1~u?0_45WCffCWl(x^1;z@bT6L?rqx)iBpW||RV~cn^5d)CofpOc4qdUuz34IaD6)&RQdyt~QhVSCT^7#q{X!b2gfydr5YY>9u5@Ii!cw>P(?hpc&IVDCRTU*quDv3Y;l;)^T^9L +zw8WWn9aH$e7kr~1eO{AJk_P;^3WK%4eQ(NzALG0}6b_%1z3st!ZqTbcQqb~uS@`pM +zSx;^p+QX +zsdEF8^5xr;f`tP}u0&1iwX2q&&_`GZQQr?Cju`mDKTRlUZetlH#W|_6i`;h`eB-t) +zVqJ%OR_mOW?j;Kng}!bbqn}iN7fTjJXc`6w>&$hj9V2p1e?)9*A9_r(^gQ&*!V&k_ +z<2Rn%uOOEn!aHb#1o1E(@HswvPFn)##RSc)_zIFDJni^lAGnw8lcM2= +zStaDMoEwJoBEEZ;Mu!NqKdoX~Yq?oQbxQS;VNlW~;wt!D@Y0%1j8)&>wiz5gNCIZ( +zEIQwiUMCvJ%@8z4ZIsG7tNr+y$g+vZ1KDE22d+U1n<*E4hv)`sbdZoO1ZE{KhT%C! +z&as8#vgdj}KvccX8W*VGK!Z5!cU?Ocv(e1AUpf^#{;4FKK9ghea(yu+@F7OeT{QF6 +zgo00ov)ScUrjS*!z4yJqJFw;1qyaz!(Ts1u+HR@Imqh#6lDDsuPeI=1NIjhK5@0ku +zKzbGwq@um+zA9TboF|vW824OxsX0pMUIOe%$j03|kxjC!XmiX8UOL6Qcl}z|Wp9#k +zD`$2e8*bXDvD}dQw!fA3DCY_|pS=%1I&S3RUP5!FCdUhpyn0}OKb+vArJm9yXpyj# +zS=4Mh=u)W7R{;F7Ux0?PDN-wsmgd9P`GN3P_h3v7v_*32 +zkzXlEnXLo|tj?KDJZi-Kfa|&0pEIVEf4-83J;2}$*eIOuoIcpp&v$LJc30+>`hd4W +zCmglWODi#$C+F~mh2r7Tg@EieqE95RHIVsAy7&b}WevLN*tYdg4by4*L`aZR*V$_L +z6(DzfII4CT=wVzMQodM9@E%yv=%VB2l|>^!N_B5IJ;;uddEiy*3~e0*#<>sglD!~- +zIJ6z-oRK_&CX?o=^Qjb^^m{&kHuCXYJ?B%XyVS3^*aHN@*e&hhGpW!a_Yo#iVS1R* +z(ir5#*ORk%^WIA*8nC=9ABUx*m%HS8EuL|Q|Jv>8)TU{^dj5W^zjexxP+i+bSumQQkIe#FYd2F>q@ONkJLW6?JdJK?b{EJ+q|MbxsZEl!@gN@m-d7Go&HJ% +z@$m{Li33;QB`^I9m0hwG*)#EOiZzx(Kg^5+|&p3Xl!mOe0iuWtBJqcSHJfhwpm+^mt%c2 +z+)?Gwk$y#ldS9^M?VNSYI&|5yx`!NRLv86qWjCI%M@$38f+5u@szPr_x;dp{+7Zqh +zSk_1leo^di4O2Jy+p5yP&NI39!jk*#OXm?6r35r!q*L&A8JrimZ|7g@7YH`khxHI= +zSIwid*%A+pQ>n#>oJWgSpsL)RLXAY5&8AtM=Aeb;r`(94damGAnR~@4QHTOSH#m2w +zCC|9w*C!lblT5Jj-M+P{^f-W>rD*i7 +zOv<(UcDK-%&iy?co&Yr2+bVi8-ahMNr&EK2CZw~Dh_Avemao4$9f01h=&Nzq79!f+ +z<|byz*D>RdQ})SAOZY@tEH+uB<<%nX%r%T551?xB?IiAgn +z(!r%i`cLj$&)YV`Y=4eG1p!uryhIX_HExw-zXlg74!wW4PpG~ +zn;>nE%jHRSJN@|GI%VQ%;l`+0u7)9@os{o@@iu#?35(_+CfRwl*DUDmoOn6L>=aN; +zLO9iD+b75+2G}p!5~yDS#SJ?13f)Y>=hD8j4>8wal>^rwvs$N{^I$nXLQhF?&vNiG +zOsKR|uw7J7HrYasU5YET{Ge!jmIf%dPAY3^;b3vGr5jy-wSI6tHMj1ahl%k&c~3ex +z8N20o+YGgZ3OMy7&9N5+qd(DtGr3piB;D1|GlOPw8rS*e)FDN<=fHb5V+k!FJmuAa +zQyRydAB(g5wKl~k%5(<^?RFSC9xgQQ;`j8ZBo<`epjMa!qIPcG^Xh;bSK>=XRqyY~ +z4R}>;jJDd@vFqzgs5=2?#IYfGQ9c2r8pg~N+&s#C8Mif#Kz_0;;jo@?nQrzs@#17^8Sp%Qw +zDUpQ0(Rw(_uj6LR&T31@Z}2-1Th-mf!YEV`J#OwAiTh&8i8@n=`6*uF!-U=4tAH91 +zETsD>x|DxTQ(^<3SgC-Y`OXCO09ir6+d$Pq>mWmzPI3> +zbqCUJq^<72VBa%(R6BO_5!hTPf||#o!7mu9S-?1EJK{OspUng{eN#*TpVM03;Hz*h +zKN^+25%D#~{d0anCAoR!n;J?ahUjh_s}raf$-0pFU{WYA^Oz!$U}`xlfaZC?^5yEQ +z)extmbsqEenbK5U;Q)O}njK!|z=5k&b(1QRyvsb*vUsO(kaV7)eT~Es#4msoNFI!rYUsBJAIdtQ*$`qgWa~@h0 +zfe<8}qPk!euHXmcascMgC(ZC}FAB_cVVjm7kBI{Yv$3Zy9QHffZ};@xxBfqo&Q`m@Q1i@w;_BQ!&F6C@>19?pJ6n%}yH_;z==o_lMFI*wtM +z=k8&48#$1lK3!ZB?VJE!aW2%E>metlFFQU`|tlTev +z4?E%Ng`){q>X^jk@4TDB!XMmoXF8*W$?2VkkfP#z!!kQ9dYcDp2XGJ^Wr?({9@aEk +zkihez?QN0aIMO6LX)|lr4L=MoCKIIxj8U6za%2OlWd&f?OGT>CQNO +zk8wD{Bhz<<@IJQb9hnISm_Ad0q^vG|dXcCu0<`HvumbT*4R|qH&7OWQhp~Ek3ZmL) +z`ksIKqg{DAOizZ5sJ^hk@whX}kv)eL=}gb(mU2|b_&AkS5t)w?)Cui8PMbBOzCBJemmqF_ZSo-R!@?`Uk9TWQ((v44juo4cQ$o3nD}aQw +zM{Fxa)ULgcB+A2A#!Y#B%H6JzrI&1-XyL1^+c%;?=w59P<5^e4yh%nE?mUX&*T2fH +z&y6|#7DiY;eLT^Zd*AQf(y_WiDLMrjNgCSD4!j~zC38RM89o8w`_r +zg8Zo~A3;<}ixR`-;IoI3vh_uhn?T=-GFP^ZZF%z4nUKtpc&My|hmXx?2>#>&Ag?!e +zeOa`rxrY$KS6ByP9>1}4fhjEfoENl?T`}P%=_e{ji|3}=!SWjnGK^-j_?XnmbnF{qC;GFd +zB6grmlgBt?K}b>t-4iY45b$ZF6{E|70gEphKz){hyv3~~MQ+;jmG~P8?s-+kA)HA +z!?HJ1-e9HZN)tq~QVmS;WABXUZ289Wip&7oa2t>4Vg~&sgy?DW0K+7ZV6gyoE|xEW +z2S3NXJgxDhe+#<7tDEl}62kukjtQ@`Y0{ +zh2y&jtMCYcq)7zMCW7z5jpmA5cB$@GBgLMcr@>(;tojAq6h?%j_c-bRPSuTOp&RJ; +zKDi`9WXkSxO4<;rlKB05igNjds7oe!0G?hwq4Km6De~j(>-(@a55Z@`)0~fr?^}23 +zJ{nlpC+~NOW)&XNw~iGH%3|V+!MIj>N&(nhWy~JL!COtRcTdFweHxI*LqxF_TrBQj +zaXbM~9n +z0i&L;?%1^<*vf{pn0mlh +zk}_}I(VbxC2~y3#@g%Bh1}jvii*g=IzQc^fkLR$e=jVv$lR;j3nmm2yYr^dtmxe2F +z5N`urx;HHCe6=1W5(e<(mMos#-mhnDdGS9%LJm4CHu$NHd*P7gDdS?_@4TsfO*=8n +z513I*_wA%v;cV6K7XMKtWq_*(@!mI?a_n4b(k_|+0wTD(I|se&2-cdC07Bkj&Ag%H +z!iOJSHyRA8ufc+m=Z@*^N0@Zd&rtaTngWl6C(*aZ!aw`7=!$bL+GC7grt|Vwtk|EQ +z`{N^ni0Iv9r!Q103F&9+*N5au)vh_44wAyeZ6s}eYWyHu`UG6xYiFv9Su0h1%05r$ +z_%avgU>c}^evT787qQM7y!DNVqXC7G=8Gq0>F|kT-d%Y)Bh(@|<3GXAA +zPR&xkFB03lUPl)YfUm+6<)&?{OLFN@Zl&*o7|of5bcB9NP#;-CmJ72+SpL5M(w)4C +zFbMVarai-=XYX4pvi|75DgsyfS8PYfys4r5xSG5TUF5d~6yU9Av3%@U=o;L-nM+ttrJqxoW5_DKrW7oBBv +z=4*Q)_!#SXf@77+kxsi%D|CdG&zZ`4G0Bl$=dCa+TLr2)WHT%g? +zslr3D5PI#rwbDqEemc%fO5z|*aLh44m$}E2cT@I_oqerKGwPmE0h5#Tu=J;naQIyp +zZ4J9`8OwaTU%;L&y+aSZ&vnAq^H}G1M@LSlwhj&xFXmfq%`=&E6OPc6)l#v>T(=aL +ztYC43ouk`#CAmaV|9Wt5|Ll+V8b%{d7DK+o74em +z6hop7I0nBg42cD`J?M|JJlZFM-Fnv0#4E05Jo%*KXY9b~y?8)RMP-@%)#;{LOxd@>Um%F3Gr*Z7U*B%xudAED6XGh+!~e`>LZ3qJr=gII +zHd`_DFdVK~;B?~P*uGB~jov|)>>OCd>J^a)O*o_a#B@Osxchng=TX3w>{h+eqZ6*N +z@ZQ5r`8XsoiqKomv_%_*bq?60c=ztbJU8`W*%Ji#$UEuDpwGHJ=?6Jj2pq?U-rvMLYE7Y6%kGvQv^47koz9~-(OIPX-i0x~t6#-* +zW8ngr&sP?4cLfBIwZ}t=p4dGdD7sfmB4x|_;$!3z>LK^69R^kG)7yMa%r4Au*0sJS +z^F(A$>|4Y4Ad~gNmqZN%XE?vXJ>_sFtkln_A9*p|%dDx5D^FB~VBK>@@39@3r`fh| +zMrYzVr03!N#qD!W#?#xd=U$qIv-sC9;02{gWx17J2;hmL;%>2#*4+1NklzoCbiZ3_ +z$6Mx{0^u7<3`BYjjK1@TyX}5BZ5rwv0U85ht#9$_TZP9%;EM%AWLsdF$C!_fL~A!9 +z1j(CX!T?g6Q%N~~jE|`REkYc5(nuQvI^Qc+0r!&_5w<1Le$3y5rhbNR0lX2`pXE9e +zZI4)}W1zG#DL)|DIFE6Z9R3_IY+B8Y?EU*yc%qM+2c>B1J~GBh>F8%|E+1@45y*2L +z)St41erq1L;-0UStGo3djGz{pw#ePjgctcyVE&Ye0oW~jXyC$UVYNSdK8ou07^+iY@NnQwn1Fu|}y9H4>r!k-2D +z+`PNM-95d^=V_jmbNddpoiAxApvr;x$a)aQiU1x)uvX4QbM6qAnAi-}+PZRHll*WD)uX!$}o9ND{RxqO7D&;3f+^bAVSSAg~4 +z!RHC|G9-BFGYR(K8;(ay%(&o|5Tvil3m3fZeBZp+R;$Yn)nzF^ipQkxl_S1;S)FOJ +z!%o2qkN>Qn_NuN)$d;QB83*ggX&9XZl*p^&2}YpV3@0zy +zt!v=^7_k>6>v>BBJVDXg-jD +zX7aU4Yi+aJaG;LU($^#CY1KN;d_73n@eXYswOTwDZF?Wj&rFAc1dD!Ck;6e&Zb0A7 +z6w8a5H+S-)pqU>fHUg{1+9i2UV>WZt6AC99B=Rc{gXPP~LS3R+l6h+ztUCF?k+WYi +zLrgiBDBg!Abq`gc6P!mfza;1pR(UZ3#1hPq%#Q>YX&-zeCf!TQium~oAG$~SMt#Lc +zdYuozqypL*!TV<*3ysXK=tR>7k$$4k_qO*wPHF`g>@vLlWYfJSIs#F%o54=@`HW-6 +z!~qt*86|zaXBAv-zG#4h?R1|+X*`W^VKXrYb<}}FP@q1KExfud5A&{|$4#cq*zPwW +zTiXILbrXo{vpmD5O7jtBD5 +zuY_Aytoo9qJ#aX41-YY0pwn=xxS$*8J>gG(2ERWqu6b+h!22rWFA3WX=NzM9I)?aG +zqo273`}X&KCd{S@+{a-EPv!B9r$H1mpxEL8I)cqHqOOL=J?tsPyNJAZ1Ne#tT!O^X +zV{hti;!{w$;TBJha2ygDYYhR^zbegKz<4NMt>2N;KKA_tBL{HD+`6~XHQQN`pP(TN +z(RG-UiV<6lYxg|0enf=z6B!49^H_)Mlcq8bUuWnh#SeS)4Z@Kc=`4mQi6T4 +zEQYUt{Uq?{?Xi@GjC(vT#Kp{~VRs3?YqNY}3lVsHxd6T0SbR`5l|v!&A?)eB;%Pz2 +zB3}lvpJdf1Js!9HK!Y|w(nD)5mEzHO&+sp(c(5K)mmMjHc3lfT=a?(=2)&n`DnnLd +z&xdyT^{l;~$8K_e=Hr^id;u!Gg?2~~&s)X#Fe7`99mqu;fM!``^@GaA8%A9ls8h#Z +zMC!&8sq@Gp(&M*Tx)XbNUBBJ|=M3q&QKpVG7lf|icLM)dc5Y&_6jqOTYCnv2N$+C0 +z7S3ph+MA&8%A!nWh|KdV15RBNOt$PX&6gGp}D>0R+AtBhX +zWcM`Dtrt4)S5=`S__(hqu?W@^hHyY=1vY{*+%8+b5B0Y!Na);q&wGrE%~xcjtw5~G +z$@}Ovxl;&}-4plBsqKCcFcixo@dS9&*>b!#;fLGOweqwBW)TE|;flL{sc4);A&Qn3vWDUwJbY2f!&&<})}bfs{A+wqCww1NLm~#(S`r~K +zW1f$Yh^G_Clls2L@?6V!GKzV@Lj3NF4J0W +zvvzZwb16QW!Qnn@k;Z650qB%GUcNPziCy0Xn5^oqI1JgnZsuENF@C9=8Z! +zSLG@33+l0EeG_#bM!mom-?+rJ#zwO!Vo2BKg;gJ7I?9YJiFtzM1&aGn_8I^tmNG9Dm|LflR`R +zvG0Y}2Jqc_6T4TU=wuA=eC->X;@Bu{KY?5mLNM0!_;+zLNU=U5H4&soqUpO&2nOTW +zCSiTp4P;lSDIWo)p-p@{E2Z7I!<8?E*-e!28ph|_ZN7~r80QWB5T%@I|Bq8IXx9*wv(tG3S +z`uvV2mIPvj*7m8Sx3eEVUD4U_x8)`|ku4sv`TSM<_IH!3!63~DEkwxjmF}hbYHUCK +zRa+p8uH|n2ct5Y5BeRdV=NIj3_%Q~>5i6>jr=jqk +zfJYTH`{cOwRx%V=?}bNB8@UJpfO_l&Ydk2H{Fu=TMcAlP5o=7>P53FOoF|ij-<*hN +zIVjSphi-lujpLig7kBt`9+dBJ7d?x7b-1E4#kP44o7bL40lc2d3F;mprCs!Nsk%!g +zZV1r%q9bfu+neF)VGW-42RQuPy`5rDh$Ivax%O97ELx>xnIai~Lfspb|x%?GD +zDV|ksvbfqn+M-Olhq_^3z~T*_`>h}7Bd3igwrF2uOg&nDY$Cl8h#v=m>KqzzMct>A3%(3F +zenDMD=NQ0^u|co=Es^ +z{pDIqcBvI-he?=J{cERdc|V6{@fldX$!KLq@*ZWr +z@t{^yQWAP+dB3AB@2agOxem5KvGwE-j2CTA(tQ{mEPT$S<`LjWi!Z0%njt?ZqI5&` +z@YnViHj4YoDL9dj0t()1zE6C%Tw}L7>nZU#WudHJiJLANt4F>*;TJ+PqFY^U|~3#RlrZM0TbyRDKK^S$cwWOO9yp(|$wbK>cm&WCl^8z*Nei!4mJ +zj%TQ#i*&%`gaHhkyvvXPY2FsU`C*vK@W6ND6HS}8B&nRS?_wF +zG{;OdEuMn4{_2Tl_2LF)nZX|p-N`hmy!a&^I(%LZ5{#>Xx;yg!QiFH0qTuK6%09D*MH`8O17cc`G0e)KiCv +z$6^c&#IH~B?19BAcfZ3{Y4n!PqdO?1exq(JCy0La+9KO=k!HYEjl;nIY4^g +zynQd!%ZImNs=rKVEQ_6a%){a4~unE)SrgZb9^^54WBMjd3<*Y?5m8g>@R`Y +zPBD4n9T~f2Wv+N^W**(v3o(x}LJ&ljXGb6lB_Qp(nXe>zPus7$r +ze`%kj_Nap9(|#9?WCCsRo*6~JI2{`+r(FB%3V#3(?USv|y>CF@==DB5sRQ>?pF9VM +z(cyk^fdiEG?t30%`N{|oltJr`=b-bQtm^l09vGg8XTSWA>+fy1{UGJn=mV=a1jbWe +z9N9fQ2m81hLbl_mG1<)w?wW_?u1bi}CYP_lLPveo9xjh-8d2%II3ZC)u);j%9-H#EbIP)naAe=C?G(zy1OXFRXG2pT=>0v+vNTic@FE +z_`uN3qe?d+0aZtPByE`oAf8fBQi7V1PA~+%-u?9+V>n%B9N8nDDmZUsK7-3T`PUYmsSeMaV0i===!X +z+vjygp~I9!MN{Xkia_AV7stvs^JM#1y4E4UY*A%}n@CSG?&0sI7s0^<1`Qu4%?2p;PEbQB;s-l}vp8dY9j9$#;)qDG~y3>b`9ldiWZ-yQRUx+Mcnaj3tG6nY#zOssOO1n}Cq^|cB= +z^N6Yrd%=AR`^n2&1CEuezCx$=BzwE2SsX$3j*ryM#W`4-wq8{Q?vJKcLELNi;$}Br +zx(9vnt44b&E)IW>4@B31@8F&0mC2G5J3eElng}e%eCLJV8Y~ +z_o+7E7W|qcND!pkTEB3Qr!Sj*&D!Cq-@S0a^zfAL4DZh2lNt0rkS>vOQt#{!T7Gueu%bek~8q4kP;EthBK+Efv*uzWf0F +zPHvReh-cEoRRy3{Awe^2@H-iJ(TSc=sWH0oG&#iP_-AB>*;VXk?`V4uRgLyKZ*v=Xb@*6UC-I3)AFrdcL8u;;uMliRUot9{cT)K+Naxy*^56zVRZyh@5}Irb1lH!JQ7mm=S>kN +zMD#w^i03J7fixhtZdEW(jgwjB^R=m5volc-wQdm}!!Pr0=`-|w%!1?87Wa|XZ6{|c +zWW2LcZicr2hpqO)x#k^N)#w~Y-JztgGE(23RD;_oPa|Qf- +zmx^54gLRG6#$3Q +z5WsQ}ppXte;gw#drqGs2{eCIh>Usr|qu*`21DO>ZAOVDSU((Hmc$RGX;Z)96{KdlCFL`m&>-9xUOMu36Hn3CFSRsu`C{I#||38 +zcg@`TCch27qK2c+bXRtl&VwuCHOkw4Z0n6%>Svis%zVqKzO%{0*?#8a{0C_Ky!5^< +zPNaR5$-h>%o(arwsB`v?7*jc~wSY6^juqrs&t^60n4XvXu@H3t8h +z?kzW%qLE?J(M*^8tR|o=Dgc&^$2g +z%X&Z^|5(qJWTmf-v4BumShEac#2&bPvD5yJ6kgHb)M7`M0VW +zRTz#JE{yMiJVZ4&igmg5x~`Y|8-ZQ1ROqkm^%G7t#{AhREZ&k1i@x<@2821cCD_K9 +ziPl1uBv1ucz~TdsYM74V{0UAZThl_r8%#QTGl$hZa=Mo1Eb5&w@Qb(r@-Nt!$Ki)4 +zzqZD5Hs))3Fd_;pS#V!e-uvdQvG+3X6Cm`0*k%-V*3%6Z^kirnuwTum7=u*hx&fP1 +zfLRM=WIavYWLCUjX?4HE>NuZSyAv7X%}+?lcdIM%=46w7Z}NbjeX{TLTI-AbDP9!h +z;ZskX2?4gO8-<$|JU%lrO$Fl>({qaN9a=r~7CO7{HKBUM`%U~&J@NIWm77rC#pH17 +zXST0QBQG}Tuvi;y0-b8)LlE@YJmCfUjJQ3y$nN{V6HHh3I926>lAnUEyY`iNCw=X) +z?JmXJEqcI)gxh1zew}XUDal7w`*S*&Fhd?#|C%Wn)L%(o3KL3zF0edebu6A_rV}tk +zf@C*2A2_)vN?+lMsU;N}+52VJ>ZCpRA4G#r)|+dGSKr#N&ruea8kG9c0ZiwZK1F(L +zLbV^Z2^ayq2Q69N4KSMT6jWx)`to;WbJ(=I*nrx^&z;ZbvrYF_K4p(og?GtsKFM(N +z0kF*A&f|`rfc4>r)waugnulj*V{M +z30**rHB)4WN@9j5cxD06Vz-Wf;w^Bkb@?)#mjmGv$bOM?&t@w#)hUoiKVy&k@S9qR +zV)@$ju9DS4cAExtobVn!aG`_0Jf!HyJ2$l@Ezr)vLR5%z!47xFgRLQ-CPgcZ&!+*P +zM@#Zv^>}esG#sI#tA4_U{=ELydxTgJgD7sP<#D)gGHcmbzeC2ldK?TN#WLkCSZIbM +zi3u;H&%iyjA9H7zuRxx-VyMR3-q-0Q +zR7Q3(blAk@^O))pDvXq@?9T|2tZ#p|H4h|$y`BI@~4ikO+lxF>Y`o0xVd=aL_PsOpI8aBWjahnv|q_)o3T#uuHDM{d`YP#9`SLt +z9o?@d;AOyAaXZXM4~Rpj!(EaHjznXb%&^H4qWa3mWvQkz1>=dX;#zwDUl&~hS;OWlcoC|=Tl|-cdbG~K${K9k2O4jaE@0uUR>763 +zeVTOr@aGpee%OyviZgQGd;PB(=4%{I8+yO9y?iY2 +zDm`IQJLWE5Z#|E^2T;b2%Z>d^jU_QDoVOP;_&5PDE}WUI7jvr5DJp>$=~2d|6GyFz +zB^)jE2B;s?&-SF_z4<;Guq6QqM;77)IXp_$K%D;d7uj9l@zfc=_vvcQM6; +zG8LXW)zUa?Q{FE+vQdO|%bhsxT5WjpQPTFH4hF~DG~4ktmp?-X!5rqW#EhJS`U3bm +ztI)kS{2bHHJG&F)%?<4G#D*Ntz7ldIb2|)?8TfPibx5jX&?hb;rys^AI>gr3h3?aO +zG|cN22|G8tuOm0SDHeLGB9e*q|BpU*FHD=VE!Bk`WuHxah*1k;e%W-#j_L4bv8qYx +zJOSczUhtLP0_>}^nWJT*xJN*;`Mj8l_MlQDzZ?es926(d{i>}scl0R!yOfU$t2Ji3 +z8*IQA3FDEk!<K>AY;fJb1W@Ua*0%meXV>>+8R)<+D8@Tj>7&t0^;ONv%bd(_NnN_*UsrQ9LjNS!B@7PX +za|g*p43^f9d`_T`O623gOEzWDSNwC;MdHKr0+BWujt;@el_xO(dArk604kL92|a?C +zIx4CD1jHGKiWu%Q1w3z+jm~;o(k><@9&h`4J%(Xm-zP;UsT+D*77#Y +z*v@Am_w~vWOnkBfzvH?fXnN6HyT4SEB)h^6r#*n@=-6ITlX|c;47G7i^Zya{?zpz( +zOmnDzNAckw0rSngUOpi}rc6QepN7ENf~+N+2HNP|=d8V|iWwPEWJWxMwDv3ZnbawN +z+wcADw4B>TIHpCeFvpHE=*{bQJ0y9h;E3=NGHUmQn>KiCX``Y^@Z+zqGQk&W`}2Ha +zp?p0-u~;lh1|VQsmHi)pDNEB(kVGlM$bj^d@>=yjmS9{n719$lOyY=Vm`*MlJ6@BH6#VR*ubO{1O(%&UGG7 +zQB1tIPka$+8@0f3y5r0HG|-Va=i(F4Uu+;*Bel$7nSn=9FYQ~-k1IHENjozrTG%Vx +z@9d!9pu9WtR)jtc!sHakP#Qkd_e1=JRiFqzSrc#zT>)4K1n3Am0c<_(PJo-Ap`#fQ +z@3o1zMmcjMT+|;+m_#6x$tQ_dsDSwZ9_vXKz2tYK+v5pToA1yj&Fi6@{G|3?Vty)V +zYj0tO?s*+`pVpY8nELolA5-1ZPHrp>aJ+grpN{Tp_!(RIdGzown8N4SVpjyUFz6cX +zL{TVXCiw~ph@4nAJ4JY7?Vq~iQk!r+QjZTcCZ*xJ?LSUi&WfDduTNV!u|pMt&e<*(ajVV}stI9OCQ=h!Kv#eV9m?mn%r +zRB1J5oKBjQ9gVzjPd>8AgT+rHAy_inTblHi)YEnK)HHd42?kXd&EfBYZz=@0-`+3O +zjS>Ut3oLHchv>D=XWF&(g7r83We@+6`G)#s9`Vn1ma091R$}Iey@KXm_hS}*Y|nQ)9%NkjhT-ow +zlSmj*kKXdm!9UAxzuWanvX0VuE +zPcMi^6fj_(n&^Gi6DO3v_u-HfBzhhXJH0%QylsiE%2WPwWl9k_6V2*I4gZOv9|7$v%E!?&sW5T>;5^Jlwo)Zy^NVz9CediCPaD*!J6yA6&n3rW+r9 +zXH}?V2Ut*PPNi9tyw)fD+htgdJoZ+(08>D$zeh9z_pxkVAPP0&&x}WQ*w_G4J-(M* +z_|NuH+VmY8dcd@niou=LDRW{fdTruEswoVSKg`<|y@c9hultpn8)L<0b@%M96%pC?%mp=i)6 +zg-T?pxleKmj3$?rYhBTgR`9_FCO^363OJn0GvsqO+0a#1pmapEmM2D}gimx$Px_dt +zdx1jS+kNb*Zh_9_Lt}yZbk{m1&L_g9j?k?_Z}pygwB6+qUGe-P{6itVBZ3lPi%?>0 +zpv95;3k68tCpQYld!8(I&^?}rL0n;H8xO;o=|ubvgdV+i;NHyidk(WCknYYt3PPR+ +zhi95}z66OBPzzD^{5}nckwGXOa|O?3al-=Ey#u0la`@EZEX<=b-^s596S_o^lK?>Y +zHy(N3GYD5-xp=;cO1y*2gB-9|cx*1YTD= +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 +z?%O}Hasw_1!wKh#!pFNn +z^kfXh4j*s!!$sH}A!WPDPqf}*!gZV7zJT4C-!R=%Pom|8v4+u!Whq%OTU&RQcW;1T +zOx~YOgz)!^EKu7OviEJ`U8`>r9g;65xLCXSID}w#jK`y3=cYQ5`1MhE_qp&yavwna +za&Z}ESIXtlMDx$9*wnag8|V%*jJ$e1sR$qhHC21Rl)1Vi0R8BVjF{a!?ExjP86fYs +z@8388e9N)VbiKNvp?oy5U#;kC_5IqKcXR9YGoO#5JFR0LBH<@*1W}-bb(ER7y{L_a +z-xAw&8VPJ%c<>`E$pfTTZbXs?9h|vt8l7lrwx^tFgL%_$+YQp9B2$i>iLw%X{ER6` +za3sGSZaKWyj-Q?{7Z{4`N}VFF&+@yg6l8sNwesN+>wWrS>QSFFFjd-#_}V0S<~N*B +zu7XcpF2{T$E6JL5j{Y;I2^dMoB>mCM9J;h4K+|;a>N*@fCZ3gNmNTNR +z+^HBV9h+|U&v*V@Or;I6Mif3zKH)sJ@71D!XSKmGTrgpN_FV5zmGLZJ9tXf^+fq2OKqYqr1w&)R$m)0JjeAl$cX?A;ZBVcQia<0 +z%cHIH?XaDcOx~wCM;=W|UC**_-XwHy`Q9G0gL)pC*z%mcxNs2sP6pZv6ADJ%?!K>! +z-){&SqEwV<8}QN8$#Gq$2(`o0;ztUJH?$x1bvTuMum@C&i|9KO4zre*V}M0=2yV(Y +z*t`47o`H*u*Ne>q%Y=Z>L-Ol6F-u{-D*hG@a*ntk~5IYonq24bfgIiGHL(qq^o?n#Yqkz>j455XZjWwCLA+Xli0?T$QsSIbXq +zU)2hV2e4@{ON{bGvdknpurGprqkg2{gpeGKNS*~ZG_M7xL1k`UVLYJ9s&Vx +z?l}YZ8-Cyg7NAJ9J_Ys~nk!D%w0xor`|qonTui#38tnOumN0$US7bT%z*$ +z3(~P}pM8Q;(uyZ-&J{2m!uxp4d8Fv^=+EOv$Znf=q3UW#&KL2+;rNtf#{6Gn#Q*O< +z|M_2Uas1c+_;2yw-#7cO|NlS#^Z(UcSkt>PPsY6sg!FKK(wJVAF>STrJjlC{7gJ85 +zDeIRekJ~0){IIQ_rabkuCU~o*IIeD8gkpdAll(XfI!;v5yXqWZ7*~bQ?9b)fp0C%V +zPO`*M*Lhm69)a|y3ioo>naHbng@}F1$=3?BiNRbWG>)LRp2;d4sv +zV`=jhBhTxD{2KNZw#Qv?r6OVoc-qgUj^sS!g502eR6~ncp1FNUZu-6^6e)Rd+d8_uo4jQo#+6XsJecfw7^~??emSN +zV6oV1FG=y8%wn@$SMrnVq1vCDES@_EYXzqd2X!_NeVJDyot*j_B@}SYQ;(h0wT7tl +zp1ECt%6_mFdx9vAB^fbGFZ-#w`{)|z*#)>{cLDaWSq%%S(>l1jhl_ +z(5JNa@j#8zFu7#FbXeLxUvGJ2IT4)j=^BNsMGE=y2Gl0jGGflkTdnF3oc5_@*<1YC +z+(BP4lIrd}-k9H+CD=NuyBwfciAqli0~*KRR$YAy=th1<1o&7`9{Z9*LFqs`T$793 +z$NeGfryK|3KlvV6&sqlBeA}8UH!C#4_dBUK{~b5)Y5mhFdn%9 +zOl1DFujn}IH6l&z@OQaa0MnPa6ckj2zfm<(cnIB2XB{!9yBqh~W1x10fms(3X~oG2 +zvLWN(pdYItKCB3fnto0ni7!pYhn+a=QTyBNNX9I=a@Zsez{Hc7cJDo(dHznN1!kf@ +z_9)sLudu4vkdM$ePjLXxK3*dNeedVth}@UUm +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 +zqvU=V +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 +zzO(#vl4Jh}f|fu0|`khM%ep +z*kcEt77SYe5z+Dt!3AuES-n1w*K(R*IL}u;SH%c)cZR^r){MJBT;bqVUoF>K@wMQS +zaKl*Yo6VQX4!mY2fof-G*mihoxk1G3+68^Ik|R+1gw$uWN`E^AHmrFS1c92pVswwP +zcd%C$Ur#fII@Q{MzL(r;H3FK>;g!4k{&{c;@q(wfq9Yhwuc5{q0LcEv`ZVwew?Wij +zo&-|#ED;5kkR5px4_LxpVGy*>+kk-fv}>MN43Bpx+b4mtpz-bAx-nK-i_}-FqqGK +zQN|f^)lLjb)8{;FNdR;6^%9?vZ0sRw%AC91dEJMk2zfid0fE^Xf_@+7%L*`{gcJ^~ +z6U)hR@bEohY^+-6tdOJvT%tCMC-Lx0W7`G~?yi#~a!$$@v^0Y9)MngjExhyDOkcT& +z@o^C3b`8B7={(&Qi>Kn1SGYZe`K`DkjxtwEO4R8+DBkM|<-Z&;&iT2yOZ9m^^gUkJ +z<5CL4q{PL4Zu8VE(`Ky4HO(^(FS1*ivkz)I-dpBshNbCy(MuPZFT#Mx|@);T6)(+e-mes +z_(%5mb3;=E8J1J?&G=uI*Hi1}gZVgp7C&{wM1DRl> +z>5voWf#_L%fD~`}+m?ej9b+xNSE%e5pTh!Da*Dl-dFoh<)SXpBV1NdDZO{;Q`X(Ut +z31X4L>^mp4QO@<0FOo0}59lLYsN>EVz@^>@kN4}4cmt;U83wHVhK%x_=GVZTPO{)5 +zb@Tb(>qbbHQ6R}9Ot2~G$_@>)4jl;3vo +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 +z;mWn0Yp)*(Kb`9!?MS_s0LfR6g+K +zJDn%T-|GEL?3^mvVj18{oyWYip{uvDkK*p=cg?SLHvSR>d4MII4q!Mlkamz6 +zhpuKdvz$GGTP^(g_a1YRY;DzL}A%Q%*v%4`zI{O0#49Z=^izUujYP7p_0Tb|3I +zmY;QlOC4h2ERHd)_x%r?)P5*X-?Zb+;^a(6T=IGpBifi0cn-=+ZEaheu`y>Ps4uIr +z_1m@aij16;jPWY=&MWtee99S)%^`D5SdGgdo=J3q^{N{&d|}e%$5lM~=6=Up2;$tZ +z`epZ!LkMEgh9(f3+BqWAjh-W9ev;2J&$(Gr=uqcz)v1TWcf>5ZTVd2U@y-mM-d=us +zUbt;ewfds5B_r8t8oVDo1?M6~JC4wI8yX+cUi8c>!ZBgB*y!^xPibF+gSvcGma=O= +zzr&_i=WbARADe<}-Yp|2OZ-joozX8uWNo7mpMuP@?T?;_iE1CZJLmC3v!zY1O@7VV +zXVVQ#b~f8ypLYvmEq}xk-iN>Z9!x%J@}2FFXU*Xw-I7&55$ESFaa)(|cS)kgn|Zi0 +zcJ!55#!w2=J%I5~OYhKo0T3Ez7t|l-C~~byo_yaN)pi@FKm;)@OmC-S>AJfuETAVI +zxqS(G$suWNCFq2WaynB#vNES!vv}X)0_$NHz8E%7Pl&@K1zF@*;$B*MB!h5$C;w=;B9c +zk68%eeIiotRZu2KCfp*zIj{5D4d){Pc%irbuwh=Kn1Z>O&?ng7KB0CdwYqk@{KAPO +zp?<(!apVG%oGrwgk4_ckz26iyYHID{_`Prh0S|}Y&$s5+u<+5})571(VCx*l^Nmqs +z8y!uk{4CP!zVan(`==$unrXl>H>t~?qvw4D91osRT8&g_4u@QR05#u)6809v=|z}= +zhf{Vjv-^~Cr`~|+gPE_Vqfvxx+#|7sFsF{tdGtZgBqAT<>!%Mj*(`mECGev6elS1E +zubtk5hMm^A4HZR@PtegfF@bWKQ)$OgZ{15M8Dds?)S7&vsjO3S^M>pf&I!j(8P|Or +z_3<{29>Ki5sr*E08%`qJ&9$r6F3j&k{GF0c5PK7mlm$PwXWv%k$%EApv=8?P)E@pk +z$g&J)it79Rt2gWt@3ay5#fwDu@HaW;eW4p4k=dJNs_w<9lbPC&ips_Fq*LO&Z}{!f +zw#WrxUOSNQ4SfHzYXg){cwU98j}}_7%Xht}FF%=V9Y^b_{VXwhf-OoZKX+ew{J*P2 +z4LISIyg_QWFTIziby7u(4++K{Q)C3-r?S3!IIx%l* +z%;Y)uY{R4SI3$^`h@Z~?x^%{)%?|f9caR*LIpZA?E0h$qo6P*V8+M^eB``zkuf&xDB?#s(m?9y+ +zRCce_NWb?UwKG}^^5;^vPZVEC@%pAB+mu3Hp9RhLykD8Si_2>${a~yvoGq1c?O1%W +zTqt*306&B42Y4<;LaHN2s0VjEwv06l&1{?>koN18^K*jOeoqjCFmUhZdaTz!qv^YW +z-cJ_V1HlWgM(@Ty15Caxki7c^%aq)RN?8v*ad494TxVQtmTJCegMB+Af-4>hTn2+% +zj#^Gn=iEN^-9@o2e00oDt14w@;Y}QQobQsEFW74m&^)iR`C{o8ps~%s#(Qpj#(7Wk +zYZ;K2sMLv5npFY*YAuufi@+@pZ<0h{Dh-LAGml{1=39MP?TGU^m$TaXbtx$}#|K0q +zM +zQjy4Oy}*~w?3trCh2o~+_7iW2Y_B2U_{nzs=N@uQWdf@BDiihHO1OTh +zl;NIgqm-oGxO=GnIhP~OC_9oUj}qtrBYk=E_fe+LbCFe#L!p`l6eBhAO +zcbIyLckd7da$S5R1tCotGR_>zzRddYv1&RhuYX<@R_3;Lq}MDhp7dqNhezM6*(ZVS +zBhLqY?V?VGkU==1zhA2G?G0Q$?3N5`t@2h8ukXcqQgw{ZWH?S-_*^`XVA8yTM|%s4 +z4WNz`qFlWO?imslt>Q{7^dt(Wl%gl&K4rI`xq5xBbkW~oRYRX6Mo-+b-bpG4dVO@a +z*vc>O^+Xq)@8s#rrk1BZt5-@56^`dVxxq*C40ADaTk7E%lOvoT8A3WLM`}-AgNUw* +zrlnVQ3Z?=G8>$en`dLtMo~zgu3RRDz>Ol-0i&3r60XyEeW)yDgSy0066SH#Q)|F^` +zvaU&>4()gQiL@~}J&L}IQA4U{M_8%&@t9ouVo_$v4se_3hk5(asGI1hU<>J2!`9EqUCDm_h4L+N*(+Vx3Dy5s@x5}*m-91=mww*`N&e>Rk0(Vd=ty2Q3 +z2%v1a0?B%-l%X8>z>VW!+ajH89;NEQ@&rgjU)*CEh4u;*-DhvT|0ju2FGR*jkOa=v +zH5rq~`=lhlYG<%IJl|z7D%kBsZ%f|^Wt~oY{Qiocq$<5l`weL-4B0*oL(42up7JVE +z+XBnUi6N&1Ss(qaCxYw-i)A-w2!J+FmSHX(NRBT?$l~JQ#u?ifVN$wv;1VU(>t`q3 +zO0P#Rs9Y`DFW&;-=I|3hcrH`U(@9Sl@jG +zj}vi@5DWp%*|NTkTa>V2#4(gO4@%KYs4Px8-W!ve#&m@#cVn;feXMM1SQk4>9k%x2 +zEvg?p^leY@A+r`s0TxvzFtynuY%)yxDAM9iR=ab785*@?Ik-x>UZT?=X95c+>=8tG +zXz4J#r5a8O1osGTW5un@2R2*KbG-sFA5v^HGtWH1{zTvX0x(~7Gq;#S06U^Yyij)C%6A9!b +zK++r;XL7$-%fYB +z4G^zJUb-T46`n45RWQ_@({LudD_n?<@lWjexv#8Q#&&fd5Ap4yIl#AKCsX!}GwheHxAYxSxwsxt^xEK|U2|OT0{skAJ0njiZop!n2)8L_ +z%zX8s7aWx5p6PQNg|6E5kQE-H6zrMDUmmL%?j1Qtrhz?f&HWsd?#b@y&Q*;%{g96< +zmAJhk>k>QIt}xVFC{I&G-N`C@?bHe#8%H^J%8P43=CH6~1fN+A#@E^8;Y+sWXDws)&32FV +zCCqzY;Wvv(*Ir^PD{1Vya)P6d!Ci{iqeouf`od^1pKN+>9H84QBTD@1x1esvIUO#a +z%b1KpN3+MBq7PsF(#bH-aj&gwapt^E>NpqvV^A5C3jEp?YYrd~+@9aQs-X +z3J??OY>F8F)2-q&1ygu>m>#|yw3ag6>-J|`VZBd<$((g9c8RMpZ75XH!>isb?L)8S +zR8vd51yB4G@csPy{oD}p=BxV{3Ep0KSlt!C;1|#jv@W{!9j6O0@uay{aXPp6P_&_ieIi*ql&#Y_erCEj%KG0BC`K~{P4gIa*>vN0G +z7eldI<+D_GJ+UJ$Kdq_XRN%-O~8waxX6T`#lr>vetRxuumVw +z+#^`sU`-S&W@>4J*XsQ_L%wt&nh)sR;_>_fNuXAu@hxvz9>N)n)Y<_emmBjNpLJrqFiRlQjB7u9>2IBj)qSvn=65fZXeW +zbCg$);ZNj%on +z--AN0n}A}@c`x2egrH{ki&>2Kekg6a2bBPlkLr8up)iXgdJpXJ#BJ;4>$o9o0q6bV +z70JiAbecrnG=ON@#%Mr8TAJ=BcT9Nl0MoBKp7=W+4%QOC5cc-IR=ahyYV#ab@Dyr% +zDm`e4@1~Y|n*4Ke`LPiB0!}1pb78Z1?rP(r`DZ&d`bf0OwWW?naOJ%YLAlW7>ru{8 +z2o#Ayh8~1~b6;(kG#+_WzAvZX(?4i=&Nm!~Y{^yEv3a$-`4+v8|5UoO>Ek{^?JP`| +zyFjX>^8kftUwif1FNgp=zo@LkC(ejHm4hl@adE82;r-4mA7Hb7uA0j$gr1V?gm;I$ +zB_}*@bA89$GZr^(=hVLC`gtwsoVejn|2ff(vTBUIO;V~iMJ~yuDshJ!xhHBvL1XmH +z9l^e#S{XimA#1RyKI_^Wjijc$m(FcBM9^xfo`|H9i9rkcMm8>9^CKdPXYIhXrzGLz +zXPx{M`3}GnIzEf;hDuq}3kT!dpcZE|I7}o +zNO~Uim#NpAmY&pInH2$;nLA*F{v-^j&`PYZuGdq4?%jN2%JT^FEq8|sdH7-4$Bw11 +z^E?J%Q4}mNUD{dagr(oYllv`sU}A*Ntl_h7QJ)isdXlN+>MZF{?4c*ve6O_{5I7um +z7?`*xgYiCkh-m9ZZ4J3gR~GRI=Gv<@Pp6-&a8+@13USl?%IAjIF?)h175qKwQH=|E +zPxhGFIlZY4?uTHLP984(&sa1OrjGh}TIogatKR44Vi#77#S6eAFRGg&Vj7*LStm(@7q&djul!)Dt5B4QPj%yM{&hg5=;mm+Zl0r~Y@PubO@{^_$7Ly|~P7%a;$t +zaJasrT`$du!r!lx!&ZgxP!`S;D& +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 +z+4!{-gU>yTHl|?r +zzu+CWzRHk#1pQ^qp{En6^(+T5X7gP8HmpPs=a~S6uM=6eu1T`*k#7Mnwq3kTOZ4^d +zSJ-OinIqrgH$jKoHCJx5z1U^5%WRXM?Yk6A-F4(TFr&8N(qUe4`_W353lb~xwXR9s +zpko?|`0&8^(Oi86n$Bb5I!Bn#pS|*&!I7Iuev!YkjK1|0@n@M~^oSGOT}Lrh@y{v0 +zk=10ng_q$bs=~B40Y3)33v%fiWIKJ6{Unc}rNnffJ&;xH=Bxpaan_gy*COck^|sWJ +zI3ZicfE?f$?bfa}an2!hnfpn7^OG7db|??W8t1j^B=opJ!#xcLVQ*mcSPHMp3Q;3_ +z@~E777-pedy%b!x`Kf`aEZ^bCnvb-{olH;BMeIDs8R2kGed5?HUTjZTXxMoOte`7FeKzrz3h> +zvG7`*wx^-pjuUFF79JIE#M6%mq;S9BUaw+-^IqpG(^44wlD=2Q+%y*L#o79n6k`Lv +zmqHBjKFQIK3EctJ$YQ@9Fg)fCX;|=x=LvZK2j;@*mu=mZe%yd8!29c7|4i5A@ob!` +zC=VadGLl!a#BQX)lY`gw +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 +z`E)vNGfm~_Z +zaq9GCwYWD##(|X&fvI=2U2fIT8{g(sNISlbi+g}>-3Ik<#*-G`hqd>-xZu4ApVQy$ +z<$286EPAdxoq8fNOL^}eJENcBboxev^G8Q}eOFC=o;+MeHjq8ZV^2y2O?<5#2mJc2 +zLcniHcuwq^CN3Y_Z%_G=i6Y2bHlJFCWA}XBxJ)6uE#1=h$f!Q7yv&l3!W##!Tj=HsnuBDU!V#bxiwwqe>v*rgXXG@~TYx(nCm_89L7ogr +zzDaffbOniC)`=35IBubaej_qJE7Q-@?slJhBOba(ef5{Jy0Vv?E8y%hUVJ*=+Z@9o +zR%OJ&<~;TNO +z-;dNp`c72`=e#Gca2`?;AwhqaoN5-V=LjVa#x70H77(G&{;rlg{_j2$0d8BTRJDjXrnt3coX*!N_BV+AOy^xJnerfGKadU3B +z7F>Wj!BexHK^*%1F+-ZUJxM|&RQ#&s4w+=J2jjEUlQ!uxSX(Q{Qj^G_S=TiEE +zn8WDGdO{<>>;(y`+hfWm9U-G>U$0i&IFX`By-xv3-|b9o>JnU#^La2!BR$O4Z$J~c +z`0o9h9lws=&!`I@ffgi=!8FxKx(*iC#JqSpL49jw)urIUqBR +zC-WZWlYZ}7KUV(U!D+sX6#}*mmp*q(OvpV?i&sxA2XkOc-j2(4hTE^KTZ~_m_npnJ +zKCr17xys`GkTq3fJvP35!^K#}p$#ZBGPMs5$*U!ptZHu^)x~RKaFp(Ncrspgoh!mV +zC6DtDRscbVpFC0h?Gs3ik>X1g8Ks|Zk&f_*dB1lv9BN>+q~t?y=fc28c)hyr^xv!Z`W|7oUV2$#M+*;8z!Mie!Hj$l +ze5b0V_tiC2Ew;1idHo#7muGm>>bp7KnVKuc2G06f0(_SCVaFc9wBW=s+e24%Xf&i6 +zCq(TP5-dC1%=f*;t`nlQeMk#*?>FIi!_#Pcau{#R+()5~%!$(;dBv={EJCeIzG><1 +z#*c1LUcb)J*$~3b=f3Q};eI_LsAHjhTYN{Z@zE(-I`yqx2mNpG9>y~7Q)4G+_A%N( +z&4p9^0)~!55mj*Zv3=i?y5|;I9&3_sAE@Mw<@aNX4CDcgI-jmLw>AZv{AoF>3g4DdR&(4AOpnlb--#&`!LGpRjo%XgRAr_11@Dr6FHxa>c$3XSH +zoX)`vGB_bu1ZMc8;pk{R<<#`~-v9NmmC>^Yiv^&!pBVV>O^J|l6Tuwu#wnw;Q?7U@jQrt72o0ze#L4r>Q1Ja`vkx#R +z=Kxq=?`wML{d=H&m?ZDJ@QvQvH;w|bMZ)nkR^^O((&QMNk=UuH5c7mZ3}1g4jZY!) +zXHQHVRKh7+A;*;b&Us=$?Aur!-`*wTuT7sQOuntj^pwJbSM*C3QlD>jaI9Cy60+gJ +zNs?X&St^sWI?y}*kO&?H<8!1e4HZc^_Uz03ZJaZS73sa{wkTgyR64SQckiW+j5LJz +z*GvdiBlJEp1Q$=qDi$wTcD*`0Ibuv}KsW$cmb +z{$St)WIPQNf;o@NrWBoescobia`ACJntrcO!@1q31BLao7@rXZR-=x3zs@8Y@V=TW +zPl*MR?^?q*qkm`3=)OR(+kUKGJgSy{BjN4ox48uD$gcT8M*lQR<#*ts)DacNd#*KU +z7b=`NV0lCOhS~wW2K=qD?vJTV;HF_f%D|p{-~|SI{o7tCE7MzilCnSF(|_OGtqRAhJb>}-b-ggV +z1$ao@=iKkIJn2&%^PM$wTKz2rN-Tyrc~0l$Td5m6hg5~I9a@%iX4u3WSe +zvw~s$fco33<2=1=54Dx1a7K@qU%wOm=ocjC1YeDE+I$5ntLQvtX?*(hclDdWsND>E +zPWGX|lUGAE+?9g;ar!DA-_#TyT!SG=H0gDOoPZ~(r@y`M_q@6%{4(}s&7QA+?djg5 +z6R{GnBtFWDEi;b_T6>RFeNJWRtDp&YrH*3U{IEgl~OqOw=o=(OKvf52P;^O+|H>`e%;P1b^G;F5fa6uxWkdTfOfcm-957 +zPMl_5IhcO@bavqS!Vfv7B#q?E{GO +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 +z@)r{UZ+?c1n`3! +z9H&@y-U6{UR$L<#=9mN62DV-e^K}5`jsy4^e431!J;d(-8WFwHxU+X1%|6Z>0j2j* +zTCG7}cbz;Z2O_UwvOTtpCxf+R2B#@Zj`&Lq3U;Kim|q&FrF_cN4+0atMCblu*F7jt +zpjn(twkNHmTzc2Qvd;B*0#e>k2fWzg+&DlSdTklbPTp9vBW$0&i8wszh+`M7H~U*2 +zx3%NH@12EZ`;u<$i?CPM2GI~6iWiZo5zvl16ULixXo+cZSwGwDp*IJ6>h{%ZVaU4M*$qx;u%y$)B1uY{90 +zF81BB#lsJJ`E1<7?smZHoUf16Mte`wrQ4O<`~d50w}RqQ?D@Pq_^k@98XHi6-aCiw +z>X~@i?<(EQFuS}j#*ktfmWz3QElx-pt>z*t-2sC)3zt=m)E4$a>ic&l_X0z3O=?83;_cwQvG +zfrqy=Qs=~%I`mX|(iL-gp7Wot-8uj`}$b5uPqX*a{4^YwsoIaKcRiz +z(gML;mZj-bzx6a@SroV(&a%0+2IrwgM6q=)5BOcC%YFs#5j{}2sF^!lgICT~_>MGy +zZ}0G`LM9*Qi^z$qj;04^b`EP5e4biX5Ig#9 +z<`_igqbVtfOOo6&2r)?1hiY~o5|iiXK{31WMu;O}35?$iARvFpvtZ+XD@|?V>;49P +z$t@MFb$9)GyEzL|E5|HdKQSgc`eyOn2do=%grbo%b40&l2J!EhH;k^mOsQ#m%*VcZ +zA_Hs<{W`^EFSya?Vu3t2fA*o{-<>e0p0F`QKrOxJg1z+8sNcz;*61>SMX7x>m`~n& +zkC)a3vOH(z7Dr3_*Fa=d55}GXpJ*7rd9X*$zhlnxYd{Cd7DER_wT^Q&qMtJx)^?$EaGZTnj6%2(rO +z;Umd}9*VPSBVXks~Zv2uM>NBaapg(cSfBxrwB%099=!V +zl-)g|yB~4z`;K1lX7gl{>q_3Pd-yY5pH02nX +z{shZ=d-R!O-Sm<&s5h-_B-g}%%+v=%Ps1$@Q&1zy3HQxn(q^@MOO`{Lk&{h2-q$cr(g_n4sh@jTzk6pw +z7YjNPSzS8U&pA7GDVNWFmX^kRJ`YkA5_tR}xZ_{{;oUw^$=0l)H3y%j(#*(->o@U@ +zZ0e)%f4V2+i{>lMX}p^+>{o}V_PU}RP3ifzdFXsLmybT?Ry1=37Ib~SVb=Gln};h3 +zed4$_v9Fje&)ExfOLBaVO>6|7TmfjPmtpn=uLun*eZn2SjgaCz9j^TZ=-Aozy2=z= +zfQ@TNe&fU&CT?+UwIYD`JL(L*M~g?TlIF$%96UKtd>ViO@5{(a#+5Wr*R_#73|ohp +z^OS+hY9l_Z*y)^2a%-N)QFm||V$>GFFqVzNLj5Z*5=`j(=Ka&_I}5b2mi52d%mYHM +zALR9r0owE?^p2Nca?uO%llo|4^kHahe*JPfSEV)%9eFCtVH`ASW9zfyM97B2l@E#E +zD?fGj9QMOVrNJAEw?`$_)(4x;a7qjAgPgNB+G9IU7QVPgV<}u;b8k4fT%LDV(M>!e +zEoS*?9Zz5;4GhPpxm@2Ztdy+q3DV+X>PDJ^0=eKj}gb +z$K>)Jj|DmF@i2xV=X}?Y7=YtOXW7>w8v*D^LCkoXkog!~r>+B+y!DiXVM8>$1XHvg +zWN{swhEYUhEF`nRj-G^4;rx}O?eqn~$d_;p5vPLk;HhyXFRw5sJxys&Yr+NvCaxK +zd}*?P)pa8-YsGwhp|!-=zp}(}$8(R4Jb}1dDi%*!^4WjIt;xevsTEb#p9frG-J|N1 +zN|&jwE6<^OO&u@CvHK#N-=6VfzLD-ht2d(-cv6J +zu9}yebAghN-h4~_>&c*(LCnc&XO6-f%bqLW*;*^-G{o3mJA~}FF4D?5DgJdnCmrK) +zeJa!nl*_~fP1*e`aG25i8NLbH`P#W#E`+MzcrULoLgJ*^Io5g(h>NAk0FIuaJ|?#C +zba|W`6LoH&+uBn1pX}?Wj)_*j_96CE-n^WPBRfoZsSq)+uQndbEsv;vSYearb4U+e +z!Xf_$vBJsvn#A^eb=<5M6#~`02IJ%cT^l0K2BLnvO)bpV +zchLH*)K7)@yFcelR-uDDrS&9_M$TivAyq^b^jT;Oc2fuQQ>xf?3jTtYUbu*b49OC#42BbZlhcMf;Z@ND_nCI_Wmw;U)5Y~#`3yQr9h9}1ZC-s +z{sZ+nWAid%O_t~dR6nD7!H=_!PdC&&8LKU~?|a{(#)r%3Jzc-a+i!43`~6%SwI0qL +zguGBg3SovLkn&xnYCUk`ND#o#n|`igm%4$$o2+DxNtIvz40zh*;iyW|KVD-0(N2gU!`^9olAgM&wDyp!S0*-RRF)) +zh+k*7SvjJA~f`%>~6d>u|pkuvEEFLEj!rz~qdNnvxNNWMS6kgt3KH-W%ax +zF=2Ild*-S!0E*}ice+1U#Q46YH@n!;Wb@BZ_^xulY)Utmx17%2yn++@7|VnUz(4y6p&qXF +zmtYSHyj-zQC1H%9*xVBNY-Sjl;VrpT;LCjWt011Jh-PiWHSZ@|2!ZG>c`&qr3c7Qe +zs_9XXxr4}JS7DiRrDi$`CT^4h^fgGg6npZqo)V>dMLkQ0;#>dzl`Mqkr&vRr_65yZ +zrWg@SMb*A9{up$xWop`hdfyQ!l(vgW%@6kM24>Iw`eUg+{;cy=vwF@VZbUa*x^-SJ +z1qn|f1SD2}po}t|FlYIFB+p(o8uxp9S?pYaI+BzYLdCmK*OyL{JtU+;f~r-UkegpE +z){fEReNsPY8 +z%1-asg#IoJMxoj&5O$eEufNxN0>0*EH>Whv)@Fr?LdYLA60o4C-n%&eN!5 +zXU{nyfosZ!dnp)jn3uFs7;x*P3wkLFoJF^}$hlwrr%4#dKgsLx9KB5n>O+2H-eh??>Zw8m +z49?IootH_niR}pIVr06WZsr(3KNIP5;6b-A!w^>*1qMm#N^>j`#*G(|@sT%A8^TL` +zZS<89W*=x<7QSlmB-MND3@>hwg(l47h?ifC=ic`-qzR=HPDLWtwc8I9-5&u~UL@1% +z+bCIQ=d($Irwi#mLA*WuR@-HG?l<90)-+uv}p_M4F*QzFQacYA%6y4$%F% +zL;t&LsG-{6z;`d+>T0yPtLplDE}mKXe9ftjUa9xa=0V4GLPb#RI&;vH=!NEk2xJkx +z+V;}nOq0@6{5K<(9x?y3DxzWI)QjbHG;|B;>}AhOI%#6s#3lKbBu{j#_FUhu!*Ckw +z>RLPw@r*h$SvRm1aO^GZj}2blIgjPlAkgF3Wyy0Fbs`s_Ca#;!TkRIMA&40lQE%Eg +z5N+d~3v(hKFr(3M>5~R1X!qND=E@y?+A`@8l%OG#9E>SwhkUF=0q||pp08;BLm0?v +zI)x{;r6sF`i}Nx1>eIj$%BmY#Wfalr%v@*2L#O(>4{S`^iExQH3)u!XO;ZyF%Isgu +zEQIDvd_~}xx6&2^`w}#$xxD;kQ&^`3BNwG;20K>hTbjYqr +zAmj8Hfx&o$^x3sjb}VuIp6`Tx1d$#TOcp${qdI-|p!4I3m80=c(!G$aA22&pV+d?L +zkrjDiWc!qe+9RazPPRKj93D|ts*%((CPSst19;=e>Eh2Rf`IncLTdtWm5XNS-wCF0 +zC>%_(t7-{nWo_)ShVuijeJ|HOe==jMl@QV={lER6&v{b#@OAMOxJqwefo3N?goxjG +z7A0U`J*-z8Frz`iuubKvjPibaVnL}3cK&SH+YmKu_6)Mpz`3?96+N4wleYIQ&)e +zvMgOuBnC6< +z+)Hl3e3c(0A%6{im8Ahgy?C-Q8?xJ81{Vhh$-R9ml)ugl!gr^pQD!su70O=3bjwiKadUjcrf@ki%O%Q4w4AU&fh +zq$7KX&Rb41{FHOb;id27KPZc(zg)HTHNPe93omcddg;l8(L+EO6yszp#=O=!K`$4z +z%G^Rg9sV|bQuvP3=cZmyG=Nx}6*(e5whAanp8HbRLo++qm1vF@LLm+Tj#xM$L;!W> +zzUj%tSC3nIuc~C{CQ!)ZGW&xM0lkTz8YJ;a_OacqP|!N6Uxn_&Z81A@#(kdbbm<8| +z#Crs0^lag2ladmzv;wNA_YwD2Oy^F*xp=_t$i|J+bh<|6_>&sv3F$Gh7dM&XGQ4c< +zO786iv5}i^uw>KE?+Et0a$XwQ_{#mNEBTyTSBD+ZU%0(`@Vw;<8_0rJt=n9CE3kK3 +zFzLHIf<5WiZ*oSZS{k55)l)n|cPvFCG-^;V{hu-H(vvt-7wEp}a9vpMdyAGN2&d&{ +z0vz0wJ&7xn5~zn~VYTqvL+`AmBj2I#B}G!NRanZtv4~mwH7H8FT#z8FDdXV>c&-d1 +z+R6*XFKtN=0$QHD19qqbFMpT&sW9BO`|vI_ELP89r+dy8*`ClE)F+VeMDVxA_udxA +zi#kO4Mw$I~;#3^HFE&djaviXz85U)($+?8rFWoB=mmXgRz}CbYHoR+c&fVgW3%t}L_lgRDEMfC+`@;m(bRimykm(;&v{ay +z)O8$^7yL85>PQ^87|>iqh4}dHVOO58!DCw_akrl;$NOR`L&qTOV~Ev`EtY%S%`Mn4B +zyO(LbNo>LR5O;z3o+qb#SLCfPwIXWp*azeH9-%(Lw>vxO2tobb6i$SWr=<@q6f79A +zzKN*47HbgU2CKP3=OyKTM={nV=^Eap`x(;kEy4U+!a{!z98jljl)P^$Z4!gya-1X{ +zCeC3iIPx9{4!?_@wDH6gs)ZLXh!~G~ +z!qwD+ZC^uS5nV_cydi{Vd7Id97IUenWNQ4$#uH!TYPg@{A1%rr1xOd4yPlc|L7#PynoSfDdf86paJpCN!3ZLs_LW4X|*X2SlGk&H*Um5<(X=BKWQdaWP7Z(|2 +z$;}}?csT0@L^iK#Xb23jQY%4Y1*R&9XL@k# +zfac4VTuW3TJNN-%Ab2VygL!AjIeTjIc$)RB506AWVQ})HO+mlGxKl}~C6EJ!hh7+= +zV1oe9wBtT3Sc0o-DBmTgGH+Qao@O`)?NWZqqsF1?p7XI}XGWy{`Q>PJ-QdXDW06nF +zJbG0Bn!WkU^Cg29EHTn$OJO8P0ob5uUuH-1yx{e#YmWTxe!60%U#y9_rs(msv{Xbd +z=3!-Ur@j^)({l8vm +zIKJQf3wiT=_(0v#oZf-TxuaRou~@P~k!f2YDu4UY-zn_VB46|E +zJfHt3%VW9=8AEd2=LkNz&iz?NsYIj2%2RMa_I0nos}%f}@Yne|Ky~mt)u=q#lX*c& +zO`Zz!Hw><^RJX_-patukRMk7jo~&}Pcpuq&;VcJ2uI$$uSttY#5h>3@jlLvz^Cq+8 +z*s7~C`2(~g6r5wpseLNY8&GgrH{;IuwY;Ydo-(O~EIyH-eDu^;D@ad-F0#^DL1!^3 +zl+_3Q%sN4pJg%uX2=kto*Q16YSwgnY3wOuRDJk!FPB=d7$5mU(`deP<4^}xN`n^}3 +z`KrWY@UW0H3TOC61h(^M{9#HZNYso|b%=r>#JVOQ5#2RdBe`d#a4gv2Zp#DgECJ-K +zg=-}IIlLjE($~{;7_%E>Gj9}jo_Zio(=l^-?-x9vD*1XBMTx_=_Tf<>r +z{`)o_JNc9WpUZ9!*N1ve{EB10`=!p4F7qk&oxAnHypf=>xL%$1ourRf8(FD +zcPl@e;6l5rrW*I~=9@Wwh_0V5&mb<>7j=8h`AQ~nO;pnMSiFzf@BX|!qCXYFFCz5q +zdO1V#T0E5Ez$h%;-OhC4<5n)`X;76r^qJ+6)yYLIN||$-#cU-(7SrvZ3mst0&^QTG +zqUernQE?t&o_R}4?BWX{dXQIr8`K&hZk!tlk4o<&w67VWgCBKKt8BbS-*0&F=*0oZ +zMeAWt6UrzP5*QjLz)mm8FO2 +z2-I+s>v!$dYrYa7E2agr-qVXO-YBuK83*i;*^#MAZ(g>1(_9jobZ2fiUpUa0x-VaL +z59z*_C1ut*VuGweb4PpKJ?#4NE{u-bK~Dn>9HlY-+$7>)@d0qrim7PQs`%~~Wy@!> +zH+E{Me?_w29ad4tKj-mqpU4FM>UwmK9&`NqKi53TAD?^jsY~;nrodG>*?Zor|Fk2W +z&hy<%p^tS=i*;N$VQcs78H?J!6niPC7jMBoJ?B;N=p1_xh)++bH+);Dv24YtviCj^ +z=1I(m-RUl(QT$rFVWL7g8$-gz=cU~j_l?6If3MpM*dA%rej7WXt~~Pcs(v;~1td}? +zWj0du2Iv6Ii;l-!u2Y|v7KM&k9z8Sg!i_c5;c2nG)4ZLbE!+0=zs}C2+?eQnnir$k +z?bK2pLG8@r@RkqF(IEM{dSUCrD(86DA)V^K<`{21HR-wjUIwYZ2iM9v48|dY9zeqy +z4CG)tdT2@6*CG~uvlVvtKZIRLk|a3}`w}VcM=s+3pEM@VKE_xbX4<-~Dl@`e1ObTx +z%s>Y0Rl39L1@DueeN?0(Pk)@O15Qa4J~&SZdSs-L(4-U{0?XY`!c$3duTsW$B3s`^ +z7A3-*i4=GYv1FK@$X&I&FmiHgV^yL`&*l?~YF@9{m_t7ohK#tkKkNJ^#}bTqv;qQ8 +zZoU$t)H*Z(1IeiT05vNp?@S=dQK?JG%rH+s#jbrhjV7XpuGt0?yjC)K<$U+zzM-tb +zI&re(3#dL^$PzBX#oc-|7^4mFNeAmn`FwKrNv{!f+yS~^>|ciQh0LenT2HgNStGc( +zQ3LAT!`Cj$>&HV=@d~Z*FZenmBR`X3Z~1iJo^S*RzhRF}s{Mr}tW%yjJ&DQonN|n% +z1#T9#-HN{v8jo`(#_LF~dXuu!P(A?k=rMas<{Hz5sz-F>>ac8>PuIyicxIo-WDOCO +z@5E=140k-`>*lh>_H@~xnhe#e&|{B@R&wp0qzybjvFztQ|27}Kw~jS>A~xVR8z?ef +z=IJ2iK9x9qlFuEvr{T7d?W)&d(Q&xt@|mFUCar(B$OCk!(L%Y4SFUNDXf&1iG%404 +z+y3WWqs@DPqJi;jUtf{cYxcx_+{(JO`DT +zKqlT@Z1EmO$~bB>VPAELt7=ysk8C$$dV1^Xf-%;FaK#BdrX}cRs5o-UlE5 +zxRiR|JLtXZc$tCt!k&S%J&;%Km&W*TH6bc^>MI#~>KLZA_uC+j*QnWrAr5zm4T+zz +z^2_qsZ?qVmI4&jZ+wFu!mk@h*lTa}j)#HA5p`vNoCKSjVc%bzu5O0V=OdCm()#faZ +zQf?zbAwDPRA;-n2$g#Cn!xZ6CChj+07W5Ro&h^0F!hPI_uehw*sdPgHypC2qO2?jd-L$#i^`?YipI(|f +z)t-jJeO*ofJwCFnq8qZqRtopK)Z!txF8JYDf!8E}9ZKL99p%H6?)5tH%JNnMo^nl@ +z?Qjsz +zcXd^`^Xc_{9A!q4YoTg_&Ro!K!m;o2QapyVUgFAh&aE@P6bW`EY3Xn&yFDUamlK<< +zK-XHT92qs{aUAb^PTsP^PeJ5~egdIH1lnFPbm+~vqXw`t^d#R&#~$@NlH_c+D7!W#U*PExWw}cwtZB#d&l(w8*N^)y?0#8S-{>qR-A9cm%e~u=4bT_p +zUloTfK7XF~AhIEzHbklQx)$CjICRb^B0RVpmtrxOap5Os(jOiFdvTgV&;tA)=eaeq!1TpvucjRSoB@~;Lpk;&zI09U_=;)n#8jB-l0|A +z&46ziy=D#+k93_A8>t5jECP-~*lk-$!?b;>NZ9B)kPJCh>>=H=nQ%e>B49Hp?nW13 +zF5d6-$67n;exfhw*A#~QpWIj7*e4qIbaMC@z2?oMcb6vRR;AdriDs1WJO!7@VX2pk +zEp8v;Z`*XAco99X#Uj3HdZLNzt??LbHs+my)iWkwG0b3JviLu}cgAII#iTgqsx}ni +zkxN9Qw`=gS%FpP?u7?YQZ33)RO`5^r&Reua{sc77j9iVt*@P=(SX +z7HjoI+uc#ZHey8X<8|(V{me|`h~}qh^U2(digno`7??{HK1H4tFjoOsob+Mh>F?C+ +zX&9>@Dl4fGdzZ-jL~c>0 +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 +zO@=INa7J?2$Uv2ra}GbwBZAq9~Rt;c27!d +zpC>mv{c%YMkxut?+!9Uefa*90Nwc76=>l=-QQ~bUaI!tGz}3PNv4~`3KP%|)D{!di +z>LM{5MuE6-T9fO9KTIWp+jYL%Z%;ek`KDBSgdjFCzr0~lQ5?OFs+t^6U-DeTxR_jm +zk+(0@Jf57S9Opt=blKgzIm>rilbD+y0z;xLTw8~P;u%%FTrIx0CU%|yY)-1(C!<7wLu}ouPwx(Z0fnIs2%J)lklu=v1!I4_yt;_F +zl){aw(qazYB`xp98h7w;yJ_Hdu$zSG?zf0pI&2XW!v#X}suu5bpi5Lg-1$eIi;C*JR=D{Ov*A +z55E@ONI|1I;T)q~;geIP_cjuq$1{xEZM3ym?C9#bDRzg04%XF8K`qQY#PNEhr0jPc +z{(k0Dm2-3FT+f5w{I%nW-p6Bk$Hjqe6)BFii6=}fW0{pb#k^F*H`YnzHv>XmQ +zs@N8qbj076<{%-eyOEz^+jR9Ra^B26PS*qve|j82?kkN$p98{o^|+Ue5IEBGvp}8l +z=)}CI@;e>8D>K(y?ssA7grAnfKr#$EmE&9f9cPbCg`&zy7+q=f`7B%)zgwN~85w-$ +znR9ebGpSD6Wi-bo-egGHwj20G?m+K8bz~1m%y8z!QN5>?BZK$zf2}r5(MR$wq=^g< +zWScNlTs0PoOdgaudmZzJ#=RV;?>Ei65&R{H+^n;jc61`koh>dMHjml?pqtevUi+tN +zQ2g$jmCZcx3x9HSKIKgm{6&|WERUhh&1+ss^F+V9;em-Sgh3qZ#z=f79tA{+X4=%2 +z`Z(n9JP3S^Jllu}s2T9_8|*ZFL;-Sn7xwZu32~&DzVnHY`eNDa*woc~ywt3{Z6<5) +zlV|zZlHVS$i^UQ(qh5UCS{*4ZNH{aEr)S@7c~Ehs2do|WyZQyk?ko7y6!3ln!nMac +z>|xgXdF^}s&L(i*(+=O+?A`(@X(#6+u26?lA1QjgCuQ}OdeUlshr-%He=~|VSmWs` +zV#4tgv=;PKBKbL9^WTMHhygZ&#CqAGaK!iG1Eva{DmEn7TdO98@^@!8ZVIgArjS>|~=hJR^ +z)B~@P1>B@rb_qXGyz11p-*p(+3x0b|D~9g_&~gxhiN(Rgr}&^jV|bg(5!LyUSi~4c +zG37M7pC@=vckoC9fuXQmbdm&G~AH1s`Dap@joXo9^qN(cytT&*MNQIUwKh8z_t!|6yx +ztS^C{hiA{!lV~TQtaMD7OH6nKrX5#e3vI2*uO2>@&OF7S&RT6e`QGe3yz8I>($Y-w +z8eC=^==@Gy##2HeFETBgDtPLYqWX@E9TvI?2!%+&Xvgeo3!)Cr(}A80{RGmZJ92Lf +zuWV!%Dtl1`tW?Ypxs$R2n3PuwaPd6G2z*;?s+Hy;8AXHLw$I-pSz_ltEm#E0@A>mn +z+G_QknnHfTjjn8;-MuB{!|mwyCrGy3idE0fJV_D(#Hrj;3~NeXV3+%s9maa=J7n=4 +ztCL)4dC|P*V<=4zZ?V@k9tHI)PdVh|2ND2Pi9f;WkXi(cRuYWCkSdC5tff +z6YG9w7GFC)_jB-YQ32?0;_g8_o*oBYf~NOlpMpCW{VF|^z>a2Nz?G#v78i_Y%&r}^ +zMyq>l4yr)L;~$sKDu*6Z@<*LA3{G1o0UeDy$be6aQ}07lzS%DF&$+oL!I-Ih@oKWQ +z*oOn3D|W}#0QS1)WP@5y;~_%B)OZM6`nWgLUO0{momD)a)M|1199lK?k*AsWAl~yZ +ze|?!m4}PiIwiinL5e4$^Xa%V3aSG`C(y$IW*_oD^G{EbPFzf^AUv%*$tO@j=4d4|JWdNbTT=IPc&cLpu=rhkMZ0gE)==b) +zC&uqJdS8Gs@1rd4!Iu7dzSiFRG|&70IBz}3hO*E!v1IPh^r=S}{M2(G0ut{*fTH_^6v>2S?Or=boz8J)g@4j~ZV}vCzj# +zR!1-A$@_FKk1^N1@7I}8>Nn|1NR;>9X8T5++jSDt1}!0d_hkleV7P +z+?dzw#uFY7P=ZU>sO#Lqet)xgIuO23+^mfuJRylzHl(NAw&hXjz2RG?g;BOQ2FDbE +zhlXR*7CX0(oIPKf$Z6_i%0t0+?+lmwO=Y<9L4$Nb#zlPZsd1|ge_O**pxFWO$mGni +z5OY<%JovQI>vjiQ9%|U5g7z8c?sz{^2w4dt>$nK?F}A12-QzxPu&+Gs#g_jOb}dPI +z^dRg?fC0mj=lzeAa?kdw%IdGmpUm{b7E&9e)9Jo?jqcOh4Yf}$=u-9jpTE%VcgnFI +z{s{5h#NLzlLftFOBd9uHXaXDGryN7|&dYE2ea=00HY(|Av<5Uj$}7-kPU==)_bI=8 +z!CxJZoaWn~QI^>m;tImLYk-=5GT*{`O0?52oTj|?C2Rlx1lB%I{px1DXUSOc-tNIU +zJ^`g+Cd>?!QqjJ9+N!n7?DMH=H;);x+mY-APT}lVW=>1m1#MVdp@%|s1P*8dCMQ1G +zcJ5WZNl*kxj0dGofrRg6}7uP^Fm;ry&~N+Pj4A +zhhO!UE^2tYVdy-v;;E@aEr+#_U9HY@g&xMK@Zm9Qc`#{Aek&gOxl3Z6s~4ZZmpgX# +z>zta$#`LhLpSCZ#U;v`d?NP-`#|b26MYT}Tm*Hujw=3_xu~cwZ{mhYJGLOo3Eb)D% +zMu7OOQ>;J*YJ~bCY8tI8flqPrfcm8`=_9!uK#_JprgBMXpYb~sdbfK67kEE2UGa2b8^DQu$e=AGU-qcnC-MwB +zwevVG-FQrWz97h31F;n+tKx=VJ-U0YXzBN9U%I7~L@q!2SfN4a0(38kJxqS^<}4Af +zsL5=m$_kS8K|+3N!8#zgS=&JBQ`!5(3?{sFyoPu$WVc;EQr!d0OjoNcmB%>k-gp8W +z@3^?0JxUl~SnkMef9(1_OvmbP6u%Uo{>WN5la)n9-+@zpEt6R#4X>)gXFe*f%#Ez) +zluDBPnu5^ZxyYPIcYCDgo)f4BMc3izQM#ii%Hk|0U%2h|1b>j2%G#1WRB`ZD2ku8X3@gh)!4rt_8Z +zL9rt+b>p}jbf6#92R69pW5RD6^-V6;R94R$Uxdd~CZ3r$3kEJ1K%kJ|RpKQI4lx5@ +zzH6jbxYH=hj8?JonCV +z;TV{4T^Gr_aD)}%=@y~4l0lpc_*I6^#uVk8;`6l}k)^{ET#1hvCbPZbrLP#JN=43P +zDeTDcBh(;^Dw)%$&_(qwoZnVixQ&Chd@G%o)-O8vBWYm886)S4ZYQKpEXWW}0Bmgr~acerl-w(9+D;`@#{bP)$u1ga+)i`MjzeR$TyW#J0@%@>* +z_m(^2!AD(`+ZGofo!+yKf{1ee+(ly!zDpwzvH9XP24wdwO9WBYZ`!w{mOsXgb9SIw +zC&*yv+A;Gd3ifWkvd;$$+=gZ@29HmXSi?cIg{)VJOLc_y$YMm(x%O4Vu;{!32hRm* +zM$%JD+mnIOGLNs<)h;Edu9Ip!)lW&C^|-Ab#(Gk0zaa%l9NM#DP;r;hY!5xYafx!i +znSL8^raY*w@Eu0|LcHHe%3!ST*=p@_m2zI8a=B!8Bw!=5K+1F1yy|bpN3Di +zt+ch}1l%*+ooq+^G|2+MF;%yf=(!uwHUPIy+4 +z&XF&FOcFKRPmDiK$hP|pQQMRFppG&l7pd{wS0&j>j&^#GWUtx2b<3!B<}jtmr}7Nn +zw${%h;6{CZ{^FzCX^Crc6 +zxAbM(hUE(s1V-`NTCznclU<0$!1J`esG1@ +z{skyKRSukx_YTM0N43<|*n45u4-UN&n&7@)qr_+F7Z%GYXG`n!v5a$2EO1@aVXQGxexRQ^1HC?hV&iPTwxG`5aE%2RXO4euRiN?U +z?{o-05Wq$pK26&>msWjUuwmN??=maZBRCgucM(Vg#mMXP9%(k)BE4=o_L?HfTdB3xl)yme4J@HFCfpS+5G1XXc3?omcJ*V1(jbvKHdpDXw6rgpvGQl=eb0T +zOWb)$Sn~)4%zwY-QQ8XA3C7!=Mvs<8VG~Z?!s_Ku#M|ye(gi){!&P(;OD>_nyLYo* +zID3~ryDzF#-IMkJ+7b`=;drl%2=3QEcZ5E3-fMeaZJ)roN>LMXS+(BIv2SAhQlYll +zTe!IpaR~9k7DgCTGM?P^jYC^Fps=PE=K>!t_Z=}E>&H<0Ei=82ul&x_*@Vp=R}lE>)|0ta@9myAOmTn-(2`tMOZhUQDH&8ZV_ +zU1snl42i4qm$u2%29`Y8_k7mGdh}d+!i?^@2%~4yf?8CH-RKyd$DRO(xlEqiHi;-6 +zX25yUP~|3eb964OjU0Az +zH-B9IW>R1CD?snv-eQ%q_{h3BD1A+sfXaIBAP%k`#~ZwKK3Kl@u&x>8-|;gjLn9~= +z9=r!@nXf9vPG-{iivuESc=Nvr7`shf{{p$J?8Cfhx +zrgA3hoGiLaU&NC>)@4uIz-H=-p8rmcmAsNX?@magKO~R7>OOP63_k1o?lR#XBzF-? +zxxEy;LKr|;B~NcGC7(v?dr3FG>Bu6&RYT7w)%={Cp(*8)dI$9*g>kzu6FW{aEbRa( +zOYNh22N}jZGCr*{7a`uhfJ-3c80RS3jhKq|bKg%9)B9OK8q2^VYWF+macoH;jnI`4ft?;>1e(yu2qv~RyrUd~sRqaOi9u;R;uAGp5JRr+>-LOzM +zw3b>IgZ$xwXnm(ITx##lYTPnoyk}IYMmiDDHU+8X-ZQVjQElWpu#mbx-u-=RkW1nG +zSRYOoaLp5b=bKYVMpfg-7~Y0>l}mhXgR8Y2A!qxJ}WUG92Jo9_iMtuMeH0msd^HKY{gFxvTMVQj+G +zcPJKiWcC7vhVl$FtlL+DTUA{>6SC=h$DfE_BzCjb?{(R^*Gzc+s?*dK&^ +z&42sE6MZ@4_u-;ffw!Mw2b|Wk$RYRP_dfOgnG)SBxa&w&O5J$K5)P&LQ6@y2JxrPy +z_8Fzl(WmC(Ub#S`pyR_PDLTdtqmJ|x_N8d$O&dFkXnGhfZ`)B~kj^P?i$EG5V^I4X +zx;*d7JvEp@%3c9oxL2&Od1WXsg(yM+9p@qym~Fa`ta`WeCMa@9uaCpaw<^_JQJhkIlCiCOuqaqO+Y_aJIEIWE~a>mhc!saLA`iFM;u +z?mQh2xdjTl(Jpgcu5a7za2Fwi34$#HPo%cJ>XO3z>g0c&IFD(a#1P`8spECd=E3Sd +zp9g!(-Orf_c%y`$9uQup*{jDy^AZ7F_vS|rV`|}^wDgHOzOd@T!jh}dEmA`p$s*QM +zedqBWhO`^xr;i-x4&~rgP!}aU@AWM|B>Q65{TjxG_t$R$^Q5^5qB31+-a^!4u_tO> +z%G8~UZsetfk$EUq@s_I>0H|ViFC7t#IBI+N=0h32%&s-a9~zt@!6SeS?C)J@pr4K* +zD9-cNbi0!paz=#dIRyU1^p!{A7qiS^&5X1|e1L3~v9|XTolb&0oR3u}@Mke3#gDqb +z9aB<5j7=RAVKfd-52w{HZlg(`R7JmtPjyOhGG#o8VXwH2m=$D%VNfms-o$})&pHYl +zi%-8krBtJGiXguxy|8J(GikmdU%+LtxBHy>oVkdQD4(P|*{{M~DmhMxDx)CBGIhv% +z4um*gkkenj`LT%E#MAkB@a9{ND#@4IdAQb1k{I3vQ^no9bh^6jWZ0G7Qwm2OdROF^ +zp$cz_9a`)PsA{{OM-W{H*Rtx!!6=oZzc;cEt-nvZv@@#ALYb6&w +zKauZuA~ar+q4&=k3lmV3MN^L7&#M$w1)Evj#x4MLt$uySluwW@DYr+9V=r#c++_Sr +zqJiwYyUfFghaN4WiTF;5kOb|I^}(Ja2An{LB(*106wV&@<^Bsnr0!P~tNx39nu%6l +zjQNud{Mjd>fa3HuTF#U&zrjy_S-{`tRLzK +zEBe_VfNSKk_V+os&m+5Wjwo3%F76&MMibEzoUa2{kLS1LG?4vjZx`Uhs@3zb@zRNK +zk+*meb3vS0ZfKHO0-}l24K_vs^e27^?PD;CO#J +z4(Re~%naMRm8gU0+bA>oUes13_AxP`J2X1@)D=iR0qPTn<;zHjp6+{n7@7nuOD9S< +zB-+~ff&!DDv?ADt8TvRTz`T8zl*E~y +zmQQnKyuTlXo1+->nIo+~NvVp6X^&AtuU>rj8M=t-x7&*NVe5l-`@%7`;Lak~BkWs; +z>}!{Cwq`uH^)t)#ao55&u2a~VR$C)Zgcn7+Y<(X5Sf!ZycNcP3)=;i3C?uW0xDq)A +z2wQSYh@W&2;nT(|OIAG`A>e5NhlOZq71!p3+L`FXQv*C>te+E9Kknc82#9VDAU?wG +z&V4oKh$`?ycEoC6ggyyG-@R6uK;Nt98znU=7DkHw{DPG-O*?hFm8 +zi%SpdK;FB^Z5P{NKT&-9Lg1^f+4oopK8@S!?=2lDH9Hu$FI(O`MnK09Or_f0{2rMH +zA*%ka!0y=BIDdb2uH4@l(uoE=7;jl1&Rj8m1>hkOh+DN>{@fKF3$xF%F%YnHC1|7! +zuy31mxsYj~0he9K^aa@Fu7nd|hm5YEJoN91z9eVQoThVM(Z7Bl!HB1jO260v|Jo|$ +z`hCzJTeyz@cPbX#^Qy5NJVz3!Agnrs?7fBcSVbE?2l?@Czj%(B0zGD;;eO%fFhNYD +zoQL!kYE@dL@qQ{?2|??xk4gX*qG%v39QzzN;+%PG_o1*sJPANje1OA*3?8cRUrV!Z +zdA|kBk?o&}Z1OqqMVJuHHRhXVL$BT&Rqy^jMKSaA;RLs$;-N43fXv=II8`Bw4^dr- +z2i=rU3l)>Ul1}>=ka;XT?ymsh;x`*9j>kDMHIt|~Bj3zuK4BQSkBzbpm#f6Rdz440ujXtODpMlRP{=D0H{0y>38YIj3(}9R~8qsMw3{avh-*$m*MJS70NjmoR9W+sKv(3Q*r&X&slZwC$+IY8aS!9e6t=yGug80C +zqiIoaHCLkXo-1v*KHQm)5WeNNc#A)ifOjFQ{ml?_8pdf}ds;gq)5RW8?Tr382ygLG +zw<8x?O7V;AlaMc|+#EeDpAbCvD^J2tz`q5u{xvH!epY7ASAghaSoaEkEo8U%ag;;% +zv68enV5O(?y<``U_O{Wc8}B#bs7b0Gf4W85f1=;d6OP&=@0Im7R~BB-lQ_2>5}u;c +zM`u9Rz3(03d8Ewgy)C{2Uk8rdbu~P~9C(4%k=JLxKvfDlwKv#zgaU%=f#-pzeJ|ZK +z{Gz+fcW)IwS}%AH$Q@w3X*)OGPYZ3A5|RCXR}1o~L6`gv59mzG=^JAeihKN4XMV&L +zuRz>v(%OBBl%j4XCRzg!`&mXqlc>6IdYQiys(k+=t{V4gwY3GNxTlUWrlxEFTt_|4 +zW?09wrXqwb1nAs3YyGvTnu?HLiw-ZIq>&3so%Y~HIfEztt@(U<=0W&rv)M;D-!nZk +zHInB6rBlCWG*vDaIk2QK39yoB5I#@Gko~?_Re$H3@oDvj*4e2w%(yD{IG)!U%!Lsu +zIL4oq<~Jlr=QCC)Y60vi$i*eSpo^uk9NM*mbBU#I?&A*~`q`u3@9=z2 +zA)POWWcA~muusOqqHArqOrIJ>7KcIu +zoGP!n+z)?Jy5vgo6Ez#+p}jSFcpkI8RGE<_5g{jLrIMQpJrqv^2+z~y!a4WrWo8qZ%^tOrSRP;@kTl1)%Ob@fAvWjbRVs+mFt763xUg9m*3(>^LMk5l2sn} +zfL`HPPd>e$Wn|q{`ZCKd$9TPs@Br{@wQ{IP#;x<%Fjd1E@cjlq6Oa2wY-#IOt!mN& +zy?-f(%)M$b!p4YZoZUii9lykId&kYy*L%I@kOij)b_}XuenWLJI$9zPi{aT<{pVx +z>J>(xQsF*;4*1BE7s+JrW#@j+a(9|}q}A*T*phQ9y1}n$KhGDeh^NxqJ_SrAXe*f&s-I)k4D0zH(wXeYjm_!z^tJvBzI +z_uF=t_R>nA%gsP|(u2oUb>}k`d<^y;peq5(t{W(;-A1zPD#&52ezMu_1U|-j> +zUG@4xDV_j*)L`4B0R6LbGGaU5316PJoS>p{m|2=+^HettbIiwDedZ21pCd9%bcz_6 +zZn5_b^II-@US)bWaTyOW`=*|Y;knz9)`(9v0BS7mCvVi?eop3W;GZjE#+WW&-Mc#g +zln*8jBo}A`%tcyk;c?-XM|bUXAbp2$_oSO}vW#cZY`(&1boq3NGv%I3?aYVH^~nhi +z6@41vBQhaHG20qkqdU$;0b2H%hp>M!JWT3y9*}pTare1X!!xXKK5JSyxa$youHADm +zQZunKB5wdXZ$7fLrEHR)k*M+9!K&r)<)%w07DrRWS#aJHl00u0lXa$0T@|l8s7HXs +zt}C_OkWt7y#imx1MZk1E$EWlgd$GqO=PrXsLzD9(dQaf!StmnFptC%(=IQGwRkT$NPP1GmfXuLAb-AG>@OXo!`+($L>wx>k@q8 +z#+vvUFkyoatbb)y+~3L8S7&NnG`@qDwR?pOS$oduCH86q7(zR+D&w%QBo*E&4BNw? +zaOl8%=^e0$UmicH^<)qz=)tGdC~^bhU-$$0D@FBcbe*u)db=q!N$31!@#a#2 +z0dvd*UkKaB-2VFw(COkF&~t0#=wsVqAVzEB?KlwVu~;O*b5Mh$@&WzfzNwuenLTmt +zl8}y6z$-?d2^r{6Y^oe9B*}9e!W0J1IZv?yqwhWj$XTCnYxi9%0~*goyfmzq5F87e2y*glv&pLJPgLtY}Q8={i5VmO<&M@~t_nJ(~>X7>YZZ;N1e@?|G`3W#p6#y$v~PmI1A(fLSH +zlnjzQR*l&wvKY(5aJ8h)@pz<#^r_Gwn<3q|0x<4!c^(13oRbg{txqNT;qlqMcN&l8 +z+L!wzz?fcu3nHG0Zg(HEaKS?~9GpBOP&aNBpF?~c6&_pnZ1m_5cB6q4^hCcR1b9Bm +zR#1P#X;5+45TUJ0Izq~r(Cyu6ImLBwkN$cs0(v2jjM>F=PadRJ6nVe7vwW~*9pIMt +zx$Z^WpDms9;C-yW_cnZkvFcBRMaq5b7&!GQC1PjUlX1H5qT}E9MdkOxp&xf}Fb1%= +zKJk>Z<;q)yu^Be7II>2ALL$d)mCT|1>vfQehKCTgD#ggqLK`pNC*q0TmMBim#aDwL +zxxKB2-R>!~G0nEyU;`i)gmewc)KMx#e8h0-blsNRNH1YHs<_~6ybjiz)NZM=CVcj3 +ze4wI|hBQx;zE*M1Vy7dH(S`3;RYFq^h4$EK*;(HtNhFL2U=X +z4Tk}U){aLh^Rb&7qF_VF^->4 +z4RU^MrIN1z)$G@&CyNB<0EIW8(0km$oe1atzwhsl#jh-PUhTs)F=n+Un&*NW(I@S{ +z&enm8lkh5)e#0t)_cQbEp3ikEI1W*t8_mHpuVyO@?VJ#`r`YETA9@l)ITO2YNT5m) +z?-x5|QuPJV9m$3v)q`%m-#2SDIDKVCrZVv%aVWl*!-o=f>vQ^_j~4Zv!$*sbabw&_ +zyMJcc77})XxAoY;)-@X*gT^Nr~r4-aYF$3;hE`LhttfbW}r&si*+uQ`}Ic~nLo2pQ$J-0->3XgSBh4u{vdj-!!! +z__IO!LQ+`=I}C%{^W0YwzMf3Si2yvq#6{^Uu3vhMwg8j1+ktUne+2?;TVD;1&xerL +z&%01A#9YSP0~j|UL(Bm$WkqD3rg~3TjuCx2;w=kHN>-OW7DOpmuiS#bFy?dTiNx#X +z!5}A*U3eYvYxZ +zJv&sKl=WG`Q2~9q-kI`Mj>RNo?bZD**~-U-a>8y_>xQl{DxP_?SltE +z=Rq6G7s%siNKeYUJ?&Hp;A7vcOWo}C729K~t94Gyy%!A(L-1buazSHeL+C2wFBJTp +zo;{D8h1=&2Xla`DA<%Umey^qaNddsK*Jx@Q=UgN8yg8INp9H*LGw65dM)0(Jj+!jZ +zcjT^|wK>OjOuyXndH>l#H+vHBJC*gP4B>jbO@fde3ZO71DJ!XauPz9=9&fKlpZ|Lz +z+^gHRJn!`%OsF9#bYGw;^3T)P2q5p|0UZM>>!njkcxs=fIad$FThVgC)ts&53uwC+ +zl%8BKd%!^8woqA>_nfyjEa6B!&Y_h3>MI;-T9!_0Dreg~j8T+OQtDnxul@^)9B}{q +z;RG#q4WMkADWAr_bw0tVj)i=r=2E5JN6X+vXhpiOirko&}a>;fK&*5-oUoFbkh+S~Ss<}24q@MP^L +z^LWJa!JZIB;c5J4yi}?E71PB1vKT|Jk>{-@uq;oDlaJVsT*=LS8hf##?a(({GR-(5 +zNKbj;*PefI18QZj&pEGZ$e_>cisF0lbj4U7rrN~O+gB~?YuhTPeXGQMXP4|tO6w;- +zG|Bj!>S{r;M`Cdc4A&AHAK^TyU&8EV^-0)n){A_K{H-k`szOD?r!Fa=e4-hWOz(lC +zrn{V;$vwqoDME9uYqcZuiM3*3GQU^fznz%x`Zi&}tQVvNy?bf*x +zb)p_#Ue8BZ&uP09dE|jah%N+Ig*DKliMTE6#WI5zm$NQ4+FYB~eya0PvCoZzzHC4i +zbeGLK1a}Mez`HA-v7_tfVw|7f1b^pke_fZEp(0K*@O|p7N9HopA;GquwmS-R-{0Vl +zAU$wSi-V!qP4LWNZ%FoXBWWUguXb13>+R|FD{D*ju+gFJs~{W(3_HhHPiAZ~oc1BB +zI%ztsN-QHW5COcHVA_ +zrP*V#Z_%qwkjIwhI`}=4Dxf73Fq!oQxpX{>MQ~no7oKjNnVPl<3 +zYk9BdT*i7r`Vu{gBA?B86PA`wemTr+zAIuFy`loCj5;u8-^5fXRDDSR)C$<_2y*lD +zQ{}Fcl22^nfzalz2pqw+Mr +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 +zs7GzFzagCX%LA@H|fL +zTdtf47kL5HuOZ?1J>P`Kyrjq +z7sC=fR~`swz$3=+9)g=)LJ<2-S_BWI@>!Hfg%e$I+VSx{S(NcRMRz*{hes>#VR(Y2 +z!SouvSE30+WWU_8?00TBpHp(+;6WuW0K)!^Nx(?>%2-480iggQG&pX{6>s^a8zHCW +zL=@qxDIbYEYvm`KDZ!}x*4oFc!*%)CSc79tU1!jwXfOIDvReMlW{?EGWw +zN|J87S>%@J1w%x$|0PxETo1pB_j_Q6pMAR{1ep?K9xUx6Mnsal(J{(%23)M`Ua5a7 +zq>l7w!ACdm@oqLQKXOXlfR*(nXq@qQXq<{W^2(*fd*;y#IWMhqNhY~N@$xH>m7hO5`aVXA( +zs8t?Z)sGs4G5V`oeI>2VoajF2=2Gq4!o!n~b?FY-CV|`&r!>B)$j_Ec-b$T_(R4jo +z4;?;eu~-pF0-t6US-|7YU{H1DC9uc-UC13x&!{{4O$;6>zmCW+h4al|$lL09!gL=S +zw`!e4k@Jm=9E%5$>>S+;h=~419V9;CoDc@&jJk8|%PoCwpL&D>n-r6%t$mLj?DG*q +zeXKY0>)153zErookZ=G@0s55Zja +zJH?Ny)RC`!`4Jo9$HMQ!)C6&j5DZ`JJW`4=i^iX~9S?1Hn2=U{p$XIPM|tY_icu@! +z2&!A3a`Am@&#KX;m)-M|k&s<0NpXHF%x+NM7ZD5#3w~8HR`4*t-OG<-xhh_nCQsg` +zw_Q-0?so(&zIoe#9zK+*TmEN8{PPwi{qR89sWgs{*P1hc@5wYKY59CEVB*%mPc{bk +z#z}^Ya*||u&8#2~^+6V&o >h|Ulx7t70od`(W@nx*v>UN%a5$d6HY)cb1dpi_v5e${9%A${%d +z-(d5V2gy1WKHPL}L|(Xsb@upYq~DK@l|;fL-4N^Y&`O%{2mSPB*Nq9og2{yHfB>uS +zNbuk+DF#9O0 +zyXU3*d5ohJK&#gfr61y+q>D1NK4UjRD-UlU9dayA6lI8dbxo=5Tkq5b}4n4B*R|*tlBa|zU2K7 +z$w}+5&m!FXw6o|gJ~q*F>E*dHTfH9eF#W4j8q%%A5&Q^ +zt>L?T1De!?97fH@vwHrw~%v&DKf0>*?|hxB-Ra6yVGXs!e~ +zw2IW2+oLdrFDC9?{C;PQ#_lk_%d +zLh7I$dLLo$+4&FvKS030M@8`{z8I-<4jVS;H+0^Ta1IAym-scl$@qSBN#(1vDqY=H>)PBm-@VpGRrhd?T96k&Gb!wM2;IHKuhmkt=))*~E+Fm&}k0+5X +z*{urfF+!2JV+v9VF9|+g76M`ATd$6rA}F$H%S^z5ZyGGF`9okd>FasV!v~X|9W1Ty +zzf&2cobyla+}Z@^AvIBf2XY#==6G>l$44{`FoF48G|o%&XiJqW%;8%wf?r2NU9F)D +z^34UE?oWw1Zf$Q|sm-X~)$Z+4zM!ux>hwz#h}Zd!-%lJtUqVlB<~rnLiE|4d@JnIN +z5P?h5FGU1)M|u0Js+`aYySNBw?KIdGV~SPSnMh8NjfnhFQ7tUaZU>%IQ58$k)0?Ks8d)5Tn6`+@V +z)|O(ZKBr1OjGr{@WyxwEma?;ApNYbuxDP5ZIdh|&8hP>TuDayG)|@ie2G|KC3?;P( +zF6d=E^xf(}V9k2cL(s_NFhGrwW~{($%(EAGtM%lN9WQ$@&S(M6pab~juG#P_{@yFS +zvykfL?+rR`fK~0V$K##@3p&mk659Q>An&Mvo734%pL6N<0w*)asU-hcX^$pbqh~SC +zU=_R^Um|Gf=BV}A)8%hKnfUX>jC1}vOZ30p%pY!!L#0%gA6t=L@`}&A8L39SN@asB*x$rD1pp?&?~ldTZxp&%Xc4i=HoVp_nu!8c)`}VcV}< +z9(foG5*p=w_2|YI*rt8KUybdA>0acC@qa +zQ^^qb)Tf~~EyAI}o?4@TZM6?A-_TdPALvAwN`CP*Ef6Y`@K`n*^?=tRZmpbRNp7{J +z^YGnmqdoEyH@R3G>UXTa>8^GphXeI_`op#EK_Px$9u)-D_7;d9)xoQunp_wRrpTsB +zWnDa>**=duvu|cT#4^{#68#FLl6@W=1^M2z8wsEUE$|@($lBm +zJ~n9kWqy8so_jzMkzz9?aYKJU4ABlI~v7S#w~21v9fs(U0mqNhL1|mW~a*0wr=5 +zk+H!fwN#crirX?a$e&&dDc(nh>W(xo`eXBAbUB>!-m|1vIzH2kq2;RNI4C~%k$mYn +zeN$7M9;G~+-E}`N?X;5%U0^`fqc3%HojX9EaohA_psnKLP5zzGUU`YjisNJi*rkS} +z_W{cD3T`LDf@Hph7EL2IS!O#bByRBFuF;7I_pu9ou&D0_oFT*t<76jhrv7B1M4=fG +z{I97L|J(n3SdV{3ToKt)=jhif)z_SBU%6vD2bJm6N=d#Tjk*s2h})XQI-p0ZM8^9K +z>6D6ZU#LtSdKEkKhIY-BbW6+4V1GLzh!xKS`TH>5o1gWon!&8|XM2-Xx%p!7A#9b4 +ze98s|lHN8O1PeiS@qga7*xQo4Mnef4azBY`C9AQ=*)@SzzHE1cPPS~3Gp-m^+FS^Y +z+oc_FFMpB-!`)?d`{6Ic4#In?B&-8CgV5~eefZDr9h)GA-vMOW^a*s2Yv<5m_DN$~ +zmE0YTR;uhz58v{pCq)JMk*ocg@mXw%o}bzDD{}66^3p@uX#Q}H5#4F-O@fmT|Cj?| +zG|44bnOO#sWa;7U?_QZsEA7%^$`x3g&~v_vgZ1XzS$bf$V;&^hl`zv6z;Bl2297FxIg%e`3sId5g31&cXghe7o19c$gV +zTwtHA(1zD%BcoTe?ZWcZEbuuwgVE0MxowHKWW)EcPba?$x;uvtSt4!dcs1f}G#{w@#HO_%%(~PbK?nlNY!Z&Mb1T`r}a3 +zc2u)i=*CNnP#0q(U-@HX9pEE14qTn`joeNqyk|4<=WWa1j_D>-KvZ-vaDRmjUWdSaLQRVIg|s}y{oGb!Q= +z!CT#&k)-fqAW9Z@_)!9UjP-H3FDP&hgAs3I$g80@NapHkYbcs7ndAM>S>}t{*e`Eg +z(o0jV_T{$~JN(iRZ>Yv>?ISZMxKk{(A5YFc#G@b=>7K%CI=MGYP8aJpAm#d2GJ1Y@ +zf}bH5(b+>JwPOpGVYKX!^T4)P-y$L18SInqmwqaeB}4n@GrHe$KN0sZJ7Qt7c*5~-! +zuP^hQjCu^v$7f7{%CFIRSfQl%n^2+e*6ks*x1+m1595qTF?dCglb{Qsm&e{dr>p3r +zKJln5iD`H|RCeU@J$+uXG7D_pO$(9`r&n0f(9mV@;dwrVB=}x;q8@GEZdbpDmwQDQ +zbcJs@4otTC=X#VNdvH<$W&QntZ-CFOdM%1^tFHJ}@~`W8y=&_rWC>xDPdp5$--T53 +zC#rnP0k$r$<99sZ)^>Sby1tB$u+&NDO6iB?UnXH&IH&C3rw-V4Gtzp>7=3Tte7G-1 +z;O>F1rO>XQj?IpAj+%!9NnY8OxDG@?He6=XW*SP2#A!3(a4qiS!>osiI$+4Gb>AJ;9e4PD+cChu`q8HS!4g%I3@H)z$Ggr^iaRuuOPTO($(%WTk +z@q~6)mf_B0$?a23>wd4U#7SRNdBO0q)7OItdlOf*k5!}qk!Nt*akjdrc4$dcSFH#Q +zT$Jz?!ME}L^XH?#bK{@)E*dH~KXvtGI&F5fV=3%AH~;}MlI&yje&kivnRIqiBYt~b +zl=h}1Awv%jnl_>{CLMVAGER*bHB*MIKJ;q<_ev$1*M?6(n}l6RGmO;y>6d-}N5;}y +zR%gm5qu{fX5w(4kx*B6X5oiKY`C6?0>D!r$)vSktKUc-|SA#!I!{do%_;9!eRDa<> +z12+s1^2#95Hw+!5T`rlBe(LN+Gc2tm7aURCn;)(Ql<^Psy}Tw033ecDorrrw@52xA +z>aZzT6@GW5*ED!BRcSsc(?LC!ee%>2eBy~4Fu4IJr$uJbfU!9s1Uj{kymU<#SMrr^ +zGgcQ00yv%LoC{K@1-!>t@4TqON{7=}m(x4P3Ec_nmC7+X`rSXYljwVyT=^NExTB*H +zi^R(|XO#qAG3m>TSeOfR$ztK>H-F2g?Hk#@r(!)-AVs-w$~EuCd;{Y6O$2tCqT>vc +z1LggE;Zq$msT&X<=%YH^0w#tY)X)&0I0f&()UD(uU(*|)NuQqyjbUBz_cYy_OM>Qb +z!R&JGEk1-_LQ&@Xs2x~4oH)TeD$PZhWA_sR5{=zH*KgxoKeTOB1vhk+UCcc3KDr=B +z?%p`e+PA&r7%tx%Y(v1rru3;Q%eO-wlPQHOz#_+I-{zT^j=A9`Ao8|R&0A=ix-o8e +zN=EX|sVfnnpVA$_^vccglFA4@bXraCpAiO}JTf^Mx2d>I@;y7QIt915-AbdZ@UPwiG5dxj@HErdWB+Em>Oh@Rj<;(bM{+BW+?MI0ef$6gi{j{g +z)zLUEMo7isj*Q$I?r1i3BLJ3gMZTM8)?^gJC>=)x&CUflf-;Ar&(2-g;bJO0ndqKw +z&i_`!#_O3S-{mraKcKt3an9uWQa`2&!~rvS?&2|=y62%G_a?Sf7UfrhDNZ)-H};CB +z(UMCLawZ|D!-I0-I~P7D7)-T})*fdm1YC=zVa^vfDINm?r7x*Cr@pP(dX6^-8bjj| +z&>48O=Iuik5#NFP9p{$_kpOP=dPm%AWt!*O8o_*BX3Cy{ +zUhy!V)n&$Sk|^xnqe6I{Ofw&##scc#F_vS+iX1k2-MY*YUOmd8DL<3gc=Qt_rtC%E +zIG@>j58oID4`}x=hH%v1y$HL9W}Z3L{S63VEPyTs*Wu3{p_xn~eP8fS1LXBE{LWZp +zEn@NkuX9hbmk{5KmoxOCH +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 +zb6?|E*jXdca2jYO@73yykDzl0ci= +zUHocU+C?)?H>b$Ed#LB@cE-Zm(NL|u>at#@H<(2ODoP$Ey|7t$zKoQpw5O*h^Rf6Z +z>!%1ZCZh13cwglV)z!@P$AhkA9b$l&?@xRe`m2cOC6+|W~XGd5`P>Y#umlO +zQ;o*1z^f)hP;4|3y5I3!`N8R?evBL+^!wS3lf5^*(h1^l<$(fQor5j1U-LhpL9h!B +zP_Y1@1C&;0Hf&VCuOkwOz@HUITd6!;i0vfs*w}ql`vQ+I)aL`{Ykb{91fBNr)rNDS +zfpG4l>gVOoF}t@QKM59BYIMF1w&1Ec7}5@Km>iZHPSNAgda$*uVZn~(w))gwLY$;? +z9%?&~Hf}kJ;O&LQN^&DiTm`RTupTi+*s_TT);SfajUoewb*YN!T9?pevA3#3zVFZ=cD@v$q9+ +zvc;)-Ugh$d5D)UHAc$Blo1GumRxul=hjM15 +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 +z!|O;^B8CSA%_V?!xaE6Qjp~xn +ze6v*U?7c2uc=`9Pqk)b0u$C8lSkIu{dFGrfwB>G{?DHGRa;=WU +zcaLnU4pFj25J-}rr#nqdg(9P}#q4Q}$~tBZ?q5dO+mzG7id-c5xIKivtCt^ZE#B_E +z|2+9w42HyKQ;MM2XK)YB(X_|iUN)}KfgxF@db#8h6zt$0vg@>#XRR1ONHP3bxO}mBC7X_d&2h1 +zchkP-?Lq00l4K1fkU`nM7MM?Os<_E??r@p*vGZlmmisV25faaq+xaf@R3X_v#EPZM!2Et`{VWAZgzAAjO7N)Rx0{ixpC0|>bdg^xrHjmL0 +zyCgyAb$6^9`&#lh^S!9;#GSJ=keft5(GUCz!9= +zmyls0n+m!)Jr;FT(;Ey=rWoJ_xA1%)GS*8Dp6_b(mV7Vx!hF7=)u-MwOt|0R^NhX& +z7Tjt*hZQLiH9+j%gUh{!e?g55`BQ2Bp7wvrlb;!WJOAL!H +zn!2=ipHjHXzG+WvK-I}!8wi>pk3J#NgO5T8J$kxR9?i=cYGm{A)O}nrRHsjH3b(?X +z;QMvy+;4`3x_s55?*}e@^Sol8OJ6_BidQEWn2WD5>wRp__en2EhOz*&G8DsqCkuHX +z5^L+hxaE6}BNECUB||t6!7e`H-rDF63S +z3Tmcp$&)rdxh->Q>*jU2SohJVKhu681{_%U>b-fO`fb;5`umAd`KH|M*(drkpbfP4 +zysC-HegBC)dm`+r4m)8o_1^S3(L(N*@6!(6@0;oq=F$~>L+_cVh=sch;NW%yJOJeU +z`o4NEB`}zO$TZ#Rh<&8b09+%RyzDv6gZgBW_c^9dt)P!KXS@aYjwp0bVwwPD7m0CJ +z_QmJNua=hOQj45E_JyfEr3}XBW`HbI2cxrmp53Y_POPvvtmG^^B +zaBlUpbI)g}8J8L+W?yR#MuFpeJnLEOQmHzUEi`wiVF$`AshrB;JU@Bmfz;cYts!yf +z)TgXON^vZ+5b?zA_rM_GAP`jF5;&~ySIz7wJ^_Lp`TlI@&1cFFUTWDx*`znQ?~SW( +z(Ne$w#8z|!YkcpS+gHjtScAv$=E@bL+vnbUmewaF&iMKd9bSPjnI35o(mms>d;4K4ch)s`|8u5@cEfNzx}Ll)SrX1N5>3GO +z{8;blDx^dEMI}#eX}yQ4_gP6`>Su#zigU*i=6kb$AKeXG +zz3XKhD5$`DZcUr;*R5h-%AV=?EBEKq!EG`07|gakTo3Vtb0g8}uvtDY`)JmVg^!j( +zo?CuCeO+}1d;v9apXcaT@Q{9T+wsE*fViM$m;8of4ANj8lPCF)hFNTMhe31VHw)@B +zJdRpbnf!(4f7tMK1gx&uH;HHDL|ia*-OH}b{pvdo-n&c>r${*NzMU0PL5wY28aSdt +zZcX{5ed0ae%_ShlkcT~d#I_-Ym7#WhfXyL$>12m=-3!F9llcS-HYDdMw~8CvBuL^q +z*$cEbIP)bq#n&zJP5isYt7P2Jf1~2E)aC6#`kd$f_v6y&A+lMoY)8iE6TuIx-gCx(B$G&J^(^%T&PoqW)a +zARsp=V=nzf&Y!12O8SH|TBwJL1Ioi*)*Lu3uA)y|^<$p7*V8^c@?ye){bnbB<0{@W +zz$qM}nlq^^X~|1^RzVde4v@LwOtzNQiKCZHQXR`?M4kD0R3yCaU*dleDnZK8>}=^V +zC)vH&Q(p|XDsiMH;T&?q)8o)M&n$162O1L8_Zf~z(?8FJ6uj@y>fr{KI|tD(!SO+5 +z8P(%dosEp#681`FEr}GrgT@@gxGd>IX~({UvitQNn<4sMR<2DtGNSE6d!6IaKLUK$ +zisn7SF|-Re2La=xg$xqn`#c)o0PIIc9)OYF)qvN|H*@Ep&VJJ~tXjQpQNkQi*wk)O +zc5`Jo4R?W1-WP~oq6(fPN5XJc`9#ryfO2*`^LD_t#oqhuwnCG^P6d&jHSpVyGFre( +z=Gof~OQ6helG%MKYcE;MUXa6Z!=a09Q6}gu87^N-*W1AbRMx!YaMr_Z9V$@Fb4FgR +zx(uu)y-%l%MY~Ui2JlH1wzuJIVa4Exjyo$5C1`g-_OSD94w9=+gf&(GJvSuW&lfM; +zX)sd}DmwIZfr8$R>OD85SuHVS$&ob3K(aE_?q8xal$`Hnfn1+~KKQ`yVS$gFJOPs( +zSVMT~0s4chrytr&TY^h9B<0Y#aYx!on>)Z +z=Y8&5u|ixzQ+Unz;yR_(xnGx#yf4)v-ppFxaL}x-amec%_yohuH+3`;^D&a7a}kL~ +zU&-^$+-&Je*Qnt9#%ywK@_4M9)l@FUh~G*Fzy5FKxzeBqTC)kS-QZU*M0Q0WdYbA{ +zR6>Pg6IUuuRIQzauZ0*&!)26D+XNjuPTq8SK9Mx@DD)j1po88~qwc2Wa7o&CT`t}o1M`SLV+^;#Q;g-LBy-%y8c^Vzzg#fxIrUK97 +zqwf%Yi-IMmj-N9YIyav4fPvYOMqCYoX*a~cst~wyPVG0-oV4#e=(X=_5li9|leSV~ +z+%bMApQikq8 +z9v_E=2Y2zTi>yh!EnI`bYnAmrOz$)3XP2$zeYO0;m +z49j0UyHlqc=&QTx2Q_n>=pGft4aNJpELoj64Y=R^s3-9JdZavC54)XL@@R6!^Gb!=4kJ +zDa@w^%lwWAJ~WFZ!iYzUdaMT|p3@=nW6PQ~g2E@|PIYpTDqSM+#_ONi%2%!U%C)HB +zvT=J7#<6c~XZU~?eJQa}@97hOK^Q!+n?e0&@A;m*2M%o(3nXFZEiKX$8Q%d?CHc)u +zTcVZ3z}^3d41-J{eCGN`O%k0P0{4u5Fvoy%8O7`92G- +zQAz81p6AxZ6qNc#T-Qk4#4o3LC+$k^H{R2m)aZ-T-pHHR2;Sb^9e)Pz#_caM<=)3{ +z{EWi!`i6@qe}f#(W}rxe;DHe6Z@}YI!>24*7B}q_O%`HMV0Jf4L}t|!{yu&bu{e8xslvO)4Fow(uFyvfxfG=*3N*ucxN}_B(>Ado(uD| +zp@q#-9+6wLejsmMA78D<{khvFCIIlHrIWHgCI97@gCu-;T_ARzRxe3PNQuCNc@p#9 +zO?W@Vm-G_;<)1wJ$A-<{|3C-4_;vT6`QpAW#W4i@g`fWO +ztVqr}+BQJq1(dhwJooD+oi=AU!Qwev)PZidAJ!ZT1O%Jk5F7uvqr +zu}w@te1%)NEnuvZi2*>K_!V-SUK-J_t!b6>onjaG49r +zv*7U-nCP0cNHL;c2*szlA8b6>o^!t#H0C@xgO~cA@eQusMgxTlb8Ff15_L_%6`jNh +z5FdMBGvC|JFMk>YYRK4P36nj=4?%yoiZ>r@gvvRfIS2RX;SsxtqQ%@OYjwQt3T#cL +zpHl4grz8yh3Dj{bh?uMWHTZ3PQ6ErYl?%7JJzWQvcv4Sl*v@0$0nAuf+UX4&zj)M$bhx#xWuYXFe%DZ6Rcjtc3GgF*gU-z)jzDY1 +zPNDmxhw$8G!AQNARE`AV_q~K(Gk5MLA9fD;8x*)MS^DA*30e&7E +zg|fJ(eYc~lrry4f=?@-QysSU(P+GTc*`vs>RYQz7^nU%UHdFwc`Is7ys*a%kP21Bw +zpF2Bs>`

XRymFBV3vSc1UQMqf`wiwHYEE3meE@vFHV?FJGX)bEQlxje7t$S*|`c +zB8wsjo#vvu_wuzOja%UP4bgY2eH8&`<=8)iJ-T`8`kurV0{j9?JYdcHVR;;9&%UB+ +zmpNU8jwn3|`T#_tH_t-^_r6|zDm!tNDBli*dPR4Gh4H%<7QH-ovv%m4`$_JSaeO;V +zG6wDBHNC)XdT@4e&8pHw&ps~Z?^R;kO@G+@2+h)*YrdKFr%bNWjmFt91pdZK%Ff)U +z<7%H8$R|P>FE^gk9v9?Zpt(pyX~l{JF)@J`fv%( +z_;X+o97h_4R~E3RA8eJ85AR#vYv*ZXwchfHI8~!Yb6V(qeQCTwtiB0h$hjA{2&peB +zO&i=V;6{+ECDkZh(%Hh|t;Ec8Md{JZeMUzoS)>--oGx5yTQZjiyO6S-N;ds$hPph< +zepJ8XUpik>&5@(m?^E>WplYn1rx#c2bBxy3M^EeCX+hhG@|nPI)Wn>xLsFL}zp$xT +z<;rXJz9r^8-(;oxu-x!_Xh)L8Qf?J|WA&=Ak)LS3SNo3g1lL2ako}Z>b9D`4EA{V683`MtsZ^ILGSgUF1Oo +z$1i*BfUrM&`07}%Yr-Hz4+*dY +zOfQp)&}hZ%oM#T=UXoze2Q6`z+6B97MM5=Fya(TZyW1$Jo^J!3<4ktI3i#fH-yr() +z1PSIu!hrBSo&eQPZQX37iYMAqxKc(0MvF;~LebbAd7f$?(LDuokWFOayH|hJrR9Cd +zM8>OrVkz*|q2uGwdAKSwEgYEmejyU+=B}=u=n-SbZ(y|Eu*nO4PS#mzlq`RcPs;qB +zkM^k(_Lg&oZ4fORnW=!!H(Dw~qU53B(YG}u9rT}PNju0ME?>lV_tlPiszv1z@ssJw +zdM=!!-&9%vIgc`|p%-VdW8SXVRW=j5%kC_J&fgTT_^wv4aZTAA1q-X&DB`?|8?R)Z +zcg#>e@m;@kepQaGI26VqY{B^rYiG{;^&2*P;}BJ!HW!oWZ)B#X?nRyI+ioMg!>&## +zyLT?XE%#;91YfeyCt1p5L$uiyp9o?s75&CH;+w+#_Bre>$no6^TexBm#PZtHA;2?ERqBNqtZDcGdM+ +znPFT%M0@)YS%fedA8#9(K18&1Sm!)z=E-WL1Mk}aML@d0#q%Oi7x@-NFoOc=tNH5* +z>i!=8v{wj!m~`gV9!V!13wfH@zJwBQsTtT4=$c%SLipsGggo7L-_EM+Io}{wLhiib +zhGp1{{y=yid>y!~`8Amzs5#e+&edMKCealzz~h6~Fm>f#`+C|0b%pTDPJU98i?1L! +z5Np_;xaiMb&B=q%uadjd5tF{V5MO`b*@OG_B}@C|JCj>x`1b!i!Q(5S1z>~?i{SUL +z@6?z4BwI|dkF{2g+wK@yrF)*4$uYbWsRU-PioC5Iq>N?D53}7B+^x=MJ=*4++wq;k +z$X(Mr`CE&k{??+jB`(R}I(m+doUPun#wxth_X{)cE6>=S({#|EMkq2PxXxVjWs@~s +z{kqPQ^*e7q9W>uTEC9lD@8$QNzYa3p*j~aulk(r +zVUEl2_Ual%v2NIRXPC#BM8*oDBz>L>&zf(diSndiqVn5@d(fh`-JVAHu9Lgb +z6<~_^yWRu1-*zKr`^K;12=aZ(`}ryirze8WX9;jvVG1ySc+n0b)FsOV52WrfAKmvz +zlh+C#p5mPO?jVmg7dk&+4$UDmIk7>T4~F-CN36rc{fxCH43bw$$0IHdaZwLGUI;Fe +z0wq{&2SE}8DbHRob-v%Q0Ce@ZkN(%TJIa#!k&Q5f&8;Z&LlsvEaP0wjbc45@a}-Um +zCjE*(aXr)gjAEmgGG%E)Ov7QinyPJRW7nS}#bsJk;IY3HM?EqppE9a|O|rRyH&>N1 +z-D6IiQn%+pf)0dhC25#I9oyKbEk3{qz50EJLWSsjPwlanD5Bb +zEuk$%bP`yRZ*I@p7$MxAny~Dx6jw1b|5VefpDfzg+W7XWXhC)oOW)( +zyC^o{Vs%-pJ|7Y$`E`K{g~v%-UR0cuuY^}K6-_y#-zMX8U&4@2TkDj6EzOYAq +zp8j+)F|np^fROYPFSOs;*>}C=k}-&&Q9#Ae6*^q?P2B#1UN};94{$9gVYRTRtmG~$ +z_IWU!&CpBsc=+5y0+?(H6W#J0r?!szIkr5&@^IQS_O#KBQIkzI5`+Az<-o8%YbEq#ZZue5fZ4Z^f?(yT%=*OMh}Ogjn8EezXTO%N +z)1yv>`{WHj!xi$B(T=0p{jLz9yQ}sNSsd8L%?XcZ-F$BLUOX}!5B=%zdf&)7xrzID +zl}_m64t+v~?swpv+0qMRUk8B(i+sVrr@4i!NQ`o95pi(85hTEA)C_N_DOSO~v$vId +zP0T%m0w_rB!knE7Ex6+z&1e05+3s{@Ft%~L4oBunBNjyheM!aOlN +zr#7&ykLN;i;!h|&KaZFYIt4tbx+34>eP8XI95zG^@=3I(c?L71Ln!=H4Ds5i@YrpmX7Sfs7(WD^=l3MaVS%Gz87nlNZ#qnh8@n4XLB1 +zp|n-t$U}o~_VtqH8SNg)#^VO{#aL2aI)En|&LLwl{xX78u3b#1g&W4c9REISqVEP` +z?kP!mP9=%?80Pd6tYw{cl-l52f0m_GbBU{) +zm_+0UX*bXN$`5d2)+hR4aI?8qnu=(XqW3_2Nu>CsBLgU+XFm&H`y^d~SJSj(@(3{? +zJ-RHHbMs_z=|up9?;^?3A&L|sF2BCtFk-% +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 +z-Ei~RBsM7_ +zng1BOlI%!w*m@<*0GGsc|0DS^)ZV3Ed0X9*GK1tFg1`ryHqyPfgEZ@b&q*ySf(E*e +zC$~x?HJf)7{2Lca#>=3>fkzPvDT{chJD=6ThWMKGIx$(5k=giC&+|ud5J(5bKilg9 +zShdeQ25K&soPXZ$t9N^^i-N3D17v_7V_X%wpBRO9e;+7!R=St_-1mcZ +zX;7YbUNcO7-h3Fcnp+YPZq%gd;1gVZ@M|}d*j>bGz_oj#00Ekqc$J2UhiT4^=a=d( +zh%@tCg98%v)!eDbL*s<_vgXmqXfB#bW$$dQ=-1hG11I^ +zKx8CMGl^r=2^PQuGWj;Z_bz*0Y6 +zxsX971eBLb7>d8B-}A-tDLpGC^1kxTy{A-<7Wg;8d77;vy_%NJ-g}Vdxu3>T9BL@r +z_n9`U`#C}W^82?`3dYLzyUYTP$2ha|Xn-ceD>sBVcNVa0^Us;{ +zygG0B-or%RYwO&C?5e7`HjkA+eS4+e7suq}YtJ=Zbmnt|^*ZMgJ|W7pl9U^#@&Wl1C-!55uL3^IOy2^o@M$w&-4h4;MxMd(!P^k)>Xk4&WgSl^w%lh~ +z#OC2AxHSuHFXTw&Ltl%%t95wq=9R$b&inVJl>fYxa-Rv1Jj-D5J$A|S?d*|41g89Sel&4eZ +z`skNq!SPPDH8Ll8&_NgU;e*PWI+%)2NIlCq(gLJAC%VG(6dIA?gEVdgI%6^H)Z=&p +zIMnMZfq8Y`+ehOlRuWiL{WC$&%HZhpNpa0Mt)D8H$47SR#t!#=+Sz(dj~&uh^_@QN +zGs8gv@2?exfWFRHnvt?w#}nL*WN(qK4f4v9T*p%2O0Vl0R;v>B2`c+57!oS<`}}U% +zSLmn|`8?u2OrP`g=9#SeGS}8_H%w6815(aU1J*gW_A3Ov3ld&4DwUUAIqhnr)ItepQj=)WqS|q2{F0YgyZM*_fGif^#Jb~ +zd-6ZYAARP~2|6bmDg6d)@|RUT)_CjvCgJdNRb}d09_#(;Z66JIorkf7)$@%uuUVsR +z3+sC@lM)w+{bY8Xy-e4hS&ej`n1obN@CQPB{e9La7Rd6HdWYak}i|knm>Kl7m@-pYH05mRar129W>huhohI$l$(>>pmr48NF>~R39@v1iE +zlTOeXbS5RF0cKM;^v0P$=rNg=R5%=?6 +z7WB;4`SQ5MWWEXjYwL~O%aB+PAUULbguX;3?sInE5i|}cEll%R7b^9H`brDrY@0Gb +zFS4A|9Yga^z#IL^tq&;uo}O|DET)DbyoZ9 +zCp+AzCftsJO_yfj#)S02Kw5%ndh)?@)|qno8qCVWDt49(&5CMq^ngY9;yCGGYCNJc +z_dEuKvHlJgFZuEN%<&O0MG89atFUK&Gf|FxgKum*;-Sn}n1CmR3HA1O8;s9_i~>`G +zDKQODA-TY5nidqx^NhaRcct}g_>t3`u+w$}ls5lak6J}fa>&ev_^G}VYBu>c0Y3jJ +z;OA)WIp@yt=}|HZ>|#0ajYbO*YJ$Fpkfa6zH6jD$;GKuab?-uxPtcWw!RND*IGCAY +zF{AI3I&mS~?1r(!-jKNdHD5(1*KULQ*C+Yl8)k{lm(9V2suFvG&jA8?%4S5el#0*Z +zF6@39@{4TevqVsr0nAVZdVRXj{Zd%;vH!_;IL69j;6$?Q(K1C%m!21XDYK-%OCF&f+SdJ&E89-{_<+9GUN)XDi-5@3&zy +z-nQZs?Rk5Uu<^v%E9%V8^v`j1hszh>0moY|FoYoc!Xj9D05wS|CKr0Spney}EU+y0`JV8gr#qi`zqt|VMMO0&i%cq(TyTRA8wzhG5gpiRUDBueq +z>+DxQ8SeAd2? +z-#f8!`C5|MQ*UO%SOhfqq~@2dPvRctR_h7t%5nbj6NvF#Gp7}Y-K-jyQd1MO_0H+iB1 +z_IH0&{Jf}2raqdG=ia6pPjinoe6wl{AQUt^zS2{9oBg73>ZRMGy79FO7DvFWf&(-s +z=?GQ9UC{4+aE^|u=A%O&koMdY$VTJ=<&1pssO)p+X*1Nkj_Y5|2m14W5|qsszQ{GA +zl&>VY0ae74S;4y%mTwA)m-d_+H~V>>o|+3^rLTWB*dMn>PO_WJ^H1}*59FVd?8whO +zS{a^Ly|i)Tir0G@(3jnwXqH=Qx3keZyO +zXmP$|#7jHm3v9Vb@l@`yZ+O+*89y7gRHL)sTf(&H3(0R$H{!A{wmm=AD^p_%da~u_ +z9=ts7V9>?YIbZP7V-jwt7~Rr>3UEB8L|BrK+s9jEi{8V7x;gxgqfsax{R(R9%$e{4 +zy9u?C@x(;oGt#ByFqiZ=?=)K<5IUujsE#g|G?5u?(sd6 +z&QsnI?+HV~9tJVoe3A$QtQ>^FpLYlf{@xRC+V`fe8LusVqc2+UDXBU*dG#FDokY4g +z?hVTWx&a}SD9f_sxBH0Ca9tXGhzl5-QI~wTu}FwqovO%vomg2bFCg=C(uDrpAeozl +zV&HwC-C2wkXtL-b{u5fy&nqhsK^T5Kdc`#)1#Cf|@xOL+Tt@op$+Qifrx_7&nRe4Rd`!KnGxPtCm#**DK2dFeSc +z=Q2P*yYSBePJXF(z>@D?m6RhWpP@YU{OW90d*bcK_2H4_N4Atr2}!g5kq9Sft`INGF{Z_vGESf%Q6Xjk`tq6Sl`JLV%8x +zCZ7_Bd-1ClewJ7+@dLxgFVO)GU;A1!uJU<^ded0y7DZ{vvYl2V(7wYeiDk1w3Wsj3j504QTuBz +zj$;t3Fb9RvC;KjvX4Q?aqS%*XW+%>x?{z{VRN+I}xs6*AoBNeV(1itilJQileb+Fl +z%Z>;n)pO{b-oSL1gi4Q?RYHcnn6!wimx>j?vj3WzM^}Q +zA^D)=VC}L>o+W72$KGr22TJVl_L7`cii+nS$)9uExxgFu=rVSJ`bn&O2${r5Zli{A +z1l=IZiIbX_ook8yO +ztJQ>i=4{Eqb~H4}yw&CKmhgETZ9x=%yA0Hd1*-SBd&JtHH)4D(DrBL$hsi;l8n-d> +zj87ot9R#1J?Z?5G9|quB?Z^;m-Q*;u1A70$eivef;$YrG)X$Ih-AUK=vf~Ps<{daUO8&~JH0QjSg>3>M-TJ8-5Z*E*1lmj?y0vqvYzWS0zVy1 +zL|%E4Yj|qn^nr57b71|+ZY{oQdR#;-Ra%%LZdVQE=8c0gDJQz@9g2%~KBx9r>DF3k +zSAM-9P|vjS!otlX&1XTcoz~udCU^x-kJ~=Rgl|CnH)J)bSDt#2DGJerg2tn#(-_`X +z9DzDwE5*s=e!(=v>kLop^iP6X@YZ#_4*hoNOvc)5TC%)S3nn$9G2ic~10{lPTwmaoW-Btw9MZ +zXZI2WCMk&fXrMtHp)Q$E=%p$g^xK!s3)b`&Ux#}ih6;N;Xl4R3w5OLF +z^GSFqJP`Lii#T$mc;fOm8eF=B8_yi3n1*LO1?LIl%z*5k#oVV0wR^4_kn$ISXW&DF +z6cW%g1i^Pz%6yJv)sre5Z_`RbW>W`H+1{^;m5h!aP4q{Fe1~A2ll2>(+N{nl(mA-g@?spsKj|lxy +z)()OH4agx@dqUBq;L-JA7{hNu>Q~DS7RSY)_u>g}Np0t}sGn1q5%K3W)?S-wlCR>| +zE)hYXSmL?LR5W$+J_tLDZym<>Z5lr3N{ryGqWdTj&LKBC#_v%aBYnVM3Ga*HJ`rcl&Bu9mC-=y1U&ZEZ8PW<$ +zI-0l3Hx{w3hj(3&FS0@D`XRELc|_NaGhJ+WWXnYH3`VSQe3j%HV_&`KN|5M*0>^WL +zsx#Su#I(M7RMk>XwYE)O)31Mk;#RY_*|Bd@?y+O1pKAcxwb{Zn61b`AOh`{@NS!9; +zU3q@!@H`7Z+P98yH|DuU@)rJ9;|+|ab-8&?QUosqKOAUjfaiV(4#}))xw0L!=S1nI +z?7gvgCc5T$!Dkg5b^+0g>GCQ-(f4Zowkh_~a8ayIm_M8S^&>YZ92eCmY@QjyOqU=C +zzY0OmOZ{vRK>FQpl__^IAB4UqUc+_w9vYc+u8C`_Us$&~vj{x1H}Ahrx=pvfkZzeNEsgHv%BuqGX-91<>lAT}E3>_Q51FhD~9o>VFng;A19LKq^k8lx9 +zGwVO2|Fkme@Jg +z4&Kh8*dRy5O=K^OC#H|=phDs*ia_9PJ;-}7sOJF)eQ9DxxLH@}s$y{>&`^A`0{xIX-K +zg)199BZ=Qj2ggs|-$t3`1faZYOx|*p4)>#{_?ml=jvRCC#n5#4`o`)J=u#ZaOzEfya$Q?rqE)=NuP@IjJ9)km>ysty_03GoJ3ZEgNt-7#ukaSY?G*0;UOSbou|pzeH%?za_<6-H +z)d1KD<8#6vYdB@n3ATFxlUMeMnBN+feqL=6+BZK4qsj<`=fJ^h;`I(;A2r0QggekC +z6N<6;w_b8~&}%{yZ6{|u_sL-w}Q +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 +zU*-xmcAbJ%JrB +z*`;Wdrc?z_#puB~wvs7u)p0P1p7XnwY5m31U4N?LZFX#$MD2lQ4b4KSeoS7&_bYLT +zPu*-#>f&90TgdM@>F0YL9Q6c?6D)s%lk&p-X4pJZoMAL?8K=(y(NUwLz-{sb4j#+H +zGLB^|q_-U~2*%H|Bt+2n?IgPQ?q(?Y;R&L&^TfaW1!pjeWM-L_;-U1#oA%|y{l$J( +zee{DOSRg_%{mi^%()!#JXu#8g!28^V5d+HZ@oJ{NTsBx$L~|o^IW3gkh@^J>b +z$AsnP(gFQ_8D>8(!>Zgvt{kN6_bc->f_sxr-f(dLrr-q|+wD5bT}M`NdLMNV8qR+E +z0xw)Tq3S2_%ciTbFX%FRJ*aS&0Q&vrcgFfzHVr!_(>J~5~$AZ^&)BV9USr3TnLrdOBhpzC<>Rqy>;8pm(l)a_^9&%!1Lg{S

FTjCk4EfUM +z=vyXRQ-g}%=~5{L8$rv{$OrhFadYU)s2jH7(lE+9`%D1O18^iYk74?L*&TSIjFp&L +zb5w3Q;kN4zqJ8P@g3l~K6Q3R=Fcrr;W3|Vj(k?8}?VfiscXs#SSkXw(+>=GBn*ddV +zJ5j@ZpFv0pw|LI5Xf}8S;Qg+e&?gc1%O7F&GX|$eVzH*V!tR;NKw{K$E_uR|qMz8u +zVwFT=U$X@+^xJ5N6K^jFUnbWiNt3rzzBlr_H)&4A(+qvla;ywC4Zi_S6Y0-l(4}5V +z(0smO?tF=jT{m$Ksc1s-H;{?+32#3@*zH|(B>TafYoW^pSz2>F7=i-<3{m=xFNwzd +z`~f|%DGsr7L}mro@S4<Ei3E9v7&b)Sng*_G#Z9$!G- +z1ipKS>3gd{kAWXTNw9(z%Tmy@3&wd?4qiSD6sKHAQE7bYw!l&o3c?E%p7Gw!*!^wHGG#kVJvc+i^#+nKl+Xs$zW +zICblUgW8c>-IuNPV#fK(+imI^f>e-2C{sm#Y5I`*2tcNE=Lwc+{&+k*#}R~|0MdyW +z1kDn9|3kYZj_L`?#e%bA7xyB6GrVl?+-bXX@hDs*{I|Z{PN|%YP$hAMJ+_z<2hRDz +z+n+;P%6i1fY1i;%1@7tGeG7QY;ACrG*z0$1!I)^2Vu+SePr`^=csS#gGjX#YhY-I^8BzlxPdi(sfsKj4ve*Pp9v4W +z6+w99DZYHHNuLj$kpM1brh-(q?bWB#89INY6dly#DwbfM{ +zlu3og=D&srhEta)V7eYnA9lX$O*^2KxEL!sua+#NuGAzk8s?(b`+t}bOi|~3b +z96XhKylFTV@Yapw6D)*vpUL*fE2#Gy0uNu09v=+!Z@LmHb45GMv*G*Q=~aJkh|V`A +zcLV5)LyDqj;@R2o*uIT)O_L#lwZhILCol|CVdY?Qy6$|u+qRg#n3O@k$%20CbU(i{ +zE+s$13^9IRkfkZ|mSHl~=GACvpMX8mDEcr1o^_4CH*sSD5nT@gkDk2nZD0-kJpE0$ +zQ&4XSB!qQRY5Lrh%o@LXbIea2zw`V)>qHekaRTPu%uo&^W4L8tMZK=S(!1l +zog(%fnaR9+32dHv&W0JeSLajR>1lENy-@$w(QsBLURitcK##(hcI5Q{xIk5|fV_v8Yq0 +z&yBD;@Qxj0`q4R$fb~i#8B_Z=vs%?Gp0rdc=t44?IdO)x8|J#-#{*d|a}nN22CQ>V +zL5^|1-P_CDX(X!xlPkt0`3)>UwuyuFwPUl7-G1tt3Svi*z7hU>s@Rq7GRbl%JcA%E +z%g81^rkhJ|p#!987F7<_z?l$1zGC{|zwU!FS=6On-qqY|_Y}uh6zBRNUo}Bl&JBPXys>SE +z57_BdD1`U@W+?oejf>wL0iym~!yZSjHCDxsXz# +z*AMd}RbjgKLHgZ&XHkvX$=9FP1cUQzA{?h;eJp>Qyl-E-B=erfsl>@M;!l6OmFBt} +zIM^%S(Die6?RE|(&{5FL+wp)?VX|w#&Zxt_c>|ueyyw)F1MvM)uHt*N_NFfsZPNf7 +z`m&$x&A12Ue+avlBuR3Xc_qY4u;h9FBmJhx|J&7A+ib?Vt1B}U0^B8VXS~8aiUxB1 +z#)CZ_@2_vDKZa7{T|y8(Wp(+C`KthOusEU+OqBhRt8)(}d%A@8;*ssXybiiH5jPJ7 +zOawFawO~V1j!ZMM^LNVi|F|l1eyDGydzcwjnhUtUgV3`}LtMFv*s;WC=aE}|`0*k1 +zJ$n`U0dChxzwOrY9n+${)X4oR1M(uI@b>MM(+^(KebFoW7#_c*mn%p66%NCUa7RDz +zphX?a3rlP2hFAC1bsl)=Obd(r(UTcJK)mY&1Y*f3kBzQr8PepDT(&cs_oavc#AD); +zq+(-9pOjMzusxV7+ki#)@w`j_)ayE+pnhE+c7Jc~_zp$POF^F_4~{(wqW0NEMp9ng +zduooJiGGFHyg!2h_&T>Rl49wThis-e_$V9G&&Kq6umrnsTq%)X}2H~t}~A? +zo7&)QtE^6k&V5`@4?MyHLf4N^-8z0=1hEZh-!{*ol`<oR5CLJEh-V +zm>|4mINyC`p0?4EW2}OpTrpUBF46r2U9-qDByrmBlUa{`}U0@DIL;(p;e42PIRL~@-)3yc3nO3b=BGF-IT5CG|1bW=FQU{GM +zO*zkqzdt5BBfvU48>vA>qNf$NKL +z5|cvkks@b9yb~zrOf{3eZ~G1DfN2Tu@dK>c=Nit8E6R0+hdn9(Ou7hvUYb2daqyZ0 +z0qUym^rykgFEHn%m^4sH$^XyO=|j8kk+R9_RvLU;Fi~&9En-zvW^bsHgl>Fg?d%;c +zV)o!1cQ5h-sbsXwT>6QKk^cbkZ%@Zxu25%3zuiQI$?a=*nku@4)=dL|eQVXN7 +zkoY17vi(!`K-DpN~lO9#4uDRBp +zs&riL9soi>y}z~3rmVhuA(raUbUf!%fSrflKG`%ibLjp2g&$L>+4wE{RMbf>a>H*{ +zC(j*2jj%5YL2o%c<~*$1j^=(*^{vCFOT2;-19$>46poSS#7+aOK0dC9v?bvC>Zd|D?C} +zQ-W5cF*~zy*X4E|=Z~u6M2y>lqt8;W5{=$V(4cH|FC2d#*5}qOH?jzU7iihZS@H_K +zd9%=5^{a0Su}Nf7e((kW6+jvkqL*SAVIm3im68Wig+ghLv2QCElJ^kYGnr +zB3($5N49&Ga^eQ*6}WqRc_6eK=(AUXLX*9EiY=(AeDj{OUGyhJze_o%xbR?CIwQ*e)zkyh%R@Z=AwU3K@k|(>Mb7`!7 +zbsZeRNA(_Q9lv%Tn(*0lu$$+?)KY|LV{^Z^@}g(H*;QUrX}y|M>4Q1t$F^PjEq~7# +zUA*Ptl&|UsCceVj8ISa;u!bE0y<7KdBKc0t*xCBXotw~x+UJ2kJ4iPpFMZOR+Y#J? +z=Q6LGb?WxpZm(2qSI~R@S5v;YJ33yL8T?O^ngvdjv$iLE$L{!ALbiqS5!G|~a~rFFtev{(#H_sfu%_i}||Cj%3}Vb+aB>Zm2%A=SH$M +zQCV(;-bjt6PtQ_2Ekp8r>Jpk`=T&f~>(qSfG|b#A7b-hA$F7jP9pZ@YSHU~`1tIlOU}J7UE@L%?m?po +zJD>Roffx3H<{@m(n?-HL#u-V<4S8Q#T~U5ar1BGC8=xDi#2zRd4|?0$sk)orJlNIt +zfU~aTJQM)TK(Dai)WS=JX(2Z-L;)h{#C}HO(yWYof^JX6TO^phj|AOlRm23*Bzy!;DS71AeWXf5RHg1rG=5XPk3RT0!IEvmQ2& +z;l|{AK4#muNl31~lsE5ZRkFE6LQ+qijrqLjDu8V^f7d;$YQb~p*5(`mM +zKCxYbkPvlWof<%(J^0<2DxW^>_taIofR8U7&T0)qq#>xV^CEPdm!wNbiIw$}CAYEn +zID0?ix#6!ZRh>mY5llQNE5vanb+JFK4)C@$#?Iass{s!C;JnlASQ1`+9IIcs#d}T! +z)P4Wb+7Yfe`1Gxv)|=Tl#8|Fbh+TG( +zB7DfO(3*ld@1C(*ryUi(V@2I0M|?hAT`C=}#kf*_E2^L`VY+cx-q85^7R}AS%cIVm +zP$)`g2i_x`UABdO=JDr;q32!1(8ogPw`fXCb_`~51_&3nNPO+J(o7=HBY+8uVl;#*&{xBBom +zmQlbpDS~(%<58&%L*EM*FCwbq*<1V#>iEln>Jg$R$CvIuac{y5z9j$lmN;>ve@6P$ +zj|Ijap%?F1z$2d-2(h>><>L{2zC#X0@aDtWCtki}n#5!+I$S3pAdg5hq4TX*CmDC7 +zBzapKh6_)4mpFGK2*FK0k3SuL{|V2CbhN16s>|{1;lD*)baSWP{0!`PUPTo>%5T27uN{)umO%BIvaT +z$z{%N5uBe^D7;dD6>+%l2Dp6_Ab!TtrrLbl=IW^DXVGFBM|!uW%cGD-2JITX +z0{Z+0v_lSNN(R&jC_|hOLfeM}SL|Y#pxF_tmQqcvS2X-X?)VS~r;J{S>Pz=%Oca@~ +z7m|E(m8A42KpyDtCXIKdo#eBQDx67nuQ1x_alI>7f34N!?pwEBfcAWMRhw}Sv5>Ho +z#$3eZjS5*=RK9dA!wIYlA56(ULZ-<3?WU`~1QcV(s^tBPs3U_fzfCD$4J54dej?+& +zeJSs(rb|eDP!KJIUU`OBQr*gbEfyGT#`KuASImV^Xh4f8AaNxcQ*D%K> +zPQtOc-^`IrXG7XUa8rjOFUv)nrXYMj{An_9(s5au_GXjtPnSCIJm1UO;n@JU*%b8p34)+&rM(F}UJw}2zhaqEP^50wDH8InBq +zC8O&^7_8?}{xvUnl%Dv~sXjhf)d}W*F!*tQ2#y@Ua@tF9cj^e;_;mM8KUM%u +zHdX98!uG1sOCB}_5OU|pgCBK*qz{RtrQh+M8i}9KL6+YnSS;@kYxtGUc<6RM$QD+B +zBmHTt9RZEm8HHf>9)yw*cnrb7Z+1_wHhz=guXbFp458k=`GEEC0l5Q``N{BK(c{-A +z)gPtdZ*mqbH;fEdvaC~Sv%p5*$G1V&K;5(D??Yzd!Lu?CEQ@6Td>LKOHR5nMyTKTN +z?0e^HL)KkRJfD-N;Iw2vu+3O*m#02;r(;3)(4H;=RYr-NtHqCJFMp?YU8cb@XZ+K} +z`FXST#2v1rT0g+Iczxb-yT!QDmtx*0<@>TjyMG@$@PEvviF-S(h@LTg;Nb*cB-1S1 +z<=Je0hzI&JLokk*%WZHEpxc3cpHArU!YB^v%h8L`GP&%ej&9?n8i@ +zUoRmt9h^ix5d5$RA326VH+DX+iqE6B?_5Zi3JJ}Z>02(8OF|zGz@4d#uFd=}g +zEKC%Wr*D?rAQm~yr>_~x&UN7Y9>P{x@-tA|+f_QVUr!X6UORQJ +z9yxrPk9cbbLr_Q|DxK`ky8ytj(C^LMOj2#b%h%)x+tSze`54<{=`Tr__1!9X)Y?II +z8FQ)P1-~4Gd+6>R!+U1@!Z~+D`=Mb$=dt(H_L4@s1K{P(-~*O(#O1p_WZ-+ryB@Mz +zAA}5wS~p*!LPtg7pRC +zumHpOSw1QSUrTY6>LCL-dh|lmSbZtTh_H#?IKq-ca0{J!r<^r3uN=}*;1xuNN?=&hScJIrjph2)2(zdSpEh!ugSvP5_NE{eh(d>u +zT&EkC`4RrJp;wIR#+`!%1xGezk!VozGB0kb5#W79o%U6c;#IgWZ@(Sx%BG1eJD+Ni +zwcI1He5+p60i3h#z9hXrL8gUux>vF69-(-V$TI!D%t^Ard^OhN_Qi*pt4=MB9Jg;= +zVh=3}b3~i~^%@I;O4T{(_FzaO>{TyV=lV=5*AF)#zo0rT#r?wE`*Tof!amXYs>s)^ +zoN2ynrCGdY`KZ)zHacRB1|4Gs0U<(k!TH1zEs20k`eA1kyaXglUA^F*g$Ho`NcU0> +zxc$T{Cjq_Yfk%$w6R7>OXeI^;UJ5@1B~=r9&l=i;n=AGbNInkFib{<1wU`t!-uCdH +zSkd0%I;}SeY2O=AH|Ji`&%ld+8h*}A11XyKV!Vw|xmKg7ZzH`bka73H+HM?{8{;2- +z76UL2keAmT-mY`lh)I9%yp95jhpx$Yv3tMM=U8H1ewgB%VJ&qJ`y>ZVCLYDT1^^OE +zhc1XAw1K=_4+7eN0iN&;;kY$K6H;_WSW@TeiB)Ug_FnY3`U=O@YxVg89>5G&=!BF; +zNX_c#dj*=-s^_zhLA`Sv`tHMNTBNmC$Wv49!}-Y%zRp@VUD!vU{ZDB}ls~WDDy}xg +zL2(H?R}J-C05vwf@+q&5tw13jSdUN25a!khB(uUX-MR2yiH}{M>-+UMs99Zz$IxDN +z;+p~88lMKTPOQymA3wNKr!Mdy9M&e)m?RU*X@7)b9zs)(vWN+~;hXo6$B7fSr7oL- +z#A7{)eocLHy6C5Q?Y$OajZcvf +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 +zXzKBG=Ez-1;puyZw<$^r^#0pAKB +zG#+kbY`}$!Z)4AC%lb6yECF^2E_U_*3>7sn0S<~CC0ipIVLryFbo$`V|1oxDIhN%r +za7zX=elqTVNl!kvKU1nFb+^=&m3KHc5Me{aJ@?h!dmC{gwYE|Z4rK=)FT0qTTu4)b +zL1GnV9B+x|rZW^@JHJleh5IUSU)boL`dRj+O|nHyf4)$0S_EF~_@k(H;ju4fv6sWN +zvC}_a?&?}Mgnj`7;ZlN_ACS~SpsOqUpAJcW|H`XWlH*_F +zDrFnt*S83O-6uVeX9Ho~4z(fylNtD<@3{uNcw{L8K>3m(U@`HvoDsdr!iIbxg#A3U +z_c#}IjZqkb&jzD;ORNu(~iA_2-Dk#Xqm|YK;XGavl+LY|-wBy*-m?NJ1>*iWjA`I=S|4 +zqIpytc$_V`+0A8c$YUpLc@**+D4|((FV4DX1Ag_j;^Y+v+|6m|oY{hQl +zd?`5-TZmjbPnDy8D6<6LddvjUVl$B4#lg3-Y@YjR_dX7t)JI_K03eSXUORp>FEO~6JW95s2-|csEZKR(gC@0 +zMEIeaXyDoRT1J87Q>%~V+AGU_w~psp-_7*K?}TC(Ze~+wh+SqsE&9-JY&urn$K7~Q +zMyF7Cb@2Qo72##&1|=O+==bj9js@Y5#=I(Z*V4lAlMUMovpPqiA19HM%W%wq(=xJg*b8a=Jv5O{IXM3&A3-R9HW>gvxu~K?=rQi^7}3JdThsS +zE__3~=C3xtz`TIz1m83Zz9)hX$Kj+&gNtK*bNYN*?jS!#z{1=zC<=>92r;Xr6FpBGvCd8@yqRg?gqhtixr=3{J6m_T3PtE +z|Hh?8^?a%mxOb)7Q|nfjK2mKsWt#H}NhCssme?yo`wGmhM77nhpf*UaQGZNyGxz}U +zOrHKktq;f*+!uH7_L{HI-!h +zH|J`(>c(g06Gj1qa2_4XiM;XH +zx1#apdp)olk2V#&R~t_{k3Js6rIQF(2r6;F=H7FM%8y!yUHMuwZ18i%!(qlVzAN&% +zO}LDTI|3RAAYHh_8FEPah3$UCSlGGZ$SozC+I7bxM6fn4<#Oa}wQHpZ%^uN`SqW(-O}!S0ntV1Ir?^Oc +z!j5=)iwb`YwAl7JD_FRe-B|Ef>y8hmtzc?L+)G`yC~+qQ!#|D8&3I^9(`$7r1p@y} +z%lFUgz0=mmV;X$nz;*E&9-VYtyN_eXsN`HIWip}(2auY)9*C1EpK8k63yZ?c8zPV2 +zFxV?X`;r<9r6qjbv7hs~?nRU7z?1f<;<9_=A^Ifn>=h*8oa~YPX3O|h8~!dbGlb;46omr;qZqm?M3>7pYj=-%fyRxWevtyHnD%v +z#h}kwZSIt>?Mv>#_CPu4DG`s1b?2}DSzqCTB`L87?CLFPI(41QbN91NnS9CWAOEepNJKfxuFylf^wYSztaL>J|r&|cMZ+KpK39Dyd=IEUx +zQ?JnO3{9MaZYn!6^?v&;cK>W?g=Q<_qQqVXpAM4AJ482(N9~n+X@mr}ixw>Lir{&i +z#r4vBuCpAxpOtCh+rgWq#ohh@=L*Qty|o>drP%k@Ar48i>x#9s4QTk8j$c=6uybeB +zvSei&U8j8RVf=Y{_QL`rbvd@P;B1(-ipNOMppi!d;B-#`T&|wNsZII&5QF}_=&OsL +z16xn323w{4vt!)Pl+jC +z@^5&X&!UabX-|2A@kfYF>W39a;1tf*oC{A~ZdLJhJ+yUhpq4DEq=>6zsY2)QkP$WDE +z4PCFs!1A6T8zbV*U>m8#viYZmTioW_>Z)_^=Mi>LHy|N8T}$b#7x#T|RN6=^DP90* +z@JrgREj_BBDXVqI6uauX=Qr$bl{OXDZ^n{tPp|7@dd3yK^oSZ8$U~S&H(@U>R{&xp +zxsYy$JYaBR&WkS=3s;0OoEcLbvS-Q +zIb(21l)WpyiSJgq`8653YpPPPAt^Vaz{-AG20tO82b%%#D$Atgr@G9GXOkWvM!#&W +zbca&##mk|_`^kHjPvtI(kW<`;-g$!R4WT+yDaT$YkI#Lrfcy9)k0>19^~8zoj9TL-n)z +z-uW(it;BP{05G{8S3xF&qgD#&`dJ7Y;mZoxUkke*p9d(4W +zg7Ql2BV#WU8FaG7vPK|dai(+Nb;;LpRv;IWyCpSG(j3Sjxba2 +zt~_`Q_mT(imCuNj+>5w_iu`4>&w~d=zkWkLx_bjg=V;R1^glhAFaLSvm)CdFJ~jR> +zc~SGw2D}F}cbg!hEc_e0%z^4-FLOUI&<Yc@aE9BC9M&Cc952EWTU`N;7SpyTgp-*~Jz+2#}O_FzpH +zyced&4Zee=o(o_v20N%#^hmr^o)74uzj`tK>b5`wpZR>6*trQs;$-UzL&oERr3>m6 +zXiR*Lw&NIqH@z6hR-*dn@Ce@PTFWJeU@Lrq&rQG}-M6wu_3#`lC~31&lJz9&slsjb +z4py)}%~7cqy7%a(I}(9&K1XiRD}rYjFeHM8c`%*$(-69>!}awHOLi!dsOA<`Mcujm +zspBE^Cvn9*jk6=0d;$^iJ>BcQrPsIgL48)2+xDQ;Pm#rMEid8yZq(c^4(wzStN7&& +zu<eH3t75jtG>&H0yM3u6SU +zj@`G?u6rz9gXP;i7UsKxrdi-x%6>AEj6dm((Sluab-~zr40k`k;g$cGp=g6}1J#W(i +zzIXbXt|CLh1Bg6tU>}UyZ*1e$(<7k19;u*FKlwiNbENe)y(0N){Ege!r_pcpiG7fz +zY^@3W(`htSHJkT9W%}|Sx%Y_OoqG>q2r}D4n@kZ$>ww7Rlg6-ai_sWI_L0g2I}4C5 +z4+Q+@YKS|{S-3v4dPw4$GNl94ot$sNSow1a*zp>+9_otkBpK{7!4OsXg9TjC2OsyI +zFuicQ4o?KM-`g^HZQj#5FZ+Cqk7#TRk}rJxlz)IK#N6+&zD?}(wmH579r;eL~5akfZJ +zxAlO&r~;)!{z*x)s)P7L==wXVcY>}*v`TM85r@S?&x_fYR9E0_Om*3V0cj`{2vo8Y +zN~wn--+ooZ<36SK$xUL~O^NNMa~#Ri0w66WCSY +zQZ2L6WnJZ%f5&My3w~x!$?;C6CA!NC2S^3?URl9OUai!G^N7nvw&`Ap>3i8H&!dJf +z#na4Zo=a>@Qs*>C6QB_QVN~NBtBB68Q_1K?H_+UEI8o491?Mqj*oTQnOF$oYPg&e3 +z_1&=Q&f^=$!@Bjp$LnZ(t^^~|A?R#5FZHZ#zR##v&@(9vHI$7KKe-y0P1uvpC;OHu +zfIhZSIvuA#h*QeSpu<8wpLIj{qHT=sH>?|eaN#n@>1119&Ch!Mz^Sp8T!kyBKTo>r +zPA`E2X2JvV?q5gJB5sTjs!=NsRC3fOC3@mU0$I!61qC{I9RMMd4y`S#%xrm7gP)u0 +z(O6BBfXDXnt}+t3!^nD?j$~X|>+-#5H&Gn+oBWK=P7RO1l2LbO@nf=b@_w3owzF-h +zYPJ4gD`N{|RTN>T@0;&5ha3 +zI4?lloACxqNV$0iK)l8BuP1y%?jCyo4~l?86HE4Ydj9hoaHyfcT;qg^)Z689IrSTs +zcX7$Z()|Rs)LI9l;!`ydC?U)|cjB{Bk6~8>7=O=MUv`@ZUDq{9g7?fa#8C*$>tMYg +z`6<|X%vF{3h3WXYJAF1Zj^jedUK+dt*NB=YuitYHzS0tX=|Eht1l$JFpG@syCZA0S +zOP})|BDMD8Gex(h&6vviJHcSTT;Og1om-~kbB@0HG-)QEBNwA9yiJ{-#?gBL`HbuQ +zyYqOYD_7J0?Td%kAOhxIK6DFKubdVtJ$Gvb{CrJZAjSMm`_;X{dh@}77vh8({lLl* +zIDwmaUS#9YI$+)hjn6soSt4T9-GxFhtjD?PT(BGaY3V)yMYqjQEU|(B^a=-V@iFy2 +zHr^ui)}J5qRdUw8_E2ZcFfl}$^_o2nOK~n8dF%!+Nzk6=mm^q-BZXY-)(#k#kk_ki +z*y?lq(C01cOupval`svTfzj8xc2AQ$7A3R3wbnPQzFu9p4-x5J+O_+@!Rg7vw@J2l +z9R(5m9CCqJ@6Rq`;DC(Y&zbh}^z@_U3`-HVJ13BD1i}I6dMSqM%t?sSBlFE2^!uE7 +zunv&bjSX+{l-duSz^dQrC=d6ja$h%_ocV67;n*V@V>1mTo9*_^ym$h?syMy3kLFHE +zctIP{*EA;=6Grv6-*h=tDc^wT+*?PkJ2Zy$@2FeR?0z2cIG3gZ(Dges-M~qIZ{_Py +zN!ffW=se2!UfRebn~w*k)Pdtf=kQC)es}Mkv-WDXWv<$t)7y@4*zR%CdyTKwt3Q(1 +z@Lg6r-Ul#ZKkZT^D>?8&`xSYC)spL*hrgB)MN5D2;O+LXO1!ixu+c`N=$I002h6AJH!}&zLchz7qj*iz +z9T4$=epVqyll0B%s=*>4L$$Tl15G@Eb+ydjf~Dx6{vcQXybw${#jf}<+US;6?)~(z +zf$hx0@;5xSRt0$*m*gL?7iC<9vpteunr!je$q3ue-ONb}e*!zcTK0;B$ZEb`bU +zWoxz9Uc~mC$K^NWlfPOdgHP6gy;>nD?`KR}*egH7ijB!mcMeyluvUae#hD)jG%Y*% +zK(Qy?EfxCOm@S}?2v*5d>GMY)7JkcZ-8eOpQdLe5RrzB95zBWRWpn1{R#*-{hNimc +zjQ~03J+Dsi%0DqQa){X-aj;KFxu|u-~Y19U#!gK<<*(t+rgptqG^ +z7(@G0G?`oZY8lGDY;j!&_ +zDwOxx1Rff*WCR;F+!>!NTC^$xg%_7voU`XxYqUz}$+^{c&!c|+BJ*)BkfZ*2>dofP +zv}VC8X{G*(6|UcFkm=3q3J=10cE}Yt_pKQpd$14A&Zlf3YM>u!kL=&lOgj`iT^}zP*n@);zceJ +zDzVSY5#5f}+;q5b>Kb02>8lED~$Vj#3Y^b +zJI-Qa+l^w)_Pb`dccPp08*yiciV)Gv(=p>_r|!cCGdfRwMXd0ytdu_5v-Yb+% +zK64Z_yWQYC>e}||;_1vTs@S|*C1>;OVA$Ct{)AD&o4sp@Rj-Bj{frAB*6Qxp8Y|cZ +zvUMP$7&RykGAA`&sFTBI>0!J)sc>V@ZGS{b_pHG5F{Jv`<`{*UY$sbHnu}+8<<5@! +zCG)zTw*6M%{2%AgXXv~8g;Gm)?GfF*XHO0^@+Wt>dm`Uc=8}ESYqqN;R67Vo%{bqvBH@<<0aZjAFmnGKA7nz$L;HFuQO@_DX4y?4FC&bbD#Hh}kdmg)xgqd*o +zbTIAQ6W^)UT$ZZGzEHAbaF`RKX{hbIt-3%+nx*Yrm-a}<=Qq6lS%I$##GF^pXP_T8 +z1I2b%d_ +zhG{^a{z}l{9Jsj*gJ;2Nsy`5VL?4}(zH4%Nto&7khwB0!S@zM-Mk)#DeGp^yxOG!=N?Mkivlk*wI9CfSK&wu4O)-Ckj?Yx%S#ZrJl`k=SopemjlMKn;r*8Qnhy=v|F@EIw +zeuBkdvH*jvT`9(}W)?kShml;fL5ddIt&7Ck?j4E;YQyJtbZvuKd48sH;hVpc1}iHq +zrTaj15}tws-Z)yl2OlqGIWCvy1zZ*De%JERZi)Mr3i7kG3L>b?>Bn63CF6n?pi4}| +zQfGF;iq5siYhCN0Duqt#@gNc>2((YWK=IL)f{+66Nu+9c@qR1U!9Z%!5gNCIdp<$z +zJ7*SY{Q*9(26+UCi79?VT#3wd5Fe6H`1*YM)UWT9)l&iFnx|)k%v}49(>^!O0r?y! +zMVE%ZO90H{e#6d7GiMC?AQBw%pgLJL<*WzB>rw1*D7tjo>K@U@r$|k-Y1_XmMivpp +z4lDDwijP^Etu_zPd9@JYyC4ED*5>fv3Gk;68&?GRt@V}hsm%XwOnHwlJ=ziLS3iS` +zOq%1AX45RSe))4{e9x*89){uNnj?mG?V3bC;8P;>DjykKo5GKI9Ju^wOvrsqs5ad@ +zA5+y+*?AG*tTWN88032TMr;Zu1AdZ=cW)XhS7XC>hGr%dP5~+RCF=`~Bb;9FSltEp +zHIZxfIGT37eeOU}Ut44K$O)MBPG5f{y3qF;6TD=`%gt36X-~r7`%6`h?5?oI8u-a$ +zn;haf6gQOW%8`6Y0tbhDFz+6yNy_(tN1U%&%>8;5!TyvtqVwlLdn1xNk5AA)o%*;a< +zFmOrigrgggLYncm-V?WOM94*d_*cfo=z&VQ^x#JA;DR0Xj*UDwJp!&+#5T%f3Vr)D +z$eF#MxmiyFMnQJ$ERGil^eB@ +z8y%+fNL-IQ33tfFVWsXXAorXXsB@#guDfIQUNuOikBU6Z0FHI6=`Dv2--kD@*8~~s +zp;uO<$fH`PMH{K#F1)eoo^TS*gFQf;lN+&o_5Oh35-zqLC +zo|o9$GM48veZQ|lWSY+QRt1fJUCb5DH_=|9xV?i6QDa4(_+Y^}IwCY}4l%w0I=C|I +zt0uOlGI(N{*Alvt9(%0uJueoe8364?+SfR{iK3qZ)xqn=%gaN*D|kw|Mpx%3ZBVV< +zb592w$z#~(2Ht6$0h}Qel7^$4whn0mj}(8DE01nAOO)b{iSoHnP<;e3zIg^m)W`2L +zg%C*Aw9)TL<5#|GIa*s{tL*W=^Lf!|l%<7s==uDwD(4Q|0bo{CJALhu_D29DoaIwO +zfaB@PU%z4UD!{kHgSg2DjGSv3piTclr!{CTM^Xc+lEaTdW +z(z^$@USeE$OCOoI2rqTpHy=f6k2F#BmN8v8!*y03h^X0bQj=Pe&w_d9|T}-FOZtBI_r>#8+NH`i9A88y*L*3tuxR1KecGJh^2*wZZN<4=wZ6`A)pO +z51&tJ@RZ9jy$dWG&3XG%i|wuc2F+p_yc6ZI(xqcA4_Z}SUzb-igpUB!X^wmByw?cG +z1(V4B^gP)t--oJpvIhy!O;wJZf2QgwZGORq`sr+sm;*kxU#&26Y=W|qgD9QxjL|B+ +zItMR{awuW04H4Z(9ySND755xmLt^jdYpsPs2d;aX8IpX&bdmUzS3GM|b?~!aW6fB} +z$LcS*QDp9lL?6TY?g73*JYvq?jE%6HO4ZI}R&D$C(SXb&Prk>7DdQ5{w^Oap7PFp% +zWV$1J`ViQwwr&;S+w`@q?Sn*HCw!D4f5&Cv=YghAD+7GAPZiT$Prc`sQuZTCJ^QAJl^EwG&PUYVMBOOPm3J&sl4B5%YLfNXlE~v +zE#CKFu3osQy7-EUBEp_P7#(S9v^JBANz}Sf*I;dw2t%Px9@4w|9xYy!`#!OU(@lv} +zeZulpGlYJx9}scV-ny37Br9!Ue$owgMB8qB-67(=Tj9rS9)NK?fBO3o{5?}B^^IuF +zXB2OE?nFx+)_~yr6hth4OR^lU| +zLpFML^L`MxV<2(kP~9x-$XLp~8P%)8?=f8>*%qV2S6Fd&{rX*w6scn;#2UYA?@JLF +za8us4YwMDVsEUmFw6OFfwZq$=0x@$^KBokf+wWz1A59&V;cTbar1<=Fr_I$Yzkxz( +zS#Vb|s@>^_YE>ZAaPAcBuMrT}fMGso8;3x+B|lQ!+Iv#UF3BTFh+lSc`9k>M +zxg~q?_)C(EN(PwZqarsRLr(hSlOo|9!O04GkeTQ-%q#hrO9Ke0a`fx=pET^b=d+OB +zU6U%bS9n649|0_pubrV#J(o|-%Quxym1TV5-U~c5wZdn&P@&^*T#bMG075ZZt?G4C +z(xXjn4}ZF?mMVz%oMZ*FUc5K4%YyU5^n0d+4&A6n_jTv8A_asmXWDy*&*gxP(7 +zT5cv^hfAyHY*TbMJNqE>z1k5+vP>@9#%Jo*o1A4Yo!mCMbu8i~Dta_rR`@~lF@{ge +z+TpR?E1Debx9!^!0X;9x`>lSp^i!Go=UDi61L=C)zIfF0U^FsQ{pm9u-pXz&dx5NcgKPfl^a8ogg94K+wWihivRM@MMSjT_!E +z?>keeeQo%JU*EtvS0+gwS+D%OfEW95>jqN!4%Iw91?MA32dlg@+%C#12Z$UZYK{8< +zz>%pDfy<8v{x_fgcD_H}O?0LYjm>qKF1R%Q5Q+PqzOV*c-?;FSJ>Xt&!*5_Gg1xNR +zLQ9E*gd`ZEJ2%`yjdLI2V>r=aNMlwUo$Y2mi^ke~NttNqf}A@FuinKA_j<2U_bo@f +zC3AilYA#&$M1sP73GG}-QX%bX9=3X% +zpxoH#JRX$yGrg;qc{qYU_2~!9d$+xv=PEm!Q#_Yu%6jz6-)U#hz`3S2O;Rg@f+R{7{sj*pPk9vxljI?36nBR~;`={ytd9CpWakE?$9yXd6QJ&B|-%oSvNH}!-N9f`}rmxF8z!%PYGRY +z%YCpkd*Kr*IdS=8zV-g-o;9l?1sFJ#3?w0v9;b){moJ9yxK-^BpOaIGTzewj^`qU!Ex%i&=V=7^2rY3 +zDWjLhw?4xU`XK&g%uoICvjqoH#~AGIrcVem6}0}DuxA7Pda`%fUPdjoxkd?(GnCHP +zyRUIxly3WOy1KUF!tJ#I_e2K?$uQj3a3DQbOlS0H$(kDRdvsI5-_Zm#_dKXkMK=>d +zNQs)d&-=C_f*ON>!@D%=E4P3e8*0A^i8+_`t~Y$$+K~+`$}~$5RAeJUbKz@g2-M6# +zX?&GNeOdLbEBJ|F{=zd>hHmwyDLt5IRpLj*u4K%)q5Tc-zDXb +zmBc*OxJ(&cZ>aD7m-K@29iA6G>#*JSDGHRCATk9`KM_#n +zcr*P?XG_r;5YgB(=h)!zx%Y9QfXxLe*E^L6xLa2r4Lin)l&p+LN#CH4&ntH0I(&OfYGH_Ting6abMYT6W@V(3WCVK +z&}j$}`tn)yOC~)%jMtCLIoDkdAR@J(#nY9k%k-h6z>;#esQMSz5R+e1|7UX{E;u9y +zJ_p_Enw7RJdFrf=3XIyV{6dKDLDtDRciWj^UTK!^pGN+LW>h1+g`ield5!1R1rj}< +zIl<^-7y|`D_cq@--=)2M18ygxpx#2d8dWJ5N3Ax07VP``fbnr&GsSCpY`3fJ{14aSX$?M`rHS +z)ibT<(Sp4~LiFuVtshqLq!BalTVj}iPZjeFoQL;$>6Dpp>{`lq^^Cnz`k;5Hk88c+ +zU>j0TI<5d6_g8N|H|?up_@1rh>5~=abMTO#)>p*dV#$Va#Hsh1*R`B+>~^EYtb<3! +zQyS?&iMF{#l&V10?t2VcAG^7Uq~v)bL_jVbT#S50}_8zk?J14u~X19$85Zf?=(wR9KCN9 +z&eqr5L7vtfML~G+^Du9J0Bg9G$`A*Ifys6HP4`zU$82qI@7ypDv=#{!eFCQMh!u@% +zTrIMDH$lW7(p{087Hky9NTS1I3j96t8}_7V5wnE%xlZbBII<`Es@8W2xV~N`UV^i? +zSsXqTz1%1cmI40Or&J(?+|bGi7KNB04kOF0)k05_>W-nF(3^T17nqAC>YGaa>R!MP`j`L>NH`x0TQm*A<1qPR7nSA4r +zj^2`{SG9UME`#3s`f?K?!LMD=5NZ2NNB?=9~p&V8EURfoLtO1xw!b~1B%6;M5YuCcAxVWDP$QOkoSarEdzbf+zaOGYUjO!UWs0|tQPi${0hc}V`Jti +z`t;Z<3&nQS+TqqE^w0loud6OpeV6Bk&ypstxqA82_vKjDFtBww0Is903(9w$Ko+&* +z@MFNs{9RtIYv-2ly;qP4(Q;dLKS2cCX@AzmF#;8)$FlrJ@jGN0U){LvuooyB~C +zzI5!3PPW`t0us<_z!W)@qa^v1H$_;9*!o#=3tNtmTzfCwflWv^f)*C^z_dW&2CQ_A +zy}9xpDD?Ow&^{cD>=7tVvNL-DW$P8=D7<`)IxIaI`XK}zs6JeBMgw9Z~>=2 +zz{8@cR)oV_q=Kh$K<_yb$=neWqc-n*Phu~M?OY&7Qwj9EN2q9z5^nOBTq~qsXZ0mB +zK2$!!y$`?NLu4HCL=&ZnSLwiIicxw1>~0nxA^CHcEMp3BK)F*^GP(%RdXk+sVnmS& +z0xY$nP^fjai%BK<1eTUuAa=#G;S|mg8fQV5L=v`|OZ};{LDHwrNm9Rj==bUlY+CKy +z(}AX+(H3pycRKRwC3KuPo3Ma|NmtB6k@KucxZu^1y=JcS*}UHNlU2T8J+a4pHtfbe +z4bq|4;4x>zVf80H_bYun%{S~{L2Gx +z3=+&;fd@@biIj-i$@k}7WdW~mhig}X#9IgR^+^ZX^_0(>MThy7pP=LbDEI>wv{5+0wBmIzO{%8%86-ABCy)YSOPVxy9K +zp>u{9)0@1{DJKA>FNhfLzR4;sPmt+KI6lq{#j5$J)ydC6qS*+t$?DKO(#O|Rrd$?@ +zKQnqgE@zJwEQPD;h4&(>yhd=vc|Cm9HHZQ?@oETW3Gux?cOREuyy%vlhjCODA42=j +z>*iN}9zW6?CWbcc_nx^dzR=TGW@_iCKdD5eVJm5wxe)TDW6Vap%7yY4V>UY-``lpS +znh=9l>m?|$2!iQ-pq`?%-l{Lb`VsVwtnc0G>Z6kk5&=WC3y +zzD?ND`h;}p>Qmp%;99S=WIaSxJbX_ND8(aqxcZiCo^-ac~!(N&2lOik)k*L@tR1<1PXjg@+`%vUjvh)jmq~f3V8>O7I1;9D= +z+l`Aa6}5YgBA=8km4}uOUry$rWzWaF}@o+vi +zJCNC5Tre%1e1b!xXuvOW>fGk$_~MT1X%i8n&o5LFQ<7*Ix%Y9H1HyWzDNd5PzacvI +z_z)k#Q_=#|Uo05rY4c?rgU2@3LJwl@ty`y;Y}fN#{jy@f?wlt-t-NmRd5hU0q7brA +zCy&@fD9I5xkIWzc;-paq32ndY-KKYB@jlFf&}KTF#XWu#TCj*qmZk5QfBsTAAc6Oh +z6Xi=!JJ7i;+HV0IoX_9+jAZ%sJCDc@kphpX#d=8By_qa}u8cIi<>64PQeVqn+#RL-{8frq?3Q2;Q_+0;z#iA`nX_;5*~Q~m9jLtX>y=&Qibhvu +zPK7(-#}|3>aZQA8lUmQ8^Jk-KL}F%{r27|S%I}4QrPcf2rFzep)f~4F2D`_fHq~LO +z#T)qMt?w%~>QN5;*S6y^kaX{pu5aSeN{7tyD|@pl+vH*MhQ_}{N8Hk=%lzfkxD^0F +z>08EXeWv?F9vr$(zYDkGZ+~iQ`AqY)k{NR@_=Twf0H39V$Cg0rTs~s5ClD3T5e=Z( +zvPMHl>L}`W08kIW&Q79cI>g1Nu^@?`d}ElzRL(OE~#+%E(8eUIS;CGB~c(=O)=ia{>=N^CFu!h +zoLCoPpo^PCmCJLx4nE?ZQXBzm_=u|9AOn;Xa_spanY8IUTEY8RiiW-V0@r$L>U4$M +z`w8D=0d{+%_?{8bXCR)$Rt8A-2M)!nsGKbfJ$m6$#fxW7C=z_)g)#PC8$5pe{jsg( +zzQx;SmM-#iAm^8Pg2c4*6z;i5p%1{2UKv>-tOOrN6qc>WX9pNIBd>c?g2}z~xZazi +z>qb?gTlc9U)aY~5<{VseQ$2hcE9vsR^^SCnonGEY&@zZo<`Ox`}gnAB@LSSUTjdP8}`13lu28@=fkF=h#K+0G3 +zEv+TKKxw?EDaT3m2z(d1M4cKS_;44xKX~8Lr;IC(o=d00y=r71LheByjN)41ywC~+ +z#MO9=Go7Ri0kC7OvQR_AhxsPRaS?+1-DrR~H{)}ULTP`i6*U!s3lzWoGw6ix(wk3w +z4M+p;<-K3M(BtRJm0SI1xb3o6NM!N3y$=jyJ^ffPF;|Rm^s6#l1|~8+N7(Q3x!Tiw +zJ>QS(ye~0v)65pavVW3$_H!xx{M*0FGH>ZVPzuV6`0ez-c)T~TV1;?!Y&A9&B0FWi +z7eS#j}ne7<=R$&we=m+<1)%Bk}3_&zhiWqZ`ufX|~c(Ye)%S_u7M +zySEE()#os=yGGSx>zCN0xQ|_HBICTrCpPx6GN7aDe!*7>Cu5aEw@Po^h13RmBLiw> +zp~`t?l-W;xF=8{Qd}n4tyL^)j7kQZ*2+*mSrg6Q!JEroU^ZD0p9#=X-o}@#863dof +zcn*UZ?7qdGQR$ag`(AbYi4fOQx-adgfJzZP6Z +zG~257gl)%VINfS?W1{*q;U_x807ZS{m51FD51fdZuHVJ`=iy{sxevn{m5ZUP-6&su +zIB@>L9y!kFDFaevJRA`>y?NB%1h +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 +z3Rp>6RPhND^U`!6`ABy +zhoVgiw|o?j=V6!8{UWAyx61cv +zXbp-Fu?q#G=Z$TM9xL@ne#?Glp7Z&Abm>et@annQ4}`SLf;tWuPKVZaFYXqBx8~PF +zUDeLv7S6Z3?%c{e?Yp>nz#rl7{hm0d64 +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 +z=koE8Gm{}b{;3(am2ovcTLBn!m +zm0PD(`B3PD;}hbjmu%Gs;^x!CkwcFL(suybbhLfv`eE!2;B#n0kK&i01y5*b+_~qL +zH#yry?<2<#&Xmx79N62=+yGTTs=tF_aUkrR0mrhpw-tK*OQ*b`uii|Z2Y7nrXF2W< +z3AhLuspjZ!1aQ7gXUj#Vui5&<@a)>-S0X70$FIm+qAhuBnW$)rn<<)U(t^+95C9KK +zGV;r2M;~xUSn~4VReS)2e2x>YUw`1$XD2@g|G^Sb{(|mh3GyP~*d@O=R6VX?^2)+_T^FAH78n-|-c%*rz-;Lnl#IWn8*9b*di_RmCI^bt~p2}8dc|8um)`DVcd{?0f{<=~Rrllnn9 +zoG$sk_h%Ax84qfY7zPxz3nv7u2zgLZ^VfjKb^OxPCND8bn9)cTUB3!_<%Tnt^rThx +zlYFkyQ>Q`}X;aYVi(jT&@#FO7{D?{N$h)__4WEx3hyW17Jd)cuZX1s~-TP$u`@tLr +zWivLc!{4wV0J!yI{+qE@SQ~k}@D=WnW49OhZm)nf-jb~t&iZ#rUlDQ1#=FW0HgXe* +zAg1!1%X5v(>dQT7c-x41ywo>+GC?2JCFcA>sb+3GEmi8U?fIlL>xqcRa*#bPtAW6z +z+y_h#tt&!eo4LWDg-$l7nC8>d1^g;nAUIfo+7{E1)3*3@!1_GqD4>wv_?<~amY==C +z`Z!=$-@|W1zxtadLH$_$T#qrj9Qc;fwT2RO&|X37)+@%z6=z +z-N>2X)XZI8Sc(jYSF*P+S>1FnI>afwEhM#v@MBbAf_#?FL1yiQ27r4$WBuYkN@Nbd=YyXEBb+w*V!P$BntD8Q7I|>L=z%!Rd-aGPsW^08 +zAYNgT!-O3f!NR4Uv*$*ib_janu&sgb>AUOS4Ws7%UdAF}J!LXDOGJ!#){5di>@2($ +zgKRTA?&r^vZhszyZntGHeLd^>Da)jkAr>3ao?7#9F3a<_z!|^VLe=MD=MWUyIadMw +zv3I6$sG&ljS3eWLTjJViDF>zN(^&~hasgf9ZbdfO=g?;LBwfk{|4ipJ?{yso#m~W$ +zfhQ6UXL{ffN_?M!@TpR%yzQIo-+JpuE0KgJ3g-@TZNp +z`f-O;^K3xRRaZke_JrDAqboO!4@=-@wHH|EFhO;vOrd%V5iaFtdp|Pwvs=F1H`96U +zA{o-X=kXhntLXo1RCGaFfU#L93bbxjDn^@0A8DTx5Ccrmo+) +zOLyy$ZbYS7-_IobzF(sc(6UJu=H?U*pGBOG<=dyBVheV^_|kbAlw-k3hfwlSW*BDX +z0LsY8yQD`gZFKUX;7Ws$FBjtqxa7WdGc)Mqo0E!%4&lE0OpWMD_nNa#K$~KpAh}rROB2-T&6CO;Qo{};nV6v$#gDi$4K4V +zVxL(F+@X{t=r10i9}3!M?FUEqn$4>by%5QIkV^WSVfa$p1TQPGiD?|Q?{#is!Z(t; +z7_EFx!%5?zm +z@Yuu2XBYT9_0Xg_*2w8YW|@2{Ys=+eor(hNjbgl*5ssM{8kRWyzA-U7@JMt#$?;Gn +zA65xM6_+{Ox+Md0h=g}EQI25>Ug1Xe0a{0)y|3br^TV5qv>Jka9wYRIRj!$jU4mm3(qXP


;$zL+MxI{G7r<YyJ|ZNOj7 +zgc{S*ed5kuF+8O3*_$a4Fhk{sYV=rCZfBgeT*$G{OsM}kM)dV-d%s6LX9(LS=9{}- +z@tjFHaqqbCH^?;J6`559oNbPkMAtS_&M^zUiIs6YR#57$pStsQ>Uk7lynz=?H8U(7 +z%a3hA_Np+Qs+D!iJ!!kBV*VNX$^rhY4a5L`<^!RaUU8`*E1&vjxKnUW?_2TW-aE9K +zBwEBi1bFj+-C*EXBo=H@q&NE;jf8?%>_zcy;jo<;u6RpkM`|_jl*QA1>!SBj|Gg%f +zW{cmTFy*1ovf95u0%&E}rQXOvjz(a=2jSX>D|VU` +z)bbMUbq9REbVS{dtFV<|Y^OKBLGnXPjcT=&VpTWA9&U&ZQQQLRO&QUpw_px3bUgrW +zqkWYU9kW{I5Rmd0XpLq-tTgu(y0V;mQ$H{I6ZZI65omPZqsX+!OHn?NwX%JKzJ`Iq +z(KyulF6>0#w4+xZ?WT8AD{ALyVL6=CRTSrHG8i5Ti&qKky51ehraea12^GiIH~0(h +z`lcqVR3`o5%9CJ{H0=XxQ)llvLV7{Yk>S;jeE^XC&85_ir6xOaem!pUF6TT_ebohg +zoA28Uui#vU?9p5AQMPr?ynT&j010{m)awFBHm~C6Fjh|>4oUT8)^SySyNFrki)xB* +zqd3}wm9sQ-Jm{$oJP&Y(w5V8Mf+cGE<|x9aA`!iA$E8X9CUyEe4x@JM^NA!F^s#)b +z@%|YbA@S$&s4R$o3-$ogWKTbu~{#l +zS+u?`Pq)*%`h}G5045(wSK5Hd5`n5cJPRi_%+yqv>67Y|6f=Z${3xDD=8QFFfE>B= +zwM7Z~Mi$4l*nc)L5`Bs8Io-JDsxGoqR$tW{Pw1S-*9GYjbj!e3PAXXM69rW!nS~87 +z%1WOtd-|O|lTOKKk7BtzN*)c3Gm*KaTd_Qr^(8LXjr}~PoH8E1eU2>nwUXo!XH@6$ +zWHDMux>KxkAN5)@lz6%iDV{KG%r@u|R{5jlCcHH7GBZ+bH +z9_GIG8GkL*qhs>fRy^{He#IaZ^0n7%S-!>0FS^RYb*IXQse%)>He>%9w$bFSkEh2$fk +zFvl~CNz;!W|6Wqxyeud{-*oJaVe8Rv5#@k$hkKu7nztu~m+NBB0{L&Fn4lZ8QEXR33GSn>2s^t=zCZjzHC)fIk^L9~w%siXQ{n~-=P;YvXA0+`9 +z*?XPiqKYlwPv%5vZ%qj%`HNl&=Q# +zjoooQ2Aq*?Bmx6?j)d#!9^@=HLc>RJ_^!RWC2403`HOfuJ)hB8cOEN+8?%`2FD*-c +zMk;!ceZLeW(}CM2t0a<1lan=6U&|6u#}-Z|?^)Fl7*!IQkIvc?m*td)GK6;h*6eNd#O$gdp +zk69ia&lq2}&+mM-{7V$u$l15Ez4q?fFxRXG*{`u6z||?r?4K66H?DZ_iSrQ}&y0tQ +z?)G-(#-ZCRrz?2mdn4m{-!~r?O2Sk)SMkJy&t#sP)k@qfeR!pV^{K}PwZWgIaC_=y +zb?k6imbTEW$@dS4rifG3uP8oI6n3^5OZzA(4fw3xbMSK|&kWr)Iz8C&2w^qE#kr4r +znty&I4S4R{IdziRhl)T_Xc-`uX{dr{7wJk +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 +z&Y~|l1=<r$+$9;~bN?>#e;%@q +z^3rhLktfjn{lU3dR~nNJb-yJ?Y@|bVdJW>lFS_k$Pp;s%osmFqenYAIy@L~QzdcwK +z_XcM&KO{{XOdndwX#J#Ad4syg);&{uf*xF~(jm%;9IVc=uagP2wHjrH^~}IqG+XCA +zPJDYh_A{cVK4D)YtkP6PiMvfN-94rUzX0x*iZ84T$RL|`0HJxJmKiY~h|XQf^Et&- +za?71Ebn`64OYgr*DheUx)wfd=meXNB&lNU!EGa~2;W(S@V4P+e&9D88-i2(bG2%LK +zs$Z_5@%zs>X?%htcegK`7GC48$Y0L_gV&{J$#2VqBZgs{H4!ie!gU(hY;t6mItLN&qzY+BLvcxC1FS_Sp2pOKiFR +z`LBh|cV>`cgNt3^_ZA<91f9XJaq|v75`|Y=;Wk~yD)|ms+kUaOI|8^k%9jcptfQ_t +zpU+HqZDjC^0C1^wIF{Z0z%R-LPVWF9Vh_{+-Fq>m(uLIB5+F}Lre6*nWElNruY!uK +z5Y%$!C~|=FfmdVhiHDo}>Bwpq4VW`$X7X~1v%i}^-tVFinzn8wv1FOZ<#A@1HkY?H +z^k#mI--e!+mx4ntJ%*DR(KjC3jM?G8%e?$~-1?;!f60aJ*GmOXW +zsc}B%%Zk&YO%3N?G-37$dLl}hU2Uls$R^IICeP@dEN)=a%W)WRZ``;Fe_ +zJ<*TsGaUeZ_-K#Ktv`aCv-B!X6-(dmZ9s4F6Oldx@z~LJ(akAaicd_{>en4^BTrc~ +z7+f33Mm<^QJDk+Z4P>PRT5_^(+&iatDQ|YNRh4Va&HTe1zNdo<8WJhcNXvoNRRZXKv|``qBK{vP}I| +zv-Xn>@VP$3fqg3(v`yH1XrCl42&IFRLBS7N!Bht=a!5{m4e(~v0DXM{^6?D0reLYNXGvgzY +z_Bp~?PkWHgNg6}wk;{*}jicM;I$x&OscOsX>zJ)wxh7G&iBY8E3_6uizAWf6OUt3F!8!xo +zW8rswrOG_c83}WdFgVb8W3G&>+&Oz%>+6$Z@HDBRlg_|zce6)ap7QRyZuyyYBM#Er +zg>&5Cc1D_SG76N +z+p@`Q`K>~}wR{Ds5%zm2@+AFoJu2O|qQJgcdJ0uS#$CFl)1yh6Psw#reFGZp3PsMP +zJy*Qyg!aitfLj=Q!Q_KyG1wB!QC)1;#8pR5zngjM!K-m#_FVhi9HmDurErnlB>_-K?dG=*O{n)sqpBwes3TWKfz;g7)tQ#i +z8GGPNHS|1iO`{c9=U#e}tnX-%eZCcM1z&x)$cXP9%mNg!%^}~jB!S5qgaWsC8FFnL +z&%)?3;jQ@mOL6at#e0_9XCkHOq6=eIXU0{5S;!+vE=S<;V?uINWRv{N!92Jejc3UU +zkybSc?`i5~Sy~8S;Js(u&4*gt1&eQ2JL+dJZwJmzj>~kuH^R3^4UU~BufC$mOWga# +z_6<55#>u6A3V4JrN-8YXc}y&Z=}1L_T{d$wwtljWb^OWe;D@8zpjFIstzA(L9kZt4 +zp(|1e341#ctc6xC;+JXRwAJTxd0lceEn+aDb*!1U4dF>Az4SY(d|Dbg1ZwN884(@Q +z_wq%{LHxAyJ#!&S4vx>E2nt_%dYtvZDr8jB`Mva+X32=U +zAScsZpYA_(fVdN-(D=*j-;QWUDbD&RkM#m +zyiIVmo+|ft0+nz&SCA=lP>DDmIXb(Ku!Y%H=Xdf5Wbz+jSCS;zZo{s`Q6!ff#QPt~ +zp_hMIj^5ZE@w>CKG=P9a0le93moa+w?$7HVjB*V_)8MAb6v@>GG-uAH`S&In!FAxv +zBRh|_Nh}_K-&9jv5#Z^oa{=cq^gp5A{?8SxS=c3yDEm^8D^+XXhRp6qFzW% +zXUW*eu4aLxkTHs-4SWCMAiNs4sP`$)Gdd-BL@NAy@&C$uA6cbL;05y2o=4yqz_E0> +zfEM)jim*>%)t5WA_Zp)Cp^$!A19O+o;N3CXcI9$(l{ZwM(IdH7ocr*~&OLigI-2TjB9rH=BkeFGI+Y`XdX;v*4Ux9bZdSbY9nc|=R?%d|hUl32Q9w5dv +zOg~SHoO6^<5$T~t1tQT1yu3?(&+pnwiv7Ew#Erx=GLul8_IdQe7yWO2l~+=&ktu^< +zud%PA-*AJ_MtaQ1?fo)zk=CSE=w2kp74T`gW7YQ-ZJvEPw=4lOR9WA5c|@bAx9aGn +zQzjZ5k68ZFOz7xs&5@eixp-3`M?t5Z<7eN7yc +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 +zL(7~rOGts9ynd?6vr=>%ysD{ld*qAQ5 +zA;NGRsdLTrA@-sf!fC4S8sh4kG>X&L4V1oA?{ +zi$B{+xCa?8GC1`3+xTVSCqBcWBNZOus{QH~tSK*1A6tC2h(y1D7m=O^y?5?t1U=E5 +zp>M)Mua@hp?p7-|ayGuJna6V1QN +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 +zRq*kxj5SU4Jw%b=3Um28 +zYq<|_Uv>YEGxG|eL%zE37D86WcMhes9C89I(Lb-4S#bgyp-PHa3@yI#h@5g55FG;bFyD+@c$K#EGryQm8g|Q?r?E{`ZaD}O_u&+Q<*L@`_$4I{| +zFv`s}z6k#J;m`T|!uRcuM3OS0&u*WHk@&k&uQURzZgiqyGMWpZb(}aH<232o)oxny +z*jf=m-4oGedylC-osS~?;E^9EICy6dF>5@g^x4-&t-B~Zs2ae|)LY-dOSAcMV5eSg +zx%$Mpk=M+~cM|`&8ccfC$0Y32fWjdIBOWSYZs!XlgL>0ru+#}o$2jSI9rvlei%4eV +z<2@eLZ>!o3e8PARAnei2x7Ov>m1CRwmCKP3uj9wYBx4@ExqVg{x|Z%e*!L`)dNAwf +zVWFzC*(t_ZZ`BfQj9Bc?N_`xB|@)4rOxt|do+7}x6u(uvpZR*6Ow``U+q?LpGi>zlcEWKDjPqIBh +z@-?i~+bOVoUDYqJkk#@l|8Oh21D8Lm42k;sFqm5@0M5NYpiioninB;VbX%T2EwFvH +zza#C7b;|+8sh&IMzE4*>jd-ddf;_~9x)-{c)x8*dv +zEyO6UU!0_zY^p`WiP-Azb@y!LmHZw}3hfnaz4wWbLI0xJ9ICM7HqDoZHE^0bOd$`z +zy+4-$0*|75HEznm3)3ra34aH(?NC7R6Xq(~T5<4Kq$GJuS81*%!efYf{g#m9@T0~y +z`$bC3D4o+f!tZa+mC6CQ@<^u=BJ}cc1Iwhn_E;|ZgIJzaB0Mbh{+_e=65}f?h7X$K +zj6n(q#os01&#PbC*_`eeipn9*3+#RRXis9^H8mnEccVKzrn^3ClW@p}&bdT#9iKp2 +z3+MZ}cYrmK +z00MWsvBq*}6Yi6)R95oY^>QWQay4o>I|*AJ7ZtPU~jw_jDFnQIr82|t`pxrcE-35rH+MB7i*rv16ZU}EB;R%aDqXO8KWA(sGkF>gqP$q +zxX{@w_})u4@uR5Pg5ivfA;MMq`y(0S2H6c{%VANH`1CnzJW!0+iz&g9|!Bkg@BswzZ%+W7i +zHd>ak&kdg0a07?wG8Met-7Z`{hKgIU(^ +z;qz7y;_N(%UDPob6f1=80%4n9coNDCLA|B)ePjgA(A_@q_Q3_z(+!vR<{-rJuOU_@ +zoho+tb3qrra7~@*p7D8hx#|( +z`XOC1UnB&VobcSISTKlncRy!Fe5Bq%Hy!p1QF3b9(faI>w$smEBKc~R- +zne!lanzkQjILGZN@$V)bjvW+E(SYLucmigFkT3cH0rhJFh;O791wp^g-C@#WPlEts +zl%}MitvU>T&vsexny;Zx8$I+nz3cGJRU=dqueL^~&GiV)aMuWlV*;R46f1<(LfHqf$%52hvwYUM(!- +zr-SXSH8^yv62Xo>5Xpe{4hZ>NlMdnF>csF)Xx+jndLPmCc^y9$i^InQm7@H!Q{>LX +z%F>gP`}vVb9GZP~*5@I4x#(TS$JO~FEap05;^T6sZdsCh=GEX^gOA7_l1xnNle2)A +z2%vb3#yvUjFn)P?^c|DjZMG91%D$!29=hPL->D0Jzrw%DKs`pT{%EB#6#{yJR?JS( +zm$@oHYJOIY-%l$EiB+rhGOdPF@+TF+atD%*j9p!vS0MXYrt +zm(SiOA6Z7^3MRTZua&#COoP(l5R&VwVr-@C|?Vz2`kmSs=9X-#j32L +z=BZ|K^PTD4`Ojn~^57ge*03z$ck9hV86QV}wCmD$jc~=1XAb76jhG^5nL1o|C(osT +zo1vUuaW>hGJ{^JpP88yS?Z<-%)fJK@7w?6m@pK8}Y_(__oFAr^yc)b+pdn +zU_{?o)he~Ox^DFx*UzKb;_ZSh1d_n|OoLc4cj&xIWNo7R_@FgL_CD}Aw>NvF6{)%- +z{T_(9y4!PM-h`PQ82_Sai2<3vMl0p6C-Xy`(T)xh5q1E5YU6QoiF=v}NiKA%s`{H@ +z2Vn@S$jcMe>k*qzLB4u~b{q1G+`nwSZ?08)r6X=E!U;S;f;40sL<^5X=*x%d15vg>)p7a~4-Y6Ow +z{y-3})cO1-xW^723`0-E`=tBo@wAag#_Y)jP%od)vY~Vie(pm8O7Rf$2}3s9&r|5Q1)J!Kx48dY8@c4EtQ5lIvhlJc +z8NFWXoWQ+FNgJY*F{L6fdD%-*FnYVnBFH| +z95oIZyKNK>Zd~+>Q+A$cNaITw0q}G+>07tA=H+>RK|aHqsc8n;h=oMIegE- +zN$4K?HoGrvlYyBPSnE?V>=TOL_o=%H2uC0z@Eiv5Q)Rg>55-cF5oI+7&Z(zF!LLn4 +zynC^jnnapw#q6JofnysIho2ZX_r5sITJ%=qd~?E(7H;h~pP1?~x!t{@6#aFM@Ubp0 +zck(ELv#h#vR0{Hu#7OIz7egs0DPlsyA2E|ozsKM=j|9P$rE|8lnD_QPC44||nZOQR +zne6etQR68Oq32e~{dqKo+2x~8xWBZXz;UVFA1dYL?IIz@U@xMZaFpK#n#y7E0ig4$ +z3IG+$Xxv%2QD^Uvd+mHo@MsKs^A)Jf@{=#;OdL4)zQn5ubs+W!>ia&(OgdZvk>^-Lz{0Jp+>;NjMnR_OJh`c +z>-#j-%5=x|kq*zhPv%F^FDqaFrXu9Z0i%+BV(yh?BslerXWLUOPiSt`XBDB3kG>90 +z@rmARn$>3b4IS~bfw%YaD(FFv3D~{fClG~hy3O20j#B{2cgT()i#{5COAQHk!XH{b +zyr=ibH?ds4CbocAS@v_4+#FL8MN~WWXp;%FZd_m;i89p3y6W7q?=rsD +zs~VXM@FpB!MIgZ3QayP|0OH6E9Doha8*Oc}Cdm@B-`LnQSNi?$m)b1*B`Lq{fm9D~ +zXo?J!*|VdgI%wPS{&U9X3Z#U_Z8I^dlku?V0$Z!0$zVk5)n)+(V89#Sx6(Ttx$~XH +zoz>I+>Su`Fig30I1Q#7m4w;KYG#_(?R1J6vmqrSGNu-P_p%JoQW%b%LFOtm~i^VQY +zd0asmNTpZcg0#5<+o(_J*ne=4{f#yfDA1bakyI +z*ZRr~4o{rnZy*nx&*jC*4fWfQ-GO=;O5;G|IhYI^Z12AM6hX)TN7N2==iLQ{_bLmP +zrV->i5_%A&6~>3U6=hk(hIAJq0G&I_IF$W2^Ri0f8PJ3@*5Fp!DsW +z&Ep+);8Vn}?zrWomrKV$h`&-Bs<=;2nd~5#P0GN!iXT=wVQ%@&#h*$Nn@6FlY@m9J +zrqRyUQHwb?c=E)#k=rJ&3NABWfihVpv2q&ZM-~RvuYQ^8hs1yfxF7c5Rwv9_#l1W) +zlIIAgJyqXBGMjV`+8iJHre0&)V-=1f(`<~4!!7nrp;K;gUO#E32$i+kPaZ+E^5zp3 +zVeG~0w&$s02cpv$9erOpwms!-timU}ykK&Od_!FFti0SFPIcKRlFdpM4mm#QxMWqr +zg6BI-0eXb_;bNrYp(Y%;=45dKFFkdq$(KEz*o*VIJMEr+B#F*cn$A(IbBHbJm09?v8BfnFUunF2 +z9sn{wdA#w`2vyBzoqYtaJ_(Qc4FuLB!t_MeU?86oLOjVX2_$wjD2$(MZM{Z0k|ILv +zM{m`XB$~7wvG2UXYM|5d*RP*J!xXTjcNwclFZ!e%lGB3cWv&}V9iPdIWB51c&HFB1 +z)eympjrxQ(7JsUlT%w*}sL7*xnw4JSl;({0t_F^UF)~}>{f6=K8qVP5+ybX7D(l&o +ztY=(GV=_QFJO3;OPJVDAE}_3i9o4OTE`2U^PgzR}S75&NcnGqNDsc1PEW*j=3&%etsH9IkaGk$Y`-yR +zae4uWUDHP7bEG=q;kOx{BG|JrdvC!O$XiKRx5U3mt=H)~{95dS)(!+*z2jIX?`;dg +zimfMKs;=4)!I;Q31%H*C&bN!WTFX0LRk<3c^2LnC^h>pHJqi|S)r>VRw!IMGm&)h7 +zSBd04Qxszwd9O6Iv7FM48!Sk~A>5gEq8}O?Xc7l!4kKOSoIYYJ^^z0Mklhm^VZj$) +zTH2?|#&tGAfaZo;R)9~3#g+GT(zZIL`%WFHCrUNdQ;aNjl5{wz_%i(#CLRzI1T> +z>HG&tI`=kQq@xrQyI5b8s9UE;@FD4vScwotud`m6BN%~ChC@apE#9fU#@PGTXCNr;~FPEQegA0EJ{5VVK$~{ +zfz&GRclvEoPN$nCI+rz{F%P!e^K=;n^%K^OZ +z&NQ$^eMb=qg^{;_?q%+SN&OA5QPqyr(&af2@5YVmQe^*K4F2}vjcT}lztbS;&h9TG +z)r<2d6r>aLh=rX78Q^B8F@pE6b>_Z~=XrVkrcCc)tvaI8za6Rd(wqGlUFlqsq4L;Gptt&>x@ov_p27B5yaEY4fYDY +zUy-XX8A)<)khBbP +zx~SW<9*eE!Ue*k+EeV3rx4?X%N=XNn53<26%er_(znN-t2q84Gv-1J5!^Gsq_#}My&K*nc*D|Bz5%0g +z*daS+_$m*cmu2!h*=j;@d2!$boV{@yeamdm)dcZPVa +zHavWqc*OV|k5~Tb^m}^&vIv)T9#6pzvFNdv96z_T{myacw9f?3Ir!dH%2}wG0S~O; +z?ysO_3fPne^5OEM<+pp +z77*--34vGh?o|ScM_#bUGYTIfrTCynrhT1Q8IbQuOGz1bU%9eLNT1;6>rd4qBpJzzsWb620=9hIV&gLb4O +zeGz)|y~~D%N*Xe|+ww`umZ%Q%>motBbqqceAoTK6OA$g{$3(AGp75-5^`y6U@45Cl +zsNh-ab~+JAx!)J~Q82nG4w<)?yF-@(g})EB8d(n9_QY*m$A`0IC}Exk20;c2N3E75 +z3}W=L&^NyvcB5Y`8(yo_P`u6eiEya`^a~*&_#Ld{?i$hQ%#g^(H_=BA`-2r-VMOy9 +zD=g+grk$8?3OL?SEM)+se-#9H2$8lkl6gF(+1sqwpCUL{Nd?@cIT+w+k>kPhbF*c{ +zZ~Kecw`7mk6GR<3-&XgG1GbUBLdHT^(ni*cBo=C`k>4l+yRrS4tc$K{4_rjxL=g~J +zpCvj@$Dd{nt@(~`w8!U>u%;hdVcF1OYwW4H=Arj!;5x7r_^*ldsdESveD78k@Pv7f +z3V*HTQxZvs0WP~ah2fL^Tw-l;jMxddUb?n1(@P8^nrS)v4S?`?&Uc6YPoImA@o38dJwHkAEdsJ1KV$Yai^WqM_pxkE`oyJ_;$!`{T64B)pof8 +z2tFp7uT|TdZk#K*$|yJdCZ$--VCi-+EvL&P*)8CS6gw$@_7fQWxq%FLsrNEHX!I5{ +zRWCj^EdEHP@@ejufV1#BL8c`MQ%L@5J_$t)_~M~0C6>XQv52(lqhl$igIy2CKGU|M +z_0wU$c{H)tW@y?dIId5@&(DNiXOtp3P1Zu*-+HSmxNu(XWuT{#!+;1Rc530l#pr#Q +z@{~%G9z@cD`1Wfr7>-b*TEe5&i~iW0gpQ94!I5vX>t5IUeWjoCZK9nEV8;|~lr-gK +ztu;Sc^->}pkPsg@+fN1EiQ&dI#~b@3)>QN>ncubo;!Zg~20@m0WeN$V0!KWE>a!7I +zjG8MC8pDWgK$Duc)C+tC)oZ=!^iNC3tB#%uO%~_gC$G_A>uZQ+f=9^0`ZBpgThL0} +zcuEv4WY1#7Jse#L5rEJF%+ff=((*U+0}qZeIvqG?#Q?ehTT~ly%wk;5k;8gEcY#aE +zI`|D*#nYh~oQDTVF28yMUMGU?sp#uxfQ{_|`IXSbV7{OK6AmLt^>AG^cp{B^D5}i) +z>_Mf*_qVxfo*nXU#4GU_z&+;$CSQDI@yRkNZU>NFGb9b-bvURDJ-!t$TyiDwaeVEm +zzI**rs_Y{Zn-lkCgBhb2I{Y2PJyMM{b??w{6?nw&o3e6;NRw~f^#{_okl=o2c5KJe +zubqiJCv}EdkxY4O8&%)iO5}@YuYbooFW3@=$9EohO=g9V&cU{=gyT+nAs(*Ho+_3F +z6DCm-ES~{Hxld;gjONkz-)X?G3GsKB;Q&o}gMEj{;rh+Cv)WE@)dYwty2xlARd9ZG +zQ3pg0+ylsq$#g-UfYK49sQGAj*kPl_#v* +zqpJtbF;sn}orZcDf_ninGblzl^zOl_SI&~}0JLBKwu+WxgC$;E*A_g0;d0v?i8E-2 +zy@8`P&|cD$YNpCIiTcdYzajD2=gyK{Sk}6T4p2pW_}djm?|LQo$hq0OWa)W&?P{KL +zwTka1Ly}{EAG<)3^#!J0xn1oP_$2!}6EAOA^2Ft+*L~mIVHDE1B({ +zbP}lLfv`OO;N}SI=fR7$XeO>hMXzw11=$_(UBOxF5DlWM3IX^MZQ{wHQ)HYK#x$TlX7?a-Vm-EF!xyT?f0+5!FOS^ +z1<$NaIzONi-zVfP#r?{Qp0X!BTQB?Rgn?sMcAxO+o-X0SXrG&jR$k7o;!wPJKqQZ(Tl0 +zzZ;d+Bi +z?!w9s$Fq}gazg+HEtkxL5=HN^Z*Hwb5CGZTyXVZg_I`apE)<``*nDz~B>Ee>GdFN6 +z;Ik{H)1yPTwKNy?<*@J6AKrP;-~L%TwH`Jzbf@jCaSj>$x}T4(G|@gCnld2Sc*bM= +zIMid%xiKu7rqGy@Xc(?s*ww7jVkbgO-t`EwUGpNl5_!xlFAQB9hVz;9?w6S?-*Q7@5d{uXf21=Yd>Ld99^Rb1nI~|BZz==IwC=0NtH@^-&F4E^%20Hk{8G-_ +zR*OFV3a(Gm>UYXOXueU8A$CPDz3_gMlOU8!5Eq+wrT8q4`3p;E{YE<^MqeB~#_Vqy +zv9sLc-+6I05IBkDsl$#>&6ga6uP@Z~9N!@YDPW7!tID>o;+nyL$xSmTRI-(uv*Hht +zpcqTO4e8bQ{%t4B4UTptUetO^52NDq-fGX}OX1wKHU6G*MP9gbMHbIy+98IWrxfC? +zjA8}#C&2m|Hdb9l=N4ijpMy0|!3DLV8oa!`{k?p;>>{)-{rOT5806FqI{uyUZco{( +zOK}hJXQ1)r5Zks34rhZfKljs

%y|=lM+9bx#X7Na5GWAL^|x9M}^ +z#;Z}xpTCQI{i!9GQx8V* +z1`*AB3UwbDCnCN&acLc^K?keq{wC-=O=xi0Y>g3IH-w((wLCfy51ZCe~VW+ON +z5vm)x;LM+SD5H^{d$lt0!Bj?RmxLPo(Sk!UrzU_N)=sFy!+_>o4$!!y3$v*mdHC@& +z?>>E2a_=|t;Yd9;U2m1?S-^7}7jWZ#RrEp0qV)A*7dTCM^2@3-hn;G(Ai%t}u1 +z9Bp3zCLt>$8|Iniau47`g_=%=6k_IuX>qAc=yEu`pz*pBZL~DEv`6n;R__AZ&sI)f +zKsCt$hR`M*XLuNQAIdKOtn#w@2rWqYO$fU0j|}C`dtl%j#{KwWN6*w-i{~7;_dST- +zjnBlt>pZ52IoqnP`bwkmtz*|_4K8Ew(=S@ZD&yq6)gu+6CZ0_3IuZg=Bkya&EW|>eJc*zz#fEtwvo9{@>8 +zen4dS9ksD)ZA!4Uxp~JSC=#b{2qrcl*&!-g%iW{#4f=3(A*wNc=qL)d@NW}JC64zV +zKX-A9C64QeIe@1{)_IwqOuzyl&TlrB*b9L6+QV?a&Oy50na}MAxxAxLU30vijA`t2 +z1~^yPDk{IZsPwh_y!W2KobwjU!krWdk(h68Yxs33^77?yT)jRk>QI70l<4gAmSY37 +zNP|AqOFna6HaSI5FFQ4Y#FeYEoViPv!4!zUuinW)zP@g(^>z80ac;ntv~88!qs?ri +zUbDTu#e4CTCEQM2N<{&#)Rn#O&70fK`V|~Nt$<1nN!ufPZYM2eDnB(8{GFqHKQK&S +z{#4-g_khu4Z{t^(RIGOHC|uv$h4s*!Xc$KcF34s5N*@k~-dnNz6tsWc_M@wnbd5{` +zPVQr~_B5s*`g#?Tp9ZBm=dBr%lP~r;O$9{+0paS6oFKpc>32zq!6g!oQA;xsSWrw?#NV +z4$yPkKSAj#9DQxe1)8O%|&yMp%m!jZdB&RILHS9*z=WD_S_aqJ643B +zHQ_Ft#RgAIxO%#-1@bE;A-x%3fLYPKf%hnJz4d!1>T|}Fw9i-a@hB+V2JHhk9;`a+ +zvHNY?tjv5JZ*StKtA=oG>jU +zu)_pR4Ty@a)h~(N!FzHezbT{FO|)#^m4w`|cS4WOdb(Gb)o2c8LYx*OG{6^fX1%zXTDS0=9Z6@i9q51aW +zzn%bH)q-U1@6(QYU(Wn|hcDPSTzgf!(_^CK_=|NnrOKmM%#NZr3B1R{2ANBIR94$X +z8#v;K3_tMX$NvS}M4YUhC!bWwIVFR1xOn$z9E*6j2u|k^U-4`rYx7+9JymK*d|%{P +z*`?J(9it2y^ht3tw6Gr9P^%NnGCM{V1R?foMM~{=o7WSd_h}`Rcg;W7M_h2-IuO8N +zC2-SNsRmg6Mc7gIy1>XOOAjj0KL2i;x!l9XU|ks%^wD`e7Kf93$}N>3>^)407?C`^ +zL2IhAsn!&7WBGq7YfHFT?{4+WqCBi)4S1#tOV)@dBA +zGd|i__jBiq%Isr+QR0urDPNq6Tza`$AT!O3{3yvOR_)?r)ECt?{DutrId=r-NY98- +zJW6zcv(B;o8Sk|zN+Y~K;=KWPZ@p!(A%|XczV}JqY3uWK?!z~bP)!zI&I<|`(y7Uf +zL$7-4eexKsGJ;}tT5^THbZ+nF@H(K%P8~TnyfSWGy%py%Y`awC6|p@q$ub_!VE}aH +z;$!K{y5L@B+7lQll_71uXX~ZvC9Gm#Bzn=ltpVIf7XLX$zBR-KYR5vYlIjEf7zPo9^v(vxrlEe +z6Q=pn@dhCL+M@4y@1cYR`nNVkb~M;plsRuylr1 +zF5t;~lX}IEFv{Xu;#0vrkkt=vDw=aE_Bi2PwDiF|+(d%l=F}mCO`J3IkW|jO+6C5GW +z)0x$NKs@(1lbd`uK=9s6otU{%G*2Q>`b7$O@%t1m4BjMq%Rb%(4p`QOGjaERW6Pv3 +zfaVK2yqOV+t%#4;9xF3_-gH_#Ew=RCVFq6DL$>UedlZ9v1Y`tYlAIZ~MHoBS)XK(mn1J +zv~?X;R>9h>iWVJ(R`lfB{5qJxt>p*W8hI3 +zbnC9~d^~^Zfi!-xj>rWUo(l-Q-nmRFV!B8w;<}WJ^nM} +zTcLsPU+12~^0bY@ESzs-BuMj9$K6Q;J2Cat{~2`(fc>~R(t~ys_(0z?HwSf>4r!MP +z+oc1KoA*5hdnnToI{qMZ8yahFpLZPe&(Pof^1-`~4 +zIj;`WS2&V-_?ped>1sHyGO5-p~|LBm6SIRMC)<@-P!Djmw#YlYYLp6%znQf +z2TC86<~OQb?(1(&pR2v+eqWM!ch4U6n)9@cVz6maoRq}v(P2Jb +zBS?n?l`K8XsA`*KNj1M-eb7f>hq~-ht3e%_N@c=_@m!AB1ZvjPNCwLHsSo0Iu*EBVd +z`QZJI!&lImN7^N-{LQ00C$8MLV2}5!P^!58ork`KDSd-5599i0ZW?G$(-vQcOqOjv5o

8Q3jr6~N?C^+roX|I4W|h1XIZe(S09C3pY(SFv7cX4zXzJuthIbijs$)! +z-d7$~MrmsD`dL|^RO!gVBW#L1A$||^3Vo;i-(}#5@W}LC6@I)t-jVqmelwV@DOp|D +z8A7Cp0ov}XU&pf#tqFVZ?1$C!V~} +zs*OjCbLUlz%4)uVcF$tY@r1P$D>`=P0$}RgX*9wi6$kY(d9T_y=_t+dCm&AjWf@v1 +z1&1ypLszfzQ>ITj&D7_haBXY{zjL+;r;dn8M)|?K_bq0ivuW3c{K#Jr2q=NNBXxSaqtJkuxqq7wS|mFwar*0>3^#Ag8RS8rZ+S^z`m +z{`O6w8l9@Op;iyhoHb@laQg=D#qBCmDHJ_;Z#-pE#~~{W#|@)t+(vHGTlocX#r*h% +zaCMgp5HFWiW=xP=D#0heVV2{qaJ%6SdR|%R$A5DxJ^YY7r3p1X@1LJ#dsSYydCV`k +zY$b_YWJz=Co9P<2mdh_sGCSsllRiFI&0iR;U1Qgm@`{}&#pgn6P$qqahx3E58mQ-5b@r +z$vHS8IMy}|$E?8_`8$Zxh3#YJdLR#Q$ae1Oy?HKJ3!w=JgC-1O1Q@)C>Kx^<|0ocD +zZb)%6v5~O6@I)gNuhHAH*b3f;0f_ +z3$=dBygbhoPH5(6K*L;N{EX8-Yi}e0KKp&Y_)gL0%|&4dUp;pqWx|)9{D!)waSZLV +zqk6%;-+4B>WPzN$HzXyQwk+bpkt#96n7e^5`#%*}JcG&6!{`(%1V_Tc5!0s7NKMa6 +z6VChe{u#<^$mJ9VbPk*8a?1tGbZ!cLs}SMyPjQgUuNTo`K}Ek4d!B6He&)f4Noqnz +z`K9SQ1yIRt`WT|GXo=hHq0sa7gMmG24zC-OJ2=#>!0m52cinm-Mf0B}0?qEDVe#X# +zcdO~5oIHE@5PD__uvy!y3(SXJuA +ztbb?oj)p@Roq!h;1DC-`Yu@ec=N!rTgiV`ynT1v0d%$0NA8Zx$Lyvgea83i&+AE0r +zkQE?>l}bHI84oeb>BweRJ`(+&?y;9AFlS4$_{_?^XMq;*X3#tWStoMx&o4TU0%s7g +z&?wzz10#V0yNX4eXRdiKjeU+VTHm*k2EZA0eT$A#>8?Xuusgpo>)#}Vz6N2A=yH}X +zdYzg{uM00M6OjtGx-Su55U4Y*QgQCg0WtAmz(;IQA{88;v!vhLi?-^=OPYuMW#Oyq +z)_Jx~7I31nFe%SX731>ZJ~n%G(Dq|T793^w;C54c2^vq({czGdQyZUHQ^=4RzjBD1 +zrf&E`;6?eWKX@Mp^sP({F^HVp0u92h6W^~rC16I^YM%zfIm+b!BkW3&EXh^il|al( +z5ODt^eN()@%(hzeqRpx*BNYtpA#hLKOW&t$LA!LXI9|U#*@;(0N7QQ(d{vLzmTEG{ +z6oE~r5M1=G^Qm%r`@@#Ed|q`5Sz&NpHwlt8BfWNACi5cb!VBb96LS6!4iSG|P2)pt +z-yZI!WTOr4Vowe@_k4TDVGXGdmG_PlSM=t^956LLFT0PL;JL3;JdT+xk_)e1Y1Rhk +zokXA{`UcaPUDBL&%X#Uw(DUl4)Y;l|4B*^(^qi>51}~2Qh}AZJ=G{csZdYhz#2o+R +zk5(X&3-lA^5`gIVd^T$0915|MrpGcboUHMsp<*LOThit}0@C<6yV$oCzInE +zHb=$IC&C?@hacRcp$BC6(}4E!&&_hKYC6E9Te^h1y`N_6jVu3b5|eVE>`ubxNV%B9 +zZ6nuVLXhEMU58d*b_W|^@Px)!=A6X@$VM<;IUxyQ-+!jj?zWDPI6cg6Mfjw+DA%pLVc^7;I6qz_0c9Qj*@57pVKTQ_}nAQsdiee%xTTkMbTA1gX;9DtAitR#V-f_ti{ +z?6u!h{Xm-x-V1gW2eUsRZK+SQ;Kt`=c&Az~o(AY>qAQ&jKWQk0BiV;7yyy5QMYoxH +z=jI8yjdX-bZGmrIJFnTpj@v=T_Yi$Ma%p==PixtQ2rJk7?d=>s2>ohIPuVp|nu=4y +zD9ZxhnP=j@2+Qa^<0ZD|5=O*2-t;^tNYxpM`cdnxxpK~p^Uc-P2-*+qO%3r3y%ffmN<1- +z&*Z#{d0%$_)g%J`-i!8zeeXVXKG{qKpHw@;{@T_FrZ#lDcNcs)7{9yuk%t%_QplE> +zsyPLye2QIf?xV5i8m;)n;dwN&(*cDzddKJVV`@71fq)SDjEFx&;{wQ5crj&}+nF~C +zR+VxzvseV9VTA%y7$13O3m_h&)NBXIAqj`jTrgjxAOhrvf|a@r*U2@$i_?7c$tG|d +z2ajJg)V`E=hrqec0UY4F4xoxQa~De)*f^zG?!H)l_~sMDY7nV_@HqGz=|A|XLHYqo +z=cCvMpbgomjop{{7^9YY=>42$MD`GVO3Amb>j0x9-l5gwF%t>?>%#kE@sMlsfEC!-BsAb)aZUkqkDJ@CfHho`zcDiX}}Q<`D_w<?eHkx%tx710XtKLrik-MLS~;W`(>ASvcg`lx)1+**dphlpj54 +z&<#iZ=xW?=2K9CQ_zW-?`5IkaM4pzBHPN5ifaRHczl-F$l@WA#@MgC5E589=qJs?l +zXoiC_Cilx9_J>bif3TKMXSQ~t>(J0`t~pe`>3o9#F~nO;+}~^RUZzjCJCW|ZAiu<( +zat6Rulo$Fs2Z*NvBH80q0c>9UkifT+(NQw*!Ga+nl&W~!@~k*o%{PAWehr0vY{ot5 +zp#;ebEGO@yEb}_2%)u9AKSy=*3a6Sy?ZF0TBjMc2eq<@?&B(aGHjtKGVgB +zeq;q6l)aw9v;xyQbwMO;AK-^iF00AQW;z +zd+`t>xSl!4=-~Go&azUtd5>0w^Fv_qep}L6bKs*_*d{owz!xxYecv+u$Rl06av%dx +z_iTBspvp9!Z-vcp==#jmVohDAWh3O+eC@d{ +zbcgQ|y@5vPde2eR*gaw)uW+Q}g?WGPpBLAs3oU~`JrB%yFH)RV(I^6soa0(oAbgOt +zk71~W<%~m6+#56B{nXGw{}{VE?voW~+KAc^}irM`1T +zttZ4<KCq47V>xf3|Rayb4Ps3dBRyF-F^g7C*yIIarblTJmhz_CW@Bs*7OXXn8(KW!KFN4 +zd*jm>n6fi{AA-A&e4`M58bFjO0(JfFde5UThH@7Dr8z2g!rlN0M#Tjx*o}?pW?WL} +zGGZ%u9C8OgWiInH`z{n7ww#9;yIJYJzNsUh8AF`<#F$_E4%e3?gkeNfJN0GsH-x2R +zU}bZG&d|zzoJJE)kQ357I{i2npXIyy%3C7mz&ku4ha+)d2@NPvLrIrp;iS(y4(37O +zIFs-~=jx$21s3ueTC8QM=M9abg3x>L?x2MeRmzr&nc!tZ+8f7<^-z}t-C*%d`b1?& +zg9hxI^aZieThBa+Cf<87%x_Nfn5El_R>zk(DQu@8Nd +z%t(TC&bj9_g;j?r$s;uEskQ-wWt6$MY5gGD0;;OmM=}sV3cXX87+WV`FWxSCEEe`v +z$0qg@JOWrsFLMXk81|G)j+}@G!U;cRzm0(WY +zn^i0@+{_u({t5XP@WdX6JPBdvGsGgn09{!+J@&AjjW2K?)5rJDH`sQ%y!0VaW8gHh +zL-~CTm4jfZoeB%rW-~*m%RnhSUpC3ebVpFU0+6U@heni7IEC!(%<)Yd%K*pn`QGM4 +z3=<7BGrcx^CWeU2Ck^8RF`vbe$3iMOV@XRJ&(%3qU{oTaE7Bl1@A(!RNg_x*UagvhBOlbJEfG3y>^I>wKo9<>N6zs;y9>xDdJylcw9z_S=j$S;E_+F)sonLXkvha-fMYhR +zu|QiTdVNm9jZcgMw^KRFUJKK!_H887xk`l;h}VH$)b?^&eqQ9)#7jy-$(t>rtu~^E;P3-qhrtmjx=UWnnFb9|RI1(W1f> +z4J|md6j_!fdp=jn2X?e>7zI^O-9Wj85|dbM3CYN}URdL+oU6V9{b^0dYY;ppu-0%k +zQ@r+{0vrZ<69v@-tywSIYw+;?+Z%lIN*}8DbmjTZcU1#&vdC_zjaahj=Ap|?7ZolW +z8Q#jiV9DMO;lV)p9WNrgdG(C(Ae8#mtxw&Zj*m`lS@#vfSIb_n+8q=sUj_i1{v@&a^F?dv0eD#b!JEQ} +zY_ZjQ_^jPB`)G55HoUA5&3?oH=9@g0AQutS!fVN-ULT`a4uep7jU|pH> +zyta+daG2UOLfn!+RV1>JgNM*<^AGLWry6D;JSLw&PHna~-sY +z->l}kNZQSxg~aU+I1Xp(J8qPFPp-1&tdcrs6-8BeexjUZYI#46*4wLu4FXVCv9F)A +z=L)wy26W?mU*`xRKXD^tf6!b+dF!D8irY=erxcJVYLu%wxo8bM!T`29MH-20Wr$Y3 +zRl%^)n+Ltm>&|94cjs6gl~3V4Z}i7AbB}%Y--P~xEjjFt*&(`lIRjbeH{TSbc2b0r +zz7IDKKb39JzTZM|D{!T5dUSEip38pafV^0lsqDWt9mZ{BKej+)B%GCo=6duwmQ +z47^|;4SOLXVHaxOZ~lt<_tC}yPL2=7J$e*(drll^dQ4S$Zim +z>E+x~T5m`_9OH&3&oSJa`$49$62$tawrhUc*KxV59tv~!4Y2bWTg9jQ;4$a12(W+% +ziTen|E+AY*@WX4#kxe%rU;>W`$~G{$7^*;&B{Ff8z7?ew4W<_L9dNaC@Dr8cGEUl8 +z5}6-jB&0ksTS;pB*a}mZC&95P?i4a)io5S9aZ1b&4US%;3-&0dmbxF$y!zRH$eweS +zue`=}Coxm$G2j>J?j0#L_a3FPTMGazWFGi^o-w=U93J^>vHINV%irZ5Ko1NMXmLc+ +zJ4hip#_$amHwQf+&-%Kr5%cYfSoG)v#Upc@?;mnA;N4cLc|m;YK~*`rC8x8y80XU) +zN6mZEq8=LijquFz!-L&W_XN|%p&${+)V?N*H%w%tef@<=*F8w#@W@`o=Zvb&E1KEl +z6S(i^MzSB+qtGUw(4E!1etOpA5N|3Ojl)4kTHwgRGbVEqeh74mu +z!6W<)c!c(Zh||Mj4_XI!e4^H&X$jv-g;`41gV4!*rY{BK(R)^{usES-{%jZg_q8^) +z9$|M9?j;ynH%Wc(>MrpI={0>YOKqd&3cF^gpKk;TUV3_fpE~&%qz&F>^x}s{2eR)& +z_g8ZqL9V+`%{w6_kBu&MSoD}*Q(!=SUZ{p@m0DKz|`@tgBe>RN0k4P@` +zV|x|oYG>NVId?XT^0+zSZ@@FI7%#-5jiml!_= +zJPB>tDV}iZ@g%s%v^VPnDu3USD?7e>Iwj*QlljC(&%Wwi=lUXIvVvZ}a@wW%g3)%> +z9@* +z15uk8*Y3zs`IJ!e42j%#lsE3Q3PTg&HzkFyUb(4{5gYI+QCRijIcHvJ^%cD2WU{fz +za*-$lnpYR?w$y&2-Ge|6+WXpT?Z$|;4cmEW)E*!7hmVC_YLDTAEcH1hp7PIyPW!&o +z@}f*&%5Tr#_eJ=QYdZ5@`}|#-;=If{pA&B)*6nXcmuh^hZowx`r|#(f$j=;egB`mu +z2DDSMFt=}xr>cIv$B3n7vw}YhN1~zUz{L` +z%*P6lZ6HmHvJ5VV^Fn8$glNJgD${W$@rUwI}Sg2kq)seyR{9t1_QHq1=?# +z8?Q-!cE(0fN4p-aCuTFUdvvqGBNMV=2wti8TFAQyx*qwc>SNW{P786U-v9#Cu=_pwX5vP1Q^}0++~cT)qsa!icV~9yO1xL%Rq}9Gpg>aKdf| +zBJ`o2#kTJo!|LU8KOrs$prWL2M0EN=hdLZ4H^e2(gSU0gWjwd94xLF`3P1eeRbH-U +zjh=~YgvYL@GLP-hx7m>*HR +z#vtb>1ohbdiwU&+tgv1|n>quZWL+j2iG5N?ofYSZjR)Pm6Zvd7)nQz^b14iQYNAKPLk(P;$)=*I`xFDIvtzyN@hg%beMPW1J#c +z7cgHUlcUG5-ljXE3$Hl&L~;1cRUe=(+rEKjhoC=;RF-5+1Lftjbmdse2piQ|^~US< +znItzAi`Sf*J(u)Qk*DfWoxGEDZ_tHUzAO4!`J2yu?NfwbJw-k{OAfj6p{BU6;`1iz +zr!H#`vEZ#o#;(hOX2t1mg6ACX6XNziPAr>x&!KX>Noo=MDc@` +z<2bE1A7h5lQ}%tiFpl4L*$4kRDfTP!xRya=jKt1Pr`e*S4qt*J1*Xyb%@&;<9)kWFsowXqJ3XNE%IU0 +zLO<0HyyWKxtqh4yrKrIK*uYonVffbI)M~yLzK?=wPb!PVl~4cKf&eV~)g!^W +z3oxfpQ!fV^GSNfbz3uR2y}n<~fyKMcz@zNN`n})obH%#jb%;tT^RB%3#;nQ%g?jvYPX|{~k7If6b{og|3t$T6w@!)&xb<&o+ +zeFE-r`tFxhFZlxXd6|RGnK3!JKzV!sA~6TAnJgdUq8u&Zz#9eEzikKjEbb@x@~8Kj +zm6dv0r*TC-zvjozu2z_NygHJNsre8a(4z!l%EO;5mqX}K6WU(OT_}sfd(8FI)uENK +zpYz+@b%o~Pwb}-;v6QMKFDO7WB$1C@j^!DPic4@ +z##x*!+3CX7UZ3-Lj;-OshOxA`eC`WCB${wvO2r|6#g-u+%B6hhA0z0*k`fer^-GpPxjsd3PD-aN +ziTf=P%3}uxODRj$HLk|O+WPv&>%t!mb8ULB9oY@*q7O3nA>xn6oJIatuJS{08M_a? +zg;vvMC7cKg9#`!08c#ax=iFERw%%V`?|6NX`oib>D%#hWZ}{HFbFaTjwx7qGkH|W1CRE=OIffb}t~cDiaSbCeWzOU2(c9hRtDob}CrEt; +zBTs@fqy619{=D=)p}}m8CLFLQ^W}~RAopvDqb__y)>|P2YR50sc+U~OpL88z#c)qt +z^&8pCG5nGc?{R_nME6!2+}?>%FFNCrkun$IJTTeO4`FPtrP6!SR8vf% +zO+K66UG0O468CirFCkL_jE9t89>OEncTQfh2l-Ce#*KIo!Ki5BC|duiInJCm)vFQ#E1{S<`oA +zaLLYm!k`B&ud{SW1*qgNqjTrE?^w#qE+@W_SDkQW~FILifvL5B^Bgg +z(y%GzWlgSf6hi%6#zLVap8taQPghZ}S`s;gg-{dw?{B!IzdRi-ob2(7-8oDz?0TTBr}QHc+Ls55w8~3na5)+QGp*j@7>LBP4Z!u +z)3`uhN`3Y`G7=ZjuG`_q4JZuCZsGTp^qd9+cid4`VuUXGNdZ#nNgadUX1{00j6Q80 +z4i4s0cvy|+wEder{V2Pk5eJSe$lN9vIM>eJ8wL@T%h2 +zb>|8^C(MLSwc(Z$9{9Opi3(~TeR(1hg&rys>J?S3LhS6S&Nik;Ps6=6<6H3hl3#}M +zOJYa92@}r4C~=1EQN3_%I(V+09Gmk3kmFC8@vuLyzwNvhrZ1v7&owU$I6OIb#l6(!NKc5twTL!VmpO=L4h4pC#{tD43Y`Z3=D2Q$SlP +zf>#;A%|#mo3Sl()g_@P0e7v+g?u<+DjlLLTv9m9R&gbKJ?BOt=f!!B}uBt4kgLojihsEU0`bOY2r2!OQG@nhV@slSqksj!TR3qIQ0( +zND4L`77_grVLkd~( +z0V3QGyK?7xvl5}n=bHl(&|Ts7U?3e~>xip?Mc<65QJha5H(!nbl_Yoyv#?jqWvLK{ +z9=!88BrRzACsCYrYqjMUF$P57Hi_npyNK^r-Xf*=5x{i|U8kRAPWX;-mE-&P}f+$@Mt(-fhU~ +z<>@25n^(?#oQ7ZhoJE;M+?;rz?fT+9=%4j<3i%1rqzOc*`(lM3k$M#FE{GMhp^oA~C=+f-srR#^5p2K2cPluOZS +zo*PStmn-N7o_GNT>uw+IRTd2W+$kb+9>g$wFHrF~lIB3;QEvpTdKfObPZwO7E;Q`# +zLu4<1JZA@9mpS0njT8G(4Ua1FI}mu!IhPVVeDS+S#^yRsaP2{fOLn&RBtL{|#p(zq +zNUcNJpI@lzIp}GmoJNmDzG|j%?ou!_9iaZr4GK`s=*1&Z-zy-&+@M)NQ?6lGGKp!( +zx)~#JQvrC-h>_lEn4TJ2!{KIa9m!Ok#w6NVND>^hoX$2s+KPo%Z#lVI=T? +zLD6^eh-9yTzlx)L&dES@>pHVL$zq2d3S`m+yg{7X@4NI>ucXkMsGH +zIJ%8&T`_Yln@2!G@!TNoy+Hj5kJbY$YP6`J)q*YisY!BvdqUGIvE(v^C-9Mk+WGc& +z{<+FWXSXgWoxtjIL#%IKQ>D|5b-#t`n^!o_Lt19-SejKCpDQa7%sMy@>SqI#D+dNo +zkv|~xDq~10HK~+Xng%ytfrld^zLj=TL{0eiWw;F7AJcPhu3Q}0+t>NyY#k3|zpAUC +zi!(>=7%Oh7yojuxx`*>2io8^CiZxzqkQM4+$F4cdebvhAj`O|t;vA{Dtqvn8-~=+1 +zIh>9y!xQ8aSAh7=qzRQ>vkP7q-`f(zX((<1uzEk-XG}{?$|z_372u3}TP)^yg0A~w>?o%>D15uFW;NzO*8Z*tMH5|Zasx-4x=EnN^+hySHaKb0lq2!CM~(VG2sHBaIeHpNqOW?-AigYZCpQP(&6&!AC}e5cj^i +zM0mE$A5}0SUbo5g&#wP7c+v0(ojOP+Q>S=V=pr-V0qZFibqXKpj%(PuMEJr!Fv>;-}bR +zE^_pqBsbd0OR0RSC{{?mS)C0txO5&o`6utFJoWH6Ru$`ff{d1~v3>0!O$#*ep6wNa +zzVQ+*1YvK%$yqThx-xde+qJL5biKlg%8UpVCxcdwcc+=lhesw&(KL2gX??00V{Ukd2j%h9&thd%d;L< +zOABxgmeM43dq-n8DY(R^FMyBRw`h}2MI6<2DtmDP4r?h4a(i3>Ext`Vv&Uy1SAT?m +zt{4>QUeHhIK0qaGfsG&hsIYfq1r{3xp?$4tUkVY+aE+{k8elG +zE4~|~7`7wv>ita9*42IOOseRZP8-5aJf3vVW|Y%w=9^S_UW2(@Ij;l+x^7;7KoB?l +zI`(UqDoBGAtHQdVGM=l084~gkJsfF2anN)<@8!G?LlXD}?~;SE7eKk~SnMjQ0MVo7 +zx@8xkR(kH~qajcy9|yynQ&L$jO0KUaq8;QGCn#%~Bk(u}z`Zi_s+uVK=E*Fbxun#| +znA`r^%5;X`(F03ZrR=ia??d6ax4=#4Rk+J_H#(w*z8R1ayH0x@ +z0w{Nm%-ur`sCQq*nog+zc;!ao%8Bh0aTi4r384k8qcwZbpL1`2jI`k +z@n4p6X#~+dLWH1Kl!|X2IOKauM@`1naX#Dp@L+SP&K?Ps(~p+5Lw-tG&BFU}!R>6k +zVnV&+xTxq_I2CHfe^)GN}Qc_QX$=j-i{;8Rp= +z?xSGIV(L+GF~zLTXR{;QYjQ0i^}BL&EJ_juz*=~uAI>LM_`(!#w7AUG^GRS^T&<}* +zq57#Uv^trBV}%>5kL5JZ223>smtx_x +z+CN9vJGyXoK4E2HH*?&h*RFMK10z!zw3420+UQ#+Cgt*%$U#?`iM#RMl0zf6?sYtf +zsl2lp%edP`uMPMELK!1iL*Dm}oFn>u`j>oMtRL&>Mw5#3$SDRpoCq{+!*lNY-IRzW +zAuy->O0R!gl>I;U&K&i(B)Ru~t)l4_#GDb&iz#{V;5lsySwf!B4tnn*&qb<6{ONLJ +z2qd$Ls^7imoEW~J%ot?Cnu%e3)8#Y{dAQ9}W3%aSsl}fn7BD5L9&v@~Zv<4yf$TGv +z4j-COCpz&0GL7T6Xy?!;HxOHPz<|r2xjor^zcOcQ^C`J=1scWp>9nD+ +z9!#w{jf=P$cIt(1O3vq|9pItvFXgD}MWTE1emyS9#Vx$glzATNZ#WQgk+>_06CLTEhbGJjKiAI09N8)oT&+kkJet_v_|d3c9yh@UVoBY@! +z(@a=bhvR%3;q2>g+^SxtCV`5_qQh`{9cbIBu_dap_IW3~Oxl#zc6o&Qc6;RB%u +zPOIr6j3+^P6NveJDpYP?#uAd~ahl#$Z%E3k>_vg;XPE=$@WH@@BQB}K_hDK4MeTjW +zug?+Qx6;L18e>NwUXTUr^n@mO4Djt(UL9cCpsa7=#QtGFhn%43Gw?Fpxv}+-Vl%j^ +zPmyZ-lEgke&!neMKCx`wzMF-Q%0&sTjF27_>CudIh2%pu0P`rDqvbftiH&1*6x_Z; +z5I+7$|JQWsatu3!U!!*3t9652MR}uK6YsfwG=X9vMl=wn>19%o!ByNoKzrih6P6)? +zhSlZymKDK04sr1u$4g?^0^S%E$LCvO_M95E +zq2W|~)9q69f@nTVS0T^7ih_WwUj-fcwjEM1GW)hurj>8ya5)a!IZ)7p!oU?|GNf~N +zQHst9U!oGrb8_x;(aF2@RVUxC3y?BLU|-fcdmKDv#jfz8KW;(qeL2j)2q@sa=Y_qH +z=e}=ok7}HAy%2WW)HACIioRtc^Z4xWQhsHm(%andB;F$mdL($9*wr6ks9HzkJH$yEVO7 +z$M<-A;|=Icy2e40Ty8&c)|?61zcU;Uuy5oBJ+(0i)E`@(e8CZz=hXeWpd);ElJr8a#pj9b1HBQXyH +z_ipRcMn5JH{PDs(&yLHH=x(+8O5#!vVho)aK`PI9UTxzD7wo)@6YED_z|SL=_O)vW +z8C#3VZQLd1>{eWNsX|J-NNZm!Ib1`xomJ6+w$Btamp1N$eo&aB;=L%Twvp5kBx~d1KlHEAU8f=-(<31kX$E~hr +zFw5>@%0#hPhU(!6o;n?U@@TIG&HZ*e8iRA4<8I1f3h1Km{mIO%6R;L=S_@m8ek6mf +zEn6f5^HO;ig6g-->wUG+_L6qPb8dXohqvpAZ1xlT +zXiv&=B1GLTA~=5H;0zCZFdJZC9a-(6mc +zrhS&LKxTQ0Whh~FN7&b1W}5rtrPUL^p;Zw#fJJWWUM)hfc-mp(y2jTe!+Eb%$?>Z* +z>0lH~YEfksIwhYt@F8G+T>M-hV +z*;y$Zwa?P;Q^haao|k>>!7~TGTzM3w_-6H>u~T^FJ-e9|NvuG^#6zA@+G^w4>s +zc%E2X+_-t`%r@Lmx-}wd9eZxSXYC6q)*IikV3fKiA2@O3EY!Swq{Or}_; +zEQMt%{nk;Fwjcgx6oI-yI%{t48rfHdlX8S2zM^a|&ie#r;#XzKuu~q#8T-X;c$`gq +z8w&MV2#o8k1I^IF*v7t?q@~z-alZRwg*w-xZZTYqZ(i!%zL&>1vRX*B*v)T?&N!}| +zEu<{@%8&c7&eg$be7<^m-}iO4r!#stvY+w-V7u&g?!x$!yO&SR%U#|?U~SZLg!w3h +zAh@5?hs&QZ7rP6(`SSkGueB>Dj2<3D!l=rm-}CL6`BvONBzYe=6Svw6MUU~a9Y*uU +z!aDfSdE&c&n<-*1FpzN9?VMmaO~N+!GW9ulzhg%AlOpNVIy_GX19v8!HEX~34-0pF +zk6JdAh4(uxH5pf3 +zoafoR`4Dx?7Gvp@U5z5%cxjpfh3N#Noz(S=5_wRyU6~57WN6t;d95t_mi4z-!S&lG +ztMIrAFD!U23)f4ST_lKz*F)-#)LN2F_1R&iIe0{VRfZ^DlqaS)HHV1{j3;>2a-WRD +zao?|PmgId;lNVu6N%eXp1j$2dS$fp-g_EGL7MQaXfubB3~ty>%nJc2hYppoc840Bqu&6dy+1W0SwUX +zQq|pyqiFQf{&>)4wE-y>h{uU5vFxgMG$oWE4F)21=xV-jWa39tHc3d}xLWBn2Up@A +zykF-QqoW?m3D_qWf@MybE^Ml$D?ODYYpE6A5^>21+Q(O3(k9;~cs<$h98#lVA2wt> +zS!TC*wI=La50lUM`hwLSUB1MLNPfzx+6=vHCy&8U435jkvD;ivdB`>{9H`!hcxT$$ +z?laZ2%5yX8&GM0iy2rsjz){klM|RqGr5oOOu);6 +zpSQ;v3d&>JEE)I~rLdCV-m4u--x%QsH}N!R`=jOitteD8L?|OfW$f*~{%x6S{{}b0 +zulWs6IqpP0QFz`@fAk4Mizwbf13MiDk@wrV+`}L*ct2)+Ha{a{{%mPCFoJJT0kg`( +zo2M?YRcwEqdw=`iL`5#~t>?%|Llt0haq9o5E^FGbsMnH$a9w^9&zf3Mq +zetKVLIai!d^j?-Tx3&7-tcaphFPgqI#`=^q1GwLtz>nbysJ=CH2eRTKu!rmXs&YH$ +z3Gf*JlLMQkDEe>>;(kjn80+G_<3iIU**Py$OgP$dXmj-~uJ%Em +zxOb$xJaX0G3GS~y;es)qkl4K@wxRKDmtN(Zu{tvk1H+bzZ-K2DZF|w2BSe!qA;vwZ +zN+8)&!@i7R$d}_rl+7*H&R|nC0JEu=`qcf27r}cY4`V(QDmCNttrBBN0VFxMGLJ;; +z8Qs;g7)Bsn;}=j_`@A^$Yp$r;;f%fz45c|9HR7rf(~r%_C*=fOc!_K9KpE?VIvPJ$ +zc<@;#UjBX%0N{}q`6csj;+1ed5HY!Ua{DpSLnr{e>C^U2QLSZUzx=V~z}h9cW_Iu? +zLP9tyJI3QUy$>nCps1ceR4?c^0miwc@Dl{ZH>yR^|e1GPEnq@u&A1gdx->sUmS7DP<$b(hMDT=711rpIR=wcCWfyO(`Ofm7gZ8Pj)OS=C +zZjRA~@duT8j!r-4$QuxLX_d#vkh=A`ZJ{O40Kdm?x15+taabnuZBf0zf-#wy7_ThZWQ$2G`imr3!v{|8eNkUI3{Tl5t`m(xQ +zL_xQJ)S3JI))Lwwh5Ni{SccBVF?}ZmNo(-yxOmZrc!$BhlE!2GVol?cK93p4bDNYU +zm9Ca>+(RoQvwZAIt7&&SF`Sv$du;Nn+t@k_u6Ssf+~G9P0OGxMnU5(gO`O`oAlwJPipa1n4lm31*`g_)C +zY_=dR6Nm)4ST8qrb;dZA03JH0OLwSVD!Prsjxzdu><6p;S^59~0s;U2Km7mquYdo? +zzkCOBYGY_&O`vRH$6kPuqlZlYUJCuY52?>76;`ejO<2;pJ7yRP!KIKoMRJ$t8yJ~8 +z)TSieX!hgeAp5z}<=-C@1QZMoI0PgVGz=_U1Vkic6jXen(=jlyuyOEfTPCEJHieXo +z4mkxqS7{nrx(tl`RSdGS@%e_;e%IMNynF=&g@olPR+A$xAt@y-BP&-yQAt@vRZWk& +zhUN>_`YmNLFf=kYF@5R5+``hz+Q!!Ifp7mUf1kw8Iey~gsnci9p05<#>EWuYn;&XBCxI +z)iu9XxHdL5x3sqP`7bcH|Kw<-_V*o4|7K~@-%N#gA%}da9I|7G(C^*FfdegGzS4f` +zJDdoM82#43?S6}n(F6#VYC#QLeWC#x_$*6?1wWySd87rYO8SV2g+3E{jPu{jQGb3( +zaHgMh#Z|nOeYE-%H%>UOmz3)*oV|GoJ&>~9gn3NB`}wzy0;Me**vj|Nj910RR7JQea&G + +literal 0 +HcmV?d00001 + +diff --git a/ms_mod/golang.org/x/crypto/sha3/xor.go b/ms_mod/golang.org/x/crypto/sha3/xor.go +new file mode 100644 +index 00000000000000..59c8eb94186e2f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/xor.go +@@ -0,0 +1,24 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build (!amd64 && !386 && !ppc64le) || purego ++// +build !amd64,!386,!ppc64le purego ++ ++package sha3 ++ ++// A storageBuf is an aligned array of maxRate bytes. ++type storageBuf [maxRate]byte ++ ++func (b *storageBuf) asBytes() *[maxRate]byte { ++ return (*[maxRate]byte)(b) ++} ++ ++var ( ++ xorIn = xorInGeneric ++ copyOut = copyOutGeneric ++ xorInUnaligned = xorInGeneric ++ copyOutUnaligned = copyOutGeneric ++) ++ ++const xorImplementationUnaligned = "generic" +diff --git a/ms_mod/golang.org/x/crypto/sha3/xor_generic.go b/ms_mod/golang.org/x/crypto/sha3/xor_generic.go +new file mode 100644 +index 00000000000000..8d947711272c3c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/xor_generic.go +@@ -0,0 +1,28 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package sha3 ++ ++import "encoding/binary" ++ ++// xorInGeneric xors the bytes in buf into the state; it ++// makes no non-portable assumptions about memory layout ++// or alignment. ++func xorInGeneric(d *state, buf []byte) { ++ n := len(buf) / 8 ++ ++ for i := 0; i < n; i++ { ++ a := binary.LittleEndian.Uint64(buf) ++ d.a[i] ^= a ++ buf = buf[8:] ++ } ++} ++ ++// copyOutGeneric copies uint64s to a byte buffer. ++func copyOutGeneric(d *state, b []byte) { ++ for i := 0; len(b) >= 8; i++ { ++ binary.LittleEndian.PutUint64(b, d.a[i]) ++ b = b[8:] ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go b/ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go +new file mode 100644 +index 00000000000000..1ce606246d5c29 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go +@@ -0,0 +1,68 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build (amd64 || 386 || ppc64le) && !purego ++// +build amd64 386 ppc64le ++// +build !purego ++ ++package sha3 ++ ++import "unsafe" ++ ++// A storageBuf is an aligned array of maxRate bytes. ++type storageBuf [maxRate / 8]uint64 ++ ++func (b *storageBuf) asBytes() *[maxRate]byte { ++ return (*[maxRate]byte)(unsafe.Pointer(b)) ++} ++ ++// xorInUnaligned uses unaligned reads and writes to update d.a to contain d.a ++// XOR buf. ++func xorInUnaligned(d *state, buf []byte) { ++ n := len(buf) ++ bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] ++ if n >= 72 { ++ d.a[0] ^= bw[0] ++ d.a[1] ^= bw[1] ++ d.a[2] ^= bw[2] ++ d.a[3] ^= bw[3] ++ d.a[4] ^= bw[4] ++ d.a[5] ^= bw[5] ++ d.a[6] ^= bw[6] ++ d.a[7] ^= bw[7] ++ d.a[8] ^= bw[8] ++ } ++ if n >= 104 { ++ d.a[9] ^= bw[9] ++ d.a[10] ^= bw[10] ++ d.a[11] ^= bw[11] ++ d.a[12] ^= bw[12] ++ } ++ if n >= 136 { ++ d.a[13] ^= bw[13] ++ d.a[14] ^= bw[14] ++ d.a[15] ^= bw[15] ++ d.a[16] ^= bw[16] ++ } ++ if n >= 144 { ++ d.a[17] ^= bw[17] ++ } ++ if n >= 168 { ++ d.a[18] ^= bw[18] ++ d.a[19] ^= bw[19] ++ d.a[20] ^= bw[20] ++ } ++} ++ ++func copyOutUnaligned(d *state, buf []byte) { ++ ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) ++ copy(buf, ab[:]) ++} ++ ++var ( ++ xorIn = xorInUnaligned ++ copyOut = copyOutUnaligned ++) ++ ++const xorImplementationUnaligned = "unaligned" +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/client.go b/ms_mod/golang.org/x/crypto/ssh/agent/client.go +new file mode 100644 +index 00000000000000..c3e112a9396121 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/client.go +@@ -0,0 +1,849 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package agent implements the ssh-agent protocol, and provides both ++// a client and a server. The client can talk to a standard ssh-agent ++// that uses UNIX sockets, and one could implement an alternative ++// ssh-agent process using the sample server. ++// ++// References: ++// ++// [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00 ++package agent // import "golang.org/x/crypto/ssh/agent" ++ ++import ( ++ "bytes" ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rsa" ++ "encoding/base64" ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "io" ++ "math/big" ++ "sync" ++ ++ "golang.org/x/crypto/ed25519" ++ "golang.org/x/crypto/ssh" ++) ++ ++// SignatureFlags represent additional flags that can be passed to the signature ++// requests an defined in [PROTOCOL.agent] section 4.5.1. ++type SignatureFlags uint32 ++ ++// SignatureFlag values as defined in [PROTOCOL.agent] section 5.3. ++const ( ++ SignatureFlagReserved SignatureFlags = 1 << iota ++ SignatureFlagRsaSha256 ++ SignatureFlagRsaSha512 ++) ++ ++// Agent represents the capabilities of an ssh-agent. ++type Agent interface { ++ // List returns the identities known to the agent. ++ List() ([]*Key, error) ++ ++ // Sign has the agent sign the data using a protocol 2 key as defined ++ // in [PROTOCOL.agent] section 2.6.2. ++ Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) ++ ++ // Add adds a private key to the agent. ++ Add(key AddedKey) error ++ ++ // Remove removes all identities with the given public key. ++ Remove(key ssh.PublicKey) error ++ ++ // RemoveAll removes all identities. ++ RemoveAll() error ++ ++ // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. ++ Lock(passphrase []byte) error ++ ++ // Unlock undoes the effect of Lock ++ Unlock(passphrase []byte) error ++ ++ // Signers returns signers for all the known keys. ++ Signers() ([]ssh.Signer, error) ++} ++ ++type ExtendedAgent interface { ++ Agent ++ ++ // SignWithFlags signs like Sign, but allows for additional flags to be sent/received ++ SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) ++ ++ // Extension processes a custom extension request. Standard-compliant agents are not ++ // required to support any extensions, but this method allows agents to implement ++ // vendor-specific methods or add experimental features. See [PROTOCOL.agent] section 4.7. ++ // If agent extensions are unsupported entirely this method MUST return an ++ // ErrExtensionUnsupported error. Similarly, if just the specific extensionType in ++ // the request is unsupported by the agent then ErrExtensionUnsupported MUST be ++ // returned. ++ // ++ // In the case of success, since [PROTOCOL.agent] section 4.7 specifies that the contents ++ // of the response are unspecified (including the type of the message), the complete ++ // response will be returned as a []byte slice, including the "type" byte of the message. ++ Extension(extensionType string, contents []byte) ([]byte, error) ++} ++ ++// ConstraintExtension describes an optional constraint defined by users. ++type ConstraintExtension struct { ++ // ExtensionName consist of a UTF-8 string suffixed by the ++ // implementation domain following the naming scheme defined ++ // in Section 4.2 of RFC 4251, e.g. "foo@example.com". ++ ExtensionName string ++ // ExtensionDetails contains the actual content of the extended ++ // constraint. ++ ExtensionDetails []byte ++} ++ ++// AddedKey describes an SSH key to be added to an Agent. ++type AddedKey struct { ++ // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey, ++ // ed25519.PrivateKey or *ecdsa.PrivateKey, which will be inserted into the ++ // agent. ++ PrivateKey interface{} ++ // Certificate, if not nil, is communicated to the agent and will be ++ // stored with the key. ++ Certificate *ssh.Certificate ++ // Comment is an optional, free-form string. ++ Comment string ++ // LifetimeSecs, if not zero, is the number of seconds that the ++ // agent will store the key for. ++ LifetimeSecs uint32 ++ // ConfirmBeforeUse, if true, requests that the agent confirm with the ++ // user before each use of this key. ++ ConfirmBeforeUse bool ++ // ConstraintExtensions are the experimental or private-use constraints ++ // defined by users. ++ ConstraintExtensions []ConstraintExtension ++} ++ ++// See [PROTOCOL.agent], section 3. ++const ( ++ agentRequestV1Identities = 1 ++ agentRemoveAllV1Identities = 9 ++ ++ // 3.2 Requests from client to agent for protocol 2 key operations ++ agentAddIdentity = 17 ++ agentRemoveIdentity = 18 ++ agentRemoveAllIdentities = 19 ++ agentAddIDConstrained = 25 ++ ++ // 3.3 Key-type independent requests from client to agent ++ agentAddSmartcardKey = 20 ++ agentRemoveSmartcardKey = 21 ++ agentLock = 22 ++ agentUnlock = 23 ++ agentAddSmartcardKeyConstrained = 26 ++ ++ // 3.7 Key constraint identifiers ++ agentConstrainLifetime = 1 ++ agentConstrainConfirm = 2 ++ agentConstrainExtension = 3 ++) ++ ++// maxAgentResponseBytes is the maximum agent reply size that is accepted. This ++// is a sanity check, not a limit in the spec. ++const maxAgentResponseBytes = 16 << 20 ++ ++// Agent messages: ++// These structures mirror the wire format of the corresponding ssh agent ++// messages found in [PROTOCOL.agent]. ++ ++// 3.4 Generic replies from agent to client ++const agentFailure = 5 ++ ++type failureAgentMsg struct{} ++ ++const agentSuccess = 6 ++ ++type successAgentMsg struct{} ++ ++// See [PROTOCOL.agent], section 2.5.2. ++const agentRequestIdentities = 11 ++ ++type requestIdentitiesAgentMsg struct{} ++ ++// See [PROTOCOL.agent], section 2.5.2. ++const agentIdentitiesAnswer = 12 ++ ++type identitiesAnswerAgentMsg struct { ++ NumKeys uint32 `sshtype:"12"` ++ Keys []byte `ssh:"rest"` ++} ++ ++// See [PROTOCOL.agent], section 2.6.2. ++const agentSignRequest = 13 ++ ++type signRequestAgentMsg struct { ++ KeyBlob []byte `sshtype:"13"` ++ Data []byte ++ Flags uint32 ++} ++ ++// See [PROTOCOL.agent], section 2.6.2. ++ ++// 3.6 Replies from agent to client for protocol 2 key operations ++const agentSignResponse = 14 ++ ++type signResponseAgentMsg struct { ++ SigBlob []byte `sshtype:"14"` ++} ++ ++type publicKey struct { ++ Format string ++ Rest []byte `ssh:"rest"` ++} ++ ++// 3.7 Key constraint identifiers ++type constrainLifetimeAgentMsg struct { ++ LifetimeSecs uint32 `sshtype:"1"` ++} ++ ++type constrainExtensionAgentMsg struct { ++ ExtensionName string `sshtype:"3"` ++ ExtensionDetails []byte ++ ++ // Rest is a field used for parsing, not part of message ++ Rest []byte `ssh:"rest"` ++} ++ ++// See [PROTOCOL.agent], section 4.7 ++const agentExtension = 27 ++const agentExtensionFailure = 28 ++ ++// ErrExtensionUnsupported indicates that an extension defined in ++// [PROTOCOL.agent] section 4.7 is unsupported by the agent. Specifically this ++// error indicates that the agent returned a standard SSH_AGENT_FAILURE message ++// as the result of a SSH_AGENTC_EXTENSION request. Note that the protocol ++// specification (and therefore this error) does not distinguish between a ++// specific extension being unsupported and extensions being unsupported entirely. ++var ErrExtensionUnsupported = errors.New("agent: extension unsupported") ++ ++type extensionAgentMsg struct { ++ ExtensionType string `sshtype:"27"` ++ // NOTE: this matches OpenSSH's PROTOCOL.agent, not the IETF draft [PROTOCOL.agent], ++ // so that it matches what OpenSSH actually implements in the wild. ++ Contents []byte `ssh:"rest"` ++} ++ ++// Key represents a protocol 2 public key as defined in ++// [PROTOCOL.agent], section 2.5.2. ++type Key struct { ++ Format string ++ Blob []byte ++ Comment string ++} ++ ++func clientErr(err error) error { ++ return fmt.Errorf("agent: client error: %v", err) ++} ++ ++// String returns the storage form of an agent key with the format, base64 ++// encoded serialized key, and the comment if it is not empty. ++func (k *Key) String() string { ++ s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob) ++ ++ if k.Comment != "" { ++ s += " " + k.Comment ++ } ++ ++ return s ++} ++ ++// Type returns the public key type. ++func (k *Key) Type() string { ++ return k.Format ++} ++ ++// Marshal returns key blob to satisfy the ssh.PublicKey interface. ++func (k *Key) Marshal() []byte { ++ return k.Blob ++} ++ ++// Verify satisfies the ssh.PublicKey interface. ++func (k *Key) Verify(data []byte, sig *ssh.Signature) error { ++ pubKey, err := ssh.ParsePublicKey(k.Blob) ++ if err != nil { ++ return fmt.Errorf("agent: bad public key: %v", err) ++ } ++ return pubKey.Verify(data, sig) ++} ++ ++type wireKey struct { ++ Format string ++ Rest []byte `ssh:"rest"` ++} ++ ++func parseKey(in []byte) (out *Key, rest []byte, err error) { ++ var record struct { ++ Blob []byte ++ Comment string ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if err := ssh.Unmarshal(in, &record); err != nil { ++ return nil, nil, err ++ } ++ ++ var wk wireKey ++ if err := ssh.Unmarshal(record.Blob, &wk); err != nil { ++ return nil, nil, err ++ } ++ ++ return &Key{ ++ Format: wk.Format, ++ Blob: record.Blob, ++ Comment: record.Comment, ++ }, record.Rest, nil ++} ++ ++// client is a client for an ssh-agent process. ++type client struct { ++ // conn is typically a *net.UnixConn ++ conn io.ReadWriter ++ // mu is used to prevent concurrent access to the agent ++ mu sync.Mutex ++} ++ ++// NewClient returns an Agent that talks to an ssh-agent process over ++// the given connection. ++func NewClient(rw io.ReadWriter) ExtendedAgent { ++ return &client{conn: rw} ++} ++ ++// call sends an RPC to the agent. On success, the reply is ++// unmarshaled into reply and replyType is set to the first byte of ++// the reply, which contains the type of the message. ++func (c *client) call(req []byte) (reply interface{}, err error) { ++ buf, err := c.callRaw(req) ++ if err != nil { ++ return nil, err ++ } ++ reply, err = unmarshal(buf) ++ if err != nil { ++ return nil, clientErr(err) ++ } ++ return reply, nil ++} ++ ++// callRaw sends an RPC to the agent. On success, the raw ++// bytes of the response are returned; no unmarshalling is ++// performed on the response. ++func (c *client) callRaw(req []byte) (reply []byte, err error) { ++ c.mu.Lock() ++ defer c.mu.Unlock() ++ ++ msg := make([]byte, 4+len(req)) ++ binary.BigEndian.PutUint32(msg, uint32(len(req))) ++ copy(msg[4:], req) ++ if _, err = c.conn.Write(msg); err != nil { ++ return nil, clientErr(err) ++ } ++ ++ var respSizeBuf [4]byte ++ if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil { ++ return nil, clientErr(err) ++ } ++ respSize := binary.BigEndian.Uint32(respSizeBuf[:]) ++ if respSize > maxAgentResponseBytes { ++ return nil, clientErr(errors.New("response too large")) ++ } ++ ++ buf := make([]byte, respSize) ++ if _, err = io.ReadFull(c.conn, buf); err != nil { ++ return nil, clientErr(err) ++ } ++ return buf, nil ++} ++ ++func (c *client) simpleCall(req []byte) error { ++ resp, err := c.call(req) ++ if err != nil { ++ return err ++ } ++ if _, ok := resp.(*successAgentMsg); ok { ++ return nil ++ } ++ return errors.New("agent: failure") ++} ++ ++func (c *client) RemoveAll() error { ++ return c.simpleCall([]byte{agentRemoveAllIdentities}) ++} ++ ++func (c *client) Remove(key ssh.PublicKey) error { ++ req := ssh.Marshal(&agentRemoveIdentityMsg{ ++ KeyBlob: key.Marshal(), ++ }) ++ return c.simpleCall(req) ++} ++ ++func (c *client) Lock(passphrase []byte) error { ++ req := ssh.Marshal(&agentLockMsg{ ++ Passphrase: passphrase, ++ }) ++ return c.simpleCall(req) ++} ++ ++func (c *client) Unlock(passphrase []byte) error { ++ req := ssh.Marshal(&agentUnlockMsg{ ++ Passphrase: passphrase, ++ }) ++ return c.simpleCall(req) ++} ++ ++// List returns the identities known to the agent. ++func (c *client) List() ([]*Key, error) { ++ // see [PROTOCOL.agent] section 2.5.2. ++ req := []byte{agentRequestIdentities} ++ ++ msg, err := c.call(req) ++ if err != nil { ++ return nil, err ++ } ++ ++ switch msg := msg.(type) { ++ case *identitiesAnswerAgentMsg: ++ if msg.NumKeys > maxAgentResponseBytes/8 { ++ return nil, errors.New("agent: too many keys in agent reply") ++ } ++ keys := make([]*Key, msg.NumKeys) ++ data := msg.Keys ++ for i := uint32(0); i < msg.NumKeys; i++ { ++ var key *Key ++ var err error ++ if key, data, err = parseKey(data); err != nil { ++ return nil, err ++ } ++ keys[i] = key ++ } ++ return keys, nil ++ case *failureAgentMsg: ++ return nil, errors.New("agent: failed to list keys") ++ } ++ panic("unreachable") ++} ++ ++// Sign has the agent sign the data using a protocol 2 key as defined ++// in [PROTOCOL.agent] section 2.6.2. ++func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { ++ return c.SignWithFlags(key, data, 0) ++} ++ ++func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) { ++ req := ssh.Marshal(signRequestAgentMsg{ ++ KeyBlob: key.Marshal(), ++ Data: data, ++ Flags: uint32(flags), ++ }) ++ ++ msg, err := c.call(req) ++ if err != nil { ++ return nil, err ++ } ++ ++ switch msg := msg.(type) { ++ case *signResponseAgentMsg: ++ var sig ssh.Signature ++ if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { ++ return nil, err ++ } ++ ++ return &sig, nil ++ case *failureAgentMsg: ++ return nil, errors.New("agent: failed to sign challenge") ++ } ++ panic("unreachable") ++} ++ ++// unmarshal parses an agent message in packet, returning the parsed ++// form and the message type of packet. ++func unmarshal(packet []byte) (interface{}, error) { ++ if len(packet) < 1 { ++ return nil, errors.New("agent: empty packet") ++ } ++ var msg interface{} ++ switch packet[0] { ++ case agentFailure: ++ return new(failureAgentMsg), nil ++ case agentSuccess: ++ return new(successAgentMsg), nil ++ case agentIdentitiesAnswer: ++ msg = new(identitiesAnswerAgentMsg) ++ case agentSignResponse: ++ msg = new(signResponseAgentMsg) ++ case agentV1IdentitiesAnswer: ++ msg = new(agentV1IdentityMsg) ++ default: ++ return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) ++ } ++ if err := ssh.Unmarshal(packet, msg); err != nil { ++ return nil, err ++ } ++ return msg, nil ++} ++ ++type rsaKeyMsg struct { ++ Type string `sshtype:"17|25"` ++ N *big.Int ++ E *big.Int ++ D *big.Int ++ Iqmp *big.Int // IQMP = Inverse Q Mod P ++ P *big.Int ++ Q *big.Int ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++type dsaKeyMsg struct { ++ Type string `sshtype:"17|25"` ++ P *big.Int ++ Q *big.Int ++ G *big.Int ++ Y *big.Int ++ X *big.Int ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++type ecdsaKeyMsg struct { ++ Type string `sshtype:"17|25"` ++ Curve string ++ KeyBytes []byte ++ D *big.Int ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++type ed25519KeyMsg struct { ++ Type string `sshtype:"17|25"` ++ Pub []byte ++ Priv []byte ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++// Insert adds a private key to the agent. ++func (c *client) insertKey(s interface{}, comment string, constraints []byte) error { ++ var req []byte ++ switch k := s.(type) { ++ case *rsa.PrivateKey: ++ if len(k.Primes) != 2 { ++ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) ++ } ++ k.Precompute() ++ req = ssh.Marshal(rsaKeyMsg{ ++ Type: ssh.KeyAlgoRSA, ++ N: k.N, ++ E: big.NewInt(int64(k.E)), ++ D: k.D, ++ Iqmp: k.Precomputed.Qinv, ++ P: k.Primes[0], ++ Q: k.Primes[1], ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ case *dsa.PrivateKey: ++ req = ssh.Marshal(dsaKeyMsg{ ++ Type: ssh.KeyAlgoDSA, ++ P: k.P, ++ Q: k.Q, ++ G: k.G, ++ Y: k.Y, ++ X: k.X, ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ case *ecdsa.PrivateKey: ++ nistID := fmt.Sprintf("nistp%d", k.Params().BitSize) ++ req = ssh.Marshal(ecdsaKeyMsg{ ++ Type: "ecdsa-sha2-" + nistID, ++ Curve: nistID, ++ KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y), ++ D: k.D, ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ case ed25519.PrivateKey: ++ req = ssh.Marshal(ed25519KeyMsg{ ++ Type: ssh.KeyAlgoED25519, ++ Pub: []byte(k)[32:], ++ Priv: []byte(k), ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ // This function originally supported only *ed25519.PrivateKey, however the ++ // general idiom is to pass ed25519.PrivateKey by value, not by pointer. ++ // We still support the pointer variant for backwards compatibility. ++ case *ed25519.PrivateKey: ++ req = ssh.Marshal(ed25519KeyMsg{ ++ Type: ssh.KeyAlgoED25519, ++ Pub: []byte(*k)[32:], ++ Priv: []byte(*k), ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ default: ++ return fmt.Errorf("agent: unsupported key type %T", s) ++ } ++ ++ // if constraints are present then the message type needs to be changed. ++ if len(constraints) != 0 { ++ req[0] = agentAddIDConstrained ++ } ++ ++ resp, err := c.call(req) ++ if err != nil { ++ return err ++ } ++ if _, ok := resp.(*successAgentMsg); ok { ++ return nil ++ } ++ return errors.New("agent: failure") ++} ++ ++type rsaCertMsg struct { ++ Type string `sshtype:"17|25"` ++ CertBytes []byte ++ D *big.Int ++ Iqmp *big.Int // IQMP = Inverse Q Mod P ++ P *big.Int ++ Q *big.Int ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++type dsaCertMsg struct { ++ Type string `sshtype:"17|25"` ++ CertBytes []byte ++ X *big.Int ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++type ecdsaCertMsg struct { ++ Type string `sshtype:"17|25"` ++ CertBytes []byte ++ D *big.Int ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++type ed25519CertMsg struct { ++ Type string `sshtype:"17|25"` ++ CertBytes []byte ++ Pub []byte ++ Priv []byte ++ Comments string ++ Constraints []byte `ssh:"rest"` ++} ++ ++// Add adds a private key to the agent. If a certificate is given, ++// that certificate is added instead as public key. ++func (c *client) Add(key AddedKey) error { ++ var constraints []byte ++ ++ if secs := key.LifetimeSecs; secs != 0 { ++ constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...) ++ } ++ ++ if key.ConfirmBeforeUse { ++ constraints = append(constraints, agentConstrainConfirm) ++ } ++ ++ cert := key.Certificate ++ if cert == nil { ++ return c.insertKey(key.PrivateKey, key.Comment, constraints) ++ } ++ return c.insertCert(key.PrivateKey, cert, key.Comment, constraints) ++} ++ ++func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { ++ var req []byte ++ switch k := s.(type) { ++ case *rsa.PrivateKey: ++ if len(k.Primes) != 2 { ++ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) ++ } ++ k.Precompute() ++ req = ssh.Marshal(rsaCertMsg{ ++ Type: cert.Type(), ++ CertBytes: cert.Marshal(), ++ D: k.D, ++ Iqmp: k.Precomputed.Qinv, ++ P: k.Primes[0], ++ Q: k.Primes[1], ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ case *dsa.PrivateKey: ++ req = ssh.Marshal(dsaCertMsg{ ++ Type: cert.Type(), ++ CertBytes: cert.Marshal(), ++ X: k.X, ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ case *ecdsa.PrivateKey: ++ req = ssh.Marshal(ecdsaCertMsg{ ++ Type: cert.Type(), ++ CertBytes: cert.Marshal(), ++ D: k.D, ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ case ed25519.PrivateKey: ++ req = ssh.Marshal(ed25519CertMsg{ ++ Type: cert.Type(), ++ CertBytes: cert.Marshal(), ++ Pub: []byte(k)[32:], ++ Priv: []byte(k), ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ // This function originally supported only *ed25519.PrivateKey, however the ++ // general idiom is to pass ed25519.PrivateKey by value, not by pointer. ++ // We still support the pointer variant for backwards compatibility. ++ case *ed25519.PrivateKey: ++ req = ssh.Marshal(ed25519CertMsg{ ++ Type: cert.Type(), ++ CertBytes: cert.Marshal(), ++ Pub: []byte(*k)[32:], ++ Priv: []byte(*k), ++ Comments: comment, ++ Constraints: constraints, ++ }) ++ default: ++ return fmt.Errorf("agent: unsupported key type %T", s) ++ } ++ ++ // if constraints are present then the message type needs to be changed. ++ if len(constraints) != 0 { ++ req[0] = agentAddIDConstrained ++ } ++ ++ signer, err := ssh.NewSignerFromKey(s) ++ if err != nil { ++ return err ++ } ++ if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { ++ return errors.New("agent: signer and cert have different public key") ++ } ++ ++ resp, err := c.call(req) ++ if err != nil { ++ return err ++ } ++ if _, ok := resp.(*successAgentMsg); ok { ++ return nil ++ } ++ return errors.New("agent: failure") ++} ++ ++// Signers provides a callback for client authentication. ++func (c *client) Signers() ([]ssh.Signer, error) { ++ keys, err := c.List() ++ if err != nil { ++ return nil, err ++ } ++ ++ var result []ssh.Signer ++ for _, k := range keys { ++ result = append(result, &agentKeyringSigner{c, k}) ++ } ++ return result, nil ++} ++ ++type agentKeyringSigner struct { ++ agent *client ++ pub ssh.PublicKey ++} ++ ++func (s *agentKeyringSigner) PublicKey() ssh.PublicKey { ++ return s.pub ++} ++ ++func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { ++ // The agent has its own entropy source, so the rand argument is ignored. ++ return s.agent.Sign(s.pub, data) ++} ++ ++func (s *agentKeyringSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*ssh.Signature, error) { ++ if algorithm == "" || algorithm == underlyingAlgo(s.pub.Type()) { ++ return s.Sign(rand, data) ++ } ++ ++ var flags SignatureFlags ++ switch algorithm { ++ case ssh.KeyAlgoRSASHA256: ++ flags = SignatureFlagRsaSha256 ++ case ssh.KeyAlgoRSASHA512: ++ flags = SignatureFlagRsaSha512 ++ default: ++ return nil, fmt.Errorf("agent: unsupported algorithm %q", algorithm) ++ } ++ ++ return s.agent.SignWithFlags(s.pub, data, flags) ++} ++ ++var _ ssh.AlgorithmSigner = &agentKeyringSigner{} ++ ++// certKeyAlgoNames is a mapping from known certificate algorithm names to the ++// corresponding public key signature algorithm. ++// ++// This map must be kept in sync with the one in certs.go. ++var certKeyAlgoNames = map[string]string{ ++ ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA, ++ ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256, ++ ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512, ++ ssh.CertAlgoDSAv01: ssh.KeyAlgoDSA, ++ ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256, ++ ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384, ++ ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521, ++ ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256, ++ ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519, ++ ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519, ++} ++ ++// underlyingAlgo returns the signature algorithm associated with algo (which is ++// an advertised or negotiated public key or host key algorithm). These are ++// usually the same, except for certificate algorithms. ++func underlyingAlgo(algo string) string { ++ if a, ok := certKeyAlgoNames[algo]; ok { ++ return a ++ } ++ return algo ++} ++ ++// Calls an extension method. It is up to the agent implementation as to whether or not ++// any particular extension is supported and may always return an error. Because the ++// type of the response is up to the implementation, this returns the bytes of the ++// response and does not attempt any type of unmarshalling. ++func (c *client) Extension(extensionType string, contents []byte) ([]byte, error) { ++ req := ssh.Marshal(extensionAgentMsg{ ++ ExtensionType: extensionType, ++ Contents: contents, ++ }) ++ buf, err := c.callRaw(req) ++ if err != nil { ++ return nil, err ++ } ++ if len(buf) == 0 { ++ return nil, errors.New("agent: failure; empty response") ++ } ++ // [PROTOCOL.agent] section 4.7 indicates that an SSH_AGENT_FAILURE message ++ // represents an agent that does not support the extension ++ if buf[0] == agentFailure { ++ return nil, ErrExtensionUnsupported ++ } ++ if buf[0] == agentExtensionFailure { ++ return nil, errors.New("agent: generic extension failure") ++ } ++ ++ return buf, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/client_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/client_test.go +new file mode 100644 +index 00000000000000..fdc8000654c6f3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/client_test.go +@@ -0,0 +1,537 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "errors" ++ "io" ++ "net" ++ "os" ++ "os/exec" ++ "path/filepath" ++ "runtime" ++ "strconv" ++ "strings" ++ "testing" ++ "time" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++// startOpenSSHAgent executes ssh-agent, and returns an Agent interface to it. ++func startOpenSSHAgent(t *testing.T) (client ExtendedAgent, socket string, cleanup func()) { ++ if testing.Short() { ++ // ssh-agent is not always available, and the key ++ // types supported vary by platform. ++ t.Skip("skipping test due to -short") ++ } ++ if runtime.GOOS == "windows" { ++ t.Skip("skipping on windows, we don't support connecting to the ssh-agent via a named pipe") ++ } ++ ++ bin, err := exec.LookPath("ssh-agent") ++ if err != nil { ++ t.Skip("could not find ssh-agent") ++ } ++ ++ cmd := exec.Command(bin, "-s") ++ cmd.Env = []string{} // Do not let the user's environment influence ssh-agent behavior. ++ cmd.Stderr = new(bytes.Buffer) ++ out, err := cmd.Output() ++ if err != nil { ++ t.Fatalf("%s failed: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) ++ } ++ ++ // Output looks like: ++ // ++ // SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; ++ // SSH_AGENT_PID=15542; export SSH_AGENT_PID; ++ // echo Agent pid 15542; ++ ++ fields := bytes.Split(out, []byte(";")) ++ line := bytes.SplitN(fields[0], []byte("="), 2) ++ line[0] = bytes.TrimLeft(line[0], "\n") ++ if string(line[0]) != "SSH_AUTH_SOCK" { ++ t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0]) ++ } ++ socket = string(line[1]) ++ ++ line = bytes.SplitN(fields[2], []byte("="), 2) ++ line[0] = bytes.TrimLeft(line[0], "\n") ++ if string(line[0]) != "SSH_AGENT_PID" { ++ t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2]) ++ } ++ pidStr := line[1] ++ pid, err := strconv.Atoi(string(pidStr)) ++ if err != nil { ++ t.Fatalf("Atoi(%q): %v", pidStr, err) ++ } ++ ++ conn, err := net.Dial("unix", string(socket)) ++ if err != nil { ++ t.Fatalf("net.Dial: %v", err) ++ } ++ ++ ac := NewClient(conn) ++ return ac, socket, func() { ++ proc, _ := os.FindProcess(pid) ++ if proc != nil { ++ proc.Kill() ++ } ++ conn.Close() ++ os.RemoveAll(filepath.Dir(socket)) ++ } ++} ++ ++func startAgent(t *testing.T, agent Agent) (client ExtendedAgent, cleanup func()) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ go ServeAgent(agent, c2) ++ ++ return NewClient(c1), func() { ++ c1.Close() ++ c2.Close() ++ } ++} ++ ++// startKeyringAgent uses Keyring to simulate a ssh-agent Server and returns a client. ++func startKeyringAgent(t *testing.T) (client ExtendedAgent, cleanup func()) { ++ return startAgent(t, NewKeyring()) ++} ++ ++func testOpenSSHAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { ++ agent, _, cleanup := startOpenSSHAgent(t) ++ defer cleanup() ++ ++ testAgentInterface(t, agent, key, cert, lifetimeSecs) ++} ++ ++func testKeyringAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { ++ agent, cleanup := startKeyringAgent(t) ++ defer cleanup() ++ ++ testAgentInterface(t, agent, key, cert, lifetimeSecs) ++} ++ ++func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { ++ signer, err := ssh.NewSignerFromKey(key) ++ if err != nil { ++ t.Fatalf("NewSignerFromKey(%T): %v", key, err) ++ } ++ // The agent should start up empty. ++ if keys, err := agent.List(); err != nil { ++ t.Fatalf("RequestIdentities: %v", err) ++ } else if len(keys) > 0 { ++ t.Fatalf("got %d keys, want 0: %v", len(keys), keys) ++ } ++ ++ // Attempt to insert the key, with certificate if specified. ++ var pubKey ssh.PublicKey ++ if cert != nil { ++ err = agent.Add(AddedKey{ ++ PrivateKey: key, ++ Certificate: cert, ++ Comment: "comment", ++ LifetimeSecs: lifetimeSecs, ++ }) ++ pubKey = cert ++ } else { ++ err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs}) ++ pubKey = signer.PublicKey() ++ } ++ if err != nil { ++ t.Fatalf("insert(%T): %v", key, err) ++ } ++ ++ // Did the key get inserted successfully? ++ if keys, err := agent.List(); err != nil { ++ t.Fatalf("List: %v", err) ++ } else if len(keys) != 1 { ++ t.Fatalf("got %v, want 1 key", keys) ++ } else if keys[0].Comment != "comment" { ++ t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment") ++ } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) { ++ t.Fatalf("key mismatch") ++ } ++ ++ // Can the agent make a valid signature? ++ data := []byte("hello") ++ sig, err := agent.Sign(pubKey, data) ++ if err != nil { ++ t.Fatalf("Sign(%s): %v", pubKey.Type(), err) ++ } ++ ++ if err := pubKey.Verify(data, sig); err != nil { ++ t.Fatalf("Verify(%s): %v", pubKey.Type(), err) ++ } ++ ++ // For tests on RSA keys, try signing with SHA-256 and SHA-512 flags ++ if pubKey.Type() == "ssh-rsa" { ++ sshFlagTest := func(flag SignatureFlags, expectedSigFormat string) { ++ sig, err = agent.SignWithFlags(pubKey, data, flag) ++ if err != nil { ++ t.Fatalf("SignWithFlags(%s): %v", pubKey.Type(), err) ++ } ++ if sig.Format != expectedSigFormat { ++ t.Fatalf("Signature format didn't match expected value: %s != %s", sig.Format, expectedSigFormat) ++ } ++ if err := pubKey.Verify(data, sig); err != nil { ++ t.Fatalf("Verify(%s): %v", pubKey.Type(), err) ++ } ++ } ++ sshFlagTest(0, ssh.KeyAlgoRSA) ++ sshFlagTest(SignatureFlagRsaSha256, ssh.KeyAlgoRSASHA256) ++ sshFlagTest(SignatureFlagRsaSha512, ssh.KeyAlgoRSASHA512) ++ } ++ ++ // If the key has a lifetime, is it removed when it should be? ++ if lifetimeSecs > 0 { ++ time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond) ++ keys, err := agent.List() ++ if err != nil { ++ t.Fatalf("List: %v", err) ++ } ++ if len(keys) > 0 { ++ t.Fatalf("key not expired") ++ } ++ } ++ ++} ++ ++func TestMalformedRequests(t *testing.T) { ++ keyringAgent := NewKeyring() ++ ++ testCase := func(t *testing.T, requestBytes []byte, wantServerErr bool) { ++ c, s := net.Pipe() ++ defer c.Close() ++ defer s.Close() ++ go func() { ++ _, err := c.Write(requestBytes) ++ if err != nil { ++ t.Errorf("Unexpected error writing raw bytes on connection: %v", err) ++ } ++ c.Close() ++ }() ++ err := ServeAgent(keyringAgent, s) ++ if err == nil { ++ t.Error("ServeAgent should have returned an error to malformed input") ++ } else { ++ if (err != io.EOF) != wantServerErr { ++ t.Errorf("ServeAgent returned expected error: %v", err) ++ } ++ } ++ } ++ ++ var testCases = []struct { ++ name string ++ requestBytes []byte ++ wantServerErr bool ++ }{ ++ {"Empty request", []byte{}, false}, ++ {"Short header", []byte{0x00}, true}, ++ {"Empty body", []byte{0x00, 0x00, 0x00, 0x00}, true}, ++ {"Short body", []byte{0x00, 0x00, 0x00, 0x01}, false}, ++ } ++ for _, tc := range testCases { ++ t.Run(tc.name, func(t *testing.T) { testCase(t, tc.requestBytes, tc.wantServerErr) }) ++ } ++} ++ ++func TestAgent(t *testing.T) { ++ for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} { ++ testOpenSSHAgent(t, testPrivateKeys[keyType], nil, 0) ++ testKeyringAgent(t, testPrivateKeys[keyType], nil, 0) ++ } ++} ++ ++func TestCert(t *testing.T) { ++ cert := &ssh.Certificate{ ++ Key: testPublicKeys["rsa"], ++ ValidBefore: ssh.CertTimeInfinity, ++ CertType: ssh.UserCert, ++ } ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ ++ testOpenSSHAgent(t, testPrivateKeys["rsa"], cert, 0) ++ testKeyringAgent(t, testPrivateKeys["rsa"], cert, 0) ++} ++ ++// netListener creates a localhost network listener. ++func netListener() (net.Listener, error) { ++ listener, err := net.Listen("tcp", "127.0.0.1:0") ++ if err != nil { ++ listener, err = net.Listen("tcp", "[::1]:0") ++ if err != nil { ++ return nil, err ++ } ++ } ++ return listener, nil ++} ++ ++// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and ++// therefore is buffered (net.Pipe deadlocks if both sides start with ++// a write.) ++func netPipe() (net.Conn, net.Conn, error) { ++ listener, err := netListener() ++ if err != nil { ++ return nil, nil, err ++ } ++ defer listener.Close() ++ c1, err := net.Dial("tcp", listener.Addr().String()) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ c2, err := listener.Accept() ++ if err != nil { ++ c1.Close() ++ return nil, nil, err ++ } ++ ++ return c1, c2, nil ++} ++ ++func TestServerResponseTooLarge(t *testing.T) { ++ a, b, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ done := make(chan struct{}) ++ defer func() { <-done }() ++ ++ defer a.Close() ++ defer b.Close() ++ ++ var response identitiesAnswerAgentMsg ++ response.NumKeys = 1 ++ response.Keys = make([]byte, maxAgentResponseBytes+1) ++ ++ agent := NewClient(a) ++ go func() { ++ defer close(done) ++ n, err := b.Write(ssh.Marshal(response)) ++ if n < 4 { ++ if runtime.GOOS == "plan9" { ++ if e1, ok := err.(*net.OpError); ok { ++ if e2, ok := e1.Err.(*os.PathError); ok { ++ switch e2.Err.Error() { ++ case "Hangup", "i/o on hungup channel": ++ // syscall.Pwrite returns -1 in this case even when some data did get written. ++ return ++ } ++ } ++ } ++ } ++ t.Errorf("At least 4 bytes (the response size) should have been successfully written: %d < 4: %v", n, err) ++ } ++ }() ++ _, err = agent.List() ++ if err == nil { ++ t.Fatal("Did not get error result") ++ } ++ if err.Error() != "agent: client error: response too large" { ++ t.Fatal("Did not get expected error result") ++ } ++} ++ ++func TestAuth(t *testing.T) { ++ agent, _, cleanup := startOpenSSHAgent(t) ++ defer cleanup() ++ ++ a, b, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ ++ defer a.Close() ++ defer b.Close() ++ ++ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil { ++ t.Errorf("Add: %v", err) ++ } ++ ++ serverConf := ssh.ServerConfig{} ++ serverConf.AddHostKey(testSigners["rsa"]) ++ serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { ++ if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { ++ return nil, nil ++ } ++ ++ return nil, errors.New("pubkey rejected") ++ } ++ ++ go func() { ++ conn, _, _, err := ssh.NewServerConn(a, &serverConf) ++ if err != nil { ++ t.Errorf("NewServerConn error: %v", err) ++ return ++ } ++ conn.Close() ++ }() ++ ++ conf := ssh.ClientConfig{ ++ HostKeyCallback: ssh.InsecureIgnoreHostKey(), ++ } ++ conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers)) ++ conn, _, _, err := ssh.NewClientConn(b, "", &conf) ++ if err != nil { ++ t.Fatalf("NewClientConn: %v", err) ++ } ++ conn.Close() ++} ++ ++func TestLockOpenSSHAgent(t *testing.T) { ++ agent, _, cleanup := startOpenSSHAgent(t) ++ defer cleanup() ++ testLockAgent(agent, t) ++} ++ ++func TestLockKeyringAgent(t *testing.T) { ++ agent, cleanup := startKeyringAgent(t) ++ defer cleanup() ++ testLockAgent(agent, t) ++} ++ ++func testLockAgent(agent Agent, t *testing.T) { ++ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil { ++ t.Errorf("Add: %v", err) ++ } ++ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil { ++ t.Errorf("Add: %v", err) ++ } ++ if keys, err := agent.List(); err != nil { ++ t.Errorf("List: %v", err) ++ } else if len(keys) != 2 { ++ t.Errorf("Want 2 keys, got %v", keys) ++ } ++ ++ passphrase := []byte("secret") ++ if err := agent.Lock(passphrase); err != nil { ++ t.Errorf("Lock: %v", err) ++ } ++ ++ if keys, err := agent.List(); err != nil { ++ t.Errorf("List: %v", err) ++ } else if len(keys) != 0 { ++ t.Errorf("Want 0 keys, got %v", keys) ++ } ++ ++ signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"]) ++ if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil { ++ t.Fatalf("Sign did not fail") ++ } ++ ++ if err := agent.Remove(signer.PublicKey()); err == nil { ++ t.Fatalf("Remove did not fail") ++ } ++ ++ if err := agent.RemoveAll(); err == nil { ++ t.Fatalf("RemoveAll did not fail") ++ } ++ ++ if err := agent.Unlock(nil); err == nil { ++ t.Errorf("Unlock with wrong passphrase succeeded") ++ } ++ if err := agent.Unlock(passphrase); err != nil { ++ t.Errorf("Unlock: %v", err) ++ } ++ ++ if err := agent.Remove(signer.PublicKey()); err != nil { ++ t.Fatalf("Remove: %v", err) ++ } ++ ++ if keys, err := agent.List(); err != nil { ++ t.Errorf("List: %v", err) ++ } else if len(keys) != 1 { ++ t.Errorf("Want 1 keys, got %v", keys) ++ } ++} ++ ++func testOpenSSHAgentLifetime(t *testing.T) { ++ agent, _, cleanup := startOpenSSHAgent(t) ++ defer cleanup() ++ testAgentLifetime(t, agent) ++} ++ ++func testKeyringAgentLifetime(t *testing.T) { ++ agent, cleanup := startKeyringAgent(t) ++ defer cleanup() ++ testAgentLifetime(t, agent) ++} ++ ++func testAgentLifetime(t *testing.T, agent Agent) { ++ for _, keyType := range []string{"rsa", "dsa", "ecdsa"} { ++ // Add private keys to the agent. ++ err := agent.Add(AddedKey{ ++ PrivateKey: testPrivateKeys[keyType], ++ Comment: "comment", ++ LifetimeSecs: 1, ++ }) ++ if err != nil { ++ t.Fatalf("add: %v", err) ++ } ++ // Add certs to the agent. ++ cert := &ssh.Certificate{ ++ Key: testPublicKeys[keyType], ++ ValidBefore: ssh.CertTimeInfinity, ++ CertType: ssh.UserCert, ++ } ++ cert.SignCert(rand.Reader, testSigners[keyType]) ++ err = agent.Add(AddedKey{ ++ PrivateKey: testPrivateKeys[keyType], ++ Certificate: cert, ++ Comment: "comment", ++ LifetimeSecs: 1, ++ }) ++ if err != nil { ++ t.Fatalf("add: %v", err) ++ } ++ } ++ time.Sleep(1100 * time.Millisecond) ++ if keys, err := agent.List(); err != nil { ++ t.Errorf("List: %v", err) ++ } else if len(keys) != 0 { ++ t.Errorf("Want 0 keys, got %v", len(keys)) ++ } ++} ++ ++type keyringExtended struct { ++ *keyring ++} ++ ++func (r *keyringExtended) Extension(extensionType string, contents []byte) ([]byte, error) { ++ if extensionType != "my-extension@example.com" { ++ return []byte{agentExtensionFailure}, nil ++ } ++ return append([]byte{agentSuccess}, contents...), nil ++} ++ ++func TestAgentExtensions(t *testing.T) { ++ agent, _, cleanup := startOpenSSHAgent(t) ++ defer cleanup() ++ _, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02}) ++ if err == nil { ++ t.Fatal("should have gotten agent extension failure") ++ } ++ ++ agent, cleanup = startAgent(t, &keyringExtended{}) ++ defer cleanup() ++ result, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02}) ++ if err != nil { ++ t.Fatalf("agent extension failure: %v", err) ++ } ++ if len(result) != 4 || !bytes.Equal(result, []byte{agentSuccess, 0x00, 0x01, 0x02}) { ++ t.Fatalf("agent extension result invalid: %v", result) ++ } ++ ++ _, err = agent.Extension("bad-extension@example.com", []byte{0x00, 0x01, 0x02}) ++ if err == nil { ++ t.Fatal("should have gotten agent extension failure") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/example_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/example_test.go +new file mode 100644 +index 00000000000000..1fedaea1d6c9c4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/example_test.go +@@ -0,0 +1,41 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent_test ++ ++import ( ++ "log" ++ "net" ++ "os" ++ ++ "golang.org/x/crypto/ssh" ++ "golang.org/x/crypto/ssh/agent" ++) ++ ++func ExampleNewClient() { ++ // ssh-agent(1) provides a UNIX socket at $SSH_AUTH_SOCK. ++ socket := os.Getenv("SSH_AUTH_SOCK") ++ conn, err := net.Dial("unix", socket) ++ if err != nil { ++ log.Fatalf("Failed to open SSH_AUTH_SOCK: %v", err) ++ } ++ ++ agentClient := agent.NewClient(conn) ++ config := &ssh.ClientConfig{ ++ User: "gopher", ++ Auth: []ssh.AuthMethod{ ++ // Use a callback rather than PublicKeys so we only consult the ++ // agent once the remote server wants it. ++ ssh.PublicKeysCallback(agentClient.Signers), ++ }, ++ HostKeyCallback: ssh.InsecureIgnoreHostKey(), ++ } ++ ++ sshc, err := ssh.Dial("tcp", "localhost:22", config) ++ if err != nil { ++ log.Fatal(err) ++ } ++ // Use sshc... ++ sshc.Close() ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/forward.go b/ms_mod/golang.org/x/crypto/ssh/agent/forward.go +new file mode 100644 +index 00000000000000..fd24ba900d2541 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/forward.go +@@ -0,0 +1,103 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent ++ ++import ( ++ "errors" ++ "io" ++ "net" ++ "sync" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++// RequestAgentForwarding sets up agent forwarding for the session. ++// ForwardToAgent or ForwardToRemote should be called to route ++// the authentication requests. ++func RequestAgentForwarding(session *ssh.Session) error { ++ ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) ++ if err != nil { ++ return err ++ } ++ if !ok { ++ return errors.New("forwarding request denied") ++ } ++ return nil ++} ++ ++// ForwardToAgent routes authentication requests to the given keyring. ++func ForwardToAgent(client *ssh.Client, keyring Agent) error { ++ channels := client.HandleChannelOpen(channelType) ++ if channels == nil { ++ return errors.New("agent: already have handler for " + channelType) ++ } ++ ++ go func() { ++ for ch := range channels { ++ channel, reqs, err := ch.Accept() ++ if err != nil { ++ continue ++ } ++ go ssh.DiscardRequests(reqs) ++ go func() { ++ ServeAgent(keyring, channel) ++ channel.Close() ++ }() ++ } ++ }() ++ return nil ++} ++ ++const channelType = "auth-agent@openssh.com" ++ ++// ForwardToRemote routes authentication requests to the ssh-agent ++// process serving on the given unix socket. ++func ForwardToRemote(client *ssh.Client, addr string) error { ++ channels := client.HandleChannelOpen(channelType) ++ if channels == nil { ++ return errors.New("agent: already have handler for " + channelType) ++ } ++ conn, err := net.Dial("unix", addr) ++ if err != nil { ++ return err ++ } ++ conn.Close() ++ ++ go func() { ++ for ch := range channels { ++ channel, reqs, err := ch.Accept() ++ if err != nil { ++ continue ++ } ++ go ssh.DiscardRequests(reqs) ++ go forwardUnixSocket(channel, addr) ++ } ++ }() ++ return nil ++} ++ ++func forwardUnixSocket(channel ssh.Channel, addr string) { ++ conn, err := net.Dial("unix", addr) ++ if err != nil { ++ return ++ } ++ ++ var wg sync.WaitGroup ++ wg.Add(2) ++ go func() { ++ io.Copy(conn, channel) ++ conn.(*net.UnixConn).CloseWrite() ++ wg.Done() ++ }() ++ go func() { ++ io.Copy(channel, conn) ++ channel.CloseWrite() ++ wg.Done() ++ }() ++ ++ wg.Wait() ++ conn.Close() ++ channel.Close() ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/keyring.go b/ms_mod/golang.org/x/crypto/ssh/agent/keyring.go +new file mode 100644 +index 00000000000000..21bfa870fa4dd2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/keyring.go +@@ -0,0 +1,241 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "crypto/subtle" ++ "errors" ++ "fmt" ++ "sync" ++ "time" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++type privKey struct { ++ signer ssh.Signer ++ comment string ++ expire *time.Time ++} ++ ++type keyring struct { ++ mu sync.Mutex ++ keys []privKey ++ ++ locked bool ++ passphrase []byte ++} ++ ++var errLocked = errors.New("agent: locked") ++ ++// NewKeyring returns an Agent that holds keys in memory. It is safe ++// for concurrent use by multiple goroutines. ++func NewKeyring() Agent { ++ return &keyring{} ++} ++ ++// RemoveAll removes all identities. ++func (r *keyring) RemoveAll() error { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ return errLocked ++ } ++ ++ r.keys = nil ++ return nil ++} ++ ++// removeLocked does the actual key removal. The caller must already be holding the ++// keyring mutex. ++func (r *keyring) removeLocked(want []byte) error { ++ found := false ++ for i := 0; i < len(r.keys); { ++ if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { ++ found = true ++ r.keys[i] = r.keys[len(r.keys)-1] ++ r.keys = r.keys[:len(r.keys)-1] ++ continue ++ } else { ++ i++ ++ } ++ } ++ ++ if !found { ++ return errors.New("agent: key not found") ++ } ++ return nil ++} ++ ++// Remove removes all identities with the given public key. ++func (r *keyring) Remove(key ssh.PublicKey) error { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ return errLocked ++ } ++ ++ return r.removeLocked(key.Marshal()) ++} ++ ++// Lock locks the agent. Sign and Remove will fail, and List will return an empty list. ++func (r *keyring) Lock(passphrase []byte) error { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ return errLocked ++ } ++ ++ r.locked = true ++ r.passphrase = passphrase ++ return nil ++} ++ ++// Unlock undoes the effect of Lock ++func (r *keyring) Unlock(passphrase []byte) error { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if !r.locked { ++ return errors.New("agent: not locked") ++ } ++ if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { ++ return fmt.Errorf("agent: incorrect passphrase") ++ } ++ ++ r.locked = false ++ r.passphrase = nil ++ return nil ++} ++ ++// expireKeysLocked removes expired keys from the keyring. If a key was added ++// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have ++// elapsed, it is removed. The caller *must* be holding the keyring mutex. ++func (r *keyring) expireKeysLocked() { ++ for _, k := range r.keys { ++ if k.expire != nil && time.Now().After(*k.expire) { ++ r.removeLocked(k.signer.PublicKey().Marshal()) ++ } ++ } ++} ++ ++// List returns the identities known to the agent. ++func (r *keyring) List() ([]*Key, error) { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ // section 2.7: locked agents return empty. ++ return nil, nil ++ } ++ ++ r.expireKeysLocked() ++ var ids []*Key ++ for _, k := range r.keys { ++ pub := k.signer.PublicKey() ++ ids = append(ids, &Key{ ++ Format: pub.Type(), ++ Blob: pub.Marshal(), ++ Comment: k.comment}) ++ } ++ return ids, nil ++} ++ ++// Insert adds a private key to the keyring. If a certificate ++// is given, that certificate is added as public key. Note that ++// any constraints given are ignored. ++func (r *keyring) Add(key AddedKey) error { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ return errLocked ++ } ++ signer, err := ssh.NewSignerFromKey(key.PrivateKey) ++ ++ if err != nil { ++ return err ++ } ++ ++ if cert := key.Certificate; cert != nil { ++ signer, err = ssh.NewCertSigner(cert, signer) ++ if err != nil { ++ return err ++ } ++ } ++ ++ p := privKey{ ++ signer: signer, ++ comment: key.Comment, ++ } ++ ++ if key.LifetimeSecs > 0 { ++ t := time.Now().Add(time.Duration(key.LifetimeSecs) * time.Second) ++ p.expire = &t ++ } ++ ++ r.keys = append(r.keys, p) ++ ++ return nil ++} ++ ++// Sign returns a signature for the data. ++func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { ++ return r.SignWithFlags(key, data, 0) ++} ++ ++func (r *keyring) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ return nil, errLocked ++ } ++ ++ r.expireKeysLocked() ++ wanted := key.Marshal() ++ for _, k := range r.keys { ++ if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { ++ if flags == 0 { ++ return k.signer.Sign(rand.Reader, data) ++ } else { ++ if algorithmSigner, ok := k.signer.(ssh.AlgorithmSigner); !ok { ++ return nil, fmt.Errorf("agent: signature does not support non-default signature algorithm: %T", k.signer) ++ } else { ++ var algorithm string ++ switch flags { ++ case SignatureFlagRsaSha256: ++ algorithm = ssh.KeyAlgoRSASHA256 ++ case SignatureFlagRsaSha512: ++ algorithm = ssh.KeyAlgoRSASHA512 ++ default: ++ return nil, fmt.Errorf("agent: unsupported signature flags: %d", flags) ++ } ++ return algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm) ++ } ++ } ++ } ++ } ++ return nil, errors.New("not found") ++} ++ ++// Signers returns signers for all the known keys. ++func (r *keyring) Signers() ([]ssh.Signer, error) { ++ r.mu.Lock() ++ defer r.mu.Unlock() ++ if r.locked { ++ return nil, errLocked ++ } ++ ++ r.expireKeysLocked() ++ s := make([]ssh.Signer, 0, len(r.keys)) ++ for _, k := range r.keys { ++ s = append(s, k.signer) ++ } ++ return s, nil ++} ++ ++// The keyring does not support any extensions ++func (r *keyring) Extension(extensionType string, contents []byte) ([]byte, error) { ++ return nil, ErrExtensionUnsupported ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go +new file mode 100644 +index 00000000000000..e5d50e7e0db559 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go +@@ -0,0 +1,76 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent ++ ++import "testing" ++ ++func addTestKey(t *testing.T, a Agent, keyName string) { ++ err := a.Add(AddedKey{ ++ PrivateKey: testPrivateKeys[keyName], ++ Comment: keyName, ++ }) ++ if err != nil { ++ t.Fatalf("failed to add key %q: %v", keyName, err) ++ } ++} ++ ++func removeTestKey(t *testing.T, a Agent, keyName string) { ++ err := a.Remove(testPublicKeys[keyName]) ++ if err != nil { ++ t.Fatalf("failed to remove key %q: %v", keyName, err) ++ } ++} ++ ++func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) { ++ listedKeys, err := a.List() ++ if err != nil { ++ t.Fatalf("failed to list keys: %v", err) ++ return ++ } ++ actualKeys := make(map[string]bool) ++ for _, key := range listedKeys { ++ actualKeys[key.Comment] = true ++ } ++ ++ matchedKeys := make(map[string]bool) ++ for _, expectedKey := range expectedKeys { ++ if !actualKeys[expectedKey] { ++ t.Fatalf("expected key %q, but was not found", expectedKey) ++ } else { ++ matchedKeys[expectedKey] = true ++ } ++ } ++ ++ for actualKey := range actualKeys { ++ if !matchedKeys[actualKey] { ++ t.Fatalf("key %q was found, but was not expected", actualKey) ++ } ++ } ++} ++ ++func TestKeyringAddingAndRemoving(t *testing.T) { ++ keyNames := []string{"dsa", "ecdsa", "rsa", "user"} ++ ++ // add all test private keys ++ k := NewKeyring() ++ for _, keyName := range keyNames { ++ addTestKey(t, k, keyName) ++ } ++ validateListedKeys(t, k, keyNames) ++ ++ // remove a key in the middle ++ keyToRemove := keyNames[1] ++ keyNames = append(keyNames[:1], keyNames[2:]...) ++ ++ removeTestKey(t, k, keyToRemove) ++ validateListedKeys(t, k, keyNames) ++ ++ // remove all keys ++ err := k.RemoveAll() ++ if err != nil { ++ t.Fatalf("failed to remove all keys: %v", err) ++ } ++ validateListedKeys(t, k, []string{}) ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/server.go b/ms_mod/golang.org/x/crypto/ssh/agent/server.go +new file mode 100644 +index 00000000000000..9a769de03d13c9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/server.go +@@ -0,0 +1,570 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent ++ ++import ( ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rsa" ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "io" ++ "log" ++ "math/big" ++ ++ "golang.org/x/crypto/ed25519" ++ "golang.org/x/crypto/ssh" ++) ++ ++// server wraps an Agent and uses it to implement the agent side of ++// the SSH-agent, wire protocol. ++type server struct { ++ agent Agent ++} ++ ++func (s *server) processRequestBytes(reqData []byte) []byte { ++ rep, err := s.processRequest(reqData) ++ if err != nil { ++ if err != errLocked { ++ // TODO(hanwen): provide better logging interface? ++ log.Printf("agent %d: %v", reqData[0], err) ++ } ++ return []byte{agentFailure} ++ } ++ ++ if err == nil && rep == nil { ++ return []byte{agentSuccess} ++ } ++ ++ return ssh.Marshal(rep) ++} ++ ++func marshalKey(k *Key) []byte { ++ var record struct { ++ Blob []byte ++ Comment string ++ } ++ record.Blob = k.Marshal() ++ record.Comment = k.Comment ++ ++ return ssh.Marshal(&record) ++} ++ ++// See [PROTOCOL.agent], section 2.5.1. ++const agentV1IdentitiesAnswer = 2 ++ ++type agentV1IdentityMsg struct { ++ Numkeys uint32 `sshtype:"2"` ++} ++ ++type agentRemoveIdentityMsg struct { ++ KeyBlob []byte `sshtype:"18"` ++} ++ ++type agentLockMsg struct { ++ Passphrase []byte `sshtype:"22"` ++} ++ ++type agentUnlockMsg struct { ++ Passphrase []byte `sshtype:"23"` ++} ++ ++func (s *server) processRequest(data []byte) (interface{}, error) { ++ switch data[0] { ++ case agentRequestV1Identities: ++ return &agentV1IdentityMsg{0}, nil ++ ++ case agentRemoveAllV1Identities: ++ return nil, nil ++ ++ case agentRemoveIdentity: ++ var req agentRemoveIdentityMsg ++ if err := ssh.Unmarshal(data, &req); err != nil { ++ return nil, err ++ } ++ ++ var wk wireKey ++ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { ++ return nil, err ++ } ++ ++ return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) ++ ++ case agentRemoveAllIdentities: ++ return nil, s.agent.RemoveAll() ++ ++ case agentLock: ++ var req agentLockMsg ++ if err := ssh.Unmarshal(data, &req); err != nil { ++ return nil, err ++ } ++ ++ return nil, s.agent.Lock(req.Passphrase) ++ ++ case agentUnlock: ++ var req agentUnlockMsg ++ if err := ssh.Unmarshal(data, &req); err != nil { ++ return nil, err ++ } ++ return nil, s.agent.Unlock(req.Passphrase) ++ ++ case agentSignRequest: ++ var req signRequestAgentMsg ++ if err := ssh.Unmarshal(data, &req); err != nil { ++ return nil, err ++ } ++ ++ var wk wireKey ++ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { ++ return nil, err ++ } ++ ++ k := &Key{ ++ Format: wk.Format, ++ Blob: req.KeyBlob, ++ } ++ ++ var sig *ssh.Signature ++ var err error ++ if extendedAgent, ok := s.agent.(ExtendedAgent); ok { ++ sig, err = extendedAgent.SignWithFlags(k, req.Data, SignatureFlags(req.Flags)) ++ } else { ++ sig, err = s.agent.Sign(k, req.Data) ++ } ++ ++ if err != nil { ++ return nil, err ++ } ++ return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil ++ ++ case agentRequestIdentities: ++ keys, err := s.agent.List() ++ if err != nil { ++ return nil, err ++ } ++ ++ rep := identitiesAnswerAgentMsg{ ++ NumKeys: uint32(len(keys)), ++ } ++ for _, k := range keys { ++ rep.Keys = append(rep.Keys, marshalKey(k)...) ++ } ++ return rep, nil ++ ++ case agentAddIDConstrained, agentAddIdentity: ++ return nil, s.insertIdentity(data) ++ ++ case agentExtension: ++ // Return a stub object where the whole contents of the response gets marshaled. ++ var responseStub struct { ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if extendedAgent, ok := s.agent.(ExtendedAgent); !ok { ++ // If this agent doesn't implement extensions, [PROTOCOL.agent] section 4.7 ++ // requires that we return a standard SSH_AGENT_FAILURE message. ++ responseStub.Rest = []byte{agentFailure} ++ } else { ++ var req extensionAgentMsg ++ if err := ssh.Unmarshal(data, &req); err != nil { ++ return nil, err ++ } ++ res, err := extendedAgent.Extension(req.ExtensionType, req.Contents) ++ if err != nil { ++ // If agent extensions are unsupported, return a standard SSH_AGENT_FAILURE ++ // message as required by [PROTOCOL.agent] section 4.7. ++ if err == ErrExtensionUnsupported { ++ responseStub.Rest = []byte{agentFailure} ++ } else { ++ // As the result of any other error processing an extension request, ++ // [PROTOCOL.agent] section 4.7 requires that we return a ++ // SSH_AGENT_EXTENSION_FAILURE code. ++ responseStub.Rest = []byte{agentExtensionFailure} ++ } ++ } else { ++ if len(res) == 0 { ++ return nil, nil ++ } ++ responseStub.Rest = res ++ } ++ } ++ ++ return responseStub, nil ++ } ++ ++ return nil, fmt.Errorf("unknown opcode %d", data[0]) ++} ++ ++func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) { ++ for len(constraints) != 0 { ++ switch constraints[0] { ++ case agentConstrainLifetime: ++ lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5]) ++ constraints = constraints[5:] ++ case agentConstrainConfirm: ++ confirmBeforeUse = true ++ constraints = constraints[1:] ++ case agentConstrainExtension: ++ var msg constrainExtensionAgentMsg ++ if err = ssh.Unmarshal(constraints, &msg); err != nil { ++ return 0, false, nil, err ++ } ++ extensions = append(extensions, ConstraintExtension{ ++ ExtensionName: msg.ExtensionName, ++ ExtensionDetails: msg.ExtensionDetails, ++ }) ++ constraints = msg.Rest ++ default: ++ return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0]) ++ } ++ } ++ return ++} ++ ++func setConstraints(key *AddedKey, constraintBytes []byte) error { ++ lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes) ++ if err != nil { ++ return err ++ } ++ ++ key.LifetimeSecs = lifetimeSecs ++ key.ConfirmBeforeUse = confirmBeforeUse ++ key.ConstraintExtensions = constraintExtensions ++ return nil ++} ++ ++func parseRSAKey(req []byte) (*AddedKey, error) { ++ var k rsaKeyMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ if k.E.BitLen() > 30 { ++ return nil, errors.New("agent: RSA public exponent too large") ++ } ++ priv := &rsa.PrivateKey{ ++ PublicKey: rsa.PublicKey{ ++ E: int(k.E.Int64()), ++ N: k.N, ++ }, ++ D: k.D, ++ Primes: []*big.Int{k.P, k.Q}, ++ } ++ priv.Precompute() ++ ++ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func parseEd25519Key(req []byte) (*AddedKey, error) { ++ var k ed25519KeyMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ priv := ed25519.PrivateKey(k.Priv) ++ ++ addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func parseDSAKey(req []byte) (*AddedKey, error) { ++ var k dsaKeyMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ priv := &dsa.PrivateKey{ ++ PublicKey: dsa.PublicKey{ ++ Parameters: dsa.Parameters{ ++ P: k.P, ++ Q: k.Q, ++ G: k.G, ++ }, ++ Y: k.Y, ++ }, ++ X: k.X, ++ } ++ ++ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) { ++ priv = &ecdsa.PrivateKey{ ++ D: privScalar, ++ } ++ ++ switch curveName { ++ case "nistp256": ++ priv.Curve = elliptic.P256() ++ case "nistp384": ++ priv.Curve = elliptic.P384() ++ case "nistp521": ++ priv.Curve = elliptic.P521() ++ default: ++ return nil, fmt.Errorf("agent: unknown curve %q", curveName) ++ } ++ ++ priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes) ++ if priv.X == nil || priv.Y == nil { ++ return nil, errors.New("agent: point not on curve") ++ } ++ ++ return priv, nil ++} ++ ++func parseEd25519Cert(req []byte) (*AddedKey, error) { ++ var k ed25519CertMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ pubKey, err := ssh.ParsePublicKey(k.CertBytes) ++ if err != nil { ++ return nil, err ++ } ++ priv := ed25519.PrivateKey(k.Priv) ++ cert, ok := pubKey.(*ssh.Certificate) ++ if !ok { ++ return nil, errors.New("agent: bad ED25519 certificate") ++ } ++ ++ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func parseECDSAKey(req []byte) (*AddedKey, error) { ++ var k ecdsaKeyMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ ++ priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D) ++ if err != nil { ++ return nil, err ++ } ++ ++ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func parseRSACert(req []byte) (*AddedKey, error) { ++ var k rsaCertMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ ++ pubKey, err := ssh.ParsePublicKey(k.CertBytes) ++ if err != nil { ++ return nil, err ++ } ++ ++ cert, ok := pubKey.(*ssh.Certificate) ++ if !ok { ++ return nil, errors.New("agent: bad RSA certificate") ++ } ++ ++ // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go ++ var rsaPub struct { ++ Name string ++ E *big.Int ++ N *big.Int ++ } ++ if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil { ++ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) ++ } ++ ++ if rsaPub.E.BitLen() > 30 { ++ return nil, errors.New("agent: RSA public exponent too large") ++ } ++ ++ priv := rsa.PrivateKey{ ++ PublicKey: rsa.PublicKey{ ++ E: int(rsaPub.E.Int64()), ++ N: rsaPub.N, ++ }, ++ D: k.D, ++ Primes: []*big.Int{k.Q, k.P}, ++ } ++ priv.Precompute() ++ ++ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func parseDSACert(req []byte) (*AddedKey, error) { ++ var k dsaCertMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ pubKey, err := ssh.ParsePublicKey(k.CertBytes) ++ if err != nil { ++ return nil, err ++ } ++ cert, ok := pubKey.(*ssh.Certificate) ++ if !ok { ++ return nil, errors.New("agent: bad DSA certificate") ++ } ++ ++ // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go ++ var w struct { ++ Name string ++ P, Q, G, Y *big.Int ++ } ++ if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil { ++ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) ++ } ++ ++ priv := &dsa.PrivateKey{ ++ PublicKey: dsa.PublicKey{ ++ Parameters: dsa.Parameters{ ++ P: w.P, ++ Q: w.Q, ++ G: w.G, ++ }, ++ Y: w.Y, ++ }, ++ X: k.X, ++ } ++ ++ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func parseECDSACert(req []byte) (*AddedKey, error) { ++ var k ecdsaCertMsg ++ if err := ssh.Unmarshal(req, &k); err != nil { ++ return nil, err ++ } ++ ++ pubKey, err := ssh.ParsePublicKey(k.CertBytes) ++ if err != nil { ++ return nil, err ++ } ++ cert, ok := pubKey.(*ssh.Certificate) ++ if !ok { ++ return nil, errors.New("agent: bad ECDSA certificate") ++ } ++ ++ // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go ++ var ecdsaPub struct { ++ Name string ++ ID string ++ Key []byte ++ } ++ if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil { ++ return nil, err ++ } ++ ++ priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D) ++ if err != nil { ++ return nil, err ++ } ++ ++ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} ++ if err := setConstraints(addedKey, k.Constraints); err != nil { ++ return nil, err ++ } ++ return addedKey, nil ++} ++ ++func (s *server) insertIdentity(req []byte) error { ++ var record struct { ++ Type string `sshtype:"17|25"` ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if err := ssh.Unmarshal(req, &record); err != nil { ++ return err ++ } ++ ++ var addedKey *AddedKey ++ var err error ++ ++ switch record.Type { ++ case ssh.KeyAlgoRSA: ++ addedKey, err = parseRSAKey(req) ++ case ssh.KeyAlgoDSA: ++ addedKey, err = parseDSAKey(req) ++ case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: ++ addedKey, err = parseECDSAKey(req) ++ case ssh.KeyAlgoED25519: ++ addedKey, err = parseEd25519Key(req) ++ case ssh.CertAlgoRSAv01: ++ addedKey, err = parseRSACert(req) ++ case ssh.CertAlgoDSAv01: ++ addedKey, err = parseDSACert(req) ++ case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: ++ addedKey, err = parseECDSACert(req) ++ case ssh.CertAlgoED25519v01: ++ addedKey, err = parseEd25519Cert(req) ++ default: ++ return fmt.Errorf("agent: not implemented: %q", record.Type) ++ } ++ ++ if err != nil { ++ return err ++ } ++ return s.agent.Add(*addedKey) ++} ++ ++// ServeAgent serves the agent protocol on the given connection. It ++// returns when an I/O error occurs. ++func ServeAgent(agent Agent, c io.ReadWriter) error { ++ s := &server{agent} ++ ++ var length [4]byte ++ for { ++ if _, err := io.ReadFull(c, length[:]); err != nil { ++ return err ++ } ++ l := binary.BigEndian.Uint32(length[:]) ++ if l == 0 { ++ return fmt.Errorf("agent: request size is 0") ++ } ++ if l > maxAgentResponseBytes { ++ // We also cap requests. ++ return fmt.Errorf("agent: request too large: %d", l) ++ } ++ ++ req := make([]byte, l) ++ if _, err := io.ReadFull(c, req); err != nil { ++ return err ++ } ++ ++ repData := s.processRequestBytes(req) ++ if len(repData) > maxAgentResponseBytes { ++ return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) ++ } ++ ++ binary.BigEndian.PutUint32(length[:], uint32(len(repData))) ++ if _, err := c.Write(length[:]); err != nil { ++ return err ++ } ++ if _, err := c.Write(repData); err != nil { ++ return err ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/server_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/server_test.go +new file mode 100644 +index 00000000000000..0af85457e4da9d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/server_test.go +@@ -0,0 +1,262 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package agent ++ ++import ( ++ "crypto" ++ "crypto/rand" ++ "fmt" ++ pseudorand "math/rand" ++ "reflect" ++ "strings" ++ "testing" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++func TestServer(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ client := NewClient(c1) ++ ++ go ServeAgent(NewKeyring(), c2) ++ ++ testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0) ++} ++ ++func TestLockServer(t *testing.T) { ++ testLockAgent(NewKeyring(), t) ++} ++ ++func TestSetupForwardAgent(t *testing.T) { ++ a, b, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ ++ defer a.Close() ++ defer b.Close() ++ ++ _, socket, cleanup := startOpenSSHAgent(t) ++ defer cleanup() ++ ++ serverConf := ssh.ServerConfig{ ++ NoClientAuth: true, ++ } ++ serverConf.AddHostKey(testSigners["rsa"]) ++ incoming := make(chan *ssh.ServerConn, 1) ++ go func() { ++ conn, _, _, err := ssh.NewServerConn(a, &serverConf) ++ incoming <- conn ++ if err != nil { ++ t.Errorf("NewServerConn error: %v", err) ++ return ++ } ++ }() ++ ++ conf := ssh.ClientConfig{ ++ HostKeyCallback: ssh.InsecureIgnoreHostKey(), ++ } ++ conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) ++ if err != nil { ++ t.Fatalf("NewClientConn: %v", err) ++ } ++ client := ssh.NewClient(conn, chans, reqs) ++ ++ if err := ForwardToRemote(client, socket); err != nil { ++ t.Fatalf("SetupForwardAgent: %v", err) ++ } ++ server := <-incoming ++ if server == nil { ++ t.Fatal("Unable to get server") ++ } ++ ch, reqs, err := server.OpenChannel(channelType, nil) ++ if err != nil { ++ t.Fatalf("OpenChannel(%q): %v", channelType, err) ++ } ++ go ssh.DiscardRequests(reqs) ++ ++ agentClient := NewClient(ch) ++ testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0) ++ conn.Close() ++} ++ ++func TestV1ProtocolMessages(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ c := NewClient(c1) ++ ++ go ServeAgent(NewKeyring(), c2) ++ ++ testV1ProtocolMessages(t, c.(*client)) ++} ++ ++func testV1ProtocolMessages(t *testing.T, c *client) { ++ reply, err := c.call([]byte{agentRequestV1Identities}) ++ if err != nil { ++ t.Fatalf("v1 request all failed: %v", err) ++ } ++ if msg, ok := reply.(*agentV1IdentityMsg); !ok || msg.Numkeys != 0 { ++ t.Fatalf("invalid request all response: %#v", reply) ++ } ++ ++ reply, err = c.call([]byte{agentRemoveAllV1Identities}) ++ if err != nil { ++ t.Fatalf("v1 remove all failed: %v", err) ++ } ++ if _, ok := reply.(*successAgentMsg); !ok { ++ t.Fatalf("invalid remove all response: %#v", reply) ++ } ++} ++ ++func verifyKey(sshAgent Agent) error { ++ keys, err := sshAgent.List() ++ if err != nil { ++ return fmt.Errorf("listing keys: %v", err) ++ } ++ ++ if len(keys) != 1 { ++ return fmt.Errorf("bad number of keys found. expected 1, got %d", len(keys)) ++ } ++ ++ buf := make([]byte, 128) ++ if _, err := rand.Read(buf); err != nil { ++ return fmt.Errorf("rand: %v", err) ++ } ++ ++ sig, err := sshAgent.Sign(keys[0], buf) ++ if err != nil { ++ return fmt.Errorf("sign: %v", err) ++ } ++ ++ if err := keys[0].Verify(buf, sig); err != nil { ++ return fmt.Errorf("verify: %v", err) ++ } ++ return nil ++} ++ ++func addKeyToAgent(key crypto.PrivateKey) error { ++ sshAgent := NewKeyring() ++ if err := sshAgent.Add(AddedKey{PrivateKey: key}); err != nil { ++ return fmt.Errorf("add: %v", err) ++ } ++ return verifyKey(sshAgent) ++} ++ ++func TestKeyTypes(t *testing.T) { ++ for k, v := range testPrivateKeys { ++ if err := addKeyToAgent(v); err != nil { ++ t.Errorf("error adding key type %s, %v", k, err) ++ } ++ if err := addCertToAgentSock(v, nil); err != nil { ++ t.Errorf("error adding key type %s, %v", k, err) ++ } ++ } ++} ++ ++func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error { ++ a, b, err := netPipe() ++ if err != nil { ++ return err ++ } ++ agentServer := NewKeyring() ++ go ServeAgent(agentServer, a) ++ ++ agentClient := NewClient(b) ++ if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { ++ return fmt.Errorf("add: %v", err) ++ } ++ return verifyKey(agentClient) ++} ++ ++func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error { ++ sshAgent := NewKeyring() ++ if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { ++ return fmt.Errorf("add: %v", err) ++ } ++ return verifyKey(sshAgent) ++} ++ ++func TestCertTypes(t *testing.T) { ++ for keyType, key := range testPublicKeys { ++ cert := &ssh.Certificate{ ++ ValidPrincipals: []string{"gopher1"}, ++ ValidAfter: 0, ++ ValidBefore: ssh.CertTimeInfinity, ++ Key: key, ++ Serial: 1, ++ CertType: ssh.UserCert, ++ SignatureKey: testPublicKeys["rsa"], ++ Permissions: ssh.Permissions{ ++ CriticalOptions: map[string]string{}, ++ Extensions: map[string]string{}, ++ }, ++ } ++ if err := cert.SignCert(rand.Reader, testSigners["rsa"]); err != nil { ++ t.Fatalf("signcert: %v", err) ++ } ++ if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil { ++ t.Fatalf("%v", err) ++ } ++ if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil { ++ t.Fatalf("%v", err) ++ } ++ } ++} ++ ++func TestParseConstraints(t *testing.T) { ++ // Test LifetimeSecs ++ var msg = constrainLifetimeAgentMsg{pseudorand.Uint32()} ++ lifetimeSecs, _, _, err := parseConstraints(ssh.Marshal(msg)) ++ if err != nil { ++ t.Fatalf("parseConstraints: %v", err) ++ } ++ if lifetimeSecs != msg.LifetimeSecs { ++ t.Errorf("got lifetime %v, want %v", lifetimeSecs, msg.LifetimeSecs) ++ } ++ ++ // Test ConfirmBeforeUse ++ _, confirmBeforeUse, _, err := parseConstraints([]byte{agentConstrainConfirm}) ++ if err != nil { ++ t.Fatalf("%v", err) ++ } ++ if !confirmBeforeUse { ++ t.Error("got comfirmBeforeUse == false") ++ } ++ ++ // Test ConstraintExtensions ++ var data []byte ++ var expect []ConstraintExtension ++ for i := 0; i < 10; i++ { ++ var ext = ConstraintExtension{ ++ ExtensionName: fmt.Sprintf("name%d", i), ++ ExtensionDetails: []byte(fmt.Sprintf("details: %d", i)), ++ } ++ expect = append(expect, ext) ++ data = append(data, agentConstrainExtension) ++ data = append(data, ssh.Marshal(ext)...) ++ } ++ _, _, extensions, err := parseConstraints(data) ++ if err != nil { ++ t.Fatalf("%v", err) ++ } ++ if !reflect.DeepEqual(expect, extensions) { ++ t.Errorf("got extension %v, want %v", extensions, expect) ++ } ++ ++ // Test Unknown Constraint ++ _, _, _, err = parseConstraints([]byte{128}) ++ if err == nil || !strings.Contains(err.Error(), "unknown constraint") { ++ t.Errorf("unexpected error: %v", err) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go +new file mode 100644 +index 00000000000000..cc42a87cb967ea +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go +@@ -0,0 +1,64 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: ++// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three ++// instances. ++ ++package agent ++ ++import ( ++ "crypto/rand" ++ "fmt" ++ ++ "golang.org/x/crypto/ssh" ++ "golang.org/x/crypto/ssh/testdata" ++) ++ ++var ( ++ testPrivateKeys map[string]interface{} ++ testSigners map[string]ssh.Signer ++ testPublicKeys map[string]ssh.PublicKey ++) ++ ++func init() { ++ var err error ++ ++ n := len(testdata.PEMBytes) ++ testPrivateKeys = make(map[string]interface{}, n) ++ testSigners = make(map[string]ssh.Signer, n) ++ testPublicKeys = make(map[string]ssh.PublicKey, n) ++ for t, k := range testdata.PEMBytes { ++ testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) ++ } ++ testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) ++ } ++ testPublicKeys[t] = testSigners[t].PublicKey() ++ } ++ ++ // Create a cert and sign it for use in tests. ++ testCert := &ssh.Certificate{ ++ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ++ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage ++ ValidAfter: 0, // unix epoch ++ ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. ++ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ++ Key: testPublicKeys["ecdsa"], ++ SignatureKey: testPublicKeys["rsa"], ++ Permissions: ssh.Permissions{ ++ CriticalOptions: map[string]string{}, ++ Extensions: map[string]string{}, ++ }, ++ } ++ testCert.SignCert(rand.Reader, testSigners["rsa"]) ++ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] ++ testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/benchmark_test.go b/ms_mod/golang.org/x/crypto/ssh/benchmark_test.go +new file mode 100644 +index 00000000000000..b356330b469d2e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/benchmark_test.go +@@ -0,0 +1,127 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ "net" ++ "testing" ++) ++ ++type server struct { ++ *ServerConn ++ chans <-chan NewChannel ++} ++ ++func newServer(c net.Conn, conf *ServerConfig) (*server, error) { ++ sconn, chans, reqs, err := NewServerConn(c, conf) ++ if err != nil { ++ return nil, err ++ } ++ go DiscardRequests(reqs) ++ return &server{sconn, chans}, nil ++} ++ ++func (s *server) Accept() (NewChannel, error) { ++ n, ok := <-s.chans ++ if !ok { ++ return nil, io.EOF ++ } ++ return n, nil ++} ++ ++func sshPipe() (Conn, *server, error) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ clientConf := ClientConfig{ ++ User: "user", ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ serverConf := ServerConfig{ ++ NoClientAuth: true, ++ } ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ done := make(chan *server, 1) ++ go func() { ++ server, err := newServer(c2, &serverConf) ++ if err != nil { ++ done <- nil ++ } ++ done <- server ++ }() ++ ++ client, _, reqs, err := NewClientConn(c1, "", &clientConf) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ server := <-done ++ if server == nil { ++ return nil, nil, errors.New("server handshake failed.") ++ } ++ go DiscardRequests(reqs) ++ ++ return client, server, nil ++} ++ ++func BenchmarkEndToEnd(b *testing.B) { ++ b.StopTimer() ++ ++ client, server, err := sshPipe() ++ if err != nil { ++ b.Fatalf("sshPipe: %v", err) ++ } ++ ++ defer client.Close() ++ defer server.Close() ++ ++ size := (1 << 20) ++ input := make([]byte, size) ++ output := make([]byte, size) ++ b.SetBytes(int64(size)) ++ done := make(chan int, 1) ++ ++ go func() { ++ newCh, err := server.Accept() ++ if err != nil { ++ panic(fmt.Sprintf("Client: %v", err)) ++ } ++ ch, incoming, err := newCh.Accept() ++ if err != nil { ++ panic(fmt.Sprintf("Accept: %v", err)) ++ } ++ go DiscardRequests(incoming) ++ for i := 0; i < b.N; i++ { ++ if _, err := io.ReadFull(ch, output); err != nil { ++ panic(fmt.Sprintf("ReadFull: %v", err)) ++ } ++ } ++ ch.Close() ++ done <- 1 ++ }() ++ ++ ch, in, err := client.OpenChannel("speed", nil) ++ if err != nil { ++ b.Fatalf("OpenChannel: %v", err) ++ } ++ go DiscardRequests(in) ++ ++ b.ResetTimer() ++ b.StartTimer() ++ for i := 0; i < b.N; i++ { ++ if _, err := ch.Write(input); err != nil { ++ b.Fatalf("WriteFull: %v", err) ++ } ++ } ++ ch.Close() ++ b.StopTimer() ++ ++ <-done ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/buffer.go b/ms_mod/golang.org/x/crypto/ssh/buffer.go +new file mode 100644 +index 00000000000000..1ab07d078db163 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/buffer.go +@@ -0,0 +1,97 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "io" ++ "sync" ++) ++ ++// buffer provides a linked list buffer for data exchange ++// between producer and consumer. Theoretically the buffer is ++// of unlimited capacity as it does no allocation of its own. ++type buffer struct { ++ // protects concurrent access to head, tail and closed ++ *sync.Cond ++ ++ head *element // the buffer that will be read first ++ tail *element // the buffer that will be read last ++ ++ closed bool ++} ++ ++// An element represents a single link in a linked list. ++type element struct { ++ buf []byte ++ next *element ++} ++ ++// newBuffer returns an empty buffer that is not closed. ++func newBuffer() *buffer { ++ e := new(element) ++ b := &buffer{ ++ Cond: newCond(), ++ head: e, ++ tail: e, ++ } ++ return b ++} ++ ++// write makes buf available for Read to receive. ++// buf must not be modified after the call to write. ++func (b *buffer) write(buf []byte) { ++ b.Cond.L.Lock() ++ e := &element{buf: buf} ++ b.tail.next = e ++ b.tail = e ++ b.Cond.Signal() ++ b.Cond.L.Unlock() ++} ++ ++// eof closes the buffer. Reads from the buffer once all ++// the data has been consumed will receive io.EOF. ++func (b *buffer) eof() { ++ b.Cond.L.Lock() ++ b.closed = true ++ b.Cond.Signal() ++ b.Cond.L.Unlock() ++} ++ ++// Read reads data from the internal buffer in buf. Reads will block ++// if no data is available, or until the buffer is closed. ++func (b *buffer) Read(buf []byte) (n int, err error) { ++ b.Cond.L.Lock() ++ defer b.Cond.L.Unlock() ++ ++ for len(buf) > 0 { ++ // if there is data in b.head, copy it ++ if len(b.head.buf) > 0 { ++ r := copy(buf, b.head.buf) ++ buf, b.head.buf = buf[r:], b.head.buf[r:] ++ n += r ++ continue ++ } ++ // if there is a next buffer, make it the head ++ if len(b.head.buf) == 0 && b.head != b.tail { ++ b.head = b.head.next ++ continue ++ } ++ ++ // if at least one byte has been copied, return ++ if n > 0 { ++ break ++ } ++ ++ // if nothing was read, and there is nothing outstanding ++ // check to see if the buffer is closed. ++ if b.closed { ++ err = io.EOF ++ break ++ } ++ // out of buffers, wait for producer ++ b.Cond.Wait() ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/buffer_test.go b/ms_mod/golang.org/x/crypto/ssh/buffer_test.go +new file mode 100644 +index 00000000000000..d5781cb3da997f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/buffer_test.go +@@ -0,0 +1,87 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "io" ++ "testing" ++) ++ ++var alphabet = []byte("abcdefghijklmnopqrstuvwxyz") ++ ++func TestBufferReadwrite(t *testing.T) { ++ b := newBuffer() ++ b.write(alphabet[:10]) ++ r, _ := b.Read(make([]byte, 10)) ++ if r != 10 { ++ t.Fatalf("Expected written == read == 10, written: 10, read %d", r) ++ } ++ ++ b = newBuffer() ++ b.write(alphabet[:5]) ++ r, _ = b.Read(make([]byte, 10)) ++ if r != 5 { ++ t.Fatalf("Expected written == read == 5, written: 5, read %d", r) ++ } ++ ++ b = newBuffer() ++ b.write(alphabet[:10]) ++ r, _ = b.Read(make([]byte, 5)) ++ if r != 5 { ++ t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r) ++ } ++ ++ b = newBuffer() ++ b.write(alphabet[:5]) ++ b.write(alphabet[5:15]) ++ r, _ = b.Read(make([]byte, 10)) ++ r2, _ := b.Read(make([]byte, 10)) ++ if r != 10 || r2 != 5 || 15 != r+r2 { ++ t.Fatal("Expected written == read == 15") ++ } ++} ++ ++func TestBufferClose(t *testing.T) { ++ b := newBuffer() ++ b.write(alphabet[:10]) ++ b.eof() ++ _, err := b.Read(make([]byte, 5)) ++ if err != nil { ++ t.Fatal("expected read of 5 to not return EOF") ++ } ++ b = newBuffer() ++ b.write(alphabet[:10]) ++ b.eof() ++ r, err := b.Read(make([]byte, 5)) ++ r2, err2 := b.Read(make([]byte, 10)) ++ if r != 5 || r2 != 5 || err != nil || err2 != nil { ++ t.Fatal("expected reads of 5 and 5") ++ } ++ ++ b = newBuffer() ++ b.write(alphabet[:10]) ++ b.eof() ++ r, err = b.Read(make([]byte, 5)) ++ r2, err2 = b.Read(make([]byte, 10)) ++ r3, err3 := b.Read(make([]byte, 10)) ++ if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF { ++ t.Fatal("expected reads of 5 and 5 and 0, with EOF") ++ } ++ ++ b = newBuffer() ++ b.write(make([]byte, 5)) ++ b.write(make([]byte, 10)) ++ b.eof() ++ r, err = b.Read(make([]byte, 9)) ++ r2, err2 = b.Read(make([]byte, 3)) ++ r3, err3 = b.Read(make([]byte, 3)) ++ r4, err4 := b.Read(make([]byte, 10)) ++ if err != nil || err2 != nil || err3 != nil || err4 != io.EOF { ++ t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4) ++ } ++ if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 { ++ t.Fatal("Expected written == read == 15", r, r2, r3, r4) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/certs.go b/ms_mod/golang.org/x/crypto/ssh/certs.go +new file mode 100644 +index 00000000000000..fc04d03e19879d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/certs.go +@@ -0,0 +1,589 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "io" ++ "net" ++ "sort" ++ "time" ++) ++ ++// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear ++// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. ++// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't ++// appear in the Signature.Format field. ++const ( ++ CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" ++ CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" ++ CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" ++ CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" ++ CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" ++ CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" ++ CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" ++ CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" ++ ++ // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a ++ // Certificate.Type (or PublicKey.Type), but only in ++ // ClientConfig.HostKeyAlgorithms. ++ CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com" ++ CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com" ++) ++ ++const ( ++ // Deprecated: use CertAlgoRSAv01. ++ CertSigAlgoRSAv01 = CertAlgoRSAv01 ++ // Deprecated: use CertAlgoRSASHA256v01. ++ CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01 ++ // Deprecated: use CertAlgoRSASHA512v01. ++ CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01 ++) ++ ++// Certificate types distinguish between host and user ++// certificates. The values can be set in the CertType field of ++// Certificate. ++const ( ++ UserCert = 1 ++ HostCert = 2 ++) ++ ++// Signature represents a cryptographic signature. ++type Signature struct { ++ Format string ++ Blob []byte ++ Rest []byte `ssh:"rest"` ++} ++ ++// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that ++// a certificate does not expire. ++const CertTimeInfinity = 1<<64 - 1 ++ ++// An Certificate represents an OpenSSH certificate as defined in ++// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the ++// PublicKey interface, so it can be unmarshaled using ++// ParsePublicKey. ++type Certificate struct { ++ Nonce []byte ++ Key PublicKey ++ Serial uint64 ++ CertType uint32 ++ KeyId string ++ ValidPrincipals []string ++ ValidAfter uint64 ++ ValidBefore uint64 ++ Permissions ++ Reserved []byte ++ SignatureKey PublicKey ++ Signature *Signature ++} ++ ++// genericCertData holds the key-independent part of the certificate data. ++// Overall, certificates contain an nonce, public key fields and ++// key-independent fields. ++type genericCertData struct { ++ Serial uint64 ++ CertType uint32 ++ KeyId string ++ ValidPrincipals []byte ++ ValidAfter uint64 ++ ValidBefore uint64 ++ CriticalOptions []byte ++ Extensions []byte ++ Reserved []byte ++ SignatureKey []byte ++ Signature []byte ++} ++ ++func marshalStringList(namelist []string) []byte { ++ var to []byte ++ for _, name := range namelist { ++ s := struct{ N string }{name} ++ to = append(to, Marshal(&s)...) ++ } ++ return to ++} ++ ++type optionsTuple struct { ++ Key string ++ Value []byte ++} ++ ++type optionsTupleValue struct { ++ Value string ++} ++ ++// serialize a map of critical options or extensions ++// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, ++// we need two length prefixes for a non-empty string value ++func marshalTuples(tups map[string]string) []byte { ++ keys := make([]string, 0, len(tups)) ++ for key := range tups { ++ keys = append(keys, key) ++ } ++ sort.Strings(keys) ++ ++ var ret []byte ++ for _, key := range keys { ++ s := optionsTuple{Key: key} ++ if value := tups[key]; len(value) > 0 { ++ s.Value = Marshal(&optionsTupleValue{value}) ++ } ++ ret = append(ret, Marshal(&s)...) ++ } ++ return ret ++} ++ ++// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, ++// we need two length prefixes for a non-empty option value ++func parseTuples(in []byte) (map[string]string, error) { ++ tups := map[string]string{} ++ var lastKey string ++ var haveLastKey bool ++ ++ for len(in) > 0 { ++ var key, val, extra []byte ++ var ok bool ++ ++ if key, in, ok = parseString(in); !ok { ++ return nil, errShortRead ++ } ++ keyStr := string(key) ++ // according to [PROTOCOL.certkeys], the names must be in ++ // lexical order. ++ if haveLastKey && keyStr <= lastKey { ++ return nil, fmt.Errorf("ssh: certificate options are not in lexical order") ++ } ++ lastKey, haveLastKey = keyStr, true ++ // the next field is a data field, which if non-empty has a string embedded ++ if val, in, ok = parseString(in); !ok { ++ return nil, errShortRead ++ } ++ if len(val) > 0 { ++ val, extra, ok = parseString(val) ++ if !ok { ++ return nil, errShortRead ++ } ++ if len(extra) > 0 { ++ return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") ++ } ++ tups[keyStr] = string(val) ++ } else { ++ tups[keyStr] = "" ++ } ++ } ++ return tups, nil ++} ++ ++func parseCert(in []byte, privAlgo string) (*Certificate, error) { ++ nonce, rest, ok := parseString(in) ++ if !ok { ++ return nil, errShortRead ++ } ++ ++ key, rest, err := parsePubKey(rest, privAlgo) ++ if err != nil { ++ return nil, err ++ } ++ ++ var g genericCertData ++ if err := Unmarshal(rest, &g); err != nil { ++ return nil, err ++ } ++ ++ c := &Certificate{ ++ Nonce: nonce, ++ Key: key, ++ Serial: g.Serial, ++ CertType: g.CertType, ++ KeyId: g.KeyId, ++ ValidAfter: g.ValidAfter, ++ ValidBefore: g.ValidBefore, ++ } ++ ++ for principals := g.ValidPrincipals; len(principals) > 0; { ++ principal, rest, ok := parseString(principals) ++ if !ok { ++ return nil, errShortRead ++ } ++ c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) ++ principals = rest ++ } ++ ++ c.CriticalOptions, err = parseTuples(g.CriticalOptions) ++ if err != nil { ++ return nil, err ++ } ++ c.Extensions, err = parseTuples(g.Extensions) ++ if err != nil { ++ return nil, err ++ } ++ c.Reserved = g.Reserved ++ k, err := ParsePublicKey(g.SignatureKey) ++ if err != nil { ++ return nil, err ++ } ++ ++ c.SignatureKey = k ++ c.Signature, rest, ok = parseSignatureBody(g.Signature) ++ if !ok || len(rest) > 0 { ++ return nil, errors.New("ssh: signature parse error") ++ } ++ ++ return c, nil ++} ++ ++type openSSHCertSigner struct { ++ pub *Certificate ++ signer Signer ++} ++ ++type algorithmOpenSSHCertSigner struct { ++ *openSSHCertSigner ++ algorithmSigner AlgorithmSigner ++} ++ ++// NewCertSigner returns a Signer that signs with the given Certificate, whose ++// private key is held by signer. It returns an error if the public key in cert ++// doesn't match the key used by signer. ++func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { ++ if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { ++ return nil, errors.New("ssh: signer and cert have different public key") ++ } ++ ++ if algorithmSigner, ok := signer.(AlgorithmSigner); ok { ++ return &algorithmOpenSSHCertSigner{ ++ &openSSHCertSigner{cert, signer}, algorithmSigner}, nil ++ } else { ++ return &openSSHCertSigner{cert, signer}, nil ++ } ++} ++ ++func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { ++ return s.signer.Sign(rand, data) ++} ++ ++func (s *openSSHCertSigner) PublicKey() PublicKey { ++ return s.pub ++} ++ ++func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { ++ return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm) ++} ++ ++const sourceAddressCriticalOption = "source-address" ++ ++// CertChecker does the work of verifying a certificate. Its methods ++// can be plugged into ClientConfig.HostKeyCallback and ++// ServerConfig.PublicKeyCallback. For the CertChecker to work, ++// minimally, the IsAuthority callback should be set. ++type CertChecker struct { ++ // SupportedCriticalOptions lists the CriticalOptions that the ++ // server application layer understands. These are only used ++ // for user certificates. ++ SupportedCriticalOptions []string ++ ++ // IsUserAuthority should return true if the key is recognized as an ++ // authority for the given user certificate. This allows for ++ // certificates to be signed by other certificates. This must be set ++ // if this CertChecker will be checking user certificates. ++ IsUserAuthority func(auth PublicKey) bool ++ ++ // IsHostAuthority should report whether the key is recognized as ++ // an authority for this host. This allows for certificates to be ++ // signed by other keys, and for those other keys to only be valid ++ // signers for particular hostnames. This must be set if this ++ // CertChecker will be checking host certificates. ++ IsHostAuthority func(auth PublicKey, address string) bool ++ ++ // Clock is used for verifying time stamps. If nil, time.Now ++ // is used. ++ Clock func() time.Time ++ ++ // UserKeyFallback is called when CertChecker.Authenticate encounters a ++ // public key that is not a certificate. It must implement validation ++ // of user keys or else, if nil, all such keys are rejected. ++ UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) ++ ++ // HostKeyFallback is called when CertChecker.CheckHostKey encounters a ++ // public key that is not a certificate. It must implement host key ++ // validation or else, if nil, all such keys are rejected. ++ HostKeyFallback HostKeyCallback ++ ++ // IsRevoked is called for each certificate so that revocation checking ++ // can be implemented. It should return true if the given certificate ++ // is revoked and false otherwise. If nil, no certificates are ++ // considered to have been revoked. ++ IsRevoked func(cert *Certificate) bool ++} ++ ++// CheckHostKey checks a host key certificate. This method can be ++// plugged into ClientConfig.HostKeyCallback. ++func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { ++ cert, ok := key.(*Certificate) ++ if !ok { ++ if c.HostKeyFallback != nil { ++ return c.HostKeyFallback(addr, remote, key) ++ } ++ return errors.New("ssh: non-certificate host key") ++ } ++ if cert.CertType != HostCert { ++ return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) ++ } ++ if !c.IsHostAuthority(cert.SignatureKey, addr) { ++ return fmt.Errorf("ssh: no authorities for hostname: %v", addr) ++ } ++ ++ hostname, _, err := net.SplitHostPort(addr) ++ if err != nil { ++ return err ++ } ++ ++ // Pass hostname only as principal for host certificates (consistent with OpenSSH) ++ return c.CheckCert(hostname, cert) ++} ++ ++// Authenticate checks a user certificate. Authenticate can be used as ++// a value for ServerConfig.PublicKeyCallback. ++func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { ++ cert, ok := pubKey.(*Certificate) ++ if !ok { ++ if c.UserKeyFallback != nil { ++ return c.UserKeyFallback(conn, pubKey) ++ } ++ return nil, errors.New("ssh: normal key pairs not accepted") ++ } ++ ++ if cert.CertType != UserCert { ++ return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) ++ } ++ if !c.IsUserAuthority(cert.SignatureKey) { ++ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") ++ } ++ ++ if err := c.CheckCert(conn.User(), cert); err != nil { ++ return nil, err ++ } ++ ++ return &cert.Permissions, nil ++} ++ ++// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and ++// the signature of the certificate. ++func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { ++ if c.IsRevoked != nil && c.IsRevoked(cert) { ++ return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) ++ } ++ ++ for opt := range cert.CriticalOptions { ++ // sourceAddressCriticalOption will be enforced by ++ // serverAuthenticate ++ if opt == sourceAddressCriticalOption { ++ continue ++ } ++ ++ found := false ++ for _, supp := range c.SupportedCriticalOptions { ++ if supp == opt { ++ found = true ++ break ++ } ++ } ++ if !found { ++ return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) ++ } ++ } ++ ++ if len(cert.ValidPrincipals) > 0 { ++ // By default, certs are valid for all users/hosts. ++ found := false ++ for _, p := range cert.ValidPrincipals { ++ if p == principal { ++ found = true ++ break ++ } ++ } ++ if !found { ++ return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) ++ } ++ } ++ ++ clock := c.Clock ++ if clock == nil { ++ clock = time.Now ++ } ++ ++ unixNow := clock().Unix() ++ if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { ++ return fmt.Errorf("ssh: cert is not yet valid") ++ } ++ if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { ++ return fmt.Errorf("ssh: cert has expired") ++ } ++ if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { ++ return fmt.Errorf("ssh: certificate signature does not verify") ++ } ++ ++ return nil ++} ++ ++// SignCert signs the certificate with an authority, setting the Nonce, ++// SignatureKey, and Signature fields. ++func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { ++ c.Nonce = make([]byte, 32) ++ if _, err := io.ReadFull(rand, c.Nonce); err != nil { ++ return err ++ } ++ c.SignatureKey = authority.PublicKey() ++ ++ // Default to KeyAlgoRSASHA512 for ssh-rsa signers. ++ if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { ++ sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512) ++ if err != nil { ++ return err ++ } ++ c.Signature = sig ++ return nil ++ } ++ ++ sig, err := authority.Sign(rand, c.bytesForSigning()) ++ if err != nil { ++ return err ++ } ++ c.Signature = sig ++ return nil ++} ++ ++// certKeyAlgoNames is a mapping from known certificate algorithm names to the ++// corresponding public key signature algorithm. ++// ++// This map must be kept in sync with the one in agent/client.go. ++var certKeyAlgoNames = map[string]string{ ++ CertAlgoRSAv01: KeyAlgoRSA, ++ CertAlgoRSASHA256v01: KeyAlgoRSASHA256, ++ CertAlgoRSASHA512v01: KeyAlgoRSASHA512, ++ CertAlgoDSAv01: KeyAlgoDSA, ++ CertAlgoECDSA256v01: KeyAlgoECDSA256, ++ CertAlgoECDSA384v01: KeyAlgoECDSA384, ++ CertAlgoECDSA521v01: KeyAlgoECDSA521, ++ CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, ++ CertAlgoED25519v01: KeyAlgoED25519, ++ CertAlgoSKED25519v01: KeyAlgoSKED25519, ++} ++ ++// underlyingAlgo returns the signature algorithm associated with algo (which is ++// an advertised or negotiated public key or host key algorithm). These are ++// usually the same, except for certificate algorithms. ++func underlyingAlgo(algo string) string { ++ if a, ok := certKeyAlgoNames[algo]; ok { ++ return a ++ } ++ return algo ++} ++ ++// certificateAlgo returns the certificate algorithms that uses the provided ++// underlying signature algorithm. ++func certificateAlgo(algo string) (certAlgo string, ok bool) { ++ for certName, algoName := range certKeyAlgoNames { ++ if algoName == algo { ++ return certName, true ++ } ++ } ++ return "", false ++} ++ ++func (cert *Certificate) bytesForSigning() []byte { ++ c2 := *cert ++ c2.Signature = nil ++ out := c2.Marshal() ++ // Drop trailing signature length. ++ return out[:len(out)-4] ++} ++ ++// Marshal serializes c into OpenSSH's wire format. It is part of the ++// PublicKey interface. ++func (c *Certificate) Marshal() []byte { ++ generic := genericCertData{ ++ Serial: c.Serial, ++ CertType: c.CertType, ++ KeyId: c.KeyId, ++ ValidPrincipals: marshalStringList(c.ValidPrincipals), ++ ValidAfter: uint64(c.ValidAfter), ++ ValidBefore: uint64(c.ValidBefore), ++ CriticalOptions: marshalTuples(c.CriticalOptions), ++ Extensions: marshalTuples(c.Extensions), ++ Reserved: c.Reserved, ++ SignatureKey: c.SignatureKey.Marshal(), ++ } ++ if c.Signature != nil { ++ generic.Signature = Marshal(c.Signature) ++ } ++ genericBytes := Marshal(&generic) ++ keyBytes := c.Key.Marshal() ++ _, keyBytes, _ = parseString(keyBytes) ++ prefix := Marshal(&struct { ++ Name string ++ Nonce []byte ++ Key []byte `ssh:"rest"` ++ }{c.Type(), c.Nonce, keyBytes}) ++ ++ result := make([]byte, 0, len(prefix)+len(genericBytes)) ++ result = append(result, prefix...) ++ result = append(result, genericBytes...) ++ return result ++} ++ ++// Type returns the certificate algorithm name. It is part of the PublicKey interface. ++func (c *Certificate) Type() string { ++ certName, ok := certificateAlgo(c.Key.Type()) ++ if !ok { ++ panic("unknown certificate type for key type " + c.Key.Type()) ++ } ++ return certName ++} ++ ++// Verify verifies a signature against the certificate's public ++// key. It is part of the PublicKey interface. ++func (c *Certificate) Verify(data []byte, sig *Signature) error { ++ return c.Key.Verify(data, sig) ++} ++ ++func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { ++ format, in, ok := parseString(in) ++ if !ok { ++ return ++ } ++ ++ out = &Signature{ ++ Format: string(format), ++ } ++ ++ if out.Blob, in, ok = parseString(in); !ok { ++ return ++ } ++ ++ switch out.Format { ++ case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01: ++ out.Rest = in ++ return out, nil, ok ++ } ++ ++ return out, in, ok ++} ++ ++func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { ++ sigBytes, rest, ok := parseString(in) ++ if !ok { ++ return ++ } ++ ++ out, trailing, ok := parseSignatureBody(sigBytes) ++ if !ok || len(trailing) > 0 { ++ return nil, nil, false ++ } ++ return ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/certs_test.go b/ms_mod/golang.org/x/crypto/ssh/certs_test.go +new file mode 100644 +index 00000000000000..e6004835ea411a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/certs_test.go +@@ -0,0 +1,320 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "fmt" ++ "io" ++ "net" ++ "reflect" ++ "testing" ++ "time" ++) ++ ++// Cert generated by ssh-keygen 6.0p1 Debian-4. ++// % ssh-keygen -s ca-key -I test user-key ++const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` ++ ++func TestParseCert(t *testing.T) { ++ authKeyBytes := []byte(exampleSSHCert) ++ ++ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) ++ if err != nil { ++ t.Fatalf("ParseAuthorizedKey: %v", err) ++ } ++ if len(rest) > 0 { ++ t.Errorf("rest: got %q, want empty", rest) ++ } ++ ++ if _, ok := key.(*Certificate); !ok { ++ t.Fatalf("got %v (%T), want *Certificate", key, key) ++ } ++ ++ marshaled := MarshalAuthorizedKey(key) ++ // Before comparison, remove the trailing newline that ++ // MarshalAuthorizedKey adds. ++ marshaled = marshaled[:len(marshaled)-1] ++ if !bytes.Equal(authKeyBytes, marshaled) { ++ t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) ++ } ++} ++ ++// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3 ++// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub ++// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN ++// Critical Options: ++// ++// force-command /bin/sleep ++// source-address 192.168.1.0/24 ++// ++// Extensions: ++// ++// permit-X11-forwarding ++// permit-agent-forwarding ++// permit-port-forwarding ++// permit-pty ++// permit-user-rc ++const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` ++ ++func TestParseCertWithOptions(t *testing.T) { ++ opts := map[string]string{ ++ "source-address": "192.168.1.0/24", ++ "force-command": "/bin/sleep", ++ } ++ exts := map[string]string{ ++ "permit-X11-forwarding": "", ++ "permit-agent-forwarding": "", ++ "permit-port-forwarding": "", ++ "permit-pty": "", ++ "permit-user-rc": "", ++ } ++ authKeyBytes := []byte(exampleSSHCertWithOptions) ++ ++ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) ++ if err != nil { ++ t.Fatalf("ParseAuthorizedKey: %v", err) ++ } ++ if len(rest) > 0 { ++ t.Errorf("rest: got %q, want empty", rest) ++ } ++ cert, ok := key.(*Certificate) ++ if !ok { ++ t.Fatalf("got %v (%T), want *Certificate", key, key) ++ } ++ if !reflect.DeepEqual(cert.CriticalOptions, opts) { ++ t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts) ++ } ++ if !reflect.DeepEqual(cert.Extensions, exts) { ++ t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts) ++ } ++ marshaled := MarshalAuthorizedKey(key) ++ // Before comparison, remove the trailing newline that ++ // MarshalAuthorizedKey adds. ++ marshaled = marshaled[:len(marshaled)-1] ++ if !bytes.Equal(authKeyBytes, marshaled) { ++ t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) ++ } ++} ++ ++func TestValidateCert(t *testing.T) { ++ key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) ++ if err != nil { ++ t.Fatalf("ParseAuthorizedKey: %v", err) ++ } ++ validCert, ok := key.(*Certificate) ++ if !ok { ++ t.Fatalf("got %v (%T), want *Certificate", key, key) ++ } ++ checker := CertChecker{} ++ checker.IsUserAuthority = func(k PublicKey) bool { ++ return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) ++ } ++ ++ if err := checker.CheckCert("user", validCert); err != nil { ++ t.Errorf("Unable to validate certificate: %v", err) ++ } ++ invalidCert := &Certificate{ ++ Key: testPublicKeys["rsa"], ++ SignatureKey: testPublicKeys["ecdsa"], ++ ValidBefore: CertTimeInfinity, ++ Signature: &Signature{}, ++ } ++ if err := checker.CheckCert("user", invalidCert); err == nil { ++ t.Error("Invalid cert signature passed validation") ++ } ++} ++ ++func TestValidateCertTime(t *testing.T) { ++ cert := Certificate{ ++ ValidPrincipals: []string{"user"}, ++ Key: testPublicKeys["rsa"], ++ ValidAfter: 50, ++ ValidBefore: 100, ++ } ++ ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ ++ for ts, ok := range map[int64]bool{ ++ 25: false, ++ 50: true, ++ 99: true, ++ 100: false, ++ 125: false, ++ } { ++ checker := CertChecker{ ++ Clock: func() time.Time { return time.Unix(ts, 0) }, ++ } ++ checker.IsUserAuthority = func(k PublicKey) bool { ++ return bytes.Equal(k.Marshal(), ++ testPublicKeys["ecdsa"].Marshal()) ++ } ++ ++ if v := checker.CheckCert("user", &cert); (v == nil) != ok { ++ t.Errorf("Authenticate(%d): %v", ts, v) ++ } ++ } ++} ++ ++// TODO(hanwen): tests for ++// ++// host keys: ++// * fallbacks ++ ++func TestHostKeyCert(t *testing.T) { ++ cert := &Certificate{ ++ ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"}, ++ Key: testPublicKeys["rsa"], ++ ValidBefore: CertTimeInfinity, ++ CertType: HostCert, ++ } ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ ++ checker := &CertChecker{ ++ IsHostAuthority: func(p PublicKey, addr string) bool { ++ return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) ++ }, ++ } ++ ++ certSigner, err := NewCertSigner(cert, testSigners["rsa"]) ++ if err != nil { ++ t.Errorf("NewCertSigner: %v", err) ++ } ++ ++ for _, test := range []struct { ++ addr string ++ succeed bool ++ }{ ++ {addr: "hostname:22", succeed: true}, ++ {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22' ++ {addr: "lasthost:22", succeed: false}, ++ } { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ errc := make(chan error) ++ ++ go func() { ++ conf := ServerConfig{ ++ NoClientAuth: true, ++ } ++ conf.AddHostKey(certSigner) ++ _, _, _, err := NewServerConn(c1, &conf) ++ errc <- err ++ }() ++ ++ config := &ClientConfig{ ++ User: "user", ++ HostKeyCallback: checker.CheckHostKey, ++ } ++ _, _, _, err = NewClientConn(c2, test.addr, config) ++ ++ if (err == nil) != test.succeed { ++ t.Errorf("NewClientConn(%q): %v", test.addr, err) ++ } ++ ++ err = <-errc ++ if (err == nil) != test.succeed { ++ t.Errorf("NewServerConn(%q): %v", test.addr, err) ++ } ++ } ++} ++ ++type legacyRSASigner struct { ++ Signer ++} ++ ++func (s *legacyRSASigner) Sign(rand io.Reader, data []byte) (*Signature, error) { ++ v, ok := s.Signer.(AlgorithmSigner) ++ if !ok { ++ return nil, fmt.Errorf("invalid signer") ++ } ++ return v.SignWithAlgorithm(rand, data, KeyAlgoRSA) ++} ++ ++func TestCertTypes(t *testing.T) { ++ var testVars = []struct { ++ name string ++ signer Signer ++ algo string ++ }{ ++ {CertAlgoECDSA256v01, testSigners["ecdsap256"], ""}, ++ {CertAlgoECDSA384v01, testSigners["ecdsap384"], ""}, ++ {CertAlgoECDSA521v01, testSigners["ecdsap521"], ""}, ++ {CertAlgoED25519v01, testSigners["ed25519"], ""}, ++ {CertAlgoRSAv01, testSigners["rsa"], KeyAlgoRSASHA512}, ++ {"legacyRSASigner", &legacyRSASigner{testSigners["rsa"]}, KeyAlgoRSA}, ++ {CertAlgoDSAv01, testSigners["dsa"], ""}, ++ } ++ ++ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ++ if err != nil { ++ t.Fatalf("error generating host key: %v", err) ++ } ++ ++ signer, err := NewSignerFromKey(k) ++ if err != nil { ++ t.Fatalf("error generating signer for ssh listener: %v", err) ++ } ++ ++ conf := &ServerConfig{ ++ PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) { ++ return new(Permissions), nil ++ }, ++ } ++ conf.AddHostKey(signer) ++ ++ for _, m := range testVars { ++ t.Run(m.name, func(t *testing.T) { ++ ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go NewServerConn(c1, conf) ++ ++ priv := m.signer ++ if err != nil { ++ t.Fatalf("error generating ssh pubkey: %v", err) ++ } ++ ++ cert := &Certificate{ ++ CertType: UserCert, ++ Key: priv.PublicKey(), ++ } ++ cert.SignCert(rand.Reader, priv) ++ ++ certSigner, err := NewCertSigner(cert, priv) ++ if err != nil { ++ t.Fatalf("error generating cert signer: %v", err) ++ } ++ ++ if m.algo != "" && cert.Signature.Format != m.algo { ++ t.Errorf("expected %q signature format, got %q", m.algo, cert.Signature.Format) ++ } ++ ++ config := &ClientConfig{ ++ User: "user", ++ HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil }, ++ Auth: []AuthMethod{PublicKeys(certSigner)}, ++ } ++ ++ _, _, _, err = NewClientConn(c2, "", config) ++ if err != nil { ++ t.Fatalf("error connecting: %v", err) ++ } ++ }) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/channel.go b/ms_mod/golang.org/x/crypto/ssh/channel.go +new file mode 100644 +index 00000000000000..c0834c00dfee9a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/channel.go +@@ -0,0 +1,633 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "io" ++ "log" ++ "sync" ++) ++ ++const ( ++ minPacketLength = 9 ++ // channelMaxPacket contains the maximum number of bytes that will be ++ // sent in a single packet. As per RFC 4253, section 6.1, 32k is also ++ // the minimum. ++ channelMaxPacket = 1 << 15 ++ // We follow OpenSSH here. ++ channelWindowSize = 64 * channelMaxPacket ++) ++ ++// NewChannel represents an incoming request to a channel. It must either be ++// accepted for use by calling Accept, or rejected by calling Reject. ++type NewChannel interface { ++ // Accept accepts the channel creation request. It returns the Channel ++ // and a Go channel containing SSH requests. The Go channel must be ++ // serviced otherwise the Channel will hang. ++ Accept() (Channel, <-chan *Request, error) ++ ++ // Reject rejects the channel creation request. After calling ++ // this, no other methods on the Channel may be called. ++ Reject(reason RejectionReason, message string) error ++ ++ // ChannelType returns the type of the channel, as supplied by the ++ // client. ++ ChannelType() string ++ ++ // ExtraData returns the arbitrary payload for this channel, as supplied ++ // by the client. This data is specific to the channel type. ++ ExtraData() []byte ++} ++ ++// A Channel is an ordered, reliable, flow-controlled, duplex stream ++// that is multiplexed over an SSH connection. ++type Channel interface { ++ // Read reads up to len(data) bytes from the channel. ++ Read(data []byte) (int, error) ++ ++ // Write writes len(data) bytes to the channel. ++ Write(data []byte) (int, error) ++ ++ // Close signals end of channel use. No data may be sent after this ++ // call. ++ Close() error ++ ++ // CloseWrite signals the end of sending in-band ++ // data. Requests may still be sent, and the other side may ++ // still send data ++ CloseWrite() error ++ ++ // SendRequest sends a channel request. If wantReply is true, ++ // it will wait for a reply and return the result as a ++ // boolean, otherwise the return value will be false. Channel ++ // requests are out-of-band messages so they may be sent even ++ // if the data stream is closed or blocked by flow control. ++ // If the channel is closed before a reply is returned, io.EOF ++ // is returned. ++ SendRequest(name string, wantReply bool, payload []byte) (bool, error) ++ ++ // Stderr returns an io.ReadWriter that writes to this channel ++ // with the extended data type set to stderr. Stderr may ++ // safely be read and written from a different goroutine than ++ // Read and Write respectively. ++ Stderr() io.ReadWriter ++} ++ ++// Request is a request sent outside of the normal stream of ++// data. Requests can either be specific to an SSH channel, or they ++// can be global. ++type Request struct { ++ Type string ++ WantReply bool ++ Payload []byte ++ ++ ch *channel ++ mux *mux ++} ++ ++// Reply sends a response to a request. It must be called for all requests ++// where WantReply is true and is a no-op otherwise. The payload argument is ++// ignored for replies to channel-specific requests. ++func (r *Request) Reply(ok bool, payload []byte) error { ++ if !r.WantReply { ++ return nil ++ } ++ ++ if r.ch == nil { ++ return r.mux.ackRequest(ok, payload) ++ } ++ ++ return r.ch.ackRequest(ok) ++} ++ ++// RejectionReason is an enumeration used when rejecting channel creation ++// requests. See RFC 4254, section 5.1. ++type RejectionReason uint32 ++ ++const ( ++ Prohibited RejectionReason = iota + 1 ++ ConnectionFailed ++ UnknownChannelType ++ ResourceShortage ++) ++ ++// String converts the rejection reason to human readable form. ++func (r RejectionReason) String() string { ++ switch r { ++ case Prohibited: ++ return "administratively prohibited" ++ case ConnectionFailed: ++ return "connect failed" ++ case UnknownChannelType: ++ return "unknown channel type" ++ case ResourceShortage: ++ return "resource shortage" ++ } ++ return fmt.Sprintf("unknown reason %d", int(r)) ++} ++ ++func min(a uint32, b int) uint32 { ++ if a < uint32(b) { ++ return a ++ } ++ return uint32(b) ++} ++ ++type channelDirection uint8 ++ ++const ( ++ channelInbound channelDirection = iota ++ channelOutbound ++) ++ ++// channel is an implementation of the Channel interface that works ++// with the mux class. ++type channel struct { ++ // R/O after creation ++ chanType string ++ extraData []byte ++ localId, remoteId uint32 ++ ++ // maxIncomingPayload and maxRemotePayload are the maximum ++ // payload sizes of normal and extended data packets for ++ // receiving and sending, respectively. The wire packet will ++ // be 9 or 13 bytes larger (excluding encryption overhead). ++ maxIncomingPayload uint32 ++ maxRemotePayload uint32 ++ ++ mux *mux ++ ++ // decided is set to true if an accept or reject message has been sent ++ // (for outbound channels) or received (for inbound channels). ++ decided bool ++ ++ // direction contains either channelOutbound, for channels created ++ // locally, or channelInbound, for channels created by the peer. ++ direction channelDirection ++ ++ // Pending internal channel messages. ++ msg chan interface{} ++ ++ // Since requests have no ID, there can be only one request ++ // with WantReply=true outstanding. This lock is held by a ++ // goroutine that has such an outgoing request pending. ++ sentRequestMu sync.Mutex ++ ++ incomingRequests chan *Request ++ ++ sentEOF bool ++ ++ // thread-safe data ++ remoteWin window ++ pending *buffer ++ extPending *buffer ++ ++ // windowMu protects myWindow, the flow-control window. ++ windowMu sync.Mutex ++ myWindow uint32 ++ ++ // writeMu serializes calls to mux.conn.writePacket() and ++ // protects sentClose and packetPool. This mutex must be ++ // different from windowMu, as writePacket can block if there ++ // is a key exchange pending. ++ writeMu sync.Mutex ++ sentClose bool ++ ++ // packetPool has a buffer for each extended channel ID to ++ // save allocations during writes. ++ packetPool map[uint32][]byte ++} ++ ++// writePacket sends a packet. If the packet is a channel close, it updates ++// sentClose. This method takes the lock c.writeMu. ++func (ch *channel) writePacket(packet []byte) error { ++ ch.writeMu.Lock() ++ if ch.sentClose { ++ ch.writeMu.Unlock() ++ return io.EOF ++ } ++ ch.sentClose = (packet[0] == msgChannelClose) ++ err := ch.mux.conn.writePacket(packet) ++ ch.writeMu.Unlock() ++ return err ++} ++ ++func (ch *channel) sendMessage(msg interface{}) error { ++ if debugMux { ++ log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg) ++ } ++ ++ p := Marshal(msg) ++ binary.BigEndian.PutUint32(p[1:], ch.remoteId) ++ return ch.writePacket(p) ++} ++ ++// WriteExtended writes data to a specific extended stream. These streams are ++// used, for example, for stderr. ++func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { ++ if ch.sentEOF { ++ return 0, io.EOF ++ } ++ // 1 byte message type, 4 bytes remoteId, 4 bytes data length ++ opCode := byte(msgChannelData) ++ headerLength := uint32(9) ++ if extendedCode > 0 { ++ headerLength += 4 ++ opCode = msgChannelExtendedData ++ } ++ ++ ch.writeMu.Lock() ++ packet := ch.packetPool[extendedCode] ++ // We don't remove the buffer from packetPool, so ++ // WriteExtended calls from different goroutines will be ++ // flagged as errors by the race detector. ++ ch.writeMu.Unlock() ++ ++ for len(data) > 0 { ++ space := min(ch.maxRemotePayload, len(data)) ++ if space, err = ch.remoteWin.reserve(space); err != nil { ++ return n, err ++ } ++ if want := headerLength + space; uint32(cap(packet)) < want { ++ packet = make([]byte, want) ++ } else { ++ packet = packet[:want] ++ } ++ ++ todo := data[:space] ++ ++ packet[0] = opCode ++ binary.BigEndian.PutUint32(packet[1:], ch.remoteId) ++ if extendedCode > 0 { ++ binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode)) ++ } ++ binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo))) ++ copy(packet[headerLength:], todo) ++ if err = ch.writePacket(packet); err != nil { ++ return n, err ++ } ++ ++ n += len(todo) ++ data = data[len(todo):] ++ } ++ ++ ch.writeMu.Lock() ++ ch.packetPool[extendedCode] = packet ++ ch.writeMu.Unlock() ++ ++ return n, err ++} ++ ++func (ch *channel) handleData(packet []byte) error { ++ headerLen := 9 ++ isExtendedData := packet[0] == msgChannelExtendedData ++ if isExtendedData { ++ headerLen = 13 ++ } ++ if len(packet) < headerLen { ++ // malformed data packet ++ return parseError(packet[0]) ++ } ++ ++ var extended uint32 ++ if isExtendedData { ++ extended = binary.BigEndian.Uint32(packet[5:]) ++ } ++ ++ length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen]) ++ if length == 0 { ++ return nil ++ } ++ if length > ch.maxIncomingPayload { ++ // TODO(hanwen): should send Disconnect? ++ return errors.New("ssh: incoming packet exceeds maximum payload size") ++ } ++ ++ data := packet[headerLen:] ++ if length != uint32(len(data)) { ++ return errors.New("ssh: wrong packet length") ++ } ++ ++ ch.windowMu.Lock() ++ if ch.myWindow < length { ++ ch.windowMu.Unlock() ++ // TODO(hanwen): should send Disconnect with reason? ++ return errors.New("ssh: remote side wrote too much") ++ } ++ ch.myWindow -= length ++ ch.windowMu.Unlock() ++ ++ if extended == 1 { ++ ch.extPending.write(data) ++ } else if extended > 0 { ++ // discard other extended data. ++ } else { ++ ch.pending.write(data) ++ } ++ return nil ++} ++ ++func (c *channel) adjustWindow(n uint32) error { ++ c.windowMu.Lock() ++ // Since myWindow is managed on our side, and can never exceed ++ // the initial window setting, we don't worry about overflow. ++ c.myWindow += uint32(n) ++ c.windowMu.Unlock() ++ return c.sendMessage(windowAdjustMsg{ ++ AdditionalBytes: uint32(n), ++ }) ++} ++ ++func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) { ++ switch extended { ++ case 1: ++ n, err = c.extPending.Read(data) ++ case 0: ++ n, err = c.pending.Read(data) ++ default: ++ return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended) ++ } ++ ++ if n > 0 { ++ err = c.adjustWindow(uint32(n)) ++ // sendWindowAdjust can return io.EOF if the remote ++ // peer has closed the connection, however we want to ++ // defer forwarding io.EOF to the caller of Read until ++ // the buffer has been drained. ++ if n > 0 && err == io.EOF { ++ err = nil ++ } ++ } ++ ++ return n, err ++} ++ ++func (c *channel) close() { ++ c.pending.eof() ++ c.extPending.eof() ++ close(c.msg) ++ close(c.incomingRequests) ++ c.writeMu.Lock() ++ // This is not necessary for a normal channel teardown, but if ++ // there was another error, it is. ++ c.sentClose = true ++ c.writeMu.Unlock() ++ // Unblock writers. ++ c.remoteWin.close() ++} ++ ++// responseMessageReceived is called when a success or failure message is ++// received on a channel to check that such a message is reasonable for the ++// given channel. ++func (ch *channel) responseMessageReceived() error { ++ if ch.direction == channelInbound { ++ return errors.New("ssh: channel response message received on inbound channel") ++ } ++ if ch.decided { ++ return errors.New("ssh: duplicate response received for channel") ++ } ++ ch.decided = true ++ return nil ++} ++ ++func (ch *channel) handlePacket(packet []byte) error { ++ switch packet[0] { ++ case msgChannelData, msgChannelExtendedData: ++ return ch.handleData(packet) ++ case msgChannelClose: ++ ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId}) ++ ch.mux.chanList.remove(ch.localId) ++ ch.close() ++ return nil ++ case msgChannelEOF: ++ // RFC 4254 is mute on how EOF affects dataExt messages but ++ // it is logical to signal EOF at the same time. ++ ch.extPending.eof() ++ ch.pending.eof() ++ return nil ++ } ++ ++ decoded, err := decode(packet) ++ if err != nil { ++ return err ++ } ++ ++ switch msg := decoded.(type) { ++ case *channelOpenFailureMsg: ++ if err := ch.responseMessageReceived(); err != nil { ++ return err ++ } ++ ch.mux.chanList.remove(msg.PeersID) ++ ch.msg <- msg ++ case *channelOpenConfirmMsg: ++ if err := ch.responseMessageReceived(); err != nil { ++ return err ++ } ++ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { ++ return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize) ++ } ++ ch.remoteId = msg.MyID ++ ch.maxRemotePayload = msg.MaxPacketSize ++ ch.remoteWin.add(msg.MyWindow) ++ ch.msg <- msg ++ case *windowAdjustMsg: ++ if !ch.remoteWin.add(msg.AdditionalBytes) { ++ return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes) ++ } ++ case *channelRequestMsg: ++ req := Request{ ++ Type: msg.Request, ++ WantReply: msg.WantReply, ++ Payload: msg.RequestSpecificData, ++ ch: ch, ++ } ++ ++ ch.incomingRequests <- &req ++ default: ++ ch.msg <- msg ++ } ++ return nil ++} ++ ++func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { ++ ch := &channel{ ++ remoteWin: window{Cond: newCond()}, ++ myWindow: channelWindowSize, ++ pending: newBuffer(), ++ extPending: newBuffer(), ++ direction: direction, ++ incomingRequests: make(chan *Request, chanSize), ++ msg: make(chan interface{}, chanSize), ++ chanType: chanType, ++ extraData: extraData, ++ mux: m, ++ packetPool: make(map[uint32][]byte), ++ } ++ ch.localId = m.chanList.add(ch) ++ return ch ++} ++ ++var errUndecided = errors.New("ssh: must Accept or Reject channel") ++var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") ++ ++type extChannel struct { ++ code uint32 ++ ch *channel ++} ++ ++func (e *extChannel) Write(data []byte) (n int, err error) { ++ return e.ch.WriteExtended(data, e.code) ++} ++ ++func (e *extChannel) Read(data []byte) (n int, err error) { ++ return e.ch.ReadExtended(data, e.code) ++} ++ ++func (ch *channel) Accept() (Channel, <-chan *Request, error) { ++ if ch.decided { ++ return nil, nil, errDecidedAlready ++ } ++ ch.maxIncomingPayload = channelMaxPacket ++ confirm := channelOpenConfirmMsg{ ++ PeersID: ch.remoteId, ++ MyID: ch.localId, ++ MyWindow: ch.myWindow, ++ MaxPacketSize: ch.maxIncomingPayload, ++ } ++ ch.decided = true ++ if err := ch.sendMessage(confirm); err != nil { ++ return nil, nil, err ++ } ++ ++ return ch, ch.incomingRequests, nil ++} ++ ++func (ch *channel) Reject(reason RejectionReason, message string) error { ++ if ch.decided { ++ return errDecidedAlready ++ } ++ reject := channelOpenFailureMsg{ ++ PeersID: ch.remoteId, ++ Reason: reason, ++ Message: message, ++ Language: "en", ++ } ++ ch.decided = true ++ return ch.sendMessage(reject) ++} ++ ++func (ch *channel) Read(data []byte) (int, error) { ++ if !ch.decided { ++ return 0, errUndecided ++ } ++ return ch.ReadExtended(data, 0) ++} ++ ++func (ch *channel) Write(data []byte) (int, error) { ++ if !ch.decided { ++ return 0, errUndecided ++ } ++ return ch.WriteExtended(data, 0) ++} ++ ++func (ch *channel) CloseWrite() error { ++ if !ch.decided { ++ return errUndecided ++ } ++ ch.sentEOF = true ++ return ch.sendMessage(channelEOFMsg{ ++ PeersID: ch.remoteId}) ++} ++ ++func (ch *channel) Close() error { ++ if !ch.decided { ++ return errUndecided ++ } ++ ++ return ch.sendMessage(channelCloseMsg{ ++ PeersID: ch.remoteId}) ++} ++ ++// Extended returns an io.ReadWriter that sends and receives data on the given, ++// SSH extended stream. Such streams are used, for example, for stderr. ++func (ch *channel) Extended(code uint32) io.ReadWriter { ++ if !ch.decided { ++ return nil ++ } ++ return &extChannel{code, ch} ++} ++ ++func (ch *channel) Stderr() io.ReadWriter { ++ return ch.Extended(1) ++} ++ ++func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { ++ if !ch.decided { ++ return false, errUndecided ++ } ++ ++ if wantReply { ++ ch.sentRequestMu.Lock() ++ defer ch.sentRequestMu.Unlock() ++ } ++ ++ msg := channelRequestMsg{ ++ PeersID: ch.remoteId, ++ Request: name, ++ WantReply: wantReply, ++ RequestSpecificData: payload, ++ } ++ ++ if err := ch.sendMessage(msg); err != nil { ++ return false, err ++ } ++ ++ if wantReply { ++ m, ok := (<-ch.msg) ++ if !ok { ++ return false, io.EOF ++ } ++ switch m.(type) { ++ case *channelRequestFailureMsg: ++ return false, nil ++ case *channelRequestSuccessMsg: ++ return true, nil ++ default: ++ return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m) ++ } ++ } ++ ++ return false, nil ++} ++ ++// ackRequest either sends an ack or nack to the channel request. ++func (ch *channel) ackRequest(ok bool) error { ++ if !ch.decided { ++ return errUndecided ++ } ++ ++ var msg interface{} ++ if !ok { ++ msg = channelRequestFailureMsg{ ++ PeersID: ch.remoteId, ++ } ++ } else { ++ msg = channelRequestSuccessMsg{ ++ PeersID: ch.remoteId, ++ } ++ } ++ return ch.sendMessage(msg) ++} ++ ++func (ch *channel) ChannelType() string { ++ return ch.chanType ++} ++ ++func (ch *channel) ExtraData() []byte { ++ return ch.extraData ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/cipher.go b/ms_mod/golang.org/x/crypto/ssh/cipher.go +new file mode 100644 +index 00000000000000..741e984f33cb75 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/cipher.go +@@ -0,0 +1,789 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "crypto/aes" ++ "crypto/cipher" ++ "crypto/des" ++ "crypto/rc4" ++ "crypto/subtle" ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "hash" ++ "io" ++ ++ "golang.org/x/crypto/chacha20" ++ "golang.org/x/crypto/internal/poly1305" ++) ++ ++const ( ++ packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. ++ ++ // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations ++ // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC ++ // indicates implementations SHOULD be able to handle larger packet sizes, but then ++ // waffles on about reasonable limits. ++ // ++ // OpenSSH caps their maxPacket at 256kB so we choose to do ++ // the same. maxPacket is also used to ensure that uint32 ++ // length fields do not overflow, so it should remain well ++ // below 4G. ++ maxPacket = 256 * 1024 ++) ++ ++// noneCipher implements cipher.Stream and provides no encryption. It is used ++// by the transport before the first key-exchange. ++type noneCipher struct{} ++ ++func (c noneCipher) XORKeyStream(dst, src []byte) { ++ copy(dst, src) ++} ++ ++func newAESCTR(key, iv []byte) (cipher.Stream, error) { ++ c, err := aes.NewCipher(key) ++ if err != nil { ++ return nil, err ++ } ++ return cipher.NewCTR(c, iv), nil ++} ++ ++func newRC4(key, iv []byte) (cipher.Stream, error) { ++ return rc4.NewCipher(key) ++} ++ ++type cipherMode struct { ++ keySize int ++ ivSize int ++ create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) ++} ++ ++func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { ++ return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { ++ stream, err := createFunc(key, iv) ++ if err != nil { ++ return nil, err ++ } ++ ++ var streamDump []byte ++ if skip > 0 { ++ streamDump = make([]byte, 512) ++ } ++ ++ for remainingToDump := skip; remainingToDump > 0; { ++ dumpThisTime := remainingToDump ++ if dumpThisTime > len(streamDump) { ++ dumpThisTime = len(streamDump) ++ } ++ stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) ++ remainingToDump -= dumpThisTime ++ } ++ ++ mac := macModes[algs.MAC].new(macKey) ++ return &streamPacketCipher{ ++ mac: mac, ++ etm: macModes[algs.MAC].etm, ++ macResult: make([]byte, mac.Size()), ++ cipher: stream, ++ }, nil ++ } ++} ++ ++// cipherModes documents properties of supported ciphers. Ciphers not included ++// are not supported and will not be negotiated, even if explicitly requested in ++// ClientConfig.Crypto.Ciphers. ++var cipherModes = map[string]*cipherMode{ ++ // Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms ++ // are defined in the order specified in the RFC. ++ "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, ++ "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, ++ "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, ++ ++ // Ciphers from RFC 4345, which introduces security-improved arcfour ciphers. ++ // They are defined in the order specified in the RFC. ++ "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, ++ "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, ++ ++ // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. ++ // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and ++ // RC4) has problems with weak keys, and should be used with caution." ++ // RFC 4345 introduces improved versions of Arcfour. ++ "arcfour": {16, 0, streamCipherMode(0, newRC4)}, ++ ++ // AEAD ciphers ++ gcm128CipherID: {16, 12, newGCMCipher}, ++ gcm256CipherID: {32, 12, newGCMCipher}, ++ chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, ++ ++ // CBC mode is insecure and so is not included in the default config. ++ // (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely ++ // needed, it's possible to specify a custom Config to enable it. ++ // You should expect that an active attacker can recover plaintext if ++ // you do. ++ aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, ++ ++ // 3des-cbc is insecure and is not included in the default ++ // config. ++ tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, ++} ++ ++// prefixLen is the length of the packet prefix that contains the packet length ++// and number of padding bytes. ++const prefixLen = 5 ++ ++// streamPacketCipher is a packetCipher using a stream cipher. ++type streamPacketCipher struct { ++ mac hash.Hash ++ cipher cipher.Stream ++ etm bool ++ ++ // The following members are to avoid per-packet allocations. ++ prefix [prefixLen]byte ++ seqNumBytes [4]byte ++ padding [2 * packetSizeMultiple]byte ++ packetData []byte ++ macResult []byte ++} ++ ++// readCipherPacket reads and decrypt a single packet from the reader argument. ++func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { ++ if _, err := io.ReadFull(r, s.prefix[:]); err != nil { ++ return nil, err ++ } ++ ++ var encryptedPaddingLength [1]byte ++ if s.mac != nil && s.etm { ++ copy(encryptedPaddingLength[:], s.prefix[4:5]) ++ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) ++ } else { ++ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) ++ } ++ ++ length := binary.BigEndian.Uint32(s.prefix[0:4]) ++ paddingLength := uint32(s.prefix[4]) ++ ++ var macSize uint32 ++ if s.mac != nil { ++ s.mac.Reset() ++ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) ++ s.mac.Write(s.seqNumBytes[:]) ++ if s.etm { ++ s.mac.Write(s.prefix[:4]) ++ s.mac.Write(encryptedPaddingLength[:]) ++ } else { ++ s.mac.Write(s.prefix[:]) ++ } ++ macSize = uint32(s.mac.Size()) ++ } ++ ++ if length <= paddingLength+1 { ++ return nil, errors.New("ssh: invalid packet length, packet too small") ++ } ++ ++ if length > maxPacket { ++ return nil, errors.New("ssh: invalid packet length, packet too large") ++ } ++ ++ // the maxPacket check above ensures that length-1+macSize ++ // does not overflow. ++ if uint32(cap(s.packetData)) < length-1+macSize { ++ s.packetData = make([]byte, length-1+macSize) ++ } else { ++ s.packetData = s.packetData[:length-1+macSize] ++ } ++ ++ if _, err := io.ReadFull(r, s.packetData); err != nil { ++ return nil, err ++ } ++ mac := s.packetData[length-1:] ++ data := s.packetData[:length-1] ++ ++ if s.mac != nil && s.etm { ++ s.mac.Write(data) ++ } ++ ++ s.cipher.XORKeyStream(data, data) ++ ++ if s.mac != nil { ++ if !s.etm { ++ s.mac.Write(data) ++ } ++ s.macResult = s.mac.Sum(s.macResult[:0]) ++ if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { ++ return nil, errors.New("ssh: MAC failure") ++ } ++ } ++ ++ return s.packetData[:length-paddingLength-1], nil ++} ++ ++// writeCipherPacket encrypts and sends a packet of data to the writer argument ++func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { ++ if len(packet) > maxPacket { ++ return errors.New("ssh: packet too large") ++ } ++ ++ aadlen := 0 ++ if s.mac != nil && s.etm { ++ // packet length is not encrypted for EtM modes ++ aadlen = 4 ++ } ++ ++ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple ++ if paddingLength < 4 { ++ paddingLength += packetSizeMultiple ++ } ++ ++ length := len(packet) + 1 + paddingLength ++ binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) ++ s.prefix[4] = byte(paddingLength) ++ padding := s.padding[:paddingLength] ++ if _, err := io.ReadFull(rand, padding); err != nil { ++ return err ++ } ++ ++ if s.mac != nil { ++ s.mac.Reset() ++ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) ++ s.mac.Write(s.seqNumBytes[:]) ++ ++ if s.etm { ++ // For EtM algorithms, the packet length must stay unencrypted, ++ // but the following data (padding length) must be encrypted ++ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) ++ } ++ ++ s.mac.Write(s.prefix[:]) ++ ++ if !s.etm { ++ // For non-EtM algorithms, the algorithm is applied on unencrypted data ++ s.mac.Write(packet) ++ s.mac.Write(padding) ++ } ++ } ++ ++ if !(s.mac != nil && s.etm) { ++ // For EtM algorithms, the padding length has already been encrypted ++ // and the packet length must remain unencrypted ++ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) ++ } ++ ++ s.cipher.XORKeyStream(packet, packet) ++ s.cipher.XORKeyStream(padding, padding) ++ ++ if s.mac != nil && s.etm { ++ // For EtM algorithms, packet and padding must be encrypted ++ s.mac.Write(packet) ++ s.mac.Write(padding) ++ } ++ ++ if _, err := w.Write(s.prefix[:]); err != nil { ++ return err ++ } ++ if _, err := w.Write(packet); err != nil { ++ return err ++ } ++ if _, err := w.Write(padding); err != nil { ++ return err ++ } ++ ++ if s.mac != nil { ++ s.macResult = s.mac.Sum(s.macResult[:0]) ++ if _, err := w.Write(s.macResult); err != nil { ++ return err ++ } ++ } ++ ++ return nil ++} ++ ++type gcmCipher struct { ++ aead cipher.AEAD ++ prefix [4]byte ++ iv []byte ++ buf []byte ++} ++ ++func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { ++ c, err := aes.NewCipher(key) ++ if err != nil { ++ return nil, err ++ } ++ ++ aead, err := cipher.NewGCM(c) ++ if err != nil { ++ return nil, err ++ } ++ ++ return &gcmCipher{ ++ aead: aead, ++ iv: iv, ++ }, nil ++} ++ ++const gcmTagSize = 16 ++ ++func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { ++ // Pad out to multiple of 16 bytes. This is different from the ++ // stream cipher because that encrypts the length too. ++ padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) ++ if padding < 4 { ++ padding += packetSizeMultiple ++ } ++ ++ length := uint32(len(packet) + int(padding) + 1) ++ binary.BigEndian.PutUint32(c.prefix[:], length) ++ if _, err := w.Write(c.prefix[:]); err != nil { ++ return err ++ } ++ ++ if cap(c.buf) < int(length) { ++ c.buf = make([]byte, length) ++ } else { ++ c.buf = c.buf[:length] ++ } ++ ++ c.buf[0] = padding ++ copy(c.buf[1:], packet) ++ if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { ++ return err ++ } ++ c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) ++ if _, err := w.Write(c.buf); err != nil { ++ return err ++ } ++ c.incIV() ++ ++ return nil ++} ++ ++func (c *gcmCipher) incIV() { ++ for i := 4 + 7; i >= 4; i-- { ++ c.iv[i]++ ++ if c.iv[i] != 0 { ++ break ++ } ++ } ++} ++ ++func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { ++ if _, err := io.ReadFull(r, c.prefix[:]); err != nil { ++ return nil, err ++ } ++ length := binary.BigEndian.Uint32(c.prefix[:]) ++ if length > maxPacket { ++ return nil, errors.New("ssh: max packet length exceeded") ++ } ++ ++ if cap(c.buf) < int(length+gcmTagSize) { ++ c.buf = make([]byte, length+gcmTagSize) ++ } else { ++ c.buf = c.buf[:length+gcmTagSize] ++ } ++ ++ if _, err := io.ReadFull(r, c.buf); err != nil { ++ return nil, err ++ } ++ ++ plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) ++ if err != nil { ++ return nil, err ++ } ++ c.incIV() ++ ++ if len(plain) == 0 { ++ return nil, errors.New("ssh: empty packet") ++ } ++ ++ padding := plain[0] ++ if padding < 4 { ++ // padding is a byte, so it automatically satisfies ++ // the maximum size, which is 255. ++ return nil, fmt.Errorf("ssh: illegal padding %d", padding) ++ } ++ ++ if int(padding+1) >= len(plain) { ++ return nil, fmt.Errorf("ssh: padding %d too large", padding) ++ } ++ plain = plain[1 : length-uint32(padding)] ++ return plain, nil ++} ++ ++// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 ++type cbcCipher struct { ++ mac hash.Hash ++ macSize uint32 ++ decrypter cipher.BlockMode ++ encrypter cipher.BlockMode ++ ++ // The following members are to avoid per-packet allocations. ++ seqNumBytes [4]byte ++ packetData []byte ++ macResult []byte ++ ++ // Amount of data we should still read to hide which ++ // verification error triggered. ++ oracleCamouflage uint32 ++} ++ ++func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { ++ cbc := &cbcCipher{ ++ mac: macModes[algs.MAC].new(macKey), ++ decrypter: cipher.NewCBCDecrypter(c, iv), ++ encrypter: cipher.NewCBCEncrypter(c, iv), ++ packetData: make([]byte, 1024), ++ } ++ if cbc.mac != nil { ++ cbc.macSize = uint32(cbc.mac.Size()) ++ } ++ ++ return cbc, nil ++} ++ ++func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { ++ c, err := aes.NewCipher(key) ++ if err != nil { ++ return nil, err ++ } ++ ++ cbc, err := newCBCCipher(c, key, iv, macKey, algs) ++ if err != nil { ++ return nil, err ++ } ++ ++ return cbc, nil ++} ++ ++func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { ++ c, err := des.NewTripleDESCipher(key) ++ if err != nil { ++ return nil, err ++ } ++ ++ cbc, err := newCBCCipher(c, key, iv, macKey, algs) ++ if err != nil { ++ return nil, err ++ } ++ ++ return cbc, nil ++} ++ ++func maxUInt32(a, b int) uint32 { ++ if a > b { ++ return uint32(a) ++ } ++ return uint32(b) ++} ++ ++const ( ++ cbcMinPacketSizeMultiple = 8 ++ cbcMinPacketSize = 16 ++ cbcMinPaddingSize = 4 ++) ++ ++// cbcError represents a verification error that may leak information. ++type cbcError string ++ ++func (e cbcError) Error() string { return string(e) } ++ ++func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { ++ p, err := c.readCipherPacketLeaky(seqNum, r) ++ if err != nil { ++ if _, ok := err.(cbcError); ok { ++ // Verification error: read a fixed amount of ++ // data, to make distinguishing between ++ // failing MAC and failing length check more ++ // difficult. ++ io.CopyN(io.Discard, r, int64(c.oracleCamouflage)) ++ } ++ } ++ return p, err ++} ++ ++func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { ++ blockSize := c.decrypter.BlockSize() ++ ++ // Read the header, which will include some of the subsequent data in the ++ // case of block ciphers - this is copied back to the payload later. ++ // How many bytes of payload/padding will be read with this first read. ++ firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) ++ firstBlock := c.packetData[:firstBlockLength] ++ if _, err := io.ReadFull(r, firstBlock); err != nil { ++ return nil, err ++ } ++ ++ c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength ++ ++ c.decrypter.CryptBlocks(firstBlock, firstBlock) ++ length := binary.BigEndian.Uint32(firstBlock[:4]) ++ if length > maxPacket { ++ return nil, cbcError("ssh: packet too large") ++ } ++ if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { ++ // The minimum size of a packet is 16 (or the cipher block size, whichever ++ // is larger) bytes. ++ return nil, cbcError("ssh: packet too small") ++ } ++ // The length of the packet (including the length field but not the MAC) must ++ // be a multiple of the block size or 8, whichever is larger. ++ if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { ++ return nil, cbcError("ssh: invalid packet length multiple") ++ } ++ ++ paddingLength := uint32(firstBlock[4]) ++ if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { ++ return nil, cbcError("ssh: invalid packet length") ++ } ++ ++ // Positions within the c.packetData buffer: ++ macStart := 4 + length ++ paddingStart := macStart - paddingLength ++ ++ // Entire packet size, starting before length, ending at end of mac. ++ entirePacketSize := macStart + c.macSize ++ ++ // Ensure c.packetData is large enough for the entire packet data. ++ if uint32(cap(c.packetData)) < entirePacketSize { ++ // Still need to upsize and copy, but this should be rare at runtime, only ++ // on upsizing the packetData buffer. ++ c.packetData = make([]byte, entirePacketSize) ++ copy(c.packetData, firstBlock) ++ } else { ++ c.packetData = c.packetData[:entirePacketSize] ++ } ++ ++ n, err := io.ReadFull(r, c.packetData[firstBlockLength:]) ++ if err != nil { ++ return nil, err ++ } ++ c.oracleCamouflage -= uint32(n) ++ ++ remainingCrypted := c.packetData[firstBlockLength:macStart] ++ c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) ++ ++ mac := c.packetData[macStart:] ++ if c.mac != nil { ++ c.mac.Reset() ++ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) ++ c.mac.Write(c.seqNumBytes[:]) ++ c.mac.Write(c.packetData[:macStart]) ++ c.macResult = c.mac.Sum(c.macResult[:0]) ++ if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { ++ return nil, cbcError("ssh: MAC failure") ++ } ++ } ++ ++ return c.packetData[prefixLen:paddingStart], nil ++} ++ ++func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { ++ effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) ++ ++ // Length of encrypted portion of the packet (header, payload, padding). ++ // Enforce minimum padding and packet size. ++ encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) ++ // Enforce block size. ++ encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize ++ ++ length := encLength - 4 ++ paddingLength := int(length) - (1 + len(packet)) ++ ++ // Overall buffer contains: header, payload, padding, mac. ++ // Space for the MAC is reserved in the capacity but not the slice length. ++ bufferSize := encLength + c.macSize ++ if uint32(cap(c.packetData)) < bufferSize { ++ c.packetData = make([]byte, encLength, bufferSize) ++ } else { ++ c.packetData = c.packetData[:encLength] ++ } ++ ++ p := c.packetData ++ ++ // Packet header. ++ binary.BigEndian.PutUint32(p, length) ++ p = p[4:] ++ p[0] = byte(paddingLength) ++ ++ // Payload. ++ p = p[1:] ++ copy(p, packet) ++ ++ // Padding. ++ p = p[len(packet):] ++ if _, err := io.ReadFull(rand, p); err != nil { ++ return err ++ } ++ ++ if c.mac != nil { ++ c.mac.Reset() ++ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) ++ c.mac.Write(c.seqNumBytes[:]) ++ c.mac.Write(c.packetData) ++ // The MAC is now appended into the capacity reserved for it earlier. ++ c.packetData = c.mac.Sum(c.packetData) ++ } ++ ++ c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) ++ ++ if _, err := w.Write(c.packetData); err != nil { ++ return err ++ } ++ ++ return nil ++} ++ ++const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" ++ ++// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com ++// AEAD, which is described here: ++// ++// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 ++// ++// the methods here also implement padding, which RFC 4253 Section 6 ++// also requires of stream ciphers. ++type chacha20Poly1305Cipher struct { ++ lengthKey [32]byte ++ contentKey [32]byte ++ buf []byte ++} ++ ++func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { ++ if len(key) != 64 { ++ panic(len(key)) ++ } ++ ++ c := &chacha20Poly1305Cipher{ ++ buf: make([]byte, 256), ++ } ++ ++ copy(c.contentKey[:], key[:32]) ++ copy(c.lengthKey[:], key[32:]) ++ return c, nil ++} ++ ++func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { ++ nonce := make([]byte, 12) ++ binary.BigEndian.PutUint32(nonce[8:], seqNum) ++ s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) ++ if err != nil { ++ return nil, err ++ } ++ var polyKey, discardBuf [32]byte ++ s.XORKeyStream(polyKey[:], polyKey[:]) ++ s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes ++ ++ encryptedLength := c.buf[:4] ++ if _, err := io.ReadFull(r, encryptedLength); err != nil { ++ return nil, err ++ } ++ ++ var lenBytes [4]byte ++ ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) ++ if err != nil { ++ return nil, err ++ } ++ ls.XORKeyStream(lenBytes[:], encryptedLength) ++ ++ length := binary.BigEndian.Uint32(lenBytes[:]) ++ if length > maxPacket { ++ return nil, errors.New("ssh: invalid packet length, packet too large") ++ } ++ ++ contentEnd := 4 + length ++ packetEnd := contentEnd + poly1305.TagSize ++ if uint32(cap(c.buf)) < packetEnd { ++ c.buf = make([]byte, packetEnd) ++ copy(c.buf[:], encryptedLength) ++ } else { ++ c.buf = c.buf[:packetEnd] ++ } ++ ++ if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { ++ return nil, err ++ } ++ ++ var mac [poly1305.TagSize]byte ++ copy(mac[:], c.buf[contentEnd:packetEnd]) ++ if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { ++ return nil, errors.New("ssh: MAC failure") ++ } ++ ++ plain := c.buf[4:contentEnd] ++ s.XORKeyStream(plain, plain) ++ ++ if len(plain) == 0 { ++ return nil, errors.New("ssh: empty packet") ++ } ++ ++ padding := plain[0] ++ if padding < 4 { ++ // padding is a byte, so it automatically satisfies ++ // the maximum size, which is 255. ++ return nil, fmt.Errorf("ssh: illegal padding %d", padding) ++ } ++ ++ if int(padding)+1 >= len(plain) { ++ return nil, fmt.Errorf("ssh: padding %d too large", padding) ++ } ++ ++ plain = plain[1 : len(plain)-int(padding)] ++ ++ return plain, nil ++} ++ ++func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { ++ nonce := make([]byte, 12) ++ binary.BigEndian.PutUint32(nonce[8:], seqNum) ++ s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) ++ if err != nil { ++ return err ++ } ++ var polyKey, discardBuf [32]byte ++ s.XORKeyStream(polyKey[:], polyKey[:]) ++ s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes ++ ++ // There is no blocksize, so fall back to multiple of 8 byte ++ // padding, as described in RFC 4253, Sec 6. ++ const packetSizeMultiple = 8 ++ ++ padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple ++ if padding < 4 { ++ padding += packetSizeMultiple ++ } ++ ++ // size (4 bytes), padding (1), payload, padding, tag. ++ totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize ++ if cap(c.buf) < totalLength { ++ c.buf = make([]byte, totalLength) ++ } else { ++ c.buf = c.buf[:totalLength] ++ } ++ ++ binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) ++ ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) ++ if err != nil { ++ return err ++ } ++ ls.XORKeyStream(c.buf, c.buf[:4]) ++ c.buf[4] = byte(padding) ++ copy(c.buf[5:], payload) ++ packetEnd := 5 + len(payload) + padding ++ if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil { ++ return err ++ } ++ ++ s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd]) ++ ++ var mac [poly1305.TagSize]byte ++ poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) ++ ++ copy(c.buf[packetEnd:], mac[:]) ++ ++ if _, err := w.Write(c.buf); err != nil { ++ return err ++ } ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/cipher_test.go b/ms_mod/golang.org/x/crypto/ssh/cipher_test.go +new file mode 100644 +index 00000000000000..f1be0d6db446df +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/cipher_test.go +@@ -0,0 +1,231 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/rand" ++ "encoding/binary" ++ "io" ++ "testing" ++ ++ "golang.org/x/crypto/chacha20" ++ "golang.org/x/crypto/internal/poly1305" ++) ++ ++func TestDefaultCiphersExist(t *testing.T) { ++ for _, cipherAlgo := range supportedCiphers { ++ if _, ok := cipherModes[cipherAlgo]; !ok { ++ t.Errorf("supported cipher %q is unknown", cipherAlgo) ++ } ++ } ++ for _, cipherAlgo := range preferredCiphers { ++ if _, ok := cipherModes[cipherAlgo]; !ok { ++ t.Errorf("preferred cipher %q is unknown", cipherAlgo) ++ } ++ } ++} ++ ++func TestPacketCiphers(t *testing.T) { ++ defaultMac := "hmac-sha2-256" ++ defaultCipher := "aes128-ctr" ++ for cipher := range cipherModes { ++ t.Run("cipher="+cipher, ++ func(t *testing.T) { testPacketCipher(t, cipher, defaultMac) }) ++ } ++ for mac := range macModes { ++ t.Run("mac="+mac, ++ func(t *testing.T) { testPacketCipher(t, defaultCipher, mac) }) ++ } ++} ++ ++func testPacketCipher(t *testing.T, cipher, mac string) { ++ kr := &kexResult{Hash: crypto.SHA1} ++ algs := directionAlgorithms{ ++ Cipher: cipher, ++ MAC: mac, ++ Compression: "none", ++ } ++ client, err := newPacketCipher(clientKeys, algs, kr) ++ if err != nil { ++ t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) ++ } ++ server, err := newPacketCipher(clientKeys, algs, kr) ++ if err != nil { ++ t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) ++ } ++ ++ want := "bla bla" ++ input := []byte(want) ++ buf := &bytes.Buffer{} ++ if err := client.writeCipherPacket(0, buf, rand.Reader, input); err != nil { ++ t.Fatalf("writeCipherPacket(%q, %q): %v", cipher, mac, err) ++ } ++ ++ packet, err := server.readCipherPacket(0, buf) ++ if err != nil { ++ t.Fatalf("readCipherPacket(%q, %q): %v", cipher, mac, err) ++ } ++ ++ if string(packet) != want { ++ t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want) ++ } ++} ++ ++func TestCBCOracleCounterMeasure(t *testing.T) { ++ kr := &kexResult{Hash: crypto.SHA1} ++ algs := directionAlgorithms{ ++ Cipher: aes128cbcID, ++ MAC: "hmac-sha1", ++ Compression: "none", ++ } ++ client, err := newPacketCipher(clientKeys, algs, kr) ++ if err != nil { ++ t.Fatalf("newPacketCipher(client): %v", err) ++ } ++ ++ want := "bla bla" ++ input := []byte(want) ++ buf := &bytes.Buffer{} ++ if err := client.writeCipherPacket(0, buf, rand.Reader, input); err != nil { ++ t.Errorf("writeCipherPacket: %v", err) ++ } ++ ++ packetSize := buf.Len() ++ buf.Write(make([]byte, 2*maxPacket)) ++ ++ // We corrupt each byte, but this usually will only test the ++ // 'packet too large' or 'MAC failure' cases. ++ lastRead := -1 ++ for i := 0; i < packetSize; i++ { ++ server, err := newPacketCipher(clientKeys, algs, kr) ++ if err != nil { ++ t.Fatalf("newPacketCipher(client): %v", err) ++ } ++ ++ fresh := &bytes.Buffer{} ++ fresh.Write(buf.Bytes()) ++ fresh.Bytes()[i] ^= 0x01 ++ ++ before := fresh.Len() ++ _, err = server.readCipherPacket(0, fresh) ++ if err == nil { ++ t.Errorf("corrupt byte %d: readCipherPacket succeeded ", i) ++ continue ++ } ++ if _, ok := err.(cbcError); !ok { ++ t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) ++ continue ++ } ++ ++ after := fresh.Len() ++ bytesRead := before - after ++ if bytesRead < maxPacket { ++ t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) ++ continue ++ } ++ ++ if i > 0 && bytesRead != lastRead { ++ t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead) ++ } ++ lastRead = bytesRead ++ } ++} ++ ++func TestCVE202143565(t *testing.T) { ++ tests := []struct { ++ cipher string ++ constructPacket func(packetCipher) io.Reader ++ }{ ++ { ++ cipher: gcm128CipherID, ++ constructPacket: func(client packetCipher) io.Reader { ++ internalCipher := client.(*gcmCipher) ++ b := &bytes.Buffer{} ++ prefix := [4]byte{} ++ if _, err := b.Write(prefix[:]); err != nil { ++ t.Fatal(err) ++ } ++ internalCipher.buf = internalCipher.aead.Seal(internalCipher.buf[:0], internalCipher.iv, []byte{}, prefix[:]) ++ if _, err := b.Write(internalCipher.buf); err != nil { ++ t.Fatal(err) ++ } ++ internalCipher.incIV() ++ ++ return b ++ }, ++ }, ++ { ++ cipher: chacha20Poly1305ID, ++ constructPacket: func(client packetCipher) io.Reader { ++ internalCipher := client.(*chacha20Poly1305Cipher) ++ b := &bytes.Buffer{} ++ ++ nonce := make([]byte, 12) ++ s, err := chacha20.NewUnauthenticatedCipher(internalCipher.contentKey[:], nonce) ++ if err != nil { ++ t.Fatal(err) ++ } ++ var polyKey, discardBuf [32]byte ++ s.XORKeyStream(polyKey[:], polyKey[:]) ++ s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes ++ ++ internalCipher.buf = make([]byte, 4+poly1305.TagSize) ++ binary.BigEndian.PutUint32(internalCipher.buf, 0) ++ ls, err := chacha20.NewUnauthenticatedCipher(internalCipher.lengthKey[:], nonce) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ls.XORKeyStream(internalCipher.buf, internalCipher.buf[:4]) ++ if _, err := io.ReadFull(rand.Reader, internalCipher.buf[4:4]); err != nil { ++ t.Fatal(err) ++ } ++ ++ s.XORKeyStream(internalCipher.buf[4:], internalCipher.buf[4:4]) ++ ++ var tag [poly1305.TagSize]byte ++ poly1305.Sum(&tag, internalCipher.buf[:4], &polyKey) ++ ++ copy(internalCipher.buf[4:], tag[:]) ++ ++ if _, err := b.Write(internalCipher.buf); err != nil { ++ t.Fatal(err) ++ } ++ ++ return b ++ }, ++ }, ++ } ++ ++ for _, tc := range tests { ++ mac := "hmac-sha2-256" ++ ++ kr := &kexResult{Hash: crypto.SHA1} ++ algs := directionAlgorithms{ ++ Cipher: tc.cipher, ++ MAC: mac, ++ Compression: "none", ++ } ++ client, err := newPacketCipher(clientKeys, algs, kr) ++ if err != nil { ++ t.Fatalf("newPacketCipher(client, %q, %q): %v", tc.cipher, mac, err) ++ } ++ server, err := newPacketCipher(clientKeys, algs, kr) ++ if err != nil { ++ t.Fatalf("newPacketCipher(client, %q, %q): %v", tc.cipher, mac, err) ++ } ++ ++ b := tc.constructPacket(client) ++ ++ wantErr := "ssh: empty packet" ++ _, err = server.readCipherPacket(0, b) ++ if err == nil { ++ t.Fatalf("readCipherPacket(%q, %q): didn't fail with empty packet", tc.cipher, mac) ++ } else if err.Error() != wantErr { ++ t.Fatalf("readCipherPacket(%q, %q): unexpected error, got %q, want %q", tc.cipher, mac, err, wantErr) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/client.go b/ms_mod/golang.org/x/crypto/ssh/client.go +new file mode 100644 +index 00000000000000..bdc356cbdf1eac +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/client.go +@@ -0,0 +1,282 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "net" ++ "os" ++ "sync" ++ "time" ++) ++ ++// Client implements a traditional SSH client that supports shells, ++// subprocesses, TCP port/streamlocal forwarding and tunneled dialing. ++type Client struct { ++ Conn ++ ++ handleForwardsOnce sync.Once // guards calling (*Client).handleForwards ++ ++ forwards forwardList // forwarded tcpip connections from the remote side ++ mu sync.Mutex ++ channelHandlers map[string]chan NewChannel ++} ++ ++// HandleChannelOpen returns a channel on which NewChannel requests ++// for the given type are sent. If the type already is being handled, ++// nil is returned. The channel is closed when the connection is closed. ++func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { ++ c.mu.Lock() ++ defer c.mu.Unlock() ++ if c.channelHandlers == nil { ++ // The SSH channel has been closed. ++ c := make(chan NewChannel) ++ close(c) ++ return c ++ } ++ ++ ch := c.channelHandlers[channelType] ++ if ch != nil { ++ return nil ++ } ++ ++ ch = make(chan NewChannel, chanSize) ++ c.channelHandlers[channelType] = ch ++ return ch ++} ++ ++// NewClient creates a Client on top of the given connection. ++func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { ++ conn := &Client{ ++ Conn: c, ++ channelHandlers: make(map[string]chan NewChannel, 1), ++ } ++ ++ go conn.handleGlobalRequests(reqs) ++ go conn.handleChannelOpens(chans) ++ go func() { ++ conn.Wait() ++ conn.forwards.closeAll() ++ }() ++ return conn ++} ++ ++// NewClientConn establishes an authenticated SSH connection using c ++// as the underlying transport. The Request and NewChannel channels ++// must be serviced or the connection will hang. ++func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { ++ fullConf := *config ++ fullConf.SetDefaults() ++ if fullConf.HostKeyCallback == nil { ++ c.Close() ++ return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback") ++ } ++ ++ conn := &connection{ ++ sshConn: sshConn{conn: c, user: fullConf.User}, ++ } ++ ++ if err := conn.clientHandshake(addr, &fullConf); err != nil { ++ c.Close() ++ return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) ++ } ++ conn.mux = newMux(conn.transport) ++ return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil ++} ++ ++// clientHandshake performs the client side key exchange. See RFC 4253 Section ++// 7. ++func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { ++ if config.ClientVersion != "" { ++ c.clientVersion = []byte(config.ClientVersion) ++ } else { ++ c.clientVersion = []byte(packageVersion) ++ } ++ var err error ++ c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) ++ if err != nil { ++ return err ++ } ++ ++ c.transport = newClientTransport( ++ newTransport(c.sshConn.conn, config.Rand, true /* is client */), ++ c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) ++ if err := c.transport.waitSession(); err != nil { ++ return err ++ } ++ ++ c.sessionID = c.transport.getSessionID() ++ return c.clientAuthenticate(config) ++} ++ ++// verifyHostKeySignature verifies the host key obtained in the key exchange. ++// algo is the negotiated algorithm, and may be a certificate type. ++func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error { ++ sig, rest, ok := parseSignatureBody(result.Signature) ++ if len(rest) > 0 || !ok { ++ return errors.New("ssh: signature parse error") ++ } ++ ++ if a := underlyingAlgo(algo); sig.Format != a { ++ return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a) ++ } ++ ++ return hostKey.Verify(result.H, sig) ++} ++ ++// NewSession opens a new Session for this client. (A session is a remote ++// execution of a program.) ++func (c *Client) NewSession() (*Session, error) { ++ ch, in, err := c.OpenChannel("session", nil) ++ if err != nil { ++ return nil, err ++ } ++ return newSession(ch, in) ++} ++ ++func (c *Client) handleGlobalRequests(incoming <-chan *Request) { ++ for r := range incoming { ++ // This handles keepalive messages and matches ++ // the behaviour of OpenSSH. ++ r.Reply(false, nil) ++ } ++} ++ ++// handleChannelOpens channel open messages from the remote side. ++func (c *Client) handleChannelOpens(in <-chan NewChannel) { ++ for ch := range in { ++ c.mu.Lock() ++ handler := c.channelHandlers[ch.ChannelType()] ++ c.mu.Unlock() ++ ++ if handler != nil { ++ handler <- ch ++ } else { ++ ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) ++ } ++ } ++ ++ c.mu.Lock() ++ for _, ch := range c.channelHandlers { ++ close(ch) ++ } ++ c.channelHandlers = nil ++ c.mu.Unlock() ++} ++ ++// Dial starts a client connection to the given SSH server. It is a ++// convenience function that connects to the given network address, ++// initiates the SSH handshake, and then sets up a Client. For access ++// to incoming channels and requests, use net.Dial with NewClientConn ++// instead. ++func Dial(network, addr string, config *ClientConfig) (*Client, error) { ++ conn, err := net.DialTimeout(network, addr, config.Timeout) ++ if err != nil { ++ return nil, err ++ } ++ c, chans, reqs, err := NewClientConn(conn, addr, config) ++ if err != nil { ++ return nil, err ++ } ++ return NewClient(c, chans, reqs), nil ++} ++ ++// HostKeyCallback is the function type used for verifying server ++// keys. A HostKeyCallback must return nil if the host key is OK, or ++// an error to reject it. It receives the hostname as passed to Dial ++// or NewClientConn. The remote address is the RemoteAddr of the ++// net.Conn underlying the SSH connection. ++type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error ++ ++// BannerCallback is the function type used for treat the banner sent by ++// the server. A BannerCallback receives the message sent by the remote server. ++type BannerCallback func(message string) error ++ ++// A ClientConfig structure is used to configure a Client. It must not be ++// modified after having been passed to an SSH function. ++type ClientConfig struct { ++ // Config contains configuration that is shared between clients and ++ // servers. ++ Config ++ ++ // User contains the username to authenticate as. ++ User string ++ ++ // Auth contains possible authentication methods to use with the ++ // server. Only the first instance of a particular RFC 4252 method will ++ // be used during authentication. ++ Auth []AuthMethod ++ ++ // HostKeyCallback is called during the cryptographic ++ // handshake to validate the server's host key. The client ++ // configuration must supply this callback for the connection ++ // to succeed. The functions InsecureIgnoreHostKey or ++ // FixedHostKey can be used for simplistic host key checks. ++ HostKeyCallback HostKeyCallback ++ ++ // BannerCallback is called during the SSH dance to display a custom ++ // server's message. The client configuration can supply this callback to ++ // handle it as wished. The function BannerDisplayStderr can be used for ++ // simplistic display on Stderr. ++ BannerCallback BannerCallback ++ ++ // ClientVersion contains the version identification string that will ++ // be used for the connection. If empty, a reasonable default is used. ++ ClientVersion string ++ ++ // HostKeyAlgorithms lists the public key algorithms that the client will ++ // accept from the server for host key authentication, in order of ++ // preference. If empty, a reasonable default is used. Any ++ // string returned from a PublicKey.Type method may be used, or ++ // any of the CertAlgo and KeyAlgo constants. ++ HostKeyAlgorithms []string ++ ++ // Timeout is the maximum amount of time for the TCP connection to establish. ++ // ++ // A Timeout of zero means no timeout. ++ Timeout time.Duration ++} ++ ++// InsecureIgnoreHostKey returns a function that can be used for ++// ClientConfig.HostKeyCallback to accept any host key. It should ++// not be used for production code. ++func InsecureIgnoreHostKey() HostKeyCallback { ++ return func(hostname string, remote net.Addr, key PublicKey) error { ++ return nil ++ } ++} ++ ++type fixedHostKey struct { ++ key PublicKey ++} ++ ++func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error { ++ if f.key == nil { ++ return fmt.Errorf("ssh: required host key was nil") ++ } ++ if !bytes.Equal(key.Marshal(), f.key.Marshal()) { ++ return fmt.Errorf("ssh: host key mismatch") ++ } ++ return nil ++} ++ ++// FixedHostKey returns a function for use in ++// ClientConfig.HostKeyCallback to accept only a specific host key. ++func FixedHostKey(key PublicKey) HostKeyCallback { ++ hk := &fixedHostKey{key} ++ return hk.check ++} ++ ++// BannerDisplayStderr returns a function that can be used for ++// ClientConfig.BannerCallback to display banners on os.Stderr. ++func BannerDisplayStderr() BannerCallback { ++ return func(banner string) error { ++ _, err := os.Stderr.WriteString(banner) ++ ++ return err ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/client_auth.go b/ms_mod/golang.org/x/crypto/ssh/client_auth.go +new file mode 100644 +index 00000000000000..409b5ea1d49dbd +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/client_auth.go +@@ -0,0 +1,725 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "io" ++ "strings" ++) ++ ++type authResult int ++ ++const ( ++ authFailure authResult = iota ++ authPartialSuccess ++ authSuccess ++) ++ ++// clientAuthenticate authenticates with the remote server. See RFC 4252. ++func (c *connection) clientAuthenticate(config *ClientConfig) error { ++ // initiate user auth session ++ if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { ++ return err ++ } ++ packet, err := c.transport.readPacket() ++ if err != nil { ++ return err ++ } ++ // The server may choose to send a SSH_MSG_EXT_INFO at this point (if we ++ // advertised willingness to receive one, which we always do) or not. See ++ // RFC 8308, Section 2.4. ++ extensions := make(map[string][]byte) ++ if len(packet) > 0 && packet[0] == msgExtInfo { ++ var extInfo extInfoMsg ++ if err := Unmarshal(packet, &extInfo); err != nil { ++ return err ++ } ++ payload := extInfo.Payload ++ for i := uint32(0); i < extInfo.NumExtensions; i++ { ++ name, rest, ok := parseString(payload) ++ if !ok { ++ return parseError(msgExtInfo) ++ } ++ value, rest, ok := parseString(rest) ++ if !ok { ++ return parseError(msgExtInfo) ++ } ++ extensions[string(name)] = value ++ payload = rest ++ } ++ packet, err = c.transport.readPacket() ++ if err != nil { ++ return err ++ } ++ } ++ var serviceAccept serviceAcceptMsg ++ if err := Unmarshal(packet, &serviceAccept); err != nil { ++ return err ++ } ++ ++ // during the authentication phase the client first attempts the "none" method ++ // then any untried methods suggested by the server. ++ var tried []string ++ var lastMethods []string ++ ++ sessionID := c.transport.getSessionID() ++ for auth := AuthMethod(new(noneAuth)); auth != nil; { ++ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions) ++ if err != nil { ++ return err ++ } ++ if ok == authSuccess { ++ // success ++ return nil ++ } else if ok == authFailure { ++ if m := auth.method(); !contains(tried, m) { ++ tried = append(tried, m) ++ } ++ } ++ if methods == nil { ++ methods = lastMethods ++ } ++ lastMethods = methods ++ ++ auth = nil ++ ++ findNext: ++ for _, a := range config.Auth { ++ candidateMethod := a.method() ++ if contains(tried, candidateMethod) { ++ continue ++ } ++ for _, meth := range methods { ++ if meth == candidateMethod { ++ auth = a ++ break findNext ++ } ++ } ++ } ++ } ++ return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried) ++} ++ ++func contains(list []string, e string) bool { ++ for _, s := range list { ++ if s == e { ++ return true ++ } ++ } ++ return false ++} ++ ++// An AuthMethod represents an instance of an RFC 4252 authentication method. ++type AuthMethod interface { ++ // auth authenticates user over transport t. ++ // Returns true if authentication is successful. ++ // If authentication is not successful, a []string of alternative ++ // method names is returned. If the slice is nil, it will be ignored ++ // and the previous set of possible methods will be reused. ++ auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) ++ ++ // method returns the RFC 4252 method name. ++ method() string ++} ++ ++// "none" authentication, RFC 4252 section 5.2. ++type noneAuth int ++ ++func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { ++ if err := c.writePacket(Marshal(&userAuthRequestMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: "none", ++ })); err != nil { ++ return authFailure, nil, err ++ } ++ ++ return handleAuthResponse(c) ++} ++ ++func (n *noneAuth) method() string { ++ return "none" ++} ++ ++// passwordCallback is an AuthMethod that fetches the password through ++// a function call, e.g. by prompting the user. ++type passwordCallback func() (password string, err error) ++ ++func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { ++ type passwordAuthMsg struct { ++ User string `sshtype:"50"` ++ Service string ++ Method string ++ Reply bool ++ Password string ++ } ++ ++ pw, err := cb() ++ // REVIEW NOTE: is there a need to support skipping a password attempt? ++ // The program may only find out that the user doesn't have a password ++ // when prompting. ++ if err != nil { ++ return authFailure, nil, err ++ } ++ ++ if err := c.writePacket(Marshal(&passwordAuthMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: cb.method(), ++ Reply: false, ++ Password: pw, ++ })); err != nil { ++ return authFailure, nil, err ++ } ++ ++ return handleAuthResponse(c) ++} ++ ++func (cb passwordCallback) method() string { ++ return "password" ++} ++ ++// Password returns an AuthMethod using the given password. ++func Password(secret string) AuthMethod { ++ return passwordCallback(func() (string, error) { return secret, nil }) ++} ++ ++// PasswordCallback returns an AuthMethod that uses a callback for ++// fetching a password. ++func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { ++ return passwordCallback(prompt) ++} ++ ++type publickeyAuthMsg struct { ++ User string `sshtype:"50"` ++ Service string ++ Method string ++ // HasSig indicates to the receiver packet that the auth request is signed and ++ // should be used for authentication of the request. ++ HasSig bool ++ Algoname string ++ PubKey []byte ++ // Sig is tagged with "rest" so Marshal will exclude it during ++ // validateKey ++ Sig []byte `ssh:"rest"` ++} ++ ++// publicKeyCallback is an AuthMethod that uses a set of key ++// pairs for authentication. ++type publicKeyCallback func() ([]Signer, error) ++ ++func (cb publicKeyCallback) method() string { ++ return "publickey" ++} ++ ++func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) { ++ keyFormat := signer.PublicKey().Type() ++ ++ // Like in sendKexInit, if the public key implements AlgorithmSigner we ++ // assume it supports all algorithms, otherwise only the key format one. ++ as, ok := signer.(AlgorithmSigner) ++ if !ok { ++ return algorithmSignerWrapper{signer}, keyFormat ++ } ++ ++ extPayload, ok := extensions["server-sig-algs"] ++ if !ok { ++ // If there is no "server-sig-algs" extension, fall back to the key ++ // format algorithm. ++ return as, keyFormat ++ } ++ ++ // The server-sig-algs extension only carries underlying signature ++ // algorithm, but we are trying to select a protocol-level public key ++ // algorithm, which might be a certificate type. Extend the list of server ++ // supported algorithms to include the corresponding certificate algorithms. ++ serverAlgos := strings.Split(string(extPayload), ",") ++ for _, algo := range serverAlgos { ++ if certAlgo, ok := certificateAlgo(algo); ok { ++ serverAlgos = append(serverAlgos, certAlgo) ++ } ++ } ++ ++ keyAlgos := algorithmsForKeyFormat(keyFormat) ++ algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos) ++ if err != nil { ++ // If there is no overlap, try the key anyway with the key format ++ // algorithm, to support servers that fail to list all supported ++ // algorithms. ++ return as, keyFormat ++ } ++ return as, algo ++} ++ ++func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { ++ // Authentication is performed by sending an enquiry to test if a key is ++ // acceptable to the remote. If the key is acceptable, the client will ++ // attempt to authenticate with the valid key. If not the client will repeat ++ // the process with the remaining keys. ++ ++ signers, err := cb() ++ if err != nil { ++ return authFailure, nil, err ++ } ++ var methods []string ++ for _, signer := range signers { ++ pub := signer.PublicKey() ++ as, algo := pickSignatureAlgorithm(signer, extensions) ++ ++ ok, err := validateKey(pub, algo, user, c) ++ if err != nil { ++ return authFailure, nil, err ++ } ++ if !ok { ++ continue ++ } ++ ++ pubKey := pub.Marshal() ++ data := buildDataSignedForAuth(session, userAuthRequestMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: cb.method(), ++ }, algo, pubKey) ++ sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) ++ if err != nil { ++ return authFailure, nil, err ++ } ++ ++ // manually wrap the serialized signature in a string ++ s := Marshal(sign) ++ sig := make([]byte, stringLength(len(s))) ++ marshalString(sig, s) ++ msg := publickeyAuthMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: cb.method(), ++ HasSig: true, ++ Algoname: algo, ++ PubKey: pubKey, ++ Sig: sig, ++ } ++ p := Marshal(&msg) ++ if err := c.writePacket(p); err != nil { ++ return authFailure, nil, err ++ } ++ var success authResult ++ success, methods, err = handleAuthResponse(c) ++ if err != nil { ++ return authFailure, nil, err ++ } ++ ++ // If authentication succeeds or the list of available methods does not ++ // contain the "publickey" method, do not attempt to authenticate with any ++ // other keys. According to RFC 4252 Section 7, the latter can occur when ++ // additional authentication methods are required. ++ if success == authSuccess || !containsMethod(methods, cb.method()) { ++ return success, methods, err ++ } ++ } ++ ++ return authFailure, methods, nil ++} ++ ++func containsMethod(methods []string, method string) bool { ++ for _, m := range methods { ++ if m == method { ++ return true ++ } ++ } ++ ++ return false ++} ++ ++// validateKey validates the key provided is acceptable to the server. ++func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) { ++ pubKey := key.Marshal() ++ msg := publickeyAuthMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: "publickey", ++ HasSig: false, ++ Algoname: algo, ++ PubKey: pubKey, ++ } ++ if err := c.writePacket(Marshal(&msg)); err != nil { ++ return false, err ++ } ++ ++ return confirmKeyAck(key, algo, c) ++} ++ ++func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) { ++ pubKey := key.Marshal() ++ ++ for { ++ packet, err := c.readPacket() ++ if err != nil { ++ return false, err ++ } ++ switch packet[0] { ++ case msgUserAuthBanner: ++ if err := handleBannerResponse(c, packet); err != nil { ++ return false, err ++ } ++ case msgUserAuthPubKeyOk: ++ var msg userAuthPubKeyOkMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return false, err ++ } ++ if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) { ++ return false, nil ++ } ++ return true, nil ++ case msgUserAuthFailure: ++ return false, nil ++ default: ++ return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0]) ++ } ++ } ++} ++ ++// PublicKeys returns an AuthMethod that uses the given key ++// pairs. ++func PublicKeys(signers ...Signer) AuthMethod { ++ return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) ++} ++ ++// PublicKeysCallback returns an AuthMethod that runs the given ++// function to obtain a list of key pairs. ++func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { ++ return publicKeyCallback(getSigners) ++} ++ ++// handleAuthResponse returns whether the preceding authentication request succeeded ++// along with a list of remaining authentication methods to try next and ++// an error if an unexpected response was received. ++func handleAuthResponse(c packetConn) (authResult, []string, error) { ++ gotMsgExtInfo := false ++ for { ++ packet, err := c.readPacket() ++ if err != nil { ++ return authFailure, nil, err ++ } ++ ++ switch packet[0] { ++ case msgUserAuthBanner: ++ if err := handleBannerResponse(c, packet); err != nil { ++ return authFailure, nil, err ++ } ++ case msgExtInfo: ++ // Ignore post-authentication RFC 8308 extensions, once. ++ if gotMsgExtInfo { ++ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) ++ } ++ gotMsgExtInfo = true ++ case msgUserAuthFailure: ++ var msg userAuthFailureMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return authFailure, nil, err ++ } ++ if msg.PartialSuccess { ++ return authPartialSuccess, msg.Methods, nil ++ } ++ return authFailure, msg.Methods, nil ++ case msgUserAuthSuccess: ++ return authSuccess, nil, nil ++ default: ++ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) ++ } ++ } ++} ++ ++func handleBannerResponse(c packetConn, packet []byte) error { ++ var msg userAuthBannerMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return err ++ } ++ ++ transport, ok := c.(*handshakeTransport) ++ if !ok { ++ return nil ++ } ++ ++ if transport.bannerCallback != nil { ++ return transport.bannerCallback(msg.Message) ++ } ++ ++ return nil ++} ++ ++// KeyboardInteractiveChallenge should print questions, optionally ++// disabling echoing (e.g. for passwords), and return all the answers. ++// Challenge may be called multiple times in a single session. After ++// successful authentication, the server may send a challenge with no ++// questions, for which the name and instruction messages should be ++// printed. RFC 4256 section 3.3 details how the UI should behave for ++// both CLI and GUI environments. ++type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error) ++ ++// KeyboardInteractive returns an AuthMethod using a prompt/response ++// sequence controlled by the server. ++func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { ++ return challenge ++} ++ ++func (cb KeyboardInteractiveChallenge) method() string { ++ return "keyboard-interactive" ++} ++ ++func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { ++ type initiateMsg struct { ++ User string `sshtype:"50"` ++ Service string ++ Method string ++ Language string ++ Submethods string ++ } ++ ++ if err := c.writePacket(Marshal(&initiateMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: "keyboard-interactive", ++ })); err != nil { ++ return authFailure, nil, err ++ } ++ ++ gotMsgExtInfo := false ++ for { ++ packet, err := c.readPacket() ++ if err != nil { ++ return authFailure, nil, err ++ } ++ ++ // like handleAuthResponse, but with less options. ++ switch packet[0] { ++ case msgUserAuthBanner: ++ if err := handleBannerResponse(c, packet); err != nil { ++ return authFailure, nil, err ++ } ++ continue ++ case msgExtInfo: ++ // Ignore post-authentication RFC 8308 extensions, once. ++ if gotMsgExtInfo { ++ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) ++ } ++ gotMsgExtInfo = true ++ continue ++ case msgUserAuthInfoRequest: ++ // OK ++ case msgUserAuthFailure: ++ var msg userAuthFailureMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return authFailure, nil, err ++ } ++ if msg.PartialSuccess { ++ return authPartialSuccess, msg.Methods, nil ++ } ++ return authFailure, msg.Methods, nil ++ case msgUserAuthSuccess: ++ return authSuccess, nil, nil ++ default: ++ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) ++ } ++ ++ var msg userAuthInfoRequestMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return authFailure, nil, err ++ } ++ ++ // Manually unpack the prompt/echo pairs. ++ rest := msg.Prompts ++ var prompts []string ++ var echos []bool ++ for i := 0; i < int(msg.NumPrompts); i++ { ++ prompt, r, ok := parseString(rest) ++ if !ok || len(r) == 0 { ++ return authFailure, nil, errors.New("ssh: prompt format error") ++ } ++ prompts = append(prompts, string(prompt)) ++ echos = append(echos, r[0] != 0) ++ rest = r[1:] ++ } ++ ++ if len(rest) != 0 { ++ return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") ++ } ++ ++ answers, err := cb(msg.Name, msg.Instruction, prompts, echos) ++ if err != nil { ++ return authFailure, nil, err ++ } ++ ++ if len(answers) != len(prompts) { ++ return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts)) ++ } ++ responseLength := 1 + 4 ++ for _, a := range answers { ++ responseLength += stringLength(len(a)) ++ } ++ serialized := make([]byte, responseLength) ++ p := serialized ++ p[0] = msgUserAuthInfoResponse ++ p = p[1:] ++ p = marshalUint32(p, uint32(len(answers))) ++ for _, a := range answers { ++ p = marshalString(p, []byte(a)) ++ } ++ ++ if err := c.writePacket(serialized); err != nil { ++ return authFailure, nil, err ++ } ++ } ++} ++ ++type retryableAuthMethod struct { ++ authMethod AuthMethod ++ maxTries int ++} ++ ++func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) { ++ for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { ++ ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions) ++ if ok != authFailure || err != nil { // either success, partial success or error terminate ++ return ok, methods, err ++ } ++ } ++ return ok, methods, err ++} ++ ++func (r *retryableAuthMethod) method() string { ++ return r.authMethod.method() ++} ++ ++// RetryableAuthMethod is a decorator for other auth methods enabling them to ++// be retried up to maxTries before considering that AuthMethod itself failed. ++// If maxTries is <= 0, will retry indefinitely ++// ++// This is useful for interactive clients using challenge/response type ++// authentication (e.g. Keyboard-Interactive, Password, etc) where the user ++// could mistype their response resulting in the server issuing a ++// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4 ++// [keyboard-interactive]); Without this decorator, the non-retryable ++// AuthMethod would be removed from future consideration, and never tried again ++// (and so the user would never be able to retry their entry). ++func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { ++ return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} ++} ++ ++// GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication. ++// See RFC 4462 section 3 ++// gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details. ++// target is the server host you want to log in to. ++func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod { ++ if gssAPIClient == nil { ++ panic("gss-api client must be not nil with enable gssapi-with-mic") ++ } ++ return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target} ++} ++ ++type gssAPIWithMICCallback struct { ++ gssAPIClient GSSAPIClient ++ target string ++} ++ ++func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { ++ m := &userAuthRequestMsg{ ++ User: user, ++ Service: serviceSSH, ++ Method: g.method(), ++ } ++ // The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST. ++ // See RFC 4462 section 3.2. ++ m.Payload = appendU32(m.Payload, 1) ++ m.Payload = appendString(m.Payload, string(krb5OID)) ++ if err := c.writePacket(Marshal(m)); err != nil { ++ return authFailure, nil, err ++ } ++ // The server responds to the SSH_MSG_USERAUTH_REQUEST with either an ++ // SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or ++ // with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE. ++ // See RFC 4462 section 3.3. ++ // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check ++ // selected mech if it is valid. ++ packet, err := c.readPacket() ++ if err != nil { ++ return authFailure, nil, err ++ } ++ userAuthGSSAPIResp := &userAuthGSSAPIResponse{} ++ if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil { ++ return authFailure, nil, err ++ } ++ // Start the loop into the exchange token. ++ // See RFC 4462 section 3.4. ++ var token []byte ++ defer g.gssAPIClient.DeleteSecContext() ++ for { ++ // Initiates the establishment of a security context between the application and a remote peer. ++ nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false) ++ if err != nil { ++ return authFailure, nil, err ++ } ++ if len(nextToken) > 0 { ++ if err := c.writePacket(Marshal(&userAuthGSSAPIToken{ ++ Token: nextToken, ++ })); err != nil { ++ return authFailure, nil, err ++ } ++ } ++ if !needContinue { ++ break ++ } ++ packet, err = c.readPacket() ++ if err != nil { ++ return authFailure, nil, err ++ } ++ switch packet[0] { ++ case msgUserAuthFailure: ++ var msg userAuthFailureMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return authFailure, nil, err ++ } ++ if msg.PartialSuccess { ++ return authPartialSuccess, msg.Methods, nil ++ } ++ return authFailure, msg.Methods, nil ++ case msgUserAuthGSSAPIError: ++ userAuthGSSAPIErrorResp := &userAuthGSSAPIError{} ++ if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil { ++ return authFailure, nil, err ++ } ++ return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+ ++ "Major Status: %d\n"+ ++ "Minor Status: %d\n"+ ++ "Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus, ++ userAuthGSSAPIErrorResp.Message) ++ case msgUserAuthGSSAPIToken: ++ userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} ++ if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { ++ return authFailure, nil, err ++ } ++ token = userAuthGSSAPITokenReq.Token ++ } ++ } ++ // Binding Encryption Keys. ++ // See RFC 4462 section 3.5. ++ micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic") ++ micToken, err := g.gssAPIClient.GetMIC(micField) ++ if err != nil { ++ return authFailure, nil, err ++ } ++ if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{ ++ MIC: micToken, ++ })); err != nil { ++ return authFailure, nil, err ++ } ++ return handleAuthResponse(c) ++} ++ ++func (g *gssAPIWithMICCallback) method() string { ++ return "gssapi-with-mic" ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/client_auth_test.go b/ms_mod/golang.org/x/crypto/ssh/client_auth_test.go +new file mode 100644 +index 00000000000000..70558a9a77f374 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/client_auth_test.go +@@ -0,0 +1,1078 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "errors" ++ "fmt" ++ "io" ++ "log" ++ "net" ++ "os" ++ "runtime" ++ "strings" ++ "testing" ++) ++ ++type keyboardInteractive map[string]string ++ ++func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) { ++ var answers []string ++ for _, q := range questions { ++ answers = append(answers, cr[q]) ++ } ++ return answers, nil ++} ++ ++// reused internally by tests ++var clientPassword = "tiger" ++ ++// tryAuth runs a handshake with a given config against an SSH server ++// with config serverConfig. Returns both client and server side errors. ++func tryAuth(t *testing.T, config *ClientConfig) error { ++ err, _ := tryAuthBothSides(t, config, nil) ++ return err ++} ++ ++// tryAuth runs a handshake with a given config against an SSH server ++// with a given GSSAPIWithMICConfig and config serverConfig. Returns both client and server side errors. ++func tryAuthWithGSSAPIWithMICConfig(t *testing.T, clientConfig *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) error { ++ err, _ := tryAuthBothSides(t, clientConfig, gssAPIWithMICConfig) ++ return err ++} ++ ++// tryAuthBothSides runs the handshake and returns the resulting errors from both sides of the connection. ++func tryAuthBothSides(t *testing.T, config *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) (clientError error, serverAuthErrors []error) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ certChecker := CertChecker{ ++ IsUserAuthority: func(k PublicKey) bool { ++ return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) ++ }, ++ UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { ++ if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { ++ return nil, nil ++ } ++ ++ return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) ++ }, ++ IsRevoked: func(c *Certificate) bool { ++ return c.Serial == 666 ++ }, ++ } ++ serverConfig := &ServerConfig{ ++ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { ++ if conn.User() == "testuser" && string(pass) == clientPassword { ++ return nil, nil ++ } ++ return nil, errors.New("password auth failed") ++ }, ++ PublicKeyCallback: certChecker.Authenticate, ++ KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) { ++ ans, err := challenge("user", ++ "instruction", ++ []string{"question1", "question2"}, ++ []bool{true, true}) ++ if err != nil { ++ return nil, err ++ } ++ ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" ++ if ok { ++ challenge("user", "motd", nil, nil) ++ return nil, nil ++ } ++ return nil, errors.New("keyboard-interactive failed") ++ }, ++ GSSAPIWithMICConfig: gssAPIWithMICConfig, ++ } ++ serverConfig.AddHostKey(testSigners["rsa"]) ++ ++ serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) { ++ serverAuthErrors = append(serverAuthErrors, err) ++ } ++ ++ go newServer(c1, serverConfig) ++ _, _, _, err = NewClientConn(c2, "", config) ++ return err, serverAuthErrors ++} ++ ++type loggingAlgorithmSigner struct { ++ used []string ++ AlgorithmSigner ++} ++ ++func (l *loggingAlgorithmSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { ++ l.used = append(l.used, "[Sign]") ++ return l.AlgorithmSigner.Sign(rand, data) ++} ++ ++func (l *loggingAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { ++ l.used = append(l.used, algorithm) ++ return l.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm) ++} ++ ++func TestClientAuthPublicKey(t *testing.T) { ++ signer := &loggingAlgorithmSigner{AlgorithmSigner: testSigners["rsa"].(AlgorithmSigner)} ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(signer), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++ if len(signer.used) != 1 || signer.used[0] != KeyAlgoRSASHA256 { ++ t.Errorf("unexpected Sign/SignWithAlgorithm calls: %q", signer.used) ++ } ++} ++ ++// TestClientAuthNoSHA2 tests a ssh-rsa Signer that doesn't implement AlgorithmSigner. ++func TestClientAuthNoSHA2(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(&legacyRSASigner{testSigners["rsa"]}), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++} ++ ++// TestClientAuthThirdKey checks that the third configured can succeed. If we ++// were to do three attempts for each key (rsa-sha2-256, rsa-sha2-512, ssh-rsa), ++// we'd hit the six maximum attempts before reaching it. ++func TestClientAuthThirdKey(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["rsa-openssh-format"], ++ testSigners["rsa-openssh-format"], testSigners["rsa"]), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++} ++ ++func TestAuthMethodPassword(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ Password(clientPassword), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++} ++ ++func TestAuthMethodFallback(t *testing.T) { ++ var passwordCalled bool ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["rsa"]), ++ PasswordCallback( ++ func() (string, error) { ++ passwordCalled = true ++ return "WRONG", nil ++ }), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++ ++ if passwordCalled { ++ t.Errorf("password auth tried before public-key auth.") ++ } ++} ++ ++func TestAuthMethodWrongPassword(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ Password("wrong"), ++ PublicKeys(testSigners["rsa"]), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++} ++ ++func TestAuthMethodKeyboardInteractive(t *testing.T) { ++ answers := keyboardInteractive(map[string]string{ ++ "question1": "answer1", ++ "question2": "answer2", ++ }) ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ KeyboardInteractive(answers.Challenge), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++} ++ ++func TestAuthMethodWrongKeyboardInteractive(t *testing.T) { ++ answers := keyboardInteractive(map[string]string{ ++ "question1": "answer1", ++ "question2": "WRONG", ++ }) ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ KeyboardInteractive(answers.Challenge), ++ }, ++ } ++ ++ if err := tryAuth(t, config); err == nil { ++ t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive") ++ } ++} ++ ++// the mock server will only authenticate ssh-rsa keys ++func TestAuthMethodInvalidPublicKey(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["dsa"]), ++ }, ++ } ++ ++ if err := tryAuth(t, config); err == nil { ++ t.Fatalf("dsa private key should not have authenticated with rsa public key") ++ } ++} ++ ++// the client should authenticate with the second key ++func TestAuthMethodRSAandDSA(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["dsa"], testSigners["rsa"]), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("client could not authenticate with rsa key: %v", err) ++ } ++} ++ ++type invalidAlgSigner struct { ++ Signer ++} ++ ++func (s *invalidAlgSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { ++ sig, err := s.Signer.Sign(rand, data) ++ if sig != nil { ++ sig.Format = "invalid" ++ } ++ return sig, err ++} ++ ++func TestMethodInvalidAlgorithm(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(&invalidAlgSigner{testSigners["rsa"]}), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ err, serverErrors := tryAuthBothSides(t, config, nil) ++ if err == nil { ++ t.Fatalf("login succeeded") ++ } ++ ++ found := false ++ want := "algorithm \"invalid\"" ++ ++ var errStrings []string ++ for _, err := range serverErrors { ++ found = found || (err != nil && strings.Contains(err.Error(), want)) ++ errStrings = append(errStrings, err.Error()) ++ } ++ if !found { ++ t.Errorf("server got error %q, want substring %q", errStrings, want) ++ } ++} ++ ++func TestClientHMAC(t *testing.T) { ++ for _, mac := range supportedMACs { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["rsa"]), ++ }, ++ Config: Config{ ++ MACs: []string{mac}, ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err) ++ } ++ } ++} ++ ++// issue 4285. ++func TestClientUnsupportedCipher(t *testing.T) { ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(), ++ }, ++ Config: Config{ ++ Ciphers: []string{"aes128-cbc"}, // not currently supported ++ }, ++ } ++ if err := tryAuth(t, config); err == nil { ++ t.Errorf("expected no ciphers in common") ++ } ++} ++ ++func TestClientUnsupportedKex(t *testing.T) { ++ if os.Getenv("GO_BUILDER_NAME") != "" { ++ t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198") ++ } ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(), ++ }, ++ Config: Config{ ++ KeyExchanges: []string{"non-existent-kex"}, ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") { ++ t.Errorf("got %v, expected 'common algorithm'", err) ++ } ++} ++ ++func TestClientLoginCert(t *testing.T) { ++ cert := &Certificate{ ++ Key: testPublicKeys["rsa"], ++ ValidBefore: CertTimeInfinity, ++ CertType: UserCert, ++ } ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ certSigner, err := NewCertSigner(cert, testSigners["rsa"]) ++ if err != nil { ++ t.Fatalf("NewCertSigner: %v", err) ++ } ++ ++ clientConfig := &ClientConfig{ ++ User: "user", ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner)) ++ ++ // should succeed ++ if err := tryAuth(t, clientConfig); err != nil { ++ t.Errorf("cert login failed: %v", err) ++ } ++ ++ // corrupted signature ++ cert.Signature.Blob[0]++ ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("cert login passed with corrupted sig") ++ } ++ ++ // revoked ++ cert.Serial = 666 ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("revoked cert login succeeded") ++ } ++ cert.Serial = 1 ++ ++ // sign with wrong key ++ cert.SignCert(rand.Reader, testSigners["dsa"]) ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("cert login passed with non-authoritative key") ++ } ++ ++ // host cert ++ cert.CertType = HostCert ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("cert login passed with wrong type") ++ } ++ cert.CertType = UserCert ++ ++ // principal specified ++ cert.ValidPrincipals = []string{"user"} ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err != nil { ++ t.Errorf("cert login failed: %v", err) ++ } ++ ++ // wrong principal specified ++ cert.ValidPrincipals = []string{"fred"} ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("cert login passed with wrong principal") ++ } ++ cert.ValidPrincipals = nil ++ ++ // added critical option ++ cert.CriticalOptions = map[string]string{"root-access": "yes"} ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("cert login passed with unrecognized critical option") ++ } ++ ++ // allowed source address ++ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"} ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err != nil { ++ t.Errorf("cert login with source-address failed: %v", err) ++ } ++ ++ // disallowed source address ++ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"} ++ cert.SignCert(rand.Reader, testSigners["ecdsa"]) ++ if err := tryAuth(t, clientConfig); err == nil { ++ t.Errorf("cert login with source-address succeeded") ++ } ++} ++ ++func testPermissionsPassing(withPermissions bool, t *testing.T) { ++ serverConfig := &ServerConfig{ ++ PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { ++ if conn.User() == "nopermissions" { ++ return nil, nil ++ } ++ return &Permissions{}, nil ++ }, ++ } ++ serverConfig.AddHostKey(testSigners["rsa"]) ++ ++ clientConfig := &ClientConfig{ ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["rsa"]), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if withPermissions { ++ clientConfig.User = "permissions" ++ } else { ++ clientConfig.User = "nopermissions" ++ } ++ ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go NewClientConn(c2, "", clientConfig) ++ serverConn, err := newServer(c1, serverConfig) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if p := serverConn.Permissions; (p != nil) != withPermissions { ++ t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p) ++ } ++} ++ ++func TestPermissionsPassing(t *testing.T) { ++ testPermissionsPassing(true, t) ++} ++ ++func TestNoPermissionsPassing(t *testing.T) { ++ testPermissionsPassing(false, t) ++} ++ ++func TestRetryableAuth(t *testing.T) { ++ n := 0 ++ passwords := []string{"WRONG1", "WRONG2"} ++ ++ config := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ RetryableAuthMethod(PasswordCallback(func() (string, error) { ++ p := passwords[n] ++ n++ ++ return p, nil ++ }), 2), ++ PublicKeys(testSigners["rsa"]), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ if err := tryAuth(t, config); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++ if n != 2 { ++ t.Fatalf("Did not try all passwords") ++ } ++} ++ ++func ExampleRetryableAuthMethod() { ++ user := "testuser" ++ NumberOfPrompts := 3 ++ ++ // Normally this would be a callback that prompts the user to answer the ++ // provided questions ++ Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { ++ return []string{"answer1", "answer2"}, nil ++ } ++ ++ config := &ClientConfig{ ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ User: user, ++ Auth: []AuthMethod{ ++ RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts), ++ }, ++ } ++ ++ host := "mysshserver" ++ netConn, err := net.Dial("tcp", host) ++ if err != nil { ++ log.Fatal(err) ++ } ++ ++ sshConn, _, _, err := NewClientConn(netConn, host, config) ++ if err != nil { ++ log.Fatal(err) ++ } ++ _ = sshConn ++} ++ ++// Test if username is received on server side when NoClientAuth is used ++func TestClientAuthNone(t *testing.T) { ++ user := "testuser" ++ serverConfig := &ServerConfig{ ++ NoClientAuth: true, ++ } ++ serverConfig.AddHostKey(testSigners["rsa"]) ++ ++ clientConfig := &ClientConfig{ ++ User: user, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go NewClientConn(c2, "", clientConfig) ++ serverConn, err := newServer(c1, serverConfig) ++ if err != nil { ++ t.Fatalf("newServer: %v", err) ++ } ++ if serverConn.User() != user { ++ t.Fatalf("server: got %q, want %q", serverConn.User(), user) ++ } ++} ++ ++// Test if authentication attempts are limited on server when MaxAuthTries is set ++func TestClientAuthMaxAuthTries(t *testing.T) { ++ user := "testuser" ++ ++ serverConfig := &ServerConfig{ ++ MaxAuthTries: 2, ++ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { ++ if conn.User() == "testuser" && string(pass) == "right" { ++ return nil, nil ++ } ++ return nil, errors.New("password auth failed") ++ }, ++ } ++ serverConfig.AddHostKey(testSigners["rsa"]) ++ ++ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ ++ Reason: 2, ++ Message: "too many authentication failures", ++ }) ++ ++ for tries := 2; tries < 4; tries++ { ++ n := tries ++ clientConfig := &ClientConfig{ ++ User: user, ++ Auth: []AuthMethod{ ++ RetryableAuthMethod(PasswordCallback(func() (string, error) { ++ n-- ++ if n == 0 { ++ return "right", nil ++ } ++ return "wrong", nil ++ }), tries), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go newServer(c1, serverConfig) ++ _, _, _, err = NewClientConn(c2, "", clientConfig) ++ if tries > 2 { ++ if err == nil { ++ t.Fatalf("client: got no error, want %s", expectedErr) ++ } else if err.Error() != expectedErr.Error() { ++ t.Fatalf("client: got %s, want %s", err, expectedErr) ++ } ++ } else { ++ if err != nil { ++ t.Fatalf("client: got %s, want no error", err) ++ } ++ } ++ } ++} ++ ++// Test if authentication attempts are correctly limited on server ++// when more public keys are provided then MaxAuthTries ++func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) { ++ signers := []Signer{} ++ for i := 0; i < 6; i++ { ++ signers = append(signers, testSigners["dsa"]) ++ } ++ ++ validConfig := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, validConfig); err != nil { ++ t.Fatalf("unable to dial remote side: %s", err) ++ } ++ ++ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ ++ Reason: 2, ++ Message: "too many authentication failures", ++ }) ++ invalidConfig := &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ PublicKeys(append(signers, testSigners["rsa"])...), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ if err := tryAuth(t, invalidConfig); err == nil { ++ t.Fatalf("client: got no error, want %s", expectedErr) ++ } else if err.Error() != expectedErr.Error() { ++ // On Windows we can see a WSAECONNABORTED error ++ // if the client writes another authentication request ++ // before the client goroutine reads the disconnection ++ // message. See issue 50805. ++ if runtime.GOOS == "windows" && strings.Contains(err.Error(), "wsarecv: An established connection was aborted") { ++ // OK. ++ } else { ++ t.Fatalf("client: got %s, want %s", err, expectedErr) ++ } ++ } ++} ++ ++// Test whether authentication errors are being properly logged if all ++// authentication methods have been exhausted ++func TestClientAuthErrorList(t *testing.T) { ++ publicKeyErr := errors.New("This is an error from PublicKeyCallback") ++ ++ clientConfig := &ClientConfig{ ++ Auth: []AuthMethod{ ++ PublicKeys(testSigners["rsa"]), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ serverConfig := &ServerConfig{ ++ PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) { ++ return nil, publicKeyErr ++ }, ++ } ++ serverConfig.AddHostKey(testSigners["rsa"]) ++ ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go NewClientConn(c2, "", clientConfig) ++ _, err = newServer(c1, serverConfig) ++ if err == nil { ++ t.Fatal("newServer: got nil, expected errors") ++ } ++ ++ authErrs, ok := err.(*ServerAuthError) ++ if !ok { ++ t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err) ++ } ++ for i, e := range authErrs.Errors { ++ switch i { ++ case 0: ++ if e != ErrNoAuth { ++ t.Fatalf("errors: got error %v, want ErrNoAuth", e) ++ } ++ case 1: ++ if e != publicKeyErr { ++ t.Fatalf("errors: got %v, want %v", e, publicKeyErr) ++ } ++ default: ++ t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors) ++ } ++ } ++} ++ ++func TestAuthMethodGSSAPIWithMIC(t *testing.T) { ++ type testcase struct { ++ config *ClientConfig ++ gssConfig *GSSAPIWithMICConfig ++ clientWantErr string ++ serverWantErr string ++ } ++ testcases := []*testcase{ ++ { ++ config: &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ GSSAPIWithMICAuthMethod( ++ &FakeClient{ ++ exchanges: []*exchange{ ++ { ++ outToken: "client-valid-token-1", ++ }, ++ { ++ expectedToken: "server-valid-token-1", ++ }, ++ }, ++ mic: []byte("valid-mic"), ++ maxRound: 2, ++ }, "testtarget", ++ ), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ }, ++ gssConfig: &GSSAPIWithMICConfig{ ++ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { ++ if srcName != conn.User()+"@DOMAIN" { ++ return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User()) ++ } ++ return nil, nil ++ }, ++ Server: &FakeServer{ ++ exchanges: []*exchange{ ++ { ++ outToken: "server-valid-token-1", ++ expectedToken: "client-valid-token-1", ++ }, ++ }, ++ maxRound: 1, ++ expectedMIC: []byte("valid-mic"), ++ srcName: "testuser@DOMAIN", ++ }, ++ }, ++ }, ++ { ++ config: &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ GSSAPIWithMICAuthMethod( ++ &FakeClient{ ++ exchanges: []*exchange{ ++ { ++ outToken: "client-valid-token-1", ++ }, ++ { ++ expectedToken: "server-valid-token-1", ++ }, ++ }, ++ mic: []byte("valid-mic"), ++ maxRound: 2, ++ }, "testtarget", ++ ), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ }, ++ gssConfig: &GSSAPIWithMICConfig{ ++ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { ++ return nil, fmt.Errorf("user is not allowed to login") ++ }, ++ Server: &FakeServer{ ++ exchanges: []*exchange{ ++ { ++ outToken: "server-valid-token-1", ++ expectedToken: "client-valid-token-1", ++ }, ++ }, ++ maxRound: 1, ++ expectedMIC: []byte("valid-mic"), ++ srcName: "testuser@DOMAIN", ++ }, ++ }, ++ serverWantErr: "user is not allowed to login", ++ clientWantErr: "ssh: handshake failed: ssh: unable to authenticate", ++ }, ++ { ++ config: &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ GSSAPIWithMICAuthMethod( ++ &FakeClient{ ++ exchanges: []*exchange{ ++ { ++ outToken: "client-valid-token-1", ++ }, ++ { ++ expectedToken: "server-valid-token-1", ++ }, ++ }, ++ mic: []byte("valid-mic"), ++ maxRound: 2, ++ }, "testtarget", ++ ), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ }, ++ gssConfig: &GSSAPIWithMICConfig{ ++ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { ++ if srcName != conn.User() { ++ return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User()) ++ } ++ return nil, nil ++ }, ++ Server: &FakeServer{ ++ exchanges: []*exchange{ ++ { ++ outToken: "server-invalid-token-1", ++ expectedToken: "client-valid-token-1", ++ }, ++ }, ++ maxRound: 1, ++ expectedMIC: []byte("valid-mic"), ++ srcName: "testuser@DOMAIN", ++ }, ++ }, ++ clientWantErr: "ssh: handshake failed: got \"server-invalid-token-1\", want token \"server-valid-token-1\"", ++ }, ++ { ++ config: &ClientConfig{ ++ User: "testuser", ++ Auth: []AuthMethod{ ++ GSSAPIWithMICAuthMethod( ++ &FakeClient{ ++ exchanges: []*exchange{ ++ { ++ outToken: "client-valid-token-1", ++ }, ++ { ++ expectedToken: "server-valid-token-1", ++ }, ++ }, ++ mic: []byte("invalid-mic"), ++ maxRound: 2, ++ }, "testtarget", ++ ), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ }, ++ gssConfig: &GSSAPIWithMICConfig{ ++ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { ++ if srcName != conn.User() { ++ return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User()) ++ } ++ return nil, nil ++ }, ++ Server: &FakeServer{ ++ exchanges: []*exchange{ ++ { ++ outToken: "server-valid-token-1", ++ expectedToken: "client-valid-token-1", ++ }, ++ }, ++ maxRound: 1, ++ expectedMIC: []byte("valid-mic"), ++ srcName: "testuser@DOMAIN", ++ }, ++ }, ++ serverWantErr: "got MICToken \"invalid-mic\", want \"valid-mic\"", ++ clientWantErr: "ssh: handshake failed: ssh: unable to authenticate", ++ }, ++ } ++ ++ for i, c := range testcases { ++ clientErr, serverErrs := tryAuthBothSides(t, c.config, c.gssConfig) ++ if (c.clientWantErr == "") != (clientErr == nil) { ++ t.Fatalf("client got %v, want %s, case %d", clientErr, c.clientWantErr, i) ++ } ++ if (c.serverWantErr == "") != (len(serverErrs) == 2 && serverErrs[1] == nil || len(serverErrs) == 1) { ++ t.Fatalf("server got err %v, want %s", serverErrs, c.serverWantErr) ++ } ++ if c.clientWantErr != "" { ++ if clientErr != nil && !strings.Contains(clientErr.Error(), c.clientWantErr) { ++ t.Fatalf("client got %v, want %s, case %d", clientErr, c.clientWantErr, i) ++ } ++ } ++ found := false ++ var errStrings []string ++ if c.serverWantErr != "" { ++ for _, err := range serverErrs { ++ found = found || (err != nil && strings.Contains(err.Error(), c.serverWantErr)) ++ errStrings = append(errStrings, err.Error()) ++ } ++ if !found { ++ t.Errorf("server got error %q, want substring %q, case %d", errStrings, c.serverWantErr, i) ++ } ++ } ++ } ++} ++ ++func TestCompatibleAlgoAndSignatures(t *testing.T) { ++ type testcase struct { ++ algo string ++ sigFormat string ++ compatible bool ++ } ++ testcases := []*testcase{ ++ { ++ KeyAlgoRSA, ++ KeyAlgoRSA, ++ true, ++ }, ++ { ++ KeyAlgoRSA, ++ KeyAlgoRSASHA256, ++ true, ++ }, ++ { ++ KeyAlgoRSA, ++ KeyAlgoRSASHA512, ++ true, ++ }, ++ { ++ KeyAlgoRSASHA256, ++ KeyAlgoRSA, ++ true, ++ }, ++ { ++ KeyAlgoRSASHA512, ++ KeyAlgoRSA, ++ true, ++ }, ++ { ++ KeyAlgoRSASHA512, ++ KeyAlgoRSASHA256, ++ true, ++ }, ++ { ++ KeyAlgoRSASHA256, ++ KeyAlgoRSASHA512, ++ true, ++ }, ++ { ++ KeyAlgoRSASHA512, ++ KeyAlgoRSASHA512, ++ true, ++ }, ++ { ++ CertAlgoRSAv01, ++ KeyAlgoRSA, ++ true, ++ }, ++ { ++ CertAlgoRSAv01, ++ KeyAlgoRSASHA256, ++ true, ++ }, ++ { ++ CertAlgoRSAv01, ++ KeyAlgoRSASHA512, ++ true, ++ }, ++ { ++ CertAlgoRSASHA256v01, ++ KeyAlgoRSASHA512, ++ true, ++ }, ++ { ++ CertAlgoRSASHA512v01, ++ KeyAlgoRSASHA512, ++ true, ++ }, ++ { ++ CertAlgoRSASHA512v01, ++ KeyAlgoRSASHA256, ++ true, ++ }, ++ { ++ CertAlgoRSASHA256v01, ++ CertAlgoRSAv01, ++ true, ++ }, ++ { ++ CertAlgoRSAv01, ++ CertAlgoRSASHA512v01, ++ true, ++ }, ++ { ++ KeyAlgoECDSA256, ++ KeyAlgoRSA, ++ false, ++ }, ++ { ++ KeyAlgoECDSA256, ++ KeyAlgoECDSA521, ++ false, ++ }, ++ { ++ KeyAlgoECDSA256, ++ KeyAlgoECDSA256, ++ true, ++ }, ++ { ++ KeyAlgoECDSA256, ++ KeyAlgoED25519, ++ false, ++ }, ++ { ++ KeyAlgoED25519, ++ KeyAlgoED25519, ++ true, ++ }, ++ } ++ ++ for _, c := range testcases { ++ if isAlgoCompatible(c.algo, c.sigFormat) != c.compatible { ++ t.Errorf("algorithm %q, signature format %q, expected compatible to be %t", c.algo, c.sigFormat, c.compatible) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/client_test.go b/ms_mod/golang.org/x/crypto/ssh/client_test.go +new file mode 100644 +index 00000000000000..c114573469431b +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/client_test.go +@@ -0,0 +1,346 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "strings" ++ "testing" ++) ++ ++func TestClientVersion(t *testing.T) { ++ for _, tt := range []struct { ++ name string ++ version string ++ multiLine string ++ wantErr bool ++ }{ ++ { ++ name: "default version", ++ version: packageVersion, ++ }, ++ { ++ name: "custom version", ++ version: "SSH-2.0-CustomClientVersionString", ++ }, ++ { ++ name: "good multi line version", ++ version: packageVersion, ++ multiLine: strings.Repeat("ignored\r\n", 20), ++ }, ++ { ++ name: "bad multi line version", ++ version: packageVersion, ++ multiLine: "bad multi line version", ++ wantErr: true, ++ }, ++ { ++ name: "long multi line version", ++ version: packageVersion, ++ multiLine: strings.Repeat("long multi line version\r\n", 50)[:256], ++ wantErr: true, ++ }, ++ } { ++ t.Run(tt.name, func(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ go func() { ++ if tt.multiLine != "" { ++ c1.Write([]byte(tt.multiLine)) ++ } ++ NewClientConn(c1, "", &ClientConfig{ ++ ClientVersion: tt.version, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ }) ++ c1.Close() ++ }() ++ conf := &ServerConfig{NoClientAuth: true} ++ conf.AddHostKey(testSigners["rsa"]) ++ conn, _, _, err := NewServerConn(c2, conf) ++ if err == nil == tt.wantErr { ++ t.Fatalf("got err %v; wantErr %t", err, tt.wantErr) ++ } ++ if tt.wantErr { ++ // Don't verify the version on an expected error. ++ return ++ } ++ if got := string(conn.ClientVersion()); got != tt.version { ++ t.Fatalf("got %q; want %q", got, tt.version) ++ } ++ }) ++ } ++} ++ ++func TestHostKeyCheck(t *testing.T) { ++ for _, tt := range []struct { ++ name string ++ wantError string ++ key PublicKey ++ }{ ++ {"no callback", "must specify HostKeyCallback", nil}, ++ {"correct key", "", testSigners["rsa"].PublicKey()}, ++ {"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()}, ++ } { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ serverConf := &ServerConfig{ ++ NoClientAuth: true, ++ } ++ serverConf.AddHostKey(testSigners["rsa"]) ++ ++ go NewServerConn(c1, serverConf) ++ clientConf := ClientConfig{ ++ User: "user", ++ } ++ if tt.key != nil { ++ clientConf.HostKeyCallback = FixedHostKey(tt.key) ++ } ++ ++ _, _, _, err = NewClientConn(c2, "", &clientConf) ++ if err != nil { ++ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { ++ t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) ++ } ++ } else if tt.wantError != "" { ++ t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) ++ } ++ } ++} ++ ++func TestVerifyHostKeySignature(t *testing.T) { ++ for _, tt := range []struct { ++ key string ++ signAlgo string ++ verifyAlgo string ++ wantError string ++ }{ ++ {"rsa", KeyAlgoRSA, KeyAlgoRSA, ""}, ++ {"rsa", KeyAlgoRSASHA256, KeyAlgoRSASHA256, ""}, ++ {"rsa", KeyAlgoRSA, KeyAlgoRSASHA512, `ssh: invalid signature algorithm "ssh-rsa", expected "rsa-sha2-512"`}, ++ {"ed25519", KeyAlgoED25519, KeyAlgoED25519, ""}, ++ } { ++ key := testSigners[tt.key].PublicKey() ++ s, ok := testSigners[tt.key].(AlgorithmSigner) ++ if !ok { ++ t.Fatalf("needed an AlgorithmSigner") ++ } ++ sig, err := s.SignWithAlgorithm(rand.Reader, []byte("test"), tt.signAlgo) ++ if err != nil { ++ t.Fatalf("couldn't sign: %q", err) ++ } ++ ++ b := bytes.Buffer{} ++ writeString(&b, []byte(sig.Format)) ++ writeString(&b, sig.Blob) ++ ++ result := kexResult{Signature: b.Bytes(), H: []byte("test")} ++ ++ err = verifyHostKeySignature(key, tt.verifyAlgo, &result) ++ if err != nil { ++ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { ++ t.Errorf("got error %q, expecting %q", err.Error(), tt.wantError) ++ } ++ } else if tt.wantError != "" { ++ t.Errorf("succeeded, but want error string %q", tt.wantError) ++ } ++ } ++} ++ ++func TestBannerCallback(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ serverConf := &ServerConfig{ ++ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { ++ return &Permissions{}, nil ++ }, ++ BannerCallback: func(conn ConnMetadata) string { ++ return "Hello World" ++ }, ++ } ++ serverConf.AddHostKey(testSigners["rsa"]) ++ go NewServerConn(c1, serverConf) ++ ++ var receivedBanner string ++ var bannerCount int ++ clientConf := ClientConfig{ ++ Auth: []AuthMethod{ ++ Password("123"), ++ }, ++ User: "user", ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ BannerCallback: func(message string) error { ++ bannerCount++ ++ receivedBanner = message ++ return nil ++ }, ++ } ++ ++ _, _, _, err = NewClientConn(c2, "", &clientConf) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if bannerCount != 1 { ++ t.Errorf("got %d banners; want 1", bannerCount) ++ } ++ ++ expected := "Hello World" ++ if receivedBanner != expected { ++ t.Fatalf("got %s; want %s", receivedBanner, expected) ++ } ++} ++ ++func TestNewClientConn(t *testing.T) { ++ for _, tt := range []struct { ++ name string ++ user string ++ }{ ++ { ++ name: "good user field for ConnMetadata", ++ user: "testuser", ++ }, ++ { ++ name: "empty user field for ConnMetadata", ++ user: "", ++ }, ++ } { ++ t.Run(tt.name, func(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ serverConf := &ServerConfig{ ++ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { ++ return &Permissions{}, nil ++ }, ++ } ++ serverConf.AddHostKey(testSigners["rsa"]) ++ go NewServerConn(c1, serverConf) ++ ++ clientConf := &ClientConfig{ ++ User: tt.user, ++ Auth: []AuthMethod{ ++ Password("testpw"), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ clientConn, _, _, err := NewClientConn(c2, "", clientConf) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ if userGot := clientConn.User(); userGot != tt.user { ++ t.Errorf("got user %q; want user %q", userGot, tt.user) ++ } ++ }) ++ } ++} ++ ++func TestUnsupportedAlgorithm(t *testing.T) { ++ for _, tt := range []struct { ++ name string ++ config Config ++ wantError string ++ }{ ++ { ++ "unsupported KEX", ++ Config{ ++ KeyExchanges: []string{"unsupported"}, ++ }, ++ "no common algorithm", ++ }, ++ { ++ "unsupported and supported KEXs", ++ Config{ ++ KeyExchanges: []string{"unsupported", kexAlgoCurve25519SHA256}, ++ }, ++ "", ++ }, ++ { ++ "unsupported cipher", ++ Config{ ++ Ciphers: []string{"unsupported"}, ++ }, ++ "no common algorithm", ++ }, ++ { ++ "unsupported and supported ciphers", ++ Config{ ++ Ciphers: []string{"unsupported", chacha20Poly1305ID}, ++ }, ++ "", ++ }, ++ { ++ "unsupported MAC", ++ Config{ ++ MACs: []string{"unsupported"}, ++ // MAC is used for non AAED ciphers. ++ Ciphers: []string{"aes256-ctr"}, ++ }, ++ "no common algorithm", ++ }, ++ { ++ "unsupported and supported MACs", ++ Config{ ++ MACs: []string{"unsupported", "hmac-sha2-256-etm@openssh.com"}, ++ // MAC is used for non AAED ciphers. ++ Ciphers: []string{"aes256-ctr"}, ++ }, ++ "", ++ }, ++ } { ++ t.Run(tt.name, func(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ serverConf := &ServerConfig{ ++ Config: tt.config, ++ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { ++ return &Permissions{}, nil ++ }, ++ } ++ serverConf.AddHostKey(testSigners["rsa"]) ++ go NewServerConn(c1, serverConf) ++ ++ clientConf := &ClientConfig{ ++ User: "testuser", ++ Config: tt.config, ++ Auth: []AuthMethod{ ++ Password("testpw"), ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ _, _, _, err = NewClientConn(c2, "", clientConf) ++ if err != nil { ++ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { ++ t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) ++ } ++ } else if tt.wantError != "" { ++ t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) ++ } ++ }) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/common.go b/ms_mod/golang.org/x/crypto/ssh/common.go +new file mode 100644 +index 00000000000000..b419c761edbc12 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/common.go +@@ -0,0 +1,471 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "crypto" ++ "crypto/rand" ++ "fmt" ++ "io" ++ "math" ++ "strings" ++ "sync" ++ ++ _ "crypto/sha1" ++ _ "crypto/sha256" ++ _ "crypto/sha512" ++) ++ ++// These are string constants in the SSH protocol. ++const ( ++ compressionNone = "none" ++ serviceUserAuth = "ssh-userauth" ++ serviceSSH = "ssh-connection" ++) ++ ++// supportedCiphers lists ciphers we support but might not recommend. ++var supportedCiphers = []string{ ++ "aes128-ctr", "aes192-ctr", "aes256-ctr", ++ "aes128-gcm@openssh.com", gcm256CipherID, ++ chacha20Poly1305ID, ++ "arcfour256", "arcfour128", "arcfour", ++ aes128cbcID, ++ tripledescbcID, ++} ++ ++// preferredCiphers specifies the default preference for ciphers. ++var preferredCiphers = []string{ ++ "aes128-gcm@openssh.com", gcm256CipherID, ++ chacha20Poly1305ID, ++ "aes128-ctr", "aes192-ctr", "aes256-ctr", ++} ++ ++// supportedKexAlgos specifies the supported key-exchange algorithms in ++// preference order. ++var supportedKexAlgos = []string{ ++ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, ++ // P384 and P521 are not constant-time yet, but since we don't ++ // reuse ephemeral keys, using them for ECDH should be OK. ++ kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, ++ kexAlgoDH14SHA256, kexAlgoDH16SHA512, kexAlgoDH14SHA1, ++ kexAlgoDH1SHA1, ++} ++ ++// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden ++// for the server half. ++var serverForbiddenKexAlgos = map[string]struct{}{ ++ kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests ++ kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests ++} ++ ++// preferredKexAlgos specifies the default preference for key-exchange ++// algorithms in preference order. The diffie-hellman-group16-sha512 algorithm ++// is disabled by default because it is a bit slower than the others. ++var preferredKexAlgos = []string{ ++ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, ++ kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, ++ kexAlgoDH14SHA256, kexAlgoDH14SHA1, ++} ++ ++// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods ++// of authenticating servers) in preference order. ++var supportedHostKeyAlgos = []string{ ++ CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, ++ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, ++ CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, ++ ++ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, ++ KeyAlgoRSASHA256, KeyAlgoRSASHA512, ++ KeyAlgoRSA, KeyAlgoDSA, ++ ++ KeyAlgoED25519, ++} ++ ++// supportedMACs specifies a default set of MAC algorithms in preference order. ++// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed ++// because they have reached the end of their useful life. ++var supportedMACs = []string{ ++ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1", "hmac-sha1-96", ++} ++ ++var supportedCompressions = []string{compressionNone} ++ ++// hashFuncs keeps the mapping of supported signature algorithms to their ++// respective hashes needed for signing and verification. ++var hashFuncs = map[string]crypto.Hash{ ++ KeyAlgoRSA: crypto.SHA1, ++ KeyAlgoRSASHA256: crypto.SHA256, ++ KeyAlgoRSASHA512: crypto.SHA512, ++ KeyAlgoDSA: crypto.SHA1, ++ KeyAlgoECDSA256: crypto.SHA256, ++ KeyAlgoECDSA384: crypto.SHA384, ++ KeyAlgoECDSA521: crypto.SHA512, ++ // KeyAlgoED25519 doesn't pre-hash. ++ KeyAlgoSKECDSA256: crypto.SHA256, ++ KeyAlgoSKED25519: crypto.SHA256, ++} ++ ++// algorithmsForKeyFormat returns the supported signature algorithms for a given ++// public key format (PublicKey.Type), in order of preference. See RFC 8332, ++// Section 2. See also the note in sendKexInit on backwards compatibility. ++func algorithmsForKeyFormat(keyFormat string) []string { ++ switch keyFormat { ++ case KeyAlgoRSA: ++ return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA} ++ case CertAlgoRSAv01: ++ return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01} ++ default: ++ return []string{keyFormat} ++ } ++} ++ ++// isRSA returns whether algo is a supported RSA algorithm, including certificate ++// algorithms. ++func isRSA(algo string) bool { ++ algos := algorithmsForKeyFormat(KeyAlgoRSA) ++ return contains(algos, underlyingAlgo(algo)) ++} ++ ++// supportedPubKeyAuthAlgos specifies the supported client public key ++// authentication algorithms. Note that this doesn't include certificate types ++// since those use the underlying algorithm. This list is sent to the client if ++// it supports the server-sig-algs extension. Order is irrelevant. ++var supportedPubKeyAuthAlgos = []string{ ++ KeyAlgoED25519, ++ KeyAlgoSKED25519, KeyAlgoSKECDSA256, ++ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, ++ KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA, ++ KeyAlgoDSA, ++} ++ ++var supportedPubKeyAuthAlgosList = strings.Join(supportedPubKeyAuthAlgos, ",") ++ ++// unexpectedMessageError results when the SSH message that we received didn't ++// match what we wanted. ++func unexpectedMessageError(expected, got uint8) error { ++ return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) ++} ++ ++// parseError results from a malformed SSH message. ++func parseError(tag uint8) error { ++ return fmt.Errorf("ssh: parse error in message type %d", tag) ++} ++ ++func findCommon(what string, client []string, server []string) (common string, err error) { ++ for _, c := range client { ++ for _, s := range server { ++ if c == s { ++ return c, nil ++ } ++ } ++ } ++ return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) ++} ++ ++// directionAlgorithms records algorithm choices in one direction (either read or write) ++type directionAlgorithms struct { ++ Cipher string ++ MAC string ++ Compression string ++} ++ ++// rekeyBytes returns a rekeying intervals in bytes. ++func (a *directionAlgorithms) rekeyBytes() int64 { ++ // According to RFC 4344 block ciphers should rekey after ++ // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is ++ // 128. ++ switch a.Cipher { ++ case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcm128CipherID, gcm256CipherID, aes128cbcID: ++ return 16 * (1 << 32) ++ ++ } ++ ++ // For others, stick with RFC 4253 recommendation to rekey after 1 Gb of data. ++ return 1 << 30 ++} ++ ++var aeadCiphers = map[string]bool{ ++ gcm128CipherID: true, ++ gcm256CipherID: true, ++ chacha20Poly1305ID: true, ++} ++ ++type algorithms struct { ++ kex string ++ hostKey string ++ w directionAlgorithms ++ r directionAlgorithms ++} ++ ++func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { ++ result := &algorithms{} ++ ++ result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) ++ if err != nil { ++ return ++ } ++ ++ result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) ++ if err != nil { ++ return ++ } ++ ++ stoc, ctos := &result.w, &result.r ++ if isClient { ++ ctos, stoc = stoc, ctos ++ } ++ ++ ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) ++ if err != nil { ++ return ++ } ++ ++ stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) ++ if err != nil { ++ return ++ } ++ ++ if !aeadCiphers[ctos.Cipher] { ++ ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) ++ if err != nil { ++ return ++ } ++ } ++ ++ if !aeadCiphers[stoc.Cipher] { ++ stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) ++ if err != nil { ++ return ++ } ++ } ++ ++ ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) ++ if err != nil { ++ return ++ } ++ ++ stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) ++ if err != nil { ++ return ++ } ++ ++ return result, nil ++} ++ ++// If rekeythreshold is too small, we can't make any progress sending ++// stuff. ++const minRekeyThreshold uint64 = 256 ++ ++// Config contains configuration data common to both ServerConfig and ++// ClientConfig. ++type Config struct { ++ // Rand provides the source of entropy for cryptographic ++ // primitives. If Rand is nil, the cryptographic random reader ++ // in package crypto/rand will be used. ++ Rand io.Reader ++ ++ // The maximum number of bytes sent or received after which a ++ // new key is negotiated. It must be at least 256. If ++ // unspecified, a size suitable for the chosen cipher is used. ++ RekeyThreshold uint64 ++ ++ // The allowed key exchanges algorithms. If unspecified then a default set ++ // of algorithms is used. Unsupported values are silently ignored. ++ KeyExchanges []string ++ ++ // The allowed cipher algorithms. If unspecified then a sensible default is ++ // used. Unsupported values are silently ignored. ++ Ciphers []string ++ ++ // The allowed MAC algorithms. If unspecified then a sensible default is ++ // used. Unsupported values are silently ignored. ++ MACs []string ++} ++ ++// SetDefaults sets sensible values for unset fields in config. This is ++// exported for testing: Configs passed to SSH functions are copied and have ++// default values set automatically. ++func (c *Config) SetDefaults() { ++ if c.Rand == nil { ++ c.Rand = rand.Reader ++ } ++ if c.Ciphers == nil { ++ c.Ciphers = preferredCiphers ++ } ++ var ciphers []string ++ for _, c := range c.Ciphers { ++ if cipherModes[c] != nil { ++ // Ignore the cipher if we have no cipherModes definition. ++ ciphers = append(ciphers, c) ++ } ++ } ++ c.Ciphers = ciphers ++ ++ if c.KeyExchanges == nil { ++ c.KeyExchanges = preferredKexAlgos ++ } ++ var kexs []string ++ for _, k := range c.KeyExchanges { ++ if kexAlgoMap[k] != nil { ++ // Ignore the KEX if we have no kexAlgoMap definition. ++ kexs = append(kexs, k) ++ } ++ } ++ c.KeyExchanges = kexs ++ ++ if c.MACs == nil { ++ c.MACs = supportedMACs ++ } ++ var macs []string ++ for _, m := range c.MACs { ++ if macModes[m] != nil { ++ // Ignore the MAC if we have no macModes definition. ++ macs = append(macs, m) ++ } ++ } ++ c.MACs = macs ++ ++ if c.RekeyThreshold == 0 { ++ // cipher specific default ++ } else if c.RekeyThreshold < minRekeyThreshold { ++ c.RekeyThreshold = minRekeyThreshold ++ } else if c.RekeyThreshold >= math.MaxInt64 { ++ // Avoid weirdness if somebody uses -1 as a threshold. ++ c.RekeyThreshold = math.MaxInt64 ++ } ++} ++ ++// buildDataSignedForAuth returns the data that is signed in order to prove ++// possession of a private key. See RFC 4252, section 7. algo is the advertised ++// algorithm, and may be a certificate type. ++func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte { ++ data := struct { ++ Session []byte ++ Type byte ++ User string ++ Service string ++ Method string ++ Sign bool ++ Algo string ++ PubKey []byte ++ }{ ++ sessionID, ++ msgUserAuthRequest, ++ req.User, ++ req.Service, ++ req.Method, ++ true, ++ algo, ++ pubKey, ++ } ++ return Marshal(data) ++} ++ ++func appendU16(buf []byte, n uint16) []byte { ++ return append(buf, byte(n>>8), byte(n)) ++} ++ ++func appendU32(buf []byte, n uint32) []byte { ++ return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) ++} ++ ++func appendU64(buf []byte, n uint64) []byte { ++ return append(buf, ++ byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), ++ byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) ++} ++ ++func appendInt(buf []byte, n int) []byte { ++ return appendU32(buf, uint32(n)) ++} ++ ++func appendString(buf []byte, s string) []byte { ++ buf = appendU32(buf, uint32(len(s))) ++ buf = append(buf, s...) ++ return buf ++} ++ ++func appendBool(buf []byte, b bool) []byte { ++ if b { ++ return append(buf, 1) ++ } ++ return append(buf, 0) ++} ++ ++// newCond is a helper to hide the fact that there is no usable zero ++// value for sync.Cond. ++func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } ++ ++// window represents the buffer available to clients ++// wishing to write to a channel. ++type window struct { ++ *sync.Cond ++ win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 ++ writeWaiters int ++ closed bool ++} ++ ++// add adds win to the amount of window available ++// for consumers. ++func (w *window) add(win uint32) bool { ++ // a zero sized window adjust is a noop. ++ if win == 0 { ++ return true ++ } ++ w.L.Lock() ++ if w.win+win < win { ++ w.L.Unlock() ++ return false ++ } ++ w.win += win ++ // It is unusual that multiple goroutines would be attempting to reserve ++ // window space, but not guaranteed. Use broadcast to notify all waiters ++ // that additional window is available. ++ w.Broadcast() ++ w.L.Unlock() ++ return true ++} ++ ++// close sets the window to closed, so all reservations fail ++// immediately. ++func (w *window) close() { ++ w.L.Lock() ++ w.closed = true ++ w.Broadcast() ++ w.L.Unlock() ++} ++ ++// reserve reserves win from the available window capacity. ++// If no capacity remains, reserve will block. reserve may ++// return less than requested. ++func (w *window) reserve(win uint32) (uint32, error) { ++ var err error ++ w.L.Lock() ++ w.writeWaiters++ ++ w.Broadcast() ++ for w.win == 0 && !w.closed { ++ w.Wait() ++ } ++ w.writeWaiters-- ++ if w.win < win { ++ win = w.win ++ } ++ w.win -= win ++ if w.closed { ++ err = io.EOF ++ } ++ w.L.Unlock() ++ return win, err ++} ++ ++// waitWriterBlocked waits until some goroutine is blocked for further ++// writes. It is used in tests only. ++func (w *window) waitWriterBlocked() { ++ w.Cond.L.Lock() ++ for w.writeWaiters == 0 { ++ w.Cond.Wait() ++ } ++ w.Cond.L.Unlock() ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/common_test.go b/ms_mod/golang.org/x/crypto/ssh/common_test.go +new file mode 100644 +index 00000000000000..a7beee8e884e7e +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/common_test.go +@@ -0,0 +1,176 @@ ++// Copyright 2019 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "reflect" ++ "testing" ++) ++ ++func TestFindAgreedAlgorithms(t *testing.T) { ++ initKex := func(k *kexInitMsg) { ++ if k.KexAlgos == nil { ++ k.KexAlgos = []string{"kex1"} ++ } ++ if k.ServerHostKeyAlgos == nil { ++ k.ServerHostKeyAlgos = []string{"hostkey1"} ++ } ++ if k.CiphersClientServer == nil { ++ k.CiphersClientServer = []string{"cipher1"} ++ ++ } ++ if k.CiphersServerClient == nil { ++ k.CiphersServerClient = []string{"cipher1"} ++ ++ } ++ if k.MACsClientServer == nil { ++ k.MACsClientServer = []string{"mac1"} ++ ++ } ++ if k.MACsServerClient == nil { ++ k.MACsServerClient = []string{"mac1"} ++ ++ } ++ if k.CompressionClientServer == nil { ++ k.CompressionClientServer = []string{"compression1"} ++ ++ } ++ if k.CompressionServerClient == nil { ++ k.CompressionServerClient = []string{"compression1"} ++ ++ } ++ if k.LanguagesClientServer == nil { ++ k.LanguagesClientServer = []string{"language1"} ++ ++ } ++ if k.LanguagesServerClient == nil { ++ k.LanguagesServerClient = []string{"language1"} ++ ++ } ++ } ++ ++ initDirAlgs := func(a *directionAlgorithms) { ++ if a.Cipher == "" { ++ a.Cipher = "cipher1" ++ } ++ if a.MAC == "" { ++ a.MAC = "mac1" ++ } ++ if a.Compression == "" { ++ a.Compression = "compression1" ++ } ++ } ++ ++ initAlgs := func(a *algorithms) { ++ if a.kex == "" { ++ a.kex = "kex1" ++ } ++ if a.hostKey == "" { ++ a.hostKey = "hostkey1" ++ } ++ initDirAlgs(&a.r) ++ initDirAlgs(&a.w) ++ } ++ ++ type testcase struct { ++ name string ++ clientIn, serverIn kexInitMsg ++ wantClient, wantServer algorithms ++ wantErr bool ++ } ++ ++ cases := []testcase{ ++ { ++ name: "standard", ++ }, ++ ++ { ++ name: "no common hostkey", ++ serverIn: kexInitMsg{ ++ ServerHostKeyAlgos: []string{"hostkey2"}, ++ }, ++ wantErr: true, ++ }, ++ ++ { ++ name: "no common kex", ++ serverIn: kexInitMsg{ ++ KexAlgos: []string{"kex2"}, ++ }, ++ wantErr: true, ++ }, ++ ++ { ++ name: "no common cipher", ++ serverIn: kexInitMsg{ ++ CiphersClientServer: []string{"cipher2"}, ++ }, ++ wantErr: true, ++ }, ++ ++ { ++ name: "client decides cipher", ++ serverIn: kexInitMsg{ ++ CiphersClientServer: []string{"cipher1", "cipher2"}, ++ CiphersServerClient: []string{"cipher2", "cipher3"}, ++ }, ++ clientIn: kexInitMsg{ ++ CiphersClientServer: []string{"cipher2", "cipher1"}, ++ CiphersServerClient: []string{"cipher3", "cipher2"}, ++ }, ++ wantClient: algorithms{ ++ r: directionAlgorithms{ ++ Cipher: "cipher3", ++ }, ++ w: directionAlgorithms{ ++ Cipher: "cipher2", ++ }, ++ }, ++ wantServer: algorithms{ ++ w: directionAlgorithms{ ++ Cipher: "cipher3", ++ }, ++ r: directionAlgorithms{ ++ Cipher: "cipher2", ++ }, ++ }, ++ }, ++ ++ // TODO(hanwen): fix and add tests for AEAD ignoring ++ // the MACs field ++ } ++ ++ for i := range cases { ++ initKex(&cases[i].clientIn) ++ initKex(&cases[i].serverIn) ++ initAlgs(&cases[i].wantClient) ++ initAlgs(&cases[i].wantServer) ++ } ++ ++ for _, c := range cases { ++ t.Run(c.name, func(t *testing.T) { ++ serverAlgs, serverErr := findAgreedAlgorithms(false, &c.clientIn, &c.serverIn) ++ clientAlgs, clientErr := findAgreedAlgorithms(true, &c.clientIn, &c.serverIn) ++ ++ serverHasErr := serverErr != nil ++ clientHasErr := clientErr != nil ++ if c.wantErr != serverHasErr || c.wantErr != clientHasErr { ++ t.Fatalf("got client/server error (%v, %v), want hasError %v", ++ clientErr, serverErr, c.wantErr) ++ ++ } ++ if c.wantErr { ++ return ++ } ++ ++ if !reflect.DeepEqual(serverAlgs, &c.wantServer) { ++ t.Errorf("server: got algs %#v, want %#v", serverAlgs, &c.wantServer) ++ } ++ if !reflect.DeepEqual(clientAlgs, &c.wantClient) { ++ t.Errorf("server: got algs %#v, want %#v", clientAlgs, &c.wantClient) ++ } ++ }) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/connection.go b/ms_mod/golang.org/x/crypto/ssh/connection.go +new file mode 100644 +index 00000000000000..8f345ee924e43a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/connection.go +@@ -0,0 +1,143 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "fmt" ++ "net" ++) ++ ++// OpenChannelError is returned if the other side rejects an ++// OpenChannel request. ++type OpenChannelError struct { ++ Reason RejectionReason ++ Message string ++} ++ ++func (e *OpenChannelError) Error() string { ++ return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) ++} ++ ++// ConnMetadata holds metadata for the connection. ++type ConnMetadata interface { ++ // User returns the user ID for this connection. ++ User() string ++ ++ // SessionID returns the session hash, also denoted by H. ++ SessionID() []byte ++ ++ // ClientVersion returns the client's version string as hashed ++ // into the session ID. ++ ClientVersion() []byte ++ ++ // ServerVersion returns the server's version string as hashed ++ // into the session ID. ++ ServerVersion() []byte ++ ++ // RemoteAddr returns the remote address for this connection. ++ RemoteAddr() net.Addr ++ ++ // LocalAddr returns the local address for this connection. ++ LocalAddr() net.Addr ++} ++ ++// Conn represents an SSH connection for both server and client roles. ++// Conn is the basis for implementing an application layer, such ++// as ClientConn, which implements the traditional shell access for ++// clients. ++type Conn interface { ++ ConnMetadata ++ ++ // SendRequest sends a global request, and returns the ++ // reply. If wantReply is true, it returns the response status ++ // and payload. See also RFC 4254, section 4. ++ SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) ++ ++ // OpenChannel tries to open an channel. If the request is ++ // rejected, it returns *OpenChannelError. On success it returns ++ // the SSH Channel and a Go channel for incoming, out-of-band ++ // requests. The Go channel must be serviced, or the ++ // connection will hang. ++ OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) ++ ++ // Close closes the underlying network connection ++ Close() error ++ ++ // Wait blocks until the connection has shut down, and returns the ++ // error causing the shutdown. ++ Wait() error ++ ++ // TODO(hanwen): consider exposing: ++ // RequestKeyChange ++ // Disconnect ++} ++ ++// DiscardRequests consumes and rejects all requests from the ++// passed-in channel. ++func DiscardRequests(in <-chan *Request) { ++ for req := range in { ++ if req.WantReply { ++ req.Reply(false, nil) ++ } ++ } ++} ++ ++// A connection represents an incoming connection. ++type connection struct { ++ transport *handshakeTransport ++ sshConn ++ ++ // The connection protocol. ++ *mux ++} ++ ++func (c *connection) Close() error { ++ return c.sshConn.conn.Close() ++} ++ ++// sshConn provides net.Conn metadata, but disallows direct reads and ++// writes. ++type sshConn struct { ++ conn net.Conn ++ ++ user string ++ sessionID []byte ++ clientVersion []byte ++ serverVersion []byte ++} ++ ++func dup(src []byte) []byte { ++ dst := make([]byte, len(src)) ++ copy(dst, src) ++ return dst ++} ++ ++func (c *sshConn) User() string { ++ return c.user ++} ++ ++func (c *sshConn) RemoteAddr() net.Addr { ++ return c.conn.RemoteAddr() ++} ++ ++func (c *sshConn) Close() error { ++ return c.conn.Close() ++} ++ ++func (c *sshConn) LocalAddr() net.Addr { ++ return c.conn.LocalAddr() ++} ++ ++func (c *sshConn) SessionID() []byte { ++ return dup(c.sessionID) ++} ++ ++func (c *sshConn) ClientVersion() []byte { ++ return dup(c.clientVersion) ++} ++ ++func (c *sshConn) ServerVersion() []byte { ++ return dup(c.serverVersion) ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/doc.go b/ms_mod/golang.org/x/crypto/ssh/doc.go +new file mode 100644 +index 00000000000000..f6bff60dc741ac +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/doc.go +@@ -0,0 +1,22 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++Package ssh implements an SSH client and server. ++ ++SSH is a transport security protocol, an authentication protocol and a ++family of application protocols. The most typical application level ++protocol is a remote shell and this is specifically implemented. However, ++the multiplexed nature of SSH is exposed to users that wish to support ++others. ++ ++References: ++ ++ [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD ++ [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 ++ ++This package does not fall under the stability promise of the Go language itself, ++so its API may be changed when pressing needs arise. ++*/ ++package ssh // import "golang.org/x/crypto/ssh" +diff --git a/ms_mod/golang.org/x/crypto/ssh/example_test.go b/ms_mod/golang.org/x/crypto/ssh/example_test.go +new file mode 100644 +index 00000000000000..bee679603b57a4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/example_test.go +@@ -0,0 +1,320 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh_test ++ ++import ( ++ "bufio" ++ "bytes" ++ "fmt" ++ "log" ++ "net" ++ "net/http" ++ "os" ++ "path/filepath" ++ "strings" ++ ++ "golang.org/x/crypto/ssh" ++ "golang.org/x/crypto/ssh/terminal" ++) ++ ++func ExampleNewServerConn() { ++ // Public key authentication is done by comparing ++ // the public key of a received connection ++ // with the entries in the authorized_keys file. ++ authorizedKeysBytes, err := os.ReadFile("authorized_keys") ++ if err != nil { ++ log.Fatalf("Failed to load authorized_keys, err: %v", err) ++ } ++ ++ authorizedKeysMap := map[string]bool{} ++ for len(authorizedKeysBytes) > 0 { ++ pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes) ++ if err != nil { ++ log.Fatal(err) ++ } ++ ++ authorizedKeysMap[string(pubKey.Marshal())] = true ++ authorizedKeysBytes = rest ++ } ++ ++ // An SSH server is represented by a ServerConfig, which holds ++ // certificate details and handles authentication of ServerConns. ++ config := &ssh.ServerConfig{ ++ // Remove to disable password auth. ++ PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { ++ // Should use constant-time compare (or better, salt+hash) in ++ // a production setting. ++ if c.User() == "testuser" && string(pass) == "tiger" { ++ return nil, nil ++ } ++ return nil, fmt.Errorf("password rejected for %q", c.User()) ++ }, ++ ++ // Remove to disable public key auth. ++ PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { ++ if authorizedKeysMap[string(pubKey.Marshal())] { ++ return &ssh.Permissions{ ++ // Record the public key used for authentication. ++ Extensions: map[string]string{ ++ "pubkey-fp": ssh.FingerprintSHA256(pubKey), ++ }, ++ }, nil ++ } ++ return nil, fmt.Errorf("unknown public key for %q", c.User()) ++ }, ++ } ++ ++ privateBytes, err := os.ReadFile("id_rsa") ++ if err != nil { ++ log.Fatal("Failed to load private key: ", err) ++ } ++ ++ private, err := ssh.ParsePrivateKey(privateBytes) ++ if err != nil { ++ log.Fatal("Failed to parse private key: ", err) ++ } ++ ++ config.AddHostKey(private) ++ ++ // Once a ServerConfig has been configured, connections can be ++ // accepted. ++ listener, err := net.Listen("tcp", "0.0.0.0:2022") ++ if err != nil { ++ log.Fatal("failed to listen for connection: ", err) ++ } ++ nConn, err := listener.Accept() ++ if err != nil { ++ log.Fatal("failed to accept incoming connection: ", err) ++ } ++ ++ // Before use, a handshake must be performed on the incoming ++ // net.Conn. ++ conn, chans, reqs, err := ssh.NewServerConn(nConn, config) ++ if err != nil { ++ log.Fatal("failed to handshake: ", err) ++ } ++ log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"]) ++ ++ // The incoming Request channel must be serviced. ++ go ssh.DiscardRequests(reqs) ++ ++ // Service the incoming Channel channel. ++ for newChannel := range chans { ++ // Channels have a type, depending on the application level ++ // protocol intended. In the case of a shell, the type is ++ // "session" and ServerShell may be used to present a simple ++ // terminal interface. ++ if newChannel.ChannelType() != "session" { ++ newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") ++ continue ++ } ++ channel, requests, err := newChannel.Accept() ++ if err != nil { ++ log.Fatalf("Could not accept channel: %v", err) ++ } ++ ++ // Sessions have out-of-band requests such as "shell", ++ // "pty-req" and "env". Here we handle only the ++ // "shell" request. ++ go func(in <-chan *ssh.Request) { ++ for req := range in { ++ req.Reply(req.Type == "shell", nil) ++ } ++ }(requests) ++ ++ term := terminal.NewTerminal(channel, "> ") ++ ++ go func() { ++ defer channel.Close() ++ for { ++ line, err := term.ReadLine() ++ if err != nil { ++ break ++ } ++ fmt.Println(line) ++ } ++ }() ++ } ++} ++ ++func ExampleClientConfig_HostKeyCallback() { ++ // Every client must provide a host key check. Here is a ++ // simple-minded parse of OpenSSH's known_hosts file ++ host := "hostname" ++ file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts")) ++ if err != nil { ++ log.Fatal(err) ++ } ++ defer file.Close() ++ ++ scanner := bufio.NewScanner(file) ++ var hostKey ssh.PublicKey ++ for scanner.Scan() { ++ fields := strings.Split(scanner.Text(), " ") ++ if len(fields) != 3 { ++ continue ++ } ++ if strings.Contains(fields[0], host) { ++ var err error ++ hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes()) ++ if err != nil { ++ log.Fatalf("error parsing %q: %v", fields[2], err) ++ } ++ break ++ } ++ } ++ ++ if hostKey == nil { ++ log.Fatalf("no hostkey for %s", host) ++ } ++ ++ config := ssh.ClientConfig{ ++ User: os.Getenv("USER"), ++ HostKeyCallback: ssh.FixedHostKey(hostKey), ++ } ++ ++ _, err = ssh.Dial("tcp", host+":22", &config) ++ log.Println(err) ++} ++ ++func ExampleDial() { ++ var hostKey ssh.PublicKey ++ // An SSH client is represented with a ClientConn. ++ // ++ // To authenticate with the remote server you must pass at least one ++ // implementation of AuthMethod via the Auth field in ClientConfig, ++ // and provide a HostKeyCallback. ++ config := &ssh.ClientConfig{ ++ User: "username", ++ Auth: []ssh.AuthMethod{ ++ ssh.Password("yourpassword"), ++ }, ++ HostKeyCallback: ssh.FixedHostKey(hostKey), ++ } ++ client, err := ssh.Dial("tcp", "yourserver.com:22", config) ++ if err != nil { ++ log.Fatal("Failed to dial: ", err) ++ } ++ defer client.Close() ++ ++ // Each ClientConn can support multiple interactive sessions, ++ // represented by a Session. ++ session, err := client.NewSession() ++ if err != nil { ++ log.Fatal("Failed to create session: ", err) ++ } ++ defer session.Close() ++ ++ // Once a Session is created, you can execute a single command on ++ // the remote side using the Run method. ++ var b bytes.Buffer ++ session.Stdout = &b ++ if err := session.Run("/usr/bin/whoami"); err != nil { ++ log.Fatal("Failed to run: " + err.Error()) ++ } ++ fmt.Println(b.String()) ++} ++ ++func ExamplePublicKeys() { ++ var hostKey ssh.PublicKey ++ // A public key may be used to authenticate against the remote ++ // server by using an unencrypted PEM-encoded private key file. ++ // ++ // If you have an encrypted private key, the crypto/x509 package ++ // can be used to decrypt it. ++ key, err := os.ReadFile("/home/user/.ssh/id_rsa") ++ if err != nil { ++ log.Fatalf("unable to read private key: %v", err) ++ } ++ ++ // Create the Signer for this private key. ++ signer, err := ssh.ParsePrivateKey(key) ++ if err != nil { ++ log.Fatalf("unable to parse private key: %v", err) ++ } ++ ++ config := &ssh.ClientConfig{ ++ User: "user", ++ Auth: []ssh.AuthMethod{ ++ // Use the PublicKeys method for remote authentication. ++ ssh.PublicKeys(signer), ++ }, ++ HostKeyCallback: ssh.FixedHostKey(hostKey), ++ } ++ ++ // Connect to the remote server and perform the SSH handshake. ++ client, err := ssh.Dial("tcp", "host.com:22", config) ++ if err != nil { ++ log.Fatalf("unable to connect: %v", err) ++ } ++ defer client.Close() ++} ++ ++func ExampleClient_Listen() { ++ var hostKey ssh.PublicKey ++ config := &ssh.ClientConfig{ ++ User: "username", ++ Auth: []ssh.AuthMethod{ ++ ssh.Password("password"), ++ }, ++ HostKeyCallback: ssh.FixedHostKey(hostKey), ++ } ++ // Dial your ssh server. ++ conn, err := ssh.Dial("tcp", "localhost:22", config) ++ if err != nil { ++ log.Fatal("unable to connect: ", err) ++ } ++ defer conn.Close() ++ ++ // Request the remote side to open port 8080 on all interfaces. ++ l, err := conn.Listen("tcp", "0.0.0.0:8080") ++ if err != nil { ++ log.Fatal("unable to register tcp forward: ", err) ++ } ++ defer l.Close() ++ ++ // Serve HTTP with your SSH server acting as a reverse proxy. ++ http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { ++ fmt.Fprintf(resp, "Hello world!\n") ++ })) ++} ++ ++func ExampleSession_RequestPty() { ++ var hostKey ssh.PublicKey ++ // Create client config ++ config := &ssh.ClientConfig{ ++ User: "username", ++ Auth: []ssh.AuthMethod{ ++ ssh.Password("password"), ++ }, ++ HostKeyCallback: ssh.FixedHostKey(hostKey), ++ } ++ // Connect to ssh server ++ conn, err := ssh.Dial("tcp", "localhost:22", config) ++ if err != nil { ++ log.Fatal("unable to connect: ", err) ++ } ++ defer conn.Close() ++ // Create a session ++ session, err := conn.NewSession() ++ if err != nil { ++ log.Fatal("unable to create session: ", err) ++ } ++ defer session.Close() ++ // Set up terminal modes ++ modes := ssh.TerminalModes{ ++ ssh.ECHO: 0, // disable echoing ++ ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ++ ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud ++ } ++ // Request pseudo terminal ++ if err := session.RequestPty("xterm", 40, 80, modes); err != nil { ++ log.Fatal("request for pseudo terminal failed: ", err) ++ } ++ // Start remote shell ++ if err := session.Shell(); err != nil { ++ log.Fatal("failed to start shell: ", err) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/handshake.go b/ms_mod/golang.org/x/crypto/ssh/handshake.go +new file mode 100644 +index 00000000000000..07a1843e0a52f8 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/handshake.go +@@ -0,0 +1,735 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "crypto/rand" ++ "errors" ++ "fmt" ++ "io" ++ "log" ++ "net" ++ "sync" ++) ++ ++// debugHandshake, if set, prints messages sent and received. Key ++// exchange messages are printed as if DH were used, so the debug ++// messages are wrong when using ECDH. ++const debugHandshake = false ++ ++// chanSize sets the amount of buffering SSH connections. This is ++// primarily for testing: setting chanSize=0 uncovers deadlocks more ++// quickly. ++const chanSize = 16 ++ ++// keyingTransport is a packet based transport that supports key ++// changes. It need not be thread-safe. It should pass through ++// msgNewKeys in both directions. ++type keyingTransport interface { ++ packetConn ++ ++ // prepareKeyChange sets up a key change. The key change for a ++ // direction will be effected if a msgNewKeys message is sent ++ // or received. ++ prepareKeyChange(*algorithms, *kexResult) error ++} ++ ++// handshakeTransport implements rekeying on top of a keyingTransport ++// and offers a thread-safe writePacket() interface. ++type handshakeTransport struct { ++ conn keyingTransport ++ config *Config ++ ++ serverVersion []byte ++ clientVersion []byte ++ ++ // hostKeys is non-empty if we are the server. In that case, ++ // it contains all host keys that can be used to sign the ++ // connection. ++ hostKeys []Signer ++ ++ // hostKeyAlgorithms is non-empty if we are the client. In that case, ++ // we accept these key types from the server as host key. ++ hostKeyAlgorithms []string ++ ++ // On read error, incoming is closed, and readError is set. ++ incoming chan []byte ++ readError error ++ ++ mu sync.Mutex ++ writeError error ++ sentInitPacket []byte ++ sentInitMsg *kexInitMsg ++ pendingPackets [][]byte // Used when a key exchange is in progress. ++ writePacketsLeft uint32 ++ writeBytesLeft int64 ++ ++ // If the read loop wants to schedule a kex, it pings this ++ // channel, and the write loop will send out a kex ++ // message. ++ requestKex chan struct{} ++ ++ // If the other side requests or confirms a kex, its kexInit ++ // packet is sent here for the write loop to find it. ++ startKex chan *pendingKex ++ kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits ++ ++ // data for host key checking ++ hostKeyCallback HostKeyCallback ++ dialAddress string ++ remoteAddr net.Addr ++ ++ // bannerCallback is non-empty if we are the client and it has been set in ++ // ClientConfig. In that case it is called during the user authentication ++ // dance to handle a custom server's message. ++ bannerCallback BannerCallback ++ ++ // Algorithms agreed in the last key exchange. ++ algorithms *algorithms ++ ++ // Counters exclusively owned by readLoop. ++ readPacketsLeft uint32 ++ readBytesLeft int64 ++ ++ // The session ID or nil if first kex did not complete yet. ++ sessionID []byte ++} ++ ++type pendingKex struct { ++ otherInit []byte ++ done chan error ++} ++ ++func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport { ++ t := &handshakeTransport{ ++ conn: conn, ++ serverVersion: serverVersion, ++ clientVersion: clientVersion, ++ incoming: make(chan []byte, chanSize), ++ requestKex: make(chan struct{}, 1), ++ startKex: make(chan *pendingKex), ++ kexLoopDone: make(chan struct{}), ++ ++ config: config, ++ } ++ t.resetReadThresholds() ++ t.resetWriteThresholds() ++ ++ // We always start with a mandatory key exchange. ++ t.requestKex <- struct{}{} ++ return t ++} ++ ++func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport { ++ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) ++ t.dialAddress = dialAddr ++ t.remoteAddr = addr ++ t.hostKeyCallback = config.HostKeyCallback ++ t.bannerCallback = config.BannerCallback ++ if config.HostKeyAlgorithms != nil { ++ t.hostKeyAlgorithms = config.HostKeyAlgorithms ++ } else { ++ t.hostKeyAlgorithms = supportedHostKeyAlgos ++ } ++ go t.readLoop() ++ go t.kexLoop() ++ return t ++} ++ ++func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { ++ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) ++ t.hostKeys = config.hostKeys ++ go t.readLoop() ++ go t.kexLoop() ++ return t ++} ++ ++func (t *handshakeTransport) getSessionID() []byte { ++ return t.sessionID ++} ++ ++// waitSession waits for the session to be established. This should be ++// the first thing to call after instantiating handshakeTransport. ++func (t *handshakeTransport) waitSession() error { ++ p, err := t.readPacket() ++ if err != nil { ++ return err ++ } ++ if p[0] != msgNewKeys { ++ return fmt.Errorf("ssh: first packet should be msgNewKeys") ++ } ++ ++ return nil ++} ++ ++func (t *handshakeTransport) id() string { ++ if len(t.hostKeys) > 0 { ++ return "server" ++ } ++ return "client" ++} ++ ++func (t *handshakeTransport) printPacket(p []byte, write bool) { ++ action := "got" ++ if write { ++ action = "sent" ++ } ++ ++ if p[0] == msgChannelData || p[0] == msgChannelExtendedData { ++ log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p)) ++ } else { ++ msg, err := decode(p) ++ log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err) ++ } ++} ++ ++func (t *handshakeTransport) readPacket() ([]byte, error) { ++ p, ok := <-t.incoming ++ if !ok { ++ return nil, t.readError ++ } ++ return p, nil ++} ++ ++func (t *handshakeTransport) readLoop() { ++ first := true ++ for { ++ p, err := t.readOnePacket(first) ++ first = false ++ if err != nil { ++ t.readError = err ++ close(t.incoming) ++ break ++ } ++ if p[0] == msgIgnore || p[0] == msgDebug { ++ continue ++ } ++ t.incoming <- p ++ } ++ ++ // Stop writers too. ++ t.recordWriteError(t.readError) ++ ++ // Unblock the writer should it wait for this. ++ close(t.startKex) ++ ++ // Don't close t.requestKex; it's also written to from writePacket. ++} ++ ++func (t *handshakeTransport) pushPacket(p []byte) error { ++ if debugHandshake { ++ t.printPacket(p, true) ++ } ++ return t.conn.writePacket(p) ++} ++ ++func (t *handshakeTransport) getWriteError() error { ++ t.mu.Lock() ++ defer t.mu.Unlock() ++ return t.writeError ++} ++ ++func (t *handshakeTransport) recordWriteError(err error) { ++ t.mu.Lock() ++ defer t.mu.Unlock() ++ if t.writeError == nil && err != nil { ++ t.writeError = err ++ } ++} ++ ++func (t *handshakeTransport) requestKeyExchange() { ++ select { ++ case t.requestKex <- struct{}{}: ++ default: ++ // something already requested a kex, so do nothing. ++ } ++} ++ ++func (t *handshakeTransport) resetWriteThresholds() { ++ t.writePacketsLeft = packetRekeyThreshold ++ if t.config.RekeyThreshold > 0 { ++ t.writeBytesLeft = int64(t.config.RekeyThreshold) ++ } else if t.algorithms != nil { ++ t.writeBytesLeft = t.algorithms.w.rekeyBytes() ++ } else { ++ t.writeBytesLeft = 1 << 30 ++ } ++} ++ ++func (t *handshakeTransport) kexLoop() { ++ ++write: ++ for t.getWriteError() == nil { ++ var request *pendingKex ++ var sent bool ++ ++ for request == nil || !sent { ++ var ok bool ++ select { ++ case request, ok = <-t.startKex: ++ if !ok { ++ break write ++ } ++ case <-t.requestKex: ++ break ++ } ++ ++ if !sent { ++ if err := t.sendKexInit(); err != nil { ++ t.recordWriteError(err) ++ break ++ } ++ sent = true ++ } ++ } ++ ++ if err := t.getWriteError(); err != nil { ++ if request != nil { ++ request.done <- err ++ } ++ break ++ } ++ ++ // We're not servicing t.requestKex, but that is OK: ++ // we never block on sending to t.requestKex. ++ ++ // We're not servicing t.startKex, but the remote end ++ // has just sent us a kexInitMsg, so it can't send ++ // another key change request, until we close the done ++ // channel on the pendingKex request. ++ ++ err := t.enterKeyExchange(request.otherInit) ++ ++ t.mu.Lock() ++ t.writeError = err ++ t.sentInitPacket = nil ++ t.sentInitMsg = nil ++ ++ t.resetWriteThresholds() ++ ++ // we have completed the key exchange. Since the ++ // reader is still blocked, it is safe to clear out ++ // the requestKex channel. This avoids the situation ++ // where: 1) we consumed our own request for the ++ // initial kex, and 2) the kex from the remote side ++ // caused another send on the requestKex channel, ++ clear: ++ for { ++ select { ++ case <-t.requestKex: ++ // ++ default: ++ break clear ++ } ++ } ++ ++ request.done <- t.writeError ++ ++ // kex finished. Push packets that we received while ++ // the kex was in progress. Don't look at t.startKex ++ // and don't increment writtenSinceKex: if we trigger ++ // another kex while we are still busy with the last ++ // one, things will become very confusing. ++ for _, p := range t.pendingPackets { ++ t.writeError = t.pushPacket(p) ++ if t.writeError != nil { ++ break ++ } ++ } ++ t.pendingPackets = t.pendingPackets[:0] ++ t.mu.Unlock() ++ } ++ ++ // Unblock reader. ++ t.conn.Close() ++ ++ // drain startKex channel. We don't service t.requestKex ++ // because nobody does blocking sends there. ++ for request := range t.startKex { ++ request.done <- t.getWriteError() ++ } ++ ++ // Mark that the loop is done so that Close can return. ++ close(t.kexLoopDone) ++} ++ ++// The protocol uses uint32 for packet counters, so we can't let them ++// reach 1<<32. We will actually read and write more packets than ++// this, though: the other side may send more packets, and after we ++// hit this limit on writing we will send a few more packets for the ++// key exchange itself. ++const packetRekeyThreshold = (1 << 31) ++ ++func (t *handshakeTransport) resetReadThresholds() { ++ t.readPacketsLeft = packetRekeyThreshold ++ if t.config.RekeyThreshold > 0 { ++ t.readBytesLeft = int64(t.config.RekeyThreshold) ++ } else if t.algorithms != nil { ++ t.readBytesLeft = t.algorithms.r.rekeyBytes() ++ } else { ++ t.readBytesLeft = 1 << 30 ++ } ++} ++ ++func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) { ++ p, err := t.conn.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ if t.readPacketsLeft > 0 { ++ t.readPacketsLeft-- ++ } else { ++ t.requestKeyExchange() ++ } ++ ++ if t.readBytesLeft > 0 { ++ t.readBytesLeft -= int64(len(p)) ++ } else { ++ t.requestKeyExchange() ++ } ++ ++ if debugHandshake { ++ t.printPacket(p, false) ++ } ++ ++ if first && p[0] != msgKexInit { ++ return nil, fmt.Errorf("ssh: first packet should be msgKexInit") ++ } ++ ++ if p[0] != msgKexInit { ++ return p, nil ++ } ++ ++ firstKex := t.sessionID == nil ++ ++ kex := pendingKex{ ++ done: make(chan error, 1), ++ otherInit: p, ++ } ++ t.startKex <- &kex ++ err = <-kex.done ++ ++ if debugHandshake { ++ log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err) ++ } ++ ++ if err != nil { ++ return nil, err ++ } ++ ++ t.resetReadThresholds() ++ ++ // By default, a key exchange is hidden from higher layers by ++ // translating it into msgIgnore. ++ successPacket := []byte{msgIgnore} ++ if firstKex { ++ // sendKexInit() for the first kex waits for ++ // msgNewKeys so the authentication process is ++ // guaranteed to happen over an encrypted transport. ++ successPacket = []byte{msgNewKeys} ++ } ++ ++ return successPacket, nil ++} ++ ++// sendKexInit sends a key change message. ++func (t *handshakeTransport) sendKexInit() error { ++ t.mu.Lock() ++ defer t.mu.Unlock() ++ if t.sentInitMsg != nil { ++ // kexInits may be sent either in response to the other side, ++ // or because our side wants to initiate a key change, so we ++ // may have already sent a kexInit. In that case, don't send a ++ // second kexInit. ++ return nil ++ } ++ ++ msg := &kexInitMsg{ ++ KexAlgos: t.config.KeyExchanges, ++ CiphersClientServer: t.config.Ciphers, ++ CiphersServerClient: t.config.Ciphers, ++ MACsClientServer: t.config.MACs, ++ MACsServerClient: t.config.MACs, ++ CompressionClientServer: supportedCompressions, ++ CompressionServerClient: supportedCompressions, ++ } ++ io.ReadFull(rand.Reader, msg.Cookie[:]) ++ ++ isServer := len(t.hostKeys) > 0 ++ if isServer { ++ for _, k := range t.hostKeys { ++ // If k is an AlgorithmSigner, presume it supports all signature algorithms ++ // associated with the key format. (Ideally AlgorithmSigner would have a ++ // method to advertise supported algorithms, but it doesn't. This means that ++ // adding support for a new algorithm is a breaking change, as we will ++ // immediately negotiate it even if existing implementations don't support ++ // it. If that ever happens, we'll have to figure something out.) ++ // If k is not an AlgorithmSigner, we can only assume it only supports the ++ // algorithms that matches the key format. (This means that Sign can't pick ++ // a different default.) ++ keyFormat := k.PublicKey().Type() ++ if _, ok := k.(AlgorithmSigner); ok { ++ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...) ++ } else { ++ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat) ++ } ++ } ++ } else { ++ msg.ServerHostKeyAlgos = t.hostKeyAlgorithms ++ ++ // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what ++ // algorithms the server supports for public key authentication. See RFC ++ // 8308, Section 2.1. ++ if firstKeyExchange := t.sessionID == nil; firstKeyExchange { ++ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1) ++ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) ++ msg.KexAlgos = append(msg.KexAlgos, "ext-info-c") ++ } ++ } ++ ++ packet := Marshal(msg) ++ ++ // writePacket destroys the contents, so save a copy. ++ packetCopy := make([]byte, len(packet)) ++ copy(packetCopy, packet) ++ ++ if err := t.pushPacket(packetCopy); err != nil { ++ return err ++ } ++ ++ t.sentInitMsg = msg ++ t.sentInitPacket = packet ++ ++ return nil ++} ++ ++func (t *handshakeTransport) writePacket(p []byte) error { ++ switch p[0] { ++ case msgKexInit: ++ return errors.New("ssh: only handshakeTransport can send kexInit") ++ case msgNewKeys: ++ return errors.New("ssh: only handshakeTransport can send newKeys") ++ } ++ ++ t.mu.Lock() ++ defer t.mu.Unlock() ++ if t.writeError != nil { ++ return t.writeError ++ } ++ ++ if t.sentInitMsg != nil { ++ // Copy the packet so the writer can reuse the buffer. ++ cp := make([]byte, len(p)) ++ copy(cp, p) ++ t.pendingPackets = append(t.pendingPackets, cp) ++ return nil ++ } ++ ++ if t.writeBytesLeft > 0 { ++ t.writeBytesLeft -= int64(len(p)) ++ } else { ++ t.requestKeyExchange() ++ } ++ ++ if t.writePacketsLeft > 0 { ++ t.writePacketsLeft-- ++ } else { ++ t.requestKeyExchange() ++ } ++ ++ if err := t.pushPacket(p); err != nil { ++ t.writeError = err ++ } ++ ++ return nil ++} ++ ++func (t *handshakeTransport) Close() error { ++ // Close the connection. This should cause the readLoop goroutine to wake up ++ // and close t.startKex, which will shut down kexLoop if running. ++ err := t.conn.Close() ++ ++ // Wait for the kexLoop goroutine to complete. ++ // At that point we know that the readLoop goroutine is complete too, ++ // because kexLoop itself waits for readLoop to close the startKex channel. ++ <-t.kexLoopDone ++ ++ return err ++} ++ ++func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { ++ if debugHandshake { ++ log.Printf("%s entered key exchange", t.id()) ++ } ++ ++ otherInit := &kexInitMsg{} ++ if err := Unmarshal(otherInitPacket, otherInit); err != nil { ++ return err ++ } ++ ++ magics := handshakeMagics{ ++ clientVersion: t.clientVersion, ++ serverVersion: t.serverVersion, ++ clientKexInit: otherInitPacket, ++ serverKexInit: t.sentInitPacket, ++ } ++ ++ clientInit := otherInit ++ serverInit := t.sentInitMsg ++ isClient := len(t.hostKeys) == 0 ++ if isClient { ++ clientInit, serverInit = serverInit, clientInit ++ ++ magics.clientKexInit = t.sentInitPacket ++ magics.serverKexInit = otherInitPacket ++ } ++ ++ var err error ++ t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit) ++ if err != nil { ++ return err ++ } ++ ++ // We don't send FirstKexFollows, but we handle receiving it. ++ // ++ // RFC 4253 section 7 defines the kex and the agreement method for ++ // first_kex_packet_follows. It states that the guessed packet ++ // should be ignored if the "kex algorithm and/or the host ++ // key algorithm is guessed wrong (server and client have ++ // different preferred algorithm), or if any of the other ++ // algorithms cannot be agreed upon". The other algorithms have ++ // already been checked above so the kex algorithm and host key ++ // algorithm are checked here. ++ if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) { ++ // other side sent a kex message for the wrong algorithm, ++ // which we have to ignore. ++ if _, err := t.conn.readPacket(); err != nil { ++ return err ++ } ++ } ++ ++ kex, ok := kexAlgoMap[t.algorithms.kex] ++ if !ok { ++ return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex) ++ } ++ ++ var result *kexResult ++ if len(t.hostKeys) > 0 { ++ result, err = t.server(kex, &magics) ++ } else { ++ result, err = t.client(kex, &magics) ++ } ++ ++ if err != nil { ++ return err ++ } ++ ++ firstKeyExchange := t.sessionID == nil ++ if firstKeyExchange { ++ t.sessionID = result.H ++ } ++ result.SessionID = t.sessionID ++ ++ if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil { ++ return err ++ } ++ if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { ++ return err ++ } ++ ++ // On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO ++ // message with the server-sig-algs extension if the client supports it. See ++ // RFC 8308, Sections 2.4 and 3.1. ++ if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") { ++ extInfo := &extInfoMsg{ ++ NumExtensions: 1, ++ Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)), ++ } ++ extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs")) ++ extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...) ++ extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList)) ++ extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...) ++ if err := t.conn.writePacket(Marshal(extInfo)); err != nil { ++ return err ++ } ++ } ++ ++ if packet, err := t.conn.readPacket(); err != nil { ++ return err ++ } else if packet[0] != msgNewKeys { ++ return unexpectedMessageError(msgNewKeys, packet[0]) ++ } ++ ++ return nil ++} ++ ++// algorithmSignerWrapper is an AlgorithmSigner that only supports the default ++// key format algorithm. ++// ++// This is technically a violation of the AlgorithmSigner interface, but it ++// should be unreachable given where we use this. Anyway, at least it returns an ++// error instead of panicing or producing an incorrect signature. ++type algorithmSignerWrapper struct { ++ Signer ++} ++ ++func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { ++ if algorithm != underlyingAlgo(a.PublicKey().Type()) { ++ return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm") ++ } ++ return a.Sign(rand, data) ++} ++ ++func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner { ++ for _, k := range hostKeys { ++ if algo == k.PublicKey().Type() { ++ return algorithmSignerWrapper{k} ++ } ++ k, ok := k.(AlgorithmSigner) ++ if !ok { ++ continue ++ } ++ for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) { ++ if algo == a { ++ return k ++ } ++ } ++ } ++ return nil ++} ++ ++func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { ++ hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey) ++ if hostKey == nil { ++ return nil, errors.New("ssh: internal error: negotiated unsupported signature type") ++ } ++ ++ r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey) ++ return r, err ++} ++ ++func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { ++ result, err := kex.Client(t.conn, t.config.Rand, magics) ++ if err != nil { ++ return nil, err ++ } ++ ++ hostKey, err := ParsePublicKey(result.HostKey) ++ if err != nil { ++ return nil, err ++ } ++ ++ if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil { ++ return nil, err ++ } ++ ++ err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey) ++ if err != nil { ++ return nil, err ++ } ++ ++ return result, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/handshake_test.go b/ms_mod/golang.org/x/crypto/ssh/handshake_test.go +new file mode 100644 +index 00000000000000..879143a6b5f2e9 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/handshake_test.go +@@ -0,0 +1,622 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "errors" ++ "fmt" ++ "io" ++ "net" ++ "reflect" ++ "runtime" ++ "strings" ++ "sync" ++ "testing" ++) ++ ++type testChecker struct { ++ calls []string ++} ++ ++func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { ++ if dialAddr == "bad" { ++ return fmt.Errorf("dialAddr is bad") ++ } ++ ++ if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil { ++ return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr) ++ } ++ ++ t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal())) ++ ++ return nil ++} ++ ++// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and ++// therefore is buffered (net.Pipe deadlocks if both sides start with ++// a write.) ++func netPipe() (net.Conn, net.Conn, error) { ++ listener, err := net.Listen("tcp", "127.0.0.1:0") ++ if err != nil { ++ listener, err = net.Listen("tcp", "[::1]:0") ++ if err != nil { ++ return nil, nil, err ++ } ++ } ++ defer listener.Close() ++ c1, err := net.Dial("tcp", listener.Addr().String()) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ c2, err := listener.Accept() ++ if err != nil { ++ c1.Close() ++ return nil, nil, err ++ } ++ ++ return c1, c2, nil ++} ++ ++// noiseTransport inserts ignore messages to check that the read loop ++// and the key exchange filters out these messages. ++type noiseTransport struct { ++ keyingTransport ++} ++ ++func (t *noiseTransport) writePacket(p []byte) error { ++ ignore := []byte{msgIgnore} ++ if err := t.keyingTransport.writePacket(ignore); err != nil { ++ return err ++ } ++ debug := []byte{msgDebug, 1, 2, 3} ++ if err := t.keyingTransport.writePacket(debug); err != nil { ++ return err ++ } ++ ++ return t.keyingTransport.writePacket(p) ++} ++ ++func addNoiseTransport(t keyingTransport) keyingTransport { ++ return &noiseTransport{t} ++} ++ ++// handshakePair creates two handshakeTransports connected with each ++// other. If the noise argument is true, both transports will try to ++// confuse the other side by sending ignore and debug messages. ++func handshakePair(clientConf *ClientConfig, addr string, noise bool) (client *handshakeTransport, server *handshakeTransport, err error) { ++ a, b, err := netPipe() ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ var trC, trS keyingTransport ++ ++ trC = newTransport(a, rand.Reader, true) ++ trS = newTransport(b, rand.Reader, false) ++ if noise { ++ trC = addNoiseTransport(trC) ++ trS = addNoiseTransport(trS) ++ } ++ clientConf.SetDefaults() ++ ++ v := []byte("version") ++ client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr()) ++ ++ serverConf := &ServerConfig{} ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ serverConf.AddHostKey(testSigners["rsa"]) ++ serverConf.SetDefaults() ++ server = newServerTransport(trS, v, v, serverConf) ++ ++ if err := server.waitSession(); err != nil { ++ return nil, nil, fmt.Errorf("server.waitSession: %v", err) ++ } ++ if err := client.waitSession(); err != nil { ++ return nil, nil, fmt.Errorf("client.waitSession: %v", err) ++ } ++ ++ return client, server, nil ++} ++ ++func TestHandshakeBasic(t *testing.T) { ++ if runtime.GOOS == "plan9" { ++ t.Skip("see golang.org/issue/7237") ++ } ++ ++ checker := &syncChecker{ ++ waitCall: make(chan int, 10), ++ called: make(chan int, 10), ++ } ++ ++ checker.waitCall <- 1 ++ trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) ++ if err != nil { ++ t.Fatalf("handshakePair: %v", err) ++ } ++ ++ defer trC.Close() ++ defer trS.Close() ++ ++ // Let first kex complete normally. ++ <-checker.called ++ ++ clientDone := make(chan int, 0) ++ gotHalf := make(chan int, 0) ++ const N = 20 ++ errorCh := make(chan error, 1) ++ ++ go func() { ++ defer close(clientDone) ++ // Client writes a bunch of stuff, and does a key ++ // change in the middle. This should not confuse the ++ // handshake in progress. We do this twice, so we test ++ // that the packet buffer is reset correctly. ++ for i := 0; i < N; i++ { ++ p := []byte{msgRequestSuccess, byte(i)} ++ if err := trC.writePacket(p); err != nil { ++ errorCh <- err ++ trC.Close() ++ return ++ } ++ if (i % 10) == 5 { ++ <-gotHalf ++ // halfway through, we request a key change. ++ trC.requestKeyExchange() ++ ++ // Wait until we can be sure the key ++ // change has really started before we ++ // write more. ++ <-checker.called ++ } ++ if (i % 10) == 7 { ++ // write some packets until the kex ++ // completes, to test buffering of ++ // packets. ++ checker.waitCall <- 1 ++ } ++ } ++ errorCh <- nil ++ }() ++ ++ // Server checks that client messages come in cleanly ++ i := 0 ++ for ; i < N; i++ { ++ p, err := trS.readPacket() ++ if err != nil && err != io.EOF { ++ t.Fatalf("server error: %v", err) ++ } ++ if (i % 10) == 5 { ++ gotHalf <- 1 ++ } ++ ++ want := []byte{msgRequestSuccess, byte(i)} ++ if bytes.Compare(p, want) != 0 { ++ t.Errorf("message %d: got %v, want %v", i, p, want) ++ } ++ } ++ <-clientDone ++ if err := <-errorCh; err != nil { ++ t.Fatalf("sendPacket: %v", err) ++ } ++ if i != N { ++ t.Errorf("received %d messages, want 10.", i) ++ } ++ ++ close(checker.called) ++ if _, ok := <-checker.called; ok { ++ // If all went well, we registered exactly 2 key changes: one ++ // that establishes the session, and one that we requested ++ // additionally. ++ t.Fatalf("got another host key checks after 2 handshakes") ++ } ++} ++ ++func TestForceFirstKex(t *testing.T) { ++ // like handshakePair, but must access the keyingTransport. ++ checker := &testChecker{} ++ clientConf := &ClientConfig{HostKeyCallback: checker.Check} ++ a, b, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ ++ var trC, trS keyingTransport ++ ++ trC = newTransport(a, rand.Reader, true) ++ ++ // This is the disallowed packet: ++ trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})) ++ ++ // Rest of the setup. ++ trS = newTransport(b, rand.Reader, false) ++ clientConf.SetDefaults() ++ ++ v := []byte("version") ++ client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr()) ++ ++ serverConf := &ServerConfig{} ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ serverConf.AddHostKey(testSigners["rsa"]) ++ serverConf.SetDefaults() ++ server := newServerTransport(trS, v, v, serverConf) ++ ++ defer client.Close() ++ defer server.Close() ++ ++ // We setup the initial key exchange, but the remote side ++ // tries to send serviceRequestMsg in cleartext, which is ++ // disallowed. ++ ++ if err := server.waitSession(); err == nil { ++ t.Errorf("server first kex init should reject unexpected packet") ++ } ++} ++ ++func TestHandshakeAutoRekeyWrite(t *testing.T) { ++ checker := &syncChecker{ ++ called: make(chan int, 10), ++ waitCall: nil, ++ } ++ clientConf := &ClientConfig{HostKeyCallback: checker.Check} ++ clientConf.RekeyThreshold = 500 ++ trC, trS, err := handshakePair(clientConf, "addr", false) ++ if err != nil { ++ t.Fatalf("handshakePair: %v", err) ++ } ++ defer trC.Close() ++ defer trS.Close() ++ ++ input := make([]byte, 251) ++ input[0] = msgRequestSuccess ++ ++ done := make(chan int, 1) ++ const numPacket = 5 ++ go func() { ++ defer close(done) ++ j := 0 ++ for ; j < numPacket; j++ { ++ if p, err := trS.readPacket(); err != nil { ++ break ++ } else if !bytes.Equal(input, p) { ++ t.Errorf("got packet type %d, want %d", p[0], input[0]) ++ } ++ } ++ ++ if j != numPacket { ++ t.Errorf("got %d, want 5 messages", j) ++ } ++ }() ++ ++ <-checker.called ++ ++ for i := 0; i < numPacket; i++ { ++ p := make([]byte, len(input)) ++ copy(p, input) ++ if err := trC.writePacket(p); err != nil { ++ t.Errorf("writePacket: %v", err) ++ } ++ if i == 2 { ++ // Make sure the kex is in progress. ++ <-checker.called ++ } ++ ++ } ++ <-done ++} ++ ++type syncChecker struct { ++ waitCall chan int ++ called chan int ++} ++ ++func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { ++ c.called <- 1 ++ if c.waitCall != nil { ++ <-c.waitCall ++ } ++ return nil ++} ++ ++func TestHandshakeAutoRekeyRead(t *testing.T) { ++ sync := &syncChecker{ ++ called: make(chan int, 2), ++ waitCall: nil, ++ } ++ clientConf := &ClientConfig{ ++ HostKeyCallback: sync.Check, ++ } ++ clientConf.RekeyThreshold = 500 ++ ++ trC, trS, err := handshakePair(clientConf, "addr", false) ++ if err != nil { ++ t.Fatalf("handshakePair: %v", err) ++ } ++ defer trC.Close() ++ defer trS.Close() ++ ++ packet := make([]byte, 501) ++ packet[0] = msgRequestSuccess ++ if err := trS.writePacket(packet); err != nil { ++ t.Fatalf("writePacket: %v", err) ++ } ++ ++ // While we read out the packet, a key change will be ++ // initiated. ++ errorCh := make(chan error, 1) ++ go func() { ++ _, err := trC.readPacket() ++ errorCh <- err ++ }() ++ ++ if err := <-errorCh; err != nil { ++ t.Fatalf("readPacket(client): %v", err) ++ } ++ ++ <-sync.called ++} ++ ++// errorKeyingTransport generates errors after a given number of ++// read/write operations. ++type errorKeyingTransport struct { ++ packetConn ++ readLeft, writeLeft int ++} ++ ++func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { ++ return nil ++} ++ ++func (n *errorKeyingTransport) getSessionID() []byte { ++ return nil ++} ++ ++func (n *errorKeyingTransport) writePacket(packet []byte) error { ++ if n.writeLeft == 0 { ++ n.Close() ++ return errors.New("barf") ++ } ++ ++ n.writeLeft-- ++ return n.packetConn.writePacket(packet) ++} ++ ++func (n *errorKeyingTransport) readPacket() ([]byte, error) { ++ if n.readLeft == 0 { ++ n.Close() ++ return nil, errors.New("barf") ++ } ++ ++ n.readLeft-- ++ return n.packetConn.readPacket() ++} ++ ++func TestHandshakeErrorHandlingRead(t *testing.T) { ++ for i := 0; i < 20; i++ { ++ testHandshakeErrorHandlingN(t, i, -1, false) ++ } ++} ++ ++func TestHandshakeErrorHandlingWrite(t *testing.T) { ++ for i := 0; i < 20; i++ { ++ testHandshakeErrorHandlingN(t, -1, i, false) ++ } ++} ++ ++func TestHandshakeErrorHandlingReadCoupled(t *testing.T) { ++ for i := 0; i < 20; i++ { ++ testHandshakeErrorHandlingN(t, i, -1, true) ++ } ++} ++ ++func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) { ++ for i := 0; i < 20; i++ { ++ testHandshakeErrorHandlingN(t, -1, i, true) ++ } ++} ++ ++// testHandshakeErrorHandlingN runs handshakes, injecting errors. If ++// handshakeTransport deadlocks, the go runtime will detect it and ++// panic. ++func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) { ++ if (runtime.GOOS == "js" || runtime.GOOS == "wasip1") && runtime.GOARCH == "wasm" { ++ t.Skipf("skipping on %s/wasm; see golang.org/issue/32840", runtime.GOOS) ++ } ++ msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)}) ++ ++ a, b := memPipe() ++ defer a.Close() ++ defer b.Close() ++ ++ key := testSigners["ecdsa"] ++ serverConf := Config{RekeyThreshold: minRekeyThreshold} ++ serverConf.SetDefaults() ++ serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'}) ++ serverConn.hostKeys = []Signer{key} ++ go serverConn.readLoop() ++ go serverConn.kexLoop() ++ ++ clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold} ++ clientConf.SetDefaults() ++ clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'}) ++ clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()} ++ clientConn.hostKeyCallback = InsecureIgnoreHostKey() ++ go clientConn.readLoop() ++ go clientConn.kexLoop() ++ ++ var wg sync.WaitGroup ++ ++ for _, hs := range []packetConn{serverConn, clientConn} { ++ if !coupled { ++ wg.Add(2) ++ go func(c packetConn) { ++ for i := 0; ; i++ { ++ str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8) ++ err := c.writePacket(Marshal(&serviceRequestMsg{str})) ++ if err != nil { ++ break ++ } ++ } ++ wg.Done() ++ c.Close() ++ }(hs) ++ go func(c packetConn) { ++ for { ++ _, err := c.readPacket() ++ if err != nil { ++ break ++ } ++ } ++ wg.Done() ++ }(hs) ++ } else { ++ wg.Add(1) ++ go func(c packetConn) { ++ for { ++ _, err := c.readPacket() ++ if err != nil { ++ break ++ } ++ if err := c.writePacket(msg); err != nil { ++ break ++ } ++ ++ } ++ wg.Done() ++ }(hs) ++ } ++ } ++ wg.Wait() ++} ++ ++func TestDisconnect(t *testing.T) { ++ if runtime.GOOS == "plan9" { ++ t.Skip("see golang.org/issue/7237") ++ } ++ checker := &testChecker{} ++ trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) ++ if err != nil { ++ t.Fatalf("handshakePair: %v", err) ++ } ++ ++ defer trC.Close() ++ defer trS.Close() ++ ++ trC.writePacket([]byte{msgRequestSuccess, 0, 0}) ++ errMsg := &disconnectMsg{ ++ Reason: 42, ++ Message: "such is life", ++ } ++ trC.writePacket(Marshal(errMsg)) ++ trC.writePacket([]byte{msgRequestSuccess, 0, 0}) ++ ++ packet, err := trS.readPacket() ++ if err != nil { ++ t.Fatalf("readPacket 1: %v", err) ++ } ++ if packet[0] != msgRequestSuccess { ++ t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess) ++ } ++ ++ _, err = trS.readPacket() ++ if err == nil { ++ t.Errorf("readPacket 2 succeeded") ++ } else if !reflect.DeepEqual(err, errMsg) { ++ t.Errorf("got error %#v, want %#v", err, errMsg) ++ } ++ ++ _, err = trS.readPacket() ++ if err == nil { ++ t.Errorf("readPacket 3 succeeded") ++ } ++} ++ ++func TestHandshakeRekeyDefault(t *testing.T) { ++ clientConf := &ClientConfig{ ++ Config: Config{ ++ Ciphers: []string{"aes128-ctr"}, ++ }, ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ trC, trS, err := handshakePair(clientConf, "addr", false) ++ if err != nil { ++ t.Fatalf("handshakePair: %v", err) ++ } ++ defer trC.Close() ++ defer trS.Close() ++ ++ trC.writePacket([]byte{msgRequestSuccess, 0, 0}) ++ trC.Close() ++ ++ rgb := (1024 + trC.readBytesLeft) >> 30 ++ wgb := (1024 + trC.writeBytesLeft) >> 30 ++ ++ if rgb != 64 { ++ t.Errorf("got rekey after %dG read, want 64G", rgb) ++ } ++ if wgb != 64 { ++ t.Errorf("got rekey after %dG write, want 64G", wgb) ++ } ++} ++ ++func TestHandshakeAEADCipherNoMAC(t *testing.T) { ++ for _, cipher := range []string{chacha20Poly1305ID, gcm128CipherID} { ++ checker := &syncChecker{ ++ called: make(chan int, 1), ++ } ++ clientConf := &ClientConfig{ ++ Config: Config{ ++ Ciphers: []string{cipher}, ++ MACs: []string{}, ++ }, ++ HostKeyCallback: checker.Check, ++ } ++ trC, trS, err := handshakePair(clientConf, "addr", false) ++ if err != nil { ++ t.Fatalf("handshakePair: %v", err) ++ } ++ defer trC.Close() ++ defer trS.Close() ++ ++ <-checker.called ++ } ++} ++ ++// TestNoSHA2Support tests a host key Signer that is not an AlgorithmSigner and ++// therefore can't do SHA-2 signatures. Ensures the server does not advertise ++// support for them in this case. ++func TestNoSHA2Support(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ serverConf := &ServerConfig{ ++ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { ++ return &Permissions{}, nil ++ }, ++ } ++ serverConf.AddHostKey(&legacyRSASigner{testSigners["rsa"]}) ++ go func() { ++ _, _, _, err := NewServerConn(c1, serverConf) ++ if err != nil { ++ t.Error(err) ++ } ++ }() ++ ++ clientConf := &ClientConfig{ ++ User: "test", ++ Auth: []AuthMethod{Password("testpw")}, ++ HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), ++ } ++ ++ if _, _, _, err := NewClientConn(c2, "", clientConf); err != nil { ++ t.Fatal(err) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go +new file mode 100644 +index 00000000000000..af81d266546eaa +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go +@@ -0,0 +1,93 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD. ++// ++// See https://flak.tedunangst.com/post/bcrypt-pbkdf and ++// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c. ++package bcrypt_pbkdf ++ ++import ( ++ "crypto/sha512" ++ "errors" ++ "golang.org/x/crypto/blowfish" ++) ++ ++const blockSize = 32 ++ ++// Key derives a key from the password, salt and rounds count, returning a ++// []byte of length keyLen that can be used as cryptographic key. ++func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) { ++ if rounds < 1 { ++ return nil, errors.New("bcrypt_pbkdf: number of rounds is too small") ++ } ++ if len(password) == 0 { ++ return nil, errors.New("bcrypt_pbkdf: empty password") ++ } ++ if len(salt) == 0 || len(salt) > 1<<20 { ++ return nil, errors.New("bcrypt_pbkdf: bad salt length") ++ } ++ if keyLen > 1024 { ++ return nil, errors.New("bcrypt_pbkdf: keyLen is too large") ++ } ++ ++ numBlocks := (keyLen + blockSize - 1) / blockSize ++ key := make([]byte, numBlocks*blockSize) ++ ++ h := sha512.New() ++ h.Write(password) ++ shapass := h.Sum(nil) ++ ++ shasalt := make([]byte, 0, sha512.Size) ++ cnt, tmp := make([]byte, 4), make([]byte, blockSize) ++ for block := 1; block <= numBlocks; block++ { ++ h.Reset() ++ h.Write(salt) ++ cnt[0] = byte(block >> 24) ++ cnt[1] = byte(block >> 16) ++ cnt[2] = byte(block >> 8) ++ cnt[3] = byte(block) ++ h.Write(cnt) ++ bcryptHash(tmp, shapass, h.Sum(shasalt)) ++ ++ out := make([]byte, blockSize) ++ copy(out, tmp) ++ for i := 2; i <= rounds; i++ { ++ h.Reset() ++ h.Write(tmp) ++ bcryptHash(tmp, shapass, h.Sum(shasalt)) ++ for j := 0; j < len(out); j++ { ++ out[j] ^= tmp[j] ++ } ++ } ++ ++ for i, v := range out { ++ key[i*numBlocks+(block-1)] = v ++ } ++ } ++ return key[:keyLen], nil ++} ++ ++var magic = []byte("OxychromaticBlowfishSwatDynamite") ++ ++func bcryptHash(out, shapass, shasalt []byte) { ++ c, err := blowfish.NewSaltedCipher(shapass, shasalt) ++ if err != nil { ++ panic(err) ++ } ++ for i := 0; i < 64; i++ { ++ blowfish.ExpandKey(shasalt, c) ++ blowfish.ExpandKey(shapass, c) ++ } ++ copy(out, magic) ++ for i := 0; i < 32; i += 8 { ++ for j := 0; j < 64; j++ { ++ c.Encrypt(out[i:i+8], out[i:i+8]) ++ } ++ } ++ // Swap bytes due to different endianness. ++ for i := 0; i < 32; i += 4 { ++ out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3] ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go +new file mode 100644 +index 00000000000000..20b7889bce95a3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go +@@ -0,0 +1,97 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package bcrypt_pbkdf ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++// Test vectors generated by the reference implementation from OpenBSD. ++var golden = []struct { ++ rounds int ++ password, salt, result []byte ++}{ ++ { ++ 12, ++ []byte("password"), ++ []byte("salt"), ++ []byte{ ++ 0x1a, 0xe4, 0x2c, 0x05, 0xd4, 0x87, 0xbc, 0x02, 0xf6, ++ 0x49, 0x21, 0xa4, 0xeb, 0xe4, 0xea, 0x93, 0xbc, 0xac, ++ 0xfe, 0x13, 0x5f, 0xda, 0x99, 0x97, 0x4c, 0x06, 0xb7, ++ 0xb0, 0x1f, 0xae, 0x14, 0x9a, ++ }, ++ }, ++ { ++ 3, ++ []byte("passwordy\x00PASSWORD\x00"), ++ []byte("salty\x00SALT\x00"), ++ []byte{ ++ 0x7f, 0x31, 0x0b, 0xd3, 0xe7, 0x8c, 0x32, 0x80, 0xc5, ++ 0x9c, 0xe4, 0x59, 0x52, 0x11, 0xa2, 0x92, 0x8e, 0x8d, ++ 0x4e, 0xc7, 0x44, 0xc1, 0xed, 0x2e, 0xfc, 0x9f, 0x76, ++ 0x4e, 0x33, 0x88, 0xe0, 0xad, ++ }, ++ }, ++ { ++ // See http://thread.gmane.org/gmane.os.openbsd.bugs/20542 ++ 8, ++ []byte("сСкрСтноС слово"), ++ []byte("ΠΏΠΎΡΠΎΠ»ΠΈΡ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠΆΠΊΠΎ"), ++ []byte{ ++ 0x8d, 0xf4, 0x3f, 0xc6, 0xfe, 0x13, 0x1f, 0xc4, 0x7f, ++ 0x0c, 0x9e, 0x39, 0x22, 0x4b, 0xd9, 0x4c, 0x70, 0xb6, ++ 0xfc, 0xc8, 0xee, 0x81, 0x35, 0xfa, 0xdd, 0xf6, 0x11, ++ 0x56, 0xe6, 0xcb, 0x27, 0x33, 0xea, 0x76, 0x5f, 0x31, ++ 0x5a, 0x3e, 0x1e, 0x4a, 0xfc, 0x35, 0xbf, 0x86, 0x87, ++ 0xd1, 0x89, 0x25, 0x4c, 0x1e, 0x05, 0xa6, 0xfe, 0x80, ++ 0xc0, 0x61, 0x7f, 0x91, 0x83, 0xd6, 0x72, 0x60, 0xd6, ++ 0xa1, 0x15, 0xc6, 0xc9, 0x4e, 0x36, 0x03, 0xe2, 0x30, ++ 0x3f, 0xbb, 0x43, 0xa7, 0x6a, 0x64, 0x52, 0x3f, 0xfd, ++ 0xa6, 0x86, 0xb1, 0xd4, 0x51, 0x85, 0x43, ++ }, ++ }, ++} ++ ++func TestKey(t *testing.T) { ++ for i, v := range golden { ++ k, err := Key(v.password, v.salt, v.rounds, len(v.result)) ++ if err != nil { ++ t.Errorf("%d: %s", i, err) ++ continue ++ } ++ if !bytes.Equal(k, v.result) { ++ t.Errorf("%d: expected\n%x\n, got\n%x\n", i, v.result, k) ++ } ++ } ++} ++ ++func TestBcryptHash(t *testing.T) { ++ good := []byte{ ++ 0x87, 0x90, 0x48, 0x70, 0xee, 0xf9, 0xde, 0xdd, 0xf8, 0xe7, ++ 0x61, 0x1a, 0x14, 0x01, 0x06, 0xe6, 0xaa, 0xf1, 0xa3, 0x63, ++ 0xd9, 0xa2, 0xc5, 0x04, 0xdb, 0x35, 0x64, 0x43, 0x72, 0x1e, ++ 0xb5, 0x55, ++ } ++ var pass, salt [64]byte ++ var result [32]byte ++ for i := 0; i < 64; i++ { ++ pass[i] = byte(i) ++ salt[i] = byte(i + 64) ++ } ++ bcryptHash(result[:], pass[:], salt[:]) ++ if !bytes.Equal(result[:], good) { ++ t.Errorf("expected %x, got %x", good, result) ++ } ++} ++ ++func BenchmarkKey(b *testing.B) { ++ pass := []byte("password") ++ salt := []byte("salt") ++ for i := 0; i < b.N; i++ { ++ Key(pass, salt, 10, 32) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/kex.go b/ms_mod/golang.org/x/crypto/ssh/kex.go +new file mode 100644 +index 00000000000000..8a05f79902c095 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/kex.go +@@ -0,0 +1,786 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "crypto" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/subtle" ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "io" ++ "math/big" ++ ++ "golang.org/x/crypto/curve25519" ++) ++ ++const ( ++ kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" ++ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" ++ kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256" ++ kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512" ++ kexAlgoECDH256 = "ecdh-sha2-nistp256" ++ kexAlgoECDH384 = "ecdh-sha2-nistp384" ++ kexAlgoECDH521 = "ecdh-sha2-nistp521" ++ kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org" ++ kexAlgoCurve25519SHA256 = "curve25519-sha256" ++ ++ // For the following kex only the client half contains a production ++ // ready implementation. The server half only consists of a minimal ++ // implementation to satisfy the automated tests. ++ kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1" ++ kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256" ++) ++ ++// kexResult captures the outcome of a key exchange. ++type kexResult struct { ++ // Session hash. See also RFC 4253, section 8. ++ H []byte ++ ++ // Shared secret. See also RFC 4253, section 8. ++ K []byte ++ ++ // Host key as hashed into H. ++ HostKey []byte ++ ++ // Signature of H. ++ Signature []byte ++ ++ // A cryptographic hash function that matches the security ++ // level of the key exchange algorithm. It is used for ++ // calculating H, and for deriving keys from H and K. ++ Hash crypto.Hash ++ ++ // The session ID, which is the first H computed. This is used ++ // to derive key material inside the transport. ++ SessionID []byte ++} ++ ++// handshakeMagics contains data that is always included in the ++// session hash. ++type handshakeMagics struct { ++ clientVersion, serverVersion []byte ++ clientKexInit, serverKexInit []byte ++} ++ ++func (m *handshakeMagics) write(w io.Writer) { ++ writeString(w, m.clientVersion) ++ writeString(w, m.serverVersion) ++ writeString(w, m.clientKexInit) ++ writeString(w, m.serverKexInit) ++} ++ ++// kexAlgorithm abstracts different key exchange algorithms. ++type kexAlgorithm interface { ++ // Server runs server-side key agreement, signing the result ++ // with a hostkey. algo is the negotiated algorithm, and may ++ // be a certificate type. ++ Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error) ++ ++ // Client runs the client-side key agreement. Caller is ++ // responsible for verifying the host key signature. ++ Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) ++} ++ ++// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. ++type dhGroup struct { ++ g, p, pMinus1 *big.Int ++ hashFunc crypto.Hash ++} ++ ++func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { ++ if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 { ++ return nil, errors.New("ssh: DH parameter out of bounds") ++ } ++ return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil ++} ++ ++func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { ++ var x *big.Int ++ for { ++ var err error ++ if x, err = rand.Int(randSource, group.pMinus1); err != nil { ++ return nil, err ++ } ++ if x.Sign() > 0 { ++ break ++ } ++ } ++ ++ X := new(big.Int).Exp(group.g, x, group.p) ++ kexDHInit := kexDHInitMsg{ ++ X: X, ++ } ++ if err := c.writePacket(Marshal(&kexDHInit)); err != nil { ++ return nil, err ++ } ++ ++ packet, err := c.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ var kexDHReply kexDHReplyMsg ++ if err = Unmarshal(packet, &kexDHReply); err != nil { ++ return nil, err ++ } ++ ++ ki, err := group.diffieHellman(kexDHReply.Y, x) ++ if err != nil { ++ return nil, err ++ } ++ ++ h := group.hashFunc.New() ++ magics.write(h) ++ writeString(h, kexDHReply.HostKey) ++ writeInt(h, X) ++ writeInt(h, kexDHReply.Y) ++ K := make([]byte, intLength(ki)) ++ marshalInt(K, ki) ++ h.Write(K) ++ ++ return &kexResult{ ++ H: h.Sum(nil), ++ K: K, ++ HostKey: kexDHReply.HostKey, ++ Signature: kexDHReply.Signature, ++ Hash: group.hashFunc, ++ }, nil ++} ++ ++func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { ++ packet, err := c.readPacket() ++ if err != nil { ++ return ++ } ++ var kexDHInit kexDHInitMsg ++ if err = Unmarshal(packet, &kexDHInit); err != nil { ++ return ++ } ++ ++ var y *big.Int ++ for { ++ if y, err = rand.Int(randSource, group.pMinus1); err != nil { ++ return ++ } ++ if y.Sign() > 0 { ++ break ++ } ++ } ++ ++ Y := new(big.Int).Exp(group.g, y, group.p) ++ ki, err := group.diffieHellman(kexDHInit.X, y) ++ if err != nil { ++ return nil, err ++ } ++ ++ hostKeyBytes := priv.PublicKey().Marshal() ++ ++ h := group.hashFunc.New() ++ magics.write(h) ++ writeString(h, hostKeyBytes) ++ writeInt(h, kexDHInit.X) ++ writeInt(h, Y) ++ ++ K := make([]byte, intLength(ki)) ++ marshalInt(K, ki) ++ h.Write(K) ++ ++ H := h.Sum(nil) ++ ++ // H is already a hash, but the hostkey signing will apply its ++ // own key-specific hash algorithm. ++ sig, err := signAndMarshal(priv, randSource, H, algo) ++ if err != nil { ++ return nil, err ++ } ++ ++ kexDHReply := kexDHReplyMsg{ ++ HostKey: hostKeyBytes, ++ Y: Y, ++ Signature: sig, ++ } ++ packet = Marshal(&kexDHReply) ++ ++ err = c.writePacket(packet) ++ return &kexResult{ ++ H: H, ++ K: K, ++ HostKey: hostKeyBytes, ++ Signature: sig, ++ Hash: group.hashFunc, ++ }, err ++} ++ ++// ecdh performs Elliptic Curve Diffie-Hellman key exchange as ++// described in RFC 5656, section 4. ++type ecdh struct { ++ curve elliptic.Curve ++} ++ ++func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { ++ ephKey, err := ecdsa.GenerateKey(kex.curve, rand) ++ if err != nil { ++ return nil, err ++ } ++ ++ kexInit := kexECDHInitMsg{ ++ ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), ++ } ++ ++ serialized := Marshal(&kexInit) ++ if err := c.writePacket(serialized); err != nil { ++ return nil, err ++ } ++ ++ packet, err := c.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ var reply kexECDHReplyMsg ++ if err = Unmarshal(packet, &reply); err != nil { ++ return nil, err ++ } ++ ++ x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) ++ if err != nil { ++ return nil, err ++ } ++ ++ // generate shared secret ++ secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) ++ ++ h := ecHash(kex.curve).New() ++ magics.write(h) ++ writeString(h, reply.HostKey) ++ writeString(h, kexInit.ClientPubKey) ++ writeString(h, reply.EphemeralPubKey) ++ K := make([]byte, intLength(secret)) ++ marshalInt(K, secret) ++ h.Write(K) ++ ++ return &kexResult{ ++ H: h.Sum(nil), ++ K: K, ++ HostKey: reply.HostKey, ++ Signature: reply.Signature, ++ Hash: ecHash(kex.curve), ++ }, nil ++} ++ ++// unmarshalECKey parses and checks an EC key. ++func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { ++ x, y = elliptic.Unmarshal(curve, pubkey) ++ if x == nil { ++ return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") ++ } ++ if !validateECPublicKey(curve, x, y) { ++ return nil, nil, errors.New("ssh: public key not on curve") ++ } ++ return x, y, nil ++} ++ ++// validateECPublicKey checks that the point is a valid public key for ++// the given curve. See [SEC1], 3.2.2 ++func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { ++ if x.Sign() == 0 && y.Sign() == 0 { ++ return false ++ } ++ ++ if x.Cmp(curve.Params().P) >= 0 { ++ return false ++ } ++ ++ if y.Cmp(curve.Params().P) >= 0 { ++ return false ++ } ++ ++ if !curve.IsOnCurve(x, y) { ++ return false ++ } ++ ++ // We don't check if N * PubKey == 0, since ++ // ++ // - the NIST curves have cofactor = 1, so this is implicit. ++ // (We don't foresee an implementation that supports non NIST ++ // curves) ++ // ++ // - for ephemeral keys, we don't need to worry about small ++ // subgroup attacks. ++ return true ++} ++ ++func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { ++ packet, err := c.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ var kexECDHInit kexECDHInitMsg ++ if err = Unmarshal(packet, &kexECDHInit); err != nil { ++ return nil, err ++ } ++ ++ clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) ++ if err != nil { ++ return nil, err ++ } ++ ++ // We could cache this key across multiple users/multiple ++ // connection attempts, but the benefit is small. OpenSSH ++ // generates a new key for each incoming connection. ++ ephKey, err := ecdsa.GenerateKey(kex.curve, rand) ++ if err != nil { ++ return nil, err ++ } ++ ++ hostKeyBytes := priv.PublicKey().Marshal() ++ ++ serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) ++ ++ // generate shared secret ++ secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) ++ ++ h := ecHash(kex.curve).New() ++ magics.write(h) ++ writeString(h, hostKeyBytes) ++ writeString(h, kexECDHInit.ClientPubKey) ++ writeString(h, serializedEphKey) ++ ++ K := make([]byte, intLength(secret)) ++ marshalInt(K, secret) ++ h.Write(K) ++ ++ H := h.Sum(nil) ++ ++ // H is already a hash, but the hostkey signing will apply its ++ // own key-specific hash algorithm. ++ sig, err := signAndMarshal(priv, rand, H, algo) ++ if err != nil { ++ return nil, err ++ } ++ ++ reply := kexECDHReplyMsg{ ++ EphemeralPubKey: serializedEphKey, ++ HostKey: hostKeyBytes, ++ Signature: sig, ++ } ++ ++ serialized := Marshal(&reply) ++ if err := c.writePacket(serialized); err != nil { ++ return nil, err ++ } ++ ++ return &kexResult{ ++ H: H, ++ K: K, ++ HostKey: reply.HostKey, ++ Signature: sig, ++ Hash: ecHash(kex.curve), ++ }, nil ++} ++ ++// ecHash returns the hash to match the given elliptic curve, see RFC ++// 5656, section 6.2.1 ++func ecHash(curve elliptic.Curve) crypto.Hash { ++ bitSize := curve.Params().BitSize ++ switch { ++ case bitSize <= 256: ++ return crypto.SHA256 ++ case bitSize <= 384: ++ return crypto.SHA384 ++ } ++ return crypto.SHA512 ++} ++ ++var kexAlgoMap = map[string]kexAlgorithm{} ++ ++func init() { ++ // This is the group called diffie-hellman-group1-sha1 in ++ // RFC 4253 and Oakley Group 2 in RFC 2409. ++ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) ++ kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ ++ g: new(big.Int).SetInt64(2), ++ p: p, ++ pMinus1: new(big.Int).Sub(p, bigOne), ++ hashFunc: crypto.SHA1, ++ } ++ ++ // This are the groups called diffie-hellman-group14-sha1 and ++ // diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268, ++ // and Oakley Group 14 in RFC 3526. ++ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) ++ group14 := &dhGroup{ ++ g: new(big.Int).SetInt64(2), ++ p: p, ++ pMinus1: new(big.Int).Sub(p, bigOne), ++ } ++ ++ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ ++ g: group14.g, p: group14.p, pMinus1: group14.pMinus1, ++ hashFunc: crypto.SHA1, ++ } ++ kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{ ++ g: group14.g, p: group14.p, pMinus1: group14.pMinus1, ++ hashFunc: crypto.SHA256, ++ } ++ ++ // This is the group called diffie-hellman-group16-sha512 in RFC ++ // 8268 and Oakley Group 16 in RFC 3526. ++ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16) ++ ++ kexAlgoMap[kexAlgoDH16SHA512] = &dhGroup{ ++ g: new(big.Int).SetInt64(2), ++ p: p, ++ pMinus1: new(big.Int).Sub(p, bigOne), ++ hashFunc: crypto.SHA512, ++ } ++ ++ kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} ++ kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} ++ kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} ++ kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} ++ kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{} ++ kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} ++ kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} ++} ++ ++// curve25519sha256 implements the curve25519-sha256 (formerly known as ++// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731. ++type curve25519sha256 struct{} ++ ++type curve25519KeyPair struct { ++ priv [32]byte ++ pub [32]byte ++} ++ ++func (kp *curve25519KeyPair) generate(rand io.Reader) error { ++ if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { ++ return err ++ } ++ curve25519.ScalarBaseMult(&kp.pub, &kp.priv) ++ return nil ++} ++ ++// curve25519Zeros is just an array of 32 zero bytes so that we have something ++// convenient to compare against in order to reject curve25519 points with the ++// wrong order. ++var curve25519Zeros [32]byte ++ ++func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { ++ var kp curve25519KeyPair ++ if err := kp.generate(rand); err != nil { ++ return nil, err ++ } ++ if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { ++ return nil, err ++ } ++ ++ packet, err := c.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ var reply kexECDHReplyMsg ++ if err = Unmarshal(packet, &reply); err != nil { ++ return nil, err ++ } ++ if len(reply.EphemeralPubKey) != 32 { ++ return nil, errors.New("ssh: peer's curve25519 public value has wrong length") ++ } ++ ++ var servPub, secret [32]byte ++ copy(servPub[:], reply.EphemeralPubKey) ++ curve25519.ScalarMult(&secret, &kp.priv, &servPub) ++ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { ++ return nil, errors.New("ssh: peer's curve25519 public value has wrong order") ++ } ++ ++ h := crypto.SHA256.New() ++ magics.write(h) ++ writeString(h, reply.HostKey) ++ writeString(h, kp.pub[:]) ++ writeString(h, reply.EphemeralPubKey) ++ ++ ki := new(big.Int).SetBytes(secret[:]) ++ K := make([]byte, intLength(ki)) ++ marshalInt(K, ki) ++ h.Write(K) ++ ++ return &kexResult{ ++ H: h.Sum(nil), ++ K: K, ++ HostKey: reply.HostKey, ++ Signature: reply.Signature, ++ Hash: crypto.SHA256, ++ }, nil ++} ++ ++func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { ++ packet, err := c.readPacket() ++ if err != nil { ++ return ++ } ++ var kexInit kexECDHInitMsg ++ if err = Unmarshal(packet, &kexInit); err != nil { ++ return ++ } ++ ++ if len(kexInit.ClientPubKey) != 32 { ++ return nil, errors.New("ssh: peer's curve25519 public value has wrong length") ++ } ++ ++ var kp curve25519KeyPair ++ if err := kp.generate(rand); err != nil { ++ return nil, err ++ } ++ ++ var clientPub, secret [32]byte ++ copy(clientPub[:], kexInit.ClientPubKey) ++ curve25519.ScalarMult(&secret, &kp.priv, &clientPub) ++ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { ++ return nil, errors.New("ssh: peer's curve25519 public value has wrong order") ++ } ++ ++ hostKeyBytes := priv.PublicKey().Marshal() ++ ++ h := crypto.SHA256.New() ++ magics.write(h) ++ writeString(h, hostKeyBytes) ++ writeString(h, kexInit.ClientPubKey) ++ writeString(h, kp.pub[:]) ++ ++ ki := new(big.Int).SetBytes(secret[:]) ++ K := make([]byte, intLength(ki)) ++ marshalInt(K, ki) ++ h.Write(K) ++ ++ H := h.Sum(nil) ++ ++ sig, err := signAndMarshal(priv, rand, H, algo) ++ if err != nil { ++ return nil, err ++ } ++ ++ reply := kexECDHReplyMsg{ ++ EphemeralPubKey: kp.pub[:], ++ HostKey: hostKeyBytes, ++ Signature: sig, ++ } ++ if err := c.writePacket(Marshal(&reply)); err != nil { ++ return nil, err ++ } ++ return &kexResult{ ++ H: H, ++ K: K, ++ HostKey: hostKeyBytes, ++ Signature: sig, ++ Hash: crypto.SHA256, ++ }, nil ++} ++ ++// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and ++// diffie-hellman-group-exchange-sha256 key agreement protocols, ++// as described in RFC 4419 ++type dhGEXSHA struct { ++ hashFunc crypto.Hash ++} ++ ++const ( ++ dhGroupExchangeMinimumBits = 2048 ++ dhGroupExchangePreferredBits = 2048 ++ dhGroupExchangeMaximumBits = 8192 ++) ++ ++func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { ++ // Send GexRequest ++ kexDHGexRequest := kexDHGexRequestMsg{ ++ MinBits: dhGroupExchangeMinimumBits, ++ PreferedBits: dhGroupExchangePreferredBits, ++ MaxBits: dhGroupExchangeMaximumBits, ++ } ++ if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil { ++ return nil, err ++ } ++ ++ // Receive GexGroup ++ packet, err := c.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ var msg kexDHGexGroupMsg ++ if err = Unmarshal(packet, &msg); err != nil { ++ return nil, err ++ } ++ ++ // reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits ++ if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits { ++ return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen()) ++ } ++ ++ // Check if g is safe by verifying that 1 < g < p-1 ++ pMinusOne := new(big.Int).Sub(msg.P, bigOne) ++ if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 { ++ return nil, fmt.Errorf("ssh: server provided gex g is not safe") ++ } ++ ++ // Send GexInit ++ pHalf := new(big.Int).Rsh(msg.P, 1) ++ x, err := rand.Int(randSource, pHalf) ++ if err != nil { ++ return nil, err ++ } ++ X := new(big.Int).Exp(msg.G, x, msg.P) ++ kexDHGexInit := kexDHGexInitMsg{ ++ X: X, ++ } ++ if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil { ++ return nil, err ++ } ++ ++ // Receive GexReply ++ packet, err = c.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ ++ var kexDHGexReply kexDHGexReplyMsg ++ if err = Unmarshal(packet, &kexDHGexReply); err != nil { ++ return nil, err ++ } ++ ++ if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 { ++ return nil, errors.New("ssh: DH parameter out of bounds") ++ } ++ kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P) ++ ++ // Check if k is safe by verifying that k > 1 and k < p - 1 ++ if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 { ++ return nil, fmt.Errorf("ssh: derived k is not safe") ++ } ++ ++ h := gex.hashFunc.New() ++ magics.write(h) ++ writeString(h, kexDHGexReply.HostKey) ++ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) ++ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) ++ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) ++ writeInt(h, msg.P) ++ writeInt(h, msg.G) ++ writeInt(h, X) ++ writeInt(h, kexDHGexReply.Y) ++ K := make([]byte, intLength(kInt)) ++ marshalInt(K, kInt) ++ h.Write(K) ++ ++ return &kexResult{ ++ H: h.Sum(nil), ++ K: K, ++ HostKey: kexDHGexReply.HostKey, ++ Signature: kexDHGexReply.Signature, ++ Hash: gex.hashFunc, ++ }, nil ++} ++ ++// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. ++// ++// This is a minimal implementation to satisfy the automated tests. ++func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { ++ // Receive GexRequest ++ packet, err := c.readPacket() ++ if err != nil { ++ return ++ } ++ var kexDHGexRequest kexDHGexRequestMsg ++ if err = Unmarshal(packet, &kexDHGexRequest); err != nil { ++ return ++ } ++ ++ // Send GexGroup ++ // This is the group called diffie-hellman-group14-sha1 in RFC ++ // 4253 and Oakley Group 14 in RFC 3526. ++ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) ++ g := big.NewInt(2) ++ ++ msg := &kexDHGexGroupMsg{ ++ P: p, ++ G: g, ++ } ++ if err := c.writePacket(Marshal(msg)); err != nil { ++ return nil, err ++ } ++ ++ // Receive GexInit ++ packet, err = c.readPacket() ++ if err != nil { ++ return ++ } ++ var kexDHGexInit kexDHGexInitMsg ++ if err = Unmarshal(packet, &kexDHGexInit); err != nil { ++ return ++ } ++ ++ pHalf := new(big.Int).Rsh(p, 1) ++ ++ y, err := rand.Int(randSource, pHalf) ++ if err != nil { ++ return ++ } ++ Y := new(big.Int).Exp(g, y, p) ++ ++ pMinusOne := new(big.Int).Sub(p, bigOne) ++ if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 { ++ return nil, errors.New("ssh: DH parameter out of bounds") ++ } ++ kInt := new(big.Int).Exp(kexDHGexInit.X, y, p) ++ ++ hostKeyBytes := priv.PublicKey().Marshal() ++ ++ h := gex.hashFunc.New() ++ magics.write(h) ++ writeString(h, hostKeyBytes) ++ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) ++ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) ++ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) ++ writeInt(h, p) ++ writeInt(h, g) ++ writeInt(h, kexDHGexInit.X) ++ writeInt(h, Y) ++ ++ K := make([]byte, intLength(kInt)) ++ marshalInt(K, kInt) ++ h.Write(K) ++ ++ H := h.Sum(nil) ++ ++ // H is already a hash, but the hostkey signing will apply its ++ // own key-specific hash algorithm. ++ sig, err := signAndMarshal(priv, randSource, H, algo) ++ if err != nil { ++ return nil, err ++ } ++ ++ kexDHGexReply := kexDHGexReplyMsg{ ++ HostKey: hostKeyBytes, ++ Y: Y, ++ Signature: sig, ++ } ++ packet = Marshal(&kexDHGexReply) ++ ++ err = c.writePacket(packet) ++ ++ return &kexResult{ ++ H: H, ++ K: K, ++ HostKey: hostKeyBytes, ++ Signature: sig, ++ Hash: gex.hashFunc, ++ }, err ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/kex_test.go b/ms_mod/golang.org/x/crypto/ssh/kex_test.go +new file mode 100644 +index 00000000000000..cb7f66a5092f61 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/kex_test.go +@@ -0,0 +1,106 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++// Key exchange tests. ++ ++import ( ++ "crypto/rand" ++ "fmt" ++ "reflect" ++ "sync" ++ "testing" ++) ++ ++// Runs multiple key exchanges concurrent to detect potential data races with ++// kex obtained from the global kexAlgoMap. ++// This test needs to be executed using the race detector in order to detect ++// race conditions. ++func TestKexes(t *testing.T) { ++ type kexResultErr struct { ++ result *kexResult ++ err error ++ } ++ ++ for name, kex := range kexAlgoMap { ++ t.Run(name, func(t *testing.T) { ++ wg := sync.WaitGroup{} ++ for i := 0; i < 3; i++ { ++ wg.Add(1) ++ go func() { ++ defer wg.Done() ++ a, b := memPipe() ++ ++ s := make(chan kexResultErr, 1) ++ c := make(chan kexResultErr, 1) ++ var magics handshakeMagics ++ go func() { ++ r, e := kex.Client(a, rand.Reader, &magics) ++ a.Close() ++ c <- kexResultErr{r, e} ++ }() ++ go func() { ++ r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"].(AlgorithmSigner), testSigners["ecdsa"].PublicKey().Type()) ++ b.Close() ++ s <- kexResultErr{r, e} ++ }() ++ ++ clientRes := <-c ++ serverRes := <-s ++ if clientRes.err != nil { ++ t.Errorf("client: %v", clientRes.err) ++ } ++ if serverRes.err != nil { ++ t.Errorf("server: %v", serverRes.err) ++ } ++ if !reflect.DeepEqual(clientRes.result, serverRes.result) { ++ t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) ++ } ++ }() ++ } ++ wg.Wait() ++ }) ++ } ++} ++ ++func BenchmarkKexes(b *testing.B) { ++ type kexResultErr struct { ++ result *kexResult ++ err error ++ } ++ ++ for name, kex := range kexAlgoMap { ++ b.Run(name, func(b *testing.B) { ++ for i := 0; i < b.N; i++ { ++ t1, t2 := memPipe() ++ ++ s := make(chan kexResultErr, 1) ++ c := make(chan kexResultErr, 1) ++ var magics handshakeMagics ++ ++ go func() { ++ r, e := kex.Client(t1, rand.Reader, &magics) ++ t1.Close() ++ c <- kexResultErr{r, e} ++ }() ++ go func() { ++ r, e := kex.Server(t2, rand.Reader, &magics, testSigners["ecdsa"].(AlgorithmSigner), testSigners["ecdsa"].PublicKey().Type()) ++ t2.Close() ++ s <- kexResultErr{r, e} ++ }() ++ ++ clientRes := <-c ++ serverRes := <-s ++ ++ if clientRes.err != nil { ++ panic(fmt.Sprintf("client: %v", clientRes.err)) ++ } ++ if serverRes.err != nil { ++ panic(fmt.Sprintf("server: %v", serverRes.err)) ++ } ++ } ++ }) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/keys.go b/ms_mod/golang.org/x/crypto/ssh/keys.go +new file mode 100644 +index 00000000000000..dac8ee72447668 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/keys.go +@@ -0,0 +1,1447 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto" ++ "crypto/aes" ++ "crypto/cipher" ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/md5" ++ "crypto/rsa" ++ "crypto/sha256" ++ "crypto/x509" ++ "encoding/asn1" ++ "encoding/base64" ++ "encoding/hex" ++ "encoding/pem" ++ "errors" ++ "fmt" ++ "io" ++ "math/big" ++ "strings" ++ ++ "golang.org/x/crypto/ed25519" ++ "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf" ++) ++ ++// Public key algorithms names. These values can appear in PublicKey.Type, ++// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner ++// arguments. ++const ( ++ KeyAlgoRSA = "ssh-rsa" ++ KeyAlgoDSA = "ssh-dss" ++ KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" ++ KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" ++ KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" ++ KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" ++ KeyAlgoED25519 = "ssh-ed25519" ++ KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com" ++ ++ // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not ++ // public key formats, so they can't appear as a PublicKey.Type. The ++ // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. ++ KeyAlgoRSASHA256 = "rsa-sha2-256" ++ KeyAlgoRSASHA512 = "rsa-sha2-512" ++) ++ ++const ( ++ // Deprecated: use KeyAlgoRSA. ++ SigAlgoRSA = KeyAlgoRSA ++ // Deprecated: use KeyAlgoRSASHA256. ++ SigAlgoRSASHA2256 = KeyAlgoRSASHA256 ++ // Deprecated: use KeyAlgoRSASHA512. ++ SigAlgoRSASHA2512 = KeyAlgoRSASHA512 ++) ++ ++// parsePubKey parses a public key of the given algorithm. ++// Use ParsePublicKey for keys with prepended algorithm. ++func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { ++ switch algo { ++ case KeyAlgoRSA: ++ return parseRSA(in) ++ case KeyAlgoDSA: ++ return parseDSA(in) ++ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: ++ return parseECDSA(in) ++ case KeyAlgoSKECDSA256: ++ return parseSKECDSA(in) ++ case KeyAlgoED25519: ++ return parseED25519(in) ++ case KeyAlgoSKED25519: ++ return parseSKEd25519(in) ++ case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: ++ cert, err := parseCert(in, certKeyAlgoNames[algo]) ++ if err != nil { ++ return nil, nil, err ++ } ++ return cert, nil, nil ++ } ++ return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo) ++} ++ ++// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format ++// (see sshd(8) manual page) once the options and key type fields have been ++// removed. ++func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { ++ in = bytes.TrimSpace(in) ++ ++ i := bytes.IndexAny(in, " \t") ++ if i == -1 { ++ i = len(in) ++ } ++ base64Key := in[:i] ++ ++ key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) ++ n, err := base64.StdEncoding.Decode(key, base64Key) ++ if err != nil { ++ return nil, "", err ++ } ++ key = key[:n] ++ out, err = ParsePublicKey(key) ++ if err != nil { ++ return nil, "", err ++ } ++ comment = string(bytes.TrimSpace(in[i:])) ++ return out, comment, nil ++} ++ ++// ParseKnownHosts parses an entry in the format of the known_hosts file. ++// ++// The known_hosts format is documented in the sshd(8) manual page. This ++// function will parse a single entry from in. On successful return, marker ++// will contain the optional marker value (i.e. "cert-authority" or "revoked") ++// or else be empty, hosts will contain the hosts that this entry matches, ++// pubKey will contain the public key and comment will contain any trailing ++// comment at the end of the line. See the sshd(8) manual page for the various ++// forms that a host string can take. ++// ++// The unparsed remainder of the input will be returned in rest. This function ++// can be called repeatedly to parse multiple entries. ++// ++// If no entries were found in the input then err will be io.EOF. Otherwise a ++// non-nil err value indicates a parse error. ++func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) { ++ for len(in) > 0 { ++ end := bytes.IndexByte(in, '\n') ++ if end != -1 { ++ rest = in[end+1:] ++ in = in[:end] ++ } else { ++ rest = nil ++ } ++ ++ end = bytes.IndexByte(in, '\r') ++ if end != -1 { ++ in = in[:end] ++ } ++ ++ in = bytes.TrimSpace(in) ++ if len(in) == 0 || in[0] == '#' { ++ in = rest ++ continue ++ } ++ ++ i := bytes.IndexAny(in, " \t") ++ if i == -1 { ++ in = rest ++ continue ++ } ++ ++ // Strip out the beginning of the known_host key. ++ // This is either an optional marker or a (set of) hostname(s). ++ keyFields := bytes.Fields(in) ++ if len(keyFields) < 3 || len(keyFields) > 5 { ++ return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data") ++ } ++ ++ // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated ++ // list of hosts ++ marker := "" ++ if keyFields[0][0] == '@' { ++ marker = string(keyFields[0][1:]) ++ keyFields = keyFields[1:] ++ } ++ ++ hosts := string(keyFields[0]) ++ // keyFields[1] contains the key type (e.g. β€œssh-rsa”). ++ // However, that information is duplicated inside the ++ // base64-encoded key and so is ignored here. ++ ++ key := bytes.Join(keyFields[2:], []byte(" ")) ++ if pubKey, comment, err = parseAuthorizedKey(key); err != nil { ++ return "", nil, nil, "", nil, err ++ } ++ ++ return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil ++ } ++ ++ return "", nil, nil, "", nil, io.EOF ++} ++ ++// ParseAuthorizedKey parses a public key from an authorized_keys ++// file used in OpenSSH according to the sshd(8) manual page. ++func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { ++ for len(in) > 0 { ++ end := bytes.IndexByte(in, '\n') ++ if end != -1 { ++ rest = in[end+1:] ++ in = in[:end] ++ } else { ++ rest = nil ++ } ++ ++ end = bytes.IndexByte(in, '\r') ++ if end != -1 { ++ in = in[:end] ++ } ++ ++ in = bytes.TrimSpace(in) ++ if len(in) == 0 || in[0] == '#' { ++ in = rest ++ continue ++ } ++ ++ i := bytes.IndexAny(in, " \t") ++ if i == -1 { ++ in = rest ++ continue ++ } ++ ++ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { ++ return out, comment, options, rest, nil ++ } ++ ++ // No key type recognised. Maybe there's an options field at ++ // the beginning. ++ var b byte ++ inQuote := false ++ var candidateOptions []string ++ optionStart := 0 ++ for i, b = range in { ++ isEnd := !inQuote && (b == ' ' || b == '\t') ++ if (b == ',' && !inQuote) || isEnd { ++ if i-optionStart > 0 { ++ candidateOptions = append(candidateOptions, string(in[optionStart:i])) ++ } ++ optionStart = i + 1 ++ } ++ if isEnd { ++ break ++ } ++ if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { ++ inQuote = !inQuote ++ } ++ } ++ for i < len(in) && (in[i] == ' ' || in[i] == '\t') { ++ i++ ++ } ++ if i == len(in) { ++ // Invalid line: unmatched quote ++ in = rest ++ continue ++ } ++ ++ in = in[i:] ++ i = bytes.IndexAny(in, " \t") ++ if i == -1 { ++ in = rest ++ continue ++ } ++ ++ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { ++ options = candidateOptions ++ return out, comment, options, rest, nil ++ } ++ ++ in = rest ++ continue ++ } ++ ++ return nil, "", nil, nil, errors.New("ssh: no key found") ++} ++ ++// ParsePublicKey parses an SSH public key formatted for use in ++// the SSH wire protocol according to RFC 4253, section 6.6. ++func ParsePublicKey(in []byte) (out PublicKey, err error) { ++ algo, in, ok := parseString(in) ++ if !ok { ++ return nil, errShortRead ++ } ++ var rest []byte ++ out, rest, err = parsePubKey(in, string(algo)) ++ if len(rest) > 0 { ++ return nil, errors.New("ssh: trailing junk in public key") ++ } ++ ++ return out, err ++} ++ ++// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH ++// authorized_keys file. The return value ends with newline. ++func MarshalAuthorizedKey(key PublicKey) []byte { ++ b := &bytes.Buffer{} ++ b.WriteString(key.Type()) ++ b.WriteByte(' ') ++ e := base64.NewEncoder(base64.StdEncoding, b) ++ e.Write(key.Marshal()) ++ e.Close() ++ b.WriteByte('\n') ++ return b.Bytes() ++} ++ ++// PublicKey represents a public key using an unspecified algorithm. ++// ++// Some PublicKeys provided by this package also implement CryptoPublicKey. ++type PublicKey interface { ++ // Type returns the key format name, e.g. "ssh-rsa". ++ Type() string ++ ++ // Marshal returns the serialized key data in SSH wire format, with the name ++ // prefix. To unmarshal the returned data, use the ParsePublicKey function. ++ Marshal() []byte ++ ++ // Verify that sig is a signature on the given data using this key. This ++ // method will hash the data appropriately first. sig.Format is allowed to ++ // be any signature algorithm compatible with the key type, the caller ++ // should check if it has more stringent requirements. ++ Verify(data []byte, sig *Signature) error ++} ++ ++// CryptoPublicKey, if implemented by a PublicKey, ++// returns the underlying crypto.PublicKey form of the key. ++type CryptoPublicKey interface { ++ CryptoPublicKey() crypto.PublicKey ++} ++ ++// A Signer can create signatures that verify against a public key. ++// ++// Some Signers provided by this package also implement AlgorithmSigner. ++type Signer interface { ++ // PublicKey returns the associated PublicKey. ++ PublicKey() PublicKey ++ ++ // Sign returns a signature for the given data. This method will hash the ++ // data appropriately first. The signature algorithm is expected to match ++ // the key format returned by the PublicKey.Type method (and not to be any ++ // alternative algorithm supported by the key format). ++ Sign(rand io.Reader, data []byte) (*Signature, error) ++} ++ ++// An AlgorithmSigner is a Signer that also supports specifying an algorithm to ++// use for signing. ++// ++// An AlgorithmSigner can't advertise the algorithms it supports, so it should ++// be prepared to be invoked with every algorithm supported by the public key ++// format. ++type AlgorithmSigner interface { ++ Signer ++ ++ // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired ++ // signing algorithm. Callers may pass an empty string for the algorithm in ++ // which case the AlgorithmSigner will use a default algorithm. This default ++ // doesn't currently control any behavior in this package. ++ SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) ++} ++ ++type rsaPublicKey rsa.PublicKey ++ ++func (r *rsaPublicKey) Type() string { ++ return "ssh-rsa" ++} ++ ++// parseRSA parses an RSA key according to RFC 4253, section 6.6. ++func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { ++ var w struct { ++ E *big.Int ++ N *big.Int ++ Rest []byte `ssh:"rest"` ++ } ++ if err := Unmarshal(in, &w); err != nil { ++ return nil, nil, err ++ } ++ ++ if w.E.BitLen() > 24 { ++ return nil, nil, errors.New("ssh: exponent too large") ++ } ++ e := w.E.Int64() ++ if e < 3 || e&1 == 0 { ++ return nil, nil, errors.New("ssh: incorrect exponent") ++ } ++ ++ var key rsa.PublicKey ++ key.E = int(e) ++ key.N = w.N ++ return (*rsaPublicKey)(&key), w.Rest, nil ++} ++ ++func (r *rsaPublicKey) Marshal() []byte { ++ e := new(big.Int).SetInt64(int64(r.E)) ++ // RSA publickey struct layout should match the struct used by ++ // parseRSACert in the x/crypto/ssh/agent package. ++ wirekey := struct { ++ Name string ++ E *big.Int ++ N *big.Int ++ }{ ++ KeyAlgoRSA, ++ e, ++ r.N, ++ } ++ return Marshal(&wirekey) ++} ++ ++func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { ++ supportedAlgos := algorithmsForKeyFormat(r.Type()) ++ if !contains(supportedAlgos, sig.Format) { ++ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) ++ } ++ hash := hashFuncs[sig.Format] ++ h := hash.New() ++ h.Write(data) ++ digest := h.Sum(nil) ++ return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, sig.Blob) ++} ++ ++func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey { ++ return (*rsa.PublicKey)(r) ++} ++ ++type dsaPublicKey dsa.PublicKey ++ ++func (k *dsaPublicKey) Type() string { ++ return "ssh-dss" ++} ++ ++func checkDSAParams(param *dsa.Parameters) error { ++ // SSH specifies FIPS 186-2, which only provided a single size ++ // (1024 bits) DSA key. FIPS 186-3 allows for larger key ++ // sizes, which would confuse SSH. ++ if l := param.P.BitLen(); l != 1024 { ++ return fmt.Errorf("ssh: unsupported DSA key size %d", l) ++ } ++ ++ return nil ++} ++ ++// parseDSA parses an DSA key according to RFC 4253, section 6.6. ++func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { ++ var w struct { ++ P, Q, G, Y *big.Int ++ Rest []byte `ssh:"rest"` ++ } ++ if err := Unmarshal(in, &w); err != nil { ++ return nil, nil, err ++ } ++ ++ param := dsa.Parameters{ ++ P: w.P, ++ Q: w.Q, ++ G: w.G, ++ } ++ if err := checkDSAParams(¶m); err != nil { ++ return nil, nil, err ++ } ++ ++ key := &dsaPublicKey{ ++ Parameters: param, ++ Y: w.Y, ++ } ++ return key, w.Rest, nil ++} ++ ++func (k *dsaPublicKey) Marshal() []byte { ++ // DSA publickey struct layout should match the struct used by ++ // parseDSACert in the x/crypto/ssh/agent package. ++ w := struct { ++ Name string ++ P, Q, G, Y *big.Int ++ }{ ++ k.Type(), ++ k.P, ++ k.Q, ++ k.G, ++ k.Y, ++ } ++ ++ return Marshal(&w) ++} ++ ++func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { ++ if sig.Format != k.Type() { ++ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) ++ } ++ h := hashFuncs[sig.Format].New() ++ h.Write(data) ++ digest := h.Sum(nil) ++ ++ // Per RFC 4253, section 6.6, ++ // The value for 'dss_signature_blob' is encoded as a string containing ++ // r, followed by s (which are 160-bit integers, without lengths or ++ // padding, unsigned, and in network byte order). ++ // For DSS purposes, sig.Blob should be exactly 40 bytes in length. ++ if len(sig.Blob) != 40 { ++ return errors.New("ssh: DSA signature parse error") ++ } ++ r := new(big.Int).SetBytes(sig.Blob[:20]) ++ s := new(big.Int).SetBytes(sig.Blob[20:]) ++ if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { ++ return nil ++ } ++ return errors.New("ssh: signature did not verify") ++} ++ ++func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey { ++ return (*dsa.PublicKey)(k) ++} ++ ++type dsaPrivateKey struct { ++ *dsa.PrivateKey ++} ++ ++func (k *dsaPrivateKey) PublicKey() PublicKey { ++ return (*dsaPublicKey)(&k.PrivateKey.PublicKey) ++} ++ ++func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { ++ return k.SignWithAlgorithm(rand, data, k.PublicKey().Type()) ++} ++ ++func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { ++ if algorithm != "" && algorithm != k.PublicKey().Type() { ++ return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) ++ } ++ ++ h := hashFuncs[k.PublicKey().Type()].New() ++ h.Write(data) ++ digest := h.Sum(nil) ++ r, s, err := dsa.Sign(rand, k.PrivateKey, digest) ++ if err != nil { ++ return nil, err ++ } ++ ++ sig := make([]byte, 40) ++ rb := r.Bytes() ++ sb := s.Bytes() ++ ++ copy(sig[20-len(rb):20], rb) ++ copy(sig[40-len(sb):], sb) ++ ++ return &Signature{ ++ Format: k.PublicKey().Type(), ++ Blob: sig, ++ }, nil ++} ++ ++type ecdsaPublicKey ecdsa.PublicKey ++ ++func (k *ecdsaPublicKey) Type() string { ++ return "ecdsa-sha2-" + k.nistID() ++} ++ ++func (k *ecdsaPublicKey) nistID() string { ++ switch k.Params().BitSize { ++ case 256: ++ return "nistp256" ++ case 384: ++ return "nistp384" ++ case 521: ++ return "nistp521" ++ } ++ panic("ssh: unsupported ecdsa key size") ++} ++ ++type ed25519PublicKey ed25519.PublicKey ++ ++func (k ed25519PublicKey) Type() string { ++ return KeyAlgoED25519 ++} ++ ++func parseED25519(in []byte) (out PublicKey, rest []byte, err error) { ++ var w struct { ++ KeyBytes []byte ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if err := Unmarshal(in, &w); err != nil { ++ return nil, nil, err ++ } ++ ++ if l := len(w.KeyBytes); l != ed25519.PublicKeySize { ++ return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) ++ } ++ ++ return ed25519PublicKey(w.KeyBytes), w.Rest, nil ++} ++ ++func (k ed25519PublicKey) Marshal() []byte { ++ w := struct { ++ Name string ++ KeyBytes []byte ++ }{ ++ KeyAlgoED25519, ++ []byte(k), ++ } ++ return Marshal(&w) ++} ++ ++func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error { ++ if sig.Format != k.Type() { ++ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) ++ } ++ if l := len(k); l != ed25519.PublicKeySize { ++ return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) ++ } ++ ++ if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok { ++ return errors.New("ssh: signature did not verify") ++ } ++ ++ return nil ++} ++ ++func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey { ++ return ed25519.PublicKey(k) ++} ++ ++func supportedEllipticCurve(curve elliptic.Curve) bool { ++ return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() ++} ++ ++// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. ++func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { ++ var w struct { ++ Curve string ++ KeyBytes []byte ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if err := Unmarshal(in, &w); err != nil { ++ return nil, nil, err ++ } ++ ++ key := new(ecdsa.PublicKey) ++ ++ switch w.Curve { ++ case "nistp256": ++ key.Curve = elliptic.P256() ++ case "nistp384": ++ key.Curve = elliptic.P384() ++ case "nistp521": ++ key.Curve = elliptic.P521() ++ default: ++ return nil, nil, errors.New("ssh: unsupported curve") ++ } ++ ++ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) ++ if key.X == nil || key.Y == nil { ++ return nil, nil, errors.New("ssh: invalid curve point") ++ } ++ return (*ecdsaPublicKey)(key), w.Rest, nil ++} ++ ++func (k *ecdsaPublicKey) Marshal() []byte { ++ // See RFC 5656, section 3.1. ++ keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) ++ // ECDSA publickey struct layout should match the struct used by ++ // parseECDSACert in the x/crypto/ssh/agent package. ++ w := struct { ++ Name string ++ ID string ++ Key []byte ++ }{ ++ k.Type(), ++ k.nistID(), ++ keyBytes, ++ } ++ ++ return Marshal(&w) ++} ++ ++func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { ++ if sig.Format != k.Type() { ++ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) ++ } ++ ++ h := hashFuncs[sig.Format].New() ++ h.Write(data) ++ digest := h.Sum(nil) ++ ++ // Per RFC 5656, section 3.1.2, ++ // The ecdsa_signature_blob value has the following specific encoding: ++ // mpint r ++ // mpint s ++ var ecSig struct { ++ R *big.Int ++ S *big.Int ++ } ++ ++ if err := Unmarshal(sig.Blob, &ecSig); err != nil { ++ return err ++ } ++ ++ if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) { ++ return nil ++ } ++ return errors.New("ssh: signature did not verify") ++} ++ ++func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey { ++ return (*ecdsa.PublicKey)(k) ++} ++ ++// skFields holds the additional fields present in U2F/FIDO2 signatures. ++// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details. ++type skFields struct { ++ // Flags contains U2F/FIDO2 flags such as 'user present' ++ Flags byte ++ // Counter is a monotonic signature counter which can be ++ // used to detect concurrent use of a private key, should ++ // it be extracted from hardware. ++ Counter uint32 ++} ++ ++type skECDSAPublicKey struct { ++ // application is a URL-like string, typically "ssh:" for SSH. ++ // see openssh/PROTOCOL.u2f for details. ++ application string ++ ecdsa.PublicKey ++} ++ ++func (k *skECDSAPublicKey) Type() string { ++ return KeyAlgoSKECDSA256 ++} ++ ++func (k *skECDSAPublicKey) nistID() string { ++ return "nistp256" ++} ++ ++func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) { ++ var w struct { ++ Curve string ++ KeyBytes []byte ++ Application string ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if err := Unmarshal(in, &w); err != nil { ++ return nil, nil, err ++ } ++ ++ key := new(skECDSAPublicKey) ++ key.application = w.Application ++ ++ if w.Curve != "nistp256" { ++ return nil, nil, errors.New("ssh: unsupported curve") ++ } ++ key.Curve = elliptic.P256() ++ ++ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) ++ if key.X == nil || key.Y == nil { ++ return nil, nil, errors.New("ssh: invalid curve point") ++ } ++ ++ return key, w.Rest, nil ++} ++ ++func (k *skECDSAPublicKey) Marshal() []byte { ++ // See RFC 5656, section 3.1. ++ keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) ++ w := struct { ++ Name string ++ ID string ++ Key []byte ++ Application string ++ }{ ++ k.Type(), ++ k.nistID(), ++ keyBytes, ++ k.application, ++ } ++ ++ return Marshal(&w) ++} ++ ++func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error { ++ if sig.Format != k.Type() { ++ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) ++ } ++ ++ h := hashFuncs[sig.Format].New() ++ h.Write([]byte(k.application)) ++ appDigest := h.Sum(nil) ++ ++ h.Reset() ++ h.Write(data) ++ dataDigest := h.Sum(nil) ++ ++ var ecSig struct { ++ R *big.Int ++ S *big.Int ++ } ++ if err := Unmarshal(sig.Blob, &ecSig); err != nil { ++ return err ++ } ++ ++ var skf skFields ++ if err := Unmarshal(sig.Rest, &skf); err != nil { ++ return err ++ } ++ ++ blob := struct { ++ ApplicationDigest []byte `ssh:"rest"` ++ Flags byte ++ Counter uint32 ++ MessageDigest []byte `ssh:"rest"` ++ }{ ++ appDigest, ++ skf.Flags, ++ skf.Counter, ++ dataDigest, ++ } ++ ++ original := Marshal(blob) ++ ++ h.Reset() ++ h.Write(original) ++ digest := h.Sum(nil) ++ ++ if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) { ++ return nil ++ } ++ return errors.New("ssh: signature did not verify") ++} ++ ++type skEd25519PublicKey struct { ++ // application is a URL-like string, typically "ssh:" for SSH. ++ // see openssh/PROTOCOL.u2f for details. ++ application string ++ ed25519.PublicKey ++} ++ ++func (k *skEd25519PublicKey) Type() string { ++ return KeyAlgoSKED25519 ++} ++ ++func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) { ++ var w struct { ++ KeyBytes []byte ++ Application string ++ Rest []byte `ssh:"rest"` ++ } ++ ++ if err := Unmarshal(in, &w); err != nil { ++ return nil, nil, err ++ } ++ ++ if l := len(w.KeyBytes); l != ed25519.PublicKeySize { ++ return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) ++ } ++ ++ key := new(skEd25519PublicKey) ++ key.application = w.Application ++ key.PublicKey = ed25519.PublicKey(w.KeyBytes) ++ ++ return key, w.Rest, nil ++} ++ ++func (k *skEd25519PublicKey) Marshal() []byte { ++ w := struct { ++ Name string ++ KeyBytes []byte ++ Application string ++ }{ ++ KeyAlgoSKED25519, ++ []byte(k.PublicKey), ++ k.application, ++ } ++ return Marshal(&w) ++} ++ ++func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error { ++ if sig.Format != k.Type() { ++ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) ++ } ++ if l := len(k.PublicKey); l != ed25519.PublicKeySize { ++ return fmt.Errorf("invalid size %d for Ed25519 public key", l) ++ } ++ ++ h := hashFuncs[sig.Format].New() ++ h.Write([]byte(k.application)) ++ appDigest := h.Sum(nil) ++ ++ h.Reset() ++ h.Write(data) ++ dataDigest := h.Sum(nil) ++ ++ var edSig struct { ++ Signature []byte `ssh:"rest"` ++ } ++ ++ if err := Unmarshal(sig.Blob, &edSig); err != nil { ++ return err ++ } ++ ++ var skf skFields ++ if err := Unmarshal(sig.Rest, &skf); err != nil { ++ return err ++ } ++ ++ blob := struct { ++ ApplicationDigest []byte `ssh:"rest"` ++ Flags byte ++ Counter uint32 ++ MessageDigest []byte `ssh:"rest"` ++ }{ ++ appDigest, ++ skf.Flags, ++ skf.Counter, ++ dataDigest, ++ } ++ ++ original := Marshal(blob) ++ ++ if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok { ++ return errors.New("ssh: signature did not verify") ++ } ++ ++ return nil ++} ++ ++// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, ++// *ecdsa.PrivateKey or any other crypto.Signer and returns a ++// corresponding Signer instance. ECDSA keys must use P-256, P-384 or ++// P-521. DSA keys must use parameter size L1024N160. ++func NewSignerFromKey(key interface{}) (Signer, error) { ++ switch key := key.(type) { ++ case crypto.Signer: ++ return NewSignerFromSigner(key) ++ case *dsa.PrivateKey: ++ return newDSAPrivateKey(key) ++ default: ++ return nil, fmt.Errorf("ssh: unsupported key type %T", key) ++ } ++} ++ ++func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) { ++ if err := checkDSAParams(&key.PublicKey.Parameters); err != nil { ++ return nil, err ++ } ++ ++ return &dsaPrivateKey{key}, nil ++} ++ ++type wrappedSigner struct { ++ signer crypto.Signer ++ pubKey PublicKey ++} ++ ++// NewSignerFromSigner takes any crypto.Signer implementation and ++// returns a corresponding Signer interface. This can be used, for ++// example, with keys kept in hardware modules. ++func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { ++ pubKey, err := NewPublicKey(signer.Public()) ++ if err != nil { ++ return nil, err ++ } ++ ++ return &wrappedSigner{signer, pubKey}, nil ++} ++ ++func (s *wrappedSigner) PublicKey() PublicKey { ++ return s.pubKey ++} ++ ++func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { ++ return s.SignWithAlgorithm(rand, data, s.pubKey.Type()) ++} ++ ++func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { ++ if algorithm == "" { ++ algorithm = s.pubKey.Type() ++ } ++ ++ supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type()) ++ if !contains(supportedAlgos, algorithm) { ++ return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type()) ++ } ++ ++ hashFunc := hashFuncs[algorithm] ++ var digest []byte ++ if hashFunc != 0 { ++ h := hashFunc.New() ++ h.Write(data) ++ digest = h.Sum(nil) ++ } else { ++ digest = data ++ } ++ ++ signature, err := s.signer.Sign(rand, digest, hashFunc) ++ if err != nil { ++ return nil, err ++ } ++ ++ // crypto.Signer.Sign is expected to return an ASN.1-encoded signature ++ // for ECDSA and DSA, but that's not the encoding expected by SSH, so ++ // re-encode. ++ switch s.pubKey.(type) { ++ case *ecdsaPublicKey, *dsaPublicKey: ++ type asn1Signature struct { ++ R, S *big.Int ++ } ++ asn1Sig := new(asn1Signature) ++ _, err := asn1.Unmarshal(signature, asn1Sig) ++ if err != nil { ++ return nil, err ++ } ++ ++ switch s.pubKey.(type) { ++ case *ecdsaPublicKey: ++ signature = Marshal(asn1Sig) ++ ++ case *dsaPublicKey: ++ signature = make([]byte, 40) ++ r := asn1Sig.R.Bytes() ++ s := asn1Sig.S.Bytes() ++ copy(signature[20-len(r):20], r) ++ copy(signature[40-len(s):40], s) ++ } ++ } ++ ++ return &Signature{ ++ Format: algorithm, ++ Blob: signature, ++ }, nil ++} ++ ++// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ++// or ed25519.PublicKey returns a corresponding PublicKey instance. ++// ECDSA keys must use P-256, P-384 or P-521. ++func NewPublicKey(key interface{}) (PublicKey, error) { ++ switch key := key.(type) { ++ case *rsa.PublicKey: ++ return (*rsaPublicKey)(key), nil ++ case *ecdsa.PublicKey: ++ if !supportedEllipticCurve(key.Curve) { ++ return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported") ++ } ++ return (*ecdsaPublicKey)(key), nil ++ case *dsa.PublicKey: ++ return (*dsaPublicKey)(key), nil ++ case ed25519.PublicKey: ++ if l := len(key); l != ed25519.PublicKeySize { ++ return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) ++ } ++ return ed25519PublicKey(key), nil ++ default: ++ return nil, fmt.Errorf("ssh: unsupported key type %T", key) ++ } ++} ++ ++// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports ++// the same keys as ParseRawPrivateKey. If the private key is encrypted, it ++// will return a PassphraseMissingError. ++func ParsePrivateKey(pemBytes []byte) (Signer, error) { ++ key, err := ParseRawPrivateKey(pemBytes) ++ if err != nil { ++ return nil, err ++ } ++ ++ return NewSignerFromKey(key) ++} ++ ++// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private ++// key and passphrase. It supports the same keys as ++// ParseRawPrivateKeyWithPassphrase. ++func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) { ++ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase) ++ if err != nil { ++ return nil, err ++ } ++ ++ return NewSignerFromKey(key) ++} ++ ++// encryptedBlock tells whether a private key is ++// encrypted by examining its Proc-Type header ++// for a mention of ENCRYPTED ++// according to RFC 1421 Section 4.6.1.1. ++func encryptedBlock(block *pem.Block) bool { ++ return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") ++} ++ ++// A PassphraseMissingError indicates that parsing this private key requires a ++// passphrase. Use ParsePrivateKeyWithPassphrase. ++type PassphraseMissingError struct { ++ // PublicKey will be set if the private key format includes an unencrypted ++ // public key along with the encrypted private key. ++ PublicKey PublicKey ++} ++ ++func (*PassphraseMissingError) Error() string { ++ return "ssh: this private key is passphrase protected" ++} ++ ++// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports ++// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH ++// formats. If the private key is encrypted, it will return a PassphraseMissingError. ++func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { ++ block, _ := pem.Decode(pemBytes) ++ if block == nil { ++ return nil, errors.New("ssh: no key found") ++ } ++ ++ if encryptedBlock(block) { ++ return nil, &PassphraseMissingError{} ++ } ++ ++ switch block.Type { ++ case "RSA PRIVATE KEY": ++ return x509.ParsePKCS1PrivateKey(block.Bytes) ++ // RFC5208 - https://tools.ietf.org/html/rfc5208 ++ case "PRIVATE KEY": ++ return x509.ParsePKCS8PrivateKey(block.Bytes) ++ case "EC PRIVATE KEY": ++ return x509.ParseECPrivateKey(block.Bytes) ++ case "DSA PRIVATE KEY": ++ return ParseDSAPrivateKey(block.Bytes) ++ case "OPENSSH PRIVATE KEY": ++ return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey) ++ default: ++ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) ++ } ++} ++ ++// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with ++// passphrase from a PEM encoded private key. If the passphrase is wrong, it ++// will return x509.IncorrectPasswordError. ++func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) { ++ block, _ := pem.Decode(pemBytes) ++ if block == nil { ++ return nil, errors.New("ssh: no key found") ++ } ++ ++ if block.Type == "OPENSSH PRIVATE KEY" { ++ return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase)) ++ } ++ ++ if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) { ++ return nil, errors.New("ssh: not an encrypted key") ++ } ++ ++ buf, err := x509.DecryptPEMBlock(block, passphrase) ++ if err != nil { ++ if err == x509.IncorrectPasswordError { ++ return nil, err ++ } ++ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err) ++ } ++ ++ switch block.Type { ++ case "RSA PRIVATE KEY": ++ return x509.ParsePKCS1PrivateKey(buf) ++ case "EC PRIVATE KEY": ++ return x509.ParseECPrivateKey(buf) ++ case "DSA PRIVATE KEY": ++ return ParseDSAPrivateKey(buf) ++ default: ++ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) ++ } ++} ++ ++// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as ++// specified by the OpenSSL DSA man page. ++func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { ++ var k struct { ++ Version int ++ P *big.Int ++ Q *big.Int ++ G *big.Int ++ Pub *big.Int ++ Priv *big.Int ++ } ++ rest, err := asn1.Unmarshal(der, &k) ++ if err != nil { ++ return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) ++ } ++ if len(rest) > 0 { ++ return nil, errors.New("ssh: garbage after DSA key") ++ } ++ ++ return &dsa.PrivateKey{ ++ PublicKey: dsa.PublicKey{ ++ Parameters: dsa.Parameters{ ++ P: k.P, ++ Q: k.Q, ++ G: k.G, ++ }, ++ Y: k.Pub, ++ }, ++ X: k.Priv, ++ }, nil ++} ++ ++func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { ++ if kdfName != "none" || cipherName != "none" { ++ return nil, &PassphraseMissingError{} ++ } ++ if kdfOpts != "" { ++ return nil, errors.New("ssh: invalid openssh private key") ++ } ++ return privKeyBlock, nil ++} ++ ++func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc { ++ return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { ++ if kdfName == "none" || cipherName == "none" { ++ return nil, errors.New("ssh: key is not password protected") ++ } ++ if kdfName != "bcrypt" { ++ return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt") ++ } ++ ++ var opts struct { ++ Salt string ++ Rounds uint32 ++ } ++ if err := Unmarshal([]byte(kdfOpts), &opts); err != nil { ++ return nil, err ++ } ++ ++ k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16) ++ if err != nil { ++ return nil, err ++ } ++ key, iv := k[:32], k[32:] ++ ++ c, err := aes.NewCipher(key) ++ if err != nil { ++ return nil, err ++ } ++ switch cipherName { ++ case "aes256-ctr": ++ ctr := cipher.NewCTR(c, iv) ++ ctr.XORKeyStream(privKeyBlock, privKeyBlock) ++ case "aes256-cbc": ++ if len(privKeyBlock)%c.BlockSize() != 0 { ++ return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size") ++ } ++ cbc := cipher.NewCBCDecrypter(c, iv) ++ cbc.CryptBlocks(privKeyBlock, privKeyBlock) ++ default: ++ return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc") ++ } ++ ++ return privKeyBlock, nil ++ } ++} ++ ++type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error) ++ ++// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt ++// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used ++// as the decrypt function to parse an unencrypted private key. See ++// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key. ++func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) { ++ const magic = "openssh-key-v1\x00" ++ if len(key) < len(magic) || string(key[:len(magic)]) != magic { ++ return nil, errors.New("ssh: invalid openssh private key format") ++ } ++ remaining := key[len(magic):] ++ ++ var w struct { ++ CipherName string ++ KdfName string ++ KdfOpts string ++ NumKeys uint32 ++ PubKey []byte ++ PrivKeyBlock []byte ++ } ++ ++ if err := Unmarshal(remaining, &w); err != nil { ++ return nil, err ++ } ++ if w.NumKeys != 1 { ++ // We only support single key files, and so does OpenSSH. ++ // https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171 ++ return nil, errors.New("ssh: multi-key files are not supported") ++ } ++ ++ privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock) ++ if err != nil { ++ if err, ok := err.(*PassphraseMissingError); ok { ++ pub, errPub := ParsePublicKey(w.PubKey) ++ if errPub != nil { ++ return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub) ++ } ++ err.PublicKey = pub ++ } ++ return nil, err ++ } ++ ++ pk1 := struct { ++ Check1 uint32 ++ Check2 uint32 ++ Keytype string ++ Rest []byte `ssh:"rest"` ++ }{} ++ ++ if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 { ++ if w.CipherName != "none" { ++ return nil, x509.IncorrectPasswordError ++ } ++ return nil, errors.New("ssh: malformed OpenSSH key") ++ } ++ ++ switch pk1.Keytype { ++ case KeyAlgoRSA: ++ // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 ++ key := struct { ++ N *big.Int ++ E *big.Int ++ D *big.Int ++ Iqmp *big.Int ++ P *big.Int ++ Q *big.Int ++ Comment string ++ Pad []byte `ssh:"rest"` ++ }{} ++ ++ if err := Unmarshal(pk1.Rest, &key); err != nil { ++ return nil, err ++ } ++ ++ if err := checkOpenSSHKeyPadding(key.Pad); err != nil { ++ return nil, err ++ } ++ ++ pk := &rsa.PrivateKey{ ++ PublicKey: rsa.PublicKey{ ++ N: key.N, ++ E: int(key.E.Int64()), ++ }, ++ D: key.D, ++ Primes: []*big.Int{key.P, key.Q}, ++ } ++ ++ if err := pk.Validate(); err != nil { ++ return nil, err ++ } ++ ++ pk.Precompute() ++ ++ return pk, nil ++ case KeyAlgoED25519: ++ key := struct { ++ Pub []byte ++ Priv []byte ++ Comment string ++ Pad []byte `ssh:"rest"` ++ }{} ++ ++ if err := Unmarshal(pk1.Rest, &key); err != nil { ++ return nil, err ++ } ++ ++ if len(key.Priv) != ed25519.PrivateKeySize { ++ return nil, errors.New("ssh: private key unexpected length") ++ } ++ ++ if err := checkOpenSSHKeyPadding(key.Pad); err != nil { ++ return nil, err ++ } ++ ++ pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) ++ copy(pk, key.Priv) ++ return &pk, nil ++ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: ++ key := struct { ++ Curve string ++ Pub []byte ++ D *big.Int ++ Comment string ++ Pad []byte `ssh:"rest"` ++ }{} ++ ++ if err := Unmarshal(pk1.Rest, &key); err != nil { ++ return nil, err ++ } ++ ++ if err := checkOpenSSHKeyPadding(key.Pad); err != nil { ++ return nil, err ++ } ++ ++ var curve elliptic.Curve ++ switch key.Curve { ++ case "nistp256": ++ curve = elliptic.P256() ++ case "nistp384": ++ curve = elliptic.P384() ++ case "nistp521": ++ curve = elliptic.P521() ++ default: ++ return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve) ++ } ++ ++ X, Y := elliptic.Unmarshal(curve, key.Pub) ++ if X == nil || Y == nil { ++ return nil, errors.New("ssh: failed to unmarshal public key") ++ } ++ ++ if key.D.Cmp(curve.Params().N) >= 0 { ++ return nil, errors.New("ssh: scalar is out of range") ++ } ++ ++ x, y := curve.ScalarBaseMult(key.D.Bytes()) ++ if x.Cmp(X) != 0 || y.Cmp(Y) != 0 { ++ return nil, errors.New("ssh: public key does not match private key") ++ } ++ ++ return &ecdsa.PrivateKey{ ++ PublicKey: ecdsa.PublicKey{ ++ Curve: curve, ++ X: X, ++ Y: Y, ++ }, ++ D: key.D, ++ }, nil ++ default: ++ return nil, errors.New("ssh: unhandled key type") ++ } ++} ++ ++func checkOpenSSHKeyPadding(pad []byte) error { ++ for i, b := range pad { ++ if int(b) != i+1 { ++ return errors.New("ssh: padding not as expected") ++ } ++ } ++ return nil ++} ++ ++// FingerprintLegacyMD5 returns the user presentation of the key's ++// fingerprint as described by RFC 4716 section 4. ++func FingerprintLegacyMD5(pubKey PublicKey) string { ++ md5sum := md5.Sum(pubKey.Marshal()) ++ hexarray := make([]string, len(md5sum)) ++ for i, c := range md5sum { ++ hexarray[i] = hex.EncodeToString([]byte{c}) ++ } ++ return strings.Join(hexarray, ":") ++} ++ ++// FingerprintSHA256 returns the user presentation of the key's ++// fingerprint as unpadded base64 encoded sha256 hash. ++// This format was introduced from OpenSSH 6.8. ++// https://www.openssh.com/txt/release-6.8 ++// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding) ++func FingerprintSHA256(pubKey PublicKey) string { ++ sha256sum := sha256.Sum256(pubKey.Marshal()) ++ hash := base64.RawStdEncoding.EncodeToString(sha256sum[:]) ++ return "SHA256:" + hash ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/keys_test.go b/ms_mod/golang.org/x/crypto/ssh/keys_test.go +new file mode 100644 +index 00000000000000..334ef7453266db +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/keys_test.go +@@ -0,0 +1,618 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto/dsa" ++ "crypto/ecdsa" ++ "crypto/elliptic" ++ "crypto/rand" ++ "crypto/rsa" ++ "crypto/x509" ++ "encoding/base64" ++ "encoding/hex" ++ "encoding/pem" ++ "fmt" ++ "io" ++ "reflect" ++ "strings" ++ "testing" ++ ++ "golang.org/x/crypto/ed25519" ++ "golang.org/x/crypto/ssh/testdata" ++) ++ ++func rawKey(pub PublicKey) interface{} { ++ switch k := pub.(type) { ++ case *rsaPublicKey: ++ return (*rsa.PublicKey)(k) ++ case *dsaPublicKey: ++ return (*dsa.PublicKey)(k) ++ case *ecdsaPublicKey: ++ return (*ecdsa.PublicKey)(k) ++ case ed25519PublicKey: ++ return (ed25519.PublicKey)(k) ++ case *Certificate: ++ return k ++ } ++ panic("unknown key type") ++} ++ ++func TestKeyMarshalParse(t *testing.T) { ++ for _, priv := range testSigners { ++ pub := priv.PublicKey() ++ roundtrip, err := ParsePublicKey(pub.Marshal()) ++ if err != nil { ++ t.Errorf("ParsePublicKey(%T): %v", pub, err) ++ } ++ ++ k1 := rawKey(pub) ++ k2 := rawKey(roundtrip) ++ ++ if !reflect.DeepEqual(k1, k2) { ++ t.Errorf("got %#v in roundtrip, want %#v", k2, k1) ++ } ++ } ++} ++ ++func TestUnsupportedCurves(t *testing.T) { ++ raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) ++ if err != nil { ++ t.Fatalf("GenerateKey: %v", err) ++ } ++ ++ if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") { ++ t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err) ++ } ++ ++ if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") { ++ t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err) ++ } ++} ++ ++func TestNewPublicKey(t *testing.T) { ++ for _, k := range testSigners { ++ raw := rawKey(k.PublicKey()) ++ // Skip certificates, as NewPublicKey does not support them. ++ if _, ok := raw.(*Certificate); ok { ++ continue ++ } ++ pub, err := NewPublicKey(raw) ++ if err != nil { ++ t.Errorf("NewPublicKey(%#v): %v", raw, err) ++ } ++ if !reflect.DeepEqual(k.PublicKey(), pub) { ++ t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey()) ++ } ++ } ++} ++ ++func TestKeySignVerify(t *testing.T) { ++ for _, priv := range testSigners { ++ pub := priv.PublicKey() ++ ++ data := []byte("sign me") ++ sig, err := priv.Sign(rand.Reader, data) ++ if err != nil { ++ t.Fatalf("Sign(%T): %v", priv, err) ++ } ++ ++ if err := pub.Verify(data, sig); err != nil { ++ t.Errorf("publicKey.Verify(%T): %v", priv, err) ++ } ++ sig.Blob[5]++ ++ if err := pub.Verify(data, sig); err == nil { ++ t.Errorf("publicKey.Verify on broken sig did not fail") ++ } ++ } ++} ++ ++func TestKeySignWithAlgorithmVerify(t *testing.T) { ++ for _, priv := range testSigners { ++ if algorithmSigner, ok := priv.(AlgorithmSigner); !ok { ++ t.Errorf("Signers constructed by ssh package should always implement the AlgorithmSigner interface: %T", priv) ++ } else { ++ pub := priv.PublicKey() ++ data := []byte("sign me") ++ ++ signWithAlgTestCase := func(algorithm string, expectedAlg string) { ++ sig, err := algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm) ++ if err != nil { ++ t.Fatalf("Sign(%T): %v", priv, err) ++ } ++ if sig.Format != expectedAlg { ++ t.Errorf("signature format did not match requested signature algorithm: %s != %s", sig.Format, expectedAlg) ++ } ++ ++ if err := pub.Verify(data, sig); err != nil { ++ t.Errorf("publicKey.Verify(%T): %v", priv, err) ++ } ++ sig.Blob[5]++ ++ if err := pub.Verify(data, sig); err == nil { ++ t.Errorf("publicKey.Verify on broken sig did not fail") ++ } ++ } ++ ++ // Using the empty string as the algorithm name should result in the same signature format as the algorithm-free Sign method. ++ defaultSig, err := priv.Sign(rand.Reader, data) ++ if err != nil { ++ t.Fatalf("Sign(%T): %v", priv, err) ++ } ++ signWithAlgTestCase("", defaultSig.Format) ++ ++ // RSA keys are the only ones which currently support more than one signing algorithm ++ if pub.Type() == KeyAlgoRSA { ++ for _, algorithm := range []string{KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512} { ++ signWithAlgTestCase(algorithm, algorithm) ++ } ++ } ++ } ++ } ++} ++ ++func TestParseRSAPrivateKey(t *testing.T) { ++ key := testPrivateKeys["rsa"] ++ ++ rsa, ok := key.(*rsa.PrivateKey) ++ if !ok { ++ t.Fatalf("got %T, want *rsa.PrivateKey", rsa) ++ } ++ ++ if err := rsa.Validate(); err != nil { ++ t.Errorf("Validate: %v", err) ++ } ++} ++ ++func TestParseECPrivateKey(t *testing.T) { ++ key := testPrivateKeys["ecdsa"] ++ ++ ecKey, ok := key.(*ecdsa.PrivateKey) ++ if !ok { ++ t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey) ++ } ++ ++ if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) { ++ t.Fatalf("public key does not validate.") ++ } ++} ++ ++func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) { ++ data := []byte("sign me") ++ for _, tt := range testdata.PEMEncryptedKeys { ++ t.Run(tt.Name, func(t *testing.T) { ++ _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect")) ++ if err != x509.IncorrectPasswordError { ++ t.Errorf("got %v want IncorrectPasswordError", err) ++ } ++ ++ s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) ++ if err != nil { ++ t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err) ++ } ++ ++ sig, err := s.Sign(rand.Reader, data) ++ if err != nil { ++ t.Fatalf("Signer.Sign: %v", err) ++ } ++ if err := s.PublicKey().Verify(data, sig); err != nil { ++ t.Errorf("Verify failed: %v", err) ++ } ++ ++ _, err = ParsePrivateKey(tt.PEMBytes) ++ if err == nil { ++ t.Fatalf("ParsePrivateKey succeeded, expected an error") ++ } ++ ++ if err, ok := err.(*PassphraseMissingError); !ok { ++ t.Errorf("got error %q, want PassphraseMissingError", err) ++ } else if tt.IncludesPublicKey { ++ if err.PublicKey == nil { ++ t.Fatalf("expected PassphraseMissingError.PublicKey not to be nil") ++ } ++ got, want := err.PublicKey.Marshal(), s.PublicKey().Marshal() ++ if !bytes.Equal(got, want) { ++ t.Errorf("error field %q doesn't match signer public key %q", got, want) ++ } ++ } ++ }) ++ } ++} ++ ++func TestParseDSA(t *testing.T) { ++ // We actually exercise the ParsePrivateKey codepath here, as opposed to ++ // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go ++ // uses. ++ s, err := ParsePrivateKey(testdata.PEMBytes["dsa"]) ++ if err != nil { ++ t.Fatalf("ParsePrivateKey returned error: %s", err) ++ } ++ ++ data := []byte("sign me") ++ sig, err := s.Sign(rand.Reader, data) ++ if err != nil { ++ t.Fatalf("dsa.Sign: %v", err) ++ } ++ ++ if err := s.PublicKey().Verify(data, sig); err != nil { ++ t.Errorf("Verify failed: %v", err) ++ } ++} ++ ++// Tests for authorized_keys parsing. ++ ++// getTestKey returns a public key, and its base64 encoding. ++func getTestKey() (PublicKey, string) { ++ k := testPublicKeys["rsa"] ++ ++ b := &bytes.Buffer{} ++ e := base64.NewEncoder(base64.StdEncoding, b) ++ e.Write(k.Marshal()) ++ e.Close() ++ ++ return k, b.String() ++} ++ ++func TestMarshalParsePublicKey(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized) ++ ++ authKeys := MarshalAuthorizedKey(pub) ++ actualFields := strings.Fields(string(authKeys)) ++ if len(actualFields) == 0 { ++ t.Fatalf("failed authKeys: %v", authKeys) ++ } ++ ++ // drop the comment ++ expectedFields := strings.Fields(line)[0:2] ++ ++ if !reflect.DeepEqual(actualFields, expectedFields) { ++ t.Errorf("got %v, expected %v", actualFields, expectedFields) ++ } ++ ++ actPub, _, _, _, err := ParseAuthorizedKey([]byte(line)) ++ if err != nil { ++ t.Fatalf("cannot parse %v: %v", line, err) ++ } ++ if !reflect.DeepEqual(actPub, pub) { ++ t.Errorf("got %v, expected %v", actPub, pub) ++ } ++} ++ ++type testAuthResult struct { ++ pubKey PublicKey ++ options []string ++ comments string ++ rest string ++ ok bool ++} ++ ++func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []testAuthResult) { ++ rest := authKeys ++ var values []testAuthResult ++ for len(rest) > 0 { ++ var r testAuthResult ++ var err error ++ r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) ++ r.ok = (err == nil) ++ t.Log(err) ++ r.rest = string(rest) ++ values = append(values, r) ++ } ++ ++ if !reflect.DeepEqual(values, expected) { ++ t.Errorf("got %#v, expected %#v", values, expected) ++ } ++} ++ ++func TestAuthorizedKeyBasic(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ line := "ssh-rsa " + pubSerialized + " user@host" ++ testAuthorizedKeys(t, []byte(line), ++ []testAuthResult{ ++ {pub, nil, "user@host", "", true}, ++ }) ++} ++ ++func TestAuth(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ authWithOptions := []string{ ++ `# comments to ignore before any keys...`, ++ ``, ++ `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`, ++ `# comments to ignore, along with a blank line`, ++ ``, ++ `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`, ++ ``, ++ `# more comments, plus a invalid entry`, ++ `ssh-rsa data-that-will-not-parse user@host3`, ++ } ++ for _, eol := range []string{"\n", "\r\n"} { ++ authOptions := strings.Join(authWithOptions, eol) ++ rest2 := strings.Join(authWithOptions[3:], eol) ++ rest3 := strings.Join(authWithOptions[6:], eol) ++ testAuthorizedKeys(t, []byte(authOptions), []testAuthResult{ ++ {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, ++ {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, ++ {nil, nil, "", "", false}, ++ }) ++ } ++} ++ ++func TestAuthWithQuotedSpaceInEnv(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) ++ testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []testAuthResult{ ++ {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, ++ }) ++} ++ ++func TestAuthWithQuotedCommaInEnv(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) ++ testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []testAuthResult{ ++ {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, ++ }) ++} ++ ++func TestAuthWithQuotedQuoteInEnv(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) ++ authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) ++ testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []testAuthResult{ ++ {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, ++ }) ++ ++ testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []testAuthResult{ ++ {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, ++ }) ++} ++ ++func TestAuthWithInvalidSpace(t *testing.T) { ++ _, pubSerialized := getTestKey() ++ authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host ++#more to follow but still no valid keys`) ++ testAuthorizedKeys(t, []byte(authWithInvalidSpace), []testAuthResult{ ++ {nil, nil, "", "", false}, ++ }) ++} ++ ++func TestAuthWithMissingQuote(t *testing.T) { ++ pub, pubSerialized := getTestKey() ++ authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host ++env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) ++ ++ testAuthorizedKeys(t, []byte(authWithMissingQuote), []testAuthResult{ ++ {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, ++ }) ++} ++ ++func TestInvalidEntry(t *testing.T) { ++ authInvalid := []byte(`ssh-rsa`) ++ _, _, _, _, err := ParseAuthorizedKey(authInvalid) ++ if err == nil { ++ t.Errorf("got valid entry for %q", authInvalid) ++ } ++} ++ ++var knownHostsParseTests = []struct { ++ input string ++ err string ++ ++ marker string ++ comment string ++ hosts []string ++ rest string ++}{ ++ { ++ "", ++ "EOF", ++ ++ "", "", nil, "", ++ }, ++ { ++ "# Just a comment", ++ "EOF", ++ ++ "", "", nil, "", ++ }, ++ { ++ " \t ", ++ "EOF", ++ ++ "", "", nil, "", ++ }, ++ { ++ "localhost ssh-rsa {RSAPUB}", ++ "", ++ ++ "", "", []string{"localhost"}, "", ++ }, ++ { ++ "localhost\tssh-rsa {RSAPUB}", ++ "", ++ ++ "", "", []string{"localhost"}, "", ++ }, ++ { ++ "localhost\tssh-rsa {RSAPUB}\tcomment comment", ++ "", ++ ++ "", "comment comment", []string{"localhost"}, "", ++ }, ++ { ++ "localhost\tssh-rsa {RSAPUB}\tcomment comment\n", ++ "", ++ ++ "", "comment comment", []string{"localhost"}, "", ++ }, ++ { ++ "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n", ++ "", ++ ++ "", "comment comment", []string{"localhost"}, "", ++ }, ++ { ++ "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line", ++ "", ++ ++ "", "comment comment", []string{"localhost"}, "next line", ++ }, ++ { ++ "localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment", ++ "", ++ ++ "", "comment comment", []string{"localhost", "[host2:123]"}, "", ++ }, ++ { ++ "@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}", ++ "", ++ ++ "marker", "", []string{"localhost", "[host2:123]"}, "", ++ }, ++ { ++ "@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd", ++ "short read", ++ ++ "", "", nil, "", ++ }, ++} ++ ++func TestKnownHostsParsing(t *testing.T) { ++ rsaPub, rsaPubSerialized := getTestKey() ++ ++ for i, test := range knownHostsParseTests { ++ var expectedKey PublicKey ++ const rsaKeyToken = "{RSAPUB}" ++ ++ input := test.input ++ if strings.Contains(input, rsaKeyToken) { ++ expectedKey = rsaPub ++ input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1) ++ } ++ ++ marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input)) ++ if err != nil { ++ if len(test.err) == 0 { ++ t.Errorf("#%d: unexpectedly failed with %q", i, err) ++ } else if !strings.Contains(err.Error(), test.err) { ++ t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err) ++ } ++ continue ++ } else if len(test.err) != 0 { ++ t.Errorf("#%d: succeeded but expected error including %q", i, test.err) ++ continue ++ } ++ ++ if !reflect.DeepEqual(expectedKey, pubKey) { ++ t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey) ++ } ++ ++ if marker != test.marker { ++ t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker) ++ } ++ ++ if comment != test.comment { ++ t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment) ++ } ++ ++ if !reflect.DeepEqual(test.hosts, hosts) { ++ t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts) ++ } ++ ++ if rest := string(rest); rest != test.rest { ++ t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest) ++ } ++ } ++} ++ ++func TestFingerprintLegacyMD5(t *testing.T) { ++ pub, _ := getTestKey() ++ fingerprint := FingerprintLegacyMD5(pub) ++ want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa ++ if fingerprint != want { ++ t.Errorf("got fingerprint %q want %q", fingerprint, want) ++ } ++} ++ ++func TestFingerprintSHA256(t *testing.T) { ++ pub, _ := getTestKey() ++ fingerprint := FingerprintSHA256(pub) ++ want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa ++ if fingerprint != want { ++ t.Errorf("got fingerprint %q want %q", fingerprint, want) ++ } ++} ++ ++func TestInvalidKeys(t *testing.T) { ++ keyTypes := []string{ ++ "RSA PRIVATE KEY", ++ "PRIVATE KEY", ++ "EC PRIVATE KEY", ++ "DSA PRIVATE KEY", ++ "OPENSSH PRIVATE KEY", ++ } ++ ++ for _, keyType := range keyTypes { ++ for _, dataLen := range []int{0, 1, 2, 5, 10, 20} { ++ data := make([]byte, dataLen) ++ if _, err := io.ReadFull(rand.Reader, data); err != nil { ++ t.Fatal(err) ++ } ++ ++ var buf bytes.Buffer ++ pem.Encode(&buf, &pem.Block{ ++ Type: keyType, ++ Bytes: data, ++ }) ++ ++ // This test is just to ensure that the function ++ // doesn't panic so the return value is ignored. ++ ParseRawPrivateKey(buf.Bytes()) ++ } ++ } ++} ++ ++func TestSKKeys(t *testing.T) { ++ for _, d := range testdata.SKData { ++ pk, _, _, _, err := ParseAuthorizedKey(d.PubKey) ++ if err != nil { ++ t.Fatalf("parseAuthorizedKey returned error: %v", err) ++ } ++ ++ sigBuf := make([]byte, hex.DecodedLen(len(d.HexSignature))) ++ if _, err := hex.Decode(sigBuf, d.HexSignature); err != nil { ++ t.Fatalf("hex.Decode() failed: %v", err) ++ } ++ ++ dataBuf := make([]byte, hex.DecodedLen(len(d.HexData))) ++ if _, err := hex.Decode(dataBuf, d.HexData); err != nil { ++ t.Fatalf("hex.Decode() failed: %v", err) ++ } ++ ++ sig, _, ok := parseSignature(sigBuf) ++ if !ok { ++ t.Fatalf("parseSignature(%v) failed", sigBuf) ++ } ++ ++ // Test that good data and signature pass verification ++ if err := pk.Verify(dataBuf, sig); err != nil { ++ t.Errorf("%s: PublicKey.Verify(%v, %v) failed: %v", d.Name, dataBuf, sig, err) ++ } ++ ++ // Invalid data being passed in ++ invalidData := []byte("INVALID DATA") ++ if err := pk.Verify(invalidData, sig); err == nil { ++ t.Errorf("%s with invalid data: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, invalidData, sig) ++ } ++ ++ // Change byte in blob to corrup signature ++ sig.Blob[5] = byte('A') ++ // Corrupted data being passed in ++ if err := pk.Verify(dataBuf, sig); err == nil { ++ t.Errorf("%s with corrupted signature: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, dataBuf, sig) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go +new file mode 100644 +index 00000000000000..7376a8dff23f61 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go +@@ -0,0 +1,540 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package knownhosts implements a parser for the OpenSSH known_hosts ++// host key database, and provides utility functions for writing ++// OpenSSH compliant known_hosts files. ++package knownhosts ++ ++import ( ++ "bufio" ++ "bytes" ++ "crypto/hmac" ++ "crypto/rand" ++ "crypto/sha1" ++ "encoding/base64" ++ "errors" ++ "fmt" ++ "io" ++ "net" ++ "os" ++ "strings" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++// See the sshd manpage ++// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for ++// background. ++ ++type addr struct{ host, port string } ++ ++func (a *addr) String() string { ++ h := a.host ++ if strings.Contains(h, ":") { ++ h = "[" + h + "]" ++ } ++ return h + ":" + a.port ++} ++ ++type matcher interface { ++ match(addr) bool ++} ++ ++type hostPattern struct { ++ negate bool ++ addr addr ++} ++ ++func (p *hostPattern) String() string { ++ n := "" ++ if p.negate { ++ n = "!" ++ } ++ ++ return n + p.addr.String() ++} ++ ++type hostPatterns []hostPattern ++ ++func (ps hostPatterns) match(a addr) bool { ++ matched := false ++ for _, p := range ps { ++ if !p.match(a) { ++ continue ++ } ++ if p.negate { ++ return false ++ } ++ matched = true ++ } ++ return matched ++} ++ ++// See ++// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c ++// The matching of * has no regard for separators, unlike filesystem globs ++func wildcardMatch(pat []byte, str []byte) bool { ++ for { ++ if len(pat) == 0 { ++ return len(str) == 0 ++ } ++ if len(str) == 0 { ++ return false ++ } ++ ++ if pat[0] == '*' { ++ if len(pat) == 1 { ++ return true ++ } ++ ++ for j := range str { ++ if wildcardMatch(pat[1:], str[j:]) { ++ return true ++ } ++ } ++ return false ++ } ++ ++ if pat[0] == '?' || pat[0] == str[0] { ++ pat = pat[1:] ++ str = str[1:] ++ } else { ++ return false ++ } ++ } ++} ++ ++func (p *hostPattern) match(a addr) bool { ++ return wildcardMatch([]byte(p.addr.host), []byte(a.host)) && p.addr.port == a.port ++} ++ ++type keyDBLine struct { ++ cert bool ++ matcher matcher ++ knownKey KnownKey ++} ++ ++func serialize(k ssh.PublicKey) string { ++ return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal()) ++} ++ ++func (l *keyDBLine) match(a addr) bool { ++ return l.matcher.match(a) ++} ++ ++type hostKeyDB struct { ++ // Serialized version of revoked keys ++ revoked map[string]*KnownKey ++ lines []keyDBLine ++} ++ ++func newHostKeyDB() *hostKeyDB { ++ db := &hostKeyDB{ ++ revoked: make(map[string]*KnownKey), ++ } ++ ++ return db ++} ++ ++func keyEq(a, b ssh.PublicKey) bool { ++ return bytes.Equal(a.Marshal(), b.Marshal()) ++} ++ ++// IsHostAuthority can be used as a callback in ssh.CertChecker ++func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool { ++ h, p, err := net.SplitHostPort(address) ++ if err != nil { ++ return false ++ } ++ a := addr{host: h, port: p} ++ ++ for _, l := range db.lines { ++ if l.cert && keyEq(l.knownKey.Key, remote) && l.match(a) { ++ return true ++ } ++ } ++ return false ++} ++ ++// IsRevoked can be used as a callback in ssh.CertChecker ++func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool { ++ _, ok := db.revoked[string(key.Marshal())] ++ return ok ++} ++ ++const markerCert = "@cert-authority" ++const markerRevoked = "@revoked" ++ ++func nextWord(line []byte) (string, []byte) { ++ i := bytes.IndexAny(line, "\t ") ++ if i == -1 { ++ return string(line), nil ++ } ++ ++ return string(line[:i]), bytes.TrimSpace(line[i:]) ++} ++ ++func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) { ++ if w, next := nextWord(line); w == markerCert || w == markerRevoked { ++ marker = w ++ line = next ++ } ++ ++ host, line = nextWord(line) ++ if len(line) == 0 { ++ return "", "", nil, errors.New("knownhosts: missing host pattern") ++ } ++ ++ // ignore the keytype as it's in the key blob anyway. ++ _, line = nextWord(line) ++ if len(line) == 0 { ++ return "", "", nil, errors.New("knownhosts: missing key type pattern") ++ } ++ ++ keyBlob, _ := nextWord(line) ++ ++ keyBytes, err := base64.StdEncoding.DecodeString(keyBlob) ++ if err != nil { ++ return "", "", nil, err ++ } ++ key, err = ssh.ParsePublicKey(keyBytes) ++ if err != nil { ++ return "", "", nil, err ++ } ++ ++ return marker, host, key, nil ++} ++ ++func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error { ++ marker, pattern, key, err := parseLine(line) ++ if err != nil { ++ return err ++ } ++ ++ if marker == markerRevoked { ++ db.revoked[string(key.Marshal())] = &KnownKey{ ++ Key: key, ++ Filename: filename, ++ Line: linenum, ++ } ++ ++ return nil ++ } ++ ++ entry := keyDBLine{ ++ cert: marker == markerCert, ++ knownKey: KnownKey{ ++ Filename: filename, ++ Line: linenum, ++ Key: key, ++ }, ++ } ++ ++ if pattern[0] == '|' { ++ entry.matcher, err = newHashedHost(pattern) ++ } else { ++ entry.matcher, err = newHostnameMatcher(pattern) ++ } ++ ++ if err != nil { ++ return err ++ } ++ ++ db.lines = append(db.lines, entry) ++ return nil ++} ++ ++func newHostnameMatcher(pattern string) (matcher, error) { ++ var hps hostPatterns ++ for _, p := range strings.Split(pattern, ",") { ++ if len(p) == 0 { ++ continue ++ } ++ ++ var a addr ++ var negate bool ++ if p[0] == '!' { ++ negate = true ++ p = p[1:] ++ } ++ ++ if len(p) == 0 { ++ return nil, errors.New("knownhosts: negation without following hostname") ++ } ++ ++ var err error ++ if p[0] == '[' { ++ a.host, a.port, err = net.SplitHostPort(p) ++ if err != nil { ++ return nil, err ++ } ++ } else { ++ a.host, a.port, err = net.SplitHostPort(p) ++ if err != nil { ++ a.host = p ++ a.port = "22" ++ } ++ } ++ hps = append(hps, hostPattern{ ++ negate: negate, ++ addr: a, ++ }) ++ } ++ return hps, nil ++} ++ ++// KnownKey represents a key declared in a known_hosts file. ++type KnownKey struct { ++ Key ssh.PublicKey ++ Filename string ++ Line int ++} ++ ++func (k *KnownKey) String() string { ++ return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key)) ++} ++ ++// KeyError is returned if we did not find the key in the host key ++// database, or there was a mismatch. Typically, in batch ++// applications, this should be interpreted as failure. Interactive ++// applications can offer an interactive prompt to the user. ++type KeyError struct { ++ // Want holds the accepted host keys. For each key algorithm, ++ // there can be one hostkey. If Want is empty, the host is ++ // unknown. If Want is non-empty, there was a mismatch, which ++ // can signify a MITM attack. ++ Want []KnownKey ++} ++ ++func (u *KeyError) Error() string { ++ if len(u.Want) == 0 { ++ return "knownhosts: key is unknown" ++ } ++ return "knownhosts: key mismatch" ++} ++ ++// RevokedError is returned if we found a key that was revoked. ++type RevokedError struct { ++ Revoked KnownKey ++} ++ ++func (r *RevokedError) Error() string { ++ return "knownhosts: key is revoked" ++} ++ ++// check checks a key against the host database. This should not be ++// used for verifying certificates. ++func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error { ++ if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil { ++ return &RevokedError{Revoked: *revoked} ++ } ++ ++ host, port, err := net.SplitHostPort(remote.String()) ++ if err != nil { ++ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err) ++ } ++ ++ hostToCheck := addr{host, port} ++ if address != "" { ++ // Give preference to the hostname if available. ++ host, port, err := net.SplitHostPort(address) ++ if err != nil { ++ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err) ++ } ++ ++ hostToCheck = addr{host, port} ++ } ++ ++ return db.checkAddr(hostToCheck, remoteKey) ++} ++ ++// checkAddr checks if we can find the given public key for the ++// given address. If we only find an entry for the IP address, ++// or only the hostname, then this still succeeds. ++func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { ++ // TODO(hanwen): are these the right semantics? What if there ++ // is just a key for the IP address, but not for the ++ // hostname? ++ ++ // Algorithm => key. ++ knownKeys := map[string]KnownKey{} ++ for _, l := range db.lines { ++ if l.match(a) { ++ typ := l.knownKey.Key.Type() ++ if _, ok := knownKeys[typ]; !ok { ++ knownKeys[typ] = l.knownKey ++ } ++ } ++ } ++ ++ keyErr := &KeyError{} ++ for _, v := range knownKeys { ++ keyErr.Want = append(keyErr.Want, v) ++ } ++ ++ // Unknown remote host. ++ if len(knownKeys) == 0 { ++ return keyErr ++ } ++ ++ // If the remote host starts using a different, unknown key type, we ++ // also interpret that as a mismatch. ++ if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { ++ return keyErr ++ } ++ ++ return nil ++} ++ ++// The Read function parses file contents. ++func (db *hostKeyDB) Read(r io.Reader, filename string) error { ++ scanner := bufio.NewScanner(r) ++ ++ lineNum := 0 ++ for scanner.Scan() { ++ lineNum++ ++ line := scanner.Bytes() ++ line = bytes.TrimSpace(line) ++ if len(line) == 0 || line[0] == '#' { ++ continue ++ } ++ ++ if err := db.parseLine(line, filename, lineNum); err != nil { ++ return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err) ++ } ++ } ++ return scanner.Err() ++} ++ ++// New creates a host key callback from the given OpenSSH host key ++// files. The returned callback is for use in ++// ssh.ClientConfig.HostKeyCallback. By preference, the key check ++// operates on the hostname if available, i.e. if a server changes its ++// IP address, the host key check will still succeed, even though a ++// record of the new IP address is not available. ++func New(files ...string) (ssh.HostKeyCallback, error) { ++ db := newHostKeyDB() ++ for _, fn := range files { ++ f, err := os.Open(fn) ++ if err != nil { ++ return nil, err ++ } ++ defer f.Close() ++ if err := db.Read(f, fn); err != nil { ++ return nil, err ++ } ++ } ++ ++ var certChecker ssh.CertChecker ++ certChecker.IsHostAuthority = db.IsHostAuthority ++ certChecker.IsRevoked = db.IsRevoked ++ certChecker.HostKeyFallback = db.check ++ ++ return certChecker.CheckHostKey, nil ++} ++ ++// Normalize normalizes an address into the form used in known_hosts ++func Normalize(address string) string { ++ host, port, err := net.SplitHostPort(address) ++ if err != nil { ++ host = address ++ port = "22" ++ } ++ entry := host ++ if port != "22" { ++ entry = "[" + entry + "]:" + port ++ } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { ++ entry = "[" + entry + "]" ++ } ++ return entry ++} ++ ++// Line returns a line to add append to the known_hosts files. ++func Line(addresses []string, key ssh.PublicKey) string { ++ var trimmed []string ++ for _, a := range addresses { ++ trimmed = append(trimmed, Normalize(a)) ++ } ++ ++ return strings.Join(trimmed, ",") + " " + serialize(key) ++} ++ ++// HashHostname hashes the given hostname. The hostname is not ++// normalized before hashing. ++func HashHostname(hostname string) string { ++ // TODO(hanwen): check if we can safely normalize this always. ++ salt := make([]byte, sha1.Size) ++ ++ _, err := rand.Read(salt) ++ if err != nil { ++ panic(fmt.Sprintf("crypto/rand failure %v", err)) ++ } ++ ++ hash := hashHost(hostname, salt) ++ return encodeHash(sha1HashType, salt, hash) ++} ++ ++func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) { ++ if len(encoded) == 0 || encoded[0] != '|' { ++ err = errors.New("knownhosts: hashed host must start with '|'") ++ return ++ } ++ components := strings.Split(encoded, "|") ++ if len(components) != 4 { ++ err = fmt.Errorf("knownhosts: got %d components, want 3", len(components)) ++ return ++ } ++ ++ hashType = components[1] ++ if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil { ++ return ++ } ++ if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil { ++ return ++ } ++ return ++} ++ ++func encodeHash(typ string, salt []byte, hash []byte) string { ++ return strings.Join([]string{"", ++ typ, ++ base64.StdEncoding.EncodeToString(salt), ++ base64.StdEncoding.EncodeToString(hash), ++ }, "|") ++} ++ ++// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 ++func hashHost(hostname string, salt []byte) []byte { ++ mac := hmac.New(sha1.New, salt) ++ mac.Write([]byte(hostname)) ++ return mac.Sum(nil) ++} ++ ++type hashedHost struct { ++ salt []byte ++ hash []byte ++} ++ ++const sha1HashType = "1" ++ ++func newHashedHost(encoded string) (*hashedHost, error) { ++ typ, salt, hash, err := decodeHash(encoded) ++ if err != nil { ++ return nil, err ++ } ++ ++ // The type field seems for future algorithm agility, but it's ++ // actually hardcoded in openssh currently, see ++ // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 ++ if typ != sha1HashType { ++ return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ) ++ } ++ ++ return &hashedHost{salt: salt, hash: hash}, nil ++} ++ ++func (h *hashedHost) match(a addr) bool { ++ return bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go +new file mode 100644 +index 00000000000000..464dd592493ab3 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go +@@ -0,0 +1,356 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package knownhosts ++ ++import ( ++ "bytes" ++ "fmt" ++ "net" ++ "reflect" ++ "testing" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX" ++const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx" ++const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs=" ++ ++var ecKey, alternateEdKey, edKey ssh.PublicKey ++var testAddr = &net.TCPAddr{ ++ IP: net.IP{198, 41, 30, 196}, ++ Port: 22, ++} ++ ++var testAddr6 = &net.TCPAddr{ ++ IP: net.IP{198, 41, 30, 196, ++ 1, 2, 3, 4, ++ 1, 2, 3, 4, ++ 1, 2, 3, 4, ++ }, ++ Port: 22, ++} ++ ++func init() { ++ var err error ++ ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr)) ++ if err != nil { ++ panic(err) ++ } ++ edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr)) ++ if err != nil { ++ panic(err) ++ } ++ alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr)) ++ if err != nil { ++ panic(err) ++ } ++} ++ ++func testDB(t *testing.T, s string) *hostKeyDB { ++ db := newHostKeyDB() ++ if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil { ++ t.Fatalf("Read: %v", err) ++ } ++ ++ return db ++} ++ ++func TestRevoked(t *testing.T) { ++ db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n") ++ want := &RevokedError{ ++ Revoked: KnownKey{ ++ Key: edKey, ++ Filename: "testdb", ++ Line: 3, ++ }, ++ } ++ if err := db.check("", &net.TCPAddr{ ++ Port: 42, ++ }, edKey); err == nil { ++ t.Fatal("no error for revoked key") ++ } else if !reflect.DeepEqual(want, err) { ++ t.Fatalf("got %#v, want %#v", want, err) ++ } ++} ++ ++func TestHostAuthority(t *testing.T) { ++ for _, m := range []struct { ++ authorityFor string ++ address string ++ ++ good bool ++ }{ ++ {authorityFor: "localhost", address: "localhost:22", good: true}, ++ {authorityFor: "localhost", address: "localhost", good: false}, ++ {authorityFor: "localhost", address: "localhost:1234", good: false}, ++ {authorityFor: "[localhost]:1234", address: "localhost:1234", good: true}, ++ {authorityFor: "[localhost]:1234", address: "localhost:22", good: false}, ++ {authorityFor: "[localhost]:1234", address: "localhost", good: false}, ++ } { ++ db := testDB(t, `@cert-authority `+m.authorityFor+` `+edKeyStr) ++ if ok := db.IsHostAuthority(db.lines[0].knownKey.Key, m.address); ok != m.good { ++ t.Errorf("IsHostAuthority: authority %s, address %s, wanted good = %v, got good = %v", ++ m.authorityFor, m.address, m.good, ok) ++ } ++ } ++} ++ ++func TestBracket(t *testing.T) { ++ db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr) ++ ++ if err := db.check("git.eclipse.org:29418", &net.TCPAddr{ ++ IP: net.IP{198, 41, 30, 196}, ++ Port: 29418, ++ }, edKey); err != nil { ++ t.Errorf("got error %v, want none", err) ++ } ++ ++ if err := db.check("git.eclipse.org:29419", &net.TCPAddr{ ++ Port: 42, ++ }, edKey); err == nil { ++ t.Fatalf("no error for unknown address") ++ } else if ke, ok := err.(*KeyError); !ok { ++ t.Fatalf("got type %T, want *KeyError", err) ++ } else if len(ke.Want) > 0 { ++ t.Fatalf("got Want %v, want []", ke.Want) ++ } ++} ++ ++func TestNewKeyType(t *testing.T) { ++ str := fmt.Sprintf("%s %s", testAddr, edKeyStr) ++ db := testDB(t, str) ++ if err := db.check("", testAddr, ecKey); err == nil { ++ t.Fatalf("no error for unknown address") ++ } else if ke, ok := err.(*KeyError); !ok { ++ t.Fatalf("got type %T, want *KeyError", err) ++ } else if len(ke.Want) == 0 { ++ t.Fatalf("got empty KeyError.Want") ++ } ++} ++ ++func TestSameKeyType(t *testing.T) { ++ str := fmt.Sprintf("%s %s", testAddr, edKeyStr) ++ db := testDB(t, str) ++ if err := db.check("", testAddr, alternateEdKey); err == nil { ++ t.Fatalf("no error for unknown address") ++ } else if ke, ok := err.(*KeyError); !ok { ++ t.Fatalf("got type %T, want *KeyError", err) ++ } else if len(ke.Want) == 0 { ++ t.Fatalf("got empty KeyError.Want") ++ } else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) { ++ t.Fatalf("got key %q, want %q", got, want) ++ } ++} ++ ++func TestIPAddress(t *testing.T) { ++ str := fmt.Sprintf("%s %s", testAddr, edKeyStr) ++ db := testDB(t, str) ++ if err := db.check("", testAddr, edKey); err != nil { ++ t.Errorf("got error %q, want none", err) ++ } ++} ++ ++func TestIPv6Address(t *testing.T) { ++ str := fmt.Sprintf("%s %s", testAddr6, edKeyStr) ++ db := testDB(t, str) ++ ++ if err := db.check("", testAddr6, edKey); err != nil { ++ t.Errorf("got error %q, want none", err) ++ } ++} ++ ++func TestBasic(t *testing.T) { ++ str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr) ++ db := testDB(t, str) ++ if err := db.check("server.org:22", testAddr, edKey); err != nil { ++ t.Errorf("got error %v, want none", err) ++ } ++ ++ want := KnownKey{ ++ Key: edKey, ++ Filename: "testdb", ++ Line: 3, ++ } ++ if err := db.check("server.org:22", testAddr, ecKey); err == nil { ++ t.Errorf("succeeded, want KeyError") ++ } else if ke, ok := err.(*KeyError); !ok { ++ t.Errorf("got %T, want *KeyError", err) ++ } else if len(ke.Want) != 1 { ++ t.Errorf("got %v, want 1 entry", ke) ++ } else if !reflect.DeepEqual(ke.Want[0], want) { ++ t.Errorf("got %v, want %v", ke.Want[0], want) ++ } ++} ++ ++func TestHostNamePrecedence(t *testing.T) { ++ var evilAddr = &net.TCPAddr{ ++ IP: net.IP{66, 66, 66, 66}, ++ Port: 22, ++ } ++ ++ str := fmt.Sprintf("server.org,%s %s\nevil.org,%s %s", testAddr, edKeyStr, evilAddr, ecKeyStr) ++ db := testDB(t, str) ++ ++ if err := db.check("server.org:22", evilAddr, ecKey); err == nil { ++ t.Errorf("check succeeded") ++ } else if _, ok := err.(*KeyError); !ok { ++ t.Errorf("got %T, want *KeyError", err) ++ } ++} ++ ++func TestDBOrderingPrecedenceKeyType(t *testing.T) { ++ str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) ++ db := testDB(t, str) ++ ++ if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil { ++ t.Errorf("check succeeded") ++ } else if _, ok := err.(*KeyError); !ok { ++ t.Errorf("got %T, want *KeyError", err) ++ } ++} ++ ++func TestNegate(t *testing.T) { ++ str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) ++ db := testDB(t, str) ++ if err := db.check("server.org:22", testAddr, ecKey); err == nil { ++ t.Errorf("succeeded") ++ } else if ke, ok := err.(*KeyError); !ok { ++ t.Errorf("got error type %T, want *KeyError", err) ++ } else if len(ke.Want) != 0 { ++ t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type()) ++ } ++} ++ ++func TestWildcard(t *testing.T) { ++ str := fmt.Sprintf("server*.domain %s", edKeyStr) ++ db := testDB(t, str) ++ ++ want := &KeyError{ ++ Want: []KnownKey{{ ++ Filename: "testdb", ++ Line: 1, ++ Key: edKey, ++ }}, ++ } ++ ++ got := db.check("server.domain:22", &net.TCPAddr{}, ecKey) ++ if !reflect.DeepEqual(got, want) { ++ t.Errorf("got %s, want %s", got, want) ++ } ++} ++ ++func TestLine(t *testing.T) { ++ for in, want := range map[string]string{ ++ "server.org": "server.org " + edKeyStr, ++ "server.org:22": "server.org " + edKeyStr, ++ "server.org:23": "[server.org]:23 " + edKeyStr, ++ "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr, ++ "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr, ++ } { ++ if got := Line([]string{in}, edKey); got != want { ++ t.Errorf("Line(%q) = %q, want %q", in, got, want) ++ } ++ } ++} ++ ++func TestWildcardMatch(t *testing.T) { ++ for _, c := range []struct { ++ pat, str string ++ want bool ++ }{ ++ {"a?b", "abb", true}, ++ {"ab", "abc", false}, ++ {"abc", "ab", false}, ++ {"a*b", "axxxb", true}, ++ {"a*b", "axbxb", true}, ++ {"a*b", "axbxbc", false}, ++ {"a*?", "axbxc", true}, ++ {"a*b*", "axxbxxxxxx", true}, ++ {"a*b*c", "axxbxxxxxxc", true}, ++ {"a*b*?", "axxbxxxxxxc", true}, ++ {"a*b*z", "axxbxxbxxxz", true}, ++ {"a*b*z", "axxbxxzxxxz", true}, ++ {"a*b*z", "axxbxxzxxx", false}, ++ } { ++ got := wildcardMatch([]byte(c.pat), []byte(c.str)) ++ if got != c.want { ++ t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want) ++ } ++ ++ } ++} ++ ++// TODO(hanwen): test coverage for certificates. ++ ++const testHostname = "hostname" ++ ++// generated with keygen -H -f ++const encodedTestHostnameHash = "|1|IHXZvQMvTcZTUU29+2vXFgx8Frs=|UGccIWfRVDwilMBnA3WJoRAC75Y=" ++ ++func TestHostHash(t *testing.T) { ++ testHostHash(t, testHostname, encodedTestHostnameHash) ++} ++ ++func TestHashList(t *testing.T) { ++ encoded := HashHostname(testHostname) ++ testHostHash(t, testHostname, encoded) ++} ++ ++func testHostHash(t *testing.T, hostname, encoded string) { ++ typ, salt, hash, err := decodeHash(encoded) ++ if err != nil { ++ t.Fatalf("decodeHash: %v", err) ++ } ++ ++ if got := encodeHash(typ, salt, hash); got != encoded { ++ t.Errorf("got encoding %s want %s", got, encoded) ++ } ++ ++ if typ != sha1HashType { ++ t.Fatalf("got hash type %q, want %q", typ, sha1HashType) ++ } ++ ++ got := hashHost(hostname, salt) ++ if !bytes.Equal(got, hash) { ++ t.Errorf("got hash %x want %x", got, hash) ++ } ++} ++ ++func TestNormalize(t *testing.T) { ++ for in, want := range map[string]string{ ++ "127.0.0.1:22": "127.0.0.1", ++ "[127.0.0.1]:22": "127.0.0.1", ++ "[127.0.0.1]:23": "[127.0.0.1]:23", ++ "127.0.0.1:23": "[127.0.0.1]:23", ++ "[a.b.c]:22": "a.b.c", ++ "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]", ++ "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]", ++ "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23", ++ } { ++ got := Normalize(in) ++ if got != want { ++ t.Errorf("Normalize(%q) = %q, want %q", in, got, want) ++ } ++ } ++} ++ ++func TestHashedHostkeyCheck(t *testing.T) { ++ str := fmt.Sprintf("%s %s", HashHostname(testHostname), edKeyStr) ++ db := testDB(t, str) ++ if err := db.check(testHostname+":22", testAddr, edKey); err != nil { ++ t.Errorf("check(%s): %v", testHostname, err) ++ } ++ want := &KeyError{ ++ Want: []KnownKey{{ ++ Filename: "testdb", ++ Line: 1, ++ Key: edKey, ++ }}, ++ } ++ if got := db.check(testHostname+":22", testAddr, alternateEdKey); !reflect.DeepEqual(got, want) { ++ t.Errorf("got error %v, want %v", got, want) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/mac.go b/ms_mod/golang.org/x/crypto/ssh/mac.go +new file mode 100644 +index 00000000000000..06a1b27507ee3a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/mac.go +@@ -0,0 +1,68 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++// Message authentication support ++ ++import ( ++ "crypto/hmac" ++ "crypto/sha1" ++ "crypto/sha256" ++ "crypto/sha512" ++ "hash" ++) ++ ++type macMode struct { ++ keySize int ++ etm bool ++ new func(key []byte) hash.Hash ++} ++ ++// truncatingMAC wraps around a hash.Hash and truncates the output digest to ++// a given size. ++type truncatingMAC struct { ++ length int ++ hmac hash.Hash ++} ++ ++func (t truncatingMAC) Write(data []byte) (int, error) { ++ return t.hmac.Write(data) ++} ++ ++func (t truncatingMAC) Sum(in []byte) []byte { ++ out := t.hmac.Sum(in) ++ return out[:len(in)+t.length] ++} ++ ++func (t truncatingMAC) Reset() { ++ t.hmac.Reset() ++} ++ ++func (t truncatingMAC) Size() int { ++ return t.length ++} ++ ++func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } ++ ++var macModes = map[string]*macMode{ ++ "hmac-sha2-512-etm@openssh.com": {64, true, func(key []byte) hash.Hash { ++ return hmac.New(sha512.New, key) ++ }}, ++ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { ++ return hmac.New(sha256.New, key) ++ }}, ++ "hmac-sha2-512": {64, false, func(key []byte) hash.Hash { ++ return hmac.New(sha512.New, key) ++ }}, ++ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash { ++ return hmac.New(sha256.New, key) ++ }}, ++ "hmac-sha1": {20, false, func(key []byte) hash.Hash { ++ return hmac.New(sha1.New, key) ++ }}, ++ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash { ++ return truncatingMAC{12, hmac.New(sha1.New, key)} ++ }}, ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/mempipe_test.go b/ms_mod/golang.org/x/crypto/ssh/mempipe_test.go +new file mode 100644 +index 00000000000000..8697cd6140a737 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/mempipe_test.go +@@ -0,0 +1,110 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "io" ++ "sync" ++ "testing" ++) ++ ++// An in-memory packetConn. It is safe to call Close and writePacket ++// from different goroutines. ++type memTransport struct { ++ eof bool ++ pending [][]byte ++ write *memTransport ++ sync.Mutex ++ *sync.Cond ++} ++ ++func (t *memTransport) readPacket() ([]byte, error) { ++ t.Lock() ++ defer t.Unlock() ++ for { ++ if len(t.pending) > 0 { ++ r := t.pending[0] ++ t.pending = t.pending[1:] ++ return r, nil ++ } ++ if t.eof { ++ return nil, io.EOF ++ } ++ t.Cond.Wait() ++ } ++} ++ ++func (t *memTransport) closeSelf() error { ++ t.Lock() ++ defer t.Unlock() ++ if t.eof { ++ return io.EOF ++ } ++ t.eof = true ++ t.Cond.Broadcast() ++ return nil ++} ++ ++func (t *memTransport) Close() error { ++ err := t.write.closeSelf() ++ t.closeSelf() ++ return err ++} ++ ++func (t *memTransport) writePacket(p []byte) error { ++ t.write.Lock() ++ defer t.write.Unlock() ++ if t.write.eof { ++ return io.EOF ++ } ++ c := make([]byte, len(p)) ++ copy(c, p) ++ t.write.pending = append(t.write.pending, c) ++ t.write.Cond.Signal() ++ return nil ++} ++ ++func memPipe() (a, b packetConn) { ++ t1 := memTransport{} ++ t2 := memTransport{} ++ t1.write = &t2 ++ t2.write = &t1 ++ t1.Cond = sync.NewCond(&t1.Mutex) ++ t2.Cond = sync.NewCond(&t2.Mutex) ++ return &t1, &t2 ++} ++ ++func TestMemPipe(t *testing.T) { ++ a, b := memPipe() ++ if err := a.writePacket([]byte{42}); err != nil { ++ t.Fatalf("writePacket: %v", err) ++ } ++ if err := a.Close(); err != nil { ++ t.Fatal("Close: ", err) ++ } ++ p, err := b.readPacket() ++ if err != nil { ++ t.Fatal("readPacket: ", err) ++ } ++ if len(p) != 1 || p[0] != 42 { ++ t.Fatalf("got %v, want {42}", p) ++ } ++ p, err = b.readPacket() ++ if err != io.EOF { ++ t.Fatalf("got %v, %v, want EOF", p, err) ++ } ++} ++ ++func TestDoubleClose(t *testing.T) { ++ a, _ := memPipe() ++ err := a.Close() ++ if err != nil { ++ t.Errorf("Close: %v", err) ++ } ++ err = a.Close() ++ if err != io.EOF { ++ t.Errorf("expect EOF on double close.") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/messages.go b/ms_mod/golang.org/x/crypto/ssh/messages.go +new file mode 100644 +index 00000000000000..922032d9525604 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/messages.go +@@ -0,0 +1,877 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "io" ++ "math/big" ++ "reflect" ++ "strconv" ++ "strings" ++) ++ ++// These are SSH message type numbers. They are scattered around several ++// documents but many were taken from [SSH-PARAMETERS]. ++const ( ++ msgIgnore = 2 ++ msgUnimplemented = 3 ++ msgDebug = 4 ++ msgNewKeys = 21 ++) ++ ++// SSH messages: ++// ++// These structures mirror the wire format of the corresponding SSH messages. ++// They are marshaled using reflection with the marshal and unmarshal functions ++// in this file. The only wrinkle is that a final member of type []byte with a ++// ssh tag of "rest" receives the remainder of a packet when unmarshaling. ++ ++// See RFC 4253, section 11.1. ++const msgDisconnect = 1 ++ ++// disconnectMsg is the message that signals a disconnect. It is also ++// the error type returned from mux.Wait() ++type disconnectMsg struct { ++ Reason uint32 `sshtype:"1"` ++ Message string ++ Language string ++} ++ ++func (d *disconnectMsg) Error() string { ++ return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message) ++} ++ ++// See RFC 4253, section 7.1. ++const msgKexInit = 20 ++ ++type kexInitMsg struct { ++ Cookie [16]byte `sshtype:"20"` ++ KexAlgos []string ++ ServerHostKeyAlgos []string ++ CiphersClientServer []string ++ CiphersServerClient []string ++ MACsClientServer []string ++ MACsServerClient []string ++ CompressionClientServer []string ++ CompressionServerClient []string ++ LanguagesClientServer []string ++ LanguagesServerClient []string ++ FirstKexFollows bool ++ Reserved uint32 ++} ++ ++// See RFC 4253, section 8. ++ ++// Diffie-Hellman ++const msgKexDHInit = 30 ++ ++type kexDHInitMsg struct { ++ X *big.Int `sshtype:"30"` ++} ++ ++const msgKexECDHInit = 30 ++ ++type kexECDHInitMsg struct { ++ ClientPubKey []byte `sshtype:"30"` ++} ++ ++const msgKexECDHReply = 31 ++ ++type kexECDHReplyMsg struct { ++ HostKey []byte `sshtype:"31"` ++ EphemeralPubKey []byte ++ Signature []byte ++} ++ ++const msgKexDHReply = 31 ++ ++type kexDHReplyMsg struct { ++ HostKey []byte `sshtype:"31"` ++ Y *big.Int ++ Signature []byte ++} ++ ++// See RFC 4419, section 5. ++const msgKexDHGexGroup = 31 ++ ++type kexDHGexGroupMsg struct { ++ P *big.Int `sshtype:"31"` ++ G *big.Int ++} ++ ++const msgKexDHGexInit = 32 ++ ++type kexDHGexInitMsg struct { ++ X *big.Int `sshtype:"32"` ++} ++ ++const msgKexDHGexReply = 33 ++ ++type kexDHGexReplyMsg struct { ++ HostKey []byte `sshtype:"33"` ++ Y *big.Int ++ Signature []byte ++} ++ ++const msgKexDHGexRequest = 34 ++ ++type kexDHGexRequestMsg struct { ++ MinBits uint32 `sshtype:"34"` ++ PreferedBits uint32 ++ MaxBits uint32 ++} ++ ++// See RFC 4253, section 10. ++const msgServiceRequest = 5 ++ ++type serviceRequestMsg struct { ++ Service string `sshtype:"5"` ++} ++ ++// See RFC 4253, section 10. ++const msgServiceAccept = 6 ++ ++type serviceAcceptMsg struct { ++ Service string `sshtype:"6"` ++} ++ ++// See RFC 8308, section 2.3 ++const msgExtInfo = 7 ++ ++type extInfoMsg struct { ++ NumExtensions uint32 `sshtype:"7"` ++ Payload []byte `ssh:"rest"` ++} ++ ++// See RFC 4252, section 5. ++const msgUserAuthRequest = 50 ++ ++type userAuthRequestMsg struct { ++ User string `sshtype:"50"` ++ Service string ++ Method string ++ Payload []byte `ssh:"rest"` ++} ++ ++// Used for debug printouts of packets. ++type userAuthSuccessMsg struct { ++} ++ ++// See RFC 4252, section 5.1 ++const msgUserAuthFailure = 51 ++ ++type userAuthFailureMsg struct { ++ Methods []string `sshtype:"51"` ++ PartialSuccess bool ++} ++ ++// See RFC 4252, section 5.1 ++const msgUserAuthSuccess = 52 ++ ++// See RFC 4252, section 5.4 ++const msgUserAuthBanner = 53 ++ ++type userAuthBannerMsg struct { ++ Message string `sshtype:"53"` ++ // unused, but required to allow message parsing ++ Language string ++} ++ ++// See RFC 4256, section 3.2 ++const msgUserAuthInfoRequest = 60 ++const msgUserAuthInfoResponse = 61 ++ ++type userAuthInfoRequestMsg struct { ++ Name string `sshtype:"60"` ++ Instruction string ++ Language string ++ NumPrompts uint32 ++ Prompts []byte `ssh:"rest"` ++} ++ ++// See RFC 4254, section 5.1. ++const msgChannelOpen = 90 ++ ++type channelOpenMsg struct { ++ ChanType string `sshtype:"90"` ++ PeersID uint32 ++ PeersWindow uint32 ++ MaxPacketSize uint32 ++ TypeSpecificData []byte `ssh:"rest"` ++} ++ ++const msgChannelExtendedData = 95 ++const msgChannelData = 94 ++ ++// Used for debug print outs of packets. ++type channelDataMsg struct { ++ PeersID uint32 `sshtype:"94"` ++ Length uint32 ++ Rest []byte `ssh:"rest"` ++} ++ ++// See RFC 4254, section 5.1. ++const msgChannelOpenConfirm = 91 ++ ++type channelOpenConfirmMsg struct { ++ PeersID uint32 `sshtype:"91"` ++ MyID uint32 ++ MyWindow uint32 ++ MaxPacketSize uint32 ++ TypeSpecificData []byte `ssh:"rest"` ++} ++ ++// See RFC 4254, section 5.1. ++const msgChannelOpenFailure = 92 ++ ++type channelOpenFailureMsg struct { ++ PeersID uint32 `sshtype:"92"` ++ Reason RejectionReason ++ Message string ++ Language string ++} ++ ++const msgChannelRequest = 98 ++ ++type channelRequestMsg struct { ++ PeersID uint32 `sshtype:"98"` ++ Request string ++ WantReply bool ++ RequestSpecificData []byte `ssh:"rest"` ++} ++ ++// See RFC 4254, section 5.4. ++const msgChannelSuccess = 99 ++ ++type channelRequestSuccessMsg struct { ++ PeersID uint32 `sshtype:"99"` ++} ++ ++// See RFC 4254, section 5.4. ++const msgChannelFailure = 100 ++ ++type channelRequestFailureMsg struct { ++ PeersID uint32 `sshtype:"100"` ++} ++ ++// See RFC 4254, section 5.3 ++const msgChannelClose = 97 ++ ++type channelCloseMsg struct { ++ PeersID uint32 `sshtype:"97"` ++} ++ ++// See RFC 4254, section 5.3 ++const msgChannelEOF = 96 ++ ++type channelEOFMsg struct { ++ PeersID uint32 `sshtype:"96"` ++} ++ ++// See RFC 4254, section 4 ++const msgGlobalRequest = 80 ++ ++type globalRequestMsg struct { ++ Type string `sshtype:"80"` ++ WantReply bool ++ Data []byte `ssh:"rest"` ++} ++ ++// See RFC 4254, section 4 ++const msgRequestSuccess = 81 ++ ++type globalRequestSuccessMsg struct { ++ Data []byte `ssh:"rest" sshtype:"81"` ++} ++ ++// See RFC 4254, section 4 ++const msgRequestFailure = 82 ++ ++type globalRequestFailureMsg struct { ++ Data []byte `ssh:"rest" sshtype:"82"` ++} ++ ++// See RFC 4254, section 5.2 ++const msgChannelWindowAdjust = 93 ++ ++type windowAdjustMsg struct { ++ PeersID uint32 `sshtype:"93"` ++ AdditionalBytes uint32 ++} ++ ++// See RFC 4252, section 7 ++const msgUserAuthPubKeyOk = 60 ++ ++type userAuthPubKeyOkMsg struct { ++ Algo string `sshtype:"60"` ++ PubKey []byte ++} ++ ++// See RFC 4462, section 3 ++const msgUserAuthGSSAPIResponse = 60 ++ ++type userAuthGSSAPIResponse struct { ++ SupportMech []byte `sshtype:"60"` ++} ++ ++const msgUserAuthGSSAPIToken = 61 ++ ++type userAuthGSSAPIToken struct { ++ Token []byte `sshtype:"61"` ++} ++ ++const msgUserAuthGSSAPIMIC = 66 ++ ++type userAuthGSSAPIMIC struct { ++ MIC []byte `sshtype:"66"` ++} ++ ++// See RFC 4462, section 3.9 ++const msgUserAuthGSSAPIErrTok = 64 ++ ++type userAuthGSSAPIErrTok struct { ++ ErrorToken []byte `sshtype:"64"` ++} ++ ++// See RFC 4462, section 3.8 ++const msgUserAuthGSSAPIError = 65 ++ ++type userAuthGSSAPIError struct { ++ MajorStatus uint32 `sshtype:"65"` ++ MinorStatus uint32 ++ Message string ++ LanguageTag string ++} ++ ++// typeTags returns the possible type bytes for the given reflect.Type, which ++// should be a struct. The possible values are separated by a '|' character. ++func typeTags(structType reflect.Type) (tags []byte) { ++ tagStr := structType.Field(0).Tag.Get("sshtype") ++ ++ for _, tag := range strings.Split(tagStr, "|") { ++ i, err := strconv.Atoi(tag) ++ if err == nil { ++ tags = append(tags, byte(i)) ++ } ++ } ++ ++ return tags ++} ++ ++func fieldError(t reflect.Type, field int, problem string) error { ++ if problem != "" { ++ problem = ": " + problem ++ } ++ return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem) ++} ++ ++var errShortRead = errors.New("ssh: short read") ++ ++// Unmarshal parses data in SSH wire format into a structure. The out ++// argument should be a pointer to struct. If the first member of the ++// struct has the "sshtype" tag set to a '|'-separated set of numbers ++// in decimal, the packet must start with one of those numbers. In ++// case of error, Unmarshal returns a ParseError or ++// UnexpectedMessageError. ++func Unmarshal(data []byte, out interface{}) error { ++ v := reflect.ValueOf(out).Elem() ++ structType := v.Type() ++ expectedTypes := typeTags(structType) ++ ++ var expectedType byte ++ if len(expectedTypes) > 0 { ++ expectedType = expectedTypes[0] ++ } ++ ++ if len(data) == 0 { ++ return parseError(expectedType) ++ } ++ ++ if len(expectedTypes) > 0 { ++ goodType := false ++ for _, e := range expectedTypes { ++ if e > 0 && data[0] == e { ++ goodType = true ++ break ++ } ++ } ++ if !goodType { ++ return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes) ++ } ++ data = data[1:] ++ } ++ ++ var ok bool ++ for i := 0; i < v.NumField(); i++ { ++ field := v.Field(i) ++ t := field.Type() ++ switch t.Kind() { ++ case reflect.Bool: ++ if len(data) < 1 { ++ return errShortRead ++ } ++ field.SetBool(data[0] != 0) ++ data = data[1:] ++ case reflect.Array: ++ if t.Elem().Kind() != reflect.Uint8 { ++ return fieldError(structType, i, "array of unsupported type") ++ } ++ if len(data) < t.Len() { ++ return errShortRead ++ } ++ for j, n := 0, t.Len(); j < n; j++ { ++ field.Index(j).Set(reflect.ValueOf(data[j])) ++ } ++ data = data[t.Len():] ++ case reflect.Uint64: ++ var u64 uint64 ++ if u64, data, ok = parseUint64(data); !ok { ++ return errShortRead ++ } ++ field.SetUint(u64) ++ case reflect.Uint32: ++ var u32 uint32 ++ if u32, data, ok = parseUint32(data); !ok { ++ return errShortRead ++ } ++ field.SetUint(uint64(u32)) ++ case reflect.Uint8: ++ if len(data) < 1 { ++ return errShortRead ++ } ++ field.SetUint(uint64(data[0])) ++ data = data[1:] ++ case reflect.String: ++ var s []byte ++ if s, data, ok = parseString(data); !ok { ++ return fieldError(structType, i, "") ++ } ++ field.SetString(string(s)) ++ case reflect.Slice: ++ switch t.Elem().Kind() { ++ case reflect.Uint8: ++ if structType.Field(i).Tag.Get("ssh") == "rest" { ++ field.Set(reflect.ValueOf(data)) ++ data = nil ++ } else { ++ var s []byte ++ if s, data, ok = parseString(data); !ok { ++ return errShortRead ++ } ++ field.Set(reflect.ValueOf(s)) ++ } ++ case reflect.String: ++ var nl []string ++ if nl, data, ok = parseNameList(data); !ok { ++ return errShortRead ++ } ++ field.Set(reflect.ValueOf(nl)) ++ default: ++ return fieldError(structType, i, "slice of unsupported type") ++ } ++ case reflect.Ptr: ++ if t == bigIntType { ++ var n *big.Int ++ if n, data, ok = parseInt(data); !ok { ++ return errShortRead ++ } ++ field.Set(reflect.ValueOf(n)) ++ } else { ++ return fieldError(structType, i, "pointer to unsupported type") ++ } ++ default: ++ return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t)) ++ } ++ } ++ ++ if len(data) != 0 { ++ return parseError(expectedType) ++ } ++ ++ return nil ++} ++ ++// Marshal serializes the message in msg to SSH wire format. The msg ++// argument should be a struct or pointer to struct. If the first ++// member has the "sshtype" tag set to a number in decimal, that ++// number is prepended to the result. If the last of member has the ++// "ssh" tag set to "rest", its contents are appended to the output. ++func Marshal(msg interface{}) []byte { ++ out := make([]byte, 0, 64) ++ return marshalStruct(out, msg) ++} ++ ++func marshalStruct(out []byte, msg interface{}) []byte { ++ v := reflect.Indirect(reflect.ValueOf(msg)) ++ msgTypes := typeTags(v.Type()) ++ if len(msgTypes) > 0 { ++ out = append(out, msgTypes[0]) ++ } ++ ++ for i, n := 0, v.NumField(); i < n; i++ { ++ field := v.Field(i) ++ switch t := field.Type(); t.Kind() { ++ case reflect.Bool: ++ var v uint8 ++ if field.Bool() { ++ v = 1 ++ } ++ out = append(out, v) ++ case reflect.Array: ++ if t.Elem().Kind() != reflect.Uint8 { ++ panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface())) ++ } ++ for j, l := 0, t.Len(); j < l; j++ { ++ out = append(out, uint8(field.Index(j).Uint())) ++ } ++ case reflect.Uint32: ++ out = appendU32(out, uint32(field.Uint())) ++ case reflect.Uint64: ++ out = appendU64(out, uint64(field.Uint())) ++ case reflect.Uint8: ++ out = append(out, uint8(field.Uint())) ++ case reflect.String: ++ s := field.String() ++ out = appendInt(out, len(s)) ++ out = append(out, s...) ++ case reflect.Slice: ++ switch t.Elem().Kind() { ++ case reflect.Uint8: ++ if v.Type().Field(i).Tag.Get("ssh") != "rest" { ++ out = appendInt(out, field.Len()) ++ } ++ out = append(out, field.Bytes()...) ++ case reflect.String: ++ offset := len(out) ++ out = appendU32(out, 0) ++ if n := field.Len(); n > 0 { ++ for j := 0; j < n; j++ { ++ f := field.Index(j) ++ if j != 0 { ++ out = append(out, ',') ++ } ++ out = append(out, f.String()...) ++ } ++ // overwrite length value ++ binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4)) ++ } ++ default: ++ panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface())) ++ } ++ case reflect.Ptr: ++ if t == bigIntType { ++ var n *big.Int ++ nValue := reflect.ValueOf(&n) ++ nValue.Elem().Set(field) ++ needed := intLength(n) ++ oldLength := len(out) ++ ++ if cap(out)-len(out) < needed { ++ newOut := make([]byte, len(out), 2*(len(out)+needed)) ++ copy(newOut, out) ++ out = newOut ++ } ++ out = out[:oldLength+needed] ++ marshalInt(out[oldLength:], n) ++ } else { ++ panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface())) ++ } ++ } ++ } ++ ++ return out ++} ++ ++var bigOne = big.NewInt(1) ++ ++func parseString(in []byte) (out, rest []byte, ok bool) { ++ if len(in) < 4 { ++ return ++ } ++ length := binary.BigEndian.Uint32(in) ++ in = in[4:] ++ if uint32(len(in)) < length { ++ return ++ } ++ out = in[:length] ++ rest = in[length:] ++ ok = true ++ return ++} ++ ++var ( ++ comma = []byte{','} ++ emptyNameList = []string{} ++) ++ ++func parseNameList(in []byte) (out []string, rest []byte, ok bool) { ++ contents, rest, ok := parseString(in) ++ if !ok { ++ return ++ } ++ if len(contents) == 0 { ++ out = emptyNameList ++ return ++ } ++ parts := bytes.Split(contents, comma) ++ out = make([]string, len(parts)) ++ for i, part := range parts { ++ out[i] = string(part) ++ } ++ return ++} ++ ++func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { ++ contents, rest, ok := parseString(in) ++ if !ok { ++ return ++ } ++ out = new(big.Int) ++ ++ if len(contents) > 0 && contents[0]&0x80 == 0x80 { ++ // This is a negative number ++ notBytes := make([]byte, len(contents)) ++ for i := range notBytes { ++ notBytes[i] = ^contents[i] ++ } ++ out.SetBytes(notBytes) ++ out.Add(out, bigOne) ++ out.Neg(out) ++ } else { ++ // Positive number ++ out.SetBytes(contents) ++ } ++ ok = true ++ return ++} ++ ++func parseUint32(in []byte) (uint32, []byte, bool) { ++ if len(in) < 4 { ++ return 0, nil, false ++ } ++ return binary.BigEndian.Uint32(in), in[4:], true ++} ++ ++func parseUint64(in []byte) (uint64, []byte, bool) { ++ if len(in) < 8 { ++ return 0, nil, false ++ } ++ return binary.BigEndian.Uint64(in), in[8:], true ++} ++ ++func intLength(n *big.Int) int { ++ length := 4 /* length bytes */ ++ if n.Sign() < 0 { ++ nMinus1 := new(big.Int).Neg(n) ++ nMinus1.Sub(nMinus1, bigOne) ++ bitLen := nMinus1.BitLen() ++ if bitLen%8 == 0 { ++ // The number will need 0xff padding ++ length++ ++ } ++ length += (bitLen + 7) / 8 ++ } else if n.Sign() == 0 { ++ // A zero is the zero length string ++ } else { ++ bitLen := n.BitLen() ++ if bitLen%8 == 0 { ++ // The number will need 0x00 padding ++ length++ ++ } ++ length += (bitLen + 7) / 8 ++ } ++ ++ return length ++} ++ ++func marshalUint32(to []byte, n uint32) []byte { ++ binary.BigEndian.PutUint32(to, n) ++ return to[4:] ++} ++ ++func marshalUint64(to []byte, n uint64) []byte { ++ binary.BigEndian.PutUint64(to, n) ++ return to[8:] ++} ++ ++func marshalInt(to []byte, n *big.Int) []byte { ++ lengthBytes := to ++ to = to[4:] ++ length := 0 ++ ++ if n.Sign() < 0 { ++ // A negative number has to be converted to two's-complement ++ // form. So we'll subtract 1 and invert. If the ++ // most-significant-bit isn't set then we'll need to pad the ++ // beginning with 0xff in order to keep the number negative. ++ nMinus1 := new(big.Int).Neg(n) ++ nMinus1.Sub(nMinus1, bigOne) ++ bytes := nMinus1.Bytes() ++ for i := range bytes { ++ bytes[i] ^= 0xff ++ } ++ if len(bytes) == 0 || bytes[0]&0x80 == 0 { ++ to[0] = 0xff ++ to = to[1:] ++ length++ ++ } ++ nBytes := copy(to, bytes) ++ to = to[nBytes:] ++ length += nBytes ++ } else if n.Sign() == 0 { ++ // A zero is the zero length string ++ } else { ++ bytes := n.Bytes() ++ if len(bytes) > 0 && bytes[0]&0x80 != 0 { ++ // We'll have to pad this with a 0x00 in order to ++ // stop it looking like a negative number. ++ to[0] = 0 ++ to = to[1:] ++ length++ ++ } ++ nBytes := copy(to, bytes) ++ to = to[nBytes:] ++ length += nBytes ++ } ++ ++ lengthBytes[0] = byte(length >> 24) ++ lengthBytes[1] = byte(length >> 16) ++ lengthBytes[2] = byte(length >> 8) ++ lengthBytes[3] = byte(length) ++ return to ++} ++ ++func writeInt(w io.Writer, n *big.Int) { ++ length := intLength(n) ++ buf := make([]byte, length) ++ marshalInt(buf, n) ++ w.Write(buf) ++} ++ ++func writeString(w io.Writer, s []byte) { ++ var lengthBytes [4]byte ++ lengthBytes[0] = byte(len(s) >> 24) ++ lengthBytes[1] = byte(len(s) >> 16) ++ lengthBytes[2] = byte(len(s) >> 8) ++ lengthBytes[3] = byte(len(s)) ++ w.Write(lengthBytes[:]) ++ w.Write(s) ++} ++ ++func stringLength(n int) int { ++ return 4 + n ++} ++ ++func marshalString(to []byte, s []byte) []byte { ++ to[0] = byte(len(s) >> 24) ++ to[1] = byte(len(s) >> 16) ++ to[2] = byte(len(s) >> 8) ++ to[3] = byte(len(s)) ++ to = to[4:] ++ copy(to, s) ++ return to[len(s):] ++} ++ ++var bigIntType = reflect.TypeOf((*big.Int)(nil)) ++ ++// Decode a packet into its corresponding message. ++func decode(packet []byte) (interface{}, error) { ++ var msg interface{} ++ switch packet[0] { ++ case msgDisconnect: ++ msg = new(disconnectMsg) ++ case msgServiceRequest: ++ msg = new(serviceRequestMsg) ++ case msgServiceAccept: ++ msg = new(serviceAcceptMsg) ++ case msgExtInfo: ++ msg = new(extInfoMsg) ++ case msgKexInit: ++ msg = new(kexInitMsg) ++ case msgKexDHInit: ++ msg = new(kexDHInitMsg) ++ case msgKexDHReply: ++ msg = new(kexDHReplyMsg) ++ case msgUserAuthRequest: ++ msg = new(userAuthRequestMsg) ++ case msgUserAuthSuccess: ++ return new(userAuthSuccessMsg), nil ++ case msgUserAuthFailure: ++ msg = new(userAuthFailureMsg) ++ case msgUserAuthPubKeyOk: ++ msg = new(userAuthPubKeyOkMsg) ++ case msgGlobalRequest: ++ msg = new(globalRequestMsg) ++ case msgRequestSuccess: ++ msg = new(globalRequestSuccessMsg) ++ case msgRequestFailure: ++ msg = new(globalRequestFailureMsg) ++ case msgChannelOpen: ++ msg = new(channelOpenMsg) ++ case msgChannelData: ++ msg = new(channelDataMsg) ++ case msgChannelOpenConfirm: ++ msg = new(channelOpenConfirmMsg) ++ case msgChannelOpenFailure: ++ msg = new(channelOpenFailureMsg) ++ case msgChannelWindowAdjust: ++ msg = new(windowAdjustMsg) ++ case msgChannelEOF: ++ msg = new(channelEOFMsg) ++ case msgChannelClose: ++ msg = new(channelCloseMsg) ++ case msgChannelRequest: ++ msg = new(channelRequestMsg) ++ case msgChannelSuccess: ++ msg = new(channelRequestSuccessMsg) ++ case msgChannelFailure: ++ msg = new(channelRequestFailureMsg) ++ case msgUserAuthGSSAPIToken: ++ msg = new(userAuthGSSAPIToken) ++ case msgUserAuthGSSAPIMIC: ++ msg = new(userAuthGSSAPIMIC) ++ case msgUserAuthGSSAPIErrTok: ++ msg = new(userAuthGSSAPIErrTok) ++ case msgUserAuthGSSAPIError: ++ msg = new(userAuthGSSAPIError) ++ default: ++ return nil, unexpectedMessageError(0, packet[0]) ++ } ++ if err := Unmarshal(packet, msg); err != nil { ++ return nil, err ++ } ++ return msg, nil ++} ++ ++var packetTypeNames = map[byte]string{ ++ msgDisconnect: "disconnectMsg", ++ msgServiceRequest: "serviceRequestMsg", ++ msgServiceAccept: "serviceAcceptMsg", ++ msgExtInfo: "extInfoMsg", ++ msgKexInit: "kexInitMsg", ++ msgKexDHInit: "kexDHInitMsg", ++ msgKexDHReply: "kexDHReplyMsg", ++ msgUserAuthRequest: "userAuthRequestMsg", ++ msgUserAuthSuccess: "userAuthSuccessMsg", ++ msgUserAuthFailure: "userAuthFailureMsg", ++ msgUserAuthPubKeyOk: "userAuthPubKeyOkMsg", ++ msgGlobalRequest: "globalRequestMsg", ++ msgRequestSuccess: "globalRequestSuccessMsg", ++ msgRequestFailure: "globalRequestFailureMsg", ++ msgChannelOpen: "channelOpenMsg", ++ msgChannelData: "channelDataMsg", ++ msgChannelOpenConfirm: "channelOpenConfirmMsg", ++ msgChannelOpenFailure: "channelOpenFailureMsg", ++ msgChannelWindowAdjust: "windowAdjustMsg", ++ msgChannelEOF: "channelEOFMsg", ++ msgChannelClose: "channelCloseMsg", ++ msgChannelRequest: "channelRequestMsg", ++ msgChannelSuccess: "channelRequestSuccessMsg", ++ msgChannelFailure: "channelRequestFailureMsg", ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/messages_test.go b/ms_mod/golang.org/x/crypto/ssh/messages_test.go +new file mode 100644 +index 00000000000000..e79076412ab49f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/messages_test.go +@@ -0,0 +1,288 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "math/big" ++ "math/rand" ++ "reflect" ++ "testing" ++ "testing/quick" ++) ++ ++var intLengthTests = []struct { ++ val, length int ++}{ ++ {0, 4 + 0}, ++ {1, 4 + 1}, ++ {127, 4 + 1}, ++ {128, 4 + 2}, ++ {-1, 4 + 1}, ++} ++ ++func TestIntLength(t *testing.T) { ++ for _, test := range intLengthTests { ++ v := new(big.Int).SetInt64(int64(test.val)) ++ length := intLength(v) ++ if length != test.length { ++ t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) ++ } ++ } ++} ++ ++type msgAllTypes struct { ++ Bool bool `sshtype:"21"` ++ Array [16]byte ++ Uint64 uint64 ++ Uint32 uint32 ++ Uint8 uint8 ++ String string ++ Strings []string ++ Bytes []byte ++ Int *big.Int ++ Rest []byte `ssh:"rest"` ++} ++ ++func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value { ++ m := &msgAllTypes{} ++ m.Bool = rand.Intn(2) == 1 ++ randomBytes(m.Array[:], rand) ++ m.Uint64 = uint64(rand.Int63n(1<<63 - 1)) ++ m.Uint32 = uint32(rand.Intn((1 << 31) - 1)) ++ m.Uint8 = uint8(rand.Intn(1 << 8)) ++ m.String = string(m.Array[:]) ++ m.Strings = randomNameList(rand) ++ m.Bytes = m.Array[:] ++ m.Int = randomInt(rand) ++ m.Rest = m.Array[:] ++ return reflect.ValueOf(m) ++} ++ ++func TestMarshalUnmarshal(t *testing.T) { ++ rand := rand.New(rand.NewSource(0)) ++ iface := &msgAllTypes{} ++ ty := reflect.ValueOf(iface).Type() ++ ++ n := 100 ++ if testing.Short() { ++ n = 5 ++ } ++ for j := 0; j < n; j++ { ++ v, ok := quick.Value(ty, rand) ++ if !ok { ++ t.Errorf("failed to create value") ++ break ++ } ++ ++ m1 := v.Elem().Interface() ++ m2 := iface ++ ++ marshaled := Marshal(m1) ++ if err := Unmarshal(marshaled, m2); err != nil { ++ t.Errorf("Unmarshal %#v: %s", m1, err) ++ break ++ } ++ ++ if !reflect.DeepEqual(v.Interface(), m2) { ++ t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled) ++ break ++ } ++ } ++} ++ ++func TestUnmarshalEmptyPacket(t *testing.T) { ++ var b []byte ++ var m channelRequestSuccessMsg ++ if err := Unmarshal(b, &m); err == nil { ++ t.Fatalf("unmarshal of empty slice succeeded") ++ } ++} ++ ++func TestUnmarshalUnexpectedPacket(t *testing.T) { ++ type S struct { ++ I uint32 `sshtype:"43"` ++ S string ++ B bool ++ } ++ ++ s := S{11, "hello", true} ++ packet := Marshal(s) ++ packet[0] = 42 ++ roundtrip := S{} ++ err := Unmarshal(packet, &roundtrip) ++ if err == nil { ++ t.Fatal("expected error, not nil") ++ } ++} ++ ++func TestMarshalPtr(t *testing.T) { ++ s := struct { ++ S string ++ }{"hello"} ++ ++ m1 := Marshal(s) ++ m2 := Marshal(&s) ++ if !bytes.Equal(m1, m2) { ++ t.Errorf("got %q, want %q for marshaled pointer", m2, m1) ++ } ++} ++ ++func TestBareMarshalUnmarshal(t *testing.T) { ++ type S struct { ++ I uint32 ++ S string ++ B bool ++ } ++ ++ s := S{42, "hello", true} ++ packet := Marshal(s) ++ roundtrip := S{} ++ Unmarshal(packet, &roundtrip) ++ ++ if !reflect.DeepEqual(s, roundtrip) { ++ t.Errorf("got %#v, want %#v", roundtrip, s) ++ } ++} ++ ++func TestBareMarshal(t *testing.T) { ++ type S2 struct { ++ I uint32 ++ } ++ s := S2{42} ++ packet := Marshal(s) ++ i, rest, ok := parseUint32(packet) ++ if len(rest) > 0 || !ok { ++ t.Errorf("parseInt(%q): parse error", packet) ++ } ++ if i != s.I { ++ t.Errorf("got %d, want %d", i, s.I) ++ } ++} ++ ++func TestUnmarshalShortKexInitPacket(t *testing.T) { ++ // This used to panic. ++ // Issue 11348 ++ packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff} ++ kim := &kexInitMsg{} ++ if err := Unmarshal(packet, kim); err == nil { ++ t.Error("truncated packet unmarshaled without error") ++ } ++} ++ ++func TestMarshalMultiTag(t *testing.T) { ++ var res struct { ++ A uint32 `sshtype:"1|2"` ++ } ++ ++ good1 := struct { ++ A uint32 `sshtype:"1"` ++ }{ ++ 1, ++ } ++ good2 := struct { ++ A uint32 `sshtype:"2"` ++ }{ ++ 1, ++ } ++ ++ if e := Unmarshal(Marshal(good1), &res); e != nil { ++ t.Errorf("error unmarshaling multipart tag: %v", e) ++ } ++ ++ if e := Unmarshal(Marshal(good2), &res); e != nil { ++ t.Errorf("error unmarshaling multipart tag: %v", e) ++ } ++ ++ bad1 := struct { ++ A uint32 `sshtype:"3"` ++ }{ ++ 1, ++ } ++ if e := Unmarshal(Marshal(bad1), &res); e == nil { ++ t.Errorf("bad struct unmarshaled without error") ++ } ++} ++ ++func randomBytes(out []byte, rand *rand.Rand) { ++ for i := 0; i < len(out); i++ { ++ out[i] = byte(rand.Int31()) ++ } ++} ++ ++func randomNameList(rand *rand.Rand) []string { ++ ret := make([]string, rand.Int31()&15) ++ for i := range ret { ++ s := make([]byte, 1+(rand.Int31()&15)) ++ for j := range s { ++ s[j] = 'a' + uint8(rand.Int31()&15) ++ } ++ ret[i] = string(s) ++ } ++ return ret ++} ++ ++func randomInt(rand *rand.Rand) *big.Int { ++ return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) ++} ++ ++func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { ++ ki := &kexInitMsg{} ++ randomBytes(ki.Cookie[:], rand) ++ ki.KexAlgos = randomNameList(rand) ++ ki.ServerHostKeyAlgos = randomNameList(rand) ++ ki.CiphersClientServer = randomNameList(rand) ++ ki.CiphersServerClient = randomNameList(rand) ++ ki.MACsClientServer = randomNameList(rand) ++ ki.MACsServerClient = randomNameList(rand) ++ ki.CompressionClientServer = randomNameList(rand) ++ ki.CompressionServerClient = randomNameList(rand) ++ ki.LanguagesClientServer = randomNameList(rand) ++ ki.LanguagesServerClient = randomNameList(rand) ++ if rand.Int31()&1 == 1 { ++ ki.FirstKexFollows = true ++ } ++ return reflect.ValueOf(ki) ++} ++ ++func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { ++ dhi := &kexDHInitMsg{} ++ dhi.X = randomInt(rand) ++ return reflect.ValueOf(dhi) ++} ++ ++var ( ++ _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() ++ _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() ++ ++ _kexInit = Marshal(_kexInitMsg) ++ _kexDHInit = Marshal(_kexDHInitMsg) ++) ++ ++func BenchmarkMarshalKexInitMsg(b *testing.B) { ++ for i := 0; i < b.N; i++ { ++ Marshal(_kexInitMsg) ++ } ++} ++ ++func BenchmarkUnmarshalKexInitMsg(b *testing.B) { ++ m := new(kexInitMsg) ++ for i := 0; i < b.N; i++ { ++ Unmarshal(_kexInit, m) ++ } ++} ++ ++func BenchmarkMarshalKexDHInitMsg(b *testing.B) { ++ for i := 0; i < b.N; i++ { ++ Marshal(_kexDHInitMsg) ++ } ++} ++ ++func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) { ++ m := new(kexDHInitMsg) ++ for i := 0; i < b.N; i++ { ++ Unmarshal(_kexDHInit, m) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/mux.go b/ms_mod/golang.org/x/crypto/ssh/mux.go +new file mode 100644 +index 00000000000000..9654c01869ad1f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/mux.go +@@ -0,0 +1,351 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "encoding/binary" ++ "fmt" ++ "io" ++ "log" ++ "sync" ++ "sync/atomic" ++) ++ ++// debugMux, if set, causes messages in the connection protocol to be ++// logged. ++const debugMux = false ++ ++// chanList is a thread safe channel list. ++type chanList struct { ++ // protects concurrent access to chans ++ sync.Mutex ++ ++ // chans are indexed by the local id of the channel, which the ++ // other side should send in the PeersId field. ++ chans []*channel ++ ++ // This is a debugging aid: it offsets all IDs by this ++ // amount. This helps distinguish otherwise identical ++ // server/client muxes ++ offset uint32 ++} ++ ++// Assigns a channel ID to the given channel. ++func (c *chanList) add(ch *channel) uint32 { ++ c.Lock() ++ defer c.Unlock() ++ for i := range c.chans { ++ if c.chans[i] == nil { ++ c.chans[i] = ch ++ return uint32(i) + c.offset ++ } ++ } ++ c.chans = append(c.chans, ch) ++ return uint32(len(c.chans)-1) + c.offset ++} ++ ++// getChan returns the channel for the given ID. ++func (c *chanList) getChan(id uint32) *channel { ++ id -= c.offset ++ ++ c.Lock() ++ defer c.Unlock() ++ if id < uint32(len(c.chans)) { ++ return c.chans[id] ++ } ++ return nil ++} ++ ++func (c *chanList) remove(id uint32) { ++ id -= c.offset ++ c.Lock() ++ if id < uint32(len(c.chans)) { ++ c.chans[id] = nil ++ } ++ c.Unlock() ++} ++ ++// dropAll forgets all channels it knows, returning them in a slice. ++func (c *chanList) dropAll() []*channel { ++ c.Lock() ++ defer c.Unlock() ++ var r []*channel ++ ++ for _, ch := range c.chans { ++ if ch == nil { ++ continue ++ } ++ r = append(r, ch) ++ } ++ c.chans = nil ++ return r ++} ++ ++// mux represents the state for the SSH connection protocol, which ++// multiplexes many channels onto a single packet transport. ++type mux struct { ++ conn packetConn ++ chanList chanList ++ ++ incomingChannels chan NewChannel ++ ++ globalSentMu sync.Mutex ++ globalResponses chan interface{} ++ incomingRequests chan *Request ++ ++ errCond *sync.Cond ++ err error ++} ++ ++// When debugging, each new chanList instantiation has a different ++// offset. ++var globalOff uint32 ++ ++func (m *mux) Wait() error { ++ m.errCond.L.Lock() ++ defer m.errCond.L.Unlock() ++ for m.err == nil { ++ m.errCond.Wait() ++ } ++ return m.err ++} ++ ++// newMux returns a mux that runs over the given connection. ++func newMux(p packetConn) *mux { ++ m := &mux{ ++ conn: p, ++ incomingChannels: make(chan NewChannel, chanSize), ++ globalResponses: make(chan interface{}, 1), ++ incomingRequests: make(chan *Request, chanSize), ++ errCond: newCond(), ++ } ++ if debugMux { ++ m.chanList.offset = atomic.AddUint32(&globalOff, 1) ++ } ++ ++ go m.loop() ++ return m ++} ++ ++func (m *mux) sendMessage(msg interface{}) error { ++ p := Marshal(msg) ++ if debugMux { ++ log.Printf("send global(%d): %#v", m.chanList.offset, msg) ++ } ++ return m.conn.writePacket(p) ++} ++ ++func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { ++ if wantReply { ++ m.globalSentMu.Lock() ++ defer m.globalSentMu.Unlock() ++ } ++ ++ if err := m.sendMessage(globalRequestMsg{ ++ Type: name, ++ WantReply: wantReply, ++ Data: payload, ++ }); err != nil { ++ return false, nil, err ++ } ++ ++ if !wantReply { ++ return false, nil, nil ++ } ++ ++ msg, ok := <-m.globalResponses ++ if !ok { ++ return false, nil, io.EOF ++ } ++ switch msg := msg.(type) { ++ case *globalRequestFailureMsg: ++ return false, msg.Data, nil ++ case *globalRequestSuccessMsg: ++ return true, msg.Data, nil ++ default: ++ return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) ++ } ++} ++ ++// ackRequest must be called after processing a global request that ++// has WantReply set. ++func (m *mux) ackRequest(ok bool, data []byte) error { ++ if ok { ++ return m.sendMessage(globalRequestSuccessMsg{Data: data}) ++ } ++ return m.sendMessage(globalRequestFailureMsg{Data: data}) ++} ++ ++func (m *mux) Close() error { ++ return m.conn.Close() ++} ++ ++// loop runs the connection machine. It will process packets until an ++// error is encountered. To synchronize on loop exit, use mux.Wait. ++func (m *mux) loop() { ++ var err error ++ for err == nil { ++ err = m.onePacket() ++ } ++ ++ for _, ch := range m.chanList.dropAll() { ++ ch.close() ++ } ++ ++ close(m.incomingChannels) ++ close(m.incomingRequests) ++ close(m.globalResponses) ++ ++ m.conn.Close() ++ ++ m.errCond.L.Lock() ++ m.err = err ++ m.errCond.Broadcast() ++ m.errCond.L.Unlock() ++ ++ if debugMux { ++ log.Println("loop exit", err) ++ } ++} ++ ++// onePacket reads and processes one packet. ++func (m *mux) onePacket() error { ++ packet, err := m.conn.readPacket() ++ if err != nil { ++ return err ++ } ++ ++ if debugMux { ++ if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { ++ log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) ++ } else { ++ p, _ := decode(packet) ++ log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) ++ } ++ } ++ ++ switch packet[0] { ++ case msgChannelOpen: ++ return m.handleChannelOpen(packet) ++ case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: ++ return m.handleGlobalPacket(packet) ++ } ++ ++ // assume a channel packet. ++ if len(packet) < 5 { ++ return parseError(packet[0]) ++ } ++ id := binary.BigEndian.Uint32(packet[1:]) ++ ch := m.chanList.getChan(id) ++ if ch == nil { ++ return m.handleUnknownChannelPacket(id, packet) ++ } ++ ++ return ch.handlePacket(packet) ++} ++ ++func (m *mux) handleGlobalPacket(packet []byte) error { ++ msg, err := decode(packet) ++ if err != nil { ++ return err ++ } ++ ++ switch msg := msg.(type) { ++ case *globalRequestMsg: ++ m.incomingRequests <- &Request{ ++ Type: msg.Type, ++ WantReply: msg.WantReply, ++ Payload: msg.Data, ++ mux: m, ++ } ++ case *globalRequestSuccessMsg, *globalRequestFailureMsg: ++ m.globalResponses <- msg ++ default: ++ panic(fmt.Sprintf("not a global message %#v", msg)) ++ } ++ ++ return nil ++} ++ ++// handleChannelOpen schedules a channel to be Accept()ed. ++func (m *mux) handleChannelOpen(packet []byte) error { ++ var msg channelOpenMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return err ++ } ++ ++ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { ++ failMsg := channelOpenFailureMsg{ ++ PeersID: msg.PeersID, ++ Reason: ConnectionFailed, ++ Message: "invalid request", ++ Language: "en_US.UTF-8", ++ } ++ return m.sendMessage(failMsg) ++ } ++ ++ c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) ++ c.remoteId = msg.PeersID ++ c.maxRemotePayload = msg.MaxPacketSize ++ c.remoteWin.add(msg.PeersWindow) ++ m.incomingChannels <- c ++ return nil ++} ++ ++func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { ++ ch, err := m.openChannel(chanType, extra) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ return ch, ch.incomingRequests, nil ++} ++ ++func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { ++ ch := m.newChannel(chanType, channelOutbound, extra) ++ ++ ch.maxIncomingPayload = channelMaxPacket ++ ++ open := channelOpenMsg{ ++ ChanType: chanType, ++ PeersWindow: ch.myWindow, ++ MaxPacketSize: ch.maxIncomingPayload, ++ TypeSpecificData: extra, ++ PeersID: ch.localId, ++ } ++ if err := m.sendMessage(open); err != nil { ++ return nil, err ++ } ++ ++ switch msg := (<-ch.msg).(type) { ++ case *channelOpenConfirmMsg: ++ return ch, nil ++ case *channelOpenFailureMsg: ++ return nil, &OpenChannelError{msg.Reason, msg.Message} ++ default: ++ return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) ++ } ++} ++ ++func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) error { ++ msg, err := decode(packet) ++ if err != nil { ++ return err ++ } ++ ++ switch msg := msg.(type) { ++ // RFC 4254 section 5.4 says unrecognized channel requests should ++ // receive a failure response. ++ case *channelRequestMsg: ++ if msg.WantReply { ++ return m.sendMessage(channelRequestFailureMsg{ ++ PeersID: msg.PeersID, ++ }) ++ } ++ return nil ++ default: ++ return fmt.Errorf("ssh: invalid channel %d", id) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/mux_test.go b/ms_mod/golang.org/x/crypto/ssh/mux_test.go +new file mode 100644 +index 00000000000000..1db3be54a0318f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/mux_test.go +@@ -0,0 +1,761 @@ ++// Copyright 2013 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ "sync" ++ "testing" ++ "time" ++) ++ ++func muxPair() (*mux, *mux) { ++ a, b := memPipe() ++ ++ s := newMux(a) ++ c := newMux(b) ++ ++ return s, c ++} ++ ++// Returns both ends of a channel, and the mux for the 2nd ++// channel. ++func channelPair(t *testing.T) (*channel, *channel, *mux) { ++ c, s := muxPair() ++ ++ res := make(chan *channel, 1) ++ go func() { ++ newCh, ok := <-s.incomingChannels ++ if !ok { ++ t.Error("no incoming channel") ++ close(res) ++ return ++ } ++ if newCh.ChannelType() != "chan" { ++ t.Errorf("got type %q want chan", newCh.ChannelType()) ++ newCh.Reject(Prohibited, fmt.Sprintf("got type %q want chan", newCh.ChannelType())) ++ close(res) ++ return ++ } ++ ch, _, err := newCh.Accept() ++ if err != nil { ++ t.Errorf("accept: %v", err) ++ close(res) ++ return ++ } ++ res <- ch.(*channel) ++ }() ++ ++ ch, err := c.openChannel("chan", nil) ++ if err != nil { ++ t.Fatalf("OpenChannel: %v", err) ++ } ++ w := <-res ++ if w == nil { ++ t.Fatal("unable to get write channel") ++ } ++ ++ return w, ch, c ++} ++ ++// Test that stderr and stdout can be addressed from different ++// goroutines. This is intended for use with the race detector. ++func TestMuxChannelExtendedThreadSafety(t *testing.T) { ++ writer, reader, mux := channelPair(t) ++ defer writer.Close() ++ defer reader.Close() ++ defer mux.Close() ++ ++ var wr, rd sync.WaitGroup ++ magic := "hello world" ++ ++ wr.Add(2) ++ go func() { ++ io.WriteString(writer, magic) ++ wr.Done() ++ }() ++ go func() { ++ io.WriteString(writer.Stderr(), magic) ++ wr.Done() ++ }() ++ ++ rd.Add(2) ++ go func() { ++ c, err := io.ReadAll(reader) ++ if string(c) != magic { ++ t.Errorf("stdout read got %q, want %q (error %s)", c, magic, err) ++ } ++ rd.Done() ++ }() ++ go func() { ++ c, err := io.ReadAll(reader.Stderr()) ++ if string(c) != magic { ++ t.Errorf("stderr read got %q, want %q (error %s)", c, magic, err) ++ } ++ rd.Done() ++ }() ++ ++ wr.Wait() ++ writer.CloseWrite() ++ rd.Wait() ++} ++ ++func TestMuxReadWrite(t *testing.T) { ++ s, c, mux := channelPair(t) ++ defer s.Close() ++ defer c.Close() ++ defer mux.Close() ++ ++ magic := "hello world" ++ magicExt := "hello stderr" ++ go func() { ++ _, err := s.Write([]byte(magic)) ++ if err != nil { ++ t.Errorf("Write: %v", err) ++ return ++ } ++ _, err = s.Extended(1).Write([]byte(magicExt)) ++ if err != nil { ++ t.Errorf("Write: %v", err) ++ return ++ } ++ }() ++ ++ var buf [1024]byte ++ n, err := c.Read(buf[:]) ++ if err != nil { ++ t.Fatalf("server Read: %v", err) ++ } ++ got := string(buf[:n]) ++ if got != magic { ++ t.Fatalf("server: got %q want %q", got, magic) ++ } ++ ++ n, err = c.Extended(1).Read(buf[:]) ++ if err != nil { ++ t.Fatalf("server Read: %v", err) ++ } ++ ++ got = string(buf[:n]) ++ if got != magicExt { ++ t.Fatalf("server: got %q want %q", got, magic) ++ } ++} ++ ++func TestMuxChannelOverflow(t *testing.T) { ++ reader, writer, mux := channelPair(t) ++ defer reader.Close() ++ defer writer.Close() ++ defer mux.Close() ++ ++ wDone := make(chan int, 1) ++ go func() { ++ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { ++ t.Errorf("could not fill window: %v", err) ++ } ++ writer.Write(make([]byte, 1)) ++ wDone <- 1 ++ }() ++ writer.remoteWin.waitWriterBlocked() ++ ++ // Send 1 byte. ++ packet := make([]byte, 1+4+4+1) ++ packet[0] = msgChannelData ++ marshalUint32(packet[1:], writer.remoteId) ++ marshalUint32(packet[5:], uint32(1)) ++ packet[9] = 42 ++ ++ if err := writer.mux.conn.writePacket(packet); err != nil { ++ t.Errorf("could not send packet") ++ } ++ if _, err := reader.SendRequest("hello", true, nil); err == nil { ++ t.Errorf("SendRequest succeeded.") ++ } ++ <-wDone ++} ++ ++func TestMuxChannelCloseWriteUnblock(t *testing.T) { ++ reader, writer, mux := channelPair(t) ++ defer reader.Close() ++ defer writer.Close() ++ defer mux.Close() ++ ++ wDone := make(chan int, 1) ++ go func() { ++ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { ++ t.Errorf("could not fill window: %v", err) ++ } ++ if _, err := writer.Write(make([]byte, 1)); err != io.EOF { ++ t.Errorf("got %v, want EOF for unblock write", err) ++ } ++ wDone <- 1 ++ }() ++ ++ writer.remoteWin.waitWriterBlocked() ++ reader.Close() ++ <-wDone ++} ++ ++func TestMuxConnectionCloseWriteUnblock(t *testing.T) { ++ reader, writer, mux := channelPair(t) ++ defer reader.Close() ++ defer writer.Close() ++ defer mux.Close() ++ ++ wDone := make(chan int, 1) ++ go func() { ++ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { ++ t.Errorf("could not fill window: %v", err) ++ } ++ if _, err := writer.Write(make([]byte, 1)); err != io.EOF { ++ t.Errorf("got %v, want EOF for unblock write", err) ++ } ++ wDone <- 1 ++ }() ++ ++ writer.remoteWin.waitWriterBlocked() ++ mux.Close() ++ <-wDone ++} ++ ++func TestMuxReject(t *testing.T) { ++ client, server := muxPair() ++ defer server.Close() ++ defer client.Close() ++ ++ go func() { ++ ch, ok := <-server.incomingChannels ++ if !ok { ++ t.Error("cannot accept channel") ++ return ++ } ++ if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" { ++ t.Errorf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) ++ ch.Reject(RejectionReason(UnknownChannelType), UnknownChannelType.String()) ++ return ++ } ++ ch.Reject(RejectionReason(42), "message") ++ }() ++ ++ ch, err := client.openChannel("ch", []byte("extra")) ++ if ch != nil { ++ t.Fatal("openChannel not rejected") ++ } ++ ++ ocf, ok := err.(*OpenChannelError) ++ if !ok { ++ t.Errorf("got %#v want *OpenChannelError", err) ++ } else if ocf.Reason != 42 || ocf.Message != "message" { ++ t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message") ++ } ++ ++ want := "ssh: rejected: unknown reason 42 (message)" ++ if err.Error() != want { ++ t.Errorf("got %q, want %q", err.Error(), want) ++ } ++} ++ ++func TestMuxChannelRequest(t *testing.T) { ++ client, server, mux := channelPair(t) ++ defer server.Close() ++ defer client.Close() ++ defer mux.Close() ++ ++ var received int ++ var wg sync.WaitGroup ++ wg.Add(1) ++ go func() { ++ for r := range server.incomingRequests { ++ received++ ++ r.Reply(r.Type == "yes", nil) ++ } ++ wg.Done() ++ }() ++ _, err := client.SendRequest("yes", false, nil) ++ if err != nil { ++ t.Fatalf("SendRequest: %v", err) ++ } ++ ok, err := client.SendRequest("yes", true, nil) ++ if err != nil { ++ t.Fatalf("SendRequest: %v", err) ++ } ++ ++ if !ok { ++ t.Errorf("SendRequest(yes): %v", ok) ++ ++ } ++ ++ ok, err = client.SendRequest("no", true, nil) ++ if err != nil { ++ t.Fatalf("SendRequest: %v", err) ++ } ++ if ok { ++ t.Errorf("SendRequest(no): %v", ok) ++ ++ } ++ ++ client.Close() ++ wg.Wait() ++ ++ if received != 3 { ++ t.Errorf("got %d requests, want %d", received, 3) ++ } ++} ++ ++func TestMuxUnknownChannelRequests(t *testing.T) { ++ clientPipe, serverPipe := memPipe() ++ client := newMux(clientPipe) ++ defer serverPipe.Close() ++ defer client.Close() ++ ++ kDone := make(chan error, 1) ++ go func() { ++ // Ignore unknown channel messages that don't want a reply. ++ err := serverPipe.writePacket(Marshal(channelRequestMsg{ ++ PeersID: 1, ++ Request: "keepalive@openssh.com", ++ WantReply: false, ++ RequestSpecificData: []byte{}, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("send: %w", err) ++ return ++ } ++ ++ // Send a keepalive, which should get a channel failure message ++ // in response. ++ err = serverPipe.writePacket(Marshal(channelRequestMsg{ ++ PeersID: 2, ++ Request: "keepalive@openssh.com", ++ WantReply: true, ++ RequestSpecificData: []byte{}, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("send: %w", err) ++ return ++ } ++ ++ packet, err := serverPipe.readPacket() ++ if err != nil { ++ kDone <- fmt.Errorf("read packet: %w", err) ++ return ++ } ++ decoded, err := decode(packet) ++ if err != nil { ++ kDone <- fmt.Errorf("decode failed: %w", err) ++ return ++ } ++ ++ switch msg := decoded.(type) { ++ case *channelRequestFailureMsg: ++ if msg.PeersID != 2 { ++ kDone <- fmt.Errorf("received response to wrong message: %v", msg) ++ return ++ ++ } ++ default: ++ kDone <- fmt.Errorf("unexpected channel message: %v", msg) ++ return ++ } ++ ++ kDone <- nil ++ ++ // Receive and respond to the keepalive to confirm the mux is ++ // still processing requests. ++ packet, err = serverPipe.readPacket() ++ if err != nil { ++ kDone <- fmt.Errorf("read packet: %w", err) ++ return ++ } ++ if packet[0] != msgGlobalRequest { ++ kDone <- errors.New("expected global request") ++ return ++ } ++ ++ err = serverPipe.writePacket(Marshal(globalRequestFailureMsg{ ++ Data: []byte{}, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("failed to send failure msg: %w", err) ++ return ++ } ++ ++ close(kDone) ++ }() ++ ++ // Wait for the server to send the keepalive message and receive back a ++ // response. ++ select { ++ case err := <-kDone: ++ if err != nil { ++ t.Fatal(err) ++ } ++ case <-time.After(10 * time.Second): ++ t.Fatalf("server never received ack") ++ } ++ ++ // Confirm client hasn't closed. ++ if _, _, err := client.SendRequest("keepalive@golang.org", true, nil); err != nil { ++ t.Fatalf("failed to send keepalive: %v", err) ++ } ++ ++ select { ++ case err := <-kDone: ++ if err != nil { ++ t.Fatal(err) ++ } ++ case <-time.After(10 * time.Second): ++ t.Fatalf("server never shut down") ++ } ++} ++ ++func TestMuxClosedChannel(t *testing.T) { ++ clientPipe, serverPipe := memPipe() ++ client := newMux(clientPipe) ++ defer serverPipe.Close() ++ defer client.Close() ++ ++ kDone := make(chan error, 1) ++ go func() { ++ // Open the channel. ++ packet, err := serverPipe.readPacket() ++ if err != nil { ++ kDone <- fmt.Errorf("read packet: %w", err) ++ return ++ } ++ if packet[0] != msgChannelOpen { ++ kDone <- errors.New("expected chan open") ++ return ++ } ++ ++ var openMsg channelOpenMsg ++ if err := Unmarshal(packet, &openMsg); err != nil { ++ kDone <- fmt.Errorf("unmarshal: %w", err) ++ return ++ } ++ ++ // Send back the opened channel confirmation. ++ err = serverPipe.writePacket(Marshal(channelOpenConfirmMsg{ ++ PeersID: openMsg.PeersID, ++ MyID: 0, ++ MyWindow: 0, ++ MaxPacketSize: channelMaxPacket, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("send: %w", err) ++ return ++ } ++ ++ // Close the channel. ++ err = serverPipe.writePacket(Marshal(channelCloseMsg{ ++ PeersID: openMsg.PeersID, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("send: %w", err) ++ return ++ } ++ ++ // Send a keepalive message on the channel we just closed. ++ err = serverPipe.writePacket(Marshal(channelRequestMsg{ ++ PeersID: openMsg.PeersID, ++ Request: "keepalive@openssh.com", ++ WantReply: true, ++ RequestSpecificData: []byte{}, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("send: %w", err) ++ return ++ } ++ ++ // Receive the channel closed response. ++ packet, err = serverPipe.readPacket() ++ if err != nil { ++ kDone <- fmt.Errorf("read packet: %w", err) ++ return ++ } ++ if packet[0] != msgChannelClose { ++ kDone <- errors.New("expected channel close") ++ return ++ } ++ ++ // Receive the keepalive response failure. ++ packet, err = serverPipe.readPacket() ++ if err != nil { ++ kDone <- fmt.Errorf("read packet: %w", err) ++ return ++ } ++ if packet[0] != msgChannelFailure { ++ kDone <- errors.New("expected channel failure") ++ return ++ } ++ kDone <- nil ++ ++ // Receive and respond to the keepalive to confirm the mux is ++ // still processing requests. ++ packet, err = serverPipe.readPacket() ++ if err != nil { ++ kDone <- fmt.Errorf("read packet: %w", err) ++ return ++ } ++ if packet[0] != msgGlobalRequest { ++ kDone <- errors.New("expected global request") ++ return ++ } ++ ++ err = serverPipe.writePacket(Marshal(globalRequestFailureMsg{ ++ Data: []byte{}, ++ })) ++ if err != nil { ++ kDone <- fmt.Errorf("failed to send failure msg: %w", err) ++ return ++ } ++ ++ close(kDone) ++ }() ++ ++ // Open a channel. ++ ch, err := client.openChannel("chan", nil) ++ if err != nil { ++ t.Fatalf("OpenChannel: %v", err) ++ } ++ defer ch.Close() ++ ++ // Wait for the server to close the channel and send the keepalive. ++ select { ++ case <-kDone: ++ case <-time.After(10 * time.Second): ++ t.Fatalf("server never received ack") ++ } ++ ++ // Make sure the channel closed. ++ if _, ok := <-ch.incomingRequests; ok { ++ t.Fatalf("channel not closed") ++ } ++ ++ // Confirm client hasn't closed ++ if _, _, err := client.SendRequest("keepalive@golang.org", true, nil); err != nil { ++ t.Fatalf("failed to send keepalive: %v", err) ++ } ++ ++ select { ++ case <-kDone: ++ case <-time.After(10 * time.Second): ++ t.Fatalf("server never shut down") ++ } ++} ++ ++func TestMuxGlobalRequest(t *testing.T) { ++ clientMux, serverMux := muxPair() ++ defer serverMux.Close() ++ defer clientMux.Close() ++ ++ var seen bool ++ go func() { ++ for r := range serverMux.incomingRequests { ++ seen = seen || r.Type == "peek" ++ if r.WantReply { ++ err := r.Reply(r.Type == "yes", ++ append([]byte(r.Type), r.Payload...)) ++ if err != nil { ++ t.Errorf("AckRequest: %v", err) ++ } ++ } ++ } ++ }() ++ ++ _, _, err := clientMux.SendRequest("peek", false, nil) ++ if err != nil { ++ t.Errorf("SendRequest: %v", err) ++ } ++ ++ ok, data, err := clientMux.SendRequest("yes", true, []byte("a")) ++ if !ok || string(data) != "yesa" || err != nil { ++ t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", ++ ok, data, err) ++ } ++ if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil { ++ t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", ++ ok, data, err) ++ } ++ ++ if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil { ++ t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v", ++ ok, data, err) ++ } ++ ++ if !seen { ++ t.Errorf("never saw 'peek' request") ++ } ++} ++ ++func TestMuxGlobalRequestUnblock(t *testing.T) { ++ clientMux, serverMux := muxPair() ++ defer serverMux.Close() ++ defer clientMux.Close() ++ ++ result := make(chan error, 1) ++ go func() { ++ _, _, err := clientMux.SendRequest("hello", true, nil) ++ result <- err ++ }() ++ ++ <-serverMux.incomingRequests ++ serverMux.conn.Close() ++ err := <-result ++ ++ if err != io.EOF { ++ t.Errorf("want EOF, got %v", io.EOF) ++ } ++} ++ ++func TestMuxChannelRequestUnblock(t *testing.T) { ++ a, b, connB := channelPair(t) ++ defer a.Close() ++ defer b.Close() ++ defer connB.Close() ++ ++ result := make(chan error, 1) ++ go func() { ++ _, err := a.SendRequest("hello", true, nil) ++ result <- err ++ }() ++ ++ <-b.incomingRequests ++ connB.conn.Close() ++ err := <-result ++ ++ if err != io.EOF { ++ t.Errorf("want EOF, got %v", err) ++ } ++} ++ ++func TestMuxCloseChannel(t *testing.T) { ++ r, w, mux := channelPair(t) ++ defer mux.Close() ++ defer r.Close() ++ defer w.Close() ++ ++ result := make(chan error, 1) ++ go func() { ++ var b [1024]byte ++ _, err := r.Read(b[:]) ++ result <- err ++ }() ++ if err := w.Close(); err != nil { ++ t.Errorf("w.Close: %v", err) ++ } ++ ++ if _, err := w.Write([]byte("hello")); err != io.EOF { ++ t.Errorf("got err %v, want io.EOF after Close", err) ++ } ++ ++ if err := <-result; err != io.EOF { ++ t.Errorf("got %v (%T), want io.EOF", err, err) ++ } ++} ++ ++func TestMuxCloseWriteChannel(t *testing.T) { ++ r, w, mux := channelPair(t) ++ defer mux.Close() ++ ++ result := make(chan error, 1) ++ go func() { ++ var b [1024]byte ++ _, err := r.Read(b[:]) ++ result <- err ++ }() ++ if err := w.CloseWrite(); err != nil { ++ t.Errorf("w.CloseWrite: %v", err) ++ } ++ ++ if _, err := w.Write([]byte("hello")); err != io.EOF { ++ t.Errorf("got err %v, want io.EOF after CloseWrite", err) ++ } ++ ++ if err := <-result; err != io.EOF { ++ t.Errorf("got %v (%T), want io.EOF", err, err) ++ } ++} ++ ++func TestMuxInvalidRecord(t *testing.T) { ++ a, b := muxPair() ++ defer a.Close() ++ defer b.Close() ++ ++ packet := make([]byte, 1+4+4+1) ++ packet[0] = msgChannelData ++ marshalUint32(packet[1:], 29348723 /* invalid channel id */) ++ marshalUint32(packet[5:], 1) ++ packet[9] = 42 ++ ++ a.conn.writePacket(packet) ++ go a.SendRequest("hello", false, nil) ++ // 'a' wrote an invalid packet, so 'b' has exited. ++ req, ok := <-b.incomingRequests ++ if ok { ++ t.Errorf("got request %#v after receiving invalid packet", req) ++ } ++} ++ ++func TestZeroWindowAdjust(t *testing.T) { ++ a, b, mux := channelPair(t) ++ defer a.Close() ++ defer b.Close() ++ defer mux.Close() ++ ++ go func() { ++ io.WriteString(a, "hello") ++ // bogus adjust. ++ a.sendMessage(windowAdjustMsg{}) ++ io.WriteString(a, "world") ++ a.Close() ++ }() ++ ++ want := "helloworld" ++ c, _ := io.ReadAll(b) ++ if string(c) != want { ++ t.Errorf("got %q want %q", c, want) ++ } ++} ++ ++func TestMuxMaxPacketSize(t *testing.T) { ++ a, b, mux := channelPair(t) ++ defer a.Close() ++ defer b.Close() ++ defer mux.Close() ++ ++ large := make([]byte, a.maxRemotePayload+1) ++ packet := make([]byte, 1+4+4+1+len(large)) ++ packet[0] = msgChannelData ++ marshalUint32(packet[1:], a.remoteId) ++ marshalUint32(packet[5:], uint32(len(large))) ++ packet[9] = 42 ++ ++ if err := a.mux.conn.writePacket(packet); err != nil { ++ t.Errorf("could not send packet") ++ } ++ ++ go a.SendRequest("hello", false, nil) ++ ++ _, ok := <-b.incomingRequests ++ if ok { ++ t.Errorf("connection still alive after receiving large packet.") ++ } ++} ++ ++// Don't ship code with debug=true. ++func TestDebug(t *testing.T) { ++ if debugMux { ++ t.Error("mux debug switched on") ++ } ++ if debugHandshake { ++ t.Error("handshake debug switched on") ++ } ++ if debugTransport { ++ t.Error("transport debug switched on") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/server.go b/ms_mod/golang.org/x/crypto/ssh/server.go +new file mode 100644 +index 00000000000000..b21322affa8a7a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/server.go +@@ -0,0 +1,774 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "io" ++ "net" ++ "strings" ++) ++ ++// The Permissions type holds fine-grained permissions that are ++// specific to a user or a specific authentication method for a user. ++// The Permissions value for a successful authentication attempt is ++// available in ServerConn, so it can be used to pass information from ++// the user-authentication phase to the application layer. ++type Permissions struct { ++ // CriticalOptions indicate restrictions to the default ++ // permissions, and are typically used in conjunction with ++ // user certificates. The standard for SSH certificates ++ // defines "force-command" (only allow the given command to ++ // execute) and "source-address" (only allow connections from ++ // the given address). The SSH package currently only enforces ++ // the "source-address" critical option. It is up to server ++ // implementations to enforce other critical options, such as ++ // "force-command", by checking them after the SSH handshake ++ // is successful. In general, SSH servers should reject ++ // connections that specify critical options that are unknown ++ // or not supported. ++ CriticalOptions map[string]string ++ ++ // Extensions are extra functionality that the server may ++ // offer on authenticated connections. Lack of support for an ++ // extension does not preclude authenticating a user. Common ++ // extensions are "permit-agent-forwarding", ++ // "permit-X11-forwarding". The Go SSH library currently does ++ // not act on any extension, and it is up to server ++ // implementations to honor them. Extensions can be used to ++ // pass data from the authentication callbacks to the server ++ // application layer. ++ Extensions map[string]string ++} ++ ++type GSSAPIWithMICConfig struct { ++ // AllowLogin, must be set, is called when gssapi-with-mic ++ // authentication is selected (RFC 4462 section 3). The srcName is from the ++ // results of the GSS-API authentication. The format is username@DOMAIN. ++ // GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions. ++ // This callback is called after the user identity is established with GSSAPI to decide if the user can login with ++ // which permissions. If the user is allowed to login, it should return a nil error. ++ AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error) ++ ++ // Server must be set. It's the implementation ++ // of the GSSAPIServer interface. See GSSAPIServer interface for details. ++ Server GSSAPIServer ++} ++ ++// ServerConfig holds server specific configuration data. ++type ServerConfig struct { ++ // Config contains configuration shared between client and server. ++ Config ++ ++ hostKeys []Signer ++ ++ // NoClientAuth is true if clients are allowed to connect without ++ // authenticating. ++ // To determine NoClientAuth at runtime, set NoClientAuth to true ++ // and the optional NoClientAuthCallback to a non-nil value. ++ NoClientAuth bool ++ ++ // NoClientAuthCallback, if non-nil, is called when a user ++ // attempts to authenticate with auth method "none". ++ // NoClientAuth must also be set to true for this be used, or ++ // this func is unused. ++ NoClientAuthCallback func(ConnMetadata) (*Permissions, error) ++ ++ // MaxAuthTries specifies the maximum number of authentication attempts ++ // permitted per connection. If set to a negative number, the number of ++ // attempts are unlimited. If set to zero, the number of attempts are limited ++ // to 6. ++ MaxAuthTries int ++ ++ // PasswordCallback, if non-nil, is called when a user ++ // attempts to authenticate using a password. ++ PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) ++ ++ // PublicKeyCallback, if non-nil, is called when a client ++ // offers a public key for authentication. It must return a nil error ++ // if the given public key can be used to authenticate the ++ // given user. For example, see CertChecker.Authenticate. A ++ // call to this function does not guarantee that the key ++ // offered is in fact used to authenticate. To record any data ++ // depending on the public key, store it inside a ++ // Permissions.Extensions entry. ++ PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) ++ ++ // KeyboardInteractiveCallback, if non-nil, is called when ++ // keyboard-interactive authentication is selected (RFC ++ // 4256). The client object's Challenge function should be ++ // used to query the user. The callback may offer multiple ++ // Challenge rounds. To avoid information leaks, the client ++ // should be presented a challenge even if the user is ++ // unknown. ++ KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) ++ ++ // AuthLogCallback, if non-nil, is called to log all authentication ++ // attempts. ++ AuthLogCallback func(conn ConnMetadata, method string, err error) ++ ++ // ServerVersion is the version identification string to announce in ++ // the public handshake. ++ // If empty, a reasonable default is used. ++ // Note that RFC 4253 section 4.2 requires that this string start with ++ // "SSH-2.0-". ++ ServerVersion string ++ ++ // BannerCallback, if present, is called and the return string is sent to ++ // the client after key exchange completed but before authentication. ++ BannerCallback func(conn ConnMetadata) string ++ ++ // GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used ++ // when gssapi-with-mic authentication is selected (RFC 4462 section 3). ++ GSSAPIWithMICConfig *GSSAPIWithMICConfig ++} ++ ++// AddHostKey adds a private key as a host key. If an existing host ++// key exists with the same public key format, it is replaced. Each server ++// config must have at least one host key. ++func (s *ServerConfig) AddHostKey(key Signer) { ++ for i, k := range s.hostKeys { ++ if k.PublicKey().Type() == key.PublicKey().Type() { ++ s.hostKeys[i] = key ++ return ++ } ++ } ++ ++ s.hostKeys = append(s.hostKeys, key) ++} ++ ++// cachedPubKey contains the results of querying whether a public key is ++// acceptable for a user. ++type cachedPubKey struct { ++ user string ++ pubKeyData []byte ++ result error ++ perms *Permissions ++} ++ ++const maxCachedPubKeys = 16 ++ ++// pubKeyCache caches tests for public keys. Since SSH clients ++// will query whether a public key is acceptable before attempting to ++// authenticate with it, we end up with duplicate queries for public ++// key validity. The cache only applies to a single ServerConn. ++type pubKeyCache struct { ++ keys []cachedPubKey ++} ++ ++// get returns the result for a given user/algo/key tuple. ++func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { ++ for _, k := range c.keys { ++ if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) { ++ return k, true ++ } ++ } ++ return cachedPubKey{}, false ++} ++ ++// add adds the given tuple to the cache. ++func (c *pubKeyCache) add(candidate cachedPubKey) { ++ if len(c.keys) < maxCachedPubKeys { ++ c.keys = append(c.keys, candidate) ++ } ++} ++ ++// ServerConn is an authenticated SSH connection, as seen from the ++// server ++type ServerConn struct { ++ Conn ++ ++ // If the succeeding authentication callback returned a ++ // non-nil Permissions pointer, it is stored here. ++ Permissions *Permissions ++} ++ ++// NewServerConn starts a new SSH server with c as the underlying ++// transport. It starts with a handshake and, if the handshake is ++// unsuccessful, it closes the connection and returns an error. The ++// Request and NewChannel channels must be serviced, or the connection ++// will hang. ++// ++// The returned error may be of type *ServerAuthError for ++// authentication errors. ++func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { ++ fullConf := *config ++ fullConf.SetDefaults() ++ if fullConf.MaxAuthTries == 0 { ++ fullConf.MaxAuthTries = 6 ++ } ++ // Check if the config contains any unsupported key exchanges ++ for _, kex := range fullConf.KeyExchanges { ++ if _, ok := serverForbiddenKexAlgos[kex]; ok { ++ return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex) ++ } ++ } ++ ++ s := &connection{ ++ sshConn: sshConn{conn: c}, ++ } ++ perms, err := s.serverHandshake(&fullConf) ++ if err != nil { ++ c.Close() ++ return nil, nil, nil, err ++ } ++ return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil ++} ++ ++// signAndMarshal signs the data with the appropriate algorithm, ++// and serializes the result in SSH wire format. algo is the negotiate ++// algorithm and may be a certificate type. ++func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) { ++ sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) ++ if err != nil { ++ return nil, err ++ } ++ ++ return Marshal(sig), nil ++} ++ ++// handshake performs key exchange and user authentication. ++func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) { ++ if len(config.hostKeys) == 0 { ++ return nil, errors.New("ssh: server has no host keys") ++ } ++ ++ if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && ++ config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil || ++ config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) { ++ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") ++ } ++ ++ if config.ServerVersion != "" { ++ s.serverVersion = []byte(config.ServerVersion) ++ } else { ++ s.serverVersion = []byte(packageVersion) ++ } ++ var err error ++ s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) ++ if err != nil { ++ return nil, err ++ } ++ ++ tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */) ++ s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config) ++ ++ if err := s.transport.waitSession(); err != nil { ++ return nil, err ++ } ++ ++ // We just did the key change, so the session ID is established. ++ s.sessionID = s.transport.getSessionID() ++ ++ var packet []byte ++ if packet, err = s.transport.readPacket(); err != nil { ++ return nil, err ++ } ++ ++ var serviceRequest serviceRequestMsg ++ if err = Unmarshal(packet, &serviceRequest); err != nil { ++ return nil, err ++ } ++ if serviceRequest.Service != serviceUserAuth { ++ return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating") ++ } ++ serviceAccept := serviceAcceptMsg{ ++ Service: serviceUserAuth, ++ } ++ if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil { ++ return nil, err ++ } ++ ++ perms, err := s.serverAuthenticate(config) ++ if err != nil { ++ return nil, err ++ } ++ s.mux = newMux(s.transport) ++ return perms, err ++} ++ ++func checkSourceAddress(addr net.Addr, sourceAddrs string) error { ++ if addr == nil { ++ return errors.New("ssh: no address known for client, but source-address match required") ++ } ++ ++ tcpAddr, ok := addr.(*net.TCPAddr) ++ if !ok { ++ return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) ++ } ++ ++ for _, sourceAddr := range strings.Split(sourceAddrs, ",") { ++ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { ++ if allowedIP.Equal(tcpAddr.IP) { ++ return nil ++ } ++ } else { ++ _, ipNet, err := net.ParseCIDR(sourceAddr) ++ if err != nil { ++ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) ++ } ++ ++ if ipNet.Contains(tcpAddr.IP) { ++ return nil ++ } ++ } ++ } ++ ++ return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) ++} ++ ++func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection, ++ sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) { ++ gssAPIServer := gssapiConfig.Server ++ defer gssAPIServer.DeleteSecContext() ++ var srcName string ++ for { ++ var ( ++ outToken []byte ++ needContinue bool ++ ) ++ outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken) ++ if err != nil { ++ return err, nil, nil ++ } ++ if len(outToken) != 0 { ++ if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{ ++ Token: outToken, ++ })); err != nil { ++ return nil, nil, err ++ } ++ } ++ if !needContinue { ++ break ++ } ++ packet, err := s.transport.readPacket() ++ if err != nil { ++ return nil, nil, err ++ } ++ userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} ++ if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { ++ return nil, nil, err ++ } ++ } ++ packet, err := s.transport.readPacket() ++ if err != nil { ++ return nil, nil, err ++ } ++ userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{} ++ if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil { ++ return nil, nil, err ++ } ++ mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method) ++ if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil { ++ return err, nil, nil ++ } ++ perms, authErr = gssapiConfig.AllowLogin(s, srcName) ++ return authErr, perms, nil ++} ++ ++// isAlgoCompatible checks if the signature format is compatible with the ++// selected algorithm taking into account edge cases that occur with old ++// clients. ++func isAlgoCompatible(algo, sigFormat string) bool { ++ // Compatibility for old clients. ++ // ++ // For certificate authentication with OpenSSH 7.2-7.7 signature format can ++ // be rsa-sha2-256 or rsa-sha2-512 for the algorithm ++ // ssh-rsa-cert-v01@openssh.com. ++ // ++ // With gpg-agent < 2.2.6 the algorithm can be rsa-sha2-256 or rsa-sha2-512 ++ // for signature format ssh-rsa. ++ if isRSA(algo) && isRSA(sigFormat) { ++ return true ++ } ++ // Standard case: the underlying algorithm must match the signature format. ++ return underlyingAlgo(algo) == sigFormat ++} ++ ++// ServerAuthError represents server authentication errors and is ++// sometimes returned by NewServerConn. It appends any authentication ++// errors that may occur, and is returned if all of the authentication ++// methods provided by the user failed to authenticate. ++type ServerAuthError struct { ++ // Errors contains authentication errors returned by the authentication ++ // callback methods. The first entry is typically ErrNoAuth. ++ Errors []error ++} ++ ++func (l ServerAuthError) Error() string { ++ var errs []string ++ for _, err := range l.Errors { ++ errs = append(errs, err.Error()) ++ } ++ return "[" + strings.Join(errs, ", ") + "]" ++} ++ ++// ErrNoAuth is the error value returned if no ++// authentication method has been passed yet. This happens as a normal ++// part of the authentication loop, since the client first tries ++// 'none' authentication to discover available methods. ++// It is returned in ServerAuthError.Errors from NewServerConn. ++var ErrNoAuth = errors.New("ssh: no auth passed yet") ++ ++func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { ++ sessionID := s.transport.getSessionID() ++ var cache pubKeyCache ++ var perms *Permissions ++ ++ authFailures := 0 ++ var authErrs []error ++ var displayedBanner bool ++ ++userAuthLoop: ++ for { ++ if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 { ++ discMsg := &disconnectMsg{ ++ Reason: 2, ++ Message: "too many authentication failures", ++ } ++ ++ if err := s.transport.writePacket(Marshal(discMsg)); err != nil { ++ return nil, err ++ } ++ ++ return nil, discMsg ++ } ++ ++ var userAuthReq userAuthRequestMsg ++ if packet, err := s.transport.readPacket(); err != nil { ++ if err == io.EOF { ++ return nil, &ServerAuthError{Errors: authErrs} ++ } ++ return nil, err ++ } else if err = Unmarshal(packet, &userAuthReq); err != nil { ++ return nil, err ++ } ++ ++ if userAuthReq.Service != serviceSSH { ++ return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) ++ } ++ ++ s.user = userAuthReq.User ++ ++ if !displayedBanner && config.BannerCallback != nil { ++ displayedBanner = true ++ msg := config.BannerCallback(s) ++ if msg != "" { ++ bannerMsg := &userAuthBannerMsg{ ++ Message: msg, ++ } ++ if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { ++ return nil, err ++ } ++ } ++ } ++ ++ perms = nil ++ authErr := ErrNoAuth ++ ++ switch userAuthReq.Method { ++ case "none": ++ if config.NoClientAuth { ++ if config.NoClientAuthCallback != nil { ++ perms, authErr = config.NoClientAuthCallback(s) ++ } else { ++ authErr = nil ++ } ++ } ++ ++ // allow initial attempt of 'none' without penalty ++ if authFailures == 0 { ++ authFailures-- ++ } ++ case "password": ++ if config.PasswordCallback == nil { ++ authErr = errors.New("ssh: password auth not configured") ++ break ++ } ++ payload := userAuthReq.Payload ++ if len(payload) < 1 || payload[0] != 0 { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ payload = payload[1:] ++ password, payload, ok := parseString(payload) ++ if !ok || len(payload) > 0 { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ ++ perms, authErr = config.PasswordCallback(s, password) ++ case "keyboard-interactive": ++ if config.KeyboardInteractiveCallback == nil { ++ authErr = errors.New("ssh: keyboard-interactive auth not configured") ++ break ++ } ++ ++ prompter := &sshClientKeyboardInteractive{s} ++ perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) ++ case "publickey": ++ if config.PublicKeyCallback == nil { ++ authErr = errors.New("ssh: publickey auth not configured") ++ break ++ } ++ payload := userAuthReq.Payload ++ if len(payload) < 1 { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ isQuery := payload[0] == 0 ++ payload = payload[1:] ++ algoBytes, payload, ok := parseString(payload) ++ if !ok { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ algo := string(algoBytes) ++ if !contains(supportedPubKeyAuthAlgos, underlyingAlgo(algo)) { ++ authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) ++ break ++ } ++ ++ pubKeyData, payload, ok := parseString(payload) ++ if !ok { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ ++ pubKey, err := ParsePublicKey(pubKeyData) ++ if err != nil { ++ return nil, err ++ } ++ ++ candidate, ok := cache.get(s.user, pubKeyData) ++ if !ok { ++ candidate.user = s.user ++ candidate.pubKeyData = pubKeyData ++ candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) ++ if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { ++ candidate.result = checkSourceAddress( ++ s.RemoteAddr(), ++ candidate.perms.CriticalOptions[sourceAddressCriticalOption]) ++ } ++ cache.add(candidate) ++ } ++ ++ if isQuery { ++ // The client can query if the given public key ++ // would be okay. ++ ++ if len(payload) > 0 { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ ++ if candidate.result == nil { ++ okMsg := userAuthPubKeyOkMsg{ ++ Algo: algo, ++ PubKey: pubKeyData, ++ } ++ if err = s.transport.writePacket(Marshal(&okMsg)); err != nil { ++ return nil, err ++ } ++ continue userAuthLoop ++ } ++ authErr = candidate.result ++ } else { ++ sig, payload, ok := parseSignature(payload) ++ if !ok || len(payload) > 0 { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ ++ // Ensure the public key algo and signature algo ++ // are supported. Compare the private key ++ // algorithm name that corresponds to algo with ++ // sig.Format. This is usually the same, but ++ // for certs, the names differ. ++ if !contains(supportedPubKeyAuthAlgos, sig.Format) { ++ authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format) ++ break ++ } ++ if !isAlgoCompatible(algo, sig.Format) { ++ authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo) ++ break ++ } ++ ++ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData) ++ ++ if err := pubKey.Verify(signedData, sig); err != nil { ++ return nil, err ++ } ++ ++ authErr = candidate.result ++ perms = candidate.perms ++ } ++ case "gssapi-with-mic": ++ if config.GSSAPIWithMICConfig == nil { ++ authErr = errors.New("ssh: gssapi-with-mic auth not configured") ++ break ++ } ++ gssapiConfig := config.GSSAPIWithMICConfig ++ userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload) ++ if err != nil { ++ return nil, parseError(msgUserAuthRequest) ++ } ++ // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication. ++ if userAuthRequestGSSAPI.N == 0 { ++ authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported") ++ break ++ } ++ var i uint32 ++ present := false ++ for i = 0; i < userAuthRequestGSSAPI.N; i++ { ++ if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) { ++ present = true ++ break ++ } ++ } ++ if !present { ++ authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism") ++ break ++ } ++ // Initial server response, see RFC 4462 section 3.3. ++ if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{ ++ SupportMech: krb5OID, ++ })); err != nil { ++ return nil, err ++ } ++ // Exchange token, see RFC 4462 section 3.4. ++ packet, err := s.transport.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} ++ if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { ++ return nil, err ++ } ++ authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID, ++ userAuthReq) ++ if err != nil { ++ return nil, err ++ } ++ default: ++ authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) ++ } ++ ++ authErrs = append(authErrs, authErr) ++ ++ if config.AuthLogCallback != nil { ++ config.AuthLogCallback(s, userAuthReq.Method, authErr) ++ } ++ ++ if authErr == nil { ++ break userAuthLoop ++ } ++ ++ authFailures++ ++ if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries { ++ // If we have hit the max attempts, don't bother sending the ++ // final SSH_MSG_USERAUTH_FAILURE message, since there are ++ // no more authentication methods which can be attempted, ++ // and this message may cause the client to re-attempt ++ // authentication while we send the disconnect message. ++ // Continue, and trigger the disconnect at the start of ++ // the loop. ++ // ++ // The SSH specification is somewhat confusing about this, ++ // RFC 4252 Section 5.1 requires each authentication failure ++ // be responded to with a respective SSH_MSG_USERAUTH_FAILURE ++ // message, but Section 4 says the server should disconnect ++ // after some number of attempts, but it isn't explicit which ++ // message should take precedence (i.e. should there be a failure ++ // message than a disconnect message, or if we are going to ++ // disconnect, should we only send that message.) ++ // ++ // Either way, OpenSSH disconnects immediately after the last ++ // failed authnetication attempt, and given they are typically ++ // considered the golden implementation it seems reasonable ++ // to match that behavior. ++ continue ++ } ++ ++ var failureMsg userAuthFailureMsg ++ if config.PasswordCallback != nil { ++ failureMsg.Methods = append(failureMsg.Methods, "password") ++ } ++ if config.PublicKeyCallback != nil { ++ failureMsg.Methods = append(failureMsg.Methods, "publickey") ++ } ++ if config.KeyboardInteractiveCallback != nil { ++ failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") ++ } ++ if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil && ++ config.GSSAPIWithMICConfig.AllowLogin != nil { ++ failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic") ++ } ++ ++ if len(failureMsg.Methods) == 0 { ++ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") ++ } ++ ++ if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil { ++ return nil, err ++ } ++ } ++ ++ if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil { ++ return nil, err ++ } ++ return perms, nil ++} ++ ++// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by ++// asking the client on the other side of a ServerConn. ++type sshClientKeyboardInteractive struct { ++ *connection ++} ++ ++func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) { ++ if len(questions) != len(echos) { ++ return nil, errors.New("ssh: echos and questions must have equal length") ++ } ++ ++ var prompts []byte ++ for i := range questions { ++ prompts = appendString(prompts, questions[i]) ++ prompts = appendBool(prompts, echos[i]) ++ } ++ ++ if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ ++ Name: name, ++ Instruction: instruction, ++ NumPrompts: uint32(len(questions)), ++ Prompts: prompts, ++ })); err != nil { ++ return nil, err ++ } ++ ++ packet, err := c.transport.readPacket() ++ if err != nil { ++ return nil, err ++ } ++ if packet[0] != msgUserAuthInfoResponse { ++ return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0]) ++ } ++ packet = packet[1:] ++ ++ n, packet, ok := parseUint32(packet) ++ if !ok || int(n) != len(questions) { ++ return nil, parseError(msgUserAuthInfoResponse) ++ } ++ ++ for i := uint32(0); i < n; i++ { ++ ans, rest, ok := parseString(packet) ++ if !ok { ++ return nil, parseError(msgUserAuthInfoResponse) ++ } ++ ++ answers = append(answers, string(ans)) ++ packet = rest ++ } ++ if len(packet) != 0 { ++ return nil, errors.New("ssh: junk at end of message") ++ } ++ ++ return answers, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/session.go b/ms_mod/golang.org/x/crypto/ssh/session.go +new file mode 100644 +index 00000000000000..acef62259fdee5 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/session.go +@@ -0,0 +1,647 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++// Session implements an interactive session described in ++// "RFC 4254, section 6". ++ ++import ( ++ "bytes" ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "io" ++ "sync" ++) ++ ++type Signal string ++ ++// POSIX signals as listed in RFC 4254 Section 6.10. ++const ( ++ SIGABRT Signal = "ABRT" ++ SIGALRM Signal = "ALRM" ++ SIGFPE Signal = "FPE" ++ SIGHUP Signal = "HUP" ++ SIGILL Signal = "ILL" ++ SIGINT Signal = "INT" ++ SIGKILL Signal = "KILL" ++ SIGPIPE Signal = "PIPE" ++ SIGQUIT Signal = "QUIT" ++ SIGSEGV Signal = "SEGV" ++ SIGTERM Signal = "TERM" ++ SIGUSR1 Signal = "USR1" ++ SIGUSR2 Signal = "USR2" ++) ++ ++var signals = map[Signal]int{ ++ SIGABRT: 6, ++ SIGALRM: 14, ++ SIGFPE: 8, ++ SIGHUP: 1, ++ SIGILL: 4, ++ SIGINT: 2, ++ SIGKILL: 9, ++ SIGPIPE: 13, ++ SIGQUIT: 3, ++ SIGSEGV: 11, ++ SIGTERM: 15, ++} ++ ++type TerminalModes map[uint8]uint32 ++ ++// POSIX terminal mode flags as listed in RFC 4254 Section 8. ++const ( ++ tty_OP_END = 0 ++ VINTR = 1 ++ VQUIT = 2 ++ VERASE = 3 ++ VKILL = 4 ++ VEOF = 5 ++ VEOL = 6 ++ VEOL2 = 7 ++ VSTART = 8 ++ VSTOP = 9 ++ VSUSP = 10 ++ VDSUSP = 11 ++ VREPRINT = 12 ++ VWERASE = 13 ++ VLNEXT = 14 ++ VFLUSH = 15 ++ VSWTCH = 16 ++ VSTATUS = 17 ++ VDISCARD = 18 ++ IGNPAR = 30 ++ PARMRK = 31 ++ INPCK = 32 ++ ISTRIP = 33 ++ INLCR = 34 ++ IGNCR = 35 ++ ICRNL = 36 ++ IUCLC = 37 ++ IXON = 38 ++ IXANY = 39 ++ IXOFF = 40 ++ IMAXBEL = 41 ++ IUTF8 = 42 // RFC 8160 ++ ISIG = 50 ++ ICANON = 51 ++ XCASE = 52 ++ ECHO = 53 ++ ECHOE = 54 ++ ECHOK = 55 ++ ECHONL = 56 ++ NOFLSH = 57 ++ TOSTOP = 58 ++ IEXTEN = 59 ++ ECHOCTL = 60 ++ ECHOKE = 61 ++ PENDIN = 62 ++ OPOST = 70 ++ OLCUC = 71 ++ ONLCR = 72 ++ OCRNL = 73 ++ ONOCR = 74 ++ ONLRET = 75 ++ CS7 = 90 ++ CS8 = 91 ++ PARENB = 92 ++ PARODD = 93 ++ TTY_OP_ISPEED = 128 ++ TTY_OP_OSPEED = 129 ++) ++ ++// A Session represents a connection to a remote command or shell. ++type Session struct { ++ // Stdin specifies the remote process's standard input. ++ // If Stdin is nil, the remote process reads from an empty ++ // bytes.Buffer. ++ Stdin io.Reader ++ ++ // Stdout and Stderr specify the remote process's standard ++ // output and error. ++ // ++ // If either is nil, Run connects the corresponding file ++ // descriptor to an instance of io.Discard. There is a ++ // fixed amount of buffering that is shared for the two streams. ++ // If either blocks it may eventually cause the remote ++ // command to block. ++ Stdout io.Writer ++ Stderr io.Writer ++ ++ ch Channel // the channel backing this session ++ started bool // true once Start, Run or Shell is invoked. ++ copyFuncs []func() error ++ errors chan error // one send per copyFunc ++ ++ // true if pipe method is active ++ stdinpipe, stdoutpipe, stderrpipe bool ++ ++ // stdinPipeWriter is non-nil if StdinPipe has not been called ++ // and Stdin was specified by the user; it is the write end of ++ // a pipe connecting Session.Stdin to the stdin channel. ++ stdinPipeWriter io.WriteCloser ++ ++ exitStatus chan error ++} ++ ++// SendRequest sends an out-of-band channel request on the SSH channel ++// underlying the session. ++func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { ++ return s.ch.SendRequest(name, wantReply, payload) ++} ++ ++func (s *Session) Close() error { ++ return s.ch.Close() ++} ++ ++// RFC 4254 Section 6.4. ++type setenvRequest struct { ++ Name string ++ Value string ++} ++ ++// Setenv sets an environment variable that will be applied to any ++// command executed by Shell or Run. ++func (s *Session) Setenv(name, value string) error { ++ msg := setenvRequest{ ++ Name: name, ++ Value: value, ++ } ++ ok, err := s.ch.SendRequest("env", true, Marshal(&msg)) ++ if err == nil && !ok { ++ err = errors.New("ssh: setenv failed") ++ } ++ return err ++} ++ ++// RFC 4254 Section 6.2. ++type ptyRequestMsg struct { ++ Term string ++ Columns uint32 ++ Rows uint32 ++ Width uint32 ++ Height uint32 ++ Modelist string ++} ++ ++// RequestPty requests the association of a pty with the session on the remote host. ++func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error { ++ var tm []byte ++ for k, v := range termmodes { ++ kv := struct { ++ Key byte ++ Val uint32 ++ }{k, v} ++ ++ tm = append(tm, Marshal(&kv)...) ++ } ++ tm = append(tm, tty_OP_END) ++ req := ptyRequestMsg{ ++ Term: term, ++ Columns: uint32(w), ++ Rows: uint32(h), ++ Width: uint32(w * 8), ++ Height: uint32(h * 8), ++ Modelist: string(tm), ++ } ++ ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req)) ++ if err == nil && !ok { ++ err = errors.New("ssh: pty-req failed") ++ } ++ return err ++} ++ ++// RFC 4254 Section 6.5. ++type subsystemRequestMsg struct { ++ Subsystem string ++} ++ ++// RequestSubsystem requests the association of a subsystem with the session on the remote host. ++// A subsystem is a predefined command that runs in the background when the ssh session is initiated ++func (s *Session) RequestSubsystem(subsystem string) error { ++ msg := subsystemRequestMsg{ ++ Subsystem: subsystem, ++ } ++ ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg)) ++ if err == nil && !ok { ++ err = errors.New("ssh: subsystem request failed") ++ } ++ return err ++} ++ ++// RFC 4254 Section 6.7. ++type ptyWindowChangeMsg struct { ++ Columns uint32 ++ Rows uint32 ++ Width uint32 ++ Height uint32 ++} ++ ++// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns. ++func (s *Session) WindowChange(h, w int) error { ++ req := ptyWindowChangeMsg{ ++ Columns: uint32(w), ++ Rows: uint32(h), ++ Width: uint32(w * 8), ++ Height: uint32(h * 8), ++ } ++ _, err := s.ch.SendRequest("window-change", false, Marshal(&req)) ++ return err ++} ++ ++// RFC 4254 Section 6.9. ++type signalMsg struct { ++ Signal string ++} ++ ++// Signal sends the given signal to the remote process. ++// sig is one of the SIG* constants. ++func (s *Session) Signal(sig Signal) error { ++ msg := signalMsg{ ++ Signal: string(sig), ++ } ++ ++ _, err := s.ch.SendRequest("signal", false, Marshal(&msg)) ++ return err ++} ++ ++// RFC 4254 Section 6.5. ++type execMsg struct { ++ Command string ++} ++ ++// Start runs cmd on the remote host. Typically, the remote ++// server passes cmd to the shell for interpretation. ++// A Session only accepts one call to Run, Start or Shell. ++func (s *Session) Start(cmd string) error { ++ if s.started { ++ return errors.New("ssh: session already started") ++ } ++ req := execMsg{ ++ Command: cmd, ++ } ++ ++ ok, err := s.ch.SendRequest("exec", true, Marshal(&req)) ++ if err == nil && !ok { ++ err = fmt.Errorf("ssh: command %v failed", cmd) ++ } ++ if err != nil { ++ return err ++ } ++ return s.start() ++} ++ ++// Run runs cmd on the remote host. Typically, the remote ++// server passes cmd to the shell for interpretation. ++// A Session only accepts one call to Run, Start, Shell, Output, ++// or CombinedOutput. ++// ++// The returned error is nil if the command runs, has no problems ++// copying stdin, stdout, and stderr, and exits with a zero exit ++// status. ++// ++// If the remote server does not send an exit status, an error of type ++// *ExitMissingError is returned. If the command completes ++// unsuccessfully or is interrupted by a signal, the error is of type ++// *ExitError. Other error types may be returned for I/O problems. ++func (s *Session) Run(cmd string) error { ++ err := s.Start(cmd) ++ if err != nil { ++ return err ++ } ++ return s.Wait() ++} ++ ++// Output runs cmd on the remote host and returns its standard output. ++func (s *Session) Output(cmd string) ([]byte, error) { ++ if s.Stdout != nil { ++ return nil, errors.New("ssh: Stdout already set") ++ } ++ var b bytes.Buffer ++ s.Stdout = &b ++ err := s.Run(cmd) ++ return b.Bytes(), err ++} ++ ++type singleWriter struct { ++ b bytes.Buffer ++ mu sync.Mutex ++} ++ ++func (w *singleWriter) Write(p []byte) (int, error) { ++ w.mu.Lock() ++ defer w.mu.Unlock() ++ return w.b.Write(p) ++} ++ ++// CombinedOutput runs cmd on the remote host and returns its combined ++// standard output and standard error. ++func (s *Session) CombinedOutput(cmd string) ([]byte, error) { ++ if s.Stdout != nil { ++ return nil, errors.New("ssh: Stdout already set") ++ } ++ if s.Stderr != nil { ++ return nil, errors.New("ssh: Stderr already set") ++ } ++ var b singleWriter ++ s.Stdout = &b ++ s.Stderr = &b ++ err := s.Run(cmd) ++ return b.b.Bytes(), err ++} ++ ++// Shell starts a login shell on the remote host. A Session only ++// accepts one call to Run, Start, Shell, Output, or CombinedOutput. ++func (s *Session) Shell() error { ++ if s.started { ++ return errors.New("ssh: session already started") ++ } ++ ++ ok, err := s.ch.SendRequest("shell", true, nil) ++ if err == nil && !ok { ++ return errors.New("ssh: could not start shell") ++ } ++ if err != nil { ++ return err ++ } ++ return s.start() ++} ++ ++func (s *Session) start() error { ++ s.started = true ++ ++ type F func(*Session) ++ for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} { ++ setupFd(s) ++ } ++ ++ s.errors = make(chan error, len(s.copyFuncs)) ++ for _, fn := range s.copyFuncs { ++ go func(fn func() error) { ++ s.errors <- fn() ++ }(fn) ++ } ++ return nil ++} ++ ++// Wait waits for the remote command to exit. ++// ++// The returned error is nil if the command runs, has no problems ++// copying stdin, stdout, and stderr, and exits with a zero exit ++// status. ++// ++// If the remote server does not send an exit status, an error of type ++// *ExitMissingError is returned. If the command completes ++// unsuccessfully or is interrupted by a signal, the error is of type ++// *ExitError. Other error types may be returned for I/O problems. ++func (s *Session) Wait() error { ++ if !s.started { ++ return errors.New("ssh: session not started") ++ } ++ waitErr := <-s.exitStatus ++ ++ if s.stdinPipeWriter != nil { ++ s.stdinPipeWriter.Close() ++ } ++ var copyError error ++ for range s.copyFuncs { ++ if err := <-s.errors; err != nil && copyError == nil { ++ copyError = err ++ } ++ } ++ if waitErr != nil { ++ return waitErr ++ } ++ return copyError ++} ++ ++func (s *Session) wait(reqs <-chan *Request) error { ++ wm := Waitmsg{status: -1} ++ // Wait for msg channel to be closed before returning. ++ for msg := range reqs { ++ switch msg.Type { ++ case "exit-status": ++ wm.status = int(binary.BigEndian.Uint32(msg.Payload)) ++ case "exit-signal": ++ var sigval struct { ++ Signal string ++ CoreDumped bool ++ Error string ++ Lang string ++ } ++ if err := Unmarshal(msg.Payload, &sigval); err != nil { ++ return err ++ } ++ ++ // Must sanitize strings? ++ wm.signal = sigval.Signal ++ wm.msg = sigval.Error ++ wm.lang = sigval.Lang ++ default: ++ // This handles keepalives and matches ++ // OpenSSH's behaviour. ++ if msg.WantReply { ++ msg.Reply(false, nil) ++ } ++ } ++ } ++ if wm.status == 0 { ++ return nil ++ } ++ if wm.status == -1 { ++ // exit-status was never sent from server ++ if wm.signal == "" { ++ // signal was not sent either. RFC 4254 ++ // section 6.10 recommends against this ++ // behavior, but it is allowed, so we let ++ // clients handle it. ++ return &ExitMissingError{} ++ } ++ wm.status = 128 ++ if _, ok := signals[Signal(wm.signal)]; ok { ++ wm.status += signals[Signal(wm.signal)] ++ } ++ } ++ ++ return &ExitError{wm} ++} ++ ++// ExitMissingError is returned if a session is torn down cleanly, but ++// the server sends no confirmation of the exit status. ++type ExitMissingError struct{} ++ ++func (e *ExitMissingError) Error() string { ++ return "wait: remote command exited without exit status or exit signal" ++} ++ ++func (s *Session) stdin() { ++ if s.stdinpipe { ++ return ++ } ++ var stdin io.Reader ++ if s.Stdin == nil { ++ stdin = new(bytes.Buffer) ++ } else { ++ r, w := io.Pipe() ++ go func() { ++ _, err := io.Copy(w, s.Stdin) ++ w.CloseWithError(err) ++ }() ++ stdin, s.stdinPipeWriter = r, w ++ } ++ s.copyFuncs = append(s.copyFuncs, func() error { ++ _, err := io.Copy(s.ch, stdin) ++ if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF { ++ err = err1 ++ } ++ return err ++ }) ++} ++ ++func (s *Session) stdout() { ++ if s.stdoutpipe { ++ return ++ } ++ if s.Stdout == nil { ++ s.Stdout = io.Discard ++ } ++ s.copyFuncs = append(s.copyFuncs, func() error { ++ _, err := io.Copy(s.Stdout, s.ch) ++ return err ++ }) ++} ++ ++func (s *Session) stderr() { ++ if s.stderrpipe { ++ return ++ } ++ if s.Stderr == nil { ++ s.Stderr = io.Discard ++ } ++ s.copyFuncs = append(s.copyFuncs, func() error { ++ _, err := io.Copy(s.Stderr, s.ch.Stderr()) ++ return err ++ }) ++} ++ ++// sessionStdin reroutes Close to CloseWrite. ++type sessionStdin struct { ++ io.Writer ++ ch Channel ++} ++ ++func (s *sessionStdin) Close() error { ++ return s.ch.CloseWrite() ++} ++ ++// StdinPipe returns a pipe that will be connected to the ++// remote command's standard input when the command starts. ++func (s *Session) StdinPipe() (io.WriteCloser, error) { ++ if s.Stdin != nil { ++ return nil, errors.New("ssh: Stdin already set") ++ } ++ if s.started { ++ return nil, errors.New("ssh: StdinPipe after process started") ++ } ++ s.stdinpipe = true ++ return &sessionStdin{s.ch, s.ch}, nil ++} ++ ++// StdoutPipe returns a pipe that will be connected to the ++// remote command's standard output when the command starts. ++// There is a fixed amount of buffering that is shared between ++// stdout and stderr streams. If the StdoutPipe reader is ++// not serviced fast enough it may eventually cause the ++// remote command to block. ++func (s *Session) StdoutPipe() (io.Reader, error) { ++ if s.Stdout != nil { ++ return nil, errors.New("ssh: Stdout already set") ++ } ++ if s.started { ++ return nil, errors.New("ssh: StdoutPipe after process started") ++ } ++ s.stdoutpipe = true ++ return s.ch, nil ++} ++ ++// StderrPipe returns a pipe that will be connected to the ++// remote command's standard error when the command starts. ++// There is a fixed amount of buffering that is shared between ++// stdout and stderr streams. If the StderrPipe reader is ++// not serviced fast enough it may eventually cause the ++// remote command to block. ++func (s *Session) StderrPipe() (io.Reader, error) { ++ if s.Stderr != nil { ++ return nil, errors.New("ssh: Stderr already set") ++ } ++ if s.started { ++ return nil, errors.New("ssh: StderrPipe after process started") ++ } ++ s.stderrpipe = true ++ return s.ch.Stderr(), nil ++} ++ ++// newSession returns a new interactive session on the remote host. ++func newSession(ch Channel, reqs <-chan *Request) (*Session, error) { ++ s := &Session{ ++ ch: ch, ++ } ++ s.exitStatus = make(chan error, 1) ++ go func() { ++ s.exitStatus <- s.wait(reqs) ++ }() ++ ++ return s, nil ++} ++ ++// An ExitError reports unsuccessful completion of a remote command. ++type ExitError struct { ++ Waitmsg ++} ++ ++func (e *ExitError) Error() string { ++ return e.Waitmsg.String() ++} ++ ++// Waitmsg stores the information about an exited remote command ++// as reported by Wait. ++type Waitmsg struct { ++ status int ++ signal string ++ msg string ++ lang string ++} ++ ++// ExitStatus returns the exit status of the remote command. ++func (w Waitmsg) ExitStatus() int { ++ return w.status ++} ++ ++// Signal returns the exit signal of the remote command if ++// it was terminated violently. ++func (w Waitmsg) Signal() string { ++ return w.signal ++} ++ ++// Msg returns the exit message given by the remote command ++func (w Waitmsg) Msg() string { ++ return w.msg ++} ++ ++// Lang returns the language tag. See RFC 3066 ++func (w Waitmsg) Lang() string { ++ return w.lang ++} ++ ++func (w Waitmsg) String() string { ++ str := fmt.Sprintf("Process exited with status %v", w.status) ++ if w.signal != "" { ++ str += fmt.Sprintf(" from signal %v", w.signal) ++ } ++ if w.msg != "" { ++ str += fmt.Sprintf(". Reason was: %v", w.msg) ++ } ++ return str ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/session_test.go b/ms_mod/golang.org/x/crypto/ssh/session_test.go +new file mode 100644 +index 00000000000000..521677f9b106bc +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/session_test.go +@@ -0,0 +1,845 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++// Session tests. ++ ++import ( ++ "bytes" ++ crypto_rand "crypto/rand" ++ "errors" ++ "io" ++ "math/rand" ++ "net" ++ "testing" ++ ++ "golang.org/x/crypto/ssh/terminal" ++) ++ ++type serverType func(Channel, <-chan *Request, *testing.T) ++ ++// dial constructs a new test server and returns a *ClientConn. ++func dial(handler serverType, t *testing.T) *Client { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ ++ go func() { ++ defer c1.Close() ++ conf := ServerConfig{ ++ NoClientAuth: true, ++ } ++ conf.AddHostKey(testSigners["rsa"]) ++ ++ conn, chans, reqs, err := NewServerConn(c1, &conf) ++ if err != nil { ++ t.Errorf("Unable to handshake: %v", err) ++ return ++ } ++ go DiscardRequests(reqs) ++ ++ for newCh := range chans { ++ if newCh.ChannelType() != "session" { ++ newCh.Reject(UnknownChannelType, "unknown channel type") ++ continue ++ } ++ ++ ch, inReqs, err := newCh.Accept() ++ if err != nil { ++ t.Errorf("Accept: %v", err) ++ continue ++ } ++ go func() { ++ handler(ch, inReqs, t) ++ }() ++ } ++ if err := conn.Wait(); err != io.EOF { ++ t.Logf("server exit reason: %v", err) ++ } ++ }() ++ ++ config := &ClientConfig{ ++ User: "testuser", ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ ++ conn, chans, reqs, err := NewClientConn(c2, "", config) ++ if err != nil { ++ t.Fatalf("unable to dial remote side: %v", err) ++ } ++ ++ return NewClient(conn, chans, reqs) ++} ++ ++// Test a simple string is returned to session.Stdout. ++func TestSessionShell(t *testing.T) { ++ conn := dial(shellHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ stdout := new(bytes.Buffer) ++ session.Stdout = stdout ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %s", err) ++ } ++ if err := session.Wait(); err != nil { ++ t.Fatalf("Remote command did not exit cleanly: %v", err) ++ } ++ actual := stdout.String() ++ if actual != "golang" { ++ t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) ++ } ++} ++ ++// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it. ++ ++// Test a simple string is returned via StdoutPipe. ++func TestSessionStdoutPipe(t *testing.T) { ++ conn := dial(shellHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ stdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Fatalf("Unable to request StdoutPipe(): %v", err) ++ } ++ var buf bytes.Buffer ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ done := make(chan bool, 1) ++ go func() { ++ if _, err := io.Copy(&buf, stdout); err != nil { ++ t.Errorf("Copy of stdout failed: %v", err) ++ } ++ done <- true ++ }() ++ if err := session.Wait(); err != nil { ++ t.Fatalf("Remote command did not exit cleanly: %v", err) ++ } ++ <-done ++ actual := buf.String() ++ if actual != "golang" { ++ t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) ++ } ++} ++ ++// Test that a simple string is returned via the Output helper, ++// and that stderr is discarded. ++func TestSessionOutput(t *testing.T) { ++ conn := dial(fixedOutputHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ ++ buf, err := session.Output("") // cmd is ignored by fixedOutputHandler ++ if err != nil { ++ t.Error("Remote command did not exit cleanly:", err) ++ } ++ w := "this-is-stdout." ++ g := string(buf) ++ if g != w { ++ t.Error("Remote command did not return expected string:") ++ t.Logf("want %q", w) ++ t.Logf("got %q", g) ++ } ++} ++ ++// Test that both stdout and stderr are returned ++// via the CombinedOutput helper. ++func TestSessionCombinedOutput(t *testing.T) { ++ conn := dial(fixedOutputHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ ++ buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler ++ if err != nil { ++ t.Error("Remote command did not exit cleanly:", err) ++ } ++ const stdout = "this-is-stdout." ++ const stderr = "this-is-stderr." ++ g := string(buf) ++ if g != stdout+stderr && g != stderr+stdout { ++ t.Error("Remote command did not return expected string:") ++ t.Logf("want %q, or %q", stdout+stderr, stderr+stdout) ++ t.Logf("got %q", g) ++ } ++} ++ ++// Test non-0 exit status is returned correctly. ++func TestExitStatusNonZero(t *testing.T) { ++ conn := dial(exitStatusNonZeroHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err == nil { ++ t.Fatalf("expected command to fail but it didn't") ++ } ++ e, ok := err.(*ExitError) ++ if !ok { ++ t.Fatalf("expected *ExitError but got %T", err) ++ } ++ if e.ExitStatus() != 15 { ++ t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus()) ++ } ++} ++ ++// Test 0 exit status is returned correctly. ++func TestExitStatusZero(t *testing.T) { ++ conn := dial(exitStatusZeroHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err != nil { ++ t.Fatalf("expected nil but got %v", err) ++ } ++} ++ ++// Test exit signal and status are both returned correctly. ++func TestExitSignalAndStatus(t *testing.T) { ++ conn := dial(exitSignalAndStatusHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err == nil { ++ t.Fatalf("expected command to fail but it didn't") ++ } ++ e, ok := err.(*ExitError) ++ if !ok { ++ t.Fatalf("expected *ExitError but got %T", err) ++ } ++ if e.Signal() != "TERM" || e.ExitStatus() != 15 { ++ t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus()) ++ } ++} ++ ++// Test exit signal and status are both returned correctly. ++func TestKnownExitSignalOnly(t *testing.T) { ++ conn := dial(exitSignalHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err == nil { ++ t.Fatalf("expected command to fail but it didn't") ++ } ++ e, ok := err.(*ExitError) ++ if !ok { ++ t.Fatalf("expected *ExitError but got %T", err) ++ } ++ if e.Signal() != "TERM" || e.ExitStatus() != 143 { ++ t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus()) ++ } ++} ++ ++// Test exit signal and status are both returned correctly. ++func TestUnknownExitSignal(t *testing.T) { ++ conn := dial(exitSignalUnknownHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err == nil { ++ t.Fatalf("expected command to fail but it didn't") ++ } ++ e, ok := err.(*ExitError) ++ if !ok { ++ t.Fatalf("expected *ExitError but got %T", err) ++ } ++ if e.Signal() != "SYS" || e.ExitStatus() != 128 { ++ t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus()) ++ } ++} ++ ++func TestExitWithoutStatusOrSignal(t *testing.T) { ++ conn := dial(exitWithoutSignalOrStatus, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("Unable to request new session: %v", err) ++ } ++ defer session.Close() ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err == nil { ++ t.Fatalf("expected command to fail but it didn't") ++ } ++ if _, ok := err.(*ExitMissingError); !ok { ++ t.Fatalf("got %T want *ExitMissingError", err) ++ } ++} ++ ++// windowTestBytes is the number of bytes that we'll send to the SSH server. ++const windowTestBytes = 16000 * 200 ++ ++// TestServerWindow writes random data to the server. The server is expected to echo ++// the same data back, which is compared against the original. ++func TestServerWindow(t *testing.T) { ++ origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) ++ io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes) ++ origBytes := origBuf.Bytes() ++ ++ conn := dial(echoHandler, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer session.Close() ++ result := make(chan []byte) ++ ++ go func() { ++ defer close(result) ++ echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) ++ serverStdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Errorf("StdoutPipe failed: %v", err) ++ return ++ } ++ n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes) ++ if err != nil && err != io.EOF { ++ t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err) ++ } ++ result <- echoedBuf.Bytes() ++ }() ++ ++ serverStdin, err := session.StdinPipe() ++ if err != nil { ++ t.Fatalf("StdinPipe failed: %v", err) ++ } ++ written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes) ++ if err != nil { ++ t.Errorf("failed to copy origBuf to serverStdin: %v", err) ++ } else if written != windowTestBytes { ++ t.Errorf("Wrote only %d of %d bytes to server", written, windowTestBytes) ++ } ++ ++ echoedBytes := <-result ++ ++ if !bytes.Equal(origBytes, echoedBytes) { ++ t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes)) ++ } ++} ++ ++// Verify the client can handle a keepalive packet from the server. ++func TestClientHandlesKeepalives(t *testing.T) { ++ conn := dial(channelKeepaliveSender, t) ++ defer conn.Close() ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer session.Close() ++ if err := session.Shell(); err != nil { ++ t.Fatalf("Unable to execute command: %v", err) ++ } ++ err = session.Wait() ++ if err != nil { ++ t.Fatalf("expected nil but got: %v", err) ++ } ++} ++ ++type exitStatusMsg struct { ++ Status uint32 ++} ++ ++type exitSignalMsg struct { ++ Signal string ++ CoreDumped bool ++ Errmsg string ++ Lang string ++} ++ ++func handleTerminalRequests(in <-chan *Request) { ++ for req := range in { ++ ok := false ++ switch req.Type { ++ case "shell": ++ ok = true ++ if len(req.Payload) > 0 { ++ // We don't accept any commands, only the default shell. ++ ok = false ++ } ++ case "env": ++ ok = true ++ } ++ req.Reply(ok, nil) ++ } ++} ++ ++func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal { ++ term := terminal.NewTerminal(ch, prompt) ++ go handleTerminalRequests(in) ++ return term ++} ++ ++func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ // this string is returned to stdout ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++ sendStatus(0, ch, t) ++} ++ ++func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++ sendStatus(15, ch, t) ++} ++ ++func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++ sendStatus(15, ch, t) ++ sendSignal("TERM", ch, t) ++} ++ ++func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++ sendSignal("TERM", ch, t) ++} ++ ++func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++ sendSignal("SYS", ch, t) ++} ++ ++func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++} ++ ++func shellHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ // this string is returned to stdout ++ shell := newServerShell(ch, in, "golang") ++ readLine(shell, t) ++ sendStatus(0, ch, t) ++} ++ ++// Ignores the command, writes fixed strings to stderr and stdout. ++// Strings are "this-is-stdout." and "this-is-stderr.". ++func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ _, err := ch.Read(nil) ++ ++ req, ok := <-in ++ if !ok { ++ t.Fatalf("error: expected channel request, got: %#v", err) ++ return ++ } ++ ++ // ignore request, always send some text ++ req.Reply(true, nil) ++ ++ _, err = io.WriteString(ch, "this-is-stdout.") ++ if err != nil { ++ t.Fatalf("error writing on server: %v", err) ++ } ++ _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") ++ if err != nil { ++ t.Fatalf("error writing on server: %v", err) ++ } ++ sendStatus(0, ch, t) ++} ++ ++func readLine(shell *terminal.Terminal, t *testing.T) { ++ if _, err := shell.ReadLine(); err != nil && err != io.EOF { ++ t.Errorf("unable to read line: %v", err) ++ } ++} ++ ++func sendStatus(status uint32, ch Channel, t *testing.T) { ++ msg := exitStatusMsg{ ++ Status: status, ++ } ++ if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil { ++ t.Errorf("unable to send status: %v", err) ++ } ++} ++ ++func sendSignal(signal string, ch Channel, t *testing.T) { ++ sig := exitSignalMsg{ ++ Signal: signal, ++ CoreDumped: false, ++ Errmsg: "Process terminated", ++ Lang: "en-GB-oed", ++ } ++ if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil { ++ t.Errorf("unable to send signal: %v", err) ++ } ++} ++ ++func discardHandler(ch Channel, t *testing.T) { ++ defer ch.Close() ++ io.Copy(io.Discard, ch) ++} ++ ++func echoHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil { ++ t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err) ++ } ++} ++ ++// copyNRandomly copies n bytes from src to dst. It uses a variable, and random, ++// buffer size to exercise more code paths. ++func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) { ++ var ( ++ buf = make([]byte, 32*1024) ++ written int ++ remaining = n ++ ) ++ for remaining > 0 { ++ l := rand.Intn(1 << 15) ++ if remaining < l { ++ l = remaining ++ } ++ nr, er := src.Read(buf[:l]) ++ nw, ew := dst.Write(buf[:nr]) ++ remaining -= nw ++ written += nw ++ if ew != nil { ++ return written, ew ++ } ++ if nr != nw { ++ return written, io.ErrShortWrite ++ } ++ if er != nil && er != io.EOF { ++ return written, er ++ } ++ } ++ return written, nil ++} ++ ++func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ shell := newServerShell(ch, in, "> ") ++ readLine(shell, t) ++ if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil { ++ t.Errorf("unable to send channel keepalive request: %v", err) ++ } ++ sendStatus(0, ch, t) ++} ++ ++func TestClientWriteEOF(t *testing.T) { ++ conn := dial(simpleEchoHandler, t) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatal(err) ++ } ++ defer session.Close() ++ stdin, err := session.StdinPipe() ++ if err != nil { ++ t.Fatalf("StdinPipe failed: %v", err) ++ } ++ stdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Fatalf("StdoutPipe failed: %v", err) ++ } ++ ++ data := []byte(`0000`) ++ _, err = stdin.Write(data) ++ if err != nil { ++ t.Fatalf("Write failed: %v", err) ++ } ++ stdin.Close() ++ ++ res, err := io.ReadAll(stdout) ++ if err != nil { ++ t.Fatalf("Read failed: %v", err) ++ } ++ ++ if !bytes.Equal(data, res) { ++ t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) ++ } ++} ++ ++func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) { ++ defer ch.Close() ++ data, err := io.ReadAll(ch) ++ if err != nil { ++ t.Errorf("handler read error: %v", err) ++ } ++ _, err = ch.Write(data) ++ if err != nil { ++ t.Errorf("handler write error: %v", err) ++ } ++} ++ ++func TestSessionID(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ serverID := make(chan []byte, 1) ++ clientID := make(chan []byte, 1) ++ ++ serverConf := &ServerConfig{ ++ NoClientAuth: true, ++ } ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ clientConf := &ClientConfig{ ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ User: "user", ++ } ++ ++ srvErrCh := make(chan error, 1) ++ go func() { ++ conn, chans, reqs, err := NewServerConn(c1, serverConf) ++ srvErrCh <- err ++ if err != nil { ++ return ++ } ++ serverID <- conn.SessionID() ++ go DiscardRequests(reqs) ++ for ch := range chans { ++ ch.Reject(Prohibited, "") ++ } ++ }() ++ ++ cliErrCh := make(chan error, 1) ++ go func() { ++ conn, chans, reqs, err := NewClientConn(c2, "", clientConf) ++ cliErrCh <- err ++ if err != nil { ++ return ++ } ++ clientID <- conn.SessionID() ++ go DiscardRequests(reqs) ++ for ch := range chans { ++ ch.Reject(Prohibited, "") ++ } ++ }() ++ ++ if err := <-srvErrCh; err != nil { ++ t.Fatalf("server handshake: %v", err) ++ } ++ ++ if err := <-cliErrCh; err != nil { ++ t.Fatalf("client handshake: %v", err) ++ } ++ ++ s := <-serverID ++ c := <-clientID ++ if bytes.Compare(s, c) != 0 { ++ t.Errorf("server session ID (%x) != client session ID (%x)", s, c) ++ } else if len(s) == 0 { ++ t.Errorf("client and server SessionID were empty.") ++ } ++} ++ ++type noReadConn struct { ++ readSeen bool ++ net.Conn ++} ++ ++func (c *noReadConn) Close() error { ++ return nil ++} ++ ++func (c *noReadConn) Read(b []byte) (int, error) { ++ c.readSeen = true ++ return 0, errors.New("noReadConn error") ++} ++ ++func TestInvalidServerConfiguration(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ serveConn := noReadConn{Conn: c1} ++ serverConf := &ServerConfig{} ++ ++ NewServerConn(&serveConn, serverConf) ++ if serveConn.readSeen { ++ t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key") ++ } ++ ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ ++ NewServerConn(&serveConn, serverConf) ++ if serveConn.readSeen { ++ t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method") ++ } ++} ++ ++func TestHostKeyAlgorithms(t *testing.T) { ++ serverConf := &ServerConfig{ ++ NoClientAuth: true, ++ } ++ serverConf.AddHostKey(testSigners["rsa"]) ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ ++ connect := func(clientConf *ClientConfig, want string) { ++ var alg string ++ clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error { ++ alg = key.Type() ++ return nil ++ } ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go NewServerConn(c1, serverConf) ++ _, _, _, err = NewClientConn(c2, "", clientConf) ++ if err != nil { ++ t.Fatalf("NewClientConn: %v", err) ++ } ++ if alg != want { ++ t.Errorf("selected key algorithm %s, want %s", alg, want) ++ } ++ } ++ ++ // By default, we get the preferred algorithm, which is ECDSA 256. ++ ++ clientConf := &ClientConfig{ ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ } ++ connect(clientConf, KeyAlgoECDSA256) ++ ++ // Client asks for RSA explicitly. ++ clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} ++ connect(clientConf, KeyAlgoRSA) ++ ++ // Client asks for RSA-SHA2-512 explicitly. ++ clientConf.HostKeyAlgorithms = []string{KeyAlgoRSASHA512} ++ // We get back an "ssh-rsa" key but the verification happened ++ // with an RSA-SHA2-512 signature. ++ connect(clientConf, KeyAlgoRSA) ++ ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ go NewServerConn(c1, serverConf) ++ clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"} ++ _, _, _, err = NewClientConn(c2, "", clientConf) ++ if err == nil { ++ t.Fatal("succeeded connecting with unknown hostkey algorithm") ++ } ++} ++ ++func TestServerClientAuthCallback(t *testing.T) { ++ c1, c2, err := netPipe() ++ if err != nil { ++ t.Fatalf("netPipe: %v", err) ++ } ++ defer c1.Close() ++ defer c2.Close() ++ ++ userCh := make(chan string, 1) ++ ++ serverConf := &ServerConfig{ ++ NoClientAuth: true, ++ NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) { ++ userCh <- conn.User() ++ return nil, nil ++ }, ++ } ++ const someUsername = "some-username" ++ ++ serverConf.AddHostKey(testSigners["ecdsa"]) ++ clientConf := &ClientConfig{ ++ HostKeyCallback: InsecureIgnoreHostKey(), ++ User: someUsername, ++ } ++ ++ go func() { ++ _, chans, reqs, err := NewServerConn(c1, serverConf) ++ if err != nil { ++ t.Errorf("server handshake: %v", err) ++ userCh <- "error" ++ return ++ } ++ go DiscardRequests(reqs) ++ for ch := range chans { ++ ch.Reject(Prohibited, "") ++ } ++ }() ++ ++ conn, _, _, err := NewClientConn(c2, "", clientConf) ++ if err != nil { ++ t.Fatalf("client handshake: %v", err) ++ return ++ } ++ conn.Close() ++ ++ got := <-userCh ++ if got != someUsername { ++ t.Errorf("username = %q; want %q", got, someUsername) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/ssh_gss.go b/ms_mod/golang.org/x/crypto/ssh/ssh_gss.go +new file mode 100644 +index 00000000000000..24bd7c8e830484 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/ssh_gss.go +@@ -0,0 +1,139 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "encoding/asn1" ++ "errors" ++) ++ ++var krb5OID []byte ++ ++func init() { ++ krb5OID, _ = asn1.Marshal(krb5Mesh) ++} ++ ++// GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins. ++type GSSAPIClient interface { ++ // InitSecContext initiates the establishment of a security context for GSS-API between the ++ // ssh client and ssh server. Initially the token parameter should be specified as nil. ++ // The routine may return a outputToken which should be transferred to ++ // the ssh server, where the ssh server will present it to ++ // AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting ++ // needContinue to false. To complete the context ++ // establishment, one or more reply tokens may be required from the ssh ++ // server;if so, InitSecContext will return a needContinue which is true. ++ // In this case, InitSecContext should be called again when the ++ // reply token is received from the ssh server, passing the reply ++ // token to InitSecContext via the token parameters. ++ // See RFC 2743 section 2.2.1 and RFC 4462 section 3.4. ++ InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) ++ // GetMIC generates a cryptographic MIC for the SSH2 message, and places ++ // the MIC in a token for transfer to the ssh server. ++ // The contents of the MIC field are obtained by calling GSS_GetMIC() ++ // over the following, using the GSS-API context that was just ++ // established: ++ // string session identifier ++ // byte SSH_MSG_USERAUTH_REQUEST ++ // string user name ++ // string service ++ // string "gssapi-with-mic" ++ // See RFC 2743 section 2.3.1 and RFC 4462 3.5. ++ GetMIC(micFiled []byte) ([]byte, error) ++ // Whenever possible, it should be possible for ++ // DeleteSecContext() calls to be successfully processed even ++ // if other calls cannot succeed, thereby enabling context-related ++ // resources to be released. ++ // In addition to deleting established security contexts, ++ // gss_delete_sec_context must also be able to delete "half-built" ++ // security contexts resulting from an incomplete sequence of ++ // InitSecContext()/AcceptSecContext() calls. ++ // See RFC 2743 section 2.2.3. ++ DeleteSecContext() error ++} ++ ++// GSSAPIServer provides the API to plug in GSSAPI authentication for server logins. ++type GSSAPIServer interface { ++ // AcceptSecContext allows a remotely initiated security context between the application ++ // and a remote peer to be established by the ssh client. The routine may return a ++ // outputToken which should be transferred to the ssh client, ++ // where the ssh client will present it to InitSecContext. ++ // If no token need be sent, AcceptSecContext will indicate this ++ // by setting the needContinue to false. To ++ // complete the context establishment, one or more reply tokens may be ++ // required from the ssh client. if so, AcceptSecContext ++ // will return a needContinue which is true, in which case it ++ // should be called again when the reply token is received from the ssh ++ // client, passing the token to AcceptSecContext via the ++ // token parameters. ++ // The srcName return value is the authenticated username. ++ // See RFC 2743 section 2.2.2 and RFC 4462 section 3.4. ++ AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) ++ // VerifyMIC verifies that a cryptographic MIC, contained in the token parameter, ++ // fits the supplied message is received from the ssh client. ++ // See RFC 2743 section 2.3.2. ++ VerifyMIC(micField []byte, micToken []byte) error ++ // Whenever possible, it should be possible for ++ // DeleteSecContext() calls to be successfully processed even ++ // if other calls cannot succeed, thereby enabling context-related ++ // resources to be released. ++ // In addition to deleting established security contexts, ++ // gss_delete_sec_context must also be able to delete "half-built" ++ // security contexts resulting from an incomplete sequence of ++ // InitSecContext()/AcceptSecContext() calls. ++ // See RFC 2743 section 2.2.3. ++ DeleteSecContext() error ++} ++ ++var ( ++ // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication, ++ // so we also support the krb5 mechanism only. ++ // See RFC 1964 section 1. ++ krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2} ++) ++ ++// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST ++// See RFC 4462 section 3.2. ++type userAuthRequestGSSAPI struct { ++ N uint32 ++ OIDS []asn1.ObjectIdentifier ++} ++ ++func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) { ++ n, rest, ok := parseUint32(payload) ++ if !ok { ++ return nil, errors.New("parse uint32 failed") ++ } ++ s := &userAuthRequestGSSAPI{ ++ N: n, ++ OIDS: make([]asn1.ObjectIdentifier, n), ++ } ++ for i := 0; i < int(n); i++ { ++ var ( ++ desiredMech []byte ++ err error ++ ) ++ desiredMech, rest, ok = parseString(rest) ++ if !ok { ++ return nil, errors.New("parse string failed") ++ } ++ if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil { ++ return nil, err ++ } ++ ++ } ++ return s, nil ++} ++ ++// See RFC 4462 section 3.6. ++func buildMIC(sessionID string, username string, service string, authMethod string) []byte { ++ out := make([]byte, 0, 0) ++ out = appendString(out, sessionID) ++ out = append(out, msgUserAuthRequest) ++ out = appendString(out, username) ++ out = appendString(out, service) ++ out = appendString(out, authMethod) ++ return out ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go b/ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go +new file mode 100644 +index 00000000000000..39a111288af097 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go +@@ -0,0 +1,109 @@ ++package ssh ++ ++import ( ++ "fmt" ++ "testing" ++) ++ ++func TestParseGSSAPIPayload(t *testing.T) { ++ payload := []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x09, ++ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02} ++ res, err := parseGSSAPIPayload(payload) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if ok := res.OIDS[0].Equal(krb5Mesh); !ok { ++ t.Fatalf("got %v, want %v", res, krb5Mesh) ++ } ++} ++ ++func TestBuildMIC(t *testing.T) { ++ sessionID := []byte{134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53, ++ 183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121} ++ username := "testuser" ++ service := "ssh-connection" ++ authMethod := "gssapi-with-mic" ++ expected := []byte{0, 0, 0, 32, 134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53, 183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121, 50, 0, 0, 0, 8, 116, 101, 115, 116, 117, 115, 101, 114, 0, 0, 0, 14, 115, 115, 104, 45, 99, 111, 110, 110, 101, 99, 116, 105, 111, 110, 0, 0, 0, 15, 103, 115, 115, 97, 112, 105, 45, 119, 105, 116, 104, 45, 109, 105, 99} ++ result := buildMIC(string(sessionID), username, service, authMethod) ++ if string(result) != string(expected) { ++ t.Fatalf("buildMic: got %v, want %v", result, expected) ++ } ++} ++ ++type exchange struct { ++ outToken string ++ expectedToken string ++} ++ ++type FakeClient struct { ++ exchanges []*exchange ++ round int ++ mic []byte ++ maxRound int ++} ++ ++func (f *FakeClient) InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) { ++ if token == nil { ++ if f.exchanges[f.round].expectedToken != "" { ++ err = fmt.Errorf("got empty token, want %q", f.exchanges[f.round].expectedToken) ++ } else { ++ outputToken = []byte(f.exchanges[f.round].outToken) ++ } ++ } else { ++ if string(token) != string(f.exchanges[f.round].expectedToken) { ++ err = fmt.Errorf("got %q, want token %q", token, f.exchanges[f.round].expectedToken) ++ } else { ++ outputToken = []byte(f.exchanges[f.round].outToken) ++ } ++ } ++ f.round++ ++ needContinue = f.round < f.maxRound ++ return ++} ++ ++func (f *FakeClient) GetMIC(micField []byte) ([]byte, error) { ++ return f.mic, nil ++} ++ ++func (f *FakeClient) DeleteSecContext() error { ++ return nil ++} ++ ++type FakeServer struct { ++ exchanges []*exchange ++ round int ++ expectedMIC []byte ++ srcName string ++ maxRound int ++} ++ ++func (f *FakeServer) AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) { ++ if token == nil { ++ if f.exchanges[f.round].expectedToken != "" { ++ err = fmt.Errorf("got empty token, want %q", f.exchanges[f.round].expectedToken) ++ } else { ++ outputToken = []byte(f.exchanges[f.round].outToken) ++ } ++ } else { ++ if string(token) != string(f.exchanges[f.round].expectedToken) { ++ err = fmt.Errorf("got %q, want token %q", token, f.exchanges[f.round].expectedToken) ++ } else { ++ outputToken = []byte(f.exchanges[f.round].outToken) ++ } ++ } ++ f.round++ ++ needContinue = f.round < f.maxRound ++ srcName = f.srcName ++ return ++} ++ ++func (f *FakeServer) VerifyMIC(micField []byte, micToken []byte) error { ++ if string(micToken) != string(f.expectedMIC) { ++ return fmt.Errorf("got MICToken %q, want %q", micToken, f.expectedMIC) ++ } ++ return nil ++} ++ ++func (f *FakeServer) DeleteSecContext() error { ++ return nil ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/streamlocal.go b/ms_mod/golang.org/x/crypto/ssh/streamlocal.go +new file mode 100644 +index 00000000000000..b171b330bc380a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/streamlocal.go +@@ -0,0 +1,116 @@ ++package ssh ++ ++import ( ++ "errors" ++ "io" ++ "net" ++) ++ ++// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message ++// with "direct-streamlocal@openssh.com" string. ++// ++// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding ++// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235 ++type streamLocalChannelOpenDirectMsg struct { ++ socketPath string ++ reserved0 string ++ reserved1 uint32 ++} ++ ++// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message ++// with "forwarded-streamlocal@openssh.com" string. ++type forwardedStreamLocalPayload struct { ++ SocketPath string ++ Reserved0 string ++} ++ ++// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message ++// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string. ++type streamLocalChannelForwardMsg struct { ++ socketPath string ++} ++ ++// ListenUnix is similar to ListenTCP but uses a Unix domain socket. ++func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { ++ c.handleForwardsOnce.Do(c.handleForwards) ++ m := streamLocalChannelForwardMsg{ ++ socketPath, ++ } ++ // send message ++ ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m)) ++ if err != nil { ++ return nil, err ++ } ++ if !ok { ++ return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer") ++ } ++ ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"}) ++ ++ return &unixListener{socketPath, c, ch}, nil ++} ++ ++func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { ++ msg := streamLocalChannelOpenDirectMsg{ ++ socketPath: socketPath, ++ } ++ ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg)) ++ if err != nil { ++ return nil, err ++ } ++ go DiscardRequests(in) ++ return ch, err ++} ++ ++type unixListener struct { ++ socketPath string ++ ++ conn *Client ++ in <-chan forward ++} ++ ++// Accept waits for and returns the next connection to the listener. ++func (l *unixListener) Accept() (net.Conn, error) { ++ s, ok := <-l.in ++ if !ok { ++ return nil, io.EOF ++ } ++ ch, incoming, err := s.newCh.Accept() ++ if err != nil { ++ return nil, err ++ } ++ go DiscardRequests(incoming) ++ ++ return &chanConn{ ++ Channel: ch, ++ laddr: &net.UnixAddr{ ++ Name: l.socketPath, ++ Net: "unix", ++ }, ++ raddr: &net.UnixAddr{ ++ Name: "@", ++ Net: "unix", ++ }, ++ }, nil ++} ++ ++// Close closes the listener. ++func (l *unixListener) Close() error { ++ // this also closes the listener. ++ l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"}) ++ m := streamLocalChannelForwardMsg{ ++ l.socketPath, ++ } ++ ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m)) ++ if err == nil && !ok { ++ err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed") ++ } ++ return err ++} ++ ++// Addr returns the listener's network address. ++func (l *unixListener) Addr() net.Addr { ++ return &net.UnixAddr{ ++ Name: l.socketPath, ++ Net: "unix", ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/tcpip.go b/ms_mod/golang.org/x/crypto/ssh/tcpip.go +new file mode 100644 +index 00000000000000..80d35f5ec187a4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/tcpip.go +@@ -0,0 +1,474 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ "math/rand" ++ "net" ++ "strconv" ++ "strings" ++ "sync" ++ "time" ++) ++ ++// Listen requests the remote peer open a listening socket on ++// addr. Incoming connections will be available by calling Accept on ++// the returned net.Listener. The listener must be serviced, or the ++// SSH connection may hang. ++// N must be "tcp", "tcp4", "tcp6", or "unix". ++func (c *Client) Listen(n, addr string) (net.Listener, error) { ++ switch n { ++ case "tcp", "tcp4", "tcp6": ++ laddr, err := net.ResolveTCPAddr(n, addr) ++ if err != nil { ++ return nil, err ++ } ++ return c.ListenTCP(laddr) ++ case "unix": ++ return c.ListenUnix(addr) ++ default: ++ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) ++ } ++} ++ ++// Automatic port allocation is broken with OpenSSH before 6.0. See ++// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In ++// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, ++// rather than the actual port number. This means you can never open ++// two different listeners with auto allocated ports. We work around ++// this by trying explicit ports until we succeed. ++ ++const openSSHPrefix = "OpenSSH_" ++ ++var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) ++ ++// isBrokenOpenSSHVersion returns true if the given version string ++// specifies a version of OpenSSH that is known to have a bug in port ++// forwarding. ++func isBrokenOpenSSHVersion(versionStr string) bool { ++ i := strings.Index(versionStr, openSSHPrefix) ++ if i < 0 { ++ return false ++ } ++ i += len(openSSHPrefix) ++ j := i ++ for ; j < len(versionStr); j++ { ++ if versionStr[j] < '0' || versionStr[j] > '9' { ++ break ++ } ++ } ++ version, _ := strconv.Atoi(versionStr[i:j]) ++ return version < 6 ++} ++ ++// autoPortListenWorkaround simulates automatic port allocation by ++// trying random ports repeatedly. ++func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { ++ var sshListener net.Listener ++ var err error ++ const tries = 10 ++ for i := 0; i < tries; i++ { ++ addr := *laddr ++ addr.Port = 1024 + portRandomizer.Intn(60000) ++ sshListener, err = c.ListenTCP(&addr) ++ if err == nil { ++ laddr.Port = addr.Port ++ return sshListener, err ++ } ++ } ++ return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) ++} ++ ++// RFC 4254 7.1 ++type channelForwardMsg struct { ++ addr string ++ rport uint32 ++} ++ ++// handleForwards starts goroutines handling forwarded connections. ++// It's called on first use by (*Client).ListenTCP to not launch ++// goroutines until needed. ++func (c *Client) handleForwards() { ++ go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip")) ++ go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com")) ++} ++ ++// ListenTCP requests the remote peer open a listening socket ++// on laddr. Incoming connections will be available by calling ++// Accept on the returned net.Listener. ++func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { ++ c.handleForwardsOnce.Do(c.handleForwards) ++ if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { ++ return c.autoPortListenWorkaround(laddr) ++ } ++ ++ m := channelForwardMsg{ ++ laddr.IP.String(), ++ uint32(laddr.Port), ++ } ++ // send message ++ ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) ++ if err != nil { ++ return nil, err ++ } ++ if !ok { ++ return nil, errors.New("ssh: tcpip-forward request denied by peer") ++ } ++ ++ // If the original port was 0, then the remote side will ++ // supply a real port number in the response. ++ if laddr.Port == 0 { ++ var p struct { ++ Port uint32 ++ } ++ if err := Unmarshal(resp, &p); err != nil { ++ return nil, err ++ } ++ laddr.Port = int(p.Port) ++ } ++ ++ // Register this forward, using the port number we obtained. ++ ch := c.forwards.add(laddr) ++ ++ return &tcpListener{laddr, c, ch}, nil ++} ++ ++// forwardList stores a mapping between remote ++// forward requests and the tcpListeners. ++type forwardList struct { ++ sync.Mutex ++ entries []forwardEntry ++} ++ ++// forwardEntry represents an established mapping of a laddr on a ++// remote ssh server to a channel connected to a tcpListener. ++type forwardEntry struct { ++ laddr net.Addr ++ c chan forward ++} ++ ++// forward represents an incoming forwarded tcpip connection. The ++// arguments to add/remove/lookup should be address as specified in ++// the original forward-request. ++type forward struct { ++ newCh NewChannel // the ssh client channel underlying this forward ++ raddr net.Addr // the raddr of the incoming connection ++} ++ ++func (l *forwardList) add(addr net.Addr) chan forward { ++ l.Lock() ++ defer l.Unlock() ++ f := forwardEntry{ ++ laddr: addr, ++ c: make(chan forward, 1), ++ } ++ l.entries = append(l.entries, f) ++ return f.c ++} ++ ++// See RFC 4254, section 7.2 ++type forwardedTCPPayload struct { ++ Addr string ++ Port uint32 ++ OriginAddr string ++ OriginPort uint32 ++} ++ ++// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. ++func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { ++ if port == 0 || port > 65535 { ++ return nil, fmt.Errorf("ssh: port number out of range: %d", port) ++ } ++ ip := net.ParseIP(string(addr)) ++ if ip == nil { ++ return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) ++ } ++ return &net.TCPAddr{IP: ip, Port: int(port)}, nil ++} ++ ++func (l *forwardList) handleChannels(in <-chan NewChannel) { ++ for ch := range in { ++ var ( ++ laddr net.Addr ++ raddr net.Addr ++ err error ++ ) ++ switch channelType := ch.ChannelType(); channelType { ++ case "forwarded-tcpip": ++ var payload forwardedTCPPayload ++ if err = Unmarshal(ch.ExtraData(), &payload); err != nil { ++ ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) ++ continue ++ } ++ ++ // RFC 4254 section 7.2 specifies that incoming ++ // addresses should list the address, in string ++ // format. It is implied that this should be an IP ++ // address, as it would be impossible to connect to it ++ // otherwise. ++ laddr, err = parseTCPAddr(payload.Addr, payload.Port) ++ if err != nil { ++ ch.Reject(ConnectionFailed, err.Error()) ++ continue ++ } ++ raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort) ++ if err != nil { ++ ch.Reject(ConnectionFailed, err.Error()) ++ continue ++ } ++ ++ case "forwarded-streamlocal@openssh.com": ++ var payload forwardedStreamLocalPayload ++ if err = Unmarshal(ch.ExtraData(), &payload); err != nil { ++ ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error()) ++ continue ++ } ++ laddr = &net.UnixAddr{ ++ Name: payload.SocketPath, ++ Net: "unix", ++ } ++ raddr = &net.UnixAddr{ ++ Name: "@", ++ Net: "unix", ++ } ++ default: ++ panic(fmt.Errorf("ssh: unknown channel type %s", channelType)) ++ } ++ if ok := l.forward(laddr, raddr, ch); !ok { ++ // Section 7.2, implementations MUST reject spurious incoming ++ // connections. ++ ch.Reject(Prohibited, "no forward for address") ++ continue ++ } ++ ++ } ++} ++ ++// remove removes the forward entry, and the channel feeding its ++// listener. ++func (l *forwardList) remove(addr net.Addr) { ++ l.Lock() ++ defer l.Unlock() ++ for i, f := range l.entries { ++ if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() { ++ l.entries = append(l.entries[:i], l.entries[i+1:]...) ++ close(f.c) ++ return ++ } ++ } ++} ++ ++// closeAll closes and clears all forwards. ++func (l *forwardList) closeAll() { ++ l.Lock() ++ defer l.Unlock() ++ for _, f := range l.entries { ++ close(f.c) ++ } ++ l.entries = nil ++} ++ ++func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool { ++ l.Lock() ++ defer l.Unlock() ++ for _, f := range l.entries { ++ if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() { ++ f.c <- forward{newCh: ch, raddr: raddr} ++ return true ++ } ++ } ++ return false ++} ++ ++type tcpListener struct { ++ laddr *net.TCPAddr ++ ++ conn *Client ++ in <-chan forward ++} ++ ++// Accept waits for and returns the next connection to the listener. ++func (l *tcpListener) Accept() (net.Conn, error) { ++ s, ok := <-l.in ++ if !ok { ++ return nil, io.EOF ++ } ++ ch, incoming, err := s.newCh.Accept() ++ if err != nil { ++ return nil, err ++ } ++ go DiscardRequests(incoming) ++ ++ return &chanConn{ ++ Channel: ch, ++ laddr: l.laddr, ++ raddr: s.raddr, ++ }, nil ++} ++ ++// Close closes the listener. ++func (l *tcpListener) Close() error { ++ m := channelForwardMsg{ ++ l.laddr.IP.String(), ++ uint32(l.laddr.Port), ++ } ++ ++ // this also closes the listener. ++ l.conn.forwards.remove(l.laddr) ++ ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) ++ if err == nil && !ok { ++ err = errors.New("ssh: cancel-tcpip-forward failed") ++ } ++ return err ++} ++ ++// Addr returns the listener's network address. ++func (l *tcpListener) Addr() net.Addr { ++ return l.laddr ++} ++ ++// Dial initiates a connection to the addr from the remote host. ++// The resulting connection has a zero LocalAddr() and RemoteAddr(). ++func (c *Client) Dial(n, addr string) (net.Conn, error) { ++ var ch Channel ++ switch n { ++ case "tcp", "tcp4", "tcp6": ++ // Parse the address into host and numeric port. ++ host, portString, err := net.SplitHostPort(addr) ++ if err != nil { ++ return nil, err ++ } ++ port, err := strconv.ParseUint(portString, 10, 16) ++ if err != nil { ++ return nil, err ++ } ++ ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port)) ++ if err != nil { ++ return nil, err ++ } ++ // Use a zero address for local and remote address. ++ zeroAddr := &net.TCPAddr{ ++ IP: net.IPv4zero, ++ Port: 0, ++ } ++ return &chanConn{ ++ Channel: ch, ++ laddr: zeroAddr, ++ raddr: zeroAddr, ++ }, nil ++ case "unix": ++ var err error ++ ch, err = c.dialStreamLocal(addr) ++ if err != nil { ++ return nil, err ++ } ++ return &chanConn{ ++ Channel: ch, ++ laddr: &net.UnixAddr{ ++ Name: "@", ++ Net: "unix", ++ }, ++ raddr: &net.UnixAddr{ ++ Name: addr, ++ Net: "unix", ++ }, ++ }, nil ++ default: ++ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) ++ } ++} ++ ++// DialTCP connects to the remote address raddr on the network net, ++// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used ++// as the local address for the connection. ++func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { ++ if laddr == nil { ++ laddr = &net.TCPAddr{ ++ IP: net.IPv4zero, ++ Port: 0, ++ } ++ } ++ ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) ++ if err != nil { ++ return nil, err ++ } ++ return &chanConn{ ++ Channel: ch, ++ laddr: laddr, ++ raddr: raddr, ++ }, nil ++} ++ ++// RFC 4254 7.2 ++type channelOpenDirectMsg struct { ++ raddr string ++ rport uint32 ++ laddr string ++ lport uint32 ++} ++ ++func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { ++ msg := channelOpenDirectMsg{ ++ raddr: raddr, ++ rport: uint32(rport), ++ laddr: laddr, ++ lport: uint32(lport), ++ } ++ ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) ++ if err != nil { ++ return nil, err ++ } ++ go DiscardRequests(in) ++ return ch, err ++} ++ ++type tcpChan struct { ++ Channel // the backing channel ++} ++ ++// chanConn fulfills the net.Conn interface without ++// the tcpChan having to hold laddr or raddr directly. ++type chanConn struct { ++ Channel ++ laddr, raddr net.Addr ++} ++ ++// LocalAddr returns the local network address. ++func (t *chanConn) LocalAddr() net.Addr { ++ return t.laddr ++} ++ ++// RemoteAddr returns the remote network address. ++func (t *chanConn) RemoteAddr() net.Addr { ++ return t.raddr ++} ++ ++// SetDeadline sets the read and write deadlines associated ++// with the connection. ++func (t *chanConn) SetDeadline(deadline time.Time) error { ++ if err := t.SetReadDeadline(deadline); err != nil { ++ return err ++ } ++ return t.SetWriteDeadline(deadline) ++} ++ ++// SetReadDeadline sets the read deadline. ++// A zero value for t means Read will not time out. ++// After the deadline, the error from Read will implement net.Error ++// with Timeout() == true. ++func (t *chanConn) SetReadDeadline(deadline time.Time) error { ++ // for compatibility with previous version, ++ // the error message contains "tcpChan" ++ return errors.New("ssh: tcpChan: deadline not supported") ++} ++ ++// SetWriteDeadline exists to satisfy the net.Conn interface ++// but is not implemented by this type. It always returns an error. ++func (t *chanConn) SetWriteDeadline(deadline time.Time) error { ++ return errors.New("ssh: tcpChan: deadline not supported") ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/tcpip_test.go b/ms_mod/golang.org/x/crypto/ssh/tcpip_test.go +new file mode 100644 +index 00000000000000..f1265cb4964ede +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/tcpip_test.go +@@ -0,0 +1,20 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "testing" ++) ++ ++func TestAutoPortListenBroken(t *testing.T) { ++ broken := "SSH-2.0-OpenSSH_5.9hh11" ++ works := "SSH-2.0-OpenSSH_6.1" ++ if !isBrokenOpenSSHVersion(broken) { ++ t.Errorf("version %q not marked as broken", broken) ++ } ++ if isBrokenOpenSSHVersion(works) { ++ t.Errorf("version %q marked as broken", works) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go b/ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go +new file mode 100644 +index 00000000000000..a4d1919a9e7d64 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go +@@ -0,0 +1,76 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package terminal provides support functions for dealing with terminals, as ++// commonly found on UNIX systems. ++// ++// Deprecated: this package moved to golang.org/x/term. ++package terminal ++ ++import ( ++ "io" ++ ++ "golang.org/x/term" ++) ++ ++// EscapeCodes contains escape sequences that can be written to the terminal in ++// order to achieve different styles of text. ++type EscapeCodes = term.EscapeCodes ++ ++// Terminal contains the state for running a VT100 terminal that is capable of ++// reading lines of input. ++type Terminal = term.Terminal ++ ++// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is ++// a local terminal, that terminal must first have been put into raw mode. ++// prompt is a string that is written at the start of each input line (i.e. ++// "> "). ++func NewTerminal(c io.ReadWriter, prompt string) *Terminal { ++ return term.NewTerminal(c, prompt) ++} ++ ++// ErrPasteIndicator may be returned from ReadLine as the error, in addition ++// to valid line data. It indicates that bracketed paste mode is enabled and ++// that the returned line consists only of pasted data. Programs may wish to ++// interpret pasted data more literally than typed data. ++var ErrPasteIndicator = term.ErrPasteIndicator ++ ++// State contains the state of a terminal. ++type State = term.State ++ ++// IsTerminal returns whether the given file descriptor is a terminal. ++func IsTerminal(fd int) bool { ++ return term.IsTerminal(fd) ++} ++ ++// ReadPassword reads a line of input from a terminal without local echo. This ++// is commonly used for inputting passwords and other sensitive data. The slice ++// returned does not include the \n. ++func ReadPassword(fd int) ([]byte, error) { ++ return term.ReadPassword(fd) ++} ++ ++// MakeRaw puts the terminal connected to the given file descriptor into raw ++// mode and returns the previous state of the terminal so that it can be ++// restored. ++func MakeRaw(fd int) (*State, error) { ++ return term.MakeRaw(fd) ++} ++ ++// Restore restores the terminal connected to the given file descriptor to a ++// previous state. ++func Restore(fd int, oldState *State) error { ++ return term.Restore(fd, oldState) ++} ++ ++// GetState returns the current state of a terminal which may be useful to ++// restore the terminal after a signal. ++func GetState(fd int) (*State, error) { ++ return term.GetState(fd) ++} ++ ++// GetSize returns the dimensions of the given terminal. ++func GetSize(fd int) (width, height int, err error) { ++ return term.GetSize(fd) ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go +new file mode 100644 +index 00000000000000..43fbdb22eb4e74 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go +@@ -0,0 +1,59 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris ++// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris ++ ++package test ++ ++import ( ++ "bytes" ++ "testing" ++ ++ "golang.org/x/crypto/ssh" ++ "golang.org/x/crypto/ssh/agent" ++) ++ ++func TestAgentForward(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ keyring := agent.NewKeyring() ++ if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil { ++ t.Fatalf("Error adding key: %s", err) ++ } ++ if err := keyring.Add(agent.AddedKey{ ++ PrivateKey: testPrivateKeys["dsa"], ++ ConfirmBeforeUse: true, ++ LifetimeSecs: 3600, ++ }); err != nil { ++ t.Fatalf("Error adding key with constraints: %s", err) ++ } ++ pub := testPublicKeys["dsa"] ++ ++ sess, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("NewSession: %v", err) ++ } ++ if err := agent.RequestAgentForwarding(sess); err != nil { ++ t.Fatalf("RequestAgentForwarding: %v", err) ++ } ++ ++ if err := agent.ForwardToAgent(conn, keyring); err != nil { ++ t.Fatalf("SetupForwardKeyring: %v", err) ++ } ++ out, err := sess.CombinedOutput("ssh-add -L") ++ if err != nil { ++ t.Fatalf("running ssh-add: %v, out %s", err, out) ++ } ++ key, _, _, _, err := ssh.ParseAuthorizedKey(out) ++ if err != nil { ++ t.Fatalf("ParseAuthorizedKey(%q): %v", out, err) ++ } ++ ++ if !bytes.Equal(key.Marshal(), pub.Marshal()) { ++ t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub)) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/banner_test.go b/ms_mod/golang.org/x/crypto/ssh/test/banner_test.go +new file mode 100644 +index 00000000000000..3bfdd4b059094f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/banner_test.go +@@ -0,0 +1,32 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris ++// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris ++ ++package test ++ ++import ( ++ "testing" ++) ++ ++func TestBannerCallbackAgainstOpenSSH(t *testing.T) { ++ server := newServer(t) ++ ++ clientConf := clientConfig() ++ ++ var receivedBanner string ++ clientConf.BannerCallback = func(message string) error { ++ receivedBanner = message ++ return nil ++ } ++ ++ conn := server.Dial(clientConf) ++ defer conn.Close() ++ ++ expected := "Server Banner" ++ if receivedBanner != expected { ++ t.Fatalf("got %v; want %v", receivedBanner, expected) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/cert_test.go b/ms_mod/golang.org/x/crypto/ssh/test/cert_test.go +new file mode 100644 +index 00000000000000..83dd534c5ca5db +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/cert_test.go +@@ -0,0 +1,77 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris ++// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris ++ ++package test ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "testing" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++// Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly ++func TestCertLogin(t *testing.T) { ++ s := newServer(t) ++ ++ // Use a key different from the default. ++ clientKey := testSigners["dsa"] ++ caAuthKey := testSigners["ecdsa"] ++ cert := &ssh.Certificate{ ++ Key: clientKey.PublicKey(), ++ ValidPrincipals: []string{username()}, ++ CertType: ssh.UserCert, ++ ValidBefore: ssh.CertTimeInfinity, ++ } ++ if err := cert.SignCert(rand.Reader, caAuthKey); err != nil { ++ t.Fatalf("SetSignature: %v", err) ++ } ++ ++ certSigner, err := ssh.NewCertSigner(cert, clientKey) ++ if err != nil { ++ t.Fatalf("NewCertSigner: %v", err) ++ } ++ ++ conf := &ssh.ClientConfig{ ++ User: username(), ++ HostKeyCallback: (&ssh.CertChecker{ ++ IsHostAuthority: func(pk ssh.PublicKey, addr string) bool { ++ return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal()) ++ }, ++ }).CheckHostKey, ++ } ++ conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner)) ++ ++ for _, test := range []struct { ++ addr string ++ succeed bool ++ }{ ++ {addr: "host.example.com:22", succeed: true}, ++ {addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK ++ {addr: "host.example.com", succeed: false}, // port must be specified ++ {addr: "host.ex4mple.com:22", succeed: false}, // wrong host ++ } { ++ client, err := s.TryDialWithAddr(conf, test.addr) ++ ++ // Always close client if opened successfully ++ if err == nil { ++ client.Close() ++ } ++ ++ // Now evaluate whether the test failed or passed ++ if test.succeed { ++ if err != nil { ++ t.Fatalf("TryDialWithAddr: %v", err) ++ } ++ } else { ++ if err == nil { ++ t.Fatalf("TryDialWithAddr, unexpected success") ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go +new file mode 100644 +index 00000000000000..4a7ec31737581a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go +@@ -0,0 +1,127 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !windows && !js && !wasip1 ++// +build !windows,!js,!wasip1 ++ ++package test ++ ++// direct-tcpip and direct-streamlocal functional tests ++ ++import ( ++ "fmt" ++ "io" ++ "net" ++ "strings" ++ "testing" ++) ++ ++type dialTester interface { ++ TestServerConn(t *testing.T, c net.Conn) ++ TestClientConn(t *testing.T, c net.Conn) ++} ++ ++func testDial(t *testing.T, n, listenAddr string, x dialTester) { ++ server := newServer(t) ++ sshConn := server.Dial(clientConfig()) ++ defer sshConn.Close() ++ ++ l, err := net.Listen(n, listenAddr) ++ if err != nil { ++ t.Fatalf("Listen: %v", err) ++ } ++ defer l.Close() ++ ++ testData := fmt.Sprintf("hello from %s, %s", n, listenAddr) ++ go func() { ++ for { ++ c, err := l.Accept() ++ if err != nil { ++ break ++ } ++ x.TestServerConn(t, c) ++ ++ io.WriteString(c, testData) ++ c.Close() ++ } ++ }() ++ ++ conn, err := sshConn.Dial(n, l.Addr().String()) ++ if err != nil { ++ t.Fatalf("Dial: %v", err) ++ } ++ x.TestClientConn(t, conn) ++ defer conn.Close() ++ b, err := io.ReadAll(conn) ++ if err != nil { ++ t.Fatalf("ReadAll: %v", err) ++ } ++ t.Logf("got %q", string(b)) ++ if string(b) != testData { ++ t.Fatalf("expected %q, got %q", testData, string(b)) ++ } ++} ++ ++type tcpDialTester struct { ++ listenAddr string ++} ++ ++func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) { ++ host := strings.Split(x.listenAddr, ":")[0] ++ prefix := host + ":" ++ if !strings.HasPrefix(c.LocalAddr().String(), prefix) { ++ t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String()) ++ } ++ if !strings.HasPrefix(c.RemoteAddr().String(), prefix) { ++ t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String()) ++ } ++} ++ ++func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) { ++ // we use zero addresses. see *Client.Dial. ++ if c.LocalAddr().String() != "0.0.0.0:0" { ++ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String()) ++ } ++ if c.RemoteAddr().String() != "0.0.0.0:0" { ++ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String()) ++ } ++} ++ ++func TestDialTCP(t *testing.T) { ++ x := &tcpDialTester{ ++ listenAddr: "127.0.0.1:0", ++ } ++ testDial(t, "tcp", x.listenAddr, x) ++} ++ ++type unixDialTester struct { ++ listenAddr string ++} ++ ++func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) { ++ if c.LocalAddr().String() != x.listenAddr { ++ t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String()) ++ } ++ if c.RemoteAddr().String() != "@" && c.RemoteAddr().String() != "" { ++ t.Fatalf("expected \"@\" or \"\", got %q", c.RemoteAddr().String()) ++ } ++} ++ ++func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) { ++ if c.RemoteAddr().String() != x.listenAddr { ++ t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String()) ++ } ++ if c.LocalAddr().String() != "@" { ++ t.Fatalf("expected \"@\", got %q", c.LocalAddr().String()) ++ } ++} ++ ++func TestDialUnix(t *testing.T) { ++ addr, cleanup := newTempSocket(t) ++ defer cleanup() ++ x := &unixDialTester{ ++ listenAddr: addr, ++ } ++ testDial(t, "unix", x.listenAddr, x) ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/doc.go b/ms_mod/golang.org/x/crypto/ssh/test/doc.go +new file mode 100644 +index 00000000000000..198f0ca1e20570 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/doc.go +@@ -0,0 +1,7 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package test contains integration tests for the ++// golang.org/x/crypto/ssh package. ++package test // import "golang.org/x/crypto/ssh/test" +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go +new file mode 100644 +index 00000000000000..1171bc3a14ef01 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go +@@ -0,0 +1,198 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris ++// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris ++ ++package test ++ ++import ( ++ "bytes" ++ "fmt" ++ "io" ++ "math/rand" ++ "net" ++ "testing" ++ "time" ++) ++ ++type closeWriter interface { ++ CloseWrite() error ++} ++ ++func testPortForward(t *testing.T, n, listenAddr string) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ sshListener, err := conn.Listen(n, listenAddr) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ errCh := make(chan error, 1) ++ ++ go func() { ++ defer close(errCh) ++ sshConn, err := sshListener.Accept() ++ if err != nil { ++ errCh <- fmt.Errorf("listen.Accept failed: %v", err) ++ return ++ } ++ defer sshConn.Close() ++ ++ _, err = io.Copy(sshConn, sshConn) ++ if err != nil && err != io.EOF { ++ errCh <- fmt.Errorf("ssh client copy: %v", err) ++ } ++ }() ++ ++ forwardedAddr := sshListener.Addr().String() ++ netConn, err := net.Dial(n, forwardedAddr) ++ if err != nil { ++ t.Fatalf("net dial failed: %v", err) ++ } ++ ++ readChan := make(chan []byte) ++ go func() { ++ data, _ := io.ReadAll(netConn) ++ readChan <- data ++ }() ++ ++ // Invent some data. ++ data := make([]byte, 100*1000) ++ for i := range data { ++ data[i] = byte(i % 255) ++ } ++ ++ var sent []byte ++ for len(sent) < 1000*1000 { ++ // Send random sized chunks ++ m := rand.Intn(len(data)) ++ n, err := netConn.Write(data[:m]) ++ if err != nil { ++ break ++ } ++ sent = append(sent, data[:n]...) ++ } ++ if err := netConn.(closeWriter).CloseWrite(); err != nil { ++ t.Errorf("netConn.CloseWrite: %v", err) ++ } ++ ++ // Check for errors on server goroutine ++ err = <-errCh ++ if err != nil { ++ t.Fatalf("server: %v", err) ++ } ++ ++ read := <-readChan ++ ++ if len(sent) != len(read) { ++ t.Fatalf("got %d bytes, want %d", len(read), len(sent)) ++ } ++ if bytes.Compare(sent, read) != 0 { ++ t.Fatalf("read back data does not match") ++ } ++ ++ if err := sshListener.Close(); err != nil { ++ t.Fatalf("sshListener.Close: %v", err) ++ } ++ ++ // Check that the forward disappeared. ++ netConn, err = net.Dial(n, forwardedAddr) ++ if err == nil { ++ netConn.Close() ++ t.Errorf("still listening to %s after closing", forwardedAddr) ++ } ++} ++ ++func TestPortForwardTCP(t *testing.T) { ++ testPortForward(t, "tcp", "localhost:0") ++} ++ ++func TestPortForwardUnix(t *testing.T) { ++ addr, cleanup := newTempSocket(t) ++ defer cleanup() ++ testPortForward(t, "unix", addr) ++} ++ ++func testAcceptClose(t *testing.T, n, listenAddr string) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ ++ sshListener, err := conn.Listen(n, listenAddr) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ quit := make(chan error, 1) ++ go func() { ++ for { ++ c, err := sshListener.Accept() ++ if err != nil { ++ quit <- err ++ break ++ } ++ c.Close() ++ } ++ }() ++ sshListener.Close() ++ ++ select { ++ case <-time.After(1 * time.Second): ++ t.Errorf("timeout: listener did not close.") ++ case err := <-quit: ++ t.Logf("quit as expected (error %v)", err) ++ } ++} ++ ++func TestAcceptCloseTCP(t *testing.T) { ++ testAcceptClose(t, "tcp", "localhost:0") ++} ++ ++func TestAcceptCloseUnix(t *testing.T) { ++ addr, cleanup := newTempSocket(t) ++ defer cleanup() ++ testAcceptClose(t, "unix", addr) ++} ++ ++// Check that listeners exit if the underlying client transport dies. ++func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) { ++ server := newServer(t) ++ client := server.Dial(clientConfig()) ++ ++ sshListener, err := client.Listen(n, listenAddr) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ quit := make(chan error, 1) ++ go func() { ++ for { ++ c, err := sshListener.Accept() ++ if err != nil { ++ quit <- err ++ break ++ } ++ c.Close() ++ } ++ }() ++ ++ // It would be even nicer if we closed the server side, but it ++ // is more involved as the fd for that side is dup()ed. ++ server.lastDialConn.Close() ++ ++ err = <-quit ++ t.Logf("quit as expected (error %v)", err) ++} ++ ++func TestPortForwardConnectionCloseTCP(t *testing.T) { ++ testPortForwardConnectionClose(t, "tcp", "localhost:0") ++} ++ ++func TestPortForwardConnectionCloseUnix(t *testing.T) { ++ addr, cleanup := newTempSocket(t) ++ defer cleanup() ++ testPortForwardConnectionClose(t, "unix", addr) ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go b/ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go +new file mode 100644 +index 00000000000000..403d7363ab0206 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go +@@ -0,0 +1,144 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Tests for ssh client multi-auth ++// ++// These tests run a simple go ssh client against OpenSSH server ++// over unix domain sockets. The tests use multiple combinations ++// of password, keyboard-interactive and publickey authentication ++// methods. ++// ++// A wrapper library for making sshd PAM authentication use test ++// passwords is required in ./sshd_test_pw.so. If the library does ++// not exist these tests will be skipped. See compile instructions ++// (for linux) in file ./sshd_test_pw.c. ++ ++//go:build linux ++// +build linux ++ ++package test ++ ++import ( ++ "fmt" ++ "strings" ++ "testing" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++// test cases ++type multiAuthTestCase struct { ++ authMethods []string ++ expectedPasswordCbs int ++ expectedKbdIntCbs int ++} ++ ++// test context ++type multiAuthTestCtx struct { ++ password string ++ numPasswordCbs int ++ numKbdIntCbs int ++} ++ ++// create test context ++func newMultiAuthTestCtx(t *testing.T) *multiAuthTestCtx { ++ password, err := randomPassword() ++ if err != nil { ++ t.Fatalf("Failed to generate random test password: %s", err.Error()) ++ } ++ ++ return &multiAuthTestCtx{ ++ password: password, ++ } ++} ++ ++// password callback ++func (ctx *multiAuthTestCtx) passwordCb() (secret string, err error) { ++ ctx.numPasswordCbs++ ++ return ctx.password, nil ++} ++ ++// keyboard-interactive callback ++func (ctx *multiAuthTestCtx) kbdIntCb(user, instruction string, questions []string, echos []bool) (answers []string, err error) { ++ if len(questions) == 0 { ++ return nil, nil ++ } ++ ++ ctx.numKbdIntCbs++ ++ if len(questions) == 1 { ++ return []string{ctx.password}, nil ++ } ++ ++ return nil, fmt.Errorf("unsupported keyboard-interactive flow") ++} ++ ++// TestMultiAuth runs several subtests for different combinations of password, keyboard-interactive and publickey authentication methods ++func TestMultiAuth(t *testing.T) { ++ testCases := []multiAuthTestCase{ ++ // Test password,publickey authentication, assert that password callback is called 1 time ++ { ++ authMethods: []string{"password", "publickey"}, ++ expectedPasswordCbs: 1, ++ }, ++ // Test keyboard-interactive,publickey authentication, assert that keyboard-interactive callback is called 1 time ++ { ++ authMethods: []string{"keyboard-interactive", "publickey"}, ++ expectedKbdIntCbs: 1, ++ }, ++ // Test publickey,password authentication, assert that password callback is called 1 time ++ { ++ authMethods: []string{"publickey", "password"}, ++ expectedPasswordCbs: 1, ++ }, ++ // Test publickey,keyboard-interactive authentication, assert that keyboard-interactive callback is called 1 time ++ { ++ authMethods: []string{"publickey", "keyboard-interactive"}, ++ expectedKbdIntCbs: 1, ++ }, ++ // Test password,password authentication, assert that password callback is called 2 times ++ { ++ authMethods: []string{"password", "password"}, ++ expectedPasswordCbs: 2, ++ }, ++ } ++ ++ for _, testCase := range testCases { ++ t.Run(strings.Join(testCase.authMethods, ","), func(t *testing.T) { ++ ctx := newMultiAuthTestCtx(t) ++ ++ server := newServerForConfig(t, "MultiAuth", map[string]string{"AuthMethods": strings.Join(testCase.authMethods, ",")}) ++ ++ clientConfig := clientConfig() ++ server.setTestPassword(clientConfig.User, ctx.password) ++ ++ publicKeyAuthMethod := clientConfig.Auth[0] ++ clientConfig.Auth = nil ++ for _, authMethod := range testCase.authMethods { ++ switch authMethod { ++ case "publickey": ++ clientConfig.Auth = append(clientConfig.Auth, publicKeyAuthMethod) ++ case "password": ++ clientConfig.Auth = append(clientConfig.Auth, ++ ssh.RetryableAuthMethod(ssh.PasswordCallback(ctx.passwordCb), 5)) ++ case "keyboard-interactive": ++ clientConfig.Auth = append(clientConfig.Auth, ++ ssh.RetryableAuthMethod(ssh.KeyboardInteractive(ctx.kbdIntCb), 5)) ++ default: ++ t.Fatalf("Unknown authentication method %s", authMethod) ++ } ++ } ++ ++ conn := server.Dial(clientConfig) ++ defer conn.Close() ++ ++ if ctx.numPasswordCbs != testCase.expectedPasswordCbs { ++ t.Fatalf("passwordCallback was called %d times, expected %d times", ctx.numPasswordCbs, testCase.expectedPasswordCbs) ++ } ++ ++ if ctx.numKbdIntCbs != testCase.expectedKbdIntCbs { ++ t.Fatalf("keyboardInteractiveCallback was called %d times, expected %d times", ctx.numKbdIntCbs, testCase.expectedKbdIntCbs) ++ } ++ }) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/session_test.go b/ms_mod/golang.org/x/crypto/ssh/test/session_test.go +new file mode 100644 +index 00000000000000..4745ed9dbb1a92 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/session_test.go +@@ -0,0 +1,455 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !windows && !js && !wasip1 ++// +build !windows,!js,!wasip1 ++ ++package test ++ ++// Session functional tests. ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "io" ++ "path/filepath" ++ "regexp" ++ "runtime" ++ "strings" ++ "testing" ++ ++ "golang.org/x/crypto/ssh" ++) ++ ++func TestRunCommandSuccess(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ defer session.Close() ++ err = session.Run("true") ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++} ++ ++func TestHostKeyCheck(t *testing.T) { ++ server := newServer(t) ++ ++ conf := clientConfig() ++ hostDB := hostKeyDB() ++ conf.HostKeyCallback = hostDB.Check ++ ++ // change the keys. ++ hostDB.keys[ssh.KeyAlgoRSA][25]++ ++ hostDB.keys[ssh.KeyAlgoDSA][25]++ ++ hostDB.keys[ssh.KeyAlgoECDSA256][25]++ ++ ++ conn, err := server.TryDial(conf) ++ if err == nil { ++ conn.Close() ++ t.Fatalf("dial should have failed.") ++ } else if !strings.Contains(err.Error(), "host key mismatch") { ++ t.Fatalf("'host key mismatch' not found in %v", err) ++ } ++} ++ ++func TestRunCommandStdin(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ defer session.Close() ++ ++ r, w := io.Pipe() ++ defer r.Close() ++ defer w.Close() ++ session.Stdin = r ++ ++ err = session.Run("true") ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++} ++ ++func TestRunCommandStdinError(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ defer session.Close() ++ ++ r, w := io.Pipe() ++ defer r.Close() ++ session.Stdin = r ++ pipeErr := errors.New("closing write end of pipe") ++ w.CloseWithError(pipeErr) ++ ++ err = session.Run("true") ++ if err != pipeErr { ++ t.Fatalf("expected %v, found %v", pipeErr, err) ++ } ++} ++ ++func TestRunCommandFailed(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ defer session.Close() ++ err = session.Run(`bash -c "kill -9 $$"`) ++ if err == nil { ++ t.Fatalf("session succeeded: %v", err) ++ } ++} ++ ++func TestRunCommandWeClosed(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ err = session.Shell() ++ if err != nil { ++ t.Fatalf("shell failed: %v", err) ++ } ++ err = session.Close() ++ if err != nil { ++ t.Fatalf("shell failed: %v", err) ++ } ++} ++ ++func TestFuncLargeRead(t *testing.T) { ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("unable to create new session: %s", err) ++ } ++ ++ stdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Fatalf("unable to acquire stdout pipe: %s", err) ++ } ++ ++ err = session.Start("dd if=/dev/urandom bs=2048 count=1024") ++ if err != nil { ++ t.Fatalf("unable to execute remote command: %s", err) ++ } ++ ++ buf := new(bytes.Buffer) ++ n, err := io.Copy(buf, stdout) ++ if err != nil { ++ t.Fatalf("error reading from remote stdout: %s", err) ++ } ++ ++ if n != 2048*1024 { ++ t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n) ++ } ++} ++ ++func TestKeyChange(t *testing.T) { ++ server := newServer(t) ++ conf := clientConfig() ++ hostDB := hostKeyDB() ++ conf.HostKeyCallback = hostDB.Check ++ conf.RekeyThreshold = 1024 ++ conn := server.Dial(conf) ++ defer conn.Close() ++ ++ for i := 0; i < 4; i++ { ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("unable to create new session: %s", err) ++ } ++ ++ stdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Fatalf("unable to acquire stdout pipe: %s", err) ++ } ++ ++ err = session.Start("dd if=/dev/urandom bs=1024 count=1") ++ if err != nil { ++ t.Fatalf("unable to execute remote command: %s", err) ++ } ++ buf := new(bytes.Buffer) ++ n, err := io.Copy(buf, stdout) ++ if err != nil { ++ t.Fatalf("error reading from remote stdout: %s", err) ++ } ++ ++ want := int64(1024) ++ if n != want { ++ t.Fatalf("Expected %d bytes but read only %d from remote command", want, n) ++ } ++ } ++ ++ if changes := hostDB.checkCount; changes < 4 { ++ t.Errorf("got %d key changes, want 4", changes) ++ } ++} ++ ++func TestValidTerminalMode(t *testing.T) { ++ if runtime.GOOS == "aix" { ++ // On AIX, sshd cannot acquire /dev/pts/* if launched as ++ // a non-root user. ++ t.Skipf("skipping on %s", runtime.GOOS) ++ } ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ defer session.Close() ++ ++ stdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Fatalf("unable to acquire stdout pipe: %s", err) ++ } ++ ++ stdin, err := session.StdinPipe() ++ if err != nil { ++ t.Fatalf("unable to acquire stdin pipe: %s", err) ++ } ++ ++ tm := ssh.TerminalModes{ssh.ECHO: 0} ++ if err = session.RequestPty("xterm", 80, 40, tm); err != nil { ++ t.Fatalf("req-pty failed: %s", err) ++ } ++ ++ err = session.Shell() ++ if err != nil { ++ t.Fatalf("session failed: %s", err) ++ } ++ ++ if _, err := io.WriteString(stdin, "echo && echo SHELL $SHELL && stty -a && exit\n"); err != nil { ++ t.Fatal(err) ++ } ++ ++ buf := new(strings.Builder) ++ if _, err := io.Copy(buf, stdout); err != nil { ++ t.Fatalf("reading failed: %s", err) ++ } ++ ++ if testing.Verbose() { ++ t.Logf("echo && echo SHELL $SHELL && stty -a && exit:\n%s", buf) ++ } ++ ++ shellLine := regexp.MustCompile("(?m)^SHELL (.*)$").FindStringSubmatch(buf.String()) ++ if len(shellLine) != 2 { ++ t.Fatalf("missing output from echo SHELL $SHELL") ++ } ++ switch shell := filepath.Base(strings.TrimSpace(shellLine[1])); shell { ++ case "sh", "bash": ++ default: ++ t.Skipf("skipping test on non-Bourne shell %q", shell) ++ } ++ ++ if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { ++ t.Fatal("terminal mode failure: expected -echo in stty output") ++ } ++} ++ ++func TestWindowChange(t *testing.T) { ++ if runtime.GOOS == "aix" { ++ // On AIX, sshd cannot acquire /dev/pts/* if launched as ++ // a non-root user. ++ t.Skipf("skipping on %s", runtime.GOOS) ++ } ++ server := newServer(t) ++ conn := server.Dial(clientConfig()) ++ defer conn.Close() ++ ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("session failed: %v", err) ++ } ++ defer session.Close() ++ ++ stdout, err := session.StdoutPipe() ++ if err != nil { ++ t.Fatalf("unable to acquire stdout pipe: %s", err) ++ } ++ ++ stdin, err := session.StdinPipe() ++ if err != nil { ++ t.Fatalf("unable to acquire stdin pipe: %s", err) ++ } ++ ++ tm := ssh.TerminalModes{ssh.ECHO: 0} ++ if err = session.RequestPty("xterm", 80, 40, tm); err != nil { ++ t.Fatalf("req-pty failed: %s", err) ++ } ++ ++ if err := session.WindowChange(100, 100); err != nil { ++ t.Fatalf("window-change failed: %s", err) ++ } ++ ++ err = session.Shell() ++ if err != nil { ++ t.Fatalf("session failed: %s", err) ++ } ++ ++ stdin.Write([]byte("stty size && exit\n")) ++ ++ var buf bytes.Buffer ++ if _, err := io.Copy(&buf, stdout); err != nil { ++ t.Fatalf("reading failed: %s", err) ++ } ++ ++ if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") { ++ t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput) ++ } ++} ++ ++func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { ++ server := newServer(t) ++ conf := clientConfig() ++ conf.Ciphers = []string{cipher} ++ // Don't fail if sshd doesn't have the cipher. ++ conf.Ciphers = append(conf.Ciphers, cipherOrder...) ++ conn, err := server.TryDial(conf) ++ if err != nil { ++ t.Fatalf("TryDial: %v", err) ++ } ++ defer conn.Close() ++ ++ numBytes := 4096 ++ ++ // Exercise sending data to the server ++ if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { ++ t.Fatalf("SendRequest: %v", err) ++ } ++ ++ // Exercise receiving data from the server ++ session, err := conn.NewSession() ++ if err != nil { ++ t.Fatalf("NewSession: %v", err) ++ } ++ ++ out, err := session.Output(fmt.Sprintf("dd if=/dev/zero bs=%d count=1", numBytes)) ++ if err != nil { ++ t.Fatalf("Output: %v", err) ++ } ++ ++ if len(out) != numBytes { ++ t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) ++ } ++} ++ ++var deprecatedCiphers = []string{ ++ "aes128-cbc", "3des-cbc", ++ "arcfour128", "arcfour256", ++} ++ ++func TestCiphers(t *testing.T) { ++ var config ssh.Config ++ config.SetDefaults() ++ cipherOrder := append(config.Ciphers, deprecatedCiphers...) ++ ++ for _, ciph := range cipherOrder { ++ t.Run(ciph, func(t *testing.T) { ++ testOneCipher(t, ciph, cipherOrder) ++ }) ++ } ++} ++ ++func TestMACs(t *testing.T) { ++ var config ssh.Config ++ config.SetDefaults() ++ macOrder := config.MACs ++ ++ for _, mac := range macOrder { ++ t.Run(mac, func(t *testing.T) { ++ server := newServer(t) ++ conf := clientConfig() ++ conf.MACs = []string{mac} ++ // Don't fail if sshd doesn't have the MAC. ++ conf.MACs = append(conf.MACs, macOrder...) ++ if conn, err := server.TryDial(conf); err == nil { ++ conn.Close() ++ } else { ++ t.Fatalf("failed for MAC %q", mac) ++ } ++ }) ++ } ++} ++ ++func TestKeyExchanges(t *testing.T) { ++ var config ssh.Config ++ config.SetDefaults() ++ kexOrder := config.KeyExchanges ++ // Based on the discussion in #17230, the key exchange algorithms ++ // diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256 ++ // are not included in the default list of supported kex so we have to add them ++ // here manually. ++ kexOrder = append(kexOrder, "diffie-hellman-group-exchange-sha1", "diffie-hellman-group-exchange-sha256") ++ // The key exchange algorithms diffie-hellman-group16-sha512 is disabled by ++ // default so we add it here manually. ++ kexOrder = append(kexOrder, "diffie-hellman-group16-sha512") ++ for _, kex := range kexOrder { ++ t.Run(kex, func(t *testing.T) { ++ server := newServer(t) ++ conf := clientConfig() ++ // Don't fail if sshd doesn't have the kex. ++ conf.KeyExchanges = append([]string{kex}, kexOrder...) ++ conn, err := server.TryDial(conf) ++ if err == nil { ++ conn.Close() ++ } else { ++ t.Errorf("failed for kex %q", kex) ++ } ++ }) ++ } ++} ++ ++func TestClientAuthAlgorithms(t *testing.T) { ++ for _, key := range []string{ ++ "rsa", ++ "dsa", ++ "ecdsa", ++ "ed25519", ++ } { ++ t.Run(key, func(t *testing.T) { ++ server := newServer(t) ++ conf := clientConfig() ++ conf.SetDefaults() ++ conf.Auth = []ssh.AuthMethod{ ++ ssh.PublicKeys(testSigners[key]), ++ } ++ ++ conn, err := server.TryDial(conf) ++ if err == nil { ++ conn.Close() ++ } else { ++ t.Errorf("failed for key %q", key) ++ } ++ }) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c b/ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c +new file mode 100644 +index 00000000000000..2794a563a41726 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c +@@ -0,0 +1,173 @@ ++// Copyright 2017 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// sshd_test_pw.c ++// Wrapper to inject test password data for sshd PAM authentication ++// ++// This wrapper implements custom versions of getpwnam, getpwnam_r, ++// getspnam and getspnam_r. These functions first call their real ++// libc versions, then check if the requested user matches test user ++// specified in env variable TEST_USER and if so replace the password ++// with crypted() value of TEST_PASSWD env variable. ++// ++// Compile: ++// gcc -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c ++// ++// Compile with debug: ++// gcc -DVERBOSE -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c ++// ++// Run sshd: ++// LD_PRELOAD="sshd_test_pw.so" TEST_USER="..." TEST_PASSWD="..." sshd ... ++ ++// +build ignore ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef VERBOSE ++#define DEBUG(X...) fprintf(stderr, X) ++#else ++#define DEBUG(X...) while (0) { } ++#endif ++ ++/* crypt() password */ ++static char * ++pwhash(char *passwd) { ++ return strdup(crypt(passwd, "$6$")); ++} ++ ++/* Pointers to real functions in libc */ ++static struct passwd * (*real_getpwnam)(const char *) = NULL; ++static int (*real_getpwnam_r)(const char *, struct passwd *, char *, size_t, struct passwd **) = NULL; ++static struct spwd * (*real_getspnam)(const char *) = NULL; ++static int (*real_getspnam_r)(const char *, struct spwd *, char *, size_t, struct spwd **) = NULL; ++ ++/* Cached test user and test password */ ++static char *test_user = NULL; ++static char *test_passwd_hash = NULL; ++ ++static void ++init(void) { ++ /* Fetch real libc function pointers */ ++ real_getpwnam = dlsym(RTLD_NEXT, "getpwnam"); ++ real_getpwnam_r = dlsym(RTLD_NEXT, "getpwnam_r"); ++ real_getspnam = dlsym(RTLD_NEXT, "getspnam"); ++ real_getspnam_r = dlsym(RTLD_NEXT, "getspnam_r"); ++ ++ /* abort if env variables are not defined */ ++ if (getenv("TEST_USER") == NULL || getenv("TEST_PASSWD") == NULL) { ++ fprintf(stderr, "env variables TEST_USER and TEST_PASSWD are missing\n"); ++ abort(); ++ } ++ ++ /* Fetch test user and test password from env */ ++ test_user = strdup(getenv("TEST_USER")); ++ test_passwd_hash = pwhash(getenv("TEST_PASSWD")); ++ ++ DEBUG("sshd_test_pw init():\n"); ++ DEBUG("\treal_getpwnam: %p\n", real_getpwnam); ++ DEBUG("\treal_getpwnam_r: %p\n", real_getpwnam_r); ++ DEBUG("\treal_getspnam: %p\n", real_getspnam); ++ DEBUG("\treal_getspnam_r: %p\n", real_getspnam_r); ++ DEBUG("\tTEST_USER: '%s'\n", test_user); ++ DEBUG("\tTEST_PASSWD: '%s'\n", getenv("TEST_PASSWD")); ++ DEBUG("\tTEST_PASSWD_HASH: '%s'\n", test_passwd_hash); ++} ++ ++static int ++is_test_user(const char *name) { ++ if (test_user != NULL && strcmp(test_user, name) == 0) ++ return 1; ++ return 0; ++} ++ ++/* getpwnam */ ++ ++struct passwd * ++getpwnam(const char *name) { ++ struct passwd *pw; ++ ++ DEBUG("sshd_test_pw getpwnam(%s)\n", name); ++ ++ if (real_getpwnam == NULL) ++ init(); ++ if ((pw = real_getpwnam(name)) == NULL) ++ return NULL; ++ ++ if (is_test_user(name)) ++ pw->pw_passwd = strdup(test_passwd_hash); ++ ++ return pw; ++} ++ ++/* getpwnam_r */ ++ ++int ++getpwnam_r(const char *name, ++ struct passwd *pwd, ++ char *buf, ++ size_t buflen, ++ struct passwd **result) { ++ int r; ++ ++ DEBUG("sshd_test_pw getpwnam_r(%s)\n", name); ++ ++ if (real_getpwnam_r == NULL) ++ init(); ++ if ((r = real_getpwnam_r(name, pwd, buf, buflen, result)) != 0 || *result == NULL) ++ return r; ++ ++ if (is_test_user(name)) ++ pwd->pw_passwd = strdup(test_passwd_hash); ++ ++ return 0; ++} ++ ++/* getspnam */ ++ ++struct spwd * ++getspnam(const char *name) { ++ struct spwd *sp; ++ ++ DEBUG("sshd_test_pw getspnam(%s)\n", name); ++ ++ if (real_getspnam == NULL) ++ init(); ++ if ((sp = real_getspnam(name)) == NULL) ++ return NULL; ++ ++ if (is_test_user(name)) ++ sp->sp_pwdp = strdup(test_passwd_hash); ++ ++ return sp; ++} ++ ++/* getspnam_r */ ++ ++int ++getspnam_r(const char *name, ++ struct spwd *spbuf, ++ char *buf, ++ size_t buflen, ++ struct spwd **spbufp) { ++ int r; ++ ++ DEBUG("sshd_test_pw getspnam_r(%s)\n", name); ++ ++ if (real_getspnam_r == NULL) ++ init(); ++ if ((r = real_getspnam_r(name, spbuf, buf, buflen, spbufp)) != 0) ++ return r; ++ ++ if (is_test_user(name)) ++ spbuf->sp_pwdp = strdup(test_passwd_hash); ++ ++ return r; ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go +new file mode 100644 +index 00000000000000..f3f55db1288e45 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go +@@ -0,0 +1,364 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 || solaris ++// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9 solaris ++ ++package test ++ ++// functional test harness for unix. ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/base64" ++ "fmt" ++ "log" ++ "net" ++ "os" ++ "os/exec" ++ "os/user" ++ "path/filepath" ++ "testing" ++ "text/template" ++ ++ "golang.org/x/crypto/internal/testenv" ++ "golang.org/x/crypto/ssh" ++ "golang.org/x/crypto/ssh/testdata" ++) ++ ++const ( ++ defaultSshdConfig = ` ++Protocol 2 ++Banner {{.Dir}}/banner ++HostKey {{.Dir}}/id_rsa ++HostKey {{.Dir}}/id_dsa ++HostKey {{.Dir}}/id_ecdsa ++HostCertificate {{.Dir}}/id_rsa-sha2-512-cert.pub ++Pidfile {{.Dir}}/sshd.pid ++#UsePrivilegeSeparation no ++KeyRegenerationInterval 3600 ++ServerKeyBits 768 ++SyslogFacility AUTH ++LogLevel DEBUG2 ++LoginGraceTime 120 ++PermitRootLogin no ++StrictModes no ++RSAAuthentication yes ++PubkeyAuthentication yes ++AuthorizedKeysFile {{.Dir}}/authorized_keys ++TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub ++IgnoreRhosts yes ++RhostsRSAAuthentication no ++HostbasedAuthentication no ++PubkeyAcceptedKeyTypes=* ++` ++ multiAuthSshdConfigTail = ` ++UsePAM yes ++PasswordAuthentication yes ++ChallengeResponseAuthentication yes ++AuthenticationMethods {{.AuthMethods}} ++` ++) ++ ++var configTmpl = map[string]*template.Template{ ++ "default": template.Must(template.New("").Parse(defaultSshdConfig)), ++ "MultiAuth": template.Must(template.New("").Parse(defaultSshdConfig + multiAuthSshdConfigTail))} ++ ++type server struct { ++ t *testing.T ++ configfile string ++ ++ testUser string // test username for sshd ++ testPasswd string // test password for sshd ++ sshdTestPwSo string // dynamic library to inject a custom password into sshd ++ ++ lastDialConn net.Conn ++} ++ ++func username() string { ++ var username string ++ if user, err := user.Current(); err == nil { ++ username = user.Username ++ } else { ++ // user.Current() currently requires cgo. If an error is ++ // returned attempt to get the username from the environment. ++ log.Printf("user.Current: %v; falling back on $USER", err) ++ username = os.Getenv("USER") ++ } ++ if username == "" { ++ panic("Unable to get username") ++ } ++ return username ++} ++ ++type storedHostKey struct { ++ // keys map from an algorithm string to binary key data. ++ keys map[string][]byte ++ ++ // checkCount counts the Check calls. Used for testing ++ // rekeying. ++ checkCount int ++} ++ ++func (k *storedHostKey) Add(key ssh.PublicKey) { ++ if k.keys == nil { ++ k.keys = map[string][]byte{} ++ } ++ k.keys[key.Type()] = key.Marshal() ++} ++ ++func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { ++ k.checkCount++ ++ algo := key.Type() ++ ++ if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { ++ return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) ++ } ++ return nil ++} ++ ++func hostKeyDB() *storedHostKey { ++ keyChecker := &storedHostKey{} ++ keyChecker.Add(testPublicKeys["ecdsa"]) ++ keyChecker.Add(testPublicKeys["rsa"]) ++ keyChecker.Add(testPublicKeys["dsa"]) ++ return keyChecker ++} ++ ++func clientConfig() *ssh.ClientConfig { ++ config := &ssh.ClientConfig{ ++ User: username(), ++ Auth: []ssh.AuthMethod{ ++ ssh.PublicKeys(testSigners["user"]), ++ }, ++ HostKeyCallback: hostKeyDB().Check, ++ HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker ++ ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, ++ ssh.KeyAlgoRSA, ssh.KeyAlgoDSA, ++ ssh.KeyAlgoED25519, ++ }, ++ } ++ return config ++} ++ ++// unixConnection creates two halves of a connected net.UnixConn. It ++// is used for connecting the Go SSH client with sshd without opening ++// ports. ++func unixConnection() (*net.UnixConn, *net.UnixConn, error) { ++ dir, err := os.MkdirTemp("", "unixConnection") ++ if err != nil { ++ return nil, nil, err ++ } ++ defer os.Remove(dir) ++ ++ addr := filepath.Join(dir, "ssh") ++ listener, err := net.Listen("unix", addr) ++ if err != nil { ++ return nil, nil, err ++ } ++ defer listener.Close() ++ c1, err := net.Dial("unix", addr) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ c2, err := listener.Accept() ++ if err != nil { ++ c1.Close() ++ return nil, nil, err ++ } ++ ++ return c1.(*net.UnixConn), c2.(*net.UnixConn), nil ++} ++ ++func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { ++ return s.TryDialWithAddr(config, "") ++} ++ ++// addr is the user specified host:port. While we don't actually dial it, ++// we need to know this for host key matching ++func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) { ++ sshd, err := exec.LookPath("sshd") ++ if err != nil { ++ s.t.Skipf("skipping test: %v", err) ++ } ++ ++ c1, c2, err := unixConnection() ++ if err != nil { ++ s.t.Fatalf("unixConnection: %v", err) ++ } ++ ++ cmd := testenv.Command(s.t, sshd, "-f", s.configfile, "-i", "-e") ++ f, err := c2.File() ++ if err != nil { ++ s.t.Fatalf("UnixConn.File: %v", err) ++ } ++ defer f.Close() ++ cmd.Stdin = f ++ cmd.Stdout = f ++ cmd.Stderr = new(bytes.Buffer) ++ ++ if s.sshdTestPwSo != "" { ++ if s.testUser == "" { ++ s.t.Fatal("user missing from sshd_test_pw.so config") ++ } ++ if s.testPasswd == "" { ++ s.t.Fatal("password missing from sshd_test_pw.so config") ++ } ++ cmd.Env = append(os.Environ(), ++ fmt.Sprintf("LD_PRELOAD=%s", s.sshdTestPwSo), ++ fmt.Sprintf("TEST_USER=%s", s.testUser), ++ fmt.Sprintf("TEST_PASSWD=%s", s.testPasswd)) ++ } ++ ++ if err := cmd.Start(); err != nil { ++ s.t.Fatalf("s.cmd.Start: %v", err) ++ } ++ s.lastDialConn = c1 ++ s.t.Cleanup(func() { ++ // Don't check for errors; if it fails it's most ++ // likely "os: process already finished", and we don't ++ // care about that. Use os.Interrupt, so child ++ // processes are killed too. ++ cmd.Process.Signal(os.Interrupt) ++ cmd.Wait() ++ if s.t.Failed() { ++ // log any output from sshd process ++ s.t.Logf("sshd:\n%s", cmd.Stderr) ++ } ++ }) ++ ++ conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config) ++ if err != nil { ++ return nil, err ++ } ++ return ssh.NewClient(conn, chans, reqs), nil ++} ++ ++func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { ++ conn, err := s.TryDial(config) ++ if err != nil { ++ s.t.Fatalf("ssh.Client: %v", err) ++ } ++ return conn ++} ++ ++func writeFile(path string, contents []byte) { ++ f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) ++ if err != nil { ++ panic(err) ++ } ++ defer f.Close() ++ if _, err := f.Write(contents); err != nil { ++ panic(err) ++ } ++} ++ ++// generate random password ++func randomPassword() (string, error) { ++ b := make([]byte, 12) ++ _, err := rand.Read(b) ++ if err != nil { ++ return "", err ++ } ++ return base64.RawURLEncoding.EncodeToString(b), nil ++} ++ ++// setTestPassword is used for setting user and password data for sshd_test_pw.so ++// This function also checks that ./sshd_test_pw.so exists and if not calls s.t.Skip() ++func (s *server) setTestPassword(user, passwd string) error { ++ wd, _ := os.Getwd() ++ wrapper := filepath.Join(wd, "sshd_test_pw.so") ++ if _, err := os.Stat(wrapper); err != nil { ++ s.t.Skip(fmt.Errorf("sshd_test_pw.so is not available")) ++ return err ++ } ++ ++ s.sshdTestPwSo = wrapper ++ s.testUser = user ++ s.testPasswd = passwd ++ return nil ++} ++ ++// newServer returns a new mock ssh server. ++func newServer(t *testing.T) *server { ++ return newServerForConfig(t, "default", map[string]string{}) ++} ++ ++// newServerForConfig returns a new mock ssh server. ++func newServerForConfig(t *testing.T, config string, configVars map[string]string) *server { ++ if testing.Short() { ++ t.Skip("skipping test due to -short") ++ } ++ u, err := user.Current() ++ if err != nil { ++ t.Fatalf("user.Current: %v", err) ++ } ++ uname := u.Name ++ if uname == "" { ++ // Check the value of u.Username as u.Name ++ // can be "" on some OSes like AIX. ++ uname = u.Username ++ } ++ if uname == "root" { ++ t.Skip("skipping test because current user is root") ++ } ++ dir, err := os.MkdirTemp("", "sshtest") ++ if err != nil { ++ t.Fatal(err) ++ } ++ f, err := os.Create(filepath.Join(dir, "sshd_config")) ++ if err != nil { ++ t.Fatal(err) ++ } ++ if _, ok := configTmpl[config]; ok == false { ++ t.Fatal(fmt.Errorf("Invalid server config '%s'", config)) ++ } ++ configVars["Dir"] = dir ++ err = configTmpl[config].Execute(f, configVars) ++ if err != nil { ++ t.Fatal(err) ++ } ++ f.Close() ++ ++ writeFile(filepath.Join(dir, "banner"), []byte("Server Banner")) ++ ++ for k, v := range testdata.PEMBytes { ++ filename := "id_" + k ++ writeFile(filepath.Join(dir, filename), v) ++ writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) ++ } ++ ++ for k, v := range testdata.SSHCertificates { ++ filename := "id_" + k + "-cert.pub" ++ writeFile(filepath.Join(dir, filename), v) ++ } ++ ++ var authkeys bytes.Buffer ++ for k := range testdata.PEMBytes { ++ authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k])) ++ } ++ writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes()) ++ t.Cleanup(func() { ++ if err := os.RemoveAll(dir); err != nil { ++ t.Error(err) ++ } ++ }) ++ ++ return &server{ ++ t: t, ++ configfile: f.Name(), ++ } ++} ++ ++func newTempSocket(t *testing.T) (string, func()) { ++ dir, err := os.MkdirTemp("", "socket") ++ if err != nil { ++ t.Fatal(err) ++ } ++ deferFunc := func() { os.RemoveAll(dir) } ++ addr := filepath.Join(dir, "sock") ++ return addr, deferFunc ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go b/ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go +new file mode 100644 +index 00000000000000..a053f67eabed4c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go +@@ -0,0 +1,64 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: ++// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three ++// instances. ++ ++package test ++ ++import ( ++ "crypto/rand" ++ "fmt" ++ ++ "golang.org/x/crypto/ssh" ++ "golang.org/x/crypto/ssh/testdata" ++) ++ ++var ( ++ testPrivateKeys map[string]interface{} ++ testSigners map[string]ssh.Signer ++ testPublicKeys map[string]ssh.PublicKey ++) ++ ++func init() { ++ var err error ++ ++ n := len(testdata.PEMBytes) ++ testPrivateKeys = make(map[string]interface{}, n) ++ testSigners = make(map[string]ssh.Signer, n) ++ testPublicKeys = make(map[string]ssh.PublicKey, n) ++ for t, k := range testdata.PEMBytes { ++ testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) ++ } ++ testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) ++ } ++ testPublicKeys[t] = testSigners[t].PublicKey() ++ } ++ ++ // Create a cert and sign it for use in tests. ++ testCert := &ssh.Certificate{ ++ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ++ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage ++ ValidAfter: 0, // unix epoch ++ ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. ++ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ++ Key: testPublicKeys["ecdsa"], ++ SignatureKey: testPublicKeys["rsa"], ++ Permissions: ssh.Permissions{ ++ CriticalOptions: map[string]string{}, ++ Extensions: map[string]string{}, ++ }, ++ } ++ testCert.SignCert(rand.Reader, testSigners["rsa"]) ++ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] ++ testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/testdata/doc.go b/ms_mod/golang.org/x/crypto/ssh/testdata/doc.go +new file mode 100644 +index 00000000000000..fcae47ca6878b4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/testdata/doc.go +@@ -0,0 +1,8 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// This package contains test data shared between the various subpackages of ++// the golang.org/x/crypto/ssh package. Under no circumstance should ++// this data be used for production code. ++package testdata // import "golang.org/x/crypto/ssh/testdata" +diff --git a/ms_mod/golang.org/x/crypto/ssh/testdata/keys.go b/ms_mod/golang.org/x/crypto/ssh/testdata/keys.go +new file mode 100644 +index 00000000000000..ad95a81929b829 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/testdata/keys.go +@@ -0,0 +1,314 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package testdata ++ ++var PEMBytes = map[string][]byte{ ++ "dsa": []byte(`-----BEGIN DSA PRIVATE KEY----- ++MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB ++lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3 ++EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD ++nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV ++2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r ++juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr ++FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz ++DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj ++nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY ++Fmsr0W6fHB9nhS4/UXM8 ++-----END DSA PRIVATE KEY----- ++`), ++ "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY----- ++MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 ++AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ ++6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== ++-----END EC PRIVATE KEY----- ++`), ++ "ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY----- ++MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49 ++AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU ++qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg== ++-----END EC PRIVATE KEY----- ++`), ++ "ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY----- ++MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS ++qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43 ++VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz ++hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI= ++-----END EC PRIVATE KEY----- ++`), ++ "ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY----- ++MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF ++iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV ++UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+ ++uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn ++FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ== ++-----END EC PRIVATE KEY----- ++`), ++ "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- ++MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2 ++a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8 ++Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB ++AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R ++38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT ++Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq ++2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9 ++6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR ++fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu ++X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa ++NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM ++z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 ++KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= ++-----END RSA PRIVATE KEY----- ++`), ++ "pkcs8": []byte(`-----BEGIN PRIVATE KEY----- ++MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCitzS2KiRQTccf ++VApb0mbPpo1lt29JjeLBYAehXHWfQ+w8sXpd8e04n/020spx1R94yg+v0NjXyh2R ++NFXNBYdhNei33VJxUeKNlExaecvW2yxfuZqka+ZxT1aI8zrAsjh3Rwc6wayAJS4R ++wZuzlDv4jZitWqwD+mb/22Zwq/WSs4YX5dUHDklfdWSVnoBfue8K/00n8f5yMTdJ ++vFF0qAJwf9spPEHla0lYcozJk64CO5lRkqfLor4UnsXXOiA7aRIoaUSKa+rlhiqt ++1EMGYiBjblPt4SwMelGGU2UfywPb4d85gpQ/s8SBARbpPxNVs2IbHDMwj70P3uZc ++74M3c4VJAgMBAAECggEAFIzY3mziGzZHgMBncoNXMsCRORh6uKpvygZr0EhSHqRA ++cMXlc3n7gNxL6aGjqc7F48Z5RrY0vMQtCcq3T2Z0W6WoV5hfMiqqV0E0h3S8ds1F ++hG13h26NMyBXCILXl8Cqev4Afr45IBISCHIQTRTaoiCX+MTr1rDIU2YNQQumvzkz ++fMw2XiFTFTgxAtJUAgKoTqLtm7/T+az7TKw+Hesgbx7yaJoMh9DWGBh4Y61DnIDA ++fcxJboAfxxnFiXvdBVmzo72pCsRXrWOsjW6WxQmCKuXHvyB1FZTmMaEFNCGSJDa6 ++U+OCzA3m65loAZAE7ffFHhYgssz/h9TBaOjKO0BX1QKBgQDZiCBvu+bFh9pEodcS ++VxaI+ATlsYcmGdLtnZw5pxuEdr60iNWhpEcV6lGkbdiv5aL43QaGFDLagqeHI77b +++ITFbPPdCiYNaqlk6wyiXv4pdN7V683EDmGWSQlPeC9IhUilt2c+fChK2EB/XlkO ++q8c3Vk1MsC6JOxDXNgJxylNpswKBgQC/fYBTb9iD+uM2n3SzJlct/ZlPaONKnNDR ++pbTOdxBFHsu2VkfY858tfnEPkmSRX0yKmjHni6e8/qIzfzLwWBY4NmxhNZE5v+qJ ++qZF26ULFdrZB4oWXAOliy/1S473OpQnp2MZp2asd0LPcg/BNaMuQrz44hxHb76R7 ++qWD0ebIfEwKBgQCRCIiP1pjbVGN7ZOgPS080DSC+wClahtcyI+ZYLglTvRQTLDQ7 ++LFtUykCav748MIADKuJBnM/3DiuCF5wV71EejDDfS/fo9BdyuKBY1brhixFTUX+E ++Ww5Hc/SoLnpgALVZ/7jvWTpIBHykLxRziqYtR/YLzl+IkX/97P2ePoZ0rwKBgHNC ++/7M5Z4JJyepfIMeVFHTCaT27TNTkf20x6Rs937U7TDN8y9JzEiU4LqXI4HAAhPoI ++xnExRs4kF04YCnlRDE7Zs3Lv43J3ap1iTATfcymYwyv1RaQXEGQ/lUQHgYCZJtZz ++fTrJoo5XyWu6nzJ5Gc8FLNaptr5ECSXGVm3Rsr2xAoGBAJWqEEQS/ejhO05QcPqh ++y4cUdLr0269ILVsvic4Ot6zgfPIntXAK6IsHGKcg57kYm6W9k1CmmlA4ENGryJnR ++vxyyqA9eyTFc1CQNuc2frKFA9It49JzjXahKc0aDHEHmTR787Tmk1LbuT0/gm9kA ++L4INU6g+WqF0fatJxd+IJPrp ++-----END PRIVATE KEY----- ++`), ++ "ed25519": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW ++QyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8DvvwAAAJhAFfkOQBX5 ++DgAAAAtzc2gtZWQyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8Dvvw ++AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb ++HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg== ++-----END OPENSSH PRIVATE KEY----- ++`), ++ "rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn ++NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l ++oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz ++a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH ++c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE ++uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+ ++yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4 ++IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE ++pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk ++kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk ++pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju ++X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB ++ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ ++wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID ++-----END OPENSSH PRIVATE KEY-----`), ++ "p256-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS ++1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSN5Ld/DFy8LJK0yrWg+Ryhq4/ifHry ++QyCQeT4UXSB+UGdRct7kWA0hARbTaSCh+8U/Gs5O+IkDNoTKVsgxKUMQAAAAsO3C7nPtwu ++5zAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI3kt38MXLwskrTK ++taD5HKGrj+J8evJDIJB5PhRdIH5QZ1Fy3uRYDSEBFtNpIKH7xT8azk74iQM2hMpWyDEpQx ++AAAAAhAIHB48R+goZaiXndfYTrwk4BT1+MeLPC2/dwe0J5d1QDAAAAE21hcmlhbm9AZW5k ++b3IubG9jYWwBAgME ++-----END OPENSSH PRIVATE KEY-----`), ++ "p384-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS ++1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTZb2VzEPs2NN/i1qHddKTVfwoIq3Tf ++PeQ/kcWBvuCVJfIygvpm9MeusawEPuLSEXwiNDew+YHZ9xHIvFjCmZsLuEOzuh9t9KotwM ++57H+7N+RDFzhM2j8hAaOuT5XDLKfUAAADgn/Sny5/0p8sAAAATZWNkc2Etc2hhMi1uaXN0 ++cDM4NAAAAAhuaXN0cDM4NAAAAGEE2W9lcxD7NjTf4tah3XSk1X8KCKt03z3kP5HFgb7glS ++XyMoL6ZvTHrrGsBD7i0hF8IjQ3sPmB2fcRyLxYwpmbC7hDs7ofbfSqLcDOex/uzfkQxc4T ++No/IQGjrk+Vwyyn1AAAAMQDg0hwGKB/9Eq+e2FeTspi8QHW5xTD6prqsHDFx4cKk0ccgFV ++61dhFhD/8SEbYlHzEAAAATbWFyaWFub0BlbmRvci5sb2NhbAECAwQ= ++-----END OPENSSH PRIVATE KEY-----`), ++ "p521-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS ++1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBKzI3QSp1a2e1zMulZl1uFF1Y2Dnv ++LSIwEu837hOV1epYEgNveAhGNm57TuBqYtnZeVfd2pzaz7CKX6N4B33N1XABQ5Ngji7lF2 ++dUbmhNqJoMh43ioIsQNBaBenhmRpYP6f5k8P/7JZMIsLhkJk2hykb8maSZ+B3PYwPMNBdS ++vP+0sHQAAAEYIsr2CCLK9ggAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ ++AAAIUEASsyN0EqdWtntczLpWZdbhRdWNg57y0iMBLvN+4TldXqWBIDb3gIRjZue07gamLZ ++2XlX3dqc2s+wil+jeAd9zdVwAUOTYI4u5RdnVG5oTaiaDIeN4qCLEDQWgXp4ZkaWD+n+ZP ++D/+yWTCLC4ZCZNocpG/Jmkmfgdz2MDzDQXUrz/tLB0AAAAQgEdeH+im6iRcP/juTAoeSHo ++ExLtWhgL4JYqRwcOnzCKuLOPjEY/HSOuc+HRrbN9rbjsq+PcPHYe1NnkzXk0IW8hxQAAAB ++NtYXJpYW5vQGVuZG9yLmxvY2FsAQIDBAUGBw== ++-----END OPENSSH PRIVATE KEY-----`), ++ "user": []byte(`-----BEGIN EC PRIVATE KEY----- ++MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 ++AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD ++PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w== ++-----END EC PRIVATE KEY----- ++`), ++ "ca": []byte(`-----BEGIN RSA PRIVATE KEY----- ++MIIEpAIBAAKCAQEAvg9dQ9IRG59lYJb+GESfKWTch4yBpr7Ydw1jkK6vvtrx9jLo ++5hkA8X6+ElRPRqTAZSlN5cBm6YCAcQIOsmXDUn6Oj1lVPQAoOjTBTvsjM3NjGhvv ++52kHTY0nsMsBeY9q5DTtlzmlYkVUq2a6Htgf2mNi01dIw5fJ7uTTo8EbNf7O0i3u ++c9a8P19HaZl5NKiWN4EIZkfB2WdXYRJCVBsGgQj3dE/GrEmH9QINq1A+GkNvK96u ++vZm8H1jjmuqzHplWa7lFeXcx8FTVTbVb/iJrZ2Lc/JvIPitKZWhqbR59yrGjpwEp ++Id7bo4WhO5L3OB0fSIJYvfu+o4WYnt4f3UzecwIDAQABAoIBABRD9yHgKErVuC2Q ++bA+SYZY8VvdtF/X7q4EmQFORDNRA7EPgMc03JU6awRGbQ8i4kHs46EFzPoXvWcKz ++AXYsO6N0Myc900Tp22A5d9NAHATEbPC/wdje7hRq1KyZONMJY9BphFv3nZbY5apR ++Dc90JBFZP5RhXjTc3n9GjvqLAKfFEKVmPRCvqxCOZunw6XR+SgIQLJo36nsIsbhW ++QUXIVaCI6cXMN8bRPm8EITdBNZu06Fpu4ZHm6VaxlXN9smERCDkgBSNXNWHKxmmA ++c3Glo2DByUr2/JFBOrLEe9fkYgr24KNCQkHVcSaFxEcZvTggr7StjKISVHlCNEaB ++7Q+kPoECgYEA3zE9FmvFGoQCU4g4Nl3dpQHs6kaAW8vJlrmq3xsireIuaJoa2HMe ++wYdIvgCnK9DIjyxd5OWnE4jXtAEYPsyGD32B5rSLQrRO96lgb3f4bESCLUb3Bsn/ ++sdgeE3p1xZMA0B59htqCrvVgN9k8WxyevBxYl3/gSBm/p8OVH1RTW/ECgYEA2f9Z ++95OLj0KQHQtxQXf+I3VjhCw3LkLW39QZOXVI0QrCJfqqP7uxsJXH9NYX0l0GFTcR ++kRrlyoaSU1EGQosZh+n1MvplGBTkTSV47/bPsTzFpgK2NfEZuFm9RoWgltS+nYeH ++Y2k4mnAN3PhReCMwuprmJz8GRLsO3Cs2s2YylKMCgYEA2UX+uO/q7jgqZ5UJW+ue ++1H5+W0aMuFA3i7JtZEnvRaUVFqFGlwXin/WJ2+WY1++k/rPrJ+Rk9IBXtBUIvEGw ++FC5TIfsKQsJyyWgqx/jbbtJ2g4s8+W/1qfTAuqeRNOg5d2DnRDs90wJuS4//0JaY ++9HkHyVwkQyxFxhSA/AHEMJECgYA2MvyFR1O9bIk0D3I7GsA+xKLXa77Ua53MzIjw ++9i4CezBGDQpjCiFli/fI8am+jY5DnAtsDknvjoG24UAzLy5L0mk6IXMdB6SzYYut ++7ak5oahqW+Y9hxIj+XvLmtGQbphtxhJtLu35x75KoBpxSh6FZpmuTEccs31AVCYn ++eFM/DQKBgQDOPUwbLKqVi6ddFGgrV9MrWw+SWsDa43bPuyvYppMM3oqesvyaX1Dt ++qDvN7owaNxNM4OnfKcZr91z8YPVCFo4RbBif3DXRzjNNBlxEjHBtuMOikwvsmucN ++vIrbeEpjTiUMTEAr6PoTiVHjsfS8WAM6MDlF5M+2PNswDsBpa2yLgA== ++-----END RSA PRIVATE KEY----- ++`), ++} ++ ++var SSHCertificates = map[string][]byte{ ++ // The following are corresponding certificates for the private keys above, signed by the CA key ++ // Generated by the following commands: ++ // ++ // 1. Assumes "rsa" key above in file named "rsa", write out the public key to "rsa.pub": ++ // ssh-keygen -y -f rsa > rsa.pub ++ // ++ // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub": ++ // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub ++ "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com ++`), ++ "rsa-sha2-256": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOyK28gunJkM60qp4EbsYAjgbUsyjS8u742OLjipIgc0AAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMJ4AAAAAHBPBLwAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi0yNTYAAAEAbG4De/+QiqopPS3O1H7ySeEUCY56qmdgr02sFErnihdXPDaWXUXxacvJHaEtLrSTSaPL/3v3iKvjLWDOHaQ5c+cN9J7Tqzso7RQCXZD2nK9bwCUyBoiDyBCRe8w4DQEtfL5okpVzQsSAiojQ8hBohMOpy3gFfXrdm4PVC1ZKqlZh4fAc7ajieRq/Tpq2xOLdHwxkcgPNR83WVHva6K9/xjev/5n227/gkHo0qbGs8YYDOFXIEhENi+B23IzxdNVieWdyQpYpe0C2i95Jhyo0wJmaFY2ArruTS+D1jGQQpMPvAQRy26/A5hI83GLhpwyhrN/M8wCxzAhyPL6Ieuh5tQ== host.example.com ++`), ++ "rsa-sha2-512": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgFGv4IpXfs4L/Y0b3rmUdPFhWoUrVnXuPxXr6aHGs7wgAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMRYAAAAAHBPBp4AAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAnF4fVj6mm+UFeNCIf9AKJCv9WzymjjPvzzmaMWWkPWqoV0P0m5SiYfvbY9SbA73Blpv8SOr0DmpublF183kodREia4KyVuC8hLhSCV2Y16hy9MBegOZMepn80w+apj7Rn9QCz5OfEakDdztp6OWTBtqxnZFcTQ4XrgFkNWeWRElGdEvAVNn2WHwHi4EIdz0mdv48Imv5SPlOuW862ZdFG4Do1dUfDIiGsBofLlgcyIYlf+eNHul6sBeUkuwFxisMpI5DQzNp8PX1g/QJA2wzwT674PTqDXNttKjyh50Fdr4sXxm9Gz1+jVLoESvFNa55ERdSyAqNu4wTy11MZsWwSA== host.example.com ++`), ++} ++ ++var PEMEncryptedKeys = []struct { ++ Name string ++ EncryptionKey string ++ IncludesPublicKey bool ++ PEMBytes []byte ++}{ ++ 0: { ++ Name: "rsa-encrypted", ++ EncryptionKey: "r54-G0pher_t3st$", ++ PEMBytes: []byte(`-----BEGIN RSA PRIVATE KEY----- ++Proc-Type: 4,ENCRYPTED ++DEK-Info: AES-128-CBC,3E1714DE130BC5E81327F36564B05462 ++ ++MqW88sud4fnWk/Jk3fkjh7ydu51ZkHLN5qlQgA4SkAXORPPMj2XvqZOv1v2LOgUV ++dUevUn8PZK7a9zbZg4QShUSzwE5k6wdB7XKPyBgI39mJ79GBd2U4W3h6KT6jIdWA ++goQpluxkrzr2/X602IaxLEre97FT9mpKC6zxKCLvyFWVIP9n3OSFS47cTTXyFr+l ++7PdRhe60nn6jSBgUNk/Q1lAvEQ9fufdPwDYY93F1wyJ6lOr0F1+mzRrMbH67NyKs ++rG8J1Fa7cIIre7ueKIAXTIne7OAWqpU9UDgQatDtZTbvA7ciqGsSFgiwwW13N+Rr ++hN8MkODKs9cjtONxSKi05s206A3NDU6STtZ3KuPDjFE1gMJODotOuqSM+cxKfyFq ++wxpk/CHYCDdMAVBSwxb/vraOHamylL4uCHpJdBHypzf2HABt+lS8Su23uAmL87DR ++yvyCS/lmpuNTndef6qHPRkoW2EV3xqD3ovosGf7kgwGJUk2ZpCLVteqmYehKlZDK ++r/Jy+J26ooI2jIg9bjvD1PZq+Mv+2dQ1RlDrPG3PB+rEixw6vBaL9x3jatCd4ej7 ++XG7lb3qO9xFpLsx89tkEcvpGR+broSpUJ6Mu5LBCVmrvqHjvnDhrZVz1brMiQtU9 ++iMZbgXqDLXHd6ERWygk7OTU03u+l1gs+KGMfmS0h0ZYw6KGVLgMnsoxqd6cFSKNB ++8Ohk9ZTZGCiovlXBUepyu8wKat1k8YlHSfIHoRUJRhhcd7DrmojC+bcbMIZBU22T ++Pl2ftVRGtcQY23lYd0NNKfebF7ncjuLWQGy+vZW+7cgfI6wPIbfYfP6g7QAutk6W ++KQx0AoX5woZ6cNxtpIrymaVjSMRRBkKQrJKmRp3pC/lul5E5P2cueMs1fj4OHTbJ ++lAUv88ywr+R+mRgYQlFW/XQ653f6DT4t6+njfO9oBcPrQDASZel3LjXLpjjYG/N5 +++BWnVexuJX9ika8HJiFl55oqaKb+WknfNhk5cPY+x7SDV9ywQeMiDZpr0ffeYAEP ++LlwwiWRDYpO+uwXHSFF3+JjWwjhs8m8g99iFb7U93yKgBB12dCEPPa2ZeH9wUHMJ ++sreYhNuq6f4iWWSXpzN45inQqtTi8jrJhuNLTT543ErW7DtntBO2rWMhff3aiXbn ++Uy3qzZM1nPbuCGuBmP9L2dJ3Z5ifDWB4JmOyWY4swTZGt9AVmUxMIKdZpRONx8vz ++I9u9nbVPGZBcou50Pa0qTLbkWsSL94MNXrARBxzhHC9Zs6XNEtwN7mOuii7uMkVc ++adrxgknBH1J1N+NX/eTKzUwJuPvDtA+Z5ILWNN9wpZT/7ed8zEnKHPNUexyeT5g3 ++uw9z9jH7ffGxFYlx87oiVPHGOrCXYZYW5uoZE31SCBkbtNuffNRJRKIFeipmpJ3P ++7bpAG+kGHMelQH6b+5K1Qgsv4tpuSyKeTKpPFH9Av5nN4P1ZBm9N80tzbNWqjSJm ++S7rYdHnuNEVnUGnRmEUMmVuYZnNBEVN/fP2m2SEwXcP3Uh7TiYlcWw10ygaGmOr7 ++MvMLGkYgQ4Utwnd98mtqa0jr0hK2TcOSFir3AqVvXN3XJj4cVULkrXe4Im1laWgp ++-----END RSA PRIVATE KEY----- ++`), ++ }, ++ ++ 1: { ++ Name: "dsa-encrypted", ++ EncryptionKey: "qG0pher-dsa_t3st$", ++ PEMBytes: []byte(`-----BEGIN DSA PRIVATE KEY----- ++Proc-Type: 4,ENCRYPTED ++DEK-Info: AES-128-CBC,7CE7A6E4A647DC01AF860210B15ADE3E ++ ++hvnBpI99Hceq/55pYRdOzBLntIEis02JFNXuLEydWL+RJBFDn7tA+vXec0ERJd6J ++G8JXlSOAhmC2H4uK3q2xR8/Y3yL95n6OIcjvCBiLsV+o3jj1MYJmErxP6zRtq4w3 ++JjIjGHWmaYFSxPKQ6e8fs74HEqaeMV9ONUoTtB+aISmgaBL15Fcoayg245dkBvVl ++h5Kqspe7yvOBmzA3zjRuxmSCqKJmasXM7mqs3vIrMxZE3XPo1/fWKcPuExgpVQoT ++HkJZEoIEIIPnPMwT2uYbFJSGgPJVMDT84xz7yvjCdhLmqrsXgs5Qw7Pw0i0c0BUJ ++b7fDJ2UhdiwSckWGmIhTLlJZzr8K+JpjCDlP+REYBI5meB7kosBnlvCEHdw2EJkH ++0QDc/2F4xlVrHOLbPRFyu1Oi2Gvbeoo9EsM/DThpd1hKAlb0sF5Y0y0d+owv0PnE ++R/4X3HWfIdOHsDUvJ8xVWZ4BZk9Zk9qol045DcFCehpr/3hslCrKSZHakLt9GI58 ++vVQJ4L0aYp5nloLfzhViZtKJXRLkySMKdzYkIlNmW1oVGl7tce5UCNI8Nok4j6yn ++IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8= ++-----END DSA PRIVATE KEY----- ++`), ++ }, ++ ++ 2: { ++ Name: "ed25519-encrypted", ++ EncryptionKey: "password", ++ IncludesPublicKey: true, ++ PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKj29BlC ++ocEWuVhQ94/RjoAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIw1gSurPTDwZidA ++2AIjQZgoQi3IFn9jBtFdP10/Jj7DAAAAoFGkQbB2teSU7ikUsnc7ct2aH3pitM359lNVUh ++7DQbJWMjbQFbrBYyDJP+ALj1/RZmP2yoIf7/wr99q53/pm28Xp1gGP5V2RGRJYCA6kgFIH ++xdB6KEw1Ce7Bz8JaDIeagAGd3xtQTH3cuuleVxCZZnk9NspsPxigADKCls/RUiK7F+z3Qf ++Lvs9+PH8nIuhFMYZgo3liqZbVS5z4Fqhyzyq4= ++-----END OPENSSH PRIVATE KEY----- ++`), ++ }, ++ ++ 3: { ++ Name: "ed25519-encrypted-cbc", ++ EncryptionKey: "password", ++ IncludesPublicKey: true, ++ PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- ++b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABDzGKF3uX ++G1gXALZKFd6Ir4AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDne4/teO42zTDdj ++NwxUMNpbfmp/dxgU4ZNkC3ydgcugAAAAoJ3J/oA7+iqVOz0CIUUk9ufdP1VP4jDf2um+0s ++Sgs7x6Gpyjq67Ps7wLRdSmxr/G5b+Z8dRGFYS/wUCQEe3whwuImvLyPwWjXLzkAyMzc01f ++ywBGSrHnvP82ppenc2HuTI+E05Xc02i6JVyI1ShiekQL5twoqtR6pEBZnD17UonIx7cRzZ ++gbDGyT3bXMQtagvCwoW+/oMTKXiZP5jCJpEO8= ++-----END OPENSSH PRIVATE KEY----- ++`), ++ }, ++} ++ ++// SKData contains a list of PubKeys backed by U2F/FIDO2 Security Keys and their test data. ++var SKData = []struct { ++ Name string ++ PubKey []byte ++ HexData []byte ++ HexSignature []byte ++}{ ++ { ++ Name: "sk-ecdsa-sha2-nistp256@openssh.com", ++ PubKey: []byte("sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGRNqlFgED/pf4zXz8IzqA6CALNwYcwgd4MQDmIS1GOtn1SySFObiuyJaOlpqkV5FeEifhxfIC2ejKKtNyO4CysAAAAEc3NoOg== user@host"), ++ HexData: []byte("00000020A4DE1F50DE0EF3F66DCD156C78F5C93B07EEE89D5B5A6531656E835FA1C87B323200000006736B696E6E650000000E7373682D636F6E6E656374696F6E000000097075626C69636B65790100000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D0000007F00000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D000000086E697374703235360000004104644DAA5160103FE97F8CD7CFC233A80E8200B37061CC207783100E6212D463AD9F54B248539B8AEC8968E969AA457915E1227E1C5F202D9E8CA2AD3723B80B2B000000047373683A"), ++ HexSignature: []byte("0000007800000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D000000490000002016CC1A3070E180621CB206C2C6313D1CC5F094DB844A61D06001E243C608875F0000002100E4BD45D6B9DAA11489AEA8D76C222AA3FD6D50FBFFDA8049526D5D61F63B2C5601000000F9"), ++ }, ++ { ++ Name: "sk-ssh-ed25519@openssh.com", ++ PubKey: []byte("sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJjzc2a20RjCvN/0ibH6UpGuN9F9hDvD7x182bOesNhHAAAABHNzaDo= user@host"), ++ HexData: []byte("000000204CFE6EA65CCB99B69348339165C7F38E359D95807A377EEE8E603C71DC3316FA3200000006736B696E6E650000000E7373682D636F6E6E656374696F6E000000097075626C69636B6579010000001A736B2D7373682D65643235353139406F70656E7373682E636F6D0000004A0000001A736B2D7373682D65643235353139406F70656E7373682E636F6D0000002098F37366B6D118C2BCDFF489B1FA5291AE37D17D843BC3EF1D7CD9B39EB0D847000000047373683A"), ++ HexSignature: []byte("000000670000001A736B2D7373682D65643235353139406F70656E7373682E636F6D000000404BF5CA0CAA553099306518732317B3FE4BA6C75365BC0CB02019FBE65A1647016CBD7A682C26928DF234C378ADDBC5077B47F72381144840BF00FB2DA2FB6A0A010000009E"), ++ }, ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/testdata_test.go b/ms_mod/golang.org/x/crypto/ssh/testdata_test.go +new file mode 100644 +index 00000000000000..2da8c79dc64a43 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/testdata_test.go +@@ -0,0 +1,63 @@ ++// Copyright 2014 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: ++// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three ++// instances. ++ ++package ssh ++ ++import ( ++ "crypto/rand" ++ "fmt" ++ ++ "golang.org/x/crypto/ssh/testdata" ++) ++ ++var ( ++ testPrivateKeys map[string]interface{} ++ testSigners map[string]Signer ++ testPublicKeys map[string]PublicKey ++) ++ ++func init() { ++ var err error ++ ++ n := len(testdata.PEMBytes) ++ testPrivateKeys = make(map[string]interface{}, n) ++ testSigners = make(map[string]Signer, n) ++ testPublicKeys = make(map[string]PublicKey, n) ++ for t, k := range testdata.PEMBytes { ++ testPrivateKeys[t], err = ParseRawPrivateKey(k) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) ++ } ++ testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) ++ } ++ testPublicKeys[t] = testSigners[t].PublicKey() ++ } ++ ++ // Create a cert and sign it for use in tests. ++ testCert := &Certificate{ ++ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ++ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage ++ ValidAfter: 0, // unix epoch ++ ValidBefore: CertTimeInfinity, // The end of currently representable time. ++ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil ++ Key: testPublicKeys["ecdsa"], ++ SignatureKey: testPublicKeys["rsa"], ++ Permissions: Permissions{ ++ CriticalOptions: map[string]string{}, ++ Extensions: map[string]string{}, ++ }, ++ } ++ testCert.SignCert(rand.Reader, testSigners["rsa"]) ++ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] ++ testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"]) ++ if err != nil { ++ panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/transport.go b/ms_mod/golang.org/x/crypto/ssh/transport.go +new file mode 100644 +index 00000000000000..da015801ea5bf2 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/transport.go +@@ -0,0 +1,358 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bufio" ++ "bytes" ++ "errors" ++ "io" ++ "log" ++) ++ ++// debugTransport if set, will print packet types as they go over the ++// wire. No message decoding is done, to minimize the impact on timing. ++const debugTransport = false ++ ++const ( ++ gcm128CipherID = "aes128-gcm@openssh.com" ++ gcm256CipherID = "aes256-gcm@openssh.com" ++ aes128cbcID = "aes128-cbc" ++ tripledescbcID = "3des-cbc" ++) ++ ++// packetConn represents a transport that implements packet based ++// operations. ++type packetConn interface { ++ // Encrypt and send a packet of data to the remote peer. ++ writePacket(packet []byte) error ++ ++ // Read a packet from the connection. The read is blocking, ++ // i.e. if error is nil, then the returned byte slice is ++ // always non-empty. ++ readPacket() ([]byte, error) ++ ++ // Close closes the write-side of the connection. ++ Close() error ++} ++ ++// transport is the keyingTransport that implements the SSH packet ++// protocol. ++type transport struct { ++ reader connectionState ++ writer connectionState ++ ++ bufReader *bufio.Reader ++ bufWriter *bufio.Writer ++ rand io.Reader ++ isClient bool ++ io.Closer ++} ++ ++// packetCipher represents a combination of SSH encryption/MAC ++// protocol. A single instance should be used for one direction only. ++type packetCipher interface { ++ // writeCipherPacket encrypts the packet and writes it to w. The ++ // contents of the packet are generally scrambled. ++ writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error ++ ++ // readCipherPacket reads and decrypts a packet of data. The ++ // returned packet may be overwritten by future calls of ++ // readPacket. ++ readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error) ++} ++ ++// connectionState represents one side (read or write) of the ++// connection. This is necessary because each direction has its own ++// keys, and can even have its own algorithms ++type connectionState struct { ++ packetCipher ++ seqNum uint32 ++ dir direction ++ pendingKeyChange chan packetCipher ++} ++ ++// prepareKeyChange sets up key material for a keychange. The key changes in ++// both directions are triggered by reading and writing a msgNewKey packet ++// respectively. ++func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { ++ ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) ++ if err != nil { ++ return err ++ } ++ t.reader.pendingKeyChange <- ciph ++ ++ ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) ++ if err != nil { ++ return err ++ } ++ t.writer.pendingKeyChange <- ciph ++ ++ return nil ++} ++ ++func (t *transport) printPacket(p []byte, write bool) { ++ if len(p) == 0 { ++ return ++ } ++ who := "server" ++ if t.isClient { ++ who = "client" ++ } ++ what := "read" ++ if write { ++ what = "write" ++ } ++ ++ log.Println(what, who, p[0]) ++} ++ ++// Read and decrypt next packet. ++func (t *transport) readPacket() (p []byte, err error) { ++ for { ++ p, err = t.reader.readPacket(t.bufReader) ++ if err != nil { ++ break ++ } ++ if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { ++ break ++ } ++ } ++ if debugTransport { ++ t.printPacket(p, false) ++ } ++ ++ return p, err ++} ++ ++func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { ++ packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) ++ s.seqNum++ ++ if err == nil && len(packet) == 0 { ++ err = errors.New("ssh: zero length packet") ++ } ++ ++ if len(packet) > 0 { ++ switch packet[0] { ++ case msgNewKeys: ++ select { ++ case cipher := <-s.pendingKeyChange: ++ s.packetCipher = cipher ++ default: ++ return nil, errors.New("ssh: got bogus newkeys message") ++ } ++ ++ case msgDisconnect: ++ // Transform a disconnect message into an ++ // error. Since this is lowest level at which ++ // we interpret message types, doing it here ++ // ensures that we don't have to handle it ++ // elsewhere. ++ var msg disconnectMsg ++ if err := Unmarshal(packet, &msg); err != nil { ++ return nil, err ++ } ++ return nil, &msg ++ } ++ } ++ ++ // The packet may point to an internal buffer, so copy the ++ // packet out here. ++ fresh := make([]byte, len(packet)) ++ copy(fresh, packet) ++ ++ return fresh, err ++} ++ ++func (t *transport) writePacket(packet []byte) error { ++ if debugTransport { ++ t.printPacket(packet, true) ++ } ++ return t.writer.writePacket(t.bufWriter, t.rand, packet) ++} ++ ++func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { ++ changeKeys := len(packet) > 0 && packet[0] == msgNewKeys ++ ++ err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) ++ if err != nil { ++ return err ++ } ++ if err = w.Flush(); err != nil { ++ return err ++ } ++ s.seqNum++ ++ if changeKeys { ++ select { ++ case cipher := <-s.pendingKeyChange: ++ s.packetCipher = cipher ++ default: ++ panic("ssh: no key material for msgNewKeys") ++ } ++ } ++ return err ++} ++ ++func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { ++ t := &transport{ ++ bufReader: bufio.NewReader(rwc), ++ bufWriter: bufio.NewWriter(rwc), ++ rand: rand, ++ reader: connectionState{ ++ packetCipher: &streamPacketCipher{cipher: noneCipher{}}, ++ pendingKeyChange: make(chan packetCipher, 1), ++ }, ++ writer: connectionState{ ++ packetCipher: &streamPacketCipher{cipher: noneCipher{}}, ++ pendingKeyChange: make(chan packetCipher, 1), ++ }, ++ Closer: rwc, ++ } ++ t.isClient = isClient ++ ++ if isClient { ++ t.reader.dir = serverKeys ++ t.writer.dir = clientKeys ++ } else { ++ t.reader.dir = clientKeys ++ t.writer.dir = serverKeys ++ } ++ ++ return t ++} ++ ++type direction struct { ++ ivTag []byte ++ keyTag []byte ++ macKeyTag []byte ++} ++ ++var ( ++ serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} ++ clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} ++) ++ ++// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as ++// described in RFC 4253, section 6.4. direction should either be serverKeys ++// (to setup server->client keys) or clientKeys (for client->server keys). ++func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { ++ cipherMode := cipherModes[algs.Cipher] ++ ++ iv := make([]byte, cipherMode.ivSize) ++ key := make([]byte, cipherMode.keySize) ++ ++ generateKeyMaterial(iv, d.ivTag, kex) ++ generateKeyMaterial(key, d.keyTag, kex) ++ ++ var macKey []byte ++ if !aeadCiphers[algs.Cipher] { ++ macMode := macModes[algs.MAC] ++ macKey = make([]byte, macMode.keySize) ++ generateKeyMaterial(macKey, d.macKeyTag, kex) ++ } ++ ++ return cipherModes[algs.Cipher].create(key, iv, macKey, algs) ++} ++ ++// generateKeyMaterial fills out with key material generated from tag, K, H ++// and sessionId, as specified in RFC 4253, section 7.2. ++func generateKeyMaterial(out, tag []byte, r *kexResult) { ++ var digestsSoFar []byte ++ ++ h := r.Hash.New() ++ for len(out) > 0 { ++ h.Reset() ++ h.Write(r.K) ++ h.Write(r.H) ++ ++ if len(digestsSoFar) == 0 { ++ h.Write(tag) ++ h.Write(r.SessionID) ++ } else { ++ h.Write(digestsSoFar) ++ } ++ ++ digest := h.Sum(nil) ++ n := copy(out, digest) ++ out = out[n:] ++ if len(out) > 0 { ++ digestsSoFar = append(digestsSoFar, digest...) ++ } ++ } ++} ++ ++const packageVersion = "SSH-2.0-Go" ++ ++// Sends and receives a version line. The versionLine string should ++// be US ASCII, start with "SSH-2.0-", and should not include a ++// newline. exchangeVersions returns the other side's version line. ++func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { ++ // Contrary to the RFC, we do not ignore lines that don't ++ // start with "SSH-2.0-" to make the library usable with ++ // nonconforming servers. ++ for _, c := range versionLine { ++ // The spec disallows non US-ASCII chars, and ++ // specifically forbids null chars. ++ if c < 32 { ++ return nil, errors.New("ssh: junk character in version line") ++ } ++ } ++ if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { ++ return ++ } ++ ++ them, err = readVersion(rw) ++ return them, err ++} ++ ++// maxVersionStringBytes is the maximum number of bytes that we'll ++// accept as a version string. RFC 4253 section 4.2 limits this at 255 ++// chars ++const maxVersionStringBytes = 255 ++ ++// Read version string as specified by RFC 4253, section 4.2. ++func readVersion(r io.Reader) ([]byte, error) { ++ versionString := make([]byte, 0, 64) ++ var ok bool ++ var buf [1]byte ++ ++ for length := 0; length < maxVersionStringBytes; length++ { ++ _, err := io.ReadFull(r, buf[:]) ++ if err != nil { ++ return nil, err ++ } ++ // The RFC says that the version should be terminated with \r\n ++ // but several SSH servers actually only send a \n. ++ if buf[0] == '\n' { ++ if !bytes.HasPrefix(versionString, []byte("SSH-")) { ++ // RFC 4253 says we need to ignore all version string lines ++ // except the one containing the SSH version (provided that ++ // all the lines do not exceed 255 bytes in total). ++ versionString = versionString[:0] ++ continue ++ } ++ ok = true ++ break ++ } ++ ++ // non ASCII chars are disallowed, but we are lenient, ++ // since Go doesn't use null-terminated strings. ++ ++ // The RFC allows a comment after a space, however, ++ // all of it (version and comments) goes into the ++ // session hash. ++ versionString = append(versionString, buf[0]) ++ } ++ ++ if !ok { ++ return nil, errors.New("ssh: overflow reading version string") ++ } ++ ++ // There might be a '\r' on the end which we should remove. ++ if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { ++ versionString = versionString[:len(versionString)-1] ++ } ++ return versionString, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/ssh/transport_test.go b/ms_mod/golang.org/x/crypto/ssh/transport_test.go +new file mode 100644 +index 00000000000000..8445e1e561c15a +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/ssh/transport_test.go +@@ -0,0 +1,113 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package ssh ++ ++import ( ++ "bytes" ++ "crypto/rand" ++ "encoding/binary" ++ "strings" ++ "testing" ++) ++ ++func TestReadVersion(t *testing.T) { ++ longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] ++ multiLineVersion := strings.Repeat("ignored\r\n", 20) + "SSH-2.0-bla\r\n" ++ cases := map[string]string{ ++ "SSH-2.0-bla\r\n": "SSH-2.0-bla", ++ "SSH-2.0-bla\n": "SSH-2.0-bla", ++ multiLineVersion: "SSH-2.0-bla", ++ longVersion + "\r\n": longVersion, ++ } ++ ++ for in, want := range cases { ++ result, err := readVersion(bytes.NewBufferString(in)) ++ if err != nil { ++ t.Errorf("readVersion(%q): %s", in, err) ++ } ++ got := string(result) ++ if got != want { ++ t.Errorf("got %q, want %q", got, want) ++ } ++ } ++} ++ ++func TestReadVersionError(t *testing.T) { ++ longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] ++ multiLineVersion := strings.Repeat("ignored\r\n", 50) + "SSH-2.0-bla\r\n" ++ cases := []string{ ++ longVersion + "too-long\r\n", ++ multiLineVersion, ++ } ++ for _, in := range cases { ++ if _, err := readVersion(bytes.NewBufferString(in)); err == nil { ++ t.Errorf("readVersion(%q) should have failed", in) ++ } ++ } ++} ++ ++func TestExchangeVersionsBasic(t *testing.T) { ++ v := "SSH-2.0-bla" ++ buf := bytes.NewBufferString(v + "\r\n") ++ them, err := exchangeVersions(buf, []byte("xyz")) ++ if err != nil { ++ t.Errorf("exchangeVersions: %v", err) ++ } ++ ++ if want := "SSH-2.0-bla"; string(them) != want { ++ t.Errorf("got %q want %q for our version", them, want) ++ } ++} ++ ++func TestExchangeVersions(t *testing.T) { ++ cases := []string{ ++ "not\x000allowed", ++ "not allowed\x01\r\n", ++ } ++ for _, c := range cases { ++ buf := bytes.NewBufferString("SSH-2.0-bla\r\n") ++ if _, err := exchangeVersions(buf, []byte(c)); err == nil { ++ t.Errorf("exchangeVersions(%q): should have failed", c) ++ } ++ } ++} ++ ++type closerBuffer struct { ++ bytes.Buffer ++} ++ ++func (b *closerBuffer) Close() error { ++ return nil ++} ++ ++func TestTransportMaxPacketWrite(t *testing.T) { ++ buf := &closerBuffer{} ++ tr := newTransport(buf, rand.Reader, true) ++ huge := make([]byte, maxPacket+1) ++ err := tr.writePacket(huge) ++ if err == nil { ++ t.Errorf("transport accepted write for a huge packet.") ++ } ++} ++ ++func TestTransportMaxPacketReader(t *testing.T) { ++ var header [5]byte ++ huge := make([]byte, maxPacket+128) ++ binary.BigEndian.PutUint32(header[0:], uint32(len(huge))) ++ // padding. ++ header[4] = 0 ++ ++ buf := &closerBuffer{} ++ buf.Write(header[:]) ++ buf.Write(huge) ++ ++ tr := newTransport(buf, rand.Reader, true) ++ _, err := tr.readPacket() ++ if err == nil { ++ t.Errorf("transport succeeded reading huge packet.") ++ } else if !strings.Contains(err.Error(), "large") { ++ t.Errorf("got %q, should mention %q", err.Error(), "large") ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/tea/cipher.go b/ms_mod/golang.org/x/crypto/tea/cipher.go +new file mode 100644 +index 00000000000000..c1ff90e048d005 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/tea/cipher.go +@@ -0,0 +1,116 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package tea implements the TEA algorithm, as defined in Needham and ++// Wheeler's 1994 technical report, β€œTEA, a Tiny Encryption Algorithm”. See ++// http://www.cix.co.uk/~klockstone/tea.pdf for details. ++// ++// TEA is a legacy cipher and its short block size makes it vulnerable to ++// birthday bound attacks (see https://sweet32.info). It should only be used ++// where compatibility with legacy systems, not security, is the goal. ++// ++// Deprecated: any new system should use AES (from crypto/aes, if necessary in ++// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from ++// golang.org/x/crypto/chacha20poly1305). ++package tea ++ ++import ( ++ "crypto/cipher" ++ "encoding/binary" ++ "errors" ++) ++ ++const ( ++ // BlockSize is the size of a TEA block, in bytes. ++ BlockSize = 8 ++ ++ // KeySize is the size of a TEA key, in bytes. ++ KeySize = 16 ++ ++ // delta is the TEA key schedule constant. ++ delta = 0x9e3779b9 ++ ++ // numRounds is the standard number of rounds in TEA. ++ numRounds = 64 ++) ++ ++// tea is an instance of the TEA cipher with a particular key. ++type tea struct { ++ key [16]byte ++ rounds int ++} ++ ++// NewCipher returns an instance of the TEA cipher with the standard number of ++// rounds. The key argument must be 16 bytes long. ++func NewCipher(key []byte) (cipher.Block, error) { ++ return NewCipherWithRounds(key, numRounds) ++} ++ ++// NewCipherWithRounds returns an instance of the TEA cipher with a given ++// number of rounds, which must be even. The key argument must be 16 bytes ++// long. ++func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { ++ if len(key) != 16 { ++ return nil, errors.New("tea: incorrect key size") ++ } ++ ++ if rounds&1 != 0 { ++ return nil, errors.New("tea: odd number of rounds specified") ++ } ++ ++ c := &tea{ ++ rounds: rounds, ++ } ++ copy(c.key[:], key) ++ ++ return c, nil ++} ++ ++// BlockSize returns the TEA block size, which is eight bytes. It is necessary ++// to satisfy the Block interface in the package "crypto/cipher". ++func (*tea) BlockSize() int { ++ return BlockSize ++} ++ ++// Encrypt encrypts the 8 byte buffer src using the key in t and stores the ++// result in dst. Note that for amounts of data larger than a block, it is not ++// safe to just call Encrypt on successive blocks; instead, use an encryption ++// mode like CBC (see crypto/cipher/cbc.go). ++func (t *tea) Encrypt(dst, src []byte) { ++ e := binary.BigEndian ++ v0, v1 := e.Uint32(src), e.Uint32(src[4:]) ++ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) ++ ++ sum := uint32(0) ++ delta := uint32(delta) ++ ++ for i := 0; i < t.rounds/2; i++ { ++ sum += delta ++ v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ++ v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ++ } ++ ++ e.PutUint32(dst, v0) ++ e.PutUint32(dst[4:], v1) ++} ++ ++// Decrypt decrypts the 8 byte buffer src using the key in t and stores the ++// result in dst. ++func (t *tea) Decrypt(dst, src []byte) { ++ e := binary.BigEndian ++ v0, v1 := e.Uint32(src), e.Uint32(src[4:]) ++ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) ++ ++ delta := uint32(delta) ++ sum := delta * uint32(t.rounds/2) // in general, sum = delta * n ++ ++ for i := 0; i < t.rounds/2; i++ { ++ v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ++ v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ++ sum -= delta ++ } ++ ++ e.PutUint32(dst, v0) ++ e.PutUint32(dst[4:], v1) ++} +diff --git a/ms_mod/golang.org/x/crypto/tea/tea_test.go b/ms_mod/golang.org/x/crypto/tea/tea_test.go +new file mode 100644 +index 00000000000000..eb98d1e0e03e64 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/tea/tea_test.go +@@ -0,0 +1,93 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package tea ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++// A sample test key for when we just want to initialize a cipher ++var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} ++ ++// Test that the block size for tea is correct ++func TestBlocksize(t *testing.T) { ++ c, err := NewCipher(testKey) ++ if err != nil { ++ t.Fatalf("NewCipher returned error: %s", err) ++ } ++ ++ if result := c.BlockSize(); result != BlockSize { ++ t.Errorf("cipher.BlockSize returned %d, but expected %d", result, BlockSize) ++ } ++} ++ ++// Test that invalid key sizes return an error ++func TestInvalidKeySize(t *testing.T) { ++ var key [KeySize + 1]byte ++ ++ if _, err := NewCipher(key[:]); err == nil { ++ t.Errorf("invalid key size %d didn't result in an error.", len(key)) ++ } ++ ++ if _, err := NewCipher(key[:KeySize-1]); err == nil { ++ t.Errorf("invalid key size %d didn't result in an error.", KeySize-1) ++ } ++} ++ ++// Test Vectors ++type teaTest struct { ++ rounds int ++ key []byte ++ plaintext []byte ++ ciphertext []byte ++} ++ ++var teaTests = []teaTest{ ++ // These were sourced from https://github.com/froydnj/ironclad/blob/master/testing/test-vectors/tea.testvec ++ { ++ numRounds, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x41, 0xea, 0x3a, 0x0a, 0x94, 0xba, 0xa9, 0x40}, ++ }, ++ { ++ numRounds, ++ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, ++ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, ++ []byte{0x31, 0x9b, 0xbe, 0xfb, 0x01, 0x6a, 0xbd, 0xb2}, ++ }, ++ { ++ 16, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0xed, 0x28, 0x5d, 0xa1, 0x45, 0x5b, 0x33, 0xc1}, ++ }, ++} ++ ++// Test encryption ++func TestCipherEncrypt(t *testing.T) { ++ // Test encryption with standard 64 rounds ++ for i, test := range teaTests { ++ c, err := NewCipherWithRounds(test.key, test.rounds) ++ if err != nil { ++ t.Fatalf("#%d: NewCipher returned error: %s", i, err) ++ } ++ ++ var ciphertext [BlockSize]byte ++ c.Encrypt(ciphertext[:], test.plaintext) ++ ++ if !bytes.Equal(ciphertext[:], test.ciphertext) { ++ t.Errorf("#%d: incorrect ciphertext. Got %x, wanted %x", i, ciphertext, test.ciphertext) ++ } ++ ++ var plaintext2 [BlockSize]byte ++ c.Decrypt(plaintext2[:], ciphertext[:]) ++ ++ if !bytes.Equal(plaintext2[:], test.plaintext) { ++ t.Errorf("#%d: incorrect plaintext. Got %x, wanted %x", i, plaintext2, test.plaintext) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/twofish/twofish.go b/ms_mod/golang.org/x/crypto/twofish/twofish.go +new file mode 100644 +index 00000000000000..e4eeae17f4040f +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/twofish/twofish.go +@@ -0,0 +1,341 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package twofish implements Bruce Schneier's Twofish encryption algorithm. ++// ++// Deprecated: Twofish is a legacy cipher and should not be used for new ++// applications. Also, this package does not and will not provide an optimized ++// implementation. Instead, use AES (from crypto/aes, if necessary in an AEAD ++// mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from ++// golang.org/x/crypto/chacha20poly1305). ++package twofish // import "golang.org/x/crypto/twofish" ++ ++// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH] ++ ++// This code is a port of the LibTom C implementation. ++// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. ++// LibTomCrypt is free for all purposes under the public domain. ++// It was heavily inspired by the go blowfish package. ++ ++import ( ++ "math/bits" ++ "strconv" ++) ++ ++// BlockSize is the constant block size of Twofish. ++const BlockSize = 16 ++ ++const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 ++const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 ++ ++// A Cipher is an instance of Twofish encryption using a particular key. ++type Cipher struct { ++ s [4][256]uint32 ++ k [40]uint32 ++} ++ ++type KeySizeError int ++ ++func (k KeySizeError) Error() string { ++ return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) ++} ++ ++// NewCipher creates and returns a Cipher. ++// The key argument should be the Twofish key, 16, 24 or 32 bytes. ++func NewCipher(key []byte) (*Cipher, error) { ++ keylen := len(key) ++ ++ if keylen != 16 && keylen != 24 && keylen != 32 { ++ return nil, KeySizeError(keylen) ++ } ++ ++ // k is the number of 64 bit words in key ++ k := keylen / 8 ++ ++ // Create the S[..] words ++ var S [4 * 4]byte ++ for i := 0; i < k; i++ { ++ // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] ++ for j, rsRow := range rs { ++ for k, rsVal := range rsRow { ++ S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial) ++ } ++ } ++ } ++ ++ // Calculate subkeys ++ c := new(Cipher) ++ var tmp [4]byte ++ for i := byte(0); i < 20; i++ { ++ // A = h(p * 2x, Me) ++ for j := range tmp { ++ tmp[j] = 2 * i ++ } ++ A := h(tmp[:], key, 0) ++ ++ // B = rolc(h(p * (2x + 1), Mo), 8) ++ for j := range tmp { ++ tmp[j] = 2*i + 1 ++ } ++ B := h(tmp[:], key, 1) ++ B = bits.RotateLeft32(B, 8) ++ ++ c.k[2*i] = A + B ++ ++ // K[2i+1] = (A + 2B) <<< 9 ++ c.k[2*i+1] = bits.RotateLeft32(2*B+A, 9) ++ } ++ ++ // Calculate sboxes ++ switch k { ++ case 2: ++ for i := range c.s[0] { ++ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0) ++ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1) ++ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2) ++ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3) ++ } ++ case 3: ++ for i := range c.s[0] { ++ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0) ++ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1) ++ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2) ++ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3) ++ } ++ default: ++ for i := range c.s[0] { ++ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) ++ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) ++ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) ++ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) ++ } ++ } ++ ++ return c, nil ++} ++ ++// BlockSize returns the Twofish block size, 16 bytes. ++func (c *Cipher) BlockSize() int { return BlockSize } ++ ++// store32l stores src in dst in little-endian form. ++func store32l(dst []byte, src uint32) { ++ dst[0] = byte(src) ++ dst[1] = byte(src >> 8) ++ dst[2] = byte(src >> 16) ++ dst[3] = byte(src >> 24) ++ return ++} ++ ++// load32l reads a little-endian uint32 from src. ++func load32l(src []byte) uint32 { ++ return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24 ++} ++ ++// The RS matrix. See [TWOFISH] 4.3 ++var rs = [4][8]byte{ ++ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E}, ++ {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5}, ++ {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19}, ++ {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03}, ++} ++ ++// sbox tables ++var sbox = [2][256]byte{ ++ { ++ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, ++ 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, ++ 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, ++ 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61, ++ 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, ++ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, ++ 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, ++ 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, ++ 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, ++ 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, ++ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, ++ 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a, ++ 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, ++ 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, ++ 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, ++ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0, ++ }, ++ { ++ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, ++ 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f, ++ 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, ++ 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, ++ 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, ++ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, ++ 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, ++ 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, ++ 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, ++ 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, ++ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, ++ 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64, ++ 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, ++ 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, ++ 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, ++ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91, ++ }, ++} ++ ++// gfMult returns aΒ·b in GF(2^8)/p ++func gfMult(a, b byte, p uint32) byte { ++ B := [2]uint32{0, uint32(b)} ++ P := [2]uint32{0, p} ++ var result uint32 ++ ++ // branchless GF multiplier ++ for i := 0; i < 7; i++ { ++ result ^= B[a&1] ++ a >>= 1 ++ B[1] = P[B[1]>>7] ^ (B[1] << 1) ++ } ++ result ^= B[a&1] ++ return byte(result) ++} ++ ++// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS Β· [x0] ++func mdsColumnMult(in byte, col int) uint32 { ++ mul01 := in ++ mul5B := gfMult(in, 0x5B, mdsPolynomial) ++ mulEF := gfMult(in, 0xEF, mdsPolynomial) ++ ++ switch col { ++ case 0: ++ return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24 ++ case 1: ++ return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24 ++ case 2: ++ return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24 ++ case 3: ++ return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24 ++ } ++ ++ panic("unreachable") ++} ++ ++// h implements the S-box generation function. See [TWOFISH] 4.3.5 ++func h(in, key []byte, offset int) uint32 { ++ var y [4]byte ++ for x := range y { ++ y[x] = in[x] ++ } ++ switch len(key) / 8 { ++ case 4: ++ y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] ++ y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] ++ y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] ++ y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] ++ fallthrough ++ case 3: ++ y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] ++ y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] ++ y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] ++ y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] ++ fallthrough ++ case 2: ++ y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]] ++ y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]] ++ y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]] ++ y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]] ++ } ++ // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] ++ var mdsMult uint32 ++ for i := range y { ++ mdsMult ^= mdsColumnMult(y[i], i) ++ } ++ return mdsMult ++} ++ ++// Encrypt encrypts a 16-byte block from src to dst, which may overlap. ++// Note that for amounts of data larger than a block, ++// it is not safe to just call Encrypt on successive blocks; ++// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). ++func (c *Cipher) Encrypt(dst, src []byte) { ++ S1 := c.s[0] ++ S2 := c.s[1] ++ S3 := c.s[2] ++ S4 := c.s[3] ++ ++ // Load input ++ ia := load32l(src[0:4]) ++ ib := load32l(src[4:8]) ++ ic := load32l(src[8:12]) ++ id := load32l(src[12:16]) ++ ++ // Pre-whitening ++ ia ^= c.k[0] ++ ib ^= c.k[1] ++ ic ^= c.k[2] ++ id ^= c.k[3] ++ ++ for i := 0; i < 8; i++ { ++ k := c.k[8+i*4 : 12+i*4] ++ t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] ++ t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 ++ ic = bits.RotateLeft32(ic^(t1+k[0]), -1) ++ id = bits.RotateLeft32(id, 1) ^ (t2 + t1 + k[1]) ++ ++ t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] ++ t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 ++ ia = bits.RotateLeft32(ia^(t1+k[2]), -1) ++ ib = bits.RotateLeft32(ib, 1) ^ (t2 + t1 + k[3]) ++ } ++ ++ // Output with "undo last swap" ++ ta := ic ^ c.k[4] ++ tb := id ^ c.k[5] ++ tc := ia ^ c.k[6] ++ td := ib ^ c.k[7] ++ ++ store32l(dst[0:4], ta) ++ store32l(dst[4:8], tb) ++ store32l(dst[8:12], tc) ++ store32l(dst[12:16], td) ++} ++ ++// Decrypt decrypts a 16-byte block from src to dst, which may overlap. ++func (c *Cipher) Decrypt(dst, src []byte) { ++ S1 := c.s[0] ++ S2 := c.s[1] ++ S3 := c.s[2] ++ S4 := c.s[3] ++ ++ // Load input ++ ta := load32l(src[0:4]) ++ tb := load32l(src[4:8]) ++ tc := load32l(src[8:12]) ++ td := load32l(src[12:16]) ++ ++ // Undo undo final swap ++ ia := tc ^ c.k[6] ++ ib := td ^ c.k[7] ++ ic := ta ^ c.k[4] ++ id := tb ^ c.k[5] ++ ++ for i := 8; i > 0; i-- { ++ k := c.k[4+i*4 : 8+i*4] ++ t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] ++ t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 ++ ia = bits.RotateLeft32(ia, 1) ^ (t1 + k[2]) ++ ib = bits.RotateLeft32(ib^(t2+t1+k[3]), -1) ++ ++ t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] ++ t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 ++ ic = bits.RotateLeft32(ic, 1) ^ (t1 + k[0]) ++ id = bits.RotateLeft32(id^(t2+t1+k[1]), -1) ++ } ++ ++ // Undo pre-whitening ++ ia ^= c.k[0] ++ ib ^= c.k[1] ++ ic ^= c.k[2] ++ id ^= c.k[3] ++ ++ store32l(dst[0:4], ia) ++ store32l(dst[4:8], ib) ++ store32l(dst[8:12], ic) ++ store32l(dst[12:16], id) ++} +diff --git a/ms_mod/golang.org/x/crypto/twofish/twofish_test.go b/ms_mod/golang.org/x/crypto/twofish/twofish_test.go +new file mode 100644 +index 00000000000000..ed6a1a8fdbb788 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/twofish/twofish_test.go +@@ -0,0 +1,129 @@ ++// Copyright 2011 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package twofish ++ ++import ( ++ "bytes" ++ "testing" ++) ++ ++var qbox = [2][4][16]byte{ ++ { ++ {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4}, ++ {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD}, ++ {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1}, ++ {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA}, ++ }, ++ { ++ {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5}, ++ {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8}, ++ {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF}, ++ {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA}, ++ }, ++} ++ ++// genSbox generates the variable sbox ++func genSbox(qi int, x byte) byte { ++ a0, b0 := x/16, x%16 ++ for i := 0; i < 2; i++ { ++ a1 := a0 ^ b0 ++ b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15 ++ a0 = qbox[qi][2*i][a1] ++ b0 = qbox[qi][2*i+1][b1] ++ } ++ return (b0 << 4) + a0 ++} ++ ++func TestSbox(t *testing.T) { ++ for n := range sbox { ++ for m := range sbox[n] { ++ if genSbox(n, byte(m)) != sbox[n][m] { ++ t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m))) ++ } ++ } ++ } ++} ++ ++var testVectors = []struct { ++ key []byte ++ dec []byte ++ enc []byte ++}{ ++ // These tests are extracted from LibTom ++ { ++ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, ++ []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19}, ++ []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3}, ++ }, ++ { ++ []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, ++ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44}, ++ []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2}, ++ []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65}, ++ }, ++ { ++ []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, ++ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F}, ++ []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6}, ++ []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA}, ++ }, ++ // These tests are derived from https://www.schneier.com/code/ecb_ival.txt ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, ++ }, ++ { ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, ++ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, ++ }, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48}, ++ }, ++ { ++ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, ++ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, ++ }, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20}, ++ }, ++} ++ ++func TestCipher(t *testing.T) { ++ for n, tt := range testVectors { ++ // Test if the plaintext (dec) is encrypts to the given ++ // ciphertext (enc) using the given key. Test also if enc can ++ // be decrypted again into dec. ++ c, err := NewCipher(tt.key) ++ if err != nil { ++ t.Errorf("#%d: NewCipher: %v", n, err) ++ return ++ } ++ ++ buf := make([]byte, 16) ++ c.Encrypt(buf, tt.dec) ++ if !bytes.Equal(buf, tt.enc) { ++ t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc) ++ } ++ c.Decrypt(buf, tt.enc) ++ if !bytes.Equal(buf, tt.dec) { ++ t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec) ++ } ++ ++ // Test that 16 zero bytes, encrypted 1000 times then decrypted ++ // 1000 times results in zero bytes again. ++ zero := make([]byte, 16) ++ buf = make([]byte, 16) ++ for i := 0; i < 1000; i++ { ++ c.Encrypt(buf, buf) ++ } ++ for i := 0; i < 1000; i++ { ++ c.Decrypt(buf, buf) ++ } ++ if !bytes.Equal(buf, zero) { ++ t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero) ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go b/ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go +new file mode 100644 +index 00000000000000..542ac87217b110 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go +@@ -0,0 +1,3827 @@ ++// Code generated by gen_fallback_bundle.go; DO NOT EDIT. ++ ++//go:build go1.20 ++ ++package fallback ++ ++import "crypto/x509" ++import "encoding/pem" ++ ++func mustParse(b []byte) []*x509.Certificate { ++ var roots []*x509.Certificate ++ for len(b) > 0 { ++ var block *pem.Block ++ block, b = pem.Decode(b) ++ if block == nil { ++ break ++ } ++ if block.Type != "CERTIFICATE" { ++ panic("unexpected PEM block type: " + block.Type) ++ } ++ cert, err := x509.ParseCertificate(block.Bytes) ++ if err != nil { ++ panic(err) ++ } ++ roots = append(roots, cert) ++ } ++ return roots ++} ++ ++var bundle = mustParse([]byte(pemRoots)) ++ ++// Format of the PEM list is: ++// * Subject common name ++// * SHA256 hash ++// * PEM block ++ ++const pemRoots = ` ++# CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4 ++-----BEGIN CERTIFICATE----- ++MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb ++MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow ++GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj ++YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL ++MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE ++BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM ++GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ++ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua ++BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe ++3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 ++YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR ++rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm ++ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU ++oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF ++MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v ++QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t ++b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF ++AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q ++GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz ++Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 ++G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi ++l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 ++smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ++-----END CERTIFICATE----- ++# CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS,OU=Ceres,O=FNMT-RCM,C=ES,2.5.4.97=#130f56415445532d51323832363030344a ++# 554153b13d2cf9ddb753bfbe1a4e0ae08d0aa4187058fe60a2b862b2e4b87bcb ++-----BEGIN CERTIFICATE----- ++MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw ++CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw ++FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S ++Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 ++MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL ++DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS ++QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB ++BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH ++sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK ++Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD ++VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu ++SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC ++MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy ++v+c= ++-----END CERTIFICATE----- ++# CN=ACCVRAIZ1,OU=PKIACCV,O=ACCV,C=ES ++# 9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113 ++-----BEGIN CERTIFICATE----- ++MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE ++AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw ++CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ ++BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND ++VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb ++qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY ++HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo ++G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA ++lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr ++IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ ++0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH ++k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 ++4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO ++m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa ++cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl ++uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI ++KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls ++ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG ++AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 ++VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT ++VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG ++CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA ++cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA ++QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA ++7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA ++cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA ++QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA ++czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu ++aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt ++aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud ++DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF ++BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp ++D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU ++JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m ++AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD ++vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms ++tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH ++7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h ++I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA ++h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF ++d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H ++pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 ++-----END CERTIFICATE----- ++# CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT ++# 55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066 ++-----BEGIN CERTIFICATE----- ++MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE ++BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w ++MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 ++IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC ++SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 ++ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB ++MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv ++UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX ++4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 ++KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ ++gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb ++rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ ++51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F ++be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe ++KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F ++v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn ++fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 ++jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz ++ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ++ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL ++e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 ++jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz ++WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V ++SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j ++pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX ++X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok ++fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R ++K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU ++ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU ++LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT ++LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ++-----END CERTIFICATE----- ++# CN=AffirmTrust Commercial,O=AffirmTrust,C=US ++# 0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7 ++-----BEGIN CERTIFICATE----- ++MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE ++BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz ++dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL ++MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp ++cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC ++AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP ++Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr ++ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL ++MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 ++yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr ++VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ ++nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ ++KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG ++XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj ++vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt ++Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g ++N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC ++nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ++-----END CERTIFICATE----- ++# CN=AffirmTrust Networking,O=AffirmTrust,C=US ++# 0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b ++-----BEGIN CERTIFICATE----- ++MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE ++BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz ++dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL ++MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp ++cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC ++AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y ++YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua ++kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL ++QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp ++6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG ++yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i ++QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ ++KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO ++tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu ++QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ ++Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u ++olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 ++x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ++-----END CERTIFICATE----- ++# CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US ++# bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423 ++-----BEGIN CERTIFICATE----- ++MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC ++VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ ++cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ ++BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt ++VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D ++0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 ++ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G ++A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G ++A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs ++aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I ++flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ++-----END CERTIFICATE----- ++# CN=AffirmTrust Premium,O=AffirmTrust,C=US ++# 70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a ++-----BEGIN CERTIFICATE----- ++MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE ++BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz ++dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG ++A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U ++cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf ++qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ ++JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ +++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS ++s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 ++HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 ++70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG ++V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S ++qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S ++5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia ++C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX ++OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE ++FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ ++BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 ++KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg ++Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B ++8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ ++MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc ++0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ ++u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF ++u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH ++YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 ++GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO ++RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e ++KeC2uAloGRwYQw== ++-----END CERTIFICATE----- ++# CN=Amazon Root CA 1,O=Amazon,C=US ++# 8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e ++-----BEGIN CERTIFICATE----- ++MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF ++ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 ++b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL ++MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv ++b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj ++ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM ++9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw ++IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 ++VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L ++93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm ++jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC ++AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA ++A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI ++U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs ++N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv ++o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU ++5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy ++rqXRfboQnoZsG4q5WTP468SQvvG5 ++-----END CERTIFICATE----- ++# CN=Amazon Root CA 2,O=Amazon,C=US ++# 1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4 ++-----BEGIN CERTIFICATE----- ++MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF ++ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 ++b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL ++MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv ++b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK ++gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ ++W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg ++1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K ++8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r ++2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me ++z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR ++8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj ++mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz ++7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 +++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI ++0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB ++Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm ++UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 ++LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY +++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS ++k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl ++7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm ++btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl ++urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ ++fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 ++n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE ++76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H ++9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT ++4PsJYGw= ++-----END CERTIFICATE----- ++# CN=Amazon Root CA 3,O=Amazon,C=US ++# 18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4 ++-----BEGIN CERTIFICATE----- ++MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 ++MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g ++Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG ++A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg ++Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl ++ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j ++QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr ++ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr ++BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM ++YyRIHN8wfdVoOw== ++-----END CERTIFICATE----- ++# CN=Amazon Root CA 4,O=Amazon,C=US ++# e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092 ++-----BEGIN CERTIFICATE----- ++MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 ++MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g ++Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG ++A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg ++Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi ++9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk ++M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB ++/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB ++MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw ++CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW ++1KyLa2tJElMzrdfkviT8tQp21KW8EA== ++-----END CERTIFICATE----- ++# CN=Atos TrustedRoot 2011,O=Atos,C=DE ++# f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474 ++-----BEGIN CERTIFICATE----- ++MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE ++AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG ++EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM ++FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC ++REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp ++Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM ++VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ ++SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ ++4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L ++cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi ++eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV ++HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG ++A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 ++DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j ++vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP ++DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc ++maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D ++lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv ++KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ++-----END CERTIFICATE----- ++# CN=Atos TrustedRoot Root CA ECC TLS 2021,O=Atos,C=DE ++# b2fae53e14ccd7ab9212064701ae279c1d8988facb775fa8a008914e663988a8 ++-----BEGIN CERTIFICATE----- ++MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w ++LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w ++CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 ++MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF ++Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI ++zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X ++tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 ++AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 ++KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD ++aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu ++CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo ++9H1/IISpQuQo ++-----END CERTIFICATE----- ++# CN=Atos TrustedRoot Root CA RSA TLS 2021,O=Atos,C=DE ++# 81a9088ea59fb364c548a6f85559099b6f0405efbf18e5324ec9f457ba00112f ++-----BEGIN CERTIFICATE----- ++MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM ++MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx ++MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 ++MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD ++QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN ++BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z ++4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv ++Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ ++kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs ++GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln ++nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh ++3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD ++0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy ++geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 ++ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB ++c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI ++pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU ++dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB ++DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS ++4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs ++o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ ++qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw ++xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM ++rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 ++AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR ++0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY ++o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 ++dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE ++oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== ++-----END CERTIFICATE----- ++# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES ++# 57de0583efd2b26e0361da99da9df4648def7ee8441c3b728afa9bcde0f9b26a ++-----BEGIN CERTIFICATE----- ++MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE ++BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h ++cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 ++MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg ++Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi ++MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 ++thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM ++cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG ++L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i ++NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h ++X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b ++m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy ++Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja ++EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T ++KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF ++6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh ++OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc ++tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd ++IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j ++b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC ++AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw ++ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m ++iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF ++Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ ++hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P ++Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE ++EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV ++1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t ++CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR ++5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw ++f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 ++ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK ++GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV ++-----END CERTIFICATE----- ++# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES ++# 04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef ++-----BEGIN CERTIFICATE----- ++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 ++jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ++-----END CERTIFICATE----- ++# CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN ++# f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae ++-----BEGIN CERTIFICATE----- ++MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU ++MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI ++T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz ++MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF ++SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh ++bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z ++xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ ++spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 ++58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR ++at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll ++5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq ++nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK ++V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ ++pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO ++z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn ++jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ ++WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF ++7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE ++AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 ++YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli ++awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u +++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 ++X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN ++SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo ++P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI +++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz ++znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 ++eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 ++YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy ++r/6zcCwupvI= ++-----END CERTIFICATE----- ++# CN=BJCA Global Root CA2,O=BEIJING CERTIFICATE AUTHORITY,C=CN ++# 574df6931e278039667b720afdc1600fc27eb66dd3092979fb73856487212882 ++-----BEGIN CERTIFICATE----- ++MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw ++CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ ++VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy ++MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ ++TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS ++b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B ++IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ +++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK ++sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD ++AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA ++94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B ++43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== ++-----END CERTIFICATE----- ++# CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE ++# 16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb ++-----BEGIN CERTIFICATE----- ++MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ ++RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD ++VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX ++DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y ++ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy ++VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr ++mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr ++IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK ++mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu ++XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy ++dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye ++jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 ++BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 ++DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 ++9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx ++jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 ++Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz ++ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS ++R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ++-----END CERTIFICATE----- ++# CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO ++# 9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48 ++-----BEGIN CERTIFICATE----- ++MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd ++MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg ++Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow ++TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw ++HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB ++BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr ++6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV ++L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 ++1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx ++MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ ++QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB ++arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr ++Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi ++FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS ++P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN ++9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP ++AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz ++uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h ++9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s ++A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t ++OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo +++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 ++KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 ++DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us ++H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ ++I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 ++5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h ++3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz ++Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= ++-----END CERTIFICATE----- ++# CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO ++# edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d ++-----BEGIN CERTIFICATE----- ++MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd ++MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg ++Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow ++TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw ++HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB ++BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y ++ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E ++N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 ++tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX ++0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c ++/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X ++KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY ++zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS ++O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D ++34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP ++K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 ++AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv ++Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj ++QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV ++cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS ++IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 ++HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa ++O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv ++033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u ++dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE ++kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 ++3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD ++u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq ++4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= ++-----END CERTIFICATE----- ++# CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK ++# e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703 ++-----BEGIN CERTIFICATE----- ++MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV ++BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu ++MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy ++MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx ++EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw ++ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe ++NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH ++PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I ++x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe ++QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR ++yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO ++QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 ++H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ ++QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD ++i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs ++nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 ++rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud ++DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI ++hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM ++tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf ++GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb ++lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka +++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal ++TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i ++nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 ++gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr ++G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os ++zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x ++L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL ++-----END CERTIFICATE----- ++# CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN ++# 5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd ++-----BEGIN CERTIFICATE----- ++MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD ++TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y ++aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx ++MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j ++aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP ++T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 ++sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL ++TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 ++/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp ++7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz ++EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt ++hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP ++a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot ++aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg ++TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV ++PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv ++cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL ++tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd ++BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB ++ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT ++ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL ++jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS ++ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy ++P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 ++xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d ++Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN ++5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe ++/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z ++AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ ++5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ++-----END CERTIFICATE----- ++# CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# 0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66 ++-----BEGIN CERTIFICATE----- ++MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB ++gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G ++A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV ++BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw ++MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl ++YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P ++RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 ++aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 ++UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI ++2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 ++Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp +++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ ++DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O ++nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW ++/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g ++PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u ++QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY ++SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv ++IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ ++RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 ++zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd ++BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB ++ZQ== ++-----END CERTIFICATE----- ++# CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# 1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7 ++-----BEGIN CERTIFICATE----- ++MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL ++MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE ++BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT ++IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw ++MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy ++ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N ++T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv ++biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR ++FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J ++cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW ++BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ ++BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm ++fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv ++GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ++-----END CERTIFICATE----- ++# CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# 52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234 ++-----BEGIN CERTIFICATE----- ++MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB ++hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G ++A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV ++BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 ++MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT ++EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR ++Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh ++dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR ++6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X ++pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC ++9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV ++/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf ++Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z +++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w ++qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah ++SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC ++u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf ++Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq ++crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E ++FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB ++/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl ++wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM ++4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV ++2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna ++FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ ++CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK ++boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke ++jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL ++S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb ++QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl ++0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB ++NVOFBkpdn627G190 ++-----END CERTIFICATE----- ++# CN=Certainly Root E1,O=Certainly,C=US ++# b4585f22e4ac756a4e8612a1361c5d9d031a93fd84febb778fa3068b0fc42dc2 ++-----BEGIN CERTIFICATE----- ++MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw ++CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu ++bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ ++BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s ++eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK +++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 ++QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E ++BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 ++hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm ++ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG ++BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR ++-----END CERTIFICATE----- ++# CN=Certainly Root R1,O=Certainly,C=US ++# 77b82cd8644c4305f7acc5cb156b45675004033d51c60c6202a8e0c33467d3a0 ++-----BEGIN CERTIFICATE----- ++MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw ++PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy ++dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 ++MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 ++YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 ++1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT ++vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed ++aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 ++1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 ++r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 ++cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ ++wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ ++6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA ++2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH ++Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR ++eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB ++/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u ++d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr ++PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d ++8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi ++1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd ++rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di ++taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 ++lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj ++yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn ++Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy ++yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n ++wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 ++OV+KmalBWQewLK8= ++-----END CERTIFICATE----- ++# CN=Certigna Root CA,OU=0002 48146308100036,O=Dhimyotis,C=FR ++# d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168 ++-----BEGIN CERTIFICATE----- ++MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw ++WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw ++MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x ++MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD ++VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX ++BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ++ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO ++ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M ++CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu ++I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm ++TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh ++C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf ++ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz ++IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT ++Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k ++JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 ++hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB ++GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE ++FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of ++1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov ++L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo ++dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr ++aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq ++hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L ++6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG ++HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 ++0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB ++lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi ++o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 ++gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v ++faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 ++Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh ++jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw ++3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= ++-----END CERTIFICATE----- ++# CN=Certigna,O=Dhimyotis,C=FR ++# e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d ++-----BEGIN CERTIFICATE----- ++MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV ++BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X ++DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ ++BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 ++DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 ++QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny ++gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw ++zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q ++130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 ++JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw ++DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw ++ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT ++AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj ++AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG ++9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h ++bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc ++fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu ++HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w ++t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw ++WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ++-----END CERTIFICATE----- ++# CN=Certum EC-384 CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL ++# 6b328085625318aa50d173c98d8bda09d57e27413d114cf787a0f5d06c030cf6 ++-----BEGIN CERTIFICATE----- ++MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw ++CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw ++JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT ++EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 ++WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT ++LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX ++BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE ++KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm ++Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj ++QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 ++EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J ++UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn ++nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= ++-----END CERTIFICATE----- ++# CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL ++# b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804 ++-----BEGIN CERTIFICATE----- ++MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB ++gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu ++QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG ++A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz ++OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ ++VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp ++ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 ++b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA ++DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn ++0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB ++OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE ++fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E ++Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m ++o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i ++sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW ++OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez ++Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS ++adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n ++3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD ++AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC ++AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ ++F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf ++CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 ++XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm ++djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ ++WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb ++AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq ++P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko ++b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj ++XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P ++5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi ++DrW5viSP ++-----END CERTIFICATE----- ++# CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL ++# 5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e ++-----BEGIN CERTIFICATE----- ++MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM ++MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D ++ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU ++cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 ++WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg ++Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw ++IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B ++AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH ++UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM ++TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU ++BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM ++kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x ++AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV ++HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV ++HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y ++sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL ++I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 ++J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY ++VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI ++03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ++-----END CERTIFICATE----- ++# CN=Certum Trusted Root CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL ++# fe7696573855773e37a95e7ad4d9cc96c30157c15d31765ba9b15704e1ae78fd ++-----BEGIN CERTIFICATE----- ++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 ++-----END CERTIFICATE----- ++# CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE ++# e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044 ++-----BEGIN CERTIFICATE----- ++MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw ++CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS ++VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 ++NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG ++A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB ++BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS ++zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 ++QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ ++VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g ++PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf ++Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l ++dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 ++c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO ++PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW ++wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV ++dWNbFJWcHwHP2NVypw87 ++-----END CERTIFICATE----- ++# CN=D-TRUST EV Root CA 1 2020,O=D-Trust GmbH,C=DE ++# 08170d1aa36453901a2f959245e347db0c8d37abaabc56b81aa100dc958970db ++-----BEGIN CERTIFICATE----- ++MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw ++CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS ++VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 ++NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG ++A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB ++BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC ++/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD ++wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 ++OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g ++PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf ++Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l ++dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 ++c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO ++PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA ++y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb ++gfM0agPnIjhQW+0ZT0MW ++-----END CERTIFICATE----- ++# CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE ++# 49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1 ++-----BEGIN CERTIFICATE----- ++MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF ++MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD ++bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha ++ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM ++HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB ++BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 ++UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 ++tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R ++ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM ++lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp ++/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G ++A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G ++A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj ++dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy ++MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl ++cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js ++L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL ++BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni ++acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 ++o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K ++zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 ++PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y ++Johw1+qRzT65ysCQblrGXnRl11z+o+I= ++-----END CERTIFICATE----- ++# CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE ++# eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881 ++-----BEGIN CERTIFICATE----- ++MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF ++MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD ++bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw ++NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV ++BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI ++hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn ++ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 ++3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z ++qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR ++p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 ++HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw ++ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea ++HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw ++Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh ++c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E ++RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt ++dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku ++Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp ++3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 ++nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF ++CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na ++xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX ++KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 ++-----END CERTIFICATE----- ++# CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c ++-----BEGIN CERTIFICATE----- ++MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl ++MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ++d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv ++b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG ++EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl ++cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi ++MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c ++JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP ++mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ ++wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 ++VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ ++AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB ++AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW ++BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun ++pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC ++dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf ++fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm ++NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx ++H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ++-----END CERTIFICATE----- ++# CN=DigiCert Assured ID Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185 ++-----BEGIN CERTIFICATE----- ++MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl ++MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ++d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv ++b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG ++EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl ++cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi ++MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA ++n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc ++biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp ++EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA ++bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu ++YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB ++AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW ++BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI ++QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I ++0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni ++lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 ++B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv ++ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo ++IhNzbM8m9Yop5w== ++-----END CERTIFICATE----- ++# CN=DigiCert Assured ID Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2 ++-----BEGIN CERTIFICATE----- ++MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw ++CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ++ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg ++RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV ++UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu ++Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq ++hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf ++Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q ++RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ ++BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD ++AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY ++JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv ++6pZjamVFkpUBtA== ++-----END CERTIFICATE----- ++# CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161 ++-----BEGIN CERTIFICATE----- ++MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh ++MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ++d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD ++QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT ++MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j ++b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG ++9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB ++CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 ++nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt ++43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P ++T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 ++gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO ++BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR ++TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw ++DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr ++hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg ++06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF ++PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls ++YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk ++CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ++-----END CERTIFICATE----- ++# CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US ++# cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f ++-----BEGIN CERTIFICATE----- ++MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh ++MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ++d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH ++MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT ++MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j ++b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG ++9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI ++2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx ++1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ ++q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz ++tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ ++vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP ++BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV ++5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY ++1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 ++NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG ++Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 ++8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe ++pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl ++MrY= ++-----END CERTIFICATE----- ++# CN=DigiCert Global Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0 ++-----BEGIN CERTIFICATE----- ++MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw ++CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ++ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe ++Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw ++EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x ++IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF ++K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG ++fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO ++Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd ++BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx ++AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ ++oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 ++sycX ++-----END CERTIFICATE----- ++# CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf ++-----BEGIN CERTIFICATE----- ++MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs ++MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ++d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j ++ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL ++MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 ++LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug ++RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm +++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW ++PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM ++xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB ++Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 ++hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg ++EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF ++MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA ++FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec ++nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z ++eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF ++hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 ++Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe ++vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep +++OkuE6N36B9K ++-----END CERTIFICATE----- ++# CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US ++# 018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05 ++-----BEGIN CERTIFICATE----- ++MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw ++CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp ++Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 ++MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ ++bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG ++ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS ++7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp ++0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS ++B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 ++BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ ++LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 ++DXZDjC5Ty3zfDBeWUA== ++-----END CERTIFICATE----- ++# CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US ++# 371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75 ++-----BEGIN CERTIFICATE----- ++MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN ++MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT ++HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN ++NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs ++IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi ++MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ ++ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 ++2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp ++wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM ++pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD ++nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po ++sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx ++Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd ++Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX ++KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe ++XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL ++tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv ++TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN ++AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw ++GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H ++PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF ++O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ ++REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik ++AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv ++/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ ++p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw ++MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF ++qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK ++ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ ++-----END CERTIFICATE----- ++# CN=DigiCert Trusted Root G4,OU=www.digicert.com,O=DigiCert Inc,C=US ++# 552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988 ++-----BEGIN CERTIFICATE----- ++MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi ++MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 ++d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg ++RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV ++UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu ++Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG ++SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y ++ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If ++xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV ++ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO ++DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ ++jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ ++CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi ++EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM ++fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY ++uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK ++chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t ++9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB ++hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ++ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 ++SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd +++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc ++fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa ++sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N ++cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N ++0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie ++4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI ++r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 ++/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm ++gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ ++-----END CERTIFICATE----- ++# CN=Entrust Root Certification Authority - EC1,OU=See www.entrust.net/legal-terms+OU=(c) 2012 Entrust\, Inc. - for authorized use only,O=Entrust\, Inc.,C=US ++# 02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5 ++-----BEGIN CERTIFICATE----- ++MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG ++A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 ++d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu ++dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq ++RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy ++MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD ++VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 ++L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g ++Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD ++ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi ++A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt ++ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH ++Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O ++BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC ++R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX ++hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ++-----END CERTIFICATE----- ++# CN=Entrust Root Certification Authority - G2,OU=See www.entrust.net/legal-terms+OU=(c) 2009 Entrust\, Inc. - for authorized use only,O=Entrust\, Inc.,C=US ++# 43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339 ++-----BEGIN CERTIFICATE----- ++MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC ++VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 ++cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs ++IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz ++dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy ++NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu ++dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt ++dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 ++aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj ++YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK ++AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T ++RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN ++cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW ++wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 ++U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 ++jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP ++BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN ++BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ ++jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ ++Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v ++1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R ++nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH ++VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== ++-----END CERTIFICATE----- ++# CN=Entrust Root Certification Authority - G4,OU=See www.entrust.net/legal-terms+OU=(c) 2015 Entrust\, Inc. - for authorized use only,O=Entrust\, Inc.,C=US ++# db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88 ++-----BEGIN CERTIFICATE----- ++MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw ++gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL ++Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg ++MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw ++BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 ++MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT ++MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 ++c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ ++bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg ++Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B ++AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ ++2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E ++T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j ++5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM ++C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T ++DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX ++wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A ++2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm ++nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 ++dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl ++N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj ++c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD ++VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS ++5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS ++Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr ++hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ ++B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI ++AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw ++H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ ++b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk ++2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol ++IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk ++5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY ++n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== ++-----END CERTIFICATE----- ++# CN=Entrust Root Certification Authority,OU=www.entrust.net/CPS is incorporated by reference+OU=(c) 2006 Entrust\, Inc.,O=Entrust\, Inc.,C=US ++# 73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c ++-----BEGIN CERTIFICATE----- ++MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC ++VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 ++Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW ++KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl ++cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw ++NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw ++NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy ++ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV ++BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ ++KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo ++Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 ++4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 ++KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI ++rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi ++94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB ++sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi ++gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo ++kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE ++vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA ++A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t ++O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua ++AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP ++9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ ++eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m ++0vdXcDazv/wor3ElhVsT/h5/WrQ8 ++-----END CERTIFICATE----- ++# CN=Entrust.net Certification Authority (2048),OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)+OU=(c) 1999 Entrust.net Limited,O=Entrust.net ++# 6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177 ++-----BEGIN CERTIFICATE----- ++MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML ++RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp ++bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 ++IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp ++ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 ++MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 ++LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp ++YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG ++A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp ++MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq ++K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe ++sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX ++MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT ++XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ ++HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH ++4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV ++HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub ++j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo ++U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf ++zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b ++u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ ++bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er ++fF6adulZkMV8gzURZVE= ++-----END CERTIFICATE----- ++# CN=GDCA TrustAUTH R5 ROOT,O=GUANG DONG CERTIFICATE AUTHORITY CO.\,LTD.,C=CN ++# bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893 ++-----BEGIN CERTIFICATE----- ++MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE ++BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ ++IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 ++MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV ++BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w ++HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF ++AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj ++Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj ++TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u ++KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj ++qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm ++MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 ++ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP ++zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk ++L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC ++jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA ++HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC ++AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB ++/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg ++p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm ++DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 ++COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry ++L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf ++JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg ++IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io ++2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV ++09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ ++XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq ++T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe ++MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ++-----END CERTIFICATE----- ++# CN=GLOBALTRUST 2020,O=e-commerce monitoring GmbH,C=AT ++# 9a296a5182d1d451a2e37f439b74daafa267523329f90f9a0d2007c334e23c9a ++-----BEGIN CERTIFICATE----- ++MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG ++A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw ++FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx ++MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u ++aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq ++hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b ++RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z ++YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 ++QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw ++yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ ++BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ ++SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH ++r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 ++4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me ++dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw ++q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 ++nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC ++AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu ++H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA ++VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC ++XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd ++6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf +++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi ++kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 ++wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB ++TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C ++MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn ++4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I ++aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy ++qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== ++-----END CERTIFICATE----- ++# CN=GTS Root R1,O=Google Trust Services LLC,C=US ++# d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf ++-----BEGIN CERTIFICATE----- ++MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw ++CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU ++MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw ++MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp ++Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA ++A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo ++27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w ++Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw ++TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl ++qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH ++szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 ++Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk ++MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 ++wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p ++aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN ++VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID ++AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E ++FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb ++C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe ++QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy ++h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 ++7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J ++ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef ++MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ ++Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT ++6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ ++0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm ++2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb ++bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c ++-----END CERTIFICATE----- ++# CN=GTS Root R2,O=Google Trust Services LLC,C=US ++# 8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8 ++-----BEGIN CERTIFICATE----- ++MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw ++CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU ++MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw ++MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp ++Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA ++A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt ++nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY ++6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu ++MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k ++RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg ++f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV +++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo ++dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW ++Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa ++G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq ++gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID ++AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E ++FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H ++vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 ++0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC ++B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u ++NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg ++yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev ++HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 ++xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR ++TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg ++JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV ++7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl ++6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL ++-----END CERTIFICATE----- ++# CN=GTS Root R3,O=Google Trust Services LLC,C=US ++# 34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48 ++-----BEGIN CERTIFICATE----- ++MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD ++VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG ++A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw ++WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz ++IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi ++AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G ++jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 ++4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW ++BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 ++VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm ++ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X ++-----END CERTIFICATE----- ++# CN=GTS Root R4,O=Google Trust Services LLC,C=US ++# 349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d ++-----BEGIN CERTIFICATE----- ++MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD ++VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG ++A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw ++WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz ++IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi ++AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi ++QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR ++HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW ++BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D ++9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 ++p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD ++-----END CERTIFICATE----- ++# CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE ++# ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99 ++-----BEGIN CERTIFICATE----- ++MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG ++A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv ++b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw ++MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i ++YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT ++aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ ++jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp ++xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp ++1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG ++snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ ++U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 ++9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E ++BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B ++AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz ++yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE ++38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP ++AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad ++DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME ++HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ++-----END CERTIFICATE----- ++# CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE ++# cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058 ++-----BEGIN CERTIFICATE----- ++MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx ++CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD ++ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw ++MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex ++HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA ++IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq ++R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd ++yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud ++DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ ++7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 +++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= ++-----END CERTIFICATE----- ++# CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE ++# 4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9 ++-----BEGIN CERTIFICATE----- ++MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA ++MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD ++VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy ++MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt ++c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB ++AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ ++OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG ++vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud ++316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo ++0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE ++y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF ++zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE +++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN ++I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs ++x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa ++ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC ++4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV ++HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 ++7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg ++JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti ++2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk ++pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF ++FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt ++rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk ++ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 ++u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP ++4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 ++N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 ++vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 ++-----END CERTIFICATE----- ++# CN=GlobalSign,OU=GlobalSign ECC Root CA - R4,O=GlobalSign ++# b085d70b964f191a73e4af0d54ae7a0e07aafdaf9b71dd0862138ab7325a24a2 ++-----BEGIN CERTIFICATE----- ++MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD ++VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh ++bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw ++MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g ++UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT ++BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx ++uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV ++HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ +++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 ++bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm ++-----END CERTIFICATE----- ++# CN=GlobalSign,OU=GlobalSign ECC Root CA - R5,O=GlobalSign ++# 179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924 ++-----BEGIN CERTIFICATE----- ++MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk ++MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH ++bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX ++DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD ++QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu ++MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc ++8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke ++hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD ++VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI ++KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg ++515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO ++xwy8p2Fp8fc74SrL+SvzZpA3 ++-----END CERTIFICATE----- ++# CN=GlobalSign,OU=GlobalSign Root CA - R3,O=GlobalSign ++# cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b ++-----BEGIN CERTIFICATE----- ++MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G ++A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp ++Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 ++MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG ++A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI ++hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 ++RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT ++gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm ++KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd ++QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ ++XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw ++DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o ++LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU ++RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp ++jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK ++6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX ++mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs ++Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH ++WD9f ++-----END CERTIFICATE----- ++# CN=GlobalSign,OU=GlobalSign Root CA - R6,O=GlobalSign ++# 2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69 ++-----BEGIN CERTIFICATE----- ++MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg ++MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh ++bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx ++MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET ++MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ ++KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI ++xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k ++ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD ++aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw ++LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw ++1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX ++k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 ++SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h ++bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n ++WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY ++rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce ++MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD ++AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu ++bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN ++nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt ++Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 ++55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj ++vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf ++cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz ++oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp ++nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs ++pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v ++JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R ++8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 ++5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= ++-----END CERTIFICATE----- ++# CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\, Inc.,L=Scottsdale,ST=Arizona,C=US ++# 45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda ++-----BEGIN CERTIFICATE----- ++MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx ++EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT ++EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp ++ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz ++NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH ++EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE ++AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw ++DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD ++E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH ++/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy ++DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh ++GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR ++tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA ++AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE ++FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX ++WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu ++9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr ++gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo ++2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO ++LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI ++4uJEvlz36hz1 ++-----END CERTIFICATE----- ++# CN=HARICA TLS ECC Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR ++# 3f99cc474acfce4dfed58794665e478d1547739f2e780f1bb4ca9b133097d401 ++-----BEGIN CERTIFICATE----- ++MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw ++CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh ++cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v ++dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG ++A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj ++aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg ++Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 ++KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y ++STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw ++AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD ++AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw ++SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN ++nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps ++-----END CERTIFICATE----- ++# CN=HARICA TLS RSA Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR ++# d95d0e8eda79525bf9beb11b14d2100d3294985f0c62d9fabd9cd999eccb7b1d ++-----BEGIN CERTIFICATE----- ++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 ++63ZTGI0RmLo= ++-----END CERTIFICATE----- ++# CN=Hellenic Academic and Research Institutions ECC RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR ++# 44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833 ++-----BEGIN CERTIFICATE----- ++MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN ++BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl ++c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl ++bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv ++b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ ++BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj ++YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 ++MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 ++dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg ++QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa ++jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC ++MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi ++C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep ++lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof ++TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ++-----END CERTIFICATE----- ++# CN=Hellenic Academic and Research Institutions RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR ++# a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36 ++-----BEGIN CERTIFICATE----- ++MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix ++DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k ++IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT ++N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v ++dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG ++A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh ++ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx ++QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 ++dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC ++AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA ++4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 ++AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 ++4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C ++ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV ++9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD ++gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 ++Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq ++NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko ++LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc ++Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV ++HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd ++ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I ++XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI ++M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot ++9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V ++Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea ++j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh ++X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ ++l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf ++bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 ++pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK ++e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 ++vm9qp/UsQu0yrbYhnr68 ++-----END CERTIFICATE----- ++# CN=HiPKI Root CA - G1,O=Chunghwa Telecom Co.\, Ltd.,C=TW ++# f015ce3cc239bfef064be9f1d2c417e1a0264a0a94be1f0c8d121864eb6949cc ++-----BEGIN CERTIFICATE----- ++MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP ++MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 ++ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa ++Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 ++YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx ++MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw ++qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv ++Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 ++lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz ++Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ ++KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK ++FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj ++HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr ++y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ ++/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM ++a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 ++fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV ++HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG ++SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi ++7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc ++SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza ++ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc ++XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg ++iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho ++L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF ++Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr ++kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ ++vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU ++YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== ++-----END CERTIFICATE----- ++# CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK ++# 5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6 ++-----BEGIN CERTIFICATE----- ++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 ++mpv0 ++-----END CERTIFICATE----- ++# CN=ISRG Root X1,O=Internet Security Research Group,C=US ++# 96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6 ++-----BEGIN CERTIFICATE----- ++MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw ++TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh ++cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 ++WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu ++ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY ++MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc ++h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ ++0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U ++A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW ++T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH ++B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC ++B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv ++KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn ++OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn ++jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw ++qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI ++rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV ++HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq ++hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL ++ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ ++3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK ++NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 ++ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur ++TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC ++jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc ++oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq ++4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA ++mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d ++emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ++-----END CERTIFICATE----- ++# CN=ISRG Root X2,O=Internet Security Research Group,C=US ++# 69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470 ++-----BEGIN CERTIFICATE----- ++MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw ++CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg ++R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 ++MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT ++ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw ++EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW +++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 ++ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T ++AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI ++zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW ++tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 ++/q4AaOeMSQ+2b1tbFfLn ++-----END CERTIFICATE----- ++# CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US ++# 5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae ++-----BEGIN CERTIFICATE----- ++MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK ++MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu ++VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw ++MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw ++JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG ++SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT ++3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU +++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp ++S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 ++bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi ++T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL ++vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK ++Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK ++dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT ++c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv ++l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N ++iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB ++/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD ++ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH ++6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt ++LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 ++nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 +++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK ++W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT ++AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq ++l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG ++4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ ++mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A ++7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H ++-----END CERTIFICATE----- ++# CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US ++# 30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f ++-----BEGIN CERTIFICATE----- ++MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN ++MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu ++VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN ++MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 ++MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi ++MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 ++ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy ++RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS ++bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF ++/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R ++3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw ++EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy ++9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V ++GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ ++2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV ++WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD ++W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ ++BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN ++AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj ++t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV ++DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 ++TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G ++lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW ++mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df ++WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 +++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ ++tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA ++GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv ++8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c ++-----END CERTIFICATE----- ++# CN=Izenpe.com,O=IZENPE S.A.,C=ES ++# 2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f ++-----BEGIN CERTIFICATE----- ++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 ++-----END CERTIFICATE----- ++# CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU,1.2.840.113549.1.9.1=#0c10696e666f40652d737a69676e6f2e6875 ++# 3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378 ++-----BEGIN CERTIFICATE----- ++MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD ++VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 ++ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G ++CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y ++OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx ++FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp ++Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o ++dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP ++kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc ++cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U ++fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 ++N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC ++xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 +++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G ++A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM ++Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG ++SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h ++mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk ++ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 ++tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c ++2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t ++HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW ++-----END CERTIFICATE----- ++# CN=Microsoft ECC Root Certificate Authority 2017,O=Microsoft Corporation,C=US ++# 358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02 ++-----BEGIN CERTIFICATE----- ++MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw ++CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD ++VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw ++MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV ++UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy ++b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq ++hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR ++ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb ++hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E ++BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 ++FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV ++L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB ++iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= ++-----END CERTIFICATE----- ++# CN=Microsoft RSA Root Certificate Authority 2017,O=Microsoft Corporation,C=US ++# c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0 ++-----BEGIN CERTIFICATE----- ++MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl ++MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw ++NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 ++IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG ++EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N ++aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi ++MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ ++Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 ++ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 ++HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm ++gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ ++jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc ++aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG ++YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 ++W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K ++UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH +++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q ++W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ ++BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC ++NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC ++LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC ++gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 ++tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh ++SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 ++TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 ++pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR ++xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp ++GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 ++dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN ++AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB ++RA+GsCyRxj3qrg+E ++-----END CERTIFICATE----- ++# CN=NAVER Global Root Certification Authority,O=NAVER BUSINESS PLATFORM Corp.,C=KR ++# 88f438dcf8ffd1fa8f429115ffe5f82ae1e06e0c70c375faad717b34a49e7265 ++-----BEGIN CERTIFICATE----- ++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 ++9XXeifdy ++-----END CERTIFICATE----- ++# CN=NetLock Arany (Class Gold) FΕ‘tanΓΊsΓ­tvΓ‘ny,OU=TanΓΊsΓ­tvΓ‘nykiadΓ³k (Certification Services),O=NetLock Kft.,L=Budapest,C=HU ++# 6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98 ++-----BEGIN CERTIFICATE----- ++MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG ++EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 ++MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl ++cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR ++dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB ++pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM ++b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm ++aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz ++IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A ++MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT ++lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz ++AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 ++VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG ++ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 ++BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG ++AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M ++U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh ++bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C +++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC ++bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F ++uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 ++XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ++-----END CERTIFICATE----- ++# CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH ++# 6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6 ++-----BEGIN CERTIFICATE----- ++MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt ++MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg ++Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i ++YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x ++CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG ++b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh ++bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 ++HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx ++WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX ++1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk ++u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P ++99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r ++M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw ++AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB ++BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh ++cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 ++gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO ++ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf ++aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic ++Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ++-----END CERTIFICATE----- ++# CN=OISTE WISeKey Global Root GC CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH ++# 8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d ++-----BEGIN CERTIFICATE----- ++MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw ++CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 ++bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg ++Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ ++BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu ++ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS ++b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni ++eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W ++p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E ++BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T ++rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV ++57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg ++Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 ++-----END CERTIFICATE----- ++# CN=QuoVadis Root CA 1 G3,O=QuoVadis Limited,C=BM ++# 8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74 ++-----BEGIN CERTIFICATE----- ++MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL ++BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc ++BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 ++MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM ++aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG ++SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV ++wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe ++rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 ++68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh ++4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp ++UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o ++abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc ++3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G ++KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt ++hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO ++Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt ++zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB ++BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD ++ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC ++MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 ++cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN ++qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 ++YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv ++b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 ++8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k ++NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj ++ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp ++q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt ++nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD ++-----END CERTIFICATE----- ++# CN=QuoVadis Root CA 2 G3,O=QuoVadis Limited,C=BM ++# 8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840 ++-----BEGIN CERTIFICATE----- ++MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL ++BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc ++BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 ++MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM ++aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG ++SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf ++qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW ++n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym ++c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ ++O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 ++o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j ++IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq ++IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz ++8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh ++vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l ++7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG ++cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB ++BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD ++ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 ++AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC ++roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga ++W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n ++lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE +++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV ++csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd ++dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg ++KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM ++HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 ++WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M ++-----END CERTIFICATE----- ++# CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM ++# 85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86 ++-----BEGIN CERTIFICATE----- ++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 ++8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ++-----END CERTIFICATE----- ++# CN=QuoVadis Root CA 3 G3,O=QuoVadis Limited,C=BM ++# 88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46 ++-----BEGIN CERTIFICATE----- ++MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL ++BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc ++BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 ++MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM ++aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG ++SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR ++/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu ++FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR ++U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c ++ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR ++FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k ++A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw ++eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl ++sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp ++VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q ++A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ ++ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB ++BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD ++ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px ++KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI ++FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv ++oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg ++u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP ++0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf ++3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl ++8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ ++DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN ++PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ ++ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 ++-----END CERTIFICATE----- ++# CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM ++# 18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35 ++-----BEGIN CERTIFICATE----- ++MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x ++GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv ++b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV ++BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W ++YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM ++V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB ++4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr ++H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd ++8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv ++vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT ++mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe ++btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc ++T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt ++WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ ++c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A ++4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD ++VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG ++CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 ++aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 ++aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu ++dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw ++czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G ++A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC ++TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg ++Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 ++7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem ++d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd +++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B ++4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN ++t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x ++DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 ++k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s ++zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j ++Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT ++mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK ++4SVhM7JZG+Ju1zdXtg2pEto= ++-----END CERTIFICATE----- ++# CN=SSL.com EV Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US ++# 22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8 ++-----BEGIN CERTIFICATE----- ++MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC ++VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T ++U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp ++Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx ++NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv ++dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv ++bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 ++AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA ++VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku ++WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP ++MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX ++5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ ++ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg ++h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ++-----END CERTIFICATE----- ++# CN=SSL.com EV Root Certification Authority RSA R2,O=SSL Corporation,L=Houston,ST=Texas,C=US ++# 2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c ++-----BEGIN CERTIFICATE----- ++MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV ++BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE ++CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy ++dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy ++MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G ++A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD ++DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy ++MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq ++M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf ++OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa ++4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 ++HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR ++aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA ++b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ ++Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV ++PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO ++pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu ++UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY ++MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV ++HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 ++9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW ++s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 ++Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg ++cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM ++79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz ++/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt ++ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm ++Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK ++QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ ++w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi ++S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 ++mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ++-----END CERTIFICATE----- ++# CN=SSL.com Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US ++# 3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65 ++-----BEGIN CERTIFICATE----- ++MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC ++VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T ++U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 ++aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz ++WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 ++b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS ++b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB ++BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI ++7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg ++CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud ++EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD ++VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T ++kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ ++gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ++-----END CERTIFICATE----- ++# CN=SSL.com Root Certification Authority RSA,O=SSL Corporation,L=Houston,ST=Texas,C=US ++# 85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69 ++-----BEGIN CERTIFICATE----- ++MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE ++BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK ++DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp ++Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz ++OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv ++dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv ++bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN ++AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R ++xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX ++qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC ++C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 ++6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh ++/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF ++YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E ++JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc ++US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 ++ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm +++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi ++M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV ++HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G ++A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV ++cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc ++Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs ++PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ ++q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 ++cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr ++a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I ++H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y ++K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu ++nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf ++oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY ++Ic2wBlX7Jz9TkHCpBB5XJ7k= ++-----END CERTIFICATE----- ++# CN=SSL.com TLS ECC Root CA 2022,O=SSL Corporation,C=US ++# c32ffd9f46f936d16c3673990959434b9ad60aafbb9e7cf33654f144cc1ba143 ++-----BEGIN CERTIFICATE----- ++MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw ++CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT ++U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 ++MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh ++dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG ++ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm ++acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN ++SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME ++GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW ++uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp ++15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN ++b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== ++-----END CERTIFICATE----- ++# CN=SSL.com TLS RSA Root CA 2022,O=SSL Corporation,C=US ++# 8faf7d2e2cb4709bb8e0b33666bf75a5dd45b5de480f8ea8d4bfe6bebc17f2ed ++-----BEGIN CERTIFICATE----- ++MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO ++MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD ++DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX ++DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw ++b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC ++AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP ++L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY ++t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins ++S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 ++PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO ++L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 ++R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w ++dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS +++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS ++d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG ++AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f ++gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j ++BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z ++NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt ++hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM ++QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf ++R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ ++DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW ++P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy ++lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq ++bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w ++AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q ++r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji ++Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU ++98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= ++-----END CERTIFICATE----- ++# CN=SZAFIR ROOT CA2,O=Krajowa Izba Rozliczeniowa S.A.,C=PL ++# a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe ++-----BEGIN CERTIFICATE----- ++MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL ++BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 ++ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw ++NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L ++cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg ++Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN ++QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT ++3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw ++3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 ++3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 ++BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN ++XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD ++AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF ++AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw ++8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG ++nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP ++oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy ++d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg ++LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== ++-----END CERTIFICATE----- ++# CN=Sectigo Public Server Authentication Root E46,O=Sectigo Limited,C=GB ++# c90f26f0fb1b4018b22227519b5ca2b53e2ca5b3be5cf18efe1bef47380c5383 ++-----BEGIN CERTIFICATE----- ++MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw ++CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T ++ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN ++MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG ++A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT ++ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA ++IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC ++WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ ++6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B ++Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa ++qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q ++4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== ++-----END CERTIFICATE----- ++# CN=Sectigo Public Server Authentication Root R46,O=Sectigo Limited,C=GB ++# 7bb647a62aeeac88bf257aa522d01ffea395e0ab45c73f93f65654ec38f25a06 ++-----BEGIN CERTIFICATE----- ++MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf ++MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD ++Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw ++HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY ++MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp ++YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB ++AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa ++ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz ++SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf ++iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X ++ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 ++IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS ++VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE ++SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu +++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt ++8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L ++HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt ++zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P ++AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c ++mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ ++YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 ++gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA ++Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB ++JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX ++DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui ++TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 ++dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 ++LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp ++0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY ++QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL ++-----END CERTIFICATE----- ++# CN=Secure Global CA,O=SecureTrust Corporation,C=US ++# 4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69 ++-----BEGIN CERTIFICATE----- ++MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK ++MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x ++GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx ++MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg ++Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG ++SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ ++iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa ++/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ ++jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI ++HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 ++sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w ++gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF ++MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw ++KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG ++AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L ++URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO ++H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm ++I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY ++iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc ++f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ++-----END CERTIFICATE----- ++# CN=SecureSign RootCA11,O=Japan Certification Services\, Inc.,C=JP ++# bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612 ++-----BEGIN CERTIFICATE----- ++MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr ++MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG ++A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 ++MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp ++Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD ++QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz ++i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 ++h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV ++MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 ++UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni ++8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC ++h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD ++VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB ++AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm ++KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ ++X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr ++QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 ++pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN ++QSdJQO7e5iNEOdyhIta6A/I= ++-----END CERTIFICATE----- ++# CN=SecureTrust CA,O=SecureTrust Corporation,C=US ++# f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73 ++-----BEGIN CERTIFICATE----- ++MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI ++MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x ++FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz ++MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv ++cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN ++AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz ++Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO ++0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao ++wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj ++7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS ++8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT ++BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB ++/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg ++JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC ++NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 ++6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ ++3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm ++D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS ++CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR ++3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ++-----END CERTIFICATE----- ++# CN=Security Communication ECC RootCA1,O=SECOM Trust Systems CO.\,LTD.,C=JP ++# e74fbda55bd564c473a36b441aa799c8a68e077440e8288b9fa1e50e4bbaca11 ++-----BEGIN CERTIFICATE----- ++MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT ++AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD ++VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx ++NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT ++HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 ++IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi ++AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl ++dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK ++ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E ++BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu ++9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O ++be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= ++-----END CERTIFICATE----- ++# CN=Security Communication RootCA3,O=SECOM Trust Systems CO.\,LTD.,C=JP ++# 24a55c2ab051442d0617766541239a4ad032d7c55175aa34ffde2fbc4f5c5294 ++-----BEGIN CERTIFICATE----- ++MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV ++BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw ++JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2 ++MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc ++U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg ++Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC ++CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r ++CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA ++lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG ++TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7 ++9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7 ++8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4 ++g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we ++GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst +++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M ++0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ ++T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw ++HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP ++BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS ++YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA ++FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd ++9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI ++UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+ ++OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke ++gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf ++iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV ++nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD ++2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI// ++1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad ++TdJ0MN1kURXbg4NR16/9M51NZg== ++-----END CERTIFICATE----- ++# CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US ++# 2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5 ++-----BEGIN CERTIFICATE----- ++MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx ++EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT ++HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs ++ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw ++MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 ++b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj ++aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp ++Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ++ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg ++nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 ++HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N ++Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN ++dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 ++HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO ++BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G ++CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU ++sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 ++4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg ++8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K ++pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 ++mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ++-----END CERTIFICATE----- ++# CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US ++# 568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5 ++-----BEGIN CERTIFICATE----- ++MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx ++EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT ++HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs ++ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 ++MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD ++VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy ++ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy ++dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI ++hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p ++OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 ++8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K ++Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe ++hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk ++6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw ++DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q ++AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI ++bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB ++ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z ++qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd ++iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn ++0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN ++sSi6 ++-----END CERTIFICATE----- ++# CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH ++# 62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95 ++-----BEGIN CERTIFICATE----- ++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 ++-----END CERTIFICATE----- ++# CN=SwissSign Silver CA - G2,O=SwissSign AG,C=CH ++# be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5 ++-----BEGIN CERTIFICATE----- ++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 ++-----END CERTIFICATE----- ++# CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE ++# 91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552 ++-----BEGIN CERTIFICATE----- ++MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx ++KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd ++BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl ++YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 ++OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy ++aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 ++ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G ++CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd ++AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC ++FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi ++1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq ++jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ ++wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj ++QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ ++WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy ++NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC ++uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw ++IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 ++g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN ++9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP ++BSeOE6Fuwg== ++-----END CERTIFICATE----- ++# CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE ++# fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd ++-----BEGIN CERTIFICATE----- ++MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx ++KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd ++BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl ++YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 ++OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy ++aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 ++ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G ++CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN ++8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ ++RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 ++hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 ++ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM ++EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj ++QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 ++A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy ++WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ ++1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 ++6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT ++91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml ++e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p ++TpPDpFQUWw== ++-----END CERTIFICATE----- ++# CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1,OU=Kamu Sertifikasyon Merkezi - Kamu SM,O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK,L=Gebze - Kocaeli,C=TR ++# 46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716 ++-----BEGIN CERTIFICATE----- ++MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx ++GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp ++bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w ++KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 ++BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy ++dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG ++EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll ++IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU ++QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT ++TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg ++LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 ++a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr ++LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr ++N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X ++YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ ++iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f ++AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH ++V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL ++BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh ++AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf ++IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 ++lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c ++8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf ++lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ++-----END CERTIFICATE----- ++# CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW ++# 59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b ++-----BEGIN CERTIFICATE----- ++MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx ++EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT ++VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 ++NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT ++B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG ++SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF ++10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz ++0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh ++MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH ++zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc ++46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 ++yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi ++laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP ++oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA ++BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE ++qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm ++4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB ++/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL ++1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn ++LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF ++H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo ++RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ ++nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh ++15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW ++6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW ++nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j ++wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz ++aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy ++KwbQBM0= ++-----END CERTIFICATE----- ++# CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW ++# bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44 ++-----BEGIN CERTIFICATE----- ++MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES ++MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU ++V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz ++WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO ++LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm ++aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB ++AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE ++AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH ++K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX ++RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z ++rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx ++3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV ++HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq ++hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC ++MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls ++XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D ++lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn ++aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ ++YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ++-----END CERTIFICATE----- ++# CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI ++# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c ++-----BEGIN CERTIFICATE----- ++MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx ++CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE ++AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 ++NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ ++MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP ++ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq ++AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 ++vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 ++lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD ++n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT ++7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o ++6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC ++TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 ++WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R ++DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI ++pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj ++YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy ++rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw ++AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ ++8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi ++0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM ++A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS ++SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K ++TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF ++6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er ++3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt ++Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT ++VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW ++ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA ++rBPuUBQemMc= ++-----END CERTIFICATE----- ++# CN=TeliaSonera Root CA v1,O=TeliaSonera ++# dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389 ++-----BEGIN CERTIFICATE----- ++MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw ++NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv ++b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD ++VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 ++MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F ++VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 ++7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X ++Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ ++/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs ++81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm ++dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe ++Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu ++sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 ++pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs ++slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ ++arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD ++VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG ++9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl ++dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx ++0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj ++TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed ++Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 ++Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI ++OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 ++vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW ++t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn ++HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx ++SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ++-----END CERTIFICATE----- ++# CN=Trustwave Global Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US ++# 97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8 ++-----BEGIN CERTIFICATE----- ++MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw ++CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x ++ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 ++c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx ++OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI ++SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI ++b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp ++Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB ++ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn ++swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu ++7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 ++1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW ++80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP ++JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l ++RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw ++hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 ++coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc ++BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n ++twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud ++EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud ++DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W ++0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe ++uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q ++lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB ++aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE ++sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT ++MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe ++qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh ++VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 ++h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 ++EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK ++yeC2nOnOcXHebD8WpHk= ++-----END CERTIFICATE----- ++# CN=Trustwave Global ECC P256 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US ++# 945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4 ++-----BEGIN CERTIFICATE----- ++MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD ++VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf ++BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 ++YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x ++NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G ++A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 ++d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF ++Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG ++SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN ++FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w ++DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw ++CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh ++DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 ++-----END CERTIFICATE----- ++# CN=Trustwave Global ECC P384 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US ++# 55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097 ++-----BEGIN CERTIFICATE----- ++MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD ++VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf ++BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 ++YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x ++NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G ++A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 ++d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF ++Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB ++BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ ++j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF ++1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G ++A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 ++AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC ++MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu ++Sw== ++-----END CERTIFICATE----- ++# CN=TunTrust Root CA,O=Agence Nationale de Certification Electronique,C=TN ++# 2e44102ab58cb85419451c8e19d9acf3662cafbc614b6a53960a30f7d0e2eb41 ++-----BEGIN CERTIFICATE----- ++MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL ++BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg ++Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv ++b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG ++EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u ++IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ ++KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ ++n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd ++2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF ++VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ ++GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF ++li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU ++r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 ++eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb ++MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg ++jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB ++7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW ++5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE ++ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 ++90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z ++xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu ++QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 ++FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH ++22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP ++xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn ++dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 ++Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b ++nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ ++CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH ++u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj ++d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= ++-----END CERTIFICATE----- ++# CN=UCA Extended Validation Root,O=UniTrust,C=CN ++# d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24 ++-----BEGIN CERTIFICATE----- ++MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH ++MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF ++eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx ++MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV ++BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB ++AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog ++D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS ++sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop ++O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk ++sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi ++c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj ++VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz ++KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ ++TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G ++sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs ++1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD ++fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T ++AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN ++l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR ++ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ ++VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 ++c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp ++4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s ++t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj ++2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO ++vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C ++xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx ++cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM ++fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax ++-----END CERTIFICATE----- ++# CN=UCA Global G2 Root,O=UniTrust,C=CN ++# 9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c ++-----BEGIN CERTIFICATE----- ++MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 ++MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH ++bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x ++CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds ++b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr ++b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 ++kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm ++VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R ++VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc ++C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj ++tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY ++D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv ++j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl ++NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 ++iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP ++O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ ++BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV ++ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj ++L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 ++1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl ++1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU ++b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV ++PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj ++y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb ++EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg ++DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI +++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy ++YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX ++UB+K+wb1whnw0A== ++-----END CERTIFICATE----- ++# CN=USERTrust ECC Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US ++# 4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a ++-----BEGIN CERTIFICATE----- ++MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL ++MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl ++eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT ++JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx ++MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT ++Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg ++VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm ++aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo ++I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng ++o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G ++A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD ++VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB ++zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW ++RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ++-----END CERTIFICATE----- ++# CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US ++# e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2 ++-----BEGIN CERTIFICATE----- ++MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB ++iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl ++cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV ++BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw ++MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV ++BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU ++aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy ++dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK ++AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B ++3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY ++tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ ++Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 ++VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT ++79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 ++c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT ++Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l ++c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee ++UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE ++Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd ++BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G ++A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF ++Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO ++VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 ++ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs ++8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR ++iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze ++Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ ++XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ ++qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB ++VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB ++L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG ++jjxDah2nGN59PRbxYvnKkKj9 ++-----END CERTIFICATE----- ++# CN=XRamp Global Certification Authority,OU=www.xrampsecurity.com,O=XRamp Security Services Inc,C=US ++# cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2 ++-----BEGIN CERTIFICATE----- ++MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB ++gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk ++MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY ++UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx ++NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 ++dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy ++dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB ++dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 ++38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP ++KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q ++DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 ++qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa ++JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi ++PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P ++BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs ++jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 ++eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD ++ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR ++vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt ++qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa ++IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy ++i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ ++O+7ETPTsJ3xCwnR8gooJybQDJbw= ++-----END CERTIFICATE----- ++# CN=e-Szigno Root CA 2017,O=Microsec Ltd.,L=Budapest,C=HU,2.5.4.97=#130e56415448552d3233353834343937 ++# beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99 ++-----BEGIN CERTIFICATE----- ++MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV ++BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk ++LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv ++b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ ++BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg ++THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v ++IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv ++xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H ++Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G ++A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB ++eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo ++jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ +++efcMQ== ++-----END CERTIFICATE----- ++# CN=emSign ECC Root CA - C3,OU=emSign PKI,O=eMudhra Inc,C=US ++# bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3 ++-----BEGIN CERTIFICATE----- ++MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG ++EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx ++IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw ++MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln ++biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND ++IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci ++MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti ++sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O ++BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB ++Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c ++3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J ++0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== ++-----END CERTIFICATE----- ++# CN=emSign ECC Root CA - G3,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN ++# 86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b ++-----BEGIN CERTIFICATE----- ++MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG ++EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo ++bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g ++RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ ++TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s ++b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw ++djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 ++WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS ++fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB ++zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq ++hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB ++CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD +++JbNR6iC8hZVdyR+EhCVBCyj ++-----END CERTIFICATE----- ++# CN=emSign Root CA - C1,OU=emSign PKI,O=eMudhra Inc,C=US ++# 125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f ++-----BEGIN CERTIFICATE----- ++MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG ++A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg ++SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw ++MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln ++biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v ++dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ ++BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ ++HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH ++3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH ++GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c ++xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 ++aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq ++TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL ++BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 ++/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 ++kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG ++YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT +++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo ++WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= ++-----END CERTIFICATE----- ++# CN=emSign Root CA - G1,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN ++# 40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367 ++-----BEGIN CERTIFICATE----- ++MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD ++VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU ++ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH ++MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO ++MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv ++Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN ++BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz ++f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO ++8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq ++d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM ++tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt ++Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB ++o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD ++AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x ++PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM ++wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d ++GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH ++6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby ++RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx ++iN66zB+Afko= ++-----END CERTIFICATE----- ++# CN=vTrus ECC Root CA,O=iTrusChina Co.\,Ltd.,C=CN ++# 30fbba2c32238e2a98547af97931e550428b9b3f1c8eeb6633dcfa86c5b27dd3 ++-----BEGIN CERTIFICATE----- ++MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw ++RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY ++BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz ++MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u ++LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF ++K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 ++v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd ++e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD ++VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw ++V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA ++AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG ++GJTO ++-----END CERTIFICATE----- ++# CN=vTrus Root CA,O=iTrusChina Co.\,Ltd.,C=CN ++# 8a71de6559336f426c26e53880d00d88a18da4c6a91f0dcb6194e206c5c96387 ++-----BEGIN CERTIFICATE----- ++MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL ++BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x ++FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx ++MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s ++THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD ++ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc ++IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU ++AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ ++GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 ++8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH ++flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt ++J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim ++0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN ++pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ ++UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW ++OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB ++AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E ++BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet ++8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd ++nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j ++bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM ++Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv ++TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS ++S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr ++I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 ++b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB ++UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P ++Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven ++sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= ++-----END CERTIFICATE----- ++# OU=AC RAIZ FNMT-RCM,O=FNMT-RCM,C=ES ++# ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa ++-----BEGIN CERTIFICATE----- ++MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx ++CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ ++WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ ++BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG ++Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ ++yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf ++BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz ++WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF ++tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z ++374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC ++IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL ++mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 ++wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS ++MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 ++ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet ++UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw ++AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H ++YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 ++LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD ++nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 ++RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM ++LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf ++77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N ++JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm ++fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp ++6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp ++1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B ++9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok ++RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv ++uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ++-----END CERTIFICATE----- ++# OU=Go Daddy Class 2 Certification Authority,O=The Go Daddy Group\, Inc.,C=US ++# c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4 ++-----BEGIN CERTIFICATE----- ++MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh ++MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE ++YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 ++MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo ++ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg ++MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN ++ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA ++PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w ++wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi ++EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY ++avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ ++YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE ++sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h ++/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 ++IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj ++YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD ++ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy ++OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P ++TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ ++HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER ++dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ++ReYNnyicsbkqWletNw+vHX/bvZ8= ++-----END CERTIFICATE----- ++# OU=Security Communication RootCA1,O=SECOM Trust.net,C=JP ++# e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c ++-----BEGIN CERTIFICATE----- ++MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY ++MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t ++dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 ++WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD ++VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 ++DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 ++9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ ++DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 ++Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N ++QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ ++xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G ++A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T ++AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG ++kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr ++Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 ++Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU ++JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot ++RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== ++-----END CERTIFICATE----- ++# OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\,LTD.,C=JP ++# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6 ++-----BEGIN CERTIFICATE----- ++MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl ++MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe ++U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX ++DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy ++dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj ++YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV ++OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr ++zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM ++VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ ++hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO ++ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw ++awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs ++OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 ++DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF ++coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc ++okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 ++t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy ++1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ ++SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ++-----END CERTIFICATE----- ++# OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\, Inc.,C=US ++# 1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658 ++-----BEGIN CERTIFICATE----- ++MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl ++MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp ++U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw ++NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE ++ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp ++ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 ++DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf ++8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN +++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 ++X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa ++K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA ++1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G ++A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR ++zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 ++YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD ++bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w ++DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 ++L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D ++eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl ++xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp ++VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY ++WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ++-----END CERTIFICATE----- ++# OU=certSIGN ROOT CA G2,O=CERTSIGN SA,C=RO ++# 657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305 ++-----BEGIN CERTIFICATE----- ++MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV ++BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g ++Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ ++BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ ++R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF ++dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw ++vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ ++uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp ++n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs ++cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW ++xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P ++rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF ++DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx ++DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy ++LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C ++eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB ++/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ ++d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq ++kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC ++b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl ++qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 ++OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c ++NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk ++ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO ++pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj ++03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk ++PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE ++1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX ++QRBdJ3NghVdJIgc= ++-----END CERTIFICATE----- ++# OU=certSIGN ROOT CA,O=certSIGN,C=RO ++# eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb ++-----BEGIN CERTIFICATE----- ++MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT ++AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD ++QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP ++MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC ++ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do ++0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ ++UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d ++RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ ++OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv ++JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C ++AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O ++BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ ++LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY ++MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ ++44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I ++Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw ++i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN ++9u6wWk5JRFRYX0KD ++-----END CERTIFICATE----- ++# OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\, Ltd.,C=TW ++# c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5 ++-----BEGIN CERTIFICATE----- ++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 ++hNQ+IIX3Sj0rnP0qCglN6oH4EZw= ++-----END CERTIFICATE----- ++# SERIALNUMBER=G63287510,CN=ANF Secure Server Root CA,OU=ANF CA Raiz,O=ANF Autoridad de Certificacion,C=ES ++# fb8fec759169b9106b1e511644c618c51304373f6c0643088d8beffd1b997599 ++-----BEGIN CERTIFICATE----- ++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 ++-----END CERTIFICATE----- ++` +diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go b/ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go +new file mode 100644 +index 00000000000000..31413595fa8826 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go +@@ -0,0 +1,31 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build go1.20 ++ ++// Package fallback embeds a set of fallback X.509 trusted roots in the ++// application by automatically invoking [x509.SetFallbackRoots]. This allows ++// the application to work correctly even if the operating system does not ++// provide a verifier or system roots pool. ++// ++// To use it, import the package like ++// ++// import _ "golang.org/x/crypto/x509roots/fallback" ++// ++// It's recommended that only binaries, and not libraries, import this package. ++// ++// This package must be kept up to date for security and compatibility reasons. ++// Use govulncheck to be notified of when new versions of the package are ++// available. ++package fallback ++ ++import "crypto/x509" ++ ++func init() { ++ p := x509.NewCertPool() ++ for _, c := range bundle { ++ p.AddCert(c) ++ } ++ x509.SetFallbackRoots(p) ++} +diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod b/ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod +new file mode 100644 +index 00000000000000..d8974bf9fe0a79 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod +@@ -0,0 +1,3 @@ ++module golang.org/x/crypto/x509roots/fallback ++ ++go 1.20 +diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go b/ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go +new file mode 100644 +index 00000000000000..d946a527db79a4 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go +@@ -0,0 +1,8 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package goissue52287 is an empty internal package. ++// It exists only to work around go.dev/issue/52287 and ++// can be removed after Go 1.19 stops being supported. ++package goissue52287 +diff --git a/ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go b/ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go +new file mode 100644 +index 00000000000000..c22d1b0c381b64 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go +@@ -0,0 +1,135 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build generate ++// +build generate ++ ++//go:generate go run gen_fallback_bundle.go ++ ++package main ++ ++import ( ++ "bytes" ++ "crypto/sha256" ++ "encoding/pem" ++ "flag" ++ "fmt" ++ "go/format" ++ "io" ++ "log" ++ "net/http" ++ "os" ++ "sort" ++ ++ "golang.org/x/crypto/x509roots/nss" ++) ++ ++const tmpl = `// Code generated by gen_fallback_bundle.go; DO NOT EDIT. ++ ++//go:build go1.20 ++ ++package fallback ++ ++import "crypto/x509" ++import "encoding/pem" ++ ++func mustParse(b []byte) []*x509.Certificate { ++ var roots []*x509.Certificate ++ for len(b) > 0 { ++ var block *pem.Block ++ block, b = pem.Decode(b) ++ if block == nil { ++ break ++ } ++ if block.Type != "CERTIFICATE" { ++ panic("unexpected PEM block type: " + block.Type) ++ } ++ cert, err := x509.ParseCertificate(block.Bytes) ++ if err != nil { ++ panic(err) ++ } ++ roots = append(roots, cert) ++ } ++ return roots ++} ++ ++var bundle = mustParse([]byte(pemRoots)) ++ ++// Format of the PEM list is: ++// * Subject common name ++// * SHA256 hash ++// * PEM block ++ ++` ++ ++var ( ++ certDataURL = flag.String("certdata-url", "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt", "URL to the raw certdata.txt file to parse (certdata-path overrides this, if provided)") ++ certDataPath = flag.String("certdata-path", "", "Path to the NSS certdata.txt file to parse (this overrides certdata-url, if provided)") ++ output = flag.String("output", "fallback/bundle.go", "Path to file to write output to") ++) ++ ++func main() { ++ flag.Parse() ++ ++ var certdata io.Reader ++ ++ if *certDataPath != "" { ++ f, err := os.Open(*certDataPath) ++ if err != nil { ++ log.Fatalf("unable to open %q: %s", *certDataPath, err) ++ } ++ defer f.Close() ++ certdata = f ++ } else { ++ resp, err := http.Get(*certDataURL) ++ if err != nil { ++ log.Fatalf("failed to request %q: %s", *certDataURL, err) ++ } ++ defer resp.Body.Close() ++ certdata = resp.Body ++ } ++ ++ certs, err := nss.Parse(certdata) ++ if err != nil { ++ log.Fatalf("failed to parse %q: %s", *certDataPath, err) ++ } ++ ++ sort.Slice(certs, func(i, j int) bool { ++ // Sort based on the stringified subject (which may not be unique), and ++ // break any ties by just sorting on the raw DER (which will be unique, ++ // but is expensive). This should produce a stable sorting, which should ++ // be mostly readable by a human looking for a specific root or set of ++ // roots. ++ subjI, subjJ := certs[i].X509.Subject.String(), certs[j].X509.Subject.String() ++ if subjI == subjJ { ++ return string(certs[i].X509.Raw) < string(certs[j].X509.Raw) ++ } ++ return subjI < subjJ ++ }) ++ ++ b := new(bytes.Buffer) ++ b.WriteString(tmpl) ++ fmt.Fprintln(b, "const pemRoots = `") ++ for _, c := range certs { ++ if len(c.Constraints) > 0 { ++ // Until the constrained roots API lands, skip anything that has any ++ // additional constraints. Once that API is available, we can add ++ // build constraints that support both the current version and the ++ // new version. ++ continue ++ } ++ fmt.Fprintf(b, "# %s\n# %x\n", c.X509.Subject.String(), sha256.Sum256(c.X509.Raw)) ++ pem.Encode(b, &pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw}) ++ } ++ fmt.Fprintln(b, "`") ++ ++ formatted, err := format.Source(b.Bytes()) ++ if err != nil { ++ log.Fatalf("failed to format source: %s", err) ++ } ++ ++ if err := os.WriteFile(*output, formatted, 0644); err != nil { ++ log.Fatalf("failed to write to %q: %s", *output, err) ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/x509roots/nss/parser.go b/ms_mod/golang.org/x/crypto/x509roots/nss/parser.go +new file mode 100644 +index 00000000000000..1af3e0ae46fe1c +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/nss/parser.go +@@ -0,0 +1,259 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package nss provides functionality for parsing NSS certdata.txt ++// formatted certificate lists and extracting serverAuth roots. Most ++// users should not use this package themselves, and should instead ++// rely on the golang.org/x/crypto/x509roots/fallback package which ++// calls x509.SetFallbackRoots on a pre-parsed set of roots. ++package nss ++ ++import ( ++ "bufio" ++ "bytes" ++ "crypto/sha1" ++ "crypto/x509" ++ "errors" ++ "fmt" ++ "io" ++ "strconv" ++ "strings" ++ "time" ++) ++ ++// Constraint is a constraint to be applied to a certificate or ++// certificate chain. ++type Constraint interface { ++ Kind() Kind ++} ++ ++// Kind is the constraint kind, using the NSS enumeration. ++type Kind int ++ ++const ( ++ CKA_NSS_SERVER_DISTRUST_AFTER Kind = iota ++) ++ ++// DistrustAfter is a Constraint that indicates a certificate has a ++// CKA_NSS_SERVER_DISTRUST_AFTER constraint. This constraint defines a date ++// after which any certificate issued which is rooted by the constrained ++// certificate should be distrusted. ++type DistrustAfter time.Time ++ ++func (DistrustAfter) Kind() Kind { ++ return CKA_NSS_SERVER_DISTRUST_AFTER ++} ++ ++// A Certificate represents a single trusted serverAuth certificate in the NSS ++// certdata.txt list and any constraints that should be applied to chains ++// rooted by it. ++type Certificate struct { ++ // Certificate is the parsed certificate ++ X509 *x509.Certificate ++ // Constraints contains a list of additional constraints that should be ++ // applied to any certificates that chain to Certificate. If there are ++ // any unknown constraints in the slice, Certificate should not be ++ // trusted. ++ Constraints []Constraint ++} ++ ++func parseMulitLineOctal(s *bufio.Scanner) ([]byte, error) { ++ buf := bytes.NewBuffer(nil) ++ for s.Scan() { ++ if s.Text() == "END" { ++ break ++ } ++ b, err := strconv.Unquote(fmt.Sprintf("\"%s\"", s.Text())) ++ if err != nil { ++ return nil, err ++ } ++ buf.Write([]byte(b)) ++ } ++ return buf.Bytes(), nil ++} ++ ++type certObj struct { ++ c *x509.Certificate ++ DistrustAfter *time.Time ++} ++ ++func parseCertClass(s *bufio.Scanner) ([sha1.Size]byte, *certObj, error) { ++ var h [sha1.Size]byte ++ co := &certObj{} ++ for s.Scan() { ++ l := s.Text() ++ if l == "" { ++ // assume an empty newline indicates the end of a block ++ break ++ } ++ if strings.HasPrefix(l, "CKA_VALUE") { ++ b, err := parseMulitLineOctal(s) ++ if err != nil { ++ return h, nil, err ++ } ++ co.c, err = x509.ParseCertificate(b) ++ if err != nil { ++ return h, nil, err ++ } ++ h = sha1.Sum(b) ++ } else if strings.HasPrefix(l, "CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE") { ++ // we don't want it ++ return h, nil, nil ++ } else if l == "CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL" { ++ dateStr, err := parseMulitLineOctal(s) ++ if err != nil { ++ return h, nil, err ++ } ++ t, err := time.Parse("060102150405Z0700", string(dateStr)) ++ if err != nil { ++ return h, nil, err ++ } ++ co.DistrustAfter = &t ++ } ++ } ++ if co.c == nil { ++ return h, nil, errors.New("malformed CKO_CERTIFICATE object") ++ } ++ return h, co, nil ++} ++ ++type trustObj struct { ++ trusted bool ++} ++ ++func parseTrustClass(s *bufio.Scanner) ([sha1.Size]byte, *trustObj, error) { ++ var h [sha1.Size]byte ++ to := &trustObj{trusted: false} // default to untrusted ++ ++ for s.Scan() { ++ l := s.Text() ++ if l == "" { ++ // assume an empty newline indicates the end of a block ++ break ++ } ++ if l == "CKA_CERT_SHA1_HASH MULTILINE_OCTAL" { ++ hash, err := parseMulitLineOctal(s) ++ if err != nil { ++ return h, nil, err ++ } ++ copy(h[:], hash) ++ } else if l == "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR" { ++ // we only care about server auth ++ to.trusted = true ++ } ++ } ++ ++ return h, to, nil ++} ++ ++// Parse parses a NSS certdata.txt formatted file, returning only ++// trusted serverAuth roots, as well as any additional constraints. This parser ++// is very opinionated, only returning roots that are currently trusted for ++// serverAuth. As such roots returned by this package should only be used for ++// making trust decisions about serverAuth certificates, as the trust status for ++// other uses is not considered. Using the roots returned by this package for ++// trust decisions should be done carefully. ++// ++// Some roots returned by the parser may include additional constraints ++// (currently only DistrustAfter) which need to be considered when verifying ++// certificates which chain to them. ++// ++// Parse is not intended to be a general purpose parser for certdata.txt. ++func Parse(r io.Reader) ([]*Certificate, error) { ++ // certdata.txt is a rather strange format. It is essentially a list of ++ // textual PKCS#11 objects, delimited by empty lines. There are two main ++ // types of objects, certificates (CKO_CERTIFICATE) and trust definitions ++ // (CKO_NSS_TRUST). These objects appear to alternate, but this ordering is ++ // not defined anywhere, and should probably not be relied on. A single root ++ // certificate requires both the certificate object and the trust definition ++ // object in order to be properly understood. ++ // ++ // The list contains not just serverAuth certificates, so we need to be ++ // careful to only extract certificates which have the serverAuth trust bit ++ // set. Similarly there are a number of trust related bool fields that ++ // appear to _always_ be CKA_TRUE, but it seems unsafe to assume this is the ++ // case, so we should always double check. ++ // ++ // Since we only really care about a couple of fields, this parser throws ++ // away a lot of information, essentially just consuming CKA_CLASS objects ++ // and looking for the individual fields we care about. We could write a ++ // siginificantly more complex parser, which handles the entire format, but ++ // it feels like that would be over engineered for the little information ++ // that we really care about. ++ ++ scanner := bufio.NewScanner(r) ++ ++ type nssEntry struct { ++ cert *certObj ++ trust *trustObj ++ } ++ entries := map[[sha1.Size]byte]*nssEntry{} ++ ++ for scanner.Scan() { ++ // scan until we hit CKA_CLASS ++ if !strings.HasPrefix(scanner.Text(), "CKA_CLASS") { ++ continue ++ } ++ ++ f := strings.Fields(scanner.Text()) ++ if len(f) != 3 { ++ return nil, errors.New("malformed CKA_CLASS") ++ } ++ switch f[2] { ++ case "CKO_CERTIFICATE": ++ h, co, err := parseCertClass(scanner) ++ if err != nil { ++ return nil, err ++ } ++ if co != nil { ++ e, ok := entries[h] ++ if !ok { ++ e = &nssEntry{} ++ entries[h] = e ++ } ++ e.cert = co ++ } ++ ++ case "CKO_NSS_TRUST": ++ h, to, err := parseTrustClass(scanner) ++ if err != nil { ++ return nil, err ++ } ++ if to != nil { ++ e, ok := entries[h] ++ if !ok { ++ e = &nssEntry{} ++ entries[h] = e ++ } ++ e.trust = to ++ } ++ } ++ } ++ if err := scanner.Err(); err != nil { ++ return nil, err ++ } ++ ++ var certs []*Certificate ++ for h, e := range entries { ++ if e.cert == nil && e.trust != nil { ++ // We may skip some certificates which are distrusted due to mozilla ++ // policy (CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE), which means ++ // we might get entries that appear to have a trust object, but no ++ // certificate. We can just continue on here. ++ continue ++ } else if e.cert != nil && e.trust == nil { ++ return nil, fmt.Errorf("missing trust object for certificate with SHA1 hash: %x", h) ++ } ++ if !e.trust.trusted { ++ continue ++ } ++ nssCert := &Certificate{X509: e.cert.c} ++ if e.cert.DistrustAfter != nil { ++ nssCert.Constraints = append(nssCert.Constraints, DistrustAfter(*e.cert.DistrustAfter)) ++ } ++ certs = append(certs, nssCert) ++ } ++ ++ return certs, nil ++} +diff --git a/ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go b/ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go +new file mode 100644 +index 00000000000000..581b02cf06c583 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go +@@ -0,0 +1,1216 @@ ++// Copyright 2023 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package nss ++ ++import ( ++ "crypto/x509" ++ "encoding/pem" ++ "reflect" ++ "sort" ++ "strings" ++ "testing" ++ "time" ++) ++ ++func mustParse(b []byte) *x509.Certificate { ++ block, _ := pem.Decode(b) ++ cert, err := x509.ParseCertificate(block.Bytes) ++ if err != nil { ++ panic(err) ++ } ++ return cert ++} ++ ++var testComodo = mustParse([]byte(`-----BEGIN CERTIFICATE----- ++MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb ++MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow ++GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj ++YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL ++MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE ++BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM ++GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ++ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua ++BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe ++3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 ++YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR ++rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm ++ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU ++oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF ++MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v ++QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t ++b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF ++AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q ++GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz ++Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 ++G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi ++l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 ++smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ++-----END CERTIFICATE-----`)) ++ ++var testTrustcor = mustParse([]byte(`-----BEGIN CERTIFICATE----- ++MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV ++BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw ++IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy ++dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig ++Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk ++MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg ++Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD ++VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy ++dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK ++AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ ++QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq ++1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp ++2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK ++DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape ++az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF ++3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 ++oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM ++g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 ++mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh ++8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd ++BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U ++nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw ++DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX ++dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ ++MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL ++/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX ++CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa ++ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW ++2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 ++N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 ++Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB ++As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp ++5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu ++1uwJ ++-----END CERTIFICATE-----`)) ++ ++func TestParseCertData(t *testing.T) { ++ trustcorDistrust, err := time.Parse("060102150405Z0700", "221130000000Z") ++ if err != nil { ++ t.Fatalf("failed to parse distrust time: %s", err) ++ } ++ ++ for _, tc := range []struct { ++ name string ++ data string ++ output []*Certificate ++ err string ++ }{ ++ { ++ name: "valid certs", ++ data: validCertdata, ++ output: []*Certificate{ ++ &Certificate{X509: testComodo}, ++ &Certificate{X509: testTrustcor, Constraints: []Constraint{DistrustAfter(trustcorDistrust)}}, ++ }, ++ }, ++ { ++ name: "cert obj, no trust obj", ++ data: certNoTrust, ++ err: "missing trust object for certificate with SHA1 hash: d1eb23a46d17d68fd92564c2f1f1601764d8e349", ++ }, ++ { ++ name: "trust obj, no cert obj", ++ data: trustNoCert, ++ }, ++ { ++ name: "missing certificate der", ++ data: missingCertificateOctal, ++ err: "malformed CKO_CERTIFICATE object", ++ }, ++ { ++ name: "untrusted cert (cert)", ++ data: untrustedCertCert, ++ }, ++ { ++ name: "untrusted cert (trust)", ++ data: untrustedCertTrust, ++ }, ++ { ++ name: "malformed class", ++ data: malformedClass, ++ err: "malformed CKA_CLASS", ++ }, ++ { ++ name: "malformed cert octal", ++ data: malformedOctalCert, ++ err: "invalid syntax", ++ }, ++ { ++ name: "malformed hash octal", ++ data: malformedOctalhash, ++ err: "invalid syntax", ++ }, ++ { ++ name: "malformed distrust octal", ++ data: malformedOctalDistrust, ++ err: "invalid syntax", ++ }, ++ } { ++ t.Run(tc.name, func(t *testing.T) { ++ r := strings.NewReader(tc.data) ++ nc, err := Parse(r) ++ if err != nil { ++ if tc.err == "" { ++ t.Fatalf("unexpected error: %s", err) ++ } else if tc.err != err.Error() { ++ t.Fatalf("unexpected error: want %q, got %q", tc.err, err) ++ } ++ } else if tc.err != "" { ++ t.Fatal("expected error, got nil") ++ } ++ ++ if len(tc.output) != len(nc) { ++ t.Fatalf("unexpected number of parsed certs: want %d, got %d", len(tc.output), len(nc)) ++ } ++ ++ // sort so we can check equality ++ sort.Slice(nc, func(i, j int) bool { ++ return nc[i].X509.Subject.String() < nc[j].X509.Subject.String() ++ }) ++ ++ if !reflect.DeepEqual(tc.output, nc) { ++ t.Fatal("unexpected results") ++ } ++ }) ++ } ++} ++ ++const validCertdata = `# ++# Certificate "Comodo AAA Services root" ++# ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_VALUE MULTILINE_OCTAL ++\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 ++\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 ++\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 ++\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 ++\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 ++\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 ++\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 ++\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 ++\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 ++\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 ++\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 ++\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 ++\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 ++\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 ++\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 ++\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 ++\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 ++\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 ++\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 ++\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 ++\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 ++\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 ++\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 ++\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 ++\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 ++\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 ++\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 ++\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 ++\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 ++\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 ++\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 ++\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 ++\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 ++\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 ++\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 ++\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 ++\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 ++\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 ++\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 ++\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 ++\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 ++\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 ++\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 ++\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 ++\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 ++\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 ++\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 ++\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 ++\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 ++\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 ++\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 ++\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 ++\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 ++\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 ++\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 ++\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 ++\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 ++\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 ++\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 ++\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 ++\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 ++\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 ++\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 ++\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 ++\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 ++\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 ++\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 ++\225\351\066\226\230\156 ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE ++CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE ++CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE ++ ++# Trust for "Comodo AAA Services root" ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERT_SHA1_HASH MULTILINE_OCTAL ++\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 ++\144\330\343\111 ++END ++CKA_CERT_MD5_HASH MULTILINE_OCTAL ++\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 ++END ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE ++ ++# ++# Certificate "TrustCor RootCert CA-2" ++# ++# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA ++# Serial Number:25:a1:df:ca:33:cb:59:02 ++# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA ++# Not Valid Before: Thu Feb 04 12:32:23 2016 ++# Not Valid After : Sun Dec 31 17:26:39 2034 ++# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 ++# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 ++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "TrustCor RootCert CA-2" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 ++\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 ++\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 ++\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 ++\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 ++\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 ++\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 ++\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 ++\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 ++\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 ++\162\164\040\103\101\055\062 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 ++\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 ++\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 ++\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 ++\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 ++\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 ++\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 ++\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 ++\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 ++\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 ++\162\164\040\103\101\055\062 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\010\045\241\337\312\063\313\131\002 ++END ++CKA_VALUE MULTILINE_OCTAL ++\060\202\006\057\060\202\004\027\240\003\002\001\002\002\010\045 ++\241\337\312\063\313\131\002\060\015\006\011\052\206\110\206\367 ++\015\001\001\013\005\000\060\201\244\061\013\060\011\006\003\125 ++\004\006\023\002\120\101\061\017\060\015\006\003\125\004\010\014 ++\006\120\141\156\141\155\141\061\024\060\022\006\003\125\004\007 ++\014\013\120\141\156\141\155\141\040\103\151\164\171\061\044\060 ++\042\006\003\125\004\012\014\033\124\162\165\163\164\103\157\162 ++\040\123\171\163\164\145\155\163\040\123\056\040\144\145\040\122 ++\056\114\056\061\047\060\045\006\003\125\004\013\014\036\124\162 ++\165\163\164\103\157\162\040\103\145\162\164\151\146\151\143\141 ++\164\145\040\101\165\164\150\157\162\151\164\171\061\037\060\035 ++\006\003\125\004\003\014\026\124\162\165\163\164\103\157\162\040 ++\122\157\157\164\103\145\162\164\040\103\101\055\062\060\036\027 ++\015\061\066\060\062\060\064\061\062\063\062\062\063\132\027\015 ++\063\064\061\062\063\061\061\067\062\066\063\071\132\060\201\244 ++\061\013\060\011\006\003\125\004\006\023\002\120\101\061\017\060 ++\015\006\003\125\004\010\014\006\120\141\156\141\155\141\061\024 ++\060\022\006\003\125\004\007\014\013\120\141\156\141\155\141\040 ++\103\151\164\171\061\044\060\042\006\003\125\004\012\014\033\124 ++\162\165\163\164\103\157\162\040\123\171\163\164\145\155\163\040 ++\123\056\040\144\145\040\122\056\114\056\061\047\060\045\006\003 ++\125\004\013\014\036\124\162\165\163\164\103\157\162\040\103\145 ++\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157\162 ++\151\164\171\061\037\060\035\006\003\125\004\003\014\026\124\162 ++\165\163\164\103\157\162\040\122\157\157\164\103\145\162\164\040 ++\103\101\055\062\060\202\002\042\060\015\006\011\052\206\110\206 ++\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 ++\002\202\002\001\000\247\040\156\302\052\242\142\044\225\220\166 ++\310\070\176\200\322\253\301\233\145\005\224\364\301\012\020\325 ++\002\254\355\237\223\307\207\310\260\047\053\102\014\075\012\076 ++\101\132\236\165\335\215\312\340\233\354\150\062\244\151\222\150 ++\214\013\201\016\126\240\076\032\335\054\045\024\202\057\227\323 ++\144\106\364\124\251\334\072\124\055\061\053\231\202\362\331\052 ++\327\357\161\000\270\061\244\276\172\044\007\303\102\040\362\212 ++\324\222\004\033\145\126\114\154\324\373\266\141\132\107\043\264 ++\330\151\264\267\072\320\164\074\014\165\241\214\116\166\241\351 ++\333\052\245\073\372\316\260\377\176\152\050\375\047\034\310\261 ++\351\051\361\127\156\144\264\320\301\025\155\016\276\056\016\106 ++\310\136\364\121\376\357\016\143\072\073\161\272\317\157\131\312 ++\014\343\233\135\111\270\114\342\127\261\230\212\102\127\234\166 ++\357\357\275\321\150\250\322\364\011\273\167\065\276\045\202\010 ++\304\026\054\104\040\126\251\104\021\167\357\135\264\035\252\136 ++\153\076\213\062\366\007\057\127\004\222\312\365\376\235\302\351 ++\350\263\216\114\113\002\061\331\344\074\110\202\047\367\030\202 ++\166\110\072\161\261\023\241\071\325\056\305\064\302\035\142\205 ++\337\003\376\115\364\257\075\337\134\133\215\372\160\341\245\176 ++\047\307\206\056\152\217\022\306\204\136\103\121\120\234\031\233 ++\170\346\374\366\355\107\176\173\075\146\357\023\023\210\137\074 ++\241\143\373\371\254\207\065\237\363\202\236\244\077\012\234\061 ++\151\213\231\244\210\112\216\156\146\115\357\026\304\017\171\050 ++\041\140\015\205\026\175\327\124\070\361\222\126\375\265\063\114 ++\203\334\327\020\237\113\375\306\370\102\275\272\174\163\002\340 ++\377\175\315\133\341\324\254\141\173\127\325\112\173\133\324\205 ++\130\047\135\277\370\053\140\254\240\046\256\024\041\047\306\167 ++\232\063\200\074\136\106\077\367\303\261\243\206\063\306\350\136 ++\015\271\065\054\252\106\301\205\002\165\200\240\353\044\373\025 ++\252\344\147\177\156\167\077\364\004\212\057\174\173\343\027\141 ++\360\335\011\251\040\310\276\011\244\320\176\104\303\262\060\112 ++\070\252\251\354\030\232\007\202\053\333\270\234\030\255\332\340 ++\106\027\254\317\135\002\003\001\000\001\243\143\060\141\060\035 ++\006\003\125\035\016\004\026\004\024\331\376\041\100\156\224\236 ++\274\233\075\234\175\230\040\031\345\214\060\142\262\060\037\006 ++\003\125\035\043\004\030\060\026\200\024\331\376\041\100\156\224 ++\236\274\233\075\234\175\230\040\031\345\214\060\142\262\060\017 ++\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 ++\016\006\003\125\035\017\001\001\377\004\004\003\002\001\206\060 ++\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 ++\002\001\000\236\105\236\014\073\266\357\341\072\310\174\321\000 ++\075\317\342\352\006\265\262\072\273\006\113\150\172\320\043\227 ++\164\247\054\360\010\330\171\132\327\132\204\212\330\022\232\033 ++\331\175\134\115\160\305\245\371\253\345\243\211\211\335\001\372 ++\354\335\371\351\222\227\333\260\106\102\363\323\142\252\225\376 ++\061\147\024\151\130\220\012\252\013\356\067\043\307\120\121\264 ++\365\176\236\343\173\367\344\314\102\062\055\111\014\313\377\111 ++\014\233\036\064\375\156\156\226\212\171\003\266\157\333\011\313 ++\375\137\145\024\067\341\070\365\363\141\026\130\344\265\155\015 ++\013\004\033\077\120\055\177\263\307\172\032\026\200\140\370\212 ++\037\351\033\052\306\371\272\001\032\151\277\322\130\307\124\127 ++\010\217\341\071\140\167\113\254\131\204\032\210\361\335\313\117 ++\170\327\347\341\063\055\374\356\101\372\040\260\276\313\367\070 ++\224\300\341\320\205\017\273\355\054\163\253\355\376\222\166\032 ++\144\177\133\015\063\011\007\063\173\006\077\021\244\134\160\074 ++\205\300\317\343\220\250\203\167\372\333\346\305\214\150\147\020 ++\147\245\122\055\360\304\231\217\177\277\321\153\342\265\107\326 ++\331\320\205\231\115\224\233\017\113\215\356\000\132\107\035\021 ++\003\254\101\030\257\207\267\157\014\072\217\312\317\334\003\301 ++\242\011\310\345\375\200\136\310\140\102\001\033\032\123\132\273 ++\067\246\267\274\272\204\351\036\154\032\324\144\332\324\103\376 ++\223\213\113\362\054\171\026\020\324\223\013\210\217\241\330\206 ++\024\106\221\107\233\050\044\357\127\122\116\134\102\234\252\367 ++\111\354\047\350\100\036\263\246\211\042\162\234\365\015\063\264 ++\130\243\060\073\335\324\152\124\223\276\032\115\363\223\224\367 ++\374\204\013\077\204\040\134\064\003\104\305\332\255\274\012\301 ++\002\317\036\345\224\331\363\216\133\330\114\360\235\354\141\027 ++\273\024\062\124\014\002\051\223\036\222\206\366\177\357\347\222 ++\005\016\131\335\231\010\056\056\372\234\000\122\323\305\146\051 ++\344\247\227\104\244\016\050\201\023\065\305\366\157\144\346\101 ++\304\325\057\314\064\105\045\317\101\000\226\075\112\056\302\226 ++\230\117\116\112\234\227\267\333\037\222\062\310\377\017\121\156 ++\326\354\011 ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE ++# For Server Distrust After: Wed Nov 30 00:00:00 2022 ++CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL ++\062\062\061\061\063\060\060\060\060\060\060\060\132 ++END ++# For Email Distrust After: Wed Nov 30 00:00:00 2022 ++CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL ++\062\062\061\061\063\060\060\060\060\060\060\060\132 ++END ++ ++ ++# Trust for "TrustCor RootCert CA-2" ++# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA ++# Serial Number:25:a1:df:ca:33:cb:59:02 ++# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA ++# Not Valid Before: Thu Feb 04 12:32:23 2016 ++# Not Valid After : Sun Dec 31 17:26:39 2034 ++# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 ++# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 ++CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "TrustCor RootCert CA-2" ++CKA_CERT_SHA1_HASH MULTILINE_OCTAL ++\270\276\155\313\126\361\125\271\143\324\022\312\116\006\064\307 ++\224\262\034\300 ++END ++CKA_CERT_MD5_HASH MULTILINE_OCTAL ++\242\341\370\030\013\272\105\325\307\101\052\273\067\122\105\144 ++END ++CKA_ISSUER MULTILINE_OCTAL ++\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 ++\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 ++\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 ++\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 ++\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 ++\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 ++\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 ++\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 ++\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 ++\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 ++\162\164\040\103\101\055\062 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\010\045\241\337\312\063\313\131\002 ++END ++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE ++` ++ ++const trustNoCert = `CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERT_SHA1_HASH MULTILINE_OCTAL ++\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 ++\144\330\343\111 ++END ++CKA_CERT_MD5_HASH MULTILINE_OCTAL ++\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 ++END ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` ++ ++const certNoTrust = `CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_VALUE MULTILINE_OCTAL ++\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 ++\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 ++\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 ++\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 ++\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 ++\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 ++\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 ++\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 ++\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 ++\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 ++\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 ++\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 ++\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 ++\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 ++\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 ++\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 ++\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 ++\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 ++\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 ++\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 ++\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 ++\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 ++\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 ++\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 ++\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 ++\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 ++\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 ++\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 ++\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 ++\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 ++\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 ++\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 ++\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 ++\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 ++\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 ++\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 ++\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 ++\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 ++\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 ++\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 ++\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 ++\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 ++\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 ++\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 ++\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 ++\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 ++\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 ++\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 ++\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 ++\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 ++\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 ++\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 ++\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 ++\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 ++\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 ++\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 ++\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 ++\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 ++\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 ++\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 ++\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 ++\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 ++\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 ++\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 ++\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 ++\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 ++\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 ++\225\351\066\226\230\156 ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE ++CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE ++CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE` ++ ++const missingCertificateOctal = `CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE` ++ ++const untrustedCertCert = `# ++# Certificate "Comodo AAA Services root" ++# ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_VALUE MULTILINE_OCTAL ++\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 ++\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 ++\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 ++\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 ++\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 ++\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 ++\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 ++\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 ++\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 ++\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 ++\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 ++\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 ++\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 ++\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 ++\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 ++\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 ++\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 ++\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 ++\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 ++\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 ++\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 ++\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 ++\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 ++\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 ++\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 ++\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 ++\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 ++\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 ++\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 ++\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 ++\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 ++\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 ++\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 ++\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 ++\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 ++\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 ++\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 ++\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 ++\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 ++\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 ++\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 ++\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 ++\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 ++\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 ++\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 ++\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 ++\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 ++\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 ++\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 ++\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 ++\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 ++\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 ++\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 ++\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 ++\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 ++\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 ++\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 ++\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 ++\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 ++\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 ++\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 ++\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 ++\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 ++\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 ++\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 ++\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 ++\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 ++\225\351\066\226\230\156 ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE ++CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE ++CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE ++ ++# Trust for "Comodo AAA Services root" ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERT_SHA1_HASH MULTILINE_OCTAL ++\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 ++\144\330\343\111 ++END ++CKA_CERT_MD5_HASH MULTILINE_OCTAL ++\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 ++END ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR ++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` ++ ++const untrustedCertTrust = `# ++# Certificate "Comodo AAA Services root" ++# ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_VALUE MULTILINE_OCTAL ++\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 ++\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 ++\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 ++\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 ++\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 ++\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 ++\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 ++\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 ++\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 ++\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 ++\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 ++\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 ++\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 ++\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 ++\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 ++\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 ++\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 ++\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 ++\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 ++\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 ++\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 ++\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 ++\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 ++\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 ++\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 ++\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 ++\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 ++\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 ++\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 ++\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 ++\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 ++\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 ++\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 ++\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 ++\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 ++\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 ++\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 ++\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 ++\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 ++\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 ++\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 ++\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 ++\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 ++\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 ++\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 ++\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 ++\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 ++\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 ++\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 ++\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 ++\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 ++\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 ++\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 ++\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 ++\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 ++\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 ++\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 ++\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 ++\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 ++\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 ++\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 ++\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 ++\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 ++\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 ++\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 ++\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 ++\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 ++\225\351\066\226\230\156 ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE ++CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE ++CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE ++ ++# Trust for "Comodo AAA Services root" ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERT_SHA1_HASH MULTILINE_OCTAL ++\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 ++\144\330\343\111 ++END ++CKA_CERT_MD5_HASH MULTILINE_OCTAL ++\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 ++END ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_TRUST_SERVER_AUTH CK_TRUST ++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` ++ ++const malformedClass = `CKA_CLASS` ++ ++const malformedOctalCert = `# ++# Certificate "Comodo AAA Services root" ++# ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_VALUE MULTILINE_OCTAL ++hello\xxxxxxx ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE ++CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE ++CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE` ++ ++const malformedOctalhash = `# Trust for "Comodo AAA Services root" ++# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Serial Number: 1 (0x1) ++# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB ++# Not Valid Before: Thu Jan 01 00:00:00 2004 ++# Not Valid After : Sun Dec 31 23:59:59 2028 ++# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 ++# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 ++CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "Comodo AAA Services root" ++CKA_CERT_SHA1_HASH MULTILINE_OCTAL ++\xxxxx ++END ++CKA_CERT_MD5_HASH MULTILINE_OCTAL ++\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 ++END ++CKA_ISSUER MULTILINE_OCTAL ++\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 ++\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 ++\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 ++\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 ++\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 ++\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 ++\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 ++\143\141\164\145\040\123\145\162\166\151\143\145\163 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\001\001 ++END ++CKA_TRUST_SERVER_AUTH CK_TRUST ++CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST ++CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` ++ ++const malformedOctalDistrust = `# ++# Certificate "TrustCor RootCert CA-2" ++# ++# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA ++# Serial Number:25:a1:df:ca:33:cb:59:02 ++# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA ++# Not Valid Before: Thu Feb 04 12:32:23 2016 ++# Not Valid After : Sun Dec 31 17:26:39 2034 ++# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 ++# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 ++CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE ++CKA_TOKEN CK_BBOOL CK_TRUE ++CKA_PRIVATE CK_BBOOL CK_FALSE ++CKA_MODIFIABLE CK_BBOOL CK_FALSE ++CKA_LABEL UTF8 "TrustCor RootCert CA-2" ++CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 ++CKA_SUBJECT MULTILINE_OCTAL ++\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 ++\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 ++\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 ++\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 ++\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 ++\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 ++\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 ++\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 ++\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 ++\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 ++\162\164\040\103\101\055\062 ++END ++CKA_ID UTF8 "0" ++CKA_ISSUER MULTILINE_OCTAL ++\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 ++\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 ++\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 ++\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 ++\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 ++\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 ++\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 ++\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 ++\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 ++\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 ++\162\164\040\103\101\055\062 ++END ++CKA_SERIAL_NUMBER MULTILINE_OCTAL ++\002\010\045\241\337\312\063\313\131\002 ++END ++CKA_VALUE MULTILINE_OCTAL ++\060\202\006\057\060\202\004\027\240\003\002\001\002\002\010\045 ++\241\337\312\063\313\131\002\060\015\006\011\052\206\110\206\367 ++\015\001\001\013\005\000\060\201\244\061\013\060\011\006\003\125 ++\004\006\023\002\120\101\061\017\060\015\006\003\125\004\010\014 ++\006\120\141\156\141\155\141\061\024\060\022\006\003\125\004\007 ++\014\013\120\141\156\141\155\141\040\103\151\164\171\061\044\060 ++\042\006\003\125\004\012\014\033\124\162\165\163\164\103\157\162 ++\040\123\171\163\164\145\155\163\040\123\056\040\144\145\040\122 ++\056\114\056\061\047\060\045\006\003\125\004\013\014\036\124\162 ++\165\163\164\103\157\162\040\103\145\162\164\151\146\151\143\141 ++\164\145\040\101\165\164\150\157\162\151\164\171\061\037\060\035 ++\006\003\125\004\003\014\026\124\162\165\163\164\103\157\162\040 ++\122\157\157\164\103\145\162\164\040\103\101\055\062\060\036\027 ++\015\061\066\060\062\060\064\061\062\063\062\062\063\132\027\015 ++\063\064\061\062\063\061\061\067\062\066\063\071\132\060\201\244 ++\061\013\060\011\006\003\125\004\006\023\002\120\101\061\017\060 ++\015\006\003\125\004\010\014\006\120\141\156\141\155\141\061\024 ++\060\022\006\003\125\004\007\014\013\120\141\156\141\155\141\040 ++\103\151\164\171\061\044\060\042\006\003\125\004\012\014\033\124 ++\162\165\163\164\103\157\162\040\123\171\163\164\145\155\163\040 ++\123\056\040\144\145\040\122\056\114\056\061\047\060\045\006\003 ++\125\004\013\014\036\124\162\165\163\164\103\157\162\040\103\145 ++\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157\162 ++\151\164\171\061\037\060\035\006\003\125\004\003\014\026\124\162 ++\165\163\164\103\157\162\040\122\157\157\164\103\145\162\164\040 ++\103\101\055\062\060\202\002\042\060\015\006\011\052\206\110\206 ++\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 ++\002\202\002\001\000\247\040\156\302\052\242\142\044\225\220\166 ++\310\070\176\200\322\253\301\233\145\005\224\364\301\012\020\325 ++\002\254\355\237\223\307\207\310\260\047\053\102\014\075\012\076 ++\101\132\236\165\335\215\312\340\233\354\150\062\244\151\222\150 ++\214\013\201\016\126\240\076\032\335\054\045\024\202\057\227\323 ++\144\106\364\124\251\334\072\124\055\061\053\231\202\362\331\052 ++\327\357\161\000\270\061\244\276\172\044\007\303\102\040\362\212 ++\324\222\004\033\145\126\114\154\324\373\266\141\132\107\043\264 ++\330\151\264\267\072\320\164\074\014\165\241\214\116\166\241\351 ++\333\052\245\073\372\316\260\377\176\152\050\375\047\034\310\261 ++\351\051\361\127\156\144\264\320\301\025\155\016\276\056\016\106 ++\310\136\364\121\376\357\016\143\072\073\161\272\317\157\131\312 ++\014\343\233\135\111\270\114\342\127\261\230\212\102\127\234\166 ++\357\357\275\321\150\250\322\364\011\273\167\065\276\045\202\010 ++\304\026\054\104\040\126\251\104\021\167\357\135\264\035\252\136 ++\153\076\213\062\366\007\057\127\004\222\312\365\376\235\302\351 ++\350\263\216\114\113\002\061\331\344\074\110\202\047\367\030\202 ++\166\110\072\161\261\023\241\071\325\056\305\064\302\035\142\205 ++\337\003\376\115\364\257\075\337\134\133\215\372\160\341\245\176 ++\047\307\206\056\152\217\022\306\204\136\103\121\120\234\031\233 ++\170\346\374\366\355\107\176\173\075\146\357\023\023\210\137\074 ++\241\143\373\371\254\207\065\237\363\202\236\244\077\012\234\061 ++\151\213\231\244\210\112\216\156\146\115\357\026\304\017\171\050 ++\041\140\015\205\026\175\327\124\070\361\222\126\375\265\063\114 ++\203\334\327\020\237\113\375\306\370\102\275\272\174\163\002\340 ++\377\175\315\133\341\324\254\141\173\127\325\112\173\133\324\205 ++\130\047\135\277\370\053\140\254\240\046\256\024\041\047\306\167 ++\232\063\200\074\136\106\077\367\303\261\243\206\063\306\350\136 ++\015\271\065\054\252\106\301\205\002\165\200\240\353\044\373\025 ++\252\344\147\177\156\167\077\364\004\212\057\174\173\343\027\141 ++\360\335\011\251\040\310\276\011\244\320\176\104\303\262\060\112 ++\070\252\251\354\030\232\007\202\053\333\270\234\030\255\332\340 ++\106\027\254\317\135\002\003\001\000\001\243\143\060\141\060\035 ++\006\003\125\035\016\004\026\004\024\331\376\041\100\156\224\236 ++\274\233\075\234\175\230\040\031\345\214\060\142\262\060\037\006 ++\003\125\035\043\004\030\060\026\200\024\331\376\041\100\156\224 ++\236\274\233\075\234\175\230\040\031\345\214\060\142\262\060\017 ++\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 ++\016\006\003\125\035\017\001\001\377\004\004\003\002\001\206\060 ++\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 ++\002\001\000\236\105\236\014\073\266\357\341\072\310\174\321\000 ++\075\317\342\352\006\265\262\072\273\006\113\150\172\320\043\227 ++\164\247\054\360\010\330\171\132\327\132\204\212\330\022\232\033 ++\331\175\134\115\160\305\245\371\253\345\243\211\211\335\001\372 ++\354\335\371\351\222\227\333\260\106\102\363\323\142\252\225\376 ++\061\147\024\151\130\220\012\252\013\356\067\043\307\120\121\264 ++\365\176\236\343\173\367\344\314\102\062\055\111\014\313\377\111 ++\014\233\036\064\375\156\156\226\212\171\003\266\157\333\011\313 ++\375\137\145\024\067\341\070\365\363\141\026\130\344\265\155\015 ++\013\004\033\077\120\055\177\263\307\172\032\026\200\140\370\212 ++\037\351\033\052\306\371\272\001\032\151\277\322\130\307\124\127 ++\010\217\341\071\140\167\113\254\131\204\032\210\361\335\313\117 ++\170\327\347\341\063\055\374\356\101\372\040\260\276\313\367\070 ++\224\300\341\320\205\017\273\355\054\163\253\355\376\222\166\032 ++\144\177\133\015\063\011\007\063\173\006\077\021\244\134\160\074 ++\205\300\317\343\220\250\203\167\372\333\346\305\214\150\147\020 ++\147\245\122\055\360\304\231\217\177\277\321\153\342\265\107\326 ++\331\320\205\231\115\224\233\017\113\215\356\000\132\107\035\021 ++\003\254\101\030\257\207\267\157\014\072\217\312\317\334\003\301 ++\242\011\310\345\375\200\136\310\140\102\001\033\032\123\132\273 ++\067\246\267\274\272\204\351\036\154\032\324\144\332\324\103\376 ++\223\213\113\362\054\171\026\020\324\223\013\210\217\241\330\206 ++\024\106\221\107\233\050\044\357\127\122\116\134\102\234\252\367 ++\111\354\047\350\100\036\263\246\211\042\162\234\365\015\063\264 ++\130\243\060\073\335\324\152\124\223\276\032\115\363\223\224\367 ++\374\204\013\077\204\040\134\064\003\104\305\332\255\274\012\301 ++\002\317\036\345\224\331\363\216\133\330\114\360\235\354\141\027 ++\273\024\062\124\014\002\051\223\036\222\206\366\177\357\347\222 ++\005\016\131\335\231\010\056\056\372\234\000\122\323\305\146\051 ++\344\247\227\104\244\016\050\201\023\065\305\366\157\144\346\101 ++\304\325\057\314\064\105\045\317\101\000\226\075\112\056\302\226 ++\230\117\116\112\234\227\267\333\037\222\062\310\377\017\121\156 ++\326\354\011 ++END ++CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE ++# For Server Distrust After: Wed Nov 30 00:00:00 2022 ++CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL ++\xxxxxxxx ++END ++# For Email Distrust After: Wed Nov 30 00:00:00 2022 ++CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL ++\062\062\061\061\063\060\060\060\060\060\060\060\132 ++END` +diff --git a/ms_mod/golang.org/x/crypto/xtea/block.go b/ms_mod/golang.org/x/crypto/xtea/block.go +new file mode 100644 +index 00000000000000..fcb4e4d0003c2d +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/xtea/block.go +@@ -0,0 +1,66 @@ ++// Copyright 2009 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++/* ++ Implementation adapted from Needham and Wheeler's paper: ++ http://www.cix.co.uk/~klockstone/xtea.pdf ++ ++ A precalculated look up table is used during encryption/decryption for values that are based purely on the key. ++*/ ++ ++package xtea ++ ++// XTEA is based on 64 rounds. ++const numRounds = 64 ++ ++// blockToUint32 reads an 8 byte slice into two uint32s. ++// The block is treated as big endian. ++func blockToUint32(src []byte) (uint32, uint32) { ++ r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) ++ r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) ++ return r0, r1 ++} ++ ++// uint32ToBlock writes two uint32s into an 8 byte data block. ++// Values are written as big endian. ++func uint32ToBlock(v0, v1 uint32, dst []byte) { ++ dst[0] = byte(v0 >> 24) ++ dst[1] = byte(v0 >> 16) ++ dst[2] = byte(v0 >> 8) ++ dst[3] = byte(v0) ++ dst[4] = byte(v1 >> 24) ++ dst[5] = byte(v1 >> 16) ++ dst[6] = byte(v1 >> 8) ++ dst[7] = byte(v1 >> 0) ++} ++ ++// encryptBlock encrypts a single 8 byte block using XTEA. ++func encryptBlock(c *Cipher, dst, src []byte) { ++ v0, v1 := blockToUint32(src) ++ ++ // Two rounds of XTEA applied per loop ++ for i := 0; i < numRounds; { ++ v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] ++ i++ ++ v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] ++ i++ ++ } ++ ++ uint32ToBlock(v0, v1, dst) ++} ++ ++// decryptBlock decrypts a single 8 byte block using XTEA. ++func decryptBlock(c *Cipher, dst, src []byte) { ++ v0, v1 := blockToUint32(src) ++ ++ // Two rounds of XTEA applied per loop ++ for i := numRounds; i > 0; { ++ i-- ++ v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] ++ i-- ++ v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] ++ } ++ ++ uint32ToBlock(v0, v1, dst) ++} +diff --git a/ms_mod/golang.org/x/crypto/xtea/cipher.go b/ms_mod/golang.org/x/crypto/xtea/cipher.go +new file mode 100644 +index 00000000000000..a4c2fd02b32003 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/xtea/cipher.go +@@ -0,0 +1,90 @@ ++// Copyright 2009 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's ++// 1997 technical report, "Tea extensions." ++// ++// XTEA is a legacy cipher and its short block size makes it vulnerable to ++// birthday bound attacks (see https://sweet32.info). It should only be used ++// where compatibility with legacy systems, not security, is the goal. ++// ++// Deprecated: any new system should use AES (from crypto/aes, if necessary in ++// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from ++// golang.org/x/crypto/chacha20poly1305). ++package xtea // import "golang.org/x/crypto/xtea" ++ ++// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf ++ ++import "strconv" ++ ++// The XTEA block size in bytes. ++const BlockSize = 8 ++ ++// A Cipher is an instance of an XTEA cipher using a particular key. ++type Cipher struct { ++ // table contains a series of precalculated values that are used each round. ++ table [64]uint32 ++} ++ ++type KeySizeError int ++ ++func (k KeySizeError) Error() string { ++ return "crypto/xtea: invalid key size " + strconv.Itoa(int(k)) ++} ++ ++// NewCipher creates and returns a new Cipher. ++// The key argument should be the XTEA key. ++// XTEA only supports 128 bit (16 byte) keys. ++func NewCipher(key []byte) (*Cipher, error) { ++ k := len(key) ++ switch k { ++ default: ++ return nil, KeySizeError(k) ++ case 16: ++ break ++ } ++ ++ c := new(Cipher) ++ initCipher(c, key) ++ ++ return c, nil ++} ++ ++// BlockSize returns the XTEA block size, 8 bytes. ++// It is necessary to satisfy the Block interface in the ++// package "crypto/cipher". ++func (c *Cipher) BlockSize() int { return BlockSize } ++ ++// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst. ++// Note that for amounts of data larger than a block, ++// it is not safe to just call Encrypt on successive blocks; ++// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). ++func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) } ++ ++// Decrypt decrypts the 8 byte buffer src using the key and stores the result in dst. ++func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) } ++ ++// initCipher initializes the cipher context by creating a look up table ++// of precalculated values that are based on the key. ++func initCipher(c *Cipher, key []byte) { ++ // Load the key into four uint32s ++ var k [4]uint32 ++ for i := 0; i < len(k); i++ { ++ j := i << 2 // Multiply by 4 ++ k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3]) ++ } ++ ++ // Precalculate the table ++ const delta = 0x9E3779B9 ++ var sum uint32 ++ ++ // Two rounds of XTEA applied per loop ++ for i := 0; i < numRounds; { ++ c.table[i] = sum + k[sum&3] ++ i++ ++ sum += delta ++ c.table[i] = sum + k[(sum>>11)&3] ++ i++ ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/xtea/xtea_test.go b/ms_mod/golang.org/x/crypto/xtea/xtea_test.go +new file mode 100644 +index 00000000000000..be711bf5af0032 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/xtea/xtea_test.go +@@ -0,0 +1,229 @@ ++// Copyright 2009 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package xtea ++ ++import ( ++ "testing" ++) ++ ++// A sample test key for when we just want to initialize a cipher ++var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} ++ ++// Test that the block size for XTEA is correct ++func TestBlocksize(t *testing.T) { ++ if BlockSize != 8 { ++ t.Errorf("BlockSize constant - expected 8, got %d", BlockSize) ++ return ++ } ++ ++ c, err := NewCipher(testKey) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) ++ return ++ } ++ ++ result := c.BlockSize() ++ if result != 8 { ++ t.Errorf("BlockSize function - expected 8, got %d", result) ++ return ++ } ++} ++ ++// A series of test values to confirm that the Cipher.table array was initialized correctly ++var testTable = []uint32{ ++ 0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917, ++ 0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F, ++ 0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67, ++ 0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F, ++ 0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7, ++ 0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF, ++ 0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7, ++ 0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB, ++} ++ ++// Test that the cipher context is initialized correctly ++func TestCipherInit(t *testing.T) { ++ c, err := NewCipher(testKey) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) ++ return ++ } ++ ++ for i := 0; i < len(c.table); i++ { ++ if c.table[i] != testTable[i] { ++ t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i]) ++ break ++ } ++ } ++} ++ ++// Test that invalid key sizes return an error ++func TestInvalidKeySize(t *testing.T) { ++ // Test a long key ++ key := []byte{ ++ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, ++ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, ++ } ++ ++ _, err := NewCipher(key) ++ if err == nil { ++ t.Errorf("Invalid key size %d didn't result in an error.", len(key)) ++ } ++ ++ // Test a short key ++ key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} ++ ++ _, err = NewCipher(key) ++ if err == nil { ++ t.Errorf("Invalid key size %d didn't result in an error.", len(key)) ++ } ++} ++ ++// Test that we can correctly decode some bytes we have encoded ++func TestEncodeDecode(t *testing.T) { ++ original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} ++ input := original ++ output := make([]byte, BlockSize) ++ ++ c, err := NewCipher(testKey) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) ++ return ++ } ++ ++ // Encrypt the input block ++ c.Encrypt(output, input) ++ ++ // Check that the output does not match the input ++ differs := false ++ for i := 0; i < len(input); i++ { ++ if output[i] != input[i] { ++ differs = true ++ break ++ } ++ } ++ if differs == false { ++ t.Error("Cipher.Encrypt: Failed to encrypt the input block.") ++ return ++ } ++ ++ // Decrypt the block we just encrypted ++ input = output ++ output = make([]byte, BlockSize) ++ c.Decrypt(output, input) ++ ++ // Check that the output from decrypt matches our initial input ++ for i := 0; i < len(input); i++ { ++ if output[i] != original[i] { ++ t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i]) ++ return ++ } ++ } ++} ++ ++// Test Vectors ++type CryptTest struct { ++ key []byte ++ plainText []byte ++ cipherText []byte ++} ++ ++var CryptTests = []CryptTest{ ++ // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors ++ { ++ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, ++ []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, ++ []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5}, ++ }, ++ { ++ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, ++ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, ++ []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8}, ++ }, ++ { ++ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, ++ []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f}, ++ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, ++ }, ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, ++ []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5}, ++ }, ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, ++ []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d}, ++ }, ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55}, ++ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, ++ }, ++ ++ // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9}, ++ }, ++ { ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, ++ []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16}, ++ }, ++ { ++ []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, ++ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ++ []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64}, ++ }, ++ { ++ []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, ++ []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, ++ []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD}, ++ }, ++} ++ ++// Test encryption ++func TestCipherEncrypt(t *testing.T) { ++ for i, tt := range CryptTests { ++ c, err := NewCipher(tt.key) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) ++ continue ++ } ++ ++ out := make([]byte, len(tt.plainText)) ++ c.Encrypt(out, tt.plainText) ++ ++ for j := 0; j < len(out); j++ { ++ if out[j] != tt.cipherText[j] { ++ t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j]) ++ break ++ } ++ } ++ } ++} ++ ++// Test decryption ++func TestCipherDecrypt(t *testing.T) { ++ for i, tt := range CryptTests { ++ c, err := NewCipher(tt.key) ++ if err != nil { ++ t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) ++ continue ++ } ++ ++ out := make([]byte, len(tt.cipherText)) ++ c.Decrypt(out, tt.cipherText) ++ ++ for j := 0; j < len(out); j++ { ++ if out[j] != tt.plainText[j] { ++ t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j]) ++ break ++ } ++ } ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/xts/xts.go b/ms_mod/golang.org/x/crypto/xts/xts.go +new file mode 100644 +index 00000000000000..8c16a8301460eb +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/xts/xts.go +@@ -0,0 +1,164 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package xts implements the XTS cipher mode as specified in IEEE P1619/D16. ++// ++// XTS mode is typically used for disk encryption, which presents a number of ++// novel problems that make more common modes inapplicable. The disk is ++// conceptually an array of sectors and we must be able to encrypt and decrypt ++// a sector in isolation. However, an attacker must not be able to transpose ++// two sectors of plaintext by transposing their ciphertext. ++// ++// XTS wraps a block cipher with Rogaway's XEX mode in order to build a ++// tweakable block cipher. This allows each sector to have a unique tweak and ++// effectively create a unique key for each sector. ++// ++// XTS does not provide any authentication. An attacker can manipulate the ++// ciphertext and randomise a block (16 bytes) of the plaintext. This package ++// does not implement ciphertext-stealing so sectors must be a multiple of 16 ++// bytes. ++// ++// Note that XTS is usually not appropriate for any use besides disk encryption. ++// Most users should use an AEAD mode like GCM (from crypto/cipher.NewGCM) instead. ++package xts // import "golang.org/x/crypto/xts" ++ ++import ( ++ "crypto/cipher" ++ "encoding/binary" ++ "errors" ++ "sync" ++ ++ "golang.org/x/crypto/internal/alias" ++) ++ ++// Cipher contains an expanded key structure. It is safe for concurrent use if ++// the underlying block cipher is safe for concurrent use. ++type Cipher struct { ++ k1, k2 cipher.Block ++} ++ ++// blockSize is the block size that the underlying cipher must have. XTS is ++// only defined for 16-byte ciphers. ++const blockSize = 16 ++ ++var tweakPool = sync.Pool{ ++ New: func() interface{} { ++ return new([blockSize]byte) ++ }, ++} ++ ++// NewCipher creates a Cipher given a function for creating the underlying ++// block cipher (which must have a block size of 16 bytes). The key must be ++// twice the length of the underlying cipher's key. ++func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) { ++ c = new(Cipher) ++ if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil { ++ return ++ } ++ c.k2, err = cipherFunc(key[len(key)/2:]) ++ ++ if c.k1.BlockSize() != blockSize { ++ err = errors.New("xts: cipher does not have a block size of 16") ++ } ++ ++ return ++} ++ ++// Encrypt encrypts a sector of plaintext and puts the result into ciphertext. ++// Plaintext and ciphertext must overlap entirely or not at all. ++// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. ++func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { ++ if len(ciphertext) < len(plaintext) { ++ panic("xts: ciphertext is smaller than plaintext") ++ } ++ if len(plaintext)%blockSize != 0 { ++ panic("xts: plaintext is not a multiple of the block size") ++ } ++ if alias.InexactOverlap(ciphertext[:len(plaintext)], plaintext) { ++ panic("xts: invalid buffer overlap") ++ } ++ ++ tweak := tweakPool.Get().(*[blockSize]byte) ++ for i := range tweak { ++ tweak[i] = 0 ++ } ++ binary.LittleEndian.PutUint64(tweak[:8], sectorNum) ++ ++ c.k2.Encrypt(tweak[:], tweak[:]) ++ ++ for len(plaintext) > 0 { ++ for j := range tweak { ++ ciphertext[j] = plaintext[j] ^ tweak[j] ++ } ++ c.k1.Encrypt(ciphertext, ciphertext) ++ for j := range tweak { ++ ciphertext[j] ^= tweak[j] ++ } ++ plaintext = plaintext[blockSize:] ++ ciphertext = ciphertext[blockSize:] ++ ++ mul2(tweak) ++ } ++ ++ tweakPool.Put(tweak) ++} ++ ++// Decrypt decrypts a sector of ciphertext and puts the result into plaintext. ++// Plaintext and ciphertext must overlap entirely or not at all. ++// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. ++func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { ++ if len(plaintext) < len(ciphertext) { ++ panic("xts: plaintext is smaller than ciphertext") ++ } ++ if len(ciphertext)%blockSize != 0 { ++ panic("xts: ciphertext is not a multiple of the block size") ++ } ++ if alias.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) { ++ panic("xts: invalid buffer overlap") ++ } ++ ++ tweak := tweakPool.Get().(*[blockSize]byte) ++ for i := range tweak { ++ tweak[i] = 0 ++ } ++ binary.LittleEndian.PutUint64(tweak[:8], sectorNum) ++ ++ c.k2.Encrypt(tweak[:], tweak[:]) ++ ++ for len(ciphertext) > 0 { ++ for j := range tweak { ++ plaintext[j] = ciphertext[j] ^ tweak[j] ++ } ++ c.k1.Decrypt(plaintext, plaintext) ++ for j := range tweak { ++ plaintext[j] ^= tweak[j] ++ } ++ plaintext = plaintext[blockSize:] ++ ciphertext = ciphertext[blockSize:] ++ ++ mul2(tweak) ++ } ++ ++ tweakPool.Put(tweak) ++} ++ ++// mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of ++// x¹²⁸ + x⁷ + xΒ² + x + 1. ++func mul2(tweak *[blockSize]byte) { ++ var carryIn byte ++ for j := range tweak { ++ carryOut := tweak[j] >> 7 ++ tweak[j] = (tweak[j] << 1) + carryIn ++ carryIn = carryOut ++ } ++ if carryIn != 0 { ++ // If we have a carry bit then we need to subtract a multiple ++ // of the irreducible polynomial (x¹²⁸ + x⁷ + xΒ² + x + 1). ++ // By dropping the carry bit, we're subtracting the x^128 term ++ // so all that remains is to subtract x⁷ + xΒ² + x + 1. ++ // Subtraction (and addition) in this representation is just ++ // XOR. ++ tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1 ++ } ++} +diff --git a/ms_mod/golang.org/x/crypto/xts/xts_test.go b/ms_mod/golang.org/x/crypto/xts/xts_test.go +new file mode 100644 +index 00000000000000..75db1c509b5910 +--- /dev/null ++++ b/ms_mod/golang.org/x/crypto/xts/xts_test.go +@@ -0,0 +1,121 @@ ++// Copyright 2012 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package xts ++ ++import ( ++ "bytes" ++ "crypto/aes" ++ "encoding/hex" ++ "testing" ++) ++ ++// These test vectors have been taken from IEEE P1619/D16, Annex B. ++var xtsTestVectors = []struct { ++ key string ++ sector uint64 ++ plaintext string ++ ciphertext string ++}{ ++ { ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ 0, ++ "0000000000000000000000000000000000000000000000000000000000000000", ++ "917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e", ++ }, { ++ "1111111111111111111111111111111122222222222222222222222222222222", ++ 0x3333333333, ++ "4444444444444444444444444444444444444444444444444444444444444444", ++ "c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0", ++ }, { ++ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222", ++ 0x3333333333, ++ "4444444444444444444444444444444444444444444444444444444444444444", ++ "af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89", ++ }, { ++ "2718281828459045235360287471352631415926535897932384626433832795", ++ 0, ++ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", ++ "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", ++ }, { ++ "2718281828459045235360287471352631415926535897932384626433832795", ++ 1, ++ "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", ++ "264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd", ++ }, { ++ "27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592", ++ 0xff, ++ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", ++ "1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151", ++ }, ++} ++ ++func fromHex(s string) []byte { ++ ret, err := hex.DecodeString(s) ++ if err != nil { ++ panic("xts: invalid hex in test") ++ } ++ return ret ++} ++ ++func TestXTS(t *testing.T) { ++ for i, test := range xtsTestVectors { ++ c, err := NewCipher(aes.NewCipher, fromHex(test.key)) ++ if err != nil { ++ t.Errorf("#%d: failed to create cipher: %s", i, err) ++ continue ++ } ++ plaintext := fromHex(test.plaintext) ++ ciphertext := make([]byte, len(plaintext)) ++ c.Encrypt(ciphertext, plaintext, test.sector) ++ ++ expectedCiphertext := fromHex(test.ciphertext) ++ if !bytes.Equal(ciphertext, expectedCiphertext) { ++ t.Errorf("#%d: encrypted failed, got: %x, want: %x", i, ciphertext, expectedCiphertext) ++ continue ++ } ++ ++ decrypted := make([]byte, len(ciphertext)) ++ c.Decrypt(decrypted, ciphertext, test.sector) ++ if !bytes.Equal(decrypted, plaintext) { ++ t.Errorf("#%d: decryption failed, got: %x, want: %x", i, decrypted, plaintext) ++ } ++ } ++} ++ ++func TestShorterCiphertext(t *testing.T) { ++ // Decrypt used to panic if the input was shorter than the output. See ++ // https://go-review.googlesource.com/c/39954/ ++ c, err := NewCipher(aes.NewCipher, make([]byte, 32)) ++ if err != nil { ++ t.Fatalf("NewCipher failed: %s", err) ++ } ++ ++ plaintext := make([]byte, 32) ++ encrypted := make([]byte, 48) ++ decrypted := make([]byte, 48) ++ ++ c.Encrypt(encrypted, plaintext, 0) ++ c.Decrypt(decrypted, encrypted[:len(plaintext)], 0) ++ ++ if !bytes.Equal(plaintext, decrypted[:len(plaintext)]) { ++ t.Errorf("En/Decryption is not inverse") ++ } ++} ++ ++func BenchmarkXTS(b *testing.B) { ++ b.ReportAllocs() ++ c, err := NewCipher(aes.NewCipher, make([]byte, 32)) ++ if err != nil { ++ b.Fatalf("NewCipher failed: %s", err) ++ } ++ plaintext := make([]byte, 32) ++ encrypted := make([]byte, 48) ++ decrypted := make([]byte, 48) ++ ++ for i := 0; i < b.N; i++ { ++ c.Encrypt(encrypted, plaintext, 0) ++ c.Decrypt(decrypted, encrypted[:len(plaintext)], 0) ++ } ++} From 923f2469a34db86dbf4b972e5bdea92e134ca08a Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Fri, 15 Sep 2023 00:26:06 -0500 Subject: [PATCH 2/7] Fill in SupportsHash temporarily --- patches/0004-Add-OpenSSL-crypto-backend.patch | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/patches/0004-Add-OpenSSL-crypto-backend.patch b/patches/0004-Add-OpenSSL-crypto-backend.patch index 4491091b373..62f451b0329 100644 --- a/patches/0004-Add-OpenSSL-crypto-backend.patch +++ b/patches/0004-Add-OpenSSL-crypto-backend.patch @@ -14,7 +14,7 @@ Subject: [PATCH] Add OpenSSL crypto backend src/crypto/ecdsa/notboring.go | 2 +- src/crypto/internal/backend/bbig/big.go | 2 +- .../internal/backend/bbig/big_openssl.go | 12 + - src/crypto/internal/backend/openssl_linux.go | 253 ++++++++++++++++++ + src/crypto/internal/backend/openssl_linux.go | 259 ++++++++++++++++++ src/crypto/internal/boring/fipstls/stub.s | 2 +- src/crypto/internal/boring/fipstls/tls.go | 2 +- src/crypto/rsa/boring.go | 2 +- @@ -37,7 +37,7 @@ Subject: [PATCH] Add OpenSSL crypto backend .../goexperiment/exp_opensslcrypto_on.go | 9 + src/internal/goexperiment/flags.go | 1 + src/os/exec/exec_test.go | 9 + - 33 files changed, 353 insertions(+), 24 deletions(-) + 33 files changed, 359 insertions(+), 24 deletions(-) create mode 100644 src/crypto/internal/backend/bbig/big_openssl.go create mode 100644 src/crypto/internal/backend/openssl_linux.go create mode 100644 src/internal/goexperiment/exp_opensslcrypto_off.go @@ -190,10 +190,10 @@ index 00000000000000..e6695dd66b1d02 +var Dec = bbig.Dec diff --git a/src/crypto/internal/backend/openssl_linux.go b/src/crypto/internal/backend/openssl_linux.go new file mode 100644 -index 00000000000000..31e28bd1ac31e4 +index 00000000000000..f554d0a2bb99bb --- /dev/null +++ b/src/crypto/internal/backend/openssl_linux.go -@@ -0,0 +1,253 @@ +@@ -0,0 +1,259 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -336,7 +336,13 @@ index 00000000000000..31e28bd1ac31e4 +// xcrypto_backend_map:noescape +func SHA3_512(p []byte) (sum [64]byte) { return openssl.SHA3_512(p) } + -+func SupportsHash(h crypto.Hash) bool { return openssl.SupportsHash(h) } ++func SupportsHash(h crypto.Hash) bool { ++ switch h { ++ case crypto.SHA3_224, crypto.SHA3_256, crypto.SHA3_384, crypto.SHA3_512: ++ return openssl.SupportsSHA3() ++ } ++ return true ++} + +func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { return openssl.NewHMAC(h, key) } + From aebc16098bc4a558609bfd2f610a7c557cba2b1c Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Mon, 25 Sep 2023 19:04:55 -0500 Subject: [PATCH 3/7] Incorporate _ms_mod gen in build cmd --- .gitmodules | 5 + eng/_core/cmd/build/build.go | 26 + .../submodule-refresh/submodule-refresh.go | 4 +- eng/_core/go.mod | 2 + eng/_core/go.sum | 392 + eng/_core/submodule/submodule.go | 182 +- eng/pipeline/steps/init-submodule-task.yml | 4 +- modules/README.md | 10 + modules/golang.org/x/crypto | 1 + patches/0009-Add-xcryptobackendswap.patch | 85 +- patches/0010-Add-modified-x-crypto.patch | 107284 --------------- 11 files changed, 660 insertions(+), 107335 deletions(-) create mode 100644 eng/_core/go.sum create mode 100644 modules/README.md create mode 160000 modules/golang.org/x/crypto delete mode 100644 patches/0010-Add-modified-x-crypto.patch diff --git a/.gitmodules b/.gitmodules index 5dcf2a0b56d..ad144c41ffc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,8 @@ [submodule "go"] path = go url = https://github.com/golang/go + urlInternal = https://dnceng@dev.azure.com/dnceng/internal/_git/microsoft-go-mirror +[submodule "eng/modules/golang.org/x/crypto"] + path = modules/golang.org/x/crypto + url = https://github.com/dagood/golang_xcrypto + urlInternal = https://dnceng@dev.azure.com/dnceng/internal/_git/microsoft-go-xcrypto-fork-placeholder diff --git a/eng/_core/cmd/build/build.go b/eng/_core/cmd/build/build.go index abe731e7e30..d180036e830 100644 --- a/eng/_core/cmd/build/build.go +++ b/eng/_core/cmd/build/build.go @@ -50,6 +50,15 @@ func main() { &o.Refresh, "refresh", false, "Refresh Go submodule: clean untracked files, reset tracked files, and apply patches before building.\n"+ "For more refresh options, use the top level 'submodule-refresh' command instead of 'build'.") + flag.BoolVar( + &o.SkipMSMod, "skipmsmod", false, + "Skip creating the _ms_mod directory with the x/crypto fork to be used by the XCryptoSwap experiment.\n"+ + "Note: tests will fail. The patched standard library test suite will notice if the the backend isn't used for x/crypto.\n"+ + "A alternate way to fix tests without _ms_mod generation is to set MS_MODROOT to a manually created fork.") + flag.BoolVar( + &o.CleanMSMod, "cleanmsmod", false, + "Remove _ms_mod directory when the build is complete.\n"+ + "This may be useful during development to run tests without polluting the Go submodule's working tree.") flag.StringVar(&o.Experiment, "experiment", "", "Include this string in GOEXPERIMENT.") @@ -84,6 +93,8 @@ type options struct { PackBuild bool PackSource bool Refresh bool + SkipMSMod bool + CleanMSMod bool Experiment string MaxMakeAttempts int @@ -120,6 +131,21 @@ func build(o *options) error { } } + if !o.SkipMSMod { + fmt.Println("---- Generating _ms_mod...") + if err := submodule.GenerateMSMod(rootDir); err != nil { + return fmt.Errorf("failed to generate _ms_mod: %v", err) + } + } + if o.CleanMSMod { + defer func() { + fmt.Println("---- Cleanup: removing _ms_mod directory...") + if err := submodule.RemoveMSMod(rootDir); err != nil { + fmt.Printf("---- Error removing _ms_mod directory: %v\n", err) + } + }() + } + // Get the target platform information. If the environment variable is different from the // runtime value, this means we're doing a cross-compiled build. These values are used for // capability checks and to make sure that if Pack is enabled, the output archive is formatted diff --git a/eng/_core/cmd/submodule-refresh/submodule-refresh.go b/eng/_core/cmd/submodule-refresh/submodule-refresh.go index 9566fb11511..f06bff0a732 100644 --- a/eng/_core/cmd/submodule-refresh/submodule-refresh.go +++ b/eng/_core/cmd/submodule-refresh/submodule-refresh.go @@ -20,7 +20,7 @@ applies patches to the stage by default, or optionally as commits. var commits = flag.Bool("commits", false, "Apply the patches as commits.") var skipPatch = flag.Bool("skip-patch", false, "Skip applying patches.") -var origin = flag.String("origin", "", "Use this origin instead of the default defined in '.gitmodules' to fetch the repository.") +var internal = flag.Bool("internal", false, "Use the .gitmodules urlInternal instead of url to clone submodules.") var shallow = flag.Bool("shallow", false, "Clone the submodule with depth 1.") var fetchBearerToken = flag.String("fetch-bearer-token", "", "Use this bearer token to fetch the submodule repository.") @@ -50,7 +50,7 @@ func main() { } func refresh(rootDir string) error { - if err := submodule.Init(rootDir, *origin, *fetchBearerToken, *shallow); err != nil { + if err := submodule.Init(rootDir, *internal, *fetchBearerToken, *shallow); err != nil { return err } diff --git a/eng/_core/go.mod b/eng/_core/go.mod index 62207065ccf..7c3e504ffb4 100644 --- a/eng/_core/go.mod +++ b/eng/_core/go.mod @@ -5,3 +5,5 @@ module github.com/microsoft/go/_core go 1.16 + +require github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d diff --git a/eng/_core/go.sum b/eng/_core/go.sum new file mode 100644 index 00000000000..cbcd037b401 --- /dev/null +++ b/eng/_core/go.sum @@ -0,0 +1,392 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY= +github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d h1:2dYhK+YQIwmN5n/AImhvU6Krn48vgWGCcuvwLb1wEJ4= +github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d/go.mod h1:hGTlq0ZBZVmZwHgV+JezVdi8jZ2f4/UydeYvMVjAJLM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/eng/_core/submodule/submodule.go b/eng/_core/submodule/submodule.go index 6fb4d54bb03..a544fac6b44 100644 --- a/eng/_core/submodule/submodule.go +++ b/eng/_core/submodule/submodule.go @@ -9,17 +9,25 @@ import ( "os" "os/exec" "path/filepath" + "strings" + + "github.com/microsoft/go-infra/executil" + "github.com/microsoft/go-infra/xcryptofork" ) // Init initializes and updates the submodule, but does not clean it. This func offers more options // for initialization than Reset. If origin is defined, fetch the submodule from there instead of // the default defined in '.gitmodules'. If fetchBearerToken is nonempty, use it as a bearer token // during the fetch. If shallow is true, clone the submodule with depth 1. -func Init(rootDir, origin, fetchBearerToken string, shallow bool) error { +func Init(rootDir string, internal bool, fetchBearerToken string, shallow bool) error { // Update the submodule commit, and initialize if it hasn't been done already. command := []string{"git"} - if origin != "" { - command = append(command, "-c", "submodule.go.url="+origin) + if internal { + var err error + command, err = appendURLInternalGitConfigArgs(rootDir, command) + if err != nil { + return err + } } if fetchBearerToken != "" { command = append(command, "-c", "http.extraheader=AUTHORIZATION: bearer "+fetchBearerToken) @@ -44,23 +52,10 @@ func Reset(rootDir string) error { return err } - // Find toplevel directories (Git working tree roots) for the outer repo and what we expect to - // be the Go submodule. If the toplevel directory is the same for both, make sure not to clean! - // The submodule likely wasn't set up properly, and cleaning could result in unexpectedly losing - // work in the outer repo when the command spills over. - rootToplevel, err := getToplevel(rootDir) - if err != nil { - return err - } - goToplevel, err := getToplevel(goDir) - if err != nil { + if err := assertSubmoduleInitialized(rootDir, goDir); err != nil { return err } - if rootToplevel == goToplevel { - return fmt.Errorf("go submodule (%v) toplevel is the same as root (%v) toplevel: %v", goDir, rootDir, goToplevel) - } - // Reset the index and working directory. This doesn't clean up new untracked files. if err := run(goDir, "git", "reset", "--hard"); err != nil { return err @@ -74,6 +69,159 @@ func Reset(rootDir string) error { return nil } +// GenerateMSMod creates the _ms_mod directory with x/crypto fork and generates +// the crypto backend proxies based on the backends currently in the Go +// submodule source tree. +func GenerateMSMod(rootDir string) error { + cryptoSrcDir := filepath.Join(rootDir, "modules", "golang.org", "x", "crypto") + if err := assertSubmoduleInitialized(rootDir, cryptoSrcDir); err != nil { + return err + } + goDir := filepath.Join(rootDir, "go") + if err := assertSubmoduleInitialized(rootDir, goDir); err != nil { + return err + } + // Target directory for the x/crypto fork. + cryptoDir := filepath.Join(goDir, "_ms_mod", "golang.org", "x", "crypto") + // Clean it up. No prompt: there shouldn't be any need to do dev work in + // this directory. + if err := os.RemoveAll(cryptoDir); err != nil { + return err + } + if err := os.MkdirAll(cryptoDir, 0o777); err != nil { + return err + } + if err := xcryptofork.GitCheckoutTo(cryptoSrcDir, cryptoDir); err != nil { + return err + } + // Generate the backend proxies and the nobackend file based on the backends + // in the active Go tree. The placeholder in x/crypto is ignored: it's only + // there so the x/crypto fork will compile outside this context. + backendDir := filepath.Join(goDir, "src", "crypto", "internal", "backend") + backends, err := xcryptofork.FindBackendFiles(backendDir) + if err != nil { + return fmt.Errorf("failed to find backend files in %q: %v", backendDir, err) + } + proxyDir := filepath.Join(cryptoDir, "internal", "backend") + if err := os.RemoveAll(proxyDir); err != nil { + return err + } + // First, find the nobackend. It defines the API for the backend proxies. + const nobackendBase = "nobackend.go" + var backendAPI *xcryptofork.BackendFile + for _, b := range backends { + if filepath.Base(b.Filename) == nobackendBase { + if err := b.APITrim(); err != nil { + return fmt.Errorf("failed to trim %q into an API for proxies: %v", b.Filename, err) + } + // If someone uses the x/crypto fork but doesn't use a backend, they + // will need this nobackend.go for their build to succeed. + if err := writeBackend(b, filepath.Join(proxyDir, nobackendBase)); err != nil { + return fmt.Errorf("failed to write API based on %q: %v", b.Filename, err) + } + backendAPI = b + break + } + } + if backendAPI == nil { + return fmt.Errorf("%q not found in %v", nobackendBase, backendDir) + } + // Create a proxy for each backend. + for _, b := range backends { + if b == backendAPI { + continue + } + proxy, err := b.ProxyAPI(backendAPI) + if err != nil { + return fmt.Errorf("failed to turn %q into a proxy: %v", b.Filename, err) + } + if err := writeBackend(proxy, filepath.Join(proxyDir, filepath.Base(b.Filename))); err != nil { + return fmt.Errorf("failed to write proxy based on %q: %v", b.Filename, err) + } + } + return nil +} + +func RemoveMSMod(rootDir string) error { + msMod := filepath.Join(rootDir, "go", "_ms_mod") + entries, err := os.ReadDir(msMod) + if err != nil { + return err + } + for _, e := range entries { + if !e.IsDir() { + continue + } + if err := os.RemoveAll(filepath.Join(msMod, e.Name())); err != nil { + return err + } + } + return nil +} + +func writeBackend(b xcryptofork.FormattedWriterTo, path string) error { + if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil { + return err + } + apiFile, err := os.Create(path) + if err != nil { + return err + } + err = b.Format(apiFile) + if err2 := apiFile.Close(); err == nil { + err = err2 + } + return err +} + +func appendURLInternalGitConfigArgs(rootDir string, args []string) ([]string, error) { + cmd := exec.Command( + "git", "config", + "-f", ".gitmodules", + "-z", // Null char separator: avoid confusion with newlines in values. + "--get-regexp", `submodule\..*\.urlInternal`) + cmd.Dir = rootDir + out, err := executil.CombinedOutput(cmd) + if err != nil { + return nil, err + } + pairs := strings.Split(out, "\x00") + for _, pair := range pairs { + key, value, ok := strings.Cut(pair, "\n") + if !ok { + return nil, fmt.Errorf("invalid key-value pair: %v", pair) + } + args = append(args, "-c", strings.TrimSuffix(key, "Internal")+"="+value) + } + return args, nil +} + +// assertSubmoduleInitialized runs a basic check to ensure the submodule within +// the specified root repo is initialized. It finds toplevel directories (Git +// working tree roots) for the outer repo and what we expect to be the Go +// submodule. If the toplevel directory is the same for both, the submodule +// likely wasn't set up properly, and (e.g.) cleaning the submodule dir could +// result in unexpectedly losing work in the rootDir when the command spills +// over and affects the outer repo. +// +// There may be other ways to check whether the submodule is initialized, but +// this check at the very least helps at the most painful potential symptom of +// an uninitialized submodule: lost work. +func assertSubmoduleInitialized(rootDir, submoduleRootDir string) error { + rootToplevel, err := getToplevel(rootDir) + if err != nil { + return err + } + submoduleToplevel, err := getToplevel(submoduleRootDir) + if err != nil { + return err + } + if rootToplevel == submoduleToplevel { + return fmt.Errorf("go submodule (%v) toplevel is the same as root (%v) toplevel: %v", submoduleToplevel, rootDir, submoduleToplevel) + } + return nil +} + func getToplevel(dir string) (string, error) { c := exec.Command("git", "rev-parse", "--show-toplevel") c.Dir = dir diff --git a/eng/pipeline/steps/init-submodule-task.yml b/eng/pipeline/steps/init-submodule-task.yml index 3ad5392f146..4a01496b7d0 100644 --- a/eng/pipeline/steps/init-submodule-task.yml +++ b/eng/pipeline/steps/init-submodule-task.yml @@ -10,9 +10,7 @@ steps: } if ("$env:FETCH_BEARER_TOKEN") { - fetch_submodule ` - -origin 'https://dnceng@dev.azure.com/dnceng/internal/_git/microsoft-go-mirror' ` - -fetch-bearer-token $env:FETCH_BEARER_TOKEN + fetch_submodule -internal -fetch-bearer-token $env:FETCH_BEARER_TOKEN } else { fetch_submodule } diff --git a/modules/README.md b/modules/README.md new file mode 100644 index 00000000000..899290ee2c0 --- /dev/null +++ b/modules/README.md @@ -0,0 +1,10 @@ +This directory contains sources used to create the toolset override modules. +The Microsoft Go toolset ships with a directory that contains modules that (optionally) replace the modules a `go build` command would use. + +Replacing `x/crypto` with a version of `x/crypto` that uses the OpenSSL and CNG backends is the primary use case. +Some processing is needed to produce the final result that fits the current toolset. +This directory contains the starting point that we plan to share with other Go toolset forks. + +This will change to point at either: +* a shared repo that contains an `x/crypto` submodule and a set of patches, or +* a new repo with pre-applied patches, not a repo that doesn't use patches at all and is maintained as a simple branch fork. diff --git a/modules/golang.org/x/crypto b/modules/golang.org/x/crypto new file mode 160000 index 00000000000..a1aeb9b34eb --- /dev/null +++ b/modules/golang.org/x/crypto @@ -0,0 +1 @@ +Subproject commit a1aeb9b34eb6b8f469bbd66b9cd1c9d905cb3714 diff --git a/patches/0009-Add-xcryptobackendswap.patch b/patches/0009-Add-xcryptobackendswap.patch index 78df7a3854b..e982ed1e81c 100644 --- a/patches/0009-Add-xcryptobackendswap.patch +++ b/patches/0009-Add-xcryptobackendswap.patch @@ -6,7 +6,8 @@ Subject: [PATCH] Add xcryptobackendswap Use '-modfile' for x/crypto replacement when the xcryptobackendswap experiment is enabled. -Points at an x/crypto copy in the GOROOT directory. +Points at an x/crypto copy in the GOROOT directory or an override +provided by the MS_MODROOT environment variable. Includes tests for x/crypto backend swap, using the standard library cmd/go test framework to run tests on the swapping functionality. @@ -15,22 +16,23 @@ These can be run without running the other tests using: go test cmd/go -testwork -run=Script/^modswap_.*$ --- - ms_mod/README.md | 5 + + _ms_mod/README.md | 7 + src/cmd/go/internal/modload/import.go | 6 +- src/cmd/go/internal/modload/init.go | 10 ++ src/cmd/go/internal/modload/vendor.go | 16 ++ - src/cmd/go/internal/modload/xcryptoswap.go | 152 ++++++++++++++++++ - src/cmd/go/testdata/script/modswap_basics.txt | 65 ++++++++ + src/cmd/go/internal/modload/xcryptoswap.go | 165 ++++++++++++++++++ + src/cmd/go/testdata/script/modswap_basics.txt | 65 +++++++ .../script/modswap_compatible_vendoring.txt | 40 +++++ - .../go/testdata/script/modswap_nocrypto.txt | 28 ++++ + .../go/testdata/script/modswap_nocrypto.txt | 28 +++ .../testdata/script/modswap_reject_work.txt | 22 +++ .../testdata/script/modswap_test_openssl.txt | 43 +++++ .../testdata/script/modswap_uses_openssl.txt | 60 +++++++ - .../exp_xcryptobackendswap_off.go | 9 ++ - .../goexperiment/exp_xcryptobackendswap_on.go | 9 ++ + src/internal/cfg/cfg.go | 1 + + .../exp_xcryptobackendswap_off.go | 9 + + .../goexperiment/exp_xcryptobackendswap_on.go | 9 + src/internal/goexperiment/flags.go | 6 + - 14 files changed, 470 insertions(+), 1 deletion(-) - create mode 100644 ms_mod/README.md + 15 files changed, 486 insertions(+), 1 deletion(-) + create mode 100644 _ms_mod/README.md create mode 100644 src/cmd/go/internal/modload/xcryptoswap.go create mode 100644 src/cmd/go/testdata/script/modswap_basics.txt create mode 100644 src/cmd/go/testdata/script/modswap_compatible_vendoring.txt @@ -41,17 +43,19 @@ These can be run without running the other tests using: create mode 100644 src/internal/goexperiment/exp_xcryptobackendswap_off.go create mode 100644 src/internal/goexperiment/exp_xcryptobackendswap_on.go -diff --git a/ms_mod/README.md b/ms_mod/README.md +diff --git a/_ms_mod/README.md b/_ms_mod/README.md new file mode 100644 -index 00000000000000..cc658f4a25528d +index 00000000000000..3db282dd1701e7 --- /dev/null -+++ b/ms_mod/README.md -@@ -0,0 +1,5 @@ -+# ms_mod: Microsoft modules shipped with the Go toolset ++++ b/_ms_mod/README.md +@@ -0,0 +1,7 @@ ++# _ms_mod: Microsoft modules shipped with the Go toolset + +This dir contains modules that are shipped with the Microsoft Go toolset. +It is essentially a vendor directory that takes priority over a project's local vendor directory. +Patches to the toolset enable this behavior if `GOEXPERIMENT` includes `xcryptobackendswap`. ++ ++It begins with `_` to avoid being scanned by the `cmd/internal/moddeps` `TestAllDependencies` test. diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index cc6a482fd450d0..16f056c042481c 100644 --- a/src/cmd/go/internal/modload/import.go @@ -126,10 +130,10 @@ index b2cb44100ec4d2..23bee33d44d1ba 100644 diff --git a/src/cmd/go/internal/modload/xcryptoswap.go b/src/cmd/go/internal/modload/xcryptoswap.go new file mode 100644 -index 00000000000000..be7b46ded2be0a +index 00000000000000..5b367cd14385f1 --- /dev/null +++ b/src/cmd/go/internal/modload/xcryptoswap.go -@@ -0,0 +1,152 @@ +@@ -0,0 +1,165 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -217,11 +221,19 @@ index 00000000000000..be7b46ded2be0a + if !modFileUsesXCrypto(modFile) && cfg.BuildMod != "mod" { + return nil + } ++ // Make sure the replacement actually exists. Perhaps the module was packed ++ // wrong, or MS_MODROOT is set incorrectly. ++ newModPath := xCryptoNewModPath() ++ if fi, err := os.Stat(newModPath); err != nil { ++ return fmt.Errorf("unable to get FileInfo for replacement path: %v", err) ++ } else if !fi.IsDir() { ++ return fmt.Errorf("replacement %#q is not a directory", newModPath) ++ } + // Add (or update!) a replace directive. + modFile.AddReplace( + "golang.org/x/crypto", + "", -+ xCryptoNewModPath(), ++ newModPath, + "", + ) + modFile.Cleanup() @@ -257,11 +269,16 @@ index 00000000000000..be7b46ded2be0a + return false +} + -+// toolsetOverrideModuleDir returns the path to a directory in GOROOT where copies of modules are -+// kept that may be used when building a program with that particular toolset. It is similar to a -+// vendor directory, but only contains the modules, no modules.txt. ++// toolsetOverrideModuleDir returns the path to a directory in GOROOT where ++// copies of modules are kept that may be used when building a program with that ++// particular toolset. It is similar to a vendor directory, but only contains ++// the modules, no modules.txt. For development purposes, the MS_MODROOT ++// environment variable can redirect to a specified directory. +func toolsetOverrideModuleDir() string { -+ return filepath.Join(cfg.BuildContext.GOROOT, "ms_mod") ++ if msModRoot := cfg.Getenv("MS_MODROOT"); msModRoot != "" { ++ return msModRoot ++ } ++ return filepath.Join(cfg.BuildContext.GOROOT, "_ms_mod") +} + +// xCryptoNewModPath returns the module path that x/crypto should be replaced with. @@ -284,7 +301,7 @@ index 00000000000000..be7b46ded2be0a +} diff --git a/src/cmd/go/testdata/script/modswap_basics.txt b/src/cmd/go/testdata/script/modswap_basics.txt new file mode 100644 -index 00000000000000..0f28da05789d1c +index 00000000000000..c1a938be44dc45 --- /dev/null +++ b/src/cmd/go/testdata/script/modswap_basics.txt @@ -0,0 +1,65 @@ @@ -303,11 +320,11 @@ index 00000000000000..0f28da05789d1c + +# When vendoring isn't involved, the replacement path is used. +go list -mod= -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto +go list -mod=mod -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto +go list -mod=readonly -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto + +# Make sure the build works other than vendor mode. +go build -mod= . @@ -326,13 +343,13 @@ index 00000000000000..0f28da05789d1c +# Now that vendoring is involved, still use the replacement path. +env GOEXPERIMENT=systemcrypto,xcryptobackendswap +go list -mod= -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto +go list -mod=mod -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto +go list -mod=readonly -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto +go list -mod=vendor -deps -f '{{.Dir}}' -+stdout $GOROOT/ms_mod/golang.org/x/crypto ++stdout $GOROOT/_ms_mod/golang.org/x/crypto + +# Make sure the build works and is always the same. +go build -mod= -o no_mod.out . @@ -576,6 +593,16 @@ index 00000000000000..03cbd2ca4a81ac + t.Errorf("want %q, got %q", wantTypeName, typeName) + } +} +diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go +index 2af0ec70786894..585cc01a9137e3 100644 +--- a/src/internal/cfg/cfg.go ++++ b/src/internal/cfg/cfg.go +@@ -67,4 +67,5 @@ const KnownEnv = ` + GOWORK + GO_EXTLINK_ENABLED + PKG_CONFIG ++ MS_MODROOT + ` diff --git a/src/internal/goexperiment/exp_xcryptobackendswap_off.go b/src/internal/goexperiment/exp_xcryptobackendswap_off.go new file mode 100644 index 00000000000000..8fceaa28b7e6f0 diff --git a/patches/0010-Add-modified-x-crypto.patch b/patches/0010-Add-modified-x-crypto.patch deleted file mode 100644 index 6861099b7e0..00000000000 --- a/patches/0010-Add-modified-x-crypto.patch +++ /dev/null @@ -1,107284 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Davis Goodin -Date: Thu, 14 Sep 2023 16:29:00 -0700 -Subject: [PATCH] Add modified x/crypto - -Uses xcryptobackendgen to generate a modified copy of x/crypto that uses -the crypto backends defined in this toolset. - -From the microsoft/go repository root: - - xcryptobackendgen \ - -fork \ - -backend go/src/crypto/internal/backend \ - -out go/ms_mod/golang.org/x/crypto ---- - ms_mod/golang.org/x/crypto/.gitattributes | 10 + - ms_mod/golang.org/x/crypto/.gitignore | 2 + - ms_mod/golang.org/x/crypto/CONTRIBUTING.md | 26 + - ms_mod/golang.org/x/crypto/LICENSE | 27 + - ms_mod/golang.org/x/crypto/PATENTS | 22 + - ms_mod/golang.org/x/crypto/README.md | 23 + - ms_mod/golang.org/x/crypto/acme/acme.go | 818 ++++ - ms_mod/golang.org/x/crypto/acme/acme_test.go | 855 ++++ - .../x/crypto/acme/autocert/autocert.go | 1198 ++++++ - .../x/crypto/acme/autocert/autocert_test.go | 996 +++++ - .../x/crypto/acme/autocert/cache.go | 135 + - .../x/crypto/acme/autocert/cache_test.go | 66 + - .../x/crypto/acme/autocert/example_test.go | 35 + - .../acme/autocert/internal/acmetest/ca.go | 796 ++++ - .../x/crypto/acme/autocert/listener.go | 155 + - .../x/crypto/acme/autocert/renewal.go | 156 + - .../x/crypto/acme/autocert/renewal_test.go | 269 ++ - ms_mod/golang.org/x/crypto/acme/http.go | 325 ++ - ms_mod/golang.org/x/crypto/acme/http_test.go | 255 ++ - .../crypto/acme/internal/acmeprobe/prober.go | 433 ++ - ms_mod/golang.org/x/crypto/acme/jws.go | 257 ++ - ms_mod/golang.org/x/crypto/acme/jws_test.go | 550 +++ - ms_mod/golang.org/x/crypto/acme/rfc8555.go | 476 ++ - .../golang.org/x/crypto/acme/rfc8555_test.go | 1017 +++++ - ms_mod/golang.org/x/crypto/acme/types.go | 614 +++ - ms_mod/golang.org/x/crypto/acme/types_test.go | 219 + - .../golang.org/x/crypto/acme/version_go112.go | 28 + - ms_mod/golang.org/x/crypto/argon2/argon2.go | 283 ++ - .../golang.org/x/crypto/argon2/argon2_test.go | 233 + - ms_mod/golang.org/x/crypto/argon2/blake2b.go | 53 + - .../x/crypto/argon2/blamka_amd64.go | 61 + - .../golang.org/x/crypto/argon2/blamka_amd64.s | 244 ++ - .../x/crypto/argon2/blamka_generic.go | 163 + - .../golang.org/x/crypto/argon2/blamka_ref.go | 16 + - ms_mod/golang.org/x/crypto/bcrypt/base64.go | 35 + - ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go | 304 ++ - .../golang.org/x/crypto/bcrypt/bcrypt_test.go | 250 ++ - ms_mod/golang.org/x/crypto/blake2b/blake2b.go | 291 ++ - .../x/crypto/blake2b/blake2bAVX2_amd64.go | 38 + - .../x/crypto/blake2b/blake2bAVX2_amd64.s | 745 ++++ - .../x/crypto/blake2b/blake2b_amd64.go | 25 + - .../x/crypto/blake2b/blake2b_amd64.s | 279 ++ - .../x/crypto/blake2b/blake2b_generic.go | 182 + - .../x/crypto/blake2b/blake2b_ref.go | 12 + - .../x/crypto/blake2b/blake2b_test.go | 847 ++++ - ms_mod/golang.org/x/crypto/blake2b/blake2x.go | 177 + - .../golang.org/x/crypto/blake2b/register.go | 33 + - ms_mod/golang.org/x/crypto/blake2s/blake2s.go | 246 ++ - .../x/crypto/blake2s/blake2s_386.go | 33 + - .../golang.org/x/crypto/blake2s/blake2s_386.s | 430 ++ - .../x/crypto/blake2s/blake2s_amd64.go | 38 + - .../x/crypto/blake2s/blake2s_amd64.s | 433 ++ - .../x/crypto/blake2s/blake2s_generic.go | 178 + - .../x/crypto/blake2s/blake2s_ref.go | 18 + - .../x/crypto/blake2s/blake2s_test.go | 1050 +++++ - ms_mod/golang.org/x/crypto/blake2s/blake2x.go | 178 + - .../golang.org/x/crypto/blake2s/register.go | 22 + - ms_mod/golang.org/x/crypto/blowfish/block.go | 159 + - .../x/crypto/blowfish/blowfish_test.go | 274 ++ - ms_mod/golang.org/x/crypto/blowfish/cipher.go | 99 + - ms_mod/golang.org/x/crypto/blowfish/const.go | 199 + - ms_mod/golang.org/x/crypto/bn256/bn256.go | 429 ++ - .../golang.org/x/crypto/bn256/bn256_test.go | 304 ++ - ms_mod/golang.org/x/crypto/bn256/constants.go | 44 + - ms_mod/golang.org/x/crypto/bn256/curve.go | 287 ++ - .../golang.org/x/crypto/bn256/example_test.go | 43 + - ms_mod/golang.org/x/crypto/bn256/gfp12.go | 200 + - ms_mod/golang.org/x/crypto/bn256/gfp2.go | 219 + - ms_mod/golang.org/x/crypto/bn256/gfp6.go | 296 ++ - ms_mod/golang.org/x/crypto/bn256/optate.go | 395 ++ - ms_mod/golang.org/x/crypto/bn256/twist.go | 258 ++ - ms_mod/golang.org/x/crypto/cast5/cast5.go | 536 +++ - .../golang.org/x/crypto/cast5/cast5_test.go | 106 + - .../x/crypto/chacha20/chacha_arm64.go | 17 + - .../x/crypto/chacha20/chacha_arm64.s | 308 ++ - .../x/crypto/chacha20/chacha_generic.go | 398 ++ - .../x/crypto/chacha20/chacha_noasm.go | 14 + - .../x/crypto/chacha20/chacha_ppc64le.go | 17 + - .../x/crypto/chacha20/chacha_ppc64le.s | 450 ++ - .../x/crypto/chacha20/chacha_s390x.go | 28 + - .../x/crypto/chacha20/chacha_s390x.s | 225 + - .../x/crypto/chacha20/chacha_test.go | 274 ++ - .../x/crypto/chacha20/vectors_test.go | 511 +++ - ms_mod/golang.org/x/crypto/chacha20/xor.go | 42 + - .../chacha20poly1305/chacha20poly1305.go | 98 + - .../chacha20poly1305_amd64.go | 87 + - .../chacha20poly1305/chacha20poly1305_amd64.s | 2696 ++++++++++++ - .../chacha20poly1305_generic.go | 81 + - .../chacha20poly1305_noasm.go | 16 + - .../chacha20poly1305/chacha20poly1305_test.go | 268 ++ - .../chacha20poly1305_vectors_test.go | 727 ++++ - .../chacha20poly1305/xchacha20poly1305.go | 86 + - ms_mod/golang.org/x/crypto/codereview.cfg | 1 + - ms_mod/golang.org/x/crypto/cryptobyte/asn1.go | 824 ++++ - .../x/crypto/cryptobyte/asn1/asn1.go | 46 + - .../x/crypto/cryptobyte/asn1_test.go | 435 ++ - .../golang.org/x/crypto/cryptobyte/builder.go | 345 ++ - .../x/crypto/cryptobyte/cryptobyte_test.go | 536 +++ - .../x/crypto/cryptobyte/example_test.go | 154 + - .../golang.org/x/crypto/cryptobyte/string.go | 172 + - .../x/crypto/curve25519/curve25519.go | 59 + - .../x/crypto/curve25519/curve25519_compat.go | 105 + - .../x/crypto/curve25519/curve25519_go120.go | 46 + - .../x/crypto/curve25519/curve25519_test.go | 142 + - .../x/crypto/curve25519/internal/field/README | 7 + - .../internal/field/_asm/fe_amd64_asm.go | 298 ++ - .../curve25519/internal/field/_asm/go.mod | 10 + - .../curve25519/internal/field/_asm/go.sum | 34 + - .../x/crypto/curve25519/internal/field/fe.go | 416 ++ - .../internal/field/fe_alias_test.go | 126 + - .../curve25519/internal/field/fe_amd64.go | 16 + - .../curve25519/internal/field/fe_amd64.s | 379 ++ - .../internal/field/fe_amd64_noasm.go | 12 + - .../curve25519/internal/field/fe_arm64.go | 16 + - .../curve25519/internal/field/fe_arm64.s | 43 + - .../internal/field/fe_arm64_noasm.go | 12 + - .../internal/field/fe_bench_test.go | 36 + - .../curve25519/internal/field/fe_generic.go | 264 ++ - .../curve25519/internal/field/fe_test.go | 558 +++ - .../curve25519/internal/field/sync.checkpoint | 1 + - .../crypto/curve25519/internal/field/sync.sh | 19 + - .../x/crypto/curve25519/vectors_test.go | 105 + - ms_mod/golang.org/x/crypto/ed25519/ed25519.go | 71 + - .../x/crypto/ed25519/ed25519_test.go | 22 + - ms_mod/golang.org/x/crypto/go.mod | 11 + - ms_mod/golang.org/x/crypto/go.sum | 41 + - .../golang.org/x/crypto/hkdf/example_test.go | 56 + - ms_mod/golang.org/x/crypto/hkdf/hkdf.go | 95 + - ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go | 449 ++ - .../x/crypto/internal/alias/alias.go | 32 + - .../x/crypto/internal/alias/alias_purego.go | 35 + - .../x/crypto/internal/alias/alias_test.go | 46 + - .../x/crypto/internal/backend/boring_linux.go | 95 + - .../x/crypto/internal/backend/cng_windows.go | 77 + - .../x/crypto/internal/backend/nobackend.go | 49 + - .../crypto/internal/backend/openssl_linux.go | 69 + - .../x/crypto/internal/poly1305/bits_compat.go | 40 + - .../x/crypto/internal/poly1305/bits_go1.13.go | 22 + - .../x/crypto/internal/poly1305/mac_noasm.go | 10 + - .../x/crypto/internal/poly1305/poly1305.go | 99 + - .../crypto/internal/poly1305/poly1305_test.go | 276 ++ - .../x/crypto/internal/poly1305/sum_amd64.go | 48 + - .../x/crypto/internal/poly1305/sum_amd64.s | 109 + - .../x/crypto/internal/poly1305/sum_generic.go | 309 ++ - .../x/crypto/internal/poly1305/sum_ppc64le.go | 48 + - .../x/crypto/internal/poly1305/sum_ppc64le.s | 182 + - .../x/crypto/internal/poly1305/sum_s390x.go | 77 + - .../x/crypto/internal/poly1305/sum_s390x.s | 504 +++ - .../crypto/internal/poly1305/vectors_test.go | 3000 +++++++++++++ - .../x/crypto/internal/testenv/exec.go | 120 + - .../internal/testenv/testenv_notunix.go | 15 + - .../x/crypto/internal/testenv/testenv_unix.go | 15 + - .../x/crypto/internal/wycheproof/README.md | 12 + - .../x/crypto/internal/wycheproof/aead_test.go | 176 + - .../internal/wycheproof/aes_cbc_test.go | 127 + - .../x/crypto/internal/wycheproof/boring.go | 9 + - .../x/crypto/internal/wycheproof/dsa_test.go | 123 + - .../internal/wycheproof/ecdh_stdlib_test.go | 142 + - .../x/crypto/internal/wycheproof/ecdh_test.go | 163 + - .../crypto/internal/wycheproof/ecdsa_test.go | 105 + - .../crypto/internal/wycheproof/eddsa_test.go | 101 + - .../x/crypto/internal/wycheproof/hkdf_test.go | 111 + - .../x/crypto/internal/wycheproof/hmac_test.go | 105 + - .../internal/wycheproof/internal/dsa/dsa.go | 33 + - .../x/crypto/internal/wycheproof/notboring.go | 9 + - .../wycheproof/rsa_oaep_decrypt_test.go | 149 + - .../internal/wycheproof/rsa_pss_test.go | 169 + - .../internal/wycheproof/rsa_signature_test.go | 123 + - .../internal/wycheproof/wycheproof_test.go | 141 + - .../golang.org/x/crypto/md4/example_test.go | 20 + - ms_mod/golang.org/x/crypto/md4/md4.go | 122 + - ms_mod/golang.org/x/crypto/md4/md4_test.go | 71 + - ms_mod/golang.org/x/crypto/md4/md4block.go | 91 + - ms_mod/golang.org/x/crypto/nacl/auth/auth.go | 58 + - .../x/crypto/nacl/auth/auth_test.go | 172 + - .../x/crypto/nacl/auth/example_test.go | 36 + - ms_mod/golang.org/x/crypto/nacl/box/box.go | 182 + - .../golang.org/x/crypto/nacl/box/box_test.go | 181 + - .../x/crypto/nacl/box/example_test.go | 95 + - .../x/crypto/nacl/secretbox/example_test.go | 53 + - .../x/crypto/nacl/secretbox/secretbox.go | 173 + - .../x/crypto/nacl/secretbox/secretbox_test.go | 154 + - ms_mod/golang.org/x/crypto/nacl/sign/sign.go | 90 + - .../x/crypto/nacl/sign/sign_test.go | 74 + - ms_mod/golang.org/x/crypto/ocsp/ocsp.go | 792 ++++ - ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go | 746 ++++ - .../x/crypto/openpgp/armor/armor.go | 232 + - .../x/crypto/openpgp/armor/armor_test.go | 95 + - .../x/crypto/openpgp/armor/encode.go | 161 + - .../x/crypto/openpgp/canonical_text.go | 59 + - .../x/crypto/openpgp/canonical_text_test.go | 52 + - .../x/crypto/openpgp/clearsign/clearsign.go | 424 ++ - .../openpgp/clearsign/clearsign_test.go | 398 ++ - .../x/crypto/openpgp/elgamal/elgamal.go | 130 + - .../x/crypto/openpgp/elgamal/elgamal_test.go | 64 + - .../x/crypto/openpgp/errors/errors.go | 78 + - ms_mod/golang.org/x/crypto/openpgp/keys.go | 693 +++ - .../x/crypto/openpgp/keys_data_test.go | 200 + - .../golang.org/x/crypto/openpgp/keys_test.go | 495 +++ - .../x/crypto/openpgp/packet/compressed.go | 123 + - .../crypto/openpgp/packet/compressed_test.go | 40 + - .../x/crypto/openpgp/packet/config.go | 91 + - .../x/crypto/openpgp/packet/encrypted_key.go | 208 + - .../openpgp/packet/encrypted_key_test.go | 220 + - .../x/crypto/openpgp/packet/literal.go | 89 + - .../x/crypto/openpgp/packet/ocfb.go | 143 + - .../x/crypto/openpgp/packet/ocfb_test.go | 46 + - .../openpgp/packet/one_pass_signature.go | 73 + - .../x/crypto/openpgp/packet/opaque.go | 161 + - .../x/crypto/openpgp/packet/opaque_test.go | 67 + - .../x/crypto/openpgp/packet/packet.go | 590 +++ - .../x/crypto/openpgp/packet/packet_test.go | 290 ++ - .../x/crypto/openpgp/packet/private_key.go | 384 ++ - .../crypto/openpgp/packet/private_key_test.go | 249 ++ - .../x/crypto/openpgp/packet/public_key.go | 753 ++++ - .../crypto/openpgp/packet/public_key_test.go | 228 + - .../x/crypto/openpgp/packet/public_key_v3.go | 279 ++ - .../openpgp/packet/public_key_v3_test.go | 82 + - .../x/crypto/openpgp/packet/reader.go | 76 + - .../x/crypto/openpgp/packet/signature.go | 731 ++++ - .../x/crypto/openpgp/packet/signature_test.go | 78 + - .../x/crypto/openpgp/packet/signature_v3.go | 146 + - .../openpgp/packet/signature_v3_test.go | 96 + - .../openpgp/packet/symmetric_key_encrypted.go | 155 + - .../packet/symmetric_key_encrypted_test.go | 116 + - .../openpgp/packet/symmetrically_encrypted.go | 290 ++ - .../packet/symmetrically_encrypted_test.go | 122 + - .../x/crypto/openpgp/packet/userattribute.go | 90 + - .../openpgp/packet/userattribute_test.go | 109 + - .../x/crypto/openpgp/packet/userid.go | 159 + - .../x/crypto/openpgp/packet/userid_test.go | 87 + - ms_mod/golang.org/x/crypto/openpgp/read.go | 448 ++ - .../golang.org/x/crypto/openpgp/read_test.go | 612 +++ - ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go | 279 ++ - .../x/crypto/openpgp/s2k/s2k_test.go | 137 + - ms_mod/golang.org/x/crypto/openpgp/write.go | 418 ++ - .../golang.org/x/crypto/openpgp/write_test.go | 361 ++ - .../x/crypto/otr/libotr_test_helper.c | 197 + - ms_mod/golang.org/x/crypto/otr/otr.go | 1419 ++++++ - ms_mod/golang.org/x/crypto/otr/otr_test.go | 470 ++ - ms_mod/golang.org/x/crypto/otr/smp.go | 572 +++ - ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go | 77 + - .../golang.org/x/crypto/pbkdf2/pbkdf2_test.go | 176 + - .../golang.org/x/crypto/pkcs12/bmp-string.go | 50 + - .../x/crypto/pkcs12/bmp-string_test.go | 63 + - ms_mod/golang.org/x/crypto/pkcs12/crypto.go | 131 + - .../golang.org/x/crypto/pkcs12/crypto_test.go | 125 + - ms_mod/golang.org/x/crypto/pkcs12/errors.go | 23 + - .../crypto/pkcs12/internal/rc2/bench_test.go | 27 + - .../x/crypto/pkcs12/internal/rc2/rc2.go | 268 ++ - .../x/crypto/pkcs12/internal/rc2/rc2_test.go | 92 + - ms_mod/golang.org/x/crypto/pkcs12/mac.go | 45 + - ms_mod/golang.org/x/crypto/pkcs12/mac_test.go | 42 + - ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go | 170 + - .../golang.org/x/crypto/pkcs12/pbkdf_test.go | 34 + - ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go | 360 ++ - .../golang.org/x/crypto/pkcs12/pkcs12_test.go | 141 + - ms_mod/golang.org/x/crypto/pkcs12/safebags.go | 57 + - .../x/crypto/poly1305/poly1305_compat.go | 91 + - .../x/crypto/ripemd160/ripemd160.go | 124 + - .../x/crypto/ripemd160/ripemd160_test.go | 72 + - .../x/crypto/ripemd160/ripemd160block.go | 165 + - .../x/crypto/salsa20/salsa/hsalsa20.go | 146 + - .../x/crypto/salsa20/salsa/salsa208.go | 201 + - .../x/crypto/salsa20/salsa/salsa20_amd64.go | 24 + - .../x/crypto/salsa20/salsa/salsa20_amd64.s | 881 ++++ - .../salsa20/salsa/salsa20_amd64_test.go | 32 + - .../x/crypto/salsa20/salsa/salsa20_noasm.go | 15 + - .../x/crypto/salsa20/salsa/salsa20_ref.go | 233 + - .../x/crypto/salsa20/salsa/salsa_test.go | 54 + - ms_mod/golang.org/x/crypto/salsa20/salsa20.go | 58 + - .../x/crypto/salsa20/salsa20_test.go | 139 + - .../x/crypto/scrypt/example_test.go | 26 + - ms_mod/golang.org/x/crypto/scrypt/scrypt.go | 212 + - .../golang.org/x/crypto/scrypt/scrypt_test.go | 162 + - ms_mod/golang.org/x/crypto/sha3/doc.go | 62 + - ms_mod/golang.org/x/crypto/sha3/hashes.go | 116 + - .../x/crypto/sha3/hashes_generic.go | 28 + - ms_mod/golang.org/x/crypto/sha3/keccakf.go | 415 ++ - .../golang.org/x/crypto/sha3/keccakf_amd64.go | 14 + - .../golang.org/x/crypto/sha3/keccakf_amd64.s | 391 ++ - ms_mod/golang.org/x/crypto/sha3/register.go | 19 + - ms_mod/golang.org/x/crypto/sha3/sha3.go | 193 + - ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go | 287 ++ - ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s | 34 + - ms_mod/golang.org/x/crypto/sha3/sha3_test.go | 490 +++ - ms_mod/golang.org/x/crypto/sha3/shake.go | 173 + - .../golang.org/x/crypto/sha3/shake_generic.go | 20 + - .../sha3/testdata/keccakKats.json.deflate | Bin 0 -> 540828 bytes - ms_mod/golang.org/x/crypto/sha3/xor.go | 24 + - .../golang.org/x/crypto/sha3/xor_generic.go | 28 + - .../golang.org/x/crypto/sha3/xor_unaligned.go | 68 + - .../golang.org/x/crypto/ssh/agent/client.go | 849 ++++ - .../x/crypto/ssh/agent/client_test.go | 537 +++ - .../x/crypto/ssh/agent/example_test.go | 41 + - .../golang.org/x/crypto/ssh/agent/forward.go | 103 + - .../golang.org/x/crypto/ssh/agent/keyring.go | 241 ++ - .../x/crypto/ssh/agent/keyring_test.go | 76 + - .../golang.org/x/crypto/ssh/agent/server.go | 570 +++ - .../x/crypto/ssh/agent/server_test.go | 262 ++ - .../x/crypto/ssh/agent/testdata_test.go | 64 + - .../golang.org/x/crypto/ssh/benchmark_test.go | 127 + - ms_mod/golang.org/x/crypto/ssh/buffer.go | 97 + - ms_mod/golang.org/x/crypto/ssh/buffer_test.go | 87 + - ms_mod/golang.org/x/crypto/ssh/certs.go | 589 +++ - ms_mod/golang.org/x/crypto/ssh/certs_test.go | 320 ++ - ms_mod/golang.org/x/crypto/ssh/channel.go | 633 +++ - ms_mod/golang.org/x/crypto/ssh/cipher.go | 789 ++++ - ms_mod/golang.org/x/crypto/ssh/cipher_test.go | 231 + - ms_mod/golang.org/x/crypto/ssh/client.go | 282 ++ - ms_mod/golang.org/x/crypto/ssh/client_auth.go | 725 ++++ - .../x/crypto/ssh/client_auth_test.go | 1078 +++++ - ms_mod/golang.org/x/crypto/ssh/client_test.go | 346 ++ - ms_mod/golang.org/x/crypto/ssh/common.go | 471 ++ - ms_mod/golang.org/x/crypto/ssh/common_test.go | 176 + - ms_mod/golang.org/x/crypto/ssh/connection.go | 143 + - ms_mod/golang.org/x/crypto/ssh/doc.go | 22 + - .../golang.org/x/crypto/ssh/example_test.go | 320 ++ - ms_mod/golang.org/x/crypto/ssh/handshake.go | 735 ++++ - .../golang.org/x/crypto/ssh/handshake_test.go | 622 +++ - .../ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go | 93 + - .../bcrypt_pbkdf/bcrypt_pbkdf_test.go | 97 + - ms_mod/golang.org/x/crypto/ssh/kex.go | 786 ++++ - ms_mod/golang.org/x/crypto/ssh/kex_test.go | 106 + - ms_mod/golang.org/x/crypto/ssh/keys.go | 1447 +++++++ - ms_mod/golang.org/x/crypto/ssh/keys_test.go | 618 +++ - .../x/crypto/ssh/knownhosts/knownhosts.go | 540 +++ - .../crypto/ssh/knownhosts/knownhosts_test.go | 356 ++ - ms_mod/golang.org/x/crypto/ssh/mac.go | 68 + - .../golang.org/x/crypto/ssh/mempipe_test.go | 110 + - ms_mod/golang.org/x/crypto/ssh/messages.go | 877 ++++ - .../golang.org/x/crypto/ssh/messages_test.go | 288 ++ - ms_mod/golang.org/x/crypto/ssh/mux.go | 351 ++ - ms_mod/golang.org/x/crypto/ssh/mux_test.go | 761 ++++ - ms_mod/golang.org/x/crypto/ssh/server.go | 774 ++++ - ms_mod/golang.org/x/crypto/ssh/session.go | 647 +++ - .../golang.org/x/crypto/ssh/session_test.go | 845 ++++ - ms_mod/golang.org/x/crypto/ssh/ssh_gss.go | 139 + - .../golang.org/x/crypto/ssh/ssh_gss_test.go | 109 + - ms_mod/golang.org/x/crypto/ssh/streamlocal.go | 116 + - ms_mod/golang.org/x/crypto/ssh/tcpip.go | 474 ++ - ms_mod/golang.org/x/crypto/ssh/tcpip_test.go | 20 + - .../x/crypto/ssh/terminal/terminal.go | 76 + - .../x/crypto/ssh/test/agent_unix_test.go | 59 + - .../x/crypto/ssh/test/banner_test.go | 32 + - .../golang.org/x/crypto/ssh/test/cert_test.go | 77 + - .../x/crypto/ssh/test/dial_unix_test.go | 127 + - ms_mod/golang.org/x/crypto/ssh/test/doc.go | 7 + - .../x/crypto/ssh/test/forward_unix_test.go | 198 + - .../x/crypto/ssh/test/multi_auth_test.go | 144 + - .../x/crypto/ssh/test/session_test.go | 455 ++ - .../x/crypto/ssh/test/sshd_test_pw.c | 173 + - .../x/crypto/ssh/test/test_unix_test.go | 364 ++ - .../x/crypto/ssh/test/testdata_test.go | 64 + - .../golang.org/x/crypto/ssh/testdata/doc.go | 8 + - .../golang.org/x/crypto/ssh/testdata/keys.go | 314 ++ - .../golang.org/x/crypto/ssh/testdata_test.go | 63 + - ms_mod/golang.org/x/crypto/ssh/transport.go | 358 ++ - .../golang.org/x/crypto/ssh/transport_test.go | 113 + - ms_mod/golang.org/x/crypto/tea/cipher.go | 116 + - ms_mod/golang.org/x/crypto/tea/tea_test.go | 93 + - ms_mod/golang.org/x/crypto/twofish/twofish.go | 341 ++ - .../x/crypto/twofish/twofish_test.go | 129 + - .../x/crypto/x509roots/fallback/bundle.go | 3827 +++++++++++++++++ - .../x/crypto/x509roots/fallback/fallback.go | 31 + - .../x/crypto/x509roots/fallback/go.mod | 3 + - .../internal/goissue52287/goissue52287.go | 8 + - .../x/crypto/x509roots/gen_fallback_bundle.go | 135 + - .../x/crypto/x509roots/nss/parser.go | 259 ++ - .../x/crypto/x509roots/nss/parser_test.go | 1216 ++++++ - ms_mod/golang.org/x/crypto/xtea/block.go | 66 + - ms_mod/golang.org/x/crypto/xtea/cipher.go | 90 + - ms_mod/golang.org/x/crypto/xtea/xtea_test.go | 229 + - ms_mod/golang.org/x/crypto/xts/xts.go | 164 + - ms_mod/golang.org/x/crypto/xts/xts_test.go | 121 + - 375 files changed, 93859 insertions(+) - create mode 100644 ms_mod/golang.org/x/crypto/.gitattributes - create mode 100644 ms_mod/golang.org/x/crypto/.gitignore - create mode 100644 ms_mod/golang.org/x/crypto/CONTRIBUTING.md - create mode 100644 ms_mod/golang.org/x/crypto/LICENSE - create mode 100644 ms_mod/golang.org/x/crypto/PATENTS - create mode 100644 ms_mod/golang.org/x/crypto/README.md - create mode 100644 ms_mod/golang.org/x/crypto/acme/acme.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/acme_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/autocert.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/cache.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/listener.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/renewal.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/http.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/http_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/jws.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/jws_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/rfc8555.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/rfc8555_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/types.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/types_test.go - create mode 100644 ms_mod/golang.org/x/crypto/acme/version_go112.go - create mode 100644 ms_mod/golang.org/x/crypto/argon2/argon2.go - create mode 100644 ms_mod/golang.org/x/crypto/argon2/argon2_test.go - create mode 100644 ms_mod/golang.org/x/crypto/argon2/blake2b.go - create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/argon2/blamka_ref.go - create mode 100644 ms_mod/golang.org/x/crypto/bcrypt/base64.go - create mode 100644 ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go - create mode 100644 ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/blake2x.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2b/register.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/blake2x.go - create mode 100644 ms_mod/golang.org/x/crypto/blake2s/register.go - create mode 100644 ms_mod/golang.org/x/crypto/blowfish/block.go - create mode 100644 ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go - create mode 100644 ms_mod/golang.org/x/crypto/blowfish/cipher.go - create mode 100644 ms_mod/golang.org/x/crypto/blowfish/const.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/bn256.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/bn256_test.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/constants.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/curve.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/gfp12.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/gfp2.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/gfp6.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/optate.go - create mode 100644 ms_mod/golang.org/x/crypto/bn256/twist.go - create mode 100644 ms_mod/golang.org/x/crypto/cast5/cast5.go - create mode 100644 ms_mod/golang.org/x/crypto/cast5/cast5_test.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/chacha_test.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/vectors_test.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20/xor.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go - create mode 100644 ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go - create mode 100644 ms_mod/golang.org/x/crypto/codereview.cfg - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/asn1.go - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/builder.go - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/cryptobyte/string.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/README - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh - create mode 100644 ms_mod/golang.org/x/crypto/curve25519/vectors_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ed25519/ed25519.go - create mode 100644 ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go - create mode 100644 ms_mod/golang.org/x/crypto/go.mod - create mode 100644 ms_mod/golang.org/x/crypto/go.sum - create mode 100644 ms_mod/golang.org/x/crypto/hkdf/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/hkdf/hkdf.go - create mode 100644 ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/alias/alias.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/alias/alias_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/nobackend.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s - create mode 100644 ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/testenv/exec.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/README.md - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go - create mode 100644 ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go - create mode 100644 ms_mod/golang.org/x/crypto/md4/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/md4/md4.go - create mode 100644 ms_mod/golang.org/x/crypto/md4/md4_test.go - create mode 100644 ms_mod/golang.org/x/crypto/md4/md4block.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/auth/auth.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/auth/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/box/box.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/box/box_test.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/box/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/sign/sign.go - create mode 100644 ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ocsp/ocsp.go - create mode 100644 ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/armor/armor.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/armor/encode.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/canonical_text.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/errors/errors.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/keys.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/keys_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/config.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/literal.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/packet.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/reader.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userid.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/read.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/read_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/write.go - create mode 100644 ms_mod/golang.org/x/crypto/openpgp/write_test.go - create mode 100644 ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c - create mode 100644 ms_mod/golang.org/x/crypto/otr/otr.go - create mode 100644 ms_mod/golang.org/x/crypto/otr/otr_test.go - create mode 100644 ms_mod/golang.org/x/crypto/otr/smp.go - create mode 100644 ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go - create mode 100644 ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/crypto.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/errors.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/mac.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/mac_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go - create mode 100644 ms_mod/golang.org/x/crypto/pkcs12/safebags.go - create mode 100644 ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go - create mode 100644 ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go - create mode 100644 ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa20.go - create mode 100644 ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go - create mode 100644 ms_mod/golang.org/x/crypto/scrypt/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/scrypt/scrypt.go - create mode 100644 ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/doc.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/hashes.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/hashes_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/keccakf.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s - create mode 100644 ms_mod/golang.org/x/crypto/sha3/register.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s - create mode 100644 ms_mod/golang.org/x/crypto/sha3/sha3_test.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/shake.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/shake_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate - create mode 100644 ms_mod/golang.org/x/crypto/sha3/xor.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/xor_generic.go - create mode 100644 ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/client.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/client_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/forward.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/keyring.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/server.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/server_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/benchmark_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/buffer.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/buffer_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/certs.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/certs_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/channel.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/cipher.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/cipher_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/client.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/client_auth.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/client_auth_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/client_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/common.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/common_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/connection.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/doc.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/example_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/handshake.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/handshake_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/kex.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/kex_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/keys.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/keys_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/mac.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/mempipe_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/messages.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/messages_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/mux.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/mux_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/server.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/session.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/session_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/ssh_gss.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/streamlocal.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/tcpip.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/tcpip_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/banner_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/cert_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/doc.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/session_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/testdata/doc.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/testdata/keys.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/testdata_test.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/transport.go - create mode 100644 ms_mod/golang.org/x/crypto/ssh/transport_test.go - create mode 100644 ms_mod/golang.org/x/crypto/tea/cipher.go - create mode 100644 ms_mod/golang.org/x/crypto/tea/tea_test.go - create mode 100644 ms_mod/golang.org/x/crypto/twofish/twofish.go - create mode 100644 ms_mod/golang.org/x/crypto/twofish/twofish_test.go - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/nss/parser.go - create mode 100644 ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go - create mode 100644 ms_mod/golang.org/x/crypto/xtea/block.go - create mode 100644 ms_mod/golang.org/x/crypto/xtea/cipher.go - create mode 100644 ms_mod/golang.org/x/crypto/xtea/xtea_test.go - create mode 100644 ms_mod/golang.org/x/crypto/xts/xts.go - create mode 100644 ms_mod/golang.org/x/crypto/xts/xts_test.go - -diff --git a/ms_mod/golang.org/x/crypto/.gitattributes b/ms_mod/golang.org/x/crypto/.gitattributes -new file mode 100644 -index 00000000000000..d2f212e5da80c5 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/.gitattributes -@@ -0,0 +1,10 @@ -+# Treat all files in this repo as binary, with no git magic updating -+# line endings. Windows users contributing to Go will need to use a -+# modern version of git and editors capable of LF line endings. -+# -+# We'll prevent accidental CRLF line endings from entering the repo -+# via the git-review gofmt checks. -+# -+# See golang.org/issue/9281 -+ -+* -text -diff --git a/ms_mod/golang.org/x/crypto/.gitignore b/ms_mod/golang.org/x/crypto/.gitignore -new file mode 100644 -index 00000000000000..5a9d62efd40246 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/.gitignore -@@ -0,0 +1,2 @@ -+# Add no patterns to .gitignore except for files generated by the build. -+last-change -diff --git a/ms_mod/golang.org/x/crypto/CONTRIBUTING.md b/ms_mod/golang.org/x/crypto/CONTRIBUTING.md -new file mode 100644 -index 00000000000000..d0485e887a2b59 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/CONTRIBUTING.md -@@ -0,0 +1,26 @@ -+# Contributing to Go -+ -+Go is an open source project. -+ -+It is the work of hundreds of contributors. We appreciate your help! -+ -+## Filing issues -+ -+When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: -+ -+1. What version of Go are you using (`go version`)? -+2. What operating system and processor architecture are you using? -+3. What did you do? -+4. What did you expect to see? -+5. What did you see instead? -+ -+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -+The gophers there will answer or ask you to file an issue if you've tripped over a bug. -+ -+## Contributing code -+ -+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -+before sending patches. -+ -+Unless otherwise noted, the Go source files are distributed under -+the BSD-style license found in the LICENSE file. -diff --git a/ms_mod/golang.org/x/crypto/LICENSE b/ms_mod/golang.org/x/crypto/LICENSE -new file mode 100644 -index 00000000000000..6a66aea5eafe0c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/LICENSE -@@ -0,0 +1,27 @@ -+Copyright (c) 2009 The Go Authors. All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions are -+met: -+ -+ * Redistributions of source code must retain the above copyright -+notice, this list of conditions and the following disclaimer. -+ * Redistributions in binary form must reproduce the above -+copyright notice, this list of conditions and the following disclaimer -+in the documentation and/or other materials provided with the -+distribution. -+ * Neither the name of Google Inc. nor the names of its -+contributors may be used to endorse or promote products derived from -+this software without specific prior written permission. -+ -+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -diff --git a/ms_mod/golang.org/x/crypto/PATENTS b/ms_mod/golang.org/x/crypto/PATENTS -new file mode 100644 -index 00000000000000..733099041f84fa ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/PATENTS -@@ -0,0 +1,22 @@ -+Additional IP Rights Grant (Patents) -+ -+"This implementation" means the copyrightable works distributed by -+Google as part of the Go project. -+ -+Google hereby grants to You a perpetual, worldwide, non-exclusive, -+no-charge, royalty-free, irrevocable (except as stated in this section) -+patent license to make, have made, use, offer to sell, sell, import, -+transfer and otherwise run, modify and propagate the contents of this -+implementation of Go, where such license applies only to those patent -+claims, both currently owned or controlled by Google and acquired in -+the future, licensable by Google that are necessarily infringed by this -+implementation of Go. This grant does not include claims that would be -+infringed only as a consequence of further modification of this -+implementation. If you or your agent or exclusive licensee institute or -+order or agree to the institution of patent litigation against any -+entity (including a cross-claim or counterclaim in a lawsuit) alleging -+that this implementation of Go or any code incorporated within this -+implementation of Go constitutes direct or contributory patent -+infringement, or inducement of patent infringement, then any patent -+rights granted to you under this License for this implementation of Go -+shall terminate as of the date such litigation is filed. -diff --git a/ms_mod/golang.org/x/crypto/README.md b/ms_mod/golang.org/x/crypto/README.md -new file mode 100644 -index 00000000000000..92f73cdfbfeeb8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/README.md -@@ -0,0 +1,23 @@ -+# Go Cryptography -+ -+[![Go Reference](https://pkg.go.dev/badge/golang.org/x/crypto.svg)](https://pkg.go.dev/golang.org/x/crypto) -+ -+This repository holds supplementary Go cryptography libraries. -+ -+## Download/Install -+ -+The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You -+can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`. -+ -+## Report Issues / Send Patches -+ -+This repository uses Gerrit for code changes. To learn how to submit changes to -+this repository, see https://golang.org/doc/contribute.html. -+ -+The main issue tracker for the crypto repository is located at -+https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the -+subject line, so it is easy to find. -+ -+Note that contributions to the cryptography package receive additional scrutiny -+due to their sensitive nature. Patches may take longer than normal to receive -+feedback. -diff --git a/ms_mod/golang.org/x/crypto/acme/acme.go b/ms_mod/golang.org/x/crypto/acme/acme.go -new file mode 100644 -index 00000000000000..aaafea2bc08296 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/acme.go -@@ -0,0 +1,818 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package acme provides an implementation of the -+// Automatic Certificate Management Environment (ACME) spec, -+// most famously used by Let's Encrypt. -+// -+// The initial implementation of this package was based on an early version -+// of the spec. The current implementation supports only the modern -+// RFC 8555 but some of the old API surface remains for compatibility. -+// While code using the old API will still compile, it will return an error. -+// Note the deprecation comments to update your code. -+// -+// See https://tools.ietf.org/html/rfc8555 for the spec. -+// -+// Most common scenarios will want to use autocert subdirectory instead, -+// which provides automatic access to certificates from Let's Encrypt -+// and any other ACME-based CA. -+package acme -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/sha256" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/hex" -+ "encoding/json" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "math/big" -+ "net/http" -+ "strings" -+ "sync" -+ "time" -+) -+ -+const ( -+ // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. -+ LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory" -+ -+ // ALPNProto is the ALPN protocol name used by a CA server when validating -+ // tls-alpn-01 challenges. -+ // -+ // Package users must ensure their servers can negotiate the ACME ALPN in -+ // order for tls-alpn-01 challenge verifications to succeed. -+ // See the crypto/tls package's Config.NextProtos field. -+ ALPNProto = "acme-tls/1" -+) -+ -+// idPeACMEIdentifier is the OID for the ACME extension for the TLS-ALPN challenge. -+// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1 -+var idPeACMEIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} -+ -+const ( -+ maxChainLen = 5 // max depth and breadth of a certificate chain -+ maxCertSize = 1 << 20 // max size of a certificate, in DER bytes -+ // Used for decoding certs from application/pem-certificate-chain response, -+ // the default when in RFC mode. -+ maxCertChainSize = maxCertSize * maxChainLen -+ -+ // Max number of collected nonces kept in memory. -+ // Expect usual peak of 1 or 2. -+ maxNonces = 100 -+) -+ -+// Client is an ACME client. -+// -+// The only required field is Key. An example of creating a client with a new key -+// is as follows: -+// -+// key, err := rsa.GenerateKey(rand.Reader, 2048) -+// if err != nil { -+// log.Fatal(err) -+// } -+// client := &Client{Key: key} -+type Client struct { -+ // Key is the account key used to register with a CA and sign requests. -+ // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey. -+ // -+ // The following algorithms are supported: -+ // RS256, ES256, ES384 and ES512. -+ // See RFC 7518 for more details about the algorithms. -+ Key crypto.Signer -+ -+ // HTTPClient optionally specifies an HTTP client to use -+ // instead of http.DefaultClient. -+ HTTPClient *http.Client -+ -+ // DirectoryURL points to the CA directory endpoint. -+ // If empty, LetsEncryptURL is used. -+ // Mutating this value after a successful call of Client's Discover method -+ // will have no effect. -+ DirectoryURL string -+ -+ // RetryBackoff computes the duration after which the nth retry of a failed request -+ // should occur. The value of n for the first call on failure is 1. -+ // The values of r and resp are the request and response of the last failed attempt. -+ // If the returned value is negative or zero, no more retries are done and an error -+ // is returned to the caller of the original method. -+ // -+ // Requests which result in a 4xx client error are not retried, -+ // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests. -+ // -+ // If RetryBackoff is nil, a truncated exponential backoff algorithm -+ // with the ceiling of 10 seconds is used, where each subsequent retry n -+ // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter), -+ // preferring the former if "Retry-After" header is found in the resp. -+ // The jitter is a random value up to 1 second. -+ RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration -+ -+ // UserAgent is prepended to the User-Agent header sent to the ACME server, -+ // which by default is this package's name and version. -+ // -+ // Reusable libraries and tools in particular should set this value to be -+ // identifiable by the server, in case they are causing issues. -+ UserAgent string -+ -+ cacheMu sync.Mutex -+ dir *Directory // cached result of Client's Discover method -+ // KID is the key identifier provided by the CA. If not provided it will be -+ // retrieved from the CA by making a call to the registration endpoint. -+ KID KeyID -+ -+ noncesMu sync.Mutex -+ nonces map[string]struct{} // nonces collected from previous responses -+} -+ -+// accountKID returns a key ID associated with c.Key, the account identity -+// provided by the CA during RFC based registration. -+// It assumes c.Discover has already been called. -+// -+// accountKID requires at most one network roundtrip. -+// It caches only successful result. -+// -+// When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID -+// returns noKeyID. -+func (c *Client) accountKID(ctx context.Context) KeyID { -+ c.cacheMu.Lock() -+ defer c.cacheMu.Unlock() -+ if c.KID != noKeyID { -+ return c.KID -+ } -+ a, err := c.getRegRFC(ctx) -+ if err != nil { -+ return noKeyID -+ } -+ c.KID = KeyID(a.URI) -+ return c.KID -+} -+ -+var errPreRFC = errors.New("acme: server does not support the RFC 8555 version of ACME") -+ -+// Discover performs ACME server discovery using c.DirectoryURL. -+// -+// It caches successful result. So, subsequent calls will not result in -+// a network round-trip. This also means mutating c.DirectoryURL after successful call -+// of this method will have no effect. -+func (c *Client) Discover(ctx context.Context) (Directory, error) { -+ c.cacheMu.Lock() -+ defer c.cacheMu.Unlock() -+ if c.dir != nil { -+ return *c.dir, nil -+ } -+ -+ res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK)) -+ if err != nil { -+ return Directory{}, err -+ } -+ defer res.Body.Close() -+ c.addNonce(res.Header) -+ -+ var v struct { -+ Reg string `json:"newAccount"` -+ Authz string `json:"newAuthz"` -+ Order string `json:"newOrder"` -+ Revoke string `json:"revokeCert"` -+ Nonce string `json:"newNonce"` -+ KeyChange string `json:"keyChange"` -+ Meta struct { -+ Terms string `json:"termsOfService"` -+ Website string `json:"website"` -+ CAA []string `json:"caaIdentities"` -+ ExternalAcct bool `json:"externalAccountRequired"` -+ } -+ } -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return Directory{}, err -+ } -+ if v.Order == "" { -+ return Directory{}, errPreRFC -+ } -+ c.dir = &Directory{ -+ RegURL: v.Reg, -+ AuthzURL: v.Authz, -+ OrderURL: v.Order, -+ RevokeURL: v.Revoke, -+ NonceURL: v.Nonce, -+ KeyChangeURL: v.KeyChange, -+ Terms: v.Meta.Terms, -+ Website: v.Meta.Website, -+ CAA: v.Meta.CAA, -+ ExternalAccountRequired: v.Meta.ExternalAcct, -+ } -+ return *c.dir, nil -+} -+ -+func (c *Client) directoryURL() string { -+ if c.DirectoryURL != "" { -+ return c.DirectoryURL -+ } -+ return LetsEncryptURL -+} -+ -+// CreateCert was part of the old version of ACME. It is incompatible with RFC 8555. -+// -+// Deprecated: this was for the pre-RFC 8555 version of ACME. Callers should use CreateOrderCert. -+func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) { -+ return nil, "", errPreRFC -+} -+ -+// FetchCert retrieves already issued certificate from the given url, in DER format. -+// It retries the request until the certificate is successfully retrieved, -+// context is cancelled by the caller or an error response is received. -+// -+// If the bundle argument is true, the returned value also contains the CA (issuer) -+// certificate chain. -+// -+// FetchCert returns an error if the CA's response or chain was unreasonably large. -+// Callers are encouraged to parse the returned value to ensure the certificate is valid -+// and has expected features. -+func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.fetchCertRFC(ctx, url, bundle) -+} -+ -+// RevokeCert revokes a previously issued certificate cert, provided in DER format. -+// -+// The key argument, used to sign the request, must be authorized -+// to revoke the certificate. It's up to the CA to decide which keys are authorized. -+// For instance, the key pair of the certificate may be authorized. -+// If the key is nil, c.Key is used instead. -+func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { -+ if _, err := c.Discover(ctx); err != nil { -+ return err -+ } -+ return c.revokeCertRFC(ctx, key, cert, reason) -+} -+ -+// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service -+// during account registration. See Register method of Client for more details. -+func AcceptTOS(tosURL string) bool { return true } -+ -+// Register creates a new account with the CA using c.Key. -+// It returns the registered account. The account acct is not modified. -+// -+// The registration may require the caller to agree to the CA's Terms of Service (TOS). -+// If so, and the account has not indicated the acceptance of the terms (see Account for details), -+// Register calls prompt with a TOS URL provided by the CA. Prompt should report -+// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS. -+// -+// When interfacing with an RFC-compliant CA, non-RFC 8555 fields of acct are ignored -+// and prompt is called if Directory's Terms field is non-zero. -+// Also see Error's Instance field for when a CA requires already registered accounts to agree -+// to an updated Terms of Service. -+func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { -+ if c.Key == nil { -+ return nil, errors.New("acme: client.Key must be set to Register") -+ } -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.registerRFC(ctx, acct, prompt) -+} -+ -+// GetReg retrieves an existing account associated with c.Key. -+// -+// The url argument is a legacy artifact of the pre-RFC 8555 API -+// and is ignored. -+func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.getRegRFC(ctx) -+} -+ -+// UpdateReg updates an existing registration. -+// It returns an updated account copy. The provided account is not modified. -+// -+// The account's URI is ignored and the account URL associated with -+// c.Key is used instead. -+func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ return c.updateRegRFC(ctx, acct) -+} -+ -+// AccountKeyRollover attempts to transition a client's account key to a new key. -+// On success client's Key is updated which is not concurrency safe. -+// On failure an error will be returned. -+// The new key is already registered with the ACME provider if the following is true: -+// - error is of type acme.Error -+// - StatusCode should be 409 (Conflict) -+// - Location header will have the KID of the associated account -+// -+// More about account key rollover can be found at -+// https://tools.ietf.org/html/rfc8555#section-7.3.5. -+func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error { -+ return c.accountKeyRollover(ctx, newKey) -+} -+ -+// Authorize performs the initial step in the pre-authorization flow, -+// as opposed to order-based flow. -+// The caller will then need to choose from and perform a set of returned -+// challenges using c.Accept in order to successfully complete authorization. -+// -+// Once complete, the caller can use AuthorizeOrder which the CA -+// should provision with the already satisfied authorization. -+// For pre-RFC CAs, the caller can proceed directly to requesting a certificate -+// using CreateCert method. -+// -+// If an authorization has been previously granted, the CA may return -+// a valid authorization which has its Status field set to StatusValid. -+// -+// More about pre-authorization can be found at -+// https://tools.ietf.org/html/rfc8555#section-7.4.1. -+func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) { -+ return c.authorize(ctx, "dns", domain) -+} -+ -+// AuthorizeIP is the same as Authorize but requests IP address authorization. -+// Clients which successfully obtain such authorization may request to issue -+// a certificate for IP addresses. -+// -+// See the ACME spec extension for more details about IP address identifiers: -+// https://tools.ietf.org/html/draft-ietf-acme-ip. -+func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) { -+ return c.authorize(ctx, "ip", ipaddr) -+} -+ -+func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ type authzID struct { -+ Type string `json:"type"` -+ Value string `json:"value"` -+ } -+ req := struct { -+ Resource string `json:"resource"` -+ Identifier authzID `json:"identifier"` -+ }{ -+ Resource: "new-authz", -+ Identifier: authzID{Type: typ, Value: val}, -+ } -+ res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ var v wireAuthz -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ if v.Status != StatusPending && v.Status != StatusValid { -+ return nil, fmt.Errorf("acme: unexpected status: %s", v.Status) -+ } -+ return v.authorization(res.Header.Get("Location")), nil -+} -+ -+// GetAuthorization retrieves an authorization identified by the given URL. -+// -+// If a caller needs to poll an authorization until its status is final, -+// see the WaitAuthorization method. -+func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ var v wireAuthz -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ return v.authorization(url), nil -+} -+ -+// RevokeAuthorization relinquishes an existing authorization identified -+// by the given URL. -+// The url argument is an Authorization.URI value. -+// -+// If successful, the caller will be required to obtain a new authorization -+// using the Authorize or AuthorizeOrder methods before being able to request -+// a new certificate for the domain associated with the authorization. -+// -+// It does not revoke existing certificates. -+func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { -+ if _, err := c.Discover(ctx); err != nil { -+ return err -+ } -+ -+ req := struct { -+ Resource string `json:"resource"` -+ Status string `json:"status"` -+ Delete bool `json:"delete"` -+ }{ -+ Resource: "authz", -+ Status: "deactivated", -+ Delete: true, -+ } -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return err -+ } -+ defer res.Body.Close() -+ return nil -+} -+ -+// WaitAuthorization polls an authorization at the given URL -+// until it is in one of the final states, StatusValid or StatusInvalid, -+// the ACME CA responded with a 4xx error code, or the context is done. -+// -+// It returns a non-nil Authorization only if its Status is StatusValid. -+// In all other cases WaitAuthorization returns an error. -+// If the Status is StatusInvalid, the returned error is of type *AuthorizationError. -+func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ for { -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) -+ if err != nil { -+ return nil, err -+ } -+ -+ var raw wireAuthz -+ err = json.NewDecoder(res.Body).Decode(&raw) -+ res.Body.Close() -+ switch { -+ case err != nil: -+ // Skip and retry. -+ case raw.Status == StatusValid: -+ return raw.authorization(url), nil -+ case raw.Status == StatusInvalid: -+ return nil, raw.error(url) -+ } -+ -+ // Exponential backoff is implemented in c.get above. -+ // This is just to prevent continuously hitting the CA -+ // while waiting for a final authorization status. -+ d := retryAfter(res.Header.Get("Retry-After")) -+ if d == 0 { -+ // Given that the fastest challenges TLS-SNI and HTTP-01 -+ // require a CA to make at least 1 network round trip -+ // and most likely persist a challenge state, -+ // this default delay seems reasonable. -+ d = time.Second -+ } -+ t := time.NewTimer(d) -+ select { -+ case <-ctx.Done(): -+ t.Stop() -+ return nil, ctx.Err() -+ case <-t.C: -+ // Retry. -+ } -+ } -+} -+ -+// GetChallenge retrieves the current status of an challenge. -+// -+// A client typically polls a challenge status using this method. -+func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted)) -+ if err != nil { -+ return nil, err -+ } -+ -+ defer res.Body.Close() -+ v := wireChallenge{URI: url} -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ return v.challenge(), nil -+} -+ -+// Accept informs the server that the client accepts one of its challenges -+// previously obtained with c.Authorize. -+// -+// The server will then perform the validation asynchronously. -+func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.post(ctx, nil, chal.URI, json.RawMessage("{}"), wantStatus( -+ http.StatusOK, // according to the spec -+ http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md) -+ )) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ var v wireChallenge -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid response: %v", err) -+ } -+ return v.challenge(), nil -+} -+ -+// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response. -+// A TXT record containing the returned value must be provisioned under -+// "_acme-challenge" name of the domain being validated. -+// -+// The token argument is a Challenge.Token value. -+func (c *Client) DNS01ChallengeRecord(token string) (string, error) { -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return "", err -+ } -+ b := sha256.Sum256([]byte(ka)) -+ return base64.RawURLEncoding.EncodeToString(b[:]), nil -+} -+ -+// HTTP01ChallengeResponse returns the response for an http-01 challenge. -+// Servers should respond with the value to HTTP requests at the URL path -+// provided by HTTP01ChallengePath to validate the challenge and prove control -+// over a domain name. -+// -+// The token argument is a Challenge.Token value. -+func (c *Client) HTTP01ChallengeResponse(token string) (string, error) { -+ return keyAuth(c.Key.Public(), token) -+} -+ -+// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge -+// should be provided by the servers. -+// The response value can be obtained with HTTP01ChallengeResponse. -+// -+// The token argument is a Challenge.Token value. -+func (c *Client) HTTP01ChallengePath(token string) string { -+ return "/.well-known/acme-challenge/" + token -+} -+ -+// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response. -+// -+// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec. -+func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ b := sha256.Sum256([]byte(ka)) -+ h := hex.EncodeToString(b[:]) -+ name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:]) -+ cert, err = tlsChallengeCert([]string{name}, opt) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ return cert, name, nil -+} -+ -+// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response. -+// -+// Deprecated: This challenge type is unused in both draft-02 and RFC versions of the ACME spec. -+func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { -+ b := sha256.Sum256([]byte(token)) -+ h := hex.EncodeToString(b[:]) -+ sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:]) -+ -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ b = sha256.Sum256([]byte(ka)) -+ h = hex.EncodeToString(b[:]) -+ sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:]) -+ -+ cert, err = tlsChallengeCert([]string{sanA, sanB}, opt) -+ if err != nil { -+ return tls.Certificate{}, "", err -+ } -+ return cert, sanA, nil -+} -+ -+// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response. -+// Servers can present the certificate to validate the challenge and prove control -+// over a domain name. For more details on TLS-ALPN-01 see -+// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3 -+// -+// The token argument is a Challenge.Token value. -+// If a WithKey option is provided, its private part signs the returned cert, -+// and the public part is used to specify the signee. -+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. -+// -+// The returned certificate is valid for the next 24 hours and must be presented only when -+// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol -+// has been specified. -+func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) { -+ ka, err := keyAuth(c.Key.Public(), token) -+ if err != nil { -+ return tls.Certificate{}, err -+ } -+ shasum := sha256.Sum256([]byte(ka)) -+ extValue, err := asn1.Marshal(shasum[:]) -+ if err != nil { -+ return tls.Certificate{}, err -+ } -+ acmeExtension := pkix.Extension{ -+ Id: idPeACMEIdentifier, -+ Critical: true, -+ Value: extValue, -+ } -+ -+ tmpl := defaultTLSChallengeCertTemplate() -+ -+ var newOpt []CertOption -+ for _, o := range opt { -+ switch o := o.(type) { -+ case *certOptTemplate: -+ t := *(*x509.Certificate)(o) // shallow copy is ok -+ tmpl = &t -+ default: -+ newOpt = append(newOpt, o) -+ } -+ } -+ tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension) -+ newOpt = append(newOpt, WithTemplate(tmpl)) -+ return tlsChallengeCert([]string{domain}, newOpt) -+} -+ -+// popNonce returns a nonce value previously stored with c.addNonce -+// or fetches a fresh one from c.dir.NonceURL. -+// If NonceURL is empty, it first tries c.directoryURL() and, failing that, -+// the provided url. -+func (c *Client) popNonce(ctx context.Context, url string) (string, error) { -+ c.noncesMu.Lock() -+ defer c.noncesMu.Unlock() -+ if len(c.nonces) == 0 { -+ if c.dir != nil && c.dir.NonceURL != "" { -+ return c.fetchNonce(ctx, c.dir.NonceURL) -+ } -+ dirURL := c.directoryURL() -+ v, err := c.fetchNonce(ctx, dirURL) -+ if err != nil && url != dirURL { -+ v, err = c.fetchNonce(ctx, url) -+ } -+ return v, err -+ } -+ var nonce string -+ for nonce = range c.nonces { -+ delete(c.nonces, nonce) -+ break -+ } -+ return nonce, nil -+} -+ -+// clearNonces clears any stored nonces -+func (c *Client) clearNonces() { -+ c.noncesMu.Lock() -+ defer c.noncesMu.Unlock() -+ c.nonces = make(map[string]struct{}) -+} -+ -+// addNonce stores a nonce value found in h (if any) for future use. -+func (c *Client) addNonce(h http.Header) { -+ v := nonceFromHeader(h) -+ if v == "" { -+ return -+ } -+ c.noncesMu.Lock() -+ defer c.noncesMu.Unlock() -+ if len(c.nonces) >= maxNonces { -+ return -+ } -+ if c.nonces == nil { -+ c.nonces = make(map[string]struct{}) -+ } -+ c.nonces[v] = struct{}{} -+} -+ -+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) { -+ r, err := http.NewRequest("HEAD", url, nil) -+ if err != nil { -+ return "", err -+ } -+ resp, err := c.doNoRetry(ctx, r) -+ if err != nil { -+ return "", err -+ } -+ defer resp.Body.Close() -+ nonce := nonceFromHeader(resp.Header) -+ if nonce == "" { -+ if resp.StatusCode > 299 { -+ return "", responseError(resp) -+ } -+ return "", errors.New("acme: nonce not found") -+ } -+ return nonce, nil -+} -+ -+func nonceFromHeader(h http.Header) string { -+ return h.Get("Replay-Nonce") -+} -+ -+// linkHeader returns URI-Reference values of all Link headers -+// with relation-type rel. -+// See https://tools.ietf.org/html/rfc5988#section-5 for details. -+func linkHeader(h http.Header, rel string) []string { -+ var links []string -+ for _, v := range h["Link"] { -+ parts := strings.Split(v, ";") -+ for _, p := range parts { -+ p = strings.TrimSpace(p) -+ if !strings.HasPrefix(p, "rel=") { -+ continue -+ } -+ if v := strings.Trim(p[4:], `"`); v == rel { -+ links = append(links, strings.Trim(parts[0], "<>")) -+ } -+ } -+ } -+ return links -+} -+ -+// keyAuth generates a key authorization string for a given token. -+func keyAuth(pub crypto.PublicKey, token string) (string, error) { -+ th, err := JWKThumbprint(pub) -+ if err != nil { -+ return "", err -+ } -+ return fmt.Sprintf("%s.%s", token, th), nil -+} -+ -+// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges. -+func defaultTLSChallengeCertTemplate() *x509.Certificate { -+ return &x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ NotBefore: time.Now(), -+ NotAfter: time.Now().Add(24 * time.Hour), -+ BasicConstraintsValid: true, -+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, -+ } -+} -+ -+// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges -+// with the given SANs and auto-generated public/private key pair. -+// The Subject Common Name is set to the first SAN to aid debugging. -+// To create a cert with a custom key pair, specify WithKey option. -+func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { -+ var key crypto.Signer -+ tmpl := defaultTLSChallengeCertTemplate() -+ for _, o := range opt { -+ switch o := o.(type) { -+ case *certOptKey: -+ if key != nil { -+ return tls.Certificate{}, errors.New("acme: duplicate key option") -+ } -+ key = o.key -+ case *certOptTemplate: -+ t := *(*x509.Certificate)(o) // shallow copy is ok -+ tmpl = &t -+ default: -+ // package's fault, if we let this happen: -+ panic(fmt.Sprintf("unsupported option type %T", o)) -+ } -+ } -+ if key == nil { -+ var err error -+ if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil { -+ return tls.Certificate{}, err -+ } -+ } -+ tmpl.DNSNames = san -+ if len(san) > 0 { -+ tmpl.Subject.CommonName = san[0] -+ } -+ -+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key) -+ if err != nil { -+ return tls.Certificate{}, err -+ } -+ return tls.Certificate{ -+ Certificate: [][]byte{der}, -+ PrivateKey: key, -+ }, nil -+} -+ -+// encodePEM returns b encoded as PEM with block of type typ. -+func encodePEM(typ string, b []byte) []byte { -+ pb := &pem.Block{Type: typ, Bytes: b} -+ return pem.EncodeToMemory(pb) -+} -+ -+// timeNow is time.Now, except in tests which can mess with it. -+var timeNow = time.Now -diff --git a/ms_mod/golang.org/x/crypto/acme/acme_test.go b/ms_mod/golang.org/x/crypto/acme/acme_test.go -new file mode 100644 -index 00000000000000..3f6e2748f31a01 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/acme_test.go -@@ -0,0 +1,855 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "bytes" -+ "context" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/base64" -+ "encoding/hex" -+ "encoding/json" -+ "fmt" -+ "io" -+ "math/big" -+ "net/http" -+ "net/http/httptest" -+ "reflect" -+ "sort" -+ "strings" -+ "testing" -+ "time" -+) -+ -+// newTestClient creates a client with a non-nil Directory so that it skips -+// the discovery which is otherwise done on the first call of almost every -+// exported method. -+func newTestClient() *Client { -+ return &Client{ -+ Key: testKeyEC, -+ dir: &Directory{}, // skip discovery -+ } -+} -+ -+// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided -+// interface. -+func decodeJWSRequest(t *testing.T, v interface{}, r io.Reader) { -+ // Decode request -+ var req struct{ Payload string } -+ if err := json.NewDecoder(r).Decode(&req); err != nil { -+ t.Fatal(err) -+ } -+ payload, err := base64.RawURLEncoding.DecodeString(req.Payload) -+ if err != nil { -+ t.Fatal(err) -+ } -+ err = json.Unmarshal(payload, v) -+ if err != nil { -+ t.Fatal(err) -+ } -+} -+ -+type jwsHead struct { -+ Alg string -+ Nonce string -+ URL string `json:"url"` -+ KID string `json:"kid"` -+ JWK map[string]string `json:"jwk"` -+} -+ -+func decodeJWSHead(r io.Reader) (*jwsHead, error) { -+ var req struct{ Protected string } -+ if err := json.NewDecoder(r).Decode(&req); err != nil { -+ return nil, err -+ } -+ b, err := base64.RawURLEncoding.DecodeString(req.Protected) -+ if err != nil { -+ return nil, err -+ } -+ var head jwsHead -+ if err := json.Unmarshal(b, &head); err != nil { -+ return nil, err -+ } -+ return &head, nil -+} -+ -+func TestRegisterWithoutKey(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if r.Method == "HEAD" { -+ w.Header().Set("Replay-Nonce", "test-nonce") -+ return -+ } -+ w.WriteHeader(http.StatusCreated) -+ fmt.Fprint(w, `{}`) -+ })) -+ defer ts.Close() -+ // First verify that using a complete client results in success. -+ c := Client{ -+ Key: testKeyEC, -+ DirectoryURL: ts.URL, -+ dir: &Directory{RegURL: ts.URL}, -+ } -+ if _, err := c.Register(context.Background(), &Account{}, AcceptTOS); err != nil { -+ t.Fatalf("c.Register() = %v; want success with a complete test client", err) -+ } -+ c.Key = nil -+ if _, err := c.Register(context.Background(), &Account{}, AcceptTOS); err == nil { -+ t.Error("c.Register() from client without key succeeded, wanted error") -+ } -+} -+ -+func TestAuthorize(t *testing.T) { -+ tt := []struct{ typ, value string }{ -+ {"dns", "example.com"}, -+ {"ip", "1.2.3.4"}, -+ } -+ for _, test := range tt { -+ t.Run(test.typ, func(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if r.Method == "HEAD" { -+ w.Header().Set("Replay-Nonce", "test-nonce") -+ return -+ } -+ if r.Method != "POST" { -+ t.Errorf("r.Method = %q; want POST", r.Method) -+ } -+ -+ var j struct { -+ Resource string -+ Identifier struct { -+ Type string -+ Value string -+ } -+ } -+ decodeJWSRequest(t, &j, r.Body) -+ -+ // Test request -+ if j.Resource != "new-authz" { -+ t.Errorf("j.Resource = %q; want new-authz", j.Resource) -+ } -+ if j.Identifier.Type != test.typ { -+ t.Errorf("j.Identifier.Type = %q; want %q", j.Identifier.Type, test.typ) -+ } -+ if j.Identifier.Value != test.value { -+ t.Errorf("j.Identifier.Value = %q; want %q", j.Identifier.Value, test.value) -+ } -+ -+ w.Header().Set("Location", "https://ca.tld/acme/auth/1") -+ w.WriteHeader(http.StatusCreated) -+ fmt.Fprintf(w, `{ -+ "identifier": {"type":%q,"value":%q}, -+ "status":"pending", -+ "challenges":[ -+ { -+ "type":"http-01", -+ "status":"pending", -+ "uri":"https://ca.tld/acme/challenge/publickey/id1", -+ "token":"token1" -+ }, -+ { -+ "type":"tls-sni-01", -+ "status":"pending", -+ "uri":"https://ca.tld/acme/challenge/publickey/id2", -+ "token":"token2" -+ } -+ ], -+ "combinations":[[0],[1]] -+ }`, test.typ, test.value) -+ })) -+ defer ts.Close() -+ -+ var ( -+ auth *Authorization -+ err error -+ ) -+ cl := Client{ -+ Key: testKeyEC, -+ DirectoryURL: ts.URL, -+ dir: &Directory{AuthzURL: ts.URL}, -+ } -+ switch test.typ { -+ case "dns": -+ auth, err = cl.Authorize(context.Background(), test.value) -+ case "ip": -+ auth, err = cl.AuthorizeIP(context.Background(), test.value) -+ default: -+ t.Fatalf("unknown identifier type: %q", test.typ) -+ } -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if auth.URI != "https://ca.tld/acme/auth/1" { -+ t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI) -+ } -+ if auth.Status != "pending" { -+ t.Errorf("Status = %q; want pending", auth.Status) -+ } -+ if auth.Identifier.Type != test.typ { -+ t.Errorf("Identifier.Type = %q; want %q", auth.Identifier.Type, test.typ) -+ } -+ if auth.Identifier.Value != test.value { -+ t.Errorf("Identifier.Value = %q; want %q", auth.Identifier.Value, test.value) -+ } -+ -+ if n := len(auth.Challenges); n != 2 { -+ t.Fatalf("len(auth.Challenges) = %d; want 2", n) -+ } -+ -+ c := auth.Challenges[0] -+ if c.Type != "http-01" { -+ t.Errorf("c.Type = %q; want http-01", c.Type) -+ } -+ if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { -+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) -+ } -+ if c.Token != "token1" { -+ t.Errorf("c.Token = %q; want token1", c.Token) -+ } -+ -+ c = auth.Challenges[1] -+ if c.Type != "tls-sni-01" { -+ t.Errorf("c.Type = %q; want tls-sni-01", c.Type) -+ } -+ if c.URI != "https://ca.tld/acme/challenge/publickey/id2" { -+ t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI) -+ } -+ if c.Token != "token2" { -+ t.Errorf("c.Token = %q; want token2", c.Token) -+ } -+ -+ combs := [][]int{{0}, {1}} -+ if !reflect.DeepEqual(auth.Combinations, combs) { -+ t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs) -+ } -+ -+ }) -+ } -+} -+ -+func TestAuthorizeValid(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if r.Method == "HEAD" { -+ w.Header().Set("Replay-Nonce", "nonce") -+ return -+ } -+ w.WriteHeader(http.StatusCreated) -+ w.Write([]byte(`{"status":"valid"}`)) -+ })) -+ defer ts.Close() -+ client := Client{ -+ Key: testKey, -+ DirectoryURL: ts.URL, -+ dir: &Directory{AuthzURL: ts.URL}, -+ } -+ _, err := client.Authorize(context.Background(), "example.com") -+ if err != nil { -+ t.Errorf("err = %v", err) -+ } -+} -+ -+func TestWaitAuthorization(t *testing.T) { -+ t.Run("wait loop", func(t *testing.T) { -+ var count int -+ authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { -+ count++ -+ w.Header().Set("Retry-After", "0") -+ if count > 1 { -+ fmt.Fprintf(w, `{"status":"valid"}`) -+ return -+ } -+ fmt.Fprintf(w, `{"status":"pending"}`) -+ }) -+ if err != nil { -+ t.Fatalf("non-nil error: %v", err) -+ } -+ if authz == nil { -+ t.Fatal("authz is nil") -+ } -+ }) -+ t.Run("invalid status", func(t *testing.T) { -+ _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { -+ fmt.Fprintf(w, `{"status":"invalid"}`) -+ }) -+ if _, ok := err.(*AuthorizationError); !ok { -+ t.Errorf("err is %v (%T); want non-nil *AuthorizationError", err, err) -+ } -+ }) -+ t.Run("invalid status with error returns the authorization error", func(t *testing.T) { -+ _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { -+ fmt.Fprintf(w, `{ -+ "type": "dns-01", -+ "status": "invalid", -+ "error": { -+ "type": "urn:ietf:params:acme:error:caa", -+ "detail": "CAA record for prevents issuance", -+ "status": 403 -+ }, -+ "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/xxx/xxx", -+ "token": "xxx", -+ "validationRecord": [ -+ { -+ "hostname": "" -+ } -+ ] -+ }`) -+ }) -+ -+ want := &AuthorizationError{ -+ Errors: []error{ -+ (&wireError{ -+ Status: 403, -+ Type: "urn:ietf:params:acme:error:caa", -+ Detail: "CAA record for prevents issuance", -+ }).error(nil), -+ }, -+ } -+ -+ _, ok := err.(*AuthorizationError) -+ if !ok { -+ t.Errorf("err is %T; want non-nil *AuthorizationError", err) -+ } -+ -+ if err.Error() != want.Error() { -+ t.Errorf("err is %v; want %v", err, want) -+ } -+ }) -+ t.Run("non-retriable error", func(t *testing.T) { -+ const code = http.StatusBadRequest -+ _, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { -+ w.WriteHeader(code) -+ }) -+ res, ok := err.(*Error) -+ if !ok { -+ t.Fatalf("err is %v (%T); want a non-nil *Error", err, err) -+ } -+ if res.StatusCode != code { -+ t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, code) -+ } -+ }) -+ for _, code := range []int{http.StatusTooManyRequests, http.StatusInternalServerError} { -+ t.Run(fmt.Sprintf("retriable %d error", code), func(t *testing.T) { -+ var count int -+ authz, err := runWaitAuthorization(context.Background(), t, func(w http.ResponseWriter, r *http.Request) { -+ count++ -+ w.Header().Set("Retry-After", "0") -+ if count > 1 { -+ fmt.Fprintf(w, `{"status":"valid"}`) -+ return -+ } -+ w.WriteHeader(code) -+ }) -+ if err != nil { -+ t.Fatalf("non-nil error: %v", err) -+ } -+ if authz == nil { -+ t.Fatal("authz is nil") -+ } -+ }) -+ } -+ t.Run("context cancel", func(t *testing.T) { -+ ctx, cancel := context.WithCancel(context.Background()) -+ defer cancel() -+ _, err := runWaitAuthorization(ctx, t, func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Retry-After", "60") -+ fmt.Fprintf(w, `{"status":"pending"}`) -+ time.AfterFunc(1*time.Millisecond, cancel) -+ }) -+ if err == nil { -+ t.Error("err is nil") -+ } -+ }) -+} -+ -+func runWaitAuthorization(ctx context.Context, t *testing.T, h http.HandlerFunc) (*Authorization, error) { -+ t.Helper() -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Replay-Nonce", fmt.Sprintf("bad-test-nonce-%v", time.Now().UnixNano())) -+ h(w, r) -+ })) -+ defer ts.Close() -+ -+ client := &Client{ -+ Key: testKey, -+ DirectoryURL: ts.URL, -+ dir: &Directory{}, -+ KID: "some-key-id", // set to avoid lookup attempt -+ } -+ return client.WaitAuthorization(ctx, ts.URL) -+} -+ -+func TestRevokeAuthorization(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if r.Method == "HEAD" { -+ w.Header().Set("Replay-Nonce", "nonce") -+ return -+ } -+ switch r.URL.Path { -+ case "/1": -+ var req struct { -+ Resource string -+ Status string -+ Delete bool -+ } -+ decodeJWSRequest(t, &req, r.Body) -+ if req.Resource != "authz" { -+ t.Errorf("req.Resource = %q; want authz", req.Resource) -+ } -+ if req.Status != "deactivated" { -+ t.Errorf("req.Status = %q; want deactivated", req.Status) -+ } -+ if !req.Delete { -+ t.Errorf("req.Delete is false") -+ } -+ case "/2": -+ w.WriteHeader(http.StatusBadRequest) -+ } -+ })) -+ defer ts.Close() -+ client := &Client{ -+ Key: testKey, -+ DirectoryURL: ts.URL, // don't dial outside of localhost -+ dir: &Directory{}, // don't do discovery -+ } -+ ctx := context.Background() -+ if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil { -+ t.Errorf("err = %v", err) -+ } -+ if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil { -+ t.Error("nil error") -+ } -+} -+ -+func TestFetchCertCancel(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ <-r.Context().Done() -+ w.Header().Set("Retry-After", "0") -+ w.WriteHeader(http.StatusBadRequest) -+ })) -+ defer ts.Close() -+ ctx, cancel := context.WithCancel(context.Background()) -+ done := make(chan struct{}) -+ var err error -+ go func() { -+ cl := newTestClient() -+ _, err = cl.FetchCert(ctx, ts.URL, false) -+ close(done) -+ }() -+ cancel() -+ <-done -+ if err != context.Canceled { -+ t.Errorf("err = %v; want %v", err, context.Canceled) -+ } -+} -+ -+func TestFetchCertDepth(t *testing.T) { -+ var count byte -+ var ts *httptest.Server -+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ count++ -+ if count > maxChainLen+1 { -+ t.Errorf("count = %d; want at most %d", count, maxChainLen+1) -+ w.WriteHeader(http.StatusInternalServerError) -+ } -+ w.Header().Set("Link", fmt.Sprintf("<%s>;rel=up", ts.URL)) -+ w.Write([]byte{count}) -+ })) -+ defer ts.Close() -+ cl := newTestClient() -+ _, err := cl.FetchCert(context.Background(), ts.URL, true) -+ if err == nil { -+ t.Errorf("err is nil") -+ } -+} -+ -+func TestFetchCertBreadth(t *testing.T) { -+ var ts *httptest.Server -+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ for i := 0; i < maxChainLen+1; i++ { -+ w.Header().Add("Link", fmt.Sprintf("<%s>;rel=up", ts.URL)) -+ } -+ w.Write([]byte{1}) -+ })) -+ defer ts.Close() -+ cl := newTestClient() -+ _, err := cl.FetchCert(context.Background(), ts.URL, true) -+ if err == nil { -+ t.Errorf("err is nil") -+ } -+} -+ -+func TestFetchCertSize(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ b := bytes.Repeat([]byte{1}, maxCertSize+1) -+ w.Write(b) -+ })) -+ defer ts.Close() -+ cl := newTestClient() -+ _, err := cl.FetchCert(context.Background(), ts.URL, false) -+ if err == nil { -+ t.Errorf("err is nil") -+ } -+} -+ -+func TestNonce_add(t *testing.T) { -+ var c Client -+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) -+ c.addNonce(http.Header{"Replay-Nonce": {}}) -+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) -+ -+ nonces := map[string]struct{}{"nonce": {}} -+ if !reflect.DeepEqual(c.nonces, nonces) { -+ t.Errorf("c.nonces = %q; want %q", c.nonces, nonces) -+ } -+} -+ -+func TestNonce_addMax(t *testing.T) { -+ c := &Client{nonces: make(map[string]struct{})} -+ for i := 0; i < maxNonces; i++ { -+ c.nonces[fmt.Sprintf("%d", i)] = struct{}{} -+ } -+ c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) -+ if n := len(c.nonces); n != maxNonces { -+ t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces) -+ } -+} -+ -+func TestNonce_fetch(t *testing.T) { -+ tests := []struct { -+ code int -+ nonce string -+ }{ -+ {http.StatusOK, "nonce1"}, -+ {http.StatusBadRequest, "nonce2"}, -+ {http.StatusOK, ""}, -+ } -+ var i int -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if r.Method != "HEAD" { -+ t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method) -+ } -+ w.Header().Set("Replay-Nonce", tests[i].nonce) -+ w.WriteHeader(tests[i].code) -+ })) -+ defer ts.Close() -+ for ; i < len(tests); i++ { -+ test := tests[i] -+ c := newTestClient() -+ n, err := c.fetchNonce(context.Background(), ts.URL) -+ if n != test.nonce { -+ t.Errorf("%d: n=%q; want %q", i, n, test.nonce) -+ } -+ switch { -+ case err == nil && test.nonce == "": -+ t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err) -+ case err != nil && test.nonce != "": -+ t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce) -+ } -+ } -+} -+ -+func TestNonce_fetchError(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.WriteHeader(http.StatusTooManyRequests) -+ })) -+ defer ts.Close() -+ c := newTestClient() -+ _, err := c.fetchNonce(context.Background(), ts.URL) -+ e, ok := err.(*Error) -+ if !ok { -+ t.Fatalf("err is %T; want *Error", err) -+ } -+ if e.StatusCode != http.StatusTooManyRequests { -+ t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests) -+ } -+} -+ -+func TestNonce_popWhenEmpty(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if r.Method != "HEAD" { -+ t.Errorf("r.Method = %q; want HEAD", r.Method) -+ } -+ switch r.URL.Path { -+ case "/dir-with-nonce": -+ w.Header().Set("Replay-Nonce", "dirnonce") -+ case "/new-nonce": -+ w.Header().Set("Replay-Nonce", "newnonce") -+ case "/dir-no-nonce", "/empty": -+ // No nonce in the header. -+ default: -+ t.Errorf("Unknown URL: %s", r.URL) -+ } -+ })) -+ defer ts.Close() -+ ctx := context.Background() -+ -+ tt := []struct { -+ dirURL, popURL, nonce string -+ wantOK bool -+ }{ -+ {ts.URL + "/dir-with-nonce", ts.URL + "/new-nonce", "dirnonce", true}, -+ {ts.URL + "/dir-no-nonce", ts.URL + "/new-nonce", "newnonce", true}, -+ {ts.URL + "/dir-no-nonce", ts.URL + "/empty", "", false}, -+ } -+ for _, test := range tt { -+ t.Run(fmt.Sprintf("nonce:%s wantOK:%v", test.nonce, test.wantOK), func(t *testing.T) { -+ c := Client{DirectoryURL: test.dirURL} -+ v, err := c.popNonce(ctx, test.popURL) -+ if !test.wantOK { -+ if err == nil { -+ t.Fatalf("c.popNonce(%q) returned nil error", test.popURL) -+ } -+ return -+ } -+ if err != nil { -+ t.Fatalf("c.popNonce(%q): %v", test.popURL, err) -+ } -+ if v != test.nonce { -+ t.Errorf("c.popNonce(%q) = %q; want %q", test.popURL, v, test.nonce) -+ } -+ }) -+ } -+} -+ -+func TestLinkHeader(t *testing.T) { -+ h := http.Header{"Link": { -+ `;rel="next"`, -+ `; rel=recover`, -+ `; foo=bar; rel="terms-of-service"`, -+ `;rel="next"`, -+ }} -+ tests := []struct { -+ rel string -+ out []string -+ }{ -+ {"next", []string{"https://example.com/acme/new-authz", "dup"}}, -+ {"recover", []string{"https://example.com/acme/recover-reg"}}, -+ {"terms-of-service", []string{"https://example.com/acme/terms"}}, -+ {"empty", nil}, -+ } -+ for i, test := range tests { -+ if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) { -+ t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out) -+ } -+ } -+} -+ -+func TestTLSSNI01ChallengeCert(t *testing.T) { -+ const ( -+ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" -+ // echo -n | shasum -a 256 -+ san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid" -+ ) -+ -+ tlscert, name, err := newTestClient().TLSSNI01ChallengeCert(token) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if n := len(tlscert.Certificate); n != 1 { -+ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) -+ } -+ cert, err := x509.ParseCertificate(tlscert.Certificate[0]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san { -+ t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san) -+ } -+ if cert.DNSNames[0] != name { -+ t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name) -+ } -+ if cn := cert.Subject.CommonName; cn != san { -+ t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san) -+ } -+} -+ -+func TestTLSSNI02ChallengeCert(t *testing.T) { -+ const ( -+ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" -+ // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256 -+ sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid" -+ // echo -n | shasum -a 256 -+ sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid" -+ ) -+ -+ tlscert, name, err := newTestClient().TLSSNI02ChallengeCert(token) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if n := len(tlscert.Certificate); n != 1 { -+ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) -+ } -+ cert, err := x509.ParseCertificate(tlscert.Certificate[0]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ names := []string{sanA, sanB} -+ if !reflect.DeepEqual(cert.DNSNames, names) { -+ t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) -+ } -+ sort.Strings(cert.DNSNames) -+ i := sort.SearchStrings(cert.DNSNames, name) -+ if i >= len(cert.DNSNames) || cert.DNSNames[i] != name { -+ t.Errorf("%v doesn't have %q", cert.DNSNames, name) -+ } -+ if cn := cert.Subject.CommonName; cn != sanA { -+ t.Errorf("CommonName = %q; want %q", cn, sanA) -+ } -+} -+ -+func TestTLSALPN01ChallengeCert(t *testing.T) { -+ const ( -+ token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" -+ keyAuth = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA." + testKeyECThumbprint -+ // echo -n | shasum -a 256 -+ h = "0420dbbd5eefe7b4d06eb9d1d9f5acb4c7cda27d320e4b30332f0b6cb441734ad7b0" -+ domain = "example.com" -+ ) -+ -+ extValue, err := hex.DecodeString(h) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ tlscert, err := newTestClient().TLSALPN01ChallengeCert(token, domain) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if n := len(tlscert.Certificate); n != 1 { -+ t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) -+ } -+ cert, err := x509.ParseCertificate(tlscert.Certificate[0]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ names := []string{domain} -+ if !reflect.DeepEqual(cert.DNSNames, names) { -+ t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) -+ } -+ if cn := cert.Subject.CommonName; cn != domain { -+ t.Errorf("CommonName = %q; want %q", cn, domain) -+ } -+ acmeExts := []pkix.Extension{} -+ for _, ext := range cert.Extensions { -+ if idPeACMEIdentifier.Equal(ext.Id) { -+ acmeExts = append(acmeExts, ext) -+ } -+ } -+ if len(acmeExts) != 1 { -+ t.Errorf("acmeExts = %v; want exactly one", acmeExts) -+ } -+ if !acmeExts[0].Critical { -+ t.Errorf("acmeExt.Critical = %v; want true", acmeExts[0].Critical) -+ } -+ if bytes.Compare(acmeExts[0].Value, extValue) != 0 { -+ t.Errorf("acmeExt.Value = %v; want %v", acmeExts[0].Value, extValue) -+ } -+ -+} -+ -+func TestTLSChallengeCertOpt(t *testing.T) { -+ key, err := rsa.GenerateKey(rand.Reader, 512) -+ if err != nil { -+ t.Fatal(err) -+ } -+ tmpl := &x509.Certificate{ -+ SerialNumber: big.NewInt(2), -+ Subject: pkix.Name{Organization: []string{"Test"}}, -+ DNSNames: []string{"should-be-overwritten"}, -+ } -+ opts := []CertOption{WithKey(key), WithTemplate(tmpl)} -+ -+ client := newTestClient() -+ cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...) -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ for i, tlscert := range []tls.Certificate{cert1, cert2} { -+ // verify generated cert private key -+ tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey) -+ if !ok { -+ t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey) -+ continue -+ } -+ if tlskey.D.Cmp(key.D) != 0 { -+ t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D) -+ } -+ // verify generated cert public key -+ x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0]) -+ if err != nil { -+ t.Errorf("%d: %v", i, err) -+ continue -+ } -+ tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey) -+ if !ok { -+ t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey) -+ continue -+ } -+ if tlspub.N.Cmp(key.N) != 0 { -+ t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N) -+ } -+ // verify template option -+ sn := big.NewInt(2) -+ if x509Cert.SerialNumber.Cmp(sn) != 0 { -+ t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn) -+ } -+ org := []string{"Test"} -+ if !reflect.DeepEqual(x509Cert.Subject.Organization, org) { -+ t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org) -+ } -+ for _, v := range x509Cert.DNSNames { -+ if !strings.HasSuffix(v, ".acme.invalid") { -+ t.Errorf("%d: invalid DNSNames element: %q", i, v) -+ } -+ } -+ } -+} -+ -+func TestHTTP01Challenge(t *testing.T) { -+ const ( -+ token = "xxx" -+ // thumbprint is precomputed for testKeyEC in jws_test.go -+ value = token + "." + testKeyECThumbprint -+ urlpath = "/.well-known/acme-challenge/" + token -+ ) -+ client := newTestClient() -+ val, err := client.HTTP01ChallengeResponse(token) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if val != value { -+ t.Errorf("val = %q; want %q", val, value) -+ } -+ if path := client.HTTP01ChallengePath(token); path != urlpath { -+ t.Errorf("path = %q; want %q", path, urlpath) -+ } -+} -+ -+func TestDNS01ChallengeRecord(t *testing.T) { -+ // echo -n xxx. | \ -+ // openssl dgst -binary -sha256 | \ -+ // base64 | tr -d '=' | tr '/+' '_-' -+ const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo" -+ -+ val, err := newTestClient().DNS01ChallengeRecord("xxx") -+ if err != nil { -+ t.Fatal(err) -+ } -+ if val != value { -+ t.Errorf("val = %q; want %q", val, value) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/autocert.go b/ms_mod/golang.org/x/crypto/acme/autocert/autocert.go -new file mode 100644 -index 00000000000000..6b4cdf406d3b6e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/autocert.go -@@ -0,0 +1,1198 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package autocert provides automatic access to certificates from Let's Encrypt -+// and any other ACME-based CA. -+// -+// This package is a work in progress and makes no API stability promises. -+package autocert -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "io" -+ mathrand "math/rand" -+ "net" -+ "net/http" -+ "path" -+ "strings" -+ "sync" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+ "golang.org/x/net/idna" -+) -+ -+// DefaultACMEDirectory is the default ACME Directory URL used when the Manager's Client is nil. -+const DefaultACMEDirectory = "https://acme-v02.api.letsencrypt.org/directory" -+ -+// createCertRetryAfter is how much time to wait before removing a failed state -+// entry due to an unsuccessful createCert call. -+// This is a variable instead of a const for testing. -+// TODO: Consider making it configurable or an exp backoff? -+var createCertRetryAfter = time.Minute -+ -+// pseudoRand is safe for concurrent use. -+var pseudoRand *lockedMathRand -+ -+var errPreRFC = errors.New("autocert: ACME server doesn't support RFC 8555") -+ -+func init() { -+ src := mathrand.NewSource(time.Now().UnixNano()) -+ pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} -+} -+ -+// AcceptTOS is a Manager.Prompt function that always returns true to -+// indicate acceptance of the CA's Terms of Service during account -+// registration. -+func AcceptTOS(tosURL string) bool { return true } -+ -+// HostPolicy specifies which host names the Manager is allowed to respond to. -+// It returns a non-nil error if the host should be rejected. -+// The returned error is accessible via tls.Conn.Handshake and its callers. -+// See Manager's HostPolicy field and GetCertificate method docs for more details. -+type HostPolicy func(ctx context.Context, host string) error -+ -+// HostWhitelist returns a policy where only the specified host names are allowed. -+// Only exact matches are currently supported. Subdomains, regexp or wildcard -+// will not match. -+// -+// Note that all hosts will be converted to Punycode via idna.Lookup.ToASCII so that -+// Manager.GetCertificate can handle the Unicode IDN and mixedcase hosts correctly. -+// Invalid hosts will be silently ignored. -+func HostWhitelist(hosts ...string) HostPolicy { -+ whitelist := make(map[string]bool, len(hosts)) -+ for _, h := range hosts { -+ if h, err := idna.Lookup.ToASCII(h); err == nil { -+ whitelist[h] = true -+ } -+ } -+ return func(_ context.Context, host string) error { -+ if !whitelist[host] { -+ return fmt.Errorf("acme/autocert: host %q not configured in HostWhitelist", host) -+ } -+ return nil -+ } -+} -+ -+// defaultHostPolicy is used when Manager.HostPolicy is not set. -+func defaultHostPolicy(context.Context, string) error { -+ return nil -+} -+ -+// Manager is a stateful certificate manager built on top of acme.Client. -+// It obtains and refreshes certificates automatically using "tls-alpn-01" -+// or "http-01" challenge types, as well as providing them to a TLS server -+// via tls.Config. -+// -+// You must specify a cache implementation, such as DirCache, -+// to reuse obtained certificates across program restarts. -+// Otherwise your server is very likely to exceed the certificate -+// issuer's request rate limits. -+type Manager struct { -+ // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS). -+ // The registration may require the caller to agree to the CA's TOS. -+ // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report -+ // whether the caller agrees to the terms. -+ // -+ // To always accept the terms, the callers can use AcceptTOS. -+ Prompt func(tosURL string) bool -+ -+ // Cache optionally stores and retrieves previously-obtained certificates -+ // and other state. If nil, certs will only be cached for the lifetime of -+ // the Manager. Multiple Managers can share the same Cache. -+ // -+ // Using a persistent Cache, such as DirCache, is strongly recommended. -+ Cache Cache -+ -+ // HostPolicy controls which domains the Manager will attempt -+ // to retrieve new certificates for. It does not affect cached certs. -+ // -+ // If non-nil, HostPolicy is called before requesting a new cert. -+ // If nil, all hosts are currently allowed. This is not recommended, -+ // as it opens a potential attack where clients connect to a server -+ // by IP address and pretend to be asking for an incorrect host name. -+ // Manager will attempt to obtain a certificate for that host, incorrectly, -+ // eventually reaching the CA's rate limit for certificate requests -+ // and making it impossible to obtain actual certificates. -+ // -+ // See GetCertificate for more details. -+ HostPolicy HostPolicy -+ -+ // RenewBefore optionally specifies how early certificates should -+ // be renewed before they expire. -+ // -+ // If zero, they're renewed 30 days before expiration. -+ RenewBefore time.Duration -+ -+ // Client is used to perform low-level operations, such as account registration -+ // and requesting new certificates. -+ // -+ // If Client is nil, a zero-value acme.Client is used with DefaultACMEDirectory -+ // as the directory endpoint. -+ // If the Client.Key is nil, a new ECDSA P-256 key is generated and, -+ // if Cache is not nil, stored in cache. -+ // -+ // Mutating the field after the first call of GetCertificate method will have no effect. -+ Client *acme.Client -+ -+ // Email optionally specifies a contact email address. -+ // This is used by CAs, such as Let's Encrypt, to notify about problems -+ // with issued certificates. -+ // -+ // If the Client's account key is already registered, Email is not used. -+ Email string -+ -+ // ForceRSA used to make the Manager generate RSA certificates. It is now ignored. -+ // -+ // Deprecated: the Manager will request the correct type of certificate based -+ // on what each client supports. -+ ForceRSA bool -+ -+ // ExtraExtensions are used when generating a new CSR (Certificate Request), -+ // thus allowing customization of the resulting certificate. -+ // For instance, TLS Feature Extension (RFC 7633) can be used -+ // to prevent an OCSP downgrade attack. -+ // -+ // The field value is passed to crypto/x509.CreateCertificateRequest -+ // in the template's ExtraExtensions field as is. -+ ExtraExtensions []pkix.Extension -+ -+ // ExternalAccountBinding optionally represents an arbitrary binding to an -+ // account of the CA to which the ACME server is tied. -+ // See RFC 8555, Section 7.3.4 for more details. -+ ExternalAccountBinding *acme.ExternalAccountBinding -+ -+ clientMu sync.Mutex -+ client *acme.Client // initialized by acmeClient method -+ -+ stateMu sync.Mutex -+ state map[certKey]*certState -+ -+ // renewal tracks the set of domains currently running renewal timers. -+ renewalMu sync.Mutex -+ renewal map[certKey]*domainRenewal -+ -+ // challengeMu guards tryHTTP01, certTokens and httpTokens. -+ challengeMu sync.RWMutex -+ // tryHTTP01 indicates whether the Manager should try "http-01" challenge type -+ // during the authorization flow. -+ tryHTTP01 bool -+ // httpTokens contains response body values for http-01 challenges -+ // and is keyed by the URL path at which a challenge response is expected -+ // to be provisioned. -+ // The entries are stored for the duration of the authorization flow. -+ httpTokens map[string][]byte -+ // certTokens contains temporary certificates for tls-alpn-01 challenges -+ // and is keyed by the domain name which matches the ClientHello server name. -+ // The entries are stored for the duration of the authorization flow. -+ certTokens map[string]*tls.Certificate -+ -+ // nowFunc, if not nil, returns the current time. This may be set for -+ // testing purposes. -+ nowFunc func() time.Time -+} -+ -+// certKey is the key by which certificates are tracked in state, renewal and cache. -+type certKey struct { -+ domain string // without trailing dot -+ isRSA bool // RSA cert for legacy clients (as opposed to default ECDSA) -+ isToken bool // tls-based challenge token cert; key type is undefined regardless of isRSA -+} -+ -+func (c certKey) String() string { -+ if c.isToken { -+ return c.domain + "+token" -+ } -+ if c.isRSA { -+ return c.domain + "+rsa" -+ } -+ return c.domain -+} -+ -+// TLSConfig creates a new TLS config suitable for net/http.Server servers, -+// supporting HTTP/2 and the tls-alpn-01 ACME challenge type. -+func (m *Manager) TLSConfig() *tls.Config { -+ return &tls.Config{ -+ GetCertificate: m.GetCertificate, -+ NextProtos: []string{ -+ "h2", "http/1.1", // enable HTTP/2 -+ acme.ALPNProto, // enable tls-alpn ACME challenges -+ }, -+ } -+} -+ -+// GetCertificate implements the tls.Config.GetCertificate hook. -+// It provides a TLS certificate for hello.ServerName host, including answering -+// tls-alpn-01 challenges. -+// All other fields of hello are ignored. -+// -+// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting -+// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation. -+// The error is propagated back to the caller of GetCertificate and is user-visible. -+// This does not affect cached certs. See HostPolicy field description for more details. -+// -+// If GetCertificate is used directly, instead of via Manager.TLSConfig, package users will -+// also have to add acme.ALPNProto to NextProtos for tls-alpn-01, or use HTTPHandler for http-01. -+func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { -+ if m.Prompt == nil { -+ return nil, errors.New("acme/autocert: Manager.Prompt not set") -+ } -+ -+ name := hello.ServerName -+ if name == "" { -+ return nil, errors.New("acme/autocert: missing server name") -+ } -+ if !strings.Contains(strings.Trim(name, "."), ".") { -+ return nil, errors.New("acme/autocert: server name component count invalid") -+ } -+ -+ // Note that this conversion is necessary because some server names in the handshakes -+ // started by some clients (such as cURL) are not converted to Punycode, which will -+ // prevent us from obtaining certificates for them. In addition, we should also treat -+ // example.com and EXAMPLE.COM as equivalent and return the same certificate for them. -+ // Fortunately, this conversion also helped us deal with this kind of mixedcase problems. -+ // -+ // Due to the "σςΣ" problem (see https://unicode.org/faq/idn.html#22), we can't use -+ // idna.Punycode.ToASCII (or just idna.ToASCII) here. -+ name, err := idna.Lookup.ToASCII(name) -+ if err != nil { -+ return nil, errors.New("acme/autocert: server name contains invalid character") -+ } -+ -+ // In the worst-case scenario, the timeout needs to account for caching, host policy, -+ // domain ownership verification and certificate issuance. -+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) -+ defer cancel() -+ -+ // Check whether this is a token cert requested for TLS-ALPN challenge. -+ if wantsTokenCert(hello) { -+ m.challengeMu.RLock() -+ defer m.challengeMu.RUnlock() -+ if cert := m.certTokens[name]; cert != nil { -+ return cert, nil -+ } -+ if cert, err := m.cacheGet(ctx, certKey{domain: name, isToken: true}); err == nil { -+ return cert, nil -+ } -+ // TODO: cache error results? -+ return nil, fmt.Errorf("acme/autocert: no token cert for %q", name) -+ } -+ -+ // regular domain -+ ck := certKey{ -+ domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114 -+ isRSA: !supportsECDSA(hello), -+ } -+ cert, err := m.cert(ctx, ck) -+ if err == nil { -+ return cert, nil -+ } -+ if err != ErrCacheMiss { -+ return nil, err -+ } -+ -+ // first-time -+ if err := m.hostPolicy()(ctx, name); err != nil { -+ return nil, err -+ } -+ cert, err = m.createCert(ctx, ck) -+ if err != nil { -+ return nil, err -+ } -+ m.cachePut(ctx, ck, cert) -+ return cert, nil -+} -+ -+// wantsTokenCert reports whether a TLS request with SNI is made by a CA server -+// for a challenge verification. -+func wantsTokenCert(hello *tls.ClientHelloInfo) bool { -+ // tls-alpn-01 -+ if len(hello.SupportedProtos) == 1 && hello.SupportedProtos[0] == acme.ALPNProto { -+ return true -+ } -+ return false -+} -+ -+func supportsECDSA(hello *tls.ClientHelloInfo) bool { -+ // The "signature_algorithms" extension, if present, limits the key exchange -+ // algorithms allowed by the cipher suites. See RFC 5246, section 7.4.1.4.1. -+ if hello.SignatureSchemes != nil { -+ ecdsaOK := false -+ schemeLoop: -+ for _, scheme := range hello.SignatureSchemes { -+ const tlsECDSAWithSHA1 tls.SignatureScheme = 0x0203 // constant added in Go 1.10 -+ switch scheme { -+ case tlsECDSAWithSHA1, tls.ECDSAWithP256AndSHA256, -+ tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512: -+ ecdsaOK = true -+ break schemeLoop -+ } -+ } -+ if !ecdsaOK { -+ return false -+ } -+ } -+ if hello.SupportedCurves != nil { -+ ecdsaOK := false -+ for _, curve := range hello.SupportedCurves { -+ if curve == tls.CurveP256 { -+ ecdsaOK = true -+ break -+ } -+ } -+ if !ecdsaOK { -+ return false -+ } -+ } -+ for _, suite := range hello.CipherSuites { -+ switch suite { -+ case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, -+ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: -+ return true -+ } -+ } -+ return false -+} -+ -+// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses. -+// It returns an http.Handler that responds to the challenges and must be -+// running on port 80. If it receives a request that is not an ACME challenge, -+// it delegates the request to the optional fallback handler. -+// -+// If fallback is nil, the returned handler redirects all GET and HEAD requests -+// to the default TLS port 443 with 302 Found status code, preserving the original -+// request path and query. It responds with 400 Bad Request to all other HTTP methods. -+// The fallback is not protected by the optional HostPolicy. -+// -+// Because the fallback handler is run with unencrypted port 80 requests, -+// the fallback should not serve TLS-only requests. -+// -+// If HTTPHandler is never called, the Manager will only use the "tls-alpn-01" -+// challenge for domain verification. -+func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ m.tryHTTP01 = true -+ -+ if fallback == nil { -+ fallback = http.HandlerFunc(handleHTTPRedirect) -+ } -+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ if !strings.HasPrefix(r.URL.Path, "/.well-known/acme-challenge/") { -+ fallback.ServeHTTP(w, r) -+ return -+ } -+ // A reasonable context timeout for cache and host policy only, -+ // because we don't wait for a new certificate issuance here. -+ ctx, cancel := context.WithTimeout(r.Context(), time.Minute) -+ defer cancel() -+ if err := m.hostPolicy()(ctx, r.Host); err != nil { -+ http.Error(w, err.Error(), http.StatusForbidden) -+ return -+ } -+ data, err := m.httpToken(ctx, r.URL.Path) -+ if err != nil { -+ http.Error(w, err.Error(), http.StatusNotFound) -+ return -+ } -+ w.Write(data) -+ }) -+} -+ -+func handleHTTPRedirect(w http.ResponseWriter, r *http.Request) { -+ if r.Method != "GET" && r.Method != "HEAD" { -+ http.Error(w, "Use HTTPS", http.StatusBadRequest) -+ return -+ } -+ target := "https://" + stripPort(r.Host) + r.URL.RequestURI() -+ http.Redirect(w, r, target, http.StatusFound) -+} -+ -+func stripPort(hostport string) string { -+ host, _, err := net.SplitHostPort(hostport) -+ if err != nil { -+ return hostport -+ } -+ return net.JoinHostPort(host, "443") -+} -+ -+// cert returns an existing certificate either from m.state or cache. -+// If a certificate is found in cache but not in m.state, the latter will be filled -+// with the cached value. -+func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error) { -+ m.stateMu.Lock() -+ if s, ok := m.state[ck]; ok { -+ m.stateMu.Unlock() -+ s.RLock() -+ defer s.RUnlock() -+ return s.tlscert() -+ } -+ defer m.stateMu.Unlock() -+ cert, err := m.cacheGet(ctx, ck) -+ if err != nil { -+ return nil, err -+ } -+ signer, ok := cert.PrivateKey.(crypto.Signer) -+ if !ok { -+ return nil, errors.New("acme/autocert: private key cannot sign") -+ } -+ if m.state == nil { -+ m.state = make(map[certKey]*certState) -+ } -+ s := &certState{ -+ key: signer, -+ cert: cert.Certificate, -+ leaf: cert.Leaf, -+ } -+ m.state[ck] = s -+ m.startRenew(ck, s.key, s.leaf.NotAfter) -+ return cert, nil -+} -+ -+// cacheGet always returns a valid certificate, or an error otherwise. -+// If a cached certificate exists but is not valid, ErrCacheMiss is returned. -+func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, error) { -+ if m.Cache == nil { -+ return nil, ErrCacheMiss -+ } -+ data, err := m.Cache.Get(ctx, ck.String()) -+ if err != nil { -+ return nil, err -+ } -+ -+ // private -+ priv, pub := pem.Decode(data) -+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { -+ return nil, ErrCacheMiss -+ } -+ privKey, err := parsePrivateKey(priv.Bytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ // public -+ var pubDER [][]byte -+ for len(pub) > 0 { -+ var b *pem.Block -+ b, pub = pem.Decode(pub) -+ if b == nil { -+ break -+ } -+ pubDER = append(pubDER, b.Bytes) -+ } -+ if len(pub) > 0 { -+ // Leftover content not consumed by pem.Decode. Corrupt. Ignore. -+ return nil, ErrCacheMiss -+ } -+ -+ // verify and create TLS cert -+ leaf, err := validCert(ck, pubDER, privKey, m.now()) -+ if err != nil { -+ return nil, ErrCacheMiss -+ } -+ tlscert := &tls.Certificate{ -+ Certificate: pubDER, -+ PrivateKey: privKey, -+ Leaf: leaf, -+ } -+ return tlscert, nil -+} -+ -+func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certificate) error { -+ if m.Cache == nil { -+ return nil -+ } -+ -+ // contains PEM-encoded data -+ var buf bytes.Buffer -+ -+ // private -+ switch key := tlscert.PrivateKey.(type) { -+ case *ecdsa.PrivateKey: -+ if err := encodeECDSAKey(&buf, key); err != nil { -+ return err -+ } -+ case *rsa.PrivateKey: -+ b := x509.MarshalPKCS1PrivateKey(key) -+ pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b} -+ if err := pem.Encode(&buf, pb); err != nil { -+ return err -+ } -+ default: -+ return errors.New("acme/autocert: unknown private key type") -+ } -+ -+ // public -+ for _, b := range tlscert.Certificate { -+ pb := &pem.Block{Type: "CERTIFICATE", Bytes: b} -+ if err := pem.Encode(&buf, pb); err != nil { -+ return err -+ } -+ } -+ -+ return m.Cache.Put(ctx, ck.String(), buf.Bytes()) -+} -+ -+func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { -+ b, err := x509.MarshalECPrivateKey(key) -+ if err != nil { -+ return err -+ } -+ pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} -+ return pem.Encode(w, pb) -+} -+ -+// createCert starts the domain ownership verification and returns a certificate -+// for that domain upon success. -+// -+// If the domain is already being verified, it waits for the existing verification to complete. -+// Either way, createCert blocks for the duration of the whole process. -+func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) { -+ // TODO: maybe rewrite this whole piece using sync.Once -+ state, err := m.certState(ck) -+ if err != nil { -+ return nil, err -+ } -+ // state may exist if another goroutine is already working on it -+ // in which case just wait for it to finish -+ if !state.locked { -+ state.RLock() -+ defer state.RUnlock() -+ return state.tlscert() -+ } -+ -+ // We are the first; state is locked. -+ // Unblock the readers when domain ownership is verified -+ // and we got the cert or the process failed. -+ defer state.Unlock() -+ state.locked = false -+ -+ der, leaf, err := m.authorizedCert(ctx, state.key, ck) -+ if err != nil { -+ // Remove the failed state after some time, -+ // making the manager call createCert again on the following TLS hello. -+ didRemove := testDidRemoveState // The lifetime of this timer is untracked, so copy mutable local state to avoid races. -+ time.AfterFunc(createCertRetryAfter, func() { -+ defer didRemove(ck) -+ m.stateMu.Lock() -+ defer m.stateMu.Unlock() -+ // Verify the state hasn't changed and it's still invalid -+ // before deleting. -+ s, ok := m.state[ck] -+ if !ok { -+ return -+ } -+ if _, err := validCert(ck, s.cert, s.key, m.now()); err == nil { -+ return -+ } -+ delete(m.state, ck) -+ }) -+ return nil, err -+ } -+ state.cert = der -+ state.leaf = leaf -+ m.startRenew(ck, state.key, state.leaf.NotAfter) -+ return state.tlscert() -+} -+ -+// certState returns a new or existing certState. -+// If a new certState is returned, state.exist is false and the state is locked. -+// The returned error is non-nil only in the case where a new state could not be created. -+func (m *Manager) certState(ck certKey) (*certState, error) { -+ m.stateMu.Lock() -+ defer m.stateMu.Unlock() -+ if m.state == nil { -+ m.state = make(map[certKey]*certState) -+ } -+ // existing state -+ if state, ok := m.state[ck]; ok { -+ return state, nil -+ } -+ -+ // new locked state -+ var ( -+ err error -+ key crypto.Signer -+ ) -+ if ck.isRSA { -+ key, err = rsa.GenerateKey(rand.Reader, 2048) -+ } else { -+ key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ state := &certState{ -+ key: key, -+ locked: true, -+ } -+ state.Lock() // will be unlocked by m.certState caller -+ m.state[ck] = state -+ return state, nil -+} -+ -+// authorizedCert starts the domain ownership verification process and requests a new cert upon success. -+// The key argument is the certificate private key. -+func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) { -+ csr, err := certRequest(key, ck.domain, m.ExtraExtensions) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ client, err := m.acmeClient(ctx) -+ if err != nil { -+ return nil, nil, err -+ } -+ dir, err := client.Discover(ctx) -+ if err != nil { -+ return nil, nil, err -+ } -+ if dir.OrderURL == "" { -+ return nil, nil, errPreRFC -+ } -+ -+ o, err := m.verifyRFC(ctx, client, ck.domain) -+ if err != nil { -+ return nil, nil, err -+ } -+ chain, _, err := client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ leaf, err = validCert(ck, chain, key, m.now()) -+ if err != nil { -+ return nil, nil, err -+ } -+ return chain, leaf, nil -+} -+ -+// verifyRFC runs the identifier (domain) order-based authorization flow for RFC compliant CAs -+// using each applicable ACME challenge type. -+func (m *Manager) verifyRFC(ctx context.Context, client *acme.Client, domain string) (*acme.Order, error) { -+ // Try each supported challenge type starting with a new order each time. -+ // The nextTyp index of the next challenge type to try is shared across -+ // all order authorizations: if we've tried a challenge type once and it didn't work, -+ // it will most likely not work on another order's authorization either. -+ challengeTypes := m.supportedChallengeTypes() -+ nextTyp := 0 // challengeTypes index -+AuthorizeOrderLoop: -+ for { -+ o, err := client.AuthorizeOrder(ctx, acme.DomainIDs(domain)) -+ if err != nil { -+ return nil, err -+ } -+ // Remove all hanging authorizations to reduce rate limit quotas -+ // after we're done. -+ defer func(urls []string) { -+ go m.deactivatePendingAuthz(urls) -+ }(o.AuthzURLs) -+ -+ // Check if there's actually anything we need to do. -+ switch o.Status { -+ case acme.StatusReady: -+ // Already authorized. -+ return o, nil -+ case acme.StatusPending: -+ // Continue normal Order-based flow. -+ default: -+ return nil, fmt.Errorf("acme/autocert: invalid new order status %q; order URL: %q", o.Status, o.URI) -+ } -+ -+ // Satisfy all pending authorizations. -+ for _, zurl := range o.AuthzURLs { -+ z, err := client.GetAuthorization(ctx, zurl) -+ if err != nil { -+ return nil, err -+ } -+ if z.Status != acme.StatusPending { -+ // We are interested only in pending authorizations. -+ continue -+ } -+ // Pick the next preferred challenge. -+ var chal *acme.Challenge -+ for chal == nil && nextTyp < len(challengeTypes) { -+ chal = pickChallenge(challengeTypes[nextTyp], z.Challenges) -+ nextTyp++ -+ } -+ if chal == nil { -+ return nil, fmt.Errorf("acme/autocert: unable to satisfy %q for domain %q: no viable challenge type found", z.URI, domain) -+ } -+ // Respond to the challenge and wait for validation result. -+ cleanup, err := m.fulfill(ctx, client, chal, domain) -+ if err != nil { -+ continue AuthorizeOrderLoop -+ } -+ defer cleanup() -+ if _, err := client.Accept(ctx, chal); err != nil { -+ continue AuthorizeOrderLoop -+ } -+ if _, err := client.WaitAuthorization(ctx, z.URI); err != nil { -+ continue AuthorizeOrderLoop -+ } -+ } -+ -+ // All authorizations are satisfied. -+ // Wait for the CA to update the order status. -+ o, err = client.WaitOrder(ctx, o.URI) -+ if err != nil { -+ continue AuthorizeOrderLoop -+ } -+ return o, nil -+ } -+} -+ -+func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { -+ for _, c := range chal { -+ if c.Type == typ { -+ return c -+ } -+ } -+ return nil -+} -+ -+func (m *Manager) supportedChallengeTypes() []string { -+ m.challengeMu.RLock() -+ defer m.challengeMu.RUnlock() -+ typ := []string{"tls-alpn-01"} -+ if m.tryHTTP01 { -+ typ = append(typ, "http-01") -+ } -+ return typ -+} -+ -+// deactivatePendingAuthz relinquishes all authorizations identified by the elements -+// of the provided uri slice which are in "pending" state. -+// It ignores revocation errors. -+// -+// deactivatePendingAuthz takes no context argument and instead runs with its own -+// "detached" context because deactivations are done in a goroutine separate from -+// that of the main issuance or renewal flow. -+func (m *Manager) deactivatePendingAuthz(uri []string) { -+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) -+ defer cancel() -+ client, err := m.acmeClient(ctx) -+ if err != nil { -+ return -+ } -+ for _, u := range uri { -+ z, err := client.GetAuthorization(ctx, u) -+ if err == nil && z.Status == acme.StatusPending { -+ client.RevokeAuthorization(ctx, u) -+ } -+ } -+} -+ -+// fulfill provisions a response to the challenge chal. -+// The cleanup is non-nil only if provisioning succeeded. -+func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge, domain string) (cleanup func(), err error) { -+ switch chal.Type { -+ case "tls-alpn-01": -+ cert, err := client.TLSALPN01ChallengeCert(chal.Token, domain) -+ if err != nil { -+ return nil, err -+ } -+ m.putCertToken(ctx, domain, &cert) -+ return func() { go m.deleteCertToken(domain) }, nil -+ case "http-01": -+ resp, err := client.HTTP01ChallengeResponse(chal.Token) -+ if err != nil { -+ return nil, err -+ } -+ p := client.HTTP01ChallengePath(chal.Token) -+ m.putHTTPToken(ctx, p, resp) -+ return func() { go m.deleteHTTPToken(p) }, nil -+ } -+ return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type) -+} -+ -+// putCertToken stores the token certificate with the specified name -+// in both m.certTokens map and m.Cache. -+func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ if m.certTokens == nil { -+ m.certTokens = make(map[string]*tls.Certificate) -+ } -+ m.certTokens[name] = cert -+ m.cachePut(ctx, certKey{domain: name, isToken: true}, cert) -+} -+ -+// deleteCertToken removes the token certificate with the specified name -+// from both m.certTokens map and m.Cache. -+func (m *Manager) deleteCertToken(name string) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ delete(m.certTokens, name) -+ if m.Cache != nil { -+ ck := certKey{domain: name, isToken: true} -+ m.Cache.Delete(context.Background(), ck.String()) -+ } -+} -+ -+// httpToken retrieves an existing http-01 token value from an in-memory map -+// or the optional cache. -+func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) { -+ m.challengeMu.RLock() -+ defer m.challengeMu.RUnlock() -+ if v, ok := m.httpTokens[tokenPath]; ok { -+ return v, nil -+ } -+ if m.Cache == nil { -+ return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath) -+ } -+ return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath)) -+} -+ -+// putHTTPToken stores an http-01 token value using tokenPath as key -+// in both in-memory map and the optional Cache. -+// -+// It ignores any error returned from Cache.Put. -+func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ if m.httpTokens == nil { -+ m.httpTokens = make(map[string][]byte) -+ } -+ b := []byte(val) -+ m.httpTokens[tokenPath] = b -+ if m.Cache != nil { -+ m.Cache.Put(ctx, httpTokenCacheKey(tokenPath), b) -+ } -+} -+ -+// deleteHTTPToken removes an http-01 token value from both in-memory map -+// and the optional Cache, ignoring any error returned from the latter. -+// -+// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout. -+func (m *Manager) deleteHTTPToken(tokenPath string) { -+ m.challengeMu.Lock() -+ defer m.challengeMu.Unlock() -+ delete(m.httpTokens, tokenPath) -+ if m.Cache != nil { -+ m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath)) -+ } -+} -+ -+// httpTokenCacheKey returns a key at which an http-01 token value may be stored -+// in the Manager's optional Cache. -+func httpTokenCacheKey(tokenPath string) string { -+ return path.Base(tokenPath) + "+http-01" -+} -+ -+// startRenew starts a cert renewal timer loop, one per domain. -+// -+// The loop is scheduled in two cases: -+// - a cert was fetched from cache for the first time (wasn't in m.state) -+// - a new cert was created by m.createCert -+// -+// The key argument is a certificate private key. -+// The exp argument is the cert expiration time (NotAfter). -+func (m *Manager) startRenew(ck certKey, key crypto.Signer, exp time.Time) { -+ m.renewalMu.Lock() -+ defer m.renewalMu.Unlock() -+ if m.renewal[ck] != nil { -+ // another goroutine is already on it -+ return -+ } -+ if m.renewal == nil { -+ m.renewal = make(map[certKey]*domainRenewal) -+ } -+ dr := &domainRenewal{m: m, ck: ck, key: key} -+ m.renewal[ck] = dr -+ dr.start(exp) -+} -+ -+// stopRenew stops all currently running cert renewal timers. -+// The timers are not restarted during the lifetime of the Manager. -+func (m *Manager) stopRenew() { -+ m.renewalMu.Lock() -+ defer m.renewalMu.Unlock() -+ for name, dr := range m.renewal { -+ delete(m.renewal, name) -+ dr.stop() -+ } -+} -+ -+func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { -+ const keyName = "acme_account+key" -+ -+ // Previous versions of autocert stored the value under a different key. -+ const legacyKeyName = "acme_account.key" -+ -+ genKey := func() (*ecdsa.PrivateKey, error) { -+ return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ } -+ -+ if m.Cache == nil { -+ return genKey() -+ } -+ -+ data, err := m.Cache.Get(ctx, keyName) -+ if err == ErrCacheMiss { -+ data, err = m.Cache.Get(ctx, legacyKeyName) -+ } -+ if err == ErrCacheMiss { -+ key, err := genKey() -+ if err != nil { -+ return nil, err -+ } -+ var buf bytes.Buffer -+ if err := encodeECDSAKey(&buf, key); err != nil { -+ return nil, err -+ } -+ if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil { -+ return nil, err -+ } -+ return key, nil -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ priv, _ := pem.Decode(data) -+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { -+ return nil, errors.New("acme/autocert: invalid account key found in cache") -+ } -+ return parsePrivateKey(priv.Bytes) -+} -+ -+func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) { -+ m.clientMu.Lock() -+ defer m.clientMu.Unlock() -+ if m.client != nil { -+ return m.client, nil -+ } -+ -+ client := m.Client -+ if client == nil { -+ client = &acme.Client{DirectoryURL: DefaultACMEDirectory} -+ } -+ if client.Key == nil { -+ var err error -+ client.Key, err = m.accountKey(ctx) -+ if err != nil { -+ return nil, err -+ } -+ } -+ if client.UserAgent == "" { -+ client.UserAgent = "autocert" -+ } -+ var contact []string -+ if m.Email != "" { -+ contact = []string{"mailto:" + m.Email} -+ } -+ a := &acme.Account{Contact: contact, ExternalAccountBinding: m.ExternalAccountBinding} -+ _, err := client.Register(ctx, a, m.Prompt) -+ if err == nil || isAccountAlreadyExist(err) { -+ m.client = client -+ err = nil -+ } -+ return m.client, err -+} -+ -+// isAccountAlreadyExist reports whether the err, as returned from acme.Client.Register, -+// indicates the account has already been registered. -+func isAccountAlreadyExist(err error) bool { -+ if err == acme.ErrAccountAlreadyExists { -+ return true -+ } -+ ae, ok := err.(*acme.Error) -+ return ok && ae.StatusCode == http.StatusConflict -+} -+ -+func (m *Manager) hostPolicy() HostPolicy { -+ if m.HostPolicy != nil { -+ return m.HostPolicy -+ } -+ return defaultHostPolicy -+} -+ -+func (m *Manager) renewBefore() time.Duration { -+ if m.RenewBefore > renewJitter { -+ return m.RenewBefore -+ } -+ return 720 * time.Hour // 30 days -+} -+ -+func (m *Manager) now() time.Time { -+ if m.nowFunc != nil { -+ return m.nowFunc() -+ } -+ return time.Now() -+} -+ -+// certState is ready when its mutex is unlocked for reading. -+type certState struct { -+ sync.RWMutex -+ locked bool // locked for read/write -+ key crypto.Signer // private key for cert -+ cert [][]byte // DER encoding -+ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil -+} -+ -+// tlscert creates a tls.Certificate from s.key and s.cert. -+// Callers should wrap it in s.RLock() and s.RUnlock(). -+func (s *certState) tlscert() (*tls.Certificate, error) { -+ if s.key == nil { -+ return nil, errors.New("acme/autocert: missing signer") -+ } -+ if len(s.cert) == 0 { -+ return nil, errors.New("acme/autocert: missing certificate") -+ } -+ return &tls.Certificate{ -+ PrivateKey: s.key, -+ Certificate: s.cert, -+ Leaf: s.leaf, -+ }, nil -+} -+ -+// certRequest generates a CSR for the given common name. -+func certRequest(key crypto.Signer, name string, ext []pkix.Extension) ([]byte, error) { -+ req := &x509.CertificateRequest{ -+ Subject: pkix.Name{CommonName: name}, -+ DNSNames: []string{name}, -+ ExtraExtensions: ext, -+ } -+ return x509.CreateCertificateRequest(rand.Reader, req, key) -+} -+ -+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates -+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. -+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. -+// -+// Inspired by parsePrivateKey in crypto/tls/tls.go. -+func parsePrivateKey(der []byte) (crypto.Signer, error) { -+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { -+ return key, nil -+ } -+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { -+ switch key := key.(type) { -+ case *rsa.PrivateKey: -+ return key, nil -+ case *ecdsa.PrivateKey: -+ return key, nil -+ default: -+ return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping") -+ } -+ } -+ if key, err := x509.ParseECPrivateKey(der); err == nil { -+ return key, nil -+ } -+ -+ return nil, errors.New("acme/autocert: failed to parse private key") -+} -+ -+// validCert parses a cert chain provided as der argument and verifies the leaf and der[0] -+// correspond to the private key, the domain and key type match, and expiration dates -+// are valid. It doesn't do any revocation checking. -+// -+// The returned value is the verified leaf cert. -+func validCert(ck certKey, der [][]byte, key crypto.Signer, now time.Time) (leaf *x509.Certificate, err error) { -+ // parse public part(s) -+ var n int -+ for _, b := range der { -+ n += len(b) -+ } -+ pub := make([]byte, n) -+ n = 0 -+ for _, b := range der { -+ n += copy(pub[n:], b) -+ } -+ x509Cert, err := x509.ParseCertificates(pub) -+ if err != nil || len(x509Cert) == 0 { -+ return nil, errors.New("acme/autocert: no public key found") -+ } -+ // verify the leaf is not expired and matches the domain name -+ leaf = x509Cert[0] -+ if now.Before(leaf.NotBefore) { -+ return nil, errors.New("acme/autocert: certificate is not valid yet") -+ } -+ if now.After(leaf.NotAfter) { -+ return nil, errors.New("acme/autocert: expired certificate") -+ } -+ if err := leaf.VerifyHostname(ck.domain); err != nil { -+ return nil, err -+ } -+ // renew certificates revoked by Let's Encrypt in January 2022 -+ if isRevokedLetsEncrypt(leaf) { -+ return nil, errors.New("acme/autocert: certificate was probably revoked by Let's Encrypt") -+ } -+ // ensure the leaf corresponds to the private key and matches the certKey type -+ switch pub := leaf.PublicKey.(type) { -+ case *rsa.PublicKey: -+ prv, ok := key.(*rsa.PrivateKey) -+ if !ok { -+ return nil, errors.New("acme/autocert: private key type does not match public key type") -+ } -+ if pub.N.Cmp(prv.N) != 0 { -+ return nil, errors.New("acme/autocert: private key does not match public key") -+ } -+ if !ck.isRSA && !ck.isToken { -+ return nil, errors.New("acme/autocert: key type does not match expected value") -+ } -+ case *ecdsa.PublicKey: -+ prv, ok := key.(*ecdsa.PrivateKey) -+ if !ok { -+ return nil, errors.New("acme/autocert: private key type does not match public key type") -+ } -+ if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 { -+ return nil, errors.New("acme/autocert: private key does not match public key") -+ } -+ if ck.isRSA && !ck.isToken { -+ return nil, errors.New("acme/autocert: key type does not match expected value") -+ } -+ default: -+ return nil, errors.New("acme/autocert: unknown public key algorithm") -+ } -+ return leaf, nil -+} -+ -+// https://community.letsencrypt.org/t/2022-01-25-issue-with-tls-alpn-01-validation-method/170450 -+var letsEncryptFixDeployTime = time.Date(2022, time.January, 26, 00, 48, 0, 0, time.UTC) -+ -+// isRevokedLetsEncrypt returns whether the certificate is likely to be part of -+// a batch of certificates revoked by Let's Encrypt in January 2022. This check -+// can be safely removed from May 2022. -+func isRevokedLetsEncrypt(cert *x509.Certificate) bool { -+ O := cert.Issuer.Organization -+ return len(O) == 1 && O[0] == "Let's Encrypt" && -+ cert.NotBefore.Before(letsEncryptFixDeployTime) -+} -+ -+type lockedMathRand struct { -+ sync.Mutex -+ rnd *mathrand.Rand -+} -+ -+func (r *lockedMathRand) int63n(max int64) int64 { -+ r.Lock() -+ n := r.rnd.Int63n(max) -+ r.Unlock() -+ return n -+} -+ -+// For easier testing. -+var ( -+ // Called when a state is removed. -+ testDidRemoveState = func(certKey) {} -+) -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go -new file mode 100644 -index 00000000000000..725677574bb6cc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/autocert_test.go -@@ -0,0 +1,996 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "fmt" -+ "io" -+ "math/big" -+ "net/http" -+ "net/http/httptest" -+ "reflect" -+ "strings" -+ "sync" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+ "golang.org/x/crypto/acme/autocert/internal/acmetest" -+) -+ -+var ( -+ exampleDomain = "example.org" -+ exampleCertKey = certKey{domain: exampleDomain} -+ exampleCertKeyRSA = certKey{domain: exampleDomain, isRSA: true} -+) -+ -+type memCache struct { -+ t *testing.T -+ mu sync.Mutex -+ keyData map[string][]byte -+} -+ -+func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) { -+ m.mu.Lock() -+ defer m.mu.Unlock() -+ -+ v, ok := m.keyData[key] -+ if !ok { -+ return nil, ErrCacheMiss -+ } -+ return v, nil -+} -+ -+// filenameSafe returns whether all characters in s are printable ASCII -+// and safe to use in a filename on most filesystems. -+func filenameSafe(s string) bool { -+ for _, c := range s { -+ if c < 0x20 || c > 0x7E { -+ return false -+ } -+ switch c { -+ case '\\', '/', ':', '*', '?', '"', '<', '>', '|': -+ return false -+ } -+ } -+ return true -+} -+ -+func (m *memCache) Put(ctx context.Context, key string, data []byte) error { -+ if !filenameSafe(key) { -+ m.t.Errorf("invalid characters in cache key %q", key) -+ } -+ -+ m.mu.Lock() -+ defer m.mu.Unlock() -+ -+ m.keyData[key] = data -+ return nil -+} -+ -+func (m *memCache) Delete(ctx context.Context, key string) error { -+ m.mu.Lock() -+ defer m.mu.Unlock() -+ -+ delete(m.keyData, key) -+ return nil -+} -+ -+func newMemCache(t *testing.T) *memCache { -+ return &memCache{ -+ t: t, -+ keyData: make(map[string][]byte), -+ } -+} -+ -+func (m *memCache) numCerts() int { -+ m.mu.Lock() -+ defer m.mu.Unlock() -+ -+ res := 0 -+ for key := range m.keyData { -+ if strings.HasSuffix(key, "+token") || -+ strings.HasSuffix(key, "+key") || -+ strings.HasSuffix(key, "+http-01") { -+ continue -+ } -+ res++ -+ } -+ return res -+} -+ -+func dummyCert(pub interface{}, san ...string) ([]byte, error) { -+ return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...) -+} -+ -+func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) { -+ // use EC key to run faster on 386 -+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ return nil, err -+ } -+ t := &x509.Certificate{ -+ SerialNumber: randomSerial(), -+ NotBefore: start, -+ NotAfter: end, -+ BasicConstraintsValid: true, -+ KeyUsage: x509.KeyUsageKeyEncipherment, -+ DNSNames: san, -+ } -+ if pub == nil { -+ pub = &key.PublicKey -+ } -+ return x509.CreateCertificate(rand.Reader, t, t, pub, key) -+} -+ -+func randomSerial() *big.Int { -+ serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 32)) -+ if err != nil { -+ panic(err) -+ } -+ return serial -+} -+ -+type algorithmSupport int -+ -+const ( -+ algRSA algorithmSupport = iota -+ algECDSA -+) -+ -+func clientHelloInfo(sni string, alg algorithmSupport) *tls.ClientHelloInfo { -+ hello := &tls.ClientHelloInfo{ -+ ServerName: sni, -+ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, -+ } -+ if alg == algECDSA { -+ hello.CipherSuites = append(hello.CipherSuites, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) -+ } -+ return hello -+} -+ -+func testManager(t *testing.T) *Manager { -+ man := &Manager{ -+ Prompt: AcceptTOS, -+ Cache: newMemCache(t), -+ } -+ t.Cleanup(man.stopRenew) -+ return man -+} -+ -+func TestGetCertificate(t *testing.T) { -+ tests := []struct { -+ name string -+ hello *tls.ClientHelloInfo -+ domain string -+ expectError string -+ prepare func(t *testing.T, man *Manager, s *acmetest.CAServer) -+ verify func(t *testing.T, man *Manager, leaf *x509.Certificate) -+ disableALPN bool -+ disableHTTP bool -+ }{ -+ { -+ name: "ALPN", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ disableHTTP: true, -+ }, -+ { -+ name: "HTTP", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ disableALPN: true, -+ }, -+ { -+ name: "nilPrompt", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ man.Prompt = nil -+ }, -+ expectError: "Manager.Prompt not set", -+ }, -+ { -+ name: "trailingDot", -+ hello: clientHelloInfo("example.org.", algECDSA), -+ domain: "example.org", -+ }, -+ { -+ name: "unicodeIDN", -+ hello: clientHelloInfo("éé.com", algECDSA), -+ domain: "xn--9caa.com", -+ }, -+ { -+ name: "unicodeIDN/mixedCase", -+ hello: clientHelloInfo("éÉ.com", algECDSA), -+ domain: "xn--9caa.com", -+ }, -+ { -+ name: "upperCase", -+ hello: clientHelloInfo("EXAMPLE.ORG", algECDSA), -+ domain: "example.org", -+ }, -+ { -+ name: "goodCache", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ // Make a valid cert and cache it. -+ c := s.Start().LeafCert(exampleDomain, "ECDSA", -+ // Use a time before the Let's Encrypt revocation cutoff to also test -+ // that non-Let's Encrypt certificates are not renewed. -+ time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), -+ time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), -+ ) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ }, -+ // Break the server to check that the cache is used. -+ disableALPN: true, disableHTTP: true, -+ }, -+ { -+ name: "expiredCache", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ // Make an expired cert and cache it. -+ c := s.Start().LeafCert(exampleDomain, "ECDSA", time.Now().Add(-10*time.Minute), time.Now().Add(-5*time.Minute)) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ }, -+ }, -+ { -+ name: "forceRSA", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ man.ForceRSA = true -+ }, -+ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { -+ if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { -+ t.Errorf("leaf.PublicKey is %T; want *ecdsa.PublicKey", leaf.PublicKey) -+ } -+ }, -+ }, -+ { -+ name: "goodLetsEncrypt", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ // Make a valid certificate issued after the TLS-ALPN-01 -+ // revocation window and cache it. -+ s.IssuerName(pkix.Name{Country: []string{"US"}, -+ Organization: []string{"Let's Encrypt"}, CommonName: "R3"}) -+ c := s.Start().LeafCert(exampleDomain, "ECDSA", -+ time.Date(2022, time.January, 26, 12, 0, 0, 0, time.UTC), -+ time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), -+ ) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ }, -+ // Break the server to check that the cache is used. -+ disableALPN: true, disableHTTP: true, -+ }, -+ { -+ name: "revokedLetsEncrypt", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ // Make a certificate issued during the TLS-ALPN-01 -+ // revocation window and cache it. -+ s.IssuerName(pkix.Name{Country: []string{"US"}, -+ Organization: []string{"Let's Encrypt"}, CommonName: "R3"}) -+ c := s.Start().LeafCert(exampleDomain, "ECDSA", -+ time.Date(2022, time.January, 1, 0, 0, 0, 0, time.UTC), -+ time.Date(2122, time.January, 1, 0, 0, 0, 0, time.UTC), -+ ) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ }, -+ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { -+ if leaf.NotBefore.Before(time.Now().Add(-10 * time.Minute)) { -+ t.Error("certificate was not reissued") -+ } -+ }, -+ }, -+ { -+ // TestGetCertificate/tokenCache tests the fallback of token -+ // certificate fetches to cache when Manager.certTokens misses. -+ name: "tokenCacheALPN", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ // Make a separate manager with a shared cache, simulating -+ // separate nodes that serve requests for the same domain. -+ man2 := testManager(t) -+ man2.Cache = man.Cache -+ // Redirect the verification request to man2, although the -+ // client request will hit man, testing that they can complete a -+ // verification by communicating through the cache. -+ s.ResolveGetCertificate("example.org", man2.GetCertificate) -+ }, -+ // Drop the default verification paths. -+ disableALPN: true, -+ }, -+ { -+ name: "tokenCacheHTTP", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ man2 := testManager(t) -+ man2.Cache = man.Cache -+ s.ResolveHandler("example.org", man2.HTTPHandler(nil)) -+ }, -+ disableHTTP: true, -+ }, -+ { -+ name: "ecdsa", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { -+ if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { -+ t.Error("an ECDSA client was served a non-ECDSA certificate") -+ } -+ }, -+ }, -+ { -+ name: "rsa", -+ hello: clientHelloInfo("example.org", algRSA), -+ domain: "example.org", -+ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { -+ if _, ok := leaf.PublicKey.(*rsa.PublicKey); !ok { -+ t.Error("an RSA client was served a non-RSA certificate") -+ } -+ }, -+ }, -+ { -+ name: "wrongCacheKeyType", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ // Make an RSA cert and cache it without suffix. -+ c := s.Start().LeafCert(exampleDomain, "RSA", time.Now(), time.Now().Add(90*24*time.Hour)) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ }, -+ verify: func(t *testing.T, man *Manager, leaf *x509.Certificate) { -+ // The RSA cached cert should be silently ignored and replaced. -+ if _, ok := leaf.PublicKey.(*ecdsa.PublicKey); !ok { -+ t.Error("an ECDSA client was served a non-ECDSA certificate") -+ } -+ if numCerts := man.Cache.(*memCache).numCerts(); numCerts != 1 { -+ t.Errorf("found %d certificates in cache; want %d", numCerts, 1) -+ } -+ }, -+ }, -+ { -+ name: "almostExpiredCache", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ man.RenewBefore = 24 * time.Hour -+ // Cache an almost expired cert. -+ c := s.Start().LeafCert(exampleDomain, "ECDSA", time.Now(), time.Now().Add(10*time.Minute)) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ }, -+ }, -+ { -+ name: "provideExternalAuth", -+ hello: clientHelloInfo("example.org", algECDSA), -+ domain: "example.org", -+ prepare: func(t *testing.T, man *Manager, s *acmetest.CAServer) { -+ s.ExternalAccountRequired() -+ -+ man.ExternalAccountBinding = &acme.ExternalAccountBinding{ -+ KID: "test-key", -+ Key: make([]byte, 32), -+ } -+ }, -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ man := testManager(t) -+ s := acmetest.NewCAServer(t) -+ if !tt.disableALPN { -+ s.ResolveGetCertificate(tt.domain, man.GetCertificate) -+ } -+ if !tt.disableHTTP { -+ s.ResolveHandler(tt.domain, man.HTTPHandler(nil)) -+ } -+ -+ if tt.prepare != nil { -+ tt.prepare(t, man, s) -+ } -+ -+ s.Start() -+ -+ man.Client = &acme.Client{DirectoryURL: s.URL()} -+ -+ tlscert, err := man.GetCertificate(tt.hello) -+ if tt.expectError != "" { -+ if err == nil { -+ t.Fatal("expected error, got certificate") -+ } -+ if !strings.Contains(err.Error(), tt.expectError) { -+ t.Errorf("got %q, expected %q", err, tt.expectError) -+ } -+ return -+ } -+ if err != nil { -+ t.Fatalf("man.GetCertificate: %v", err) -+ } -+ -+ leaf, err := x509.ParseCertificate(tlscert.Certificate[0]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ opts := x509.VerifyOptions{ -+ DNSName: tt.domain, -+ Intermediates: x509.NewCertPool(), -+ Roots: s.Roots(), -+ } -+ for _, cert := range tlscert.Certificate[1:] { -+ c, err := x509.ParseCertificate(cert) -+ if err != nil { -+ t.Fatal(err) -+ } -+ opts.Intermediates.AddCert(c) -+ } -+ if _, err := leaf.Verify(opts); err != nil { -+ t.Error(err) -+ } -+ -+ if san := leaf.DNSNames[0]; san != tt.domain { -+ t.Errorf("got SAN %q, expected %q", san, tt.domain) -+ } -+ -+ if tt.verify != nil { -+ tt.verify(t, man, leaf) -+ } -+ }) -+ } -+} -+ -+func TestGetCertificate_failedAttempt(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.WriteHeader(http.StatusBadRequest) -+ })) -+ defer ts.Close() -+ -+ d := createCertRetryAfter -+ f := testDidRemoveState -+ defer func() { -+ createCertRetryAfter = d -+ testDidRemoveState = f -+ }() -+ createCertRetryAfter = 0 -+ done := make(chan struct{}) -+ testDidRemoveState = func(ck certKey) { -+ if ck != exampleCertKey { -+ t.Errorf("testDidRemoveState: domain = %v; want %v", ck, exampleCertKey) -+ } -+ close(done) -+ } -+ -+ man := &Manager{ -+ Prompt: AcceptTOS, -+ Client: &acme.Client{ -+ DirectoryURL: ts.URL, -+ }, -+ } -+ defer man.stopRenew() -+ hello := clientHelloInfo(exampleDomain, algECDSA) -+ if _, err := man.GetCertificate(hello); err == nil { -+ t.Error("GetCertificate: err is nil") -+ } -+ -+ <-done -+ man.stateMu.Lock() -+ defer man.stateMu.Unlock() -+ if v, exist := man.state[exampleCertKey]; exist { -+ t.Errorf("state exists for %v: %+v", exampleCertKey, v) -+ } -+} -+ -+func TestRevokeFailedAuthz(t *testing.T) { -+ ca := acmetest.NewCAServer(t) -+ // Make the authz unfulfillable on the client side, so it will be left -+ // pending at the end of the verification attempt. -+ ca.ChallengeTypes("fake-01", "fake-02") -+ ca.Start() -+ -+ m := testManager(t) -+ m.Client = &acme.Client{DirectoryURL: ca.URL()} -+ -+ _, err := m.GetCertificate(clientHelloInfo("example.org", algECDSA)) -+ if err == nil { -+ t.Fatal("expected GetCertificate to fail") -+ } -+ -+ logTicker := time.NewTicker(3 * time.Second) -+ defer logTicker.Stop() -+ for { -+ authz, err := m.Client.GetAuthorization(context.Background(), ca.URL()+"/authz/0") -+ if err != nil { -+ t.Fatal(err) -+ } -+ if authz.Status == acme.StatusDeactivated { -+ return -+ } -+ -+ select { -+ case <-logTicker.C: -+ t.Logf("still waiting on revocations") -+ default: -+ } -+ time.Sleep(50 * time.Millisecond) -+ } -+} -+ -+func TestHTTPHandlerDefaultFallback(t *testing.T) { -+ tt := []struct { -+ method, url string -+ wantCode int -+ wantLocation string -+ }{ -+ {"GET", "http://example.org", 302, "https://example.org/"}, -+ {"GET", "http://example.org/foo", 302, "https://example.org/foo"}, -+ {"GET", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, -+ {"GET", "http://example.org/?a=b", 302, "https://example.org/?a=b"}, -+ {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, -+ {"GET", "http://example.org:80/foo?a=b", 302, "https://example.org:443/foo?a=b"}, -+ {"GET", "http://example.org:80/foo%20bar", 302, "https://example.org:443/foo%20bar"}, -+ {"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"}, -+ {"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"}, -+ {"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"}, -+ {"HEAD", "http://example.org", 302, "https://example.org/"}, -+ {"HEAD", "http://example.org/foo", 302, "https://example.org/foo"}, -+ {"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, -+ {"HEAD", "http://example.org/?a=b", 302, "https://example.org/?a=b"}, -+ {"HEAD", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, -+ {"POST", "http://example.org", 400, ""}, -+ {"PUT", "http://example.org", 400, ""}, -+ {"GET", "http://example.org/.well-known/acme-challenge/x", 404, ""}, -+ } -+ var m Manager -+ h := m.HTTPHandler(nil) -+ for i, test := range tt { -+ r := httptest.NewRequest(test.method, test.url, nil) -+ w := httptest.NewRecorder() -+ h.ServeHTTP(w, r) -+ if w.Code != test.wantCode { -+ t.Errorf("%d: w.Code = %d; want %d", i, w.Code, test.wantCode) -+ t.Errorf("%d: body: %s", i, w.Body.Bytes()) -+ } -+ if v := w.Header().Get("Location"); v != test.wantLocation { -+ t.Errorf("%d: Location = %q; want %q", i, v, test.wantLocation) -+ } -+ } -+} -+ -+func TestAccountKeyCache(t *testing.T) { -+ m := Manager{Cache: newMemCache(t)} -+ ctx := context.Background() -+ k1, err := m.accountKey(ctx) -+ if err != nil { -+ t.Fatal(err) -+ } -+ k2, err := m.accountKey(ctx) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if !reflect.DeepEqual(k1, k2) { -+ t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2) -+ } -+} -+ -+func TestCache(t *testing.T) { -+ ecdsaKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert, err := dummyCert(ecdsaKey.Public(), exampleDomain) -+ if err != nil { -+ t.Fatal(err) -+ } -+ ecdsaCert := &tls.Certificate{ -+ Certificate: [][]byte{cert}, -+ PrivateKey: ecdsaKey, -+ } -+ -+ rsaKey, err := rsa.GenerateKey(rand.Reader, 512) -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert, err = dummyCert(rsaKey.Public(), exampleDomain) -+ if err != nil { -+ t.Fatal(err) -+ } -+ rsaCert := &tls.Certificate{ -+ Certificate: [][]byte{cert}, -+ PrivateKey: rsaKey, -+ } -+ -+ man := &Manager{Cache: newMemCache(t)} -+ defer man.stopRenew() -+ ctx := context.Background() -+ -+ if err := man.cachePut(ctx, exampleCertKey, ecdsaCert); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ if err := man.cachePut(ctx, exampleCertKeyRSA, rsaCert); err != nil { -+ t.Fatalf("man.cachePut: %v", err) -+ } -+ -+ res, err := man.cacheGet(ctx, exampleCertKey) -+ if err != nil { -+ t.Fatalf("man.cacheGet: %v", err) -+ } -+ if res == nil || !bytes.Equal(res.Certificate[0], ecdsaCert.Certificate[0]) { -+ t.Errorf("man.cacheGet = %+v; want %+v", res, ecdsaCert) -+ } -+ -+ res, err = man.cacheGet(ctx, exampleCertKeyRSA) -+ if err != nil { -+ t.Fatalf("man.cacheGet: %v", err) -+ } -+ if res == nil || !bytes.Equal(res.Certificate[0], rsaCert.Certificate[0]) { -+ t.Errorf("man.cacheGet = %+v; want %+v", res, rsaCert) -+ } -+} -+ -+func TestHostWhitelist(t *testing.T) { -+ policy := HostWhitelist("example.com", "EXAMPLE.ORG", "*.example.net", "éÉ.com") -+ tt := []struct { -+ host string -+ allow bool -+ }{ -+ {"example.com", true}, -+ {"example.org", true}, -+ {"xn--9caa.com", true}, // éé.com -+ {"one.example.com", false}, -+ {"two.example.org", false}, -+ {"three.example.net", false}, -+ {"dummy", false}, -+ } -+ for i, test := range tt { -+ err := policy(nil, test.host) -+ if err != nil && test.allow { -+ t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err) -+ } -+ if err == nil && !test.allow { -+ t.Errorf("%d: policy(%q): nil; want an error", i, test.host) -+ } -+ } -+} -+ -+func TestValidCert(t *testing.T) { -+ key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ key3, err := rsa.GenerateKey(rand.Reader, 512) -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert1, err := dummyCert(key1.Public(), "example.org") -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert2, err := dummyCert(key2.Public(), "example.org") -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert3, err := dummyCert(key3.Public(), "example.org") -+ if err != nil { -+ t.Fatal(err) -+ } -+ now := time.Now() -+ early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org") -+ if err != nil { -+ t.Fatal(err) -+ } -+ expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org") -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ tt := []struct { -+ ck certKey -+ key crypto.Signer -+ cert [][]byte -+ ok bool -+ }{ -+ {certKey{domain: "example.org"}, key1, [][]byte{cert1}, true}, -+ {certKey{domain: "example.org", isRSA: true}, key3, [][]byte{cert3}, true}, -+ {certKey{domain: "example.org"}, key1, [][]byte{cert1, cert2, cert3}, true}, -+ {certKey{domain: "example.org"}, key1, [][]byte{cert1, {1}}, false}, -+ {certKey{domain: "example.org"}, key1, [][]byte{{1}}, false}, -+ {certKey{domain: "example.org"}, key1, [][]byte{cert2}, false}, -+ {certKey{domain: "example.org"}, key2, [][]byte{cert1}, false}, -+ {certKey{domain: "example.org"}, key1, [][]byte{cert3}, false}, -+ {certKey{domain: "example.org"}, key3, [][]byte{cert1}, false}, -+ {certKey{domain: "example.net"}, key1, [][]byte{cert1}, false}, -+ {certKey{domain: "example.org"}, key1, [][]byte{early}, false}, -+ {certKey{domain: "example.org"}, key1, [][]byte{expired}, false}, -+ {certKey{domain: "example.org", isRSA: true}, key1, [][]byte{cert1}, false}, -+ {certKey{domain: "example.org"}, key3, [][]byte{cert3}, false}, -+ } -+ for i, test := range tt { -+ leaf, err := validCert(test.ck, test.cert, test.key, now) -+ if err != nil && test.ok { -+ t.Errorf("%d: err = %v", i, err) -+ } -+ if err == nil && !test.ok { -+ t.Errorf("%d: err is nil", i) -+ } -+ if err == nil && test.ok && leaf == nil { -+ t.Errorf("%d: leaf is nil", i) -+ } -+ } -+} -+ -+type cacheGetFunc func(ctx context.Context, key string) ([]byte, error) -+ -+func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) { -+ return f(ctx, key) -+} -+ -+func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error { -+ return fmt.Errorf("unsupported Put of %q = %q", key, data) -+} -+ -+func (f cacheGetFunc) Delete(ctx context.Context, key string) error { -+ return fmt.Errorf("unsupported Delete of %q", key) -+} -+ -+func TestManagerGetCertificateBogusSNI(t *testing.T) { -+ m := Manager{ -+ Prompt: AcceptTOS, -+ Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) { -+ return nil, fmt.Errorf("cache.Get of %s", key) -+ }), -+ } -+ tests := []struct { -+ name string -+ wantErr string -+ }{ -+ {"foo.com", "cache.Get of foo.com"}, -+ {"foo.com.", "cache.Get of foo.com"}, -+ {`a\b.com`, "acme/autocert: server name contains invalid character"}, -+ {`a/b.com`, "acme/autocert: server name contains invalid character"}, -+ {"", "acme/autocert: missing server name"}, -+ {"foo", "acme/autocert: server name component count invalid"}, -+ {".foo", "acme/autocert: server name component count invalid"}, -+ {"foo.", "acme/autocert: server name component count invalid"}, -+ {"fo.o", "cache.Get of fo.o"}, -+ } -+ for _, tt := range tests { -+ _, err := m.GetCertificate(clientHelloInfo(tt.name, algECDSA)) -+ got := fmt.Sprint(err) -+ if got != tt.wantErr { -+ t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr) -+ } -+ } -+} -+ -+func TestCertRequest(t *testing.T) { -+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ // An extension from RFC7633. Any will do. -+ ext := pkix.Extension{ -+ Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1}, -+ Value: []byte("dummy"), -+ } -+ b, err := certRequest(key, "example.org", []pkix.Extension{ext}) -+ if err != nil { -+ t.Fatalf("certRequest: %v", err) -+ } -+ r, err := x509.ParseCertificateRequest(b) -+ if err != nil { -+ t.Fatalf("ParseCertificateRequest: %v", err) -+ } -+ var found bool -+ for _, v := range r.Extensions { -+ if v.Id.Equal(ext.Id) { -+ found = true -+ break -+ } -+ } -+ if !found { -+ t.Errorf("want %v in Extensions: %v", ext, r.Extensions) -+ } -+} -+ -+func TestSupportsECDSA(t *testing.T) { -+ tests := []struct { -+ CipherSuites []uint16 -+ SignatureSchemes []tls.SignatureScheme -+ SupportedCurves []tls.CurveID -+ ecdsaOk bool -+ }{ -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -+ }, nil, nil, false}, -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ }, nil, nil, true}, -+ -+ // SignatureSchemes limits, not extends, CipherSuites -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -+ }, []tls.SignatureScheme{ -+ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, -+ }, nil, false}, -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ }, []tls.SignatureScheme{ -+ tls.PKCS1WithSHA256, -+ }, nil, false}, -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ }, []tls.SignatureScheme{ -+ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, -+ }, nil, true}, -+ -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ }, []tls.SignatureScheme{ -+ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, -+ }, []tls.CurveID{ -+ tls.CurveP521, -+ }, false}, -+ {[]uint16{ -+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -+ }, []tls.SignatureScheme{ -+ tls.PKCS1WithSHA256, tls.ECDSAWithP256AndSHA256, -+ }, []tls.CurveID{ -+ tls.CurveP256, -+ tls.CurveP521, -+ }, true}, -+ } -+ for i, tt := range tests { -+ result := supportsECDSA(&tls.ClientHelloInfo{ -+ CipherSuites: tt.CipherSuites, -+ SignatureSchemes: tt.SignatureSchemes, -+ SupportedCurves: tt.SupportedCurves, -+ }) -+ if result != tt.ecdsaOk { -+ t.Errorf("%d: supportsECDSA = %v; want %v", i, result, tt.ecdsaOk) -+ } -+ } -+} -+ -+func TestEndToEndALPN(t *testing.T) { -+ const domain = "example.org" -+ -+ // ACME CA server -+ ca := acmetest.NewCAServer(t).Start() -+ -+ // User HTTPS server. -+ m := &Manager{ -+ Prompt: AcceptTOS, -+ Client: &acme.Client{DirectoryURL: ca.URL()}, -+ } -+ us := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Write([]byte("OK")) -+ })) -+ us.TLS = &tls.Config{ -+ NextProtos: []string{"http/1.1", acme.ALPNProto}, -+ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { -+ cert, err := m.GetCertificate(hello) -+ if err != nil { -+ t.Errorf("m.GetCertificate: %v", err) -+ } -+ return cert, err -+ }, -+ } -+ us.StartTLS() -+ defer us.Close() -+ // In TLS-ALPN challenge verification, CA connects to the domain:443 in question. -+ // Because the domain won't resolve in tests, we need to tell the CA -+ // where to dial to instead. -+ ca.Resolve(domain, strings.TrimPrefix(us.URL, "https://")) -+ -+ // A client visiting user's HTTPS server. -+ tr := &http.Transport{ -+ TLSClientConfig: &tls.Config{ -+ RootCAs: ca.Roots(), -+ ServerName: domain, -+ }, -+ } -+ client := &http.Client{Transport: tr} -+ res, err := client.Get(us.URL) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer res.Body.Close() -+ b, err := io.ReadAll(res.Body) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if v := string(b); v != "OK" { -+ t.Errorf("user server response: %q; want 'OK'", v) -+ } -+} -+ -+func TestEndToEndHTTP(t *testing.T) { -+ const domain = "example.org" -+ -+ // ACME CA server. -+ ca := acmetest.NewCAServer(t).ChallengeTypes("http-01").Start() -+ -+ // User HTTP server for the ACME challenge. -+ m := testManager(t) -+ m.Client = &acme.Client{DirectoryURL: ca.URL()} -+ s := httptest.NewServer(m.HTTPHandler(nil)) -+ defer s.Close() -+ -+ // User HTTPS server. -+ ss := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Write([]byte("OK")) -+ })) -+ ss.TLS = &tls.Config{ -+ NextProtos: []string{"http/1.1", acme.ALPNProto}, -+ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { -+ cert, err := m.GetCertificate(hello) -+ if err != nil { -+ t.Errorf("m.GetCertificate: %v", err) -+ } -+ return cert, err -+ }, -+ } -+ ss.StartTLS() -+ defer ss.Close() -+ -+ // Redirect the CA requests to the HTTP server. -+ ca.Resolve(domain, strings.TrimPrefix(s.URL, "http://")) -+ -+ // A client visiting user's HTTPS server. -+ tr := &http.Transport{ -+ TLSClientConfig: &tls.Config{ -+ RootCAs: ca.Roots(), -+ ServerName: domain, -+ }, -+ } -+ client := &http.Client{Transport: tr} -+ res, err := client.Get(ss.URL) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer res.Body.Close() -+ b, err := io.ReadAll(res.Body) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if v := string(b); v != "OK" { -+ t.Errorf("user server response: %q; want 'OK'", v) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/cache.go b/ms_mod/golang.org/x/crypto/acme/autocert/cache.go -new file mode 100644 -index 00000000000000..758ab12cb225fc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/cache.go -@@ -0,0 +1,135 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "context" -+ "errors" -+ "os" -+ "path/filepath" -+) -+ -+// ErrCacheMiss is returned when a certificate is not found in cache. -+var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") -+ -+// Cache is used by Manager to store and retrieve previously obtained certificates -+// and other account data as opaque blobs. -+// -+// Cache implementations should not rely on the key naming pattern. Keys can -+// include any printable ASCII characters, except the following: \/:*?"<>| -+type Cache interface { -+ // Get returns a certificate data for the specified key. -+ // If there's no such key, Get returns ErrCacheMiss. -+ Get(ctx context.Context, key string) ([]byte, error) -+ -+ // Put stores the data in the cache under the specified key. -+ // Underlying implementations may use any data storage format, -+ // as long as the reverse operation, Get, results in the original data. -+ Put(ctx context.Context, key string, data []byte) error -+ -+ // Delete removes a certificate data from the cache under the specified key. -+ // If there's no such key in the cache, Delete returns nil. -+ Delete(ctx context.Context, key string) error -+} -+ -+// DirCache implements Cache using a directory on the local filesystem. -+// If the directory does not exist, it will be created with 0700 permissions. -+type DirCache string -+ -+// Get reads a certificate data from the specified file name. -+func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { -+ name = filepath.Join(string(d), filepath.Clean("/"+name)) -+ var ( -+ data []byte -+ err error -+ done = make(chan struct{}) -+ ) -+ go func() { -+ data, err = os.ReadFile(name) -+ close(done) -+ }() -+ select { -+ case <-ctx.Done(): -+ return nil, ctx.Err() -+ case <-done: -+ } -+ if os.IsNotExist(err) { -+ return nil, ErrCacheMiss -+ } -+ return data, err -+} -+ -+// Put writes the certificate data to the specified file name. -+// The file will be created with 0600 permissions. -+func (d DirCache) Put(ctx context.Context, name string, data []byte) error { -+ if err := os.MkdirAll(string(d), 0700); err != nil { -+ return err -+ } -+ -+ done := make(chan struct{}) -+ var err error -+ go func() { -+ defer close(done) -+ var tmp string -+ if tmp, err = d.writeTempFile(name, data); err != nil { -+ return -+ } -+ defer os.Remove(tmp) -+ select { -+ case <-ctx.Done(): -+ // Don't overwrite the file if the context was canceled. -+ default: -+ newName := filepath.Join(string(d), filepath.Clean("/"+name)) -+ err = os.Rename(tmp, newName) -+ } -+ }() -+ select { -+ case <-ctx.Done(): -+ return ctx.Err() -+ case <-done: -+ } -+ return err -+} -+ -+// Delete removes the specified file name. -+func (d DirCache) Delete(ctx context.Context, name string) error { -+ name = filepath.Join(string(d), filepath.Clean("/"+name)) -+ var ( -+ err error -+ done = make(chan struct{}) -+ ) -+ go func() { -+ err = os.Remove(name) -+ close(done) -+ }() -+ select { -+ case <-ctx.Done(): -+ return ctx.Err() -+ case <-done: -+ } -+ if err != nil && !os.IsNotExist(err) { -+ return err -+ } -+ return nil -+} -+ -+// writeTempFile writes b to a temporary file, closes the file and returns its path. -+func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) { -+ // TempFile uses 0600 permissions -+ f, err := os.CreateTemp(string(d), prefix) -+ if err != nil { -+ return "", err -+ } -+ defer func() { -+ if reterr != nil { -+ os.Remove(f.Name()) -+ } -+ }() -+ if _, err := f.Write(b); err != nil { -+ f.Close() -+ return "", err -+ } -+ return f.Name(), f.Close() -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go -new file mode 100644 -index 00000000000000..582e6b05804975 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/cache_test.go -@@ -0,0 +1,66 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "context" -+ "os" -+ "path/filepath" -+ "reflect" -+ "testing" -+) -+ -+// make sure DirCache satisfies Cache interface -+var _ Cache = DirCache("/") -+ -+func TestDirCache(t *testing.T) { -+ dir, err := os.MkdirTemp("", "autocert") -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer os.RemoveAll(dir) -+ dir = filepath.Join(dir, "certs") // a nonexistent dir -+ cache := DirCache(dir) -+ ctx := context.Background() -+ -+ // test cache miss -+ if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss { -+ t.Errorf("get: %v; want ErrCacheMiss", err) -+ } -+ -+ // test put/get -+ b1 := []byte{1} -+ if err := cache.Put(ctx, "dummy", b1); err != nil { -+ t.Fatalf("put: %v", err) -+ } -+ b2, err := cache.Get(ctx, "dummy") -+ if err != nil { -+ t.Fatalf("get: %v", err) -+ } -+ if !reflect.DeepEqual(b1, b2) { -+ t.Errorf("b1 = %v; want %v", b1, b2) -+ } -+ name := filepath.Join(dir, "dummy") -+ if _, err := os.Stat(name); err != nil { -+ t.Error(err) -+ } -+ -+ // test put deletes temp file -+ tmp, err := filepath.Glob(name + "?*") -+ if err != nil { -+ t.Error(err) -+ } -+ if tmp != nil { -+ t.Errorf("temp file exists: %s", tmp) -+ } -+ -+ // test delete -+ if err := cache.Delete(ctx, "dummy"); err != nil { -+ t.Fatalf("delete: %v", err) -+ } -+ if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss { -+ t.Errorf("get: %v; want ErrCacheMiss", err) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/example_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/example_test.go -new file mode 100644 -index 00000000000000..6c7458b0d53fcc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/example_test.go -@@ -0,0 +1,35 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert_test -+ -+import ( -+ "fmt" -+ "log" -+ "net/http" -+ -+ "golang.org/x/crypto/acme/autocert" -+) -+ -+func ExampleNewListener() { -+ mux := http.NewServeMux() -+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { -+ fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS) -+ }) -+ log.Fatal(http.Serve(autocert.NewListener("example.com"), mux)) -+} -+ -+func ExampleManager() { -+ m := &autocert.Manager{ -+ Cache: autocert.DirCache("secret-dir"), -+ Prompt: autocert.AcceptTOS, -+ Email: "example@example.org", -+ HostPolicy: autocert.HostWhitelist("example.org", "www.example.org"), -+ } -+ s := &http.Server{ -+ Addr: ":https", -+ TLSConfig: m.TLSConfig(), -+ } -+ s.ListenAndServeTLS("", "") -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go b/ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go -new file mode 100644 -index 00000000000000..0a5ebe7ab7652e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/internal/acmetest/ca.go -@@ -0,0 +1,796 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package acmetest provides types for testing acme and autocert packages. -+// -+// TODO: Consider moving this to x/crypto/acme/internal/acmetest for acme tests as well. -+package acmetest -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/json" -+ "encoding/pem" -+ "fmt" -+ "io" -+ "math/big" -+ "net" -+ "net/http" -+ "net/http/httptest" -+ "path" -+ "strconv" -+ "strings" -+ "sync" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+) -+ -+// CAServer is a simple test server which implements ACME spec bits needed for testing. -+type CAServer struct { -+ rootKey crypto.Signer -+ rootCert []byte // DER encoding -+ rootTemplate *x509.Certificate -+ -+ t *testing.T -+ server *httptest.Server -+ issuer pkix.Name -+ challengeTypes []string -+ url string -+ roots *x509.CertPool -+ eabRequired bool -+ -+ mu sync.Mutex -+ certCount int // number of issued certs -+ acctRegistered bool // set once an account has been registered -+ domainAddr map[string]string // domain name to addr:port resolution -+ domainGetCert map[string]getCertificateFunc // domain name to GetCertificate function -+ domainHandler map[string]http.Handler // domain name to Handle function -+ validAuthz map[string]*authorization // valid authz, keyed by domain name -+ authorizations []*authorization // all authz, index is used as ID -+ orders []*order // index is used as order ID -+ errors []error // encountered client errors -+} -+ -+type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) -+ -+// NewCAServer creates a new ACME test server. The returned CAServer issues -+// certs signed with the CA roots available in the Roots field. -+func NewCAServer(t *testing.T) *CAServer { -+ ca := &CAServer{t: t, -+ challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"}, -+ domainAddr: make(map[string]string), -+ domainGetCert: make(map[string]getCertificateFunc), -+ domainHandler: make(map[string]http.Handler), -+ validAuthz: make(map[string]*authorization), -+ } -+ -+ ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle)) -+ -+ r, err := rand.Int(rand.Reader, big.NewInt(1000000)) -+ if err != nil { -+ panic(fmt.Sprintf("rand.Int: %v", err)) -+ } -+ ca.issuer = pkix.Name{ -+ Organization: []string{"Test Acme Co"}, -+ CommonName: "Root CA " + r.String(), -+ } -+ -+ return ca -+} -+ -+func (ca *CAServer) generateRoot() { -+ key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err)) -+ } -+ tmpl := &x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ Subject: ca.issuer, -+ NotBefore: time.Now(), -+ NotAfter: time.Now().Add(365 * 24 * time.Hour), -+ KeyUsage: x509.KeyUsageCertSign, -+ BasicConstraintsValid: true, -+ IsCA: true, -+ } -+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) -+ if err != nil { -+ panic(fmt.Sprintf("x509.CreateCertificate: %v", err)) -+ } -+ cert, err := x509.ParseCertificate(der) -+ if err != nil { -+ panic(fmt.Sprintf("x509.ParseCertificate: %v", err)) -+ } -+ ca.roots = x509.NewCertPool() -+ ca.roots.AddCert(cert) -+ ca.rootKey = key -+ ca.rootCert = der -+ ca.rootTemplate = tmpl -+} -+ -+// IssuerName sets the name of the issuing CA. -+func (ca *CAServer) IssuerName(name pkix.Name) *CAServer { -+ if ca.url != "" { -+ panic("IssuerName must be called before Start") -+ } -+ ca.issuer = name -+ return ca -+} -+ -+// ChallengeTypes sets the supported challenge types. -+func (ca *CAServer) ChallengeTypes(types ...string) *CAServer { -+ if ca.url != "" { -+ panic("ChallengeTypes must be called before Start") -+ } -+ ca.challengeTypes = types -+ return ca -+} -+ -+// URL returns the server address, after Start has been called. -+func (ca *CAServer) URL() string { -+ if ca.url == "" { -+ panic("URL called before Start") -+ } -+ return ca.url -+} -+ -+// Roots returns a pool cointaining the CA root. -+func (ca *CAServer) Roots() *x509.CertPool { -+ if ca.url == "" { -+ panic("Roots called before Start") -+ } -+ return ca.roots -+} -+ -+// ExternalAccountRequired makes an EAB JWS required for account registration. -+func (ca *CAServer) ExternalAccountRequired() *CAServer { -+ if ca.url != "" { -+ panic("ExternalAccountRequired must be called before Start") -+ } -+ ca.eabRequired = true -+ return ca -+} -+ -+// Start starts serving requests. The server address becomes available in the -+// URL field. -+func (ca *CAServer) Start() *CAServer { -+ if ca.url == "" { -+ ca.generateRoot() -+ ca.server.Start() -+ ca.t.Cleanup(ca.server.Close) -+ ca.url = ca.server.URL -+ } -+ return ca -+} -+ -+func (ca *CAServer) serverURL(format string, arg ...interface{}) string { -+ return ca.server.URL + fmt.Sprintf(format, arg...) -+} -+ -+func (ca *CAServer) addr(domain string) (string, bool) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ addr, ok := ca.domainAddr[domain] -+ return addr, ok -+} -+ -+func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ f, ok := ca.domainGetCert[domain] -+ return f, ok -+} -+ -+func (ca *CAServer) getHandler(domain string) (http.Handler, bool) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ h, ok := ca.domainHandler[domain] -+ return h, ok -+} -+ -+func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) { -+ s := fmt.Sprintf(format, a...) -+ ca.t.Errorf(format, a...) -+ http.Error(w, s, code) -+} -+ -+// Resolve adds a domain to address resolution for the ca to dial to -+// when validating challenges for the domain authorization. -+func (ca *CAServer) Resolve(domain, addr string) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ ca.domainAddr[domain] = addr -+} -+ -+// ResolveGetCertificate redirects TLS connections for domain to f when -+// validating challenges for the domain authorization. -+func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ ca.domainGetCert[domain] = f -+} -+ -+// ResolveHandler redirects HTTP requests for domain to f when -+// validating challenges for the domain authorization. -+func (ca *CAServer) ResolveHandler(domain string, h http.Handler) { -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ ca.domainHandler[domain] = h -+} -+ -+type discovery struct { -+ NewNonce string `json:"newNonce"` -+ NewAccount string `json:"newAccount"` -+ NewOrder string `json:"newOrder"` -+ NewAuthz string `json:"newAuthz"` -+ -+ Meta discoveryMeta `json:"meta,omitempty"` -+} -+ -+type discoveryMeta struct { -+ ExternalAccountRequired bool `json:"externalAccountRequired,omitempty"` -+} -+ -+type challenge struct { -+ URI string `json:"uri"` -+ Type string `json:"type"` -+ Token string `json:"token"` -+} -+ -+type authorization struct { -+ Status string `json:"status"` -+ Challenges []challenge `json:"challenges"` -+ -+ domain string -+ id int -+} -+ -+type order struct { -+ Status string `json:"status"` -+ AuthzURLs []string `json:"authorizations"` -+ FinalizeURL string `json:"finalize"` // CSR submit URL -+ CertURL string `json:"certificate"` // already issued cert -+ -+ leaf []byte // issued cert in DER format -+} -+ -+func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) { -+ ca.t.Logf("%s %s", r.Method, r.URL) -+ w.Header().Set("Replay-Nonce", "nonce") -+ // TODO: Verify nonce header for all POST requests. -+ -+ switch { -+ default: -+ ca.httpErrorf(w, http.StatusBadRequest, "unrecognized r.URL.Path: %s", r.URL.Path) -+ -+ // Discovery request. -+ case r.URL.Path == "/": -+ resp := &discovery{ -+ NewNonce: ca.serverURL("/new-nonce"), -+ NewAccount: ca.serverURL("/new-account"), -+ NewOrder: ca.serverURL("/new-order"), -+ Meta: discoveryMeta{ -+ ExternalAccountRequired: ca.eabRequired, -+ }, -+ } -+ if err := json.NewEncoder(w).Encode(resp); err != nil { -+ panic(fmt.Sprintf("discovery response: %v", err)) -+ } -+ -+ // Nonce requests. -+ case r.URL.Path == "/new-nonce": -+ // Nonce values are always set. Nothing else to do. -+ return -+ -+ // Client key registration request. -+ case r.URL.Path == "/new-account": -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ if ca.acctRegistered { -+ ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented") -+ return -+ } -+ ca.acctRegistered = true -+ -+ var req struct { -+ ExternalAccountBinding json.RawMessage -+ } -+ -+ if err := decodePayload(&req, r.Body); err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ -+ if ca.eabRequired && len(req.ExternalAccountBinding) == 0 { -+ ca.httpErrorf(w, http.StatusBadRequest, "registration failed: no JWS for EAB") -+ return -+ } -+ -+ // TODO: Check the user account key against a ca.accountKeys? -+ w.Header().Set("Location", ca.serverURL("/accounts/1")) -+ w.WriteHeader(http.StatusCreated) -+ w.Write([]byte("{}")) -+ -+ // New order request. -+ case r.URL.Path == "/new-order": -+ var req struct { -+ Identifiers []struct{ Value string } -+ } -+ if err := decodePayload(&req, r.Body); err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ o := &order{Status: acme.StatusPending} -+ for _, id := range req.Identifiers { -+ z := ca.authz(id.Value) -+ o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id)) -+ } -+ orderID := len(ca.orders) -+ ca.orders = append(ca.orders, o) -+ w.Header().Set("Location", ca.serverURL("/orders/%d", orderID)) -+ w.WriteHeader(http.StatusCreated) -+ if err := json.NewEncoder(w).Encode(o); err != nil { -+ panic(err) -+ } -+ -+ // Existing order status requests. -+ case strings.HasPrefix(r.URL.Path, "/orders/"): -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/")) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ if err := json.NewEncoder(w).Encode(o); err != nil { -+ panic(err) -+ } -+ -+ // Accept challenge requests. -+ case strings.HasPrefix(r.URL.Path, "/challenge/"): -+ parts := strings.Split(r.URL.Path, "/") -+ typ, id := parts[len(parts)-2], parts[len(parts)-1] -+ ca.mu.Lock() -+ supported := false -+ for _, suppTyp := range ca.challengeTypes { -+ if suppTyp == typ { -+ supported = true -+ } -+ } -+ a, err := ca.storedAuthz(id) -+ ca.mu.Unlock() -+ if !supported { -+ ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ) -+ return -+ } -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err) -+ return -+ } -+ ca.validateChallenge(a, typ) -+ w.Write([]byte("{}")) -+ -+ // Get authorization status requests. -+ case strings.HasPrefix(r.URL.Path, "/authz/"): -+ var req struct{ Status string } -+ decodePayload(&req, r.Body) -+ deactivate := req.Status == "deactivated" -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/")) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusNotFound, "%v", err) -+ return -+ } -+ if deactivate { -+ // Note we don't invalidate authorized orders as we should. -+ authz.Status = "deactivated" -+ ca.t.Logf("authz %d is now %s", authz.id, authz.Status) -+ ca.updatePendingOrders() -+ } -+ if err := json.NewEncoder(w).Encode(authz); err != nil { -+ panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err)) -+ } -+ -+ // Certificate issuance request. -+ case strings.HasPrefix(r.URL.Path, "/new-cert/"): -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/") -+ o, err := ca.storedOrder(orderID) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ if o.Status != acme.StatusReady { -+ ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) -+ return -+ } -+ // Validate CSR request. -+ var req struct { -+ CSR string `json:"csr"` -+ } -+ decodePayload(&req, r.Body) -+ b, _ := base64.RawURLEncoding.DecodeString(req.CSR) -+ csr, err := x509.ParseCertificateRequest(b) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ // Issue the certificate. -+ der, err := ca.leafCert(csr) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, "new-cert response: ca.leafCert: %v", err) -+ return -+ } -+ o.leaf = der -+ o.CertURL = ca.serverURL("/issued-cert/%s", orderID) -+ o.Status = acme.StatusValid -+ if err := json.NewEncoder(w).Encode(o); err != nil { -+ panic(err) -+ } -+ -+ // Already issued cert download requests. -+ case strings.HasPrefix(r.URL.Path, "/issued-cert/"): -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/")) -+ if err != nil { -+ ca.httpErrorf(w, http.StatusBadRequest, err.Error()) -+ return -+ } -+ if o.Status != acme.StatusValid { -+ ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status) -+ return -+ } -+ w.Header().Set("Content-Type", "application/pem-certificate-chain") -+ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: o.leaf}) -+ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: ca.rootCert}) -+ } -+} -+ -+// storedOrder retrieves a previously created order at index i. -+// It requires ca.mu to be locked. -+func (ca *CAServer) storedOrder(i string) (*order, error) { -+ idx, err := strconv.Atoi(i) -+ if err != nil { -+ return nil, fmt.Errorf("storedOrder: %v", err) -+ } -+ if idx < 0 { -+ return nil, fmt.Errorf("storedOrder: invalid order index %d", idx) -+ } -+ if idx > len(ca.orders)-1 { -+ return nil, fmt.Errorf("storedOrder: no such order %d", idx) -+ } -+ -+ ca.updatePendingOrders() -+ return ca.orders[idx], nil -+} -+ -+// storedAuthz retrieves a previously created authz at index i. -+// It requires ca.mu to be locked. -+func (ca *CAServer) storedAuthz(i string) (*authorization, error) { -+ idx, err := strconv.Atoi(i) -+ if err != nil { -+ return nil, fmt.Errorf("storedAuthz: %v", err) -+ } -+ if idx < 0 { -+ return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx) -+ } -+ if idx > len(ca.authorizations)-1 { -+ return nil, fmt.Errorf("storedAuthz: no such authz %d", idx) -+ } -+ return ca.authorizations[idx], nil -+} -+ -+// authz returns an existing valid authorization for the identifier or creates a -+// new one. It requires ca.mu to be locked. -+func (ca *CAServer) authz(identifier string) *authorization { -+ authz, ok := ca.validAuthz[identifier] -+ if !ok { -+ authzId := len(ca.authorizations) -+ authz = &authorization{ -+ id: authzId, -+ domain: identifier, -+ Status: acme.StatusPending, -+ } -+ for _, typ := range ca.challengeTypes { -+ authz.Challenges = append(authz.Challenges, challenge{ -+ Type: typ, -+ URI: ca.serverURL("/challenge/%s/%d", typ, authzId), -+ Token: challengeToken(authz.domain, typ, authzId), -+ }) -+ } -+ ca.authorizations = append(ca.authorizations, authz) -+ } -+ return authz -+} -+ -+// leafCert issues a new certificate. -+// It requires ca.mu to be locked. -+func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) { -+ ca.certCount++ // next leaf cert serial number -+ leaf := &x509.Certificate{ -+ SerialNumber: big.NewInt(int64(ca.certCount)), -+ Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, -+ NotBefore: time.Now(), -+ NotAfter: time.Now().Add(90 * 24 * time.Hour), -+ KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, -+ DNSNames: csr.DNSNames, -+ BasicConstraintsValid: true, -+ } -+ if len(csr.DNSNames) == 0 { -+ leaf.DNSNames = []string{csr.Subject.CommonName} -+ } -+ return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey) -+} -+ -+// LeafCert issues a leaf certificate. -+func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate { -+ if ca.url == "" { -+ panic("LeafCert called before Start") -+ } -+ -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ var pk crypto.Signer -+ switch keyType { -+ case "RSA": -+ var err error -+ pk, err = rsa.GenerateKey(rand.Reader, 1024) -+ if err != nil { -+ ca.t.Fatal(err) -+ } -+ case "ECDSA": -+ var err error -+ pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ ca.t.Fatal(err) -+ } -+ default: -+ panic("LeafCert: unknown key type") -+ } -+ ca.certCount++ // next leaf cert serial number -+ leaf := &x509.Certificate{ -+ SerialNumber: big.NewInt(int64(ca.certCount)), -+ Subject: pkix.Name{Organization: []string{"Test Acme Co"}}, -+ NotBefore: notBefore, -+ NotAfter: notAfter, -+ KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, -+ DNSNames: []string{name}, -+ BasicConstraintsValid: true, -+ } -+ der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey) -+ if err != nil { -+ ca.t.Fatal(err) -+ } -+ return &tls.Certificate{ -+ Certificate: [][]byte{der}, -+ PrivateKey: pk, -+ } -+} -+ -+func (ca *CAServer) validateChallenge(authz *authorization, typ string) { -+ var err error -+ switch typ { -+ case "tls-alpn-01": -+ err = ca.verifyALPNChallenge(authz) -+ case "http-01": -+ err = ca.verifyHTTPChallenge(authz) -+ default: -+ panic(fmt.Sprintf("validation of %q is not implemented", typ)) -+ } -+ ca.mu.Lock() -+ defer ca.mu.Unlock() -+ if err != nil { -+ authz.Status = "invalid" -+ } else { -+ authz.Status = "valid" -+ ca.validAuthz[authz.domain] = authz -+ } -+ ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err) -+ ca.t.Logf("authz %d is now %s", authz.id, authz.Status) -+ -+ ca.updatePendingOrders() -+} -+ -+func (ca *CAServer) updatePendingOrders() { -+ // Update all pending orders. -+ // An order becomes "ready" if all authorizations are "valid". -+ // An order becomes "invalid" if any authorization is "invalid". -+ // Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6 -+ for i, o := range ca.orders { -+ if o.Status != acme.StatusPending { -+ continue -+ } -+ -+ countValid, countInvalid := ca.validateAuthzURLs(o.AuthzURLs, i) -+ if countInvalid > 0 { -+ o.Status = acme.StatusInvalid -+ ca.t.Logf("order %d is now invalid", i) -+ continue -+ } -+ if countValid == len(o.AuthzURLs) { -+ o.Status = acme.StatusReady -+ o.FinalizeURL = ca.serverURL("/new-cert/%d", i) -+ ca.t.Logf("order %d is now ready", i) -+ } -+ } -+} -+ -+func (ca *CAServer) validateAuthzURLs(urls []string, orderNum int) (countValid, countInvalid int) { -+ for _, zurl := range urls { -+ z, err := ca.storedAuthz(path.Base(zurl)) -+ if err != nil { -+ ca.t.Logf("no authz %q for order %d", zurl, orderNum) -+ continue -+ } -+ if z.Status == acme.StatusInvalid { -+ countInvalid++ -+ } -+ if z.Status == acme.StatusValid { -+ countValid++ -+ } -+ } -+ return countValid, countInvalid -+} -+ -+func (ca *CAServer) verifyALPNChallenge(a *authorization) error { -+ const acmeALPNProto = "acme-tls/1" -+ -+ addr, haveAddr := ca.addr(a.domain) -+ getCert, haveGetCert := ca.getCert(a.domain) -+ if !haveAddr && !haveGetCert { -+ return fmt.Errorf("no resolution information for %q", a.domain) -+ } -+ if haveAddr && haveGetCert { -+ return fmt.Errorf("overlapping resolution information for %q", a.domain) -+ } -+ -+ var crt *x509.Certificate -+ switch { -+ case haveAddr: -+ conn, err := tls.Dial("tcp", addr, &tls.Config{ -+ ServerName: a.domain, -+ InsecureSkipVerify: true, -+ NextProtos: []string{acmeALPNProto}, -+ MinVersion: tls.VersionTLS12, -+ }) -+ if err != nil { -+ return err -+ } -+ if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto { -+ return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto) -+ } -+ if n := len(conn.ConnectionState().PeerCertificates); n != 1 { -+ return fmt.Errorf("len(PeerCertificates) = %d; want 1", n) -+ } -+ crt = conn.ConnectionState().PeerCertificates[0] -+ case haveGetCert: -+ hello := &tls.ClientHelloInfo{ -+ ServerName: a.domain, -+ // TODO: support selecting ECDSA. -+ CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}, -+ SupportedProtos: []string{acme.ALPNProto}, -+ SupportedVersions: []uint16{tls.VersionTLS12}, -+ } -+ c, err := getCert(hello) -+ if err != nil { -+ return err -+ } -+ crt, err = x509.ParseCertificate(c.Certificate[0]) -+ if err != nil { -+ return err -+ } -+ } -+ -+ if err := crt.VerifyHostname(a.domain); err != nil { -+ return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err) -+ } -+ // See RFC 8737, Section 6.1. -+ oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31} -+ for _, x := range crt.Extensions { -+ if x.Id.Equal(oid) { -+ // TODO: check the token. -+ return nil -+ } -+ } -+ return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found") -+} -+ -+func (ca *CAServer) verifyHTTPChallenge(a *authorization) error { -+ addr, haveAddr := ca.addr(a.domain) -+ handler, haveHandler := ca.getHandler(a.domain) -+ if !haveAddr && !haveHandler { -+ return fmt.Errorf("no resolution information for %q", a.domain) -+ } -+ if haveAddr && haveHandler { -+ return fmt.Errorf("overlapping resolution information for %q", a.domain) -+ } -+ -+ token := challengeToken(a.domain, "http-01", a.id) -+ path := "/.well-known/acme-challenge/" + token -+ -+ var body string -+ switch { -+ case haveAddr: -+ t := &http.Transport{ -+ DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { -+ return (&net.Dialer{}).DialContext(ctx, network, addr) -+ }, -+ } -+ req, err := http.NewRequest("GET", "http://"+a.domain+path, nil) -+ if err != nil { -+ return err -+ } -+ res, err := t.RoundTrip(req) -+ if err != nil { -+ return err -+ } -+ if res.StatusCode != http.StatusOK { -+ return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK) -+ } -+ b, err := io.ReadAll(res.Body) -+ if err != nil { -+ return err -+ } -+ body = string(b) -+ case haveHandler: -+ r := httptest.NewRequest("GET", path, nil) -+ r.Host = a.domain -+ w := httptest.NewRecorder() -+ handler.ServeHTTP(w, r) -+ if w.Code != http.StatusOK { -+ return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) -+ } -+ body = w.Body.String() -+ } -+ -+ if !strings.HasPrefix(body, token) { -+ return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body) -+ } -+ return nil -+} -+ -+func decodePayload(v interface{}, r io.Reader) error { -+ var req struct{ Payload string } -+ if err := json.NewDecoder(r).Decode(&req); err != nil { -+ return err -+ } -+ payload, err := base64.RawURLEncoding.DecodeString(req.Payload) -+ if err != nil { -+ return err -+ } -+ return json.Unmarshal(payload, v) -+} -+ -+func challengeToken(domain, challType string, authzID int) string { -+ return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID) -+} -+ -+func unique(a []string) []string { -+ seen := make(map[string]bool) -+ var res []string -+ for _, s := range a { -+ if s != "" && !seen[s] { -+ seen[s] = true -+ res = append(res, s) -+ } -+ } -+ return res -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/listener.go b/ms_mod/golang.org/x/crypto/acme/autocert/listener.go -new file mode 100644 -index 00000000000000..9d62f8cedcd4c7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/listener.go -@@ -0,0 +1,155 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "crypto/tls" -+ "log" -+ "net" -+ "os" -+ "path/filepath" -+ "runtime" -+ "time" -+) -+ -+// NewListener returns a net.Listener that listens on the standard TLS -+// port (443) on all interfaces and returns *tls.Conn connections with -+// LetsEncrypt certificates for the provided domain or domains. -+// -+// It enables one-line HTTPS servers: -+// -+// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) -+// -+// NewListener is a convenience function for a common configuration. -+// More complex or custom configurations can use the autocert.Manager -+// type instead. -+// -+// Use of this function implies acceptance of the LetsEncrypt Terms of -+// Service. If domains is not empty, the provided domains are passed -+// to HostWhitelist. If domains is empty, the listener will do -+// LetsEncrypt challenges for any requested domain, which is not -+// recommended. -+// -+// Certificates are cached in a "golang-autocert" directory under an -+// operating system-specific cache or temp directory. This may not -+// be suitable for servers spanning multiple machines. -+// -+// The returned listener uses a *tls.Config that enables HTTP/2, and -+// should only be used with servers that support HTTP/2. -+// -+// The returned Listener also enables TCP keep-alives on the accepted -+// connections. The returned *tls.Conn are returned before their TLS -+// handshake has completed. -+func NewListener(domains ...string) net.Listener { -+ m := &Manager{ -+ Prompt: AcceptTOS, -+ } -+ if len(domains) > 0 { -+ m.HostPolicy = HostWhitelist(domains...) -+ } -+ dir := cacheDir() -+ if err := os.MkdirAll(dir, 0700); err != nil { -+ log.Printf("warning: autocert.NewListener not using a cache: %v", err) -+ } else { -+ m.Cache = DirCache(dir) -+ } -+ return m.Listener() -+} -+ -+// Listener listens on the standard TLS port (443) on all interfaces -+// and returns a net.Listener returning *tls.Conn connections. -+// -+// The returned listener uses a *tls.Config that enables HTTP/2, and -+// should only be used with servers that support HTTP/2. -+// -+// The returned Listener also enables TCP keep-alives on the accepted -+// connections. The returned *tls.Conn are returned before their TLS -+// handshake has completed. -+// -+// Unlike NewListener, it is the caller's responsibility to initialize -+// the Manager m's Prompt, Cache, HostPolicy, and other desired options. -+func (m *Manager) Listener() net.Listener { -+ ln := &listener{ -+ conf: m.TLSConfig(), -+ } -+ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") -+ return ln -+} -+ -+type listener struct { -+ conf *tls.Config -+ -+ tcpListener net.Listener -+ tcpListenErr error -+} -+ -+func (ln *listener) Accept() (net.Conn, error) { -+ if ln.tcpListenErr != nil { -+ return nil, ln.tcpListenErr -+ } -+ conn, err := ln.tcpListener.Accept() -+ if err != nil { -+ return nil, err -+ } -+ tcpConn := conn.(*net.TCPConn) -+ -+ // Because Listener is a convenience function, help out with -+ // this too. This is not possible for the caller to set once -+ // we return a *tcp.Conn wrapping an inaccessible net.Conn. -+ // If callers don't want this, they can do things the manual -+ // way and tweak as needed. But this is what net/http does -+ // itself, so copy that. If net/http changes, we can change -+ // here too. -+ tcpConn.SetKeepAlive(true) -+ tcpConn.SetKeepAlivePeriod(3 * time.Minute) -+ -+ return tls.Server(tcpConn, ln.conf), nil -+} -+ -+func (ln *listener) Addr() net.Addr { -+ if ln.tcpListener != nil { -+ return ln.tcpListener.Addr() -+ } -+ // net.Listen failed. Return something non-nil in case callers -+ // call Addr before Accept: -+ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443} -+} -+ -+func (ln *listener) Close() error { -+ if ln.tcpListenErr != nil { -+ return ln.tcpListenErr -+ } -+ return ln.tcpListener.Close() -+} -+ -+func homeDir() string { -+ if runtime.GOOS == "windows" { -+ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") -+ } -+ if h := os.Getenv("HOME"); h != "" { -+ return h -+ } -+ return "/" -+} -+ -+func cacheDir() string { -+ const base = "golang-autocert" -+ switch runtime.GOOS { -+ case "darwin": -+ return filepath.Join(homeDir(), "Library", "Caches", base) -+ case "windows": -+ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} { -+ if v := os.Getenv(ev); v != "" { -+ return filepath.Join(v, base) -+ } -+ } -+ // Worst case: -+ return filepath.Join(homeDir(), base) -+ } -+ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" { -+ return filepath.Join(xdg, base) -+ } -+ return filepath.Join(homeDir(), ".cache", base) -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/renewal.go b/ms_mod/golang.org/x/crypto/acme/autocert/renewal.go -new file mode 100644 -index 00000000000000..0df7da78a6f6cc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/renewal.go -@@ -0,0 +1,156 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "context" -+ "crypto" -+ "sync" -+ "time" -+) -+ -+// renewJitter is the maximum deviation from Manager.RenewBefore. -+const renewJitter = time.Hour -+ -+// domainRenewal tracks the state used by the periodic timers -+// renewing a single domain's cert. -+type domainRenewal struct { -+ m *Manager -+ ck certKey -+ key crypto.Signer -+ -+ timerMu sync.Mutex -+ timer *time.Timer -+ timerClose chan struct{} // if non-nil, renew closes this channel (and nils out the timer fields) instead of running -+} -+ -+// start starts a cert renewal timer at the time -+// defined by the certificate expiration time exp. -+// -+// If the timer is already started, calling start is a noop. -+func (dr *domainRenewal) start(exp time.Time) { -+ dr.timerMu.Lock() -+ defer dr.timerMu.Unlock() -+ if dr.timer != nil { -+ return -+ } -+ dr.timer = time.AfterFunc(dr.next(exp), dr.renew) -+} -+ -+// stop stops the cert renewal timer and waits for any in-flight calls to renew -+// to complete. If the timer is already stopped, calling stop is a noop. -+func (dr *domainRenewal) stop() { -+ dr.timerMu.Lock() -+ defer dr.timerMu.Unlock() -+ for { -+ if dr.timer == nil { -+ return -+ } -+ if dr.timer.Stop() { -+ dr.timer = nil -+ return -+ } else { -+ // dr.timer fired, and we acquired dr.timerMu before the renew callback did. -+ // (We know this because otherwise the renew callback would have reset dr.timer!) -+ timerClose := make(chan struct{}) -+ dr.timerClose = timerClose -+ dr.timerMu.Unlock() -+ <-timerClose -+ dr.timerMu.Lock() -+ } -+ } -+} -+ -+// renew is called periodically by a timer. -+// The first renew call is kicked off by dr.start. -+func (dr *domainRenewal) renew() { -+ dr.timerMu.Lock() -+ defer dr.timerMu.Unlock() -+ if dr.timerClose != nil { -+ close(dr.timerClose) -+ dr.timer, dr.timerClose = nil, nil -+ return -+ } -+ -+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) -+ defer cancel() -+ // TODO: rotate dr.key at some point? -+ next, err := dr.do(ctx) -+ if err != nil { -+ next = renewJitter / 2 -+ next += time.Duration(pseudoRand.int63n(int64(next))) -+ } -+ testDidRenewLoop(next, err) -+ dr.timer = time.AfterFunc(next, dr.renew) -+} -+ -+// updateState locks and replaces the relevant Manager.state item with the given -+// state. It additionally updates dr.key with the given state's key. -+func (dr *domainRenewal) updateState(state *certState) { -+ dr.m.stateMu.Lock() -+ defer dr.m.stateMu.Unlock() -+ dr.key = state.key -+ dr.m.state[dr.ck] = state -+} -+ -+// do is similar to Manager.createCert but it doesn't lock a Manager.state item. -+// Instead, it requests a new certificate independently and, upon success, -+// replaces dr.m.state item with a new one and updates cache for the given domain. -+// -+// It may lock and update the Manager.state if the expiration date of the currently -+// cached cert is far enough in the future. -+// -+// The returned value is a time interval after which the renewal should occur again. -+func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { -+ // a race is likely unavoidable in a distributed environment -+ // but we try nonetheless -+ if tlscert, err := dr.m.cacheGet(ctx, dr.ck); err == nil { -+ next := dr.next(tlscert.Leaf.NotAfter) -+ if next > dr.m.renewBefore()+renewJitter { -+ signer, ok := tlscert.PrivateKey.(crypto.Signer) -+ if ok { -+ state := &certState{ -+ key: signer, -+ cert: tlscert.Certificate, -+ leaf: tlscert.Leaf, -+ } -+ dr.updateState(state) -+ return next, nil -+ } -+ } -+ } -+ -+ der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.ck) -+ if err != nil { -+ return 0, err -+ } -+ state := &certState{ -+ key: dr.key, -+ cert: der, -+ leaf: leaf, -+ } -+ tlscert, err := state.tlscert() -+ if err != nil { -+ return 0, err -+ } -+ if err := dr.m.cachePut(ctx, dr.ck, tlscert); err != nil { -+ return 0, err -+ } -+ dr.updateState(state) -+ return dr.next(leaf.NotAfter), nil -+} -+ -+func (dr *domainRenewal) next(expiry time.Time) time.Duration { -+ d := expiry.Sub(dr.m.now()) - dr.m.renewBefore() -+ // add a bit of randomness to renew deadline -+ n := pseudoRand.int63n(int64(renewJitter)) -+ d -= time.Duration(n) -+ if d < 0 { -+ return 0 -+ } -+ return d -+} -+ -+var testDidRenewLoop = func(next time.Duration, err error) {} -diff --git a/ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go b/ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go -new file mode 100644 -index 00000000000000..ffe4af2a5ce2f5 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/autocert/renewal_test.go -@@ -0,0 +1,269 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package autocert -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+ "golang.org/x/crypto/acme/autocert/internal/acmetest" -+) -+ -+func TestRenewalNext(t *testing.T) { -+ now := time.Now() -+ man := &Manager{ -+ RenewBefore: 7 * 24 * time.Hour, -+ nowFunc: func() time.Time { return now }, -+ } -+ defer man.stopRenew() -+ tt := []struct { -+ expiry time.Time -+ min, max time.Duration -+ }{ -+ {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour}, -+ {now.Add(time.Hour), 0, 1}, -+ {now, 0, 1}, -+ {now.Add(-time.Hour), 0, 1}, -+ } -+ -+ dr := &domainRenewal{m: man} -+ for i, test := range tt { -+ next := dr.next(test.expiry) -+ if next < test.min || test.max < next { -+ t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max) -+ } -+ } -+} -+ -+func TestRenewFromCache(t *testing.T) { -+ man := testManager(t) -+ man.RenewBefore = 24 * time.Hour -+ -+ ca := acmetest.NewCAServer(t).Start() -+ ca.ResolveGetCertificate(exampleDomain, man.GetCertificate) -+ -+ man.Client = &acme.Client{ -+ DirectoryURL: ca.URL(), -+ } -+ -+ // cache an almost expired cert -+ now := time.Now() -+ c := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Minute)) -+ if err := man.cachePut(context.Background(), exampleCertKey, c); err != nil { -+ t.Fatal(err) -+ } -+ -+ // verify the renewal happened -+ defer func() { -+ // Stop the timers that read and execute testDidRenewLoop before restoring it. -+ // Otherwise the timer callback may race with the deferred write. -+ man.stopRenew() -+ testDidRenewLoop = func(next time.Duration, err error) {} -+ }() -+ renewed := make(chan bool, 1) -+ testDidRenewLoop = func(next time.Duration, err error) { -+ defer func() { -+ select { -+ case renewed <- true: -+ default: -+ // The renewal timer uses a random backoff. If the first renewal fails for -+ // some reason, we could end up with multiple calls here before the test -+ // stops the timer. -+ } -+ }() -+ -+ if err != nil { -+ t.Errorf("testDidRenewLoop: %v", err) -+ } -+ // Next should be about 90 days: -+ // CaServer creates 90days expiry + account for man.RenewBefore. -+ // Previous expiration was within 1 min. -+ future := 88 * 24 * time.Hour -+ if next < future { -+ t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future) -+ } -+ -+ // ensure the new cert is cached -+ after := time.Now().Add(future) -+ tlscert, err := man.cacheGet(context.Background(), exampleCertKey) -+ if err != nil { -+ t.Errorf("man.cacheGet: %v", err) -+ return -+ } -+ if !tlscert.Leaf.NotAfter.After(after) { -+ t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) -+ } -+ -+ // verify the old cert is also replaced in memory -+ man.stateMu.Lock() -+ defer man.stateMu.Unlock() -+ s := man.state[exampleCertKey] -+ if s == nil { -+ t.Errorf("m.state[%q] is nil", exampleCertKey) -+ return -+ } -+ tlscert, err = s.tlscert() -+ if err != nil { -+ t.Errorf("s.tlscert: %v", err) -+ return -+ } -+ if !tlscert.Leaf.NotAfter.After(after) { -+ t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) -+ } -+ } -+ -+ // trigger renew -+ hello := clientHelloInfo(exampleDomain, algECDSA) -+ if _, err := man.GetCertificate(hello); err != nil { -+ t.Fatal(err) -+ } -+ <-renewed -+} -+ -+func TestRenewFromCacheAlreadyRenewed(t *testing.T) { -+ ca := acmetest.NewCAServer(t).Start() -+ man := testManager(t) -+ man.RenewBefore = 24 * time.Hour -+ man.Client = &acme.Client{ -+ DirectoryURL: "invalid", -+ } -+ -+ // cache a recently renewed cert with a different private key -+ now := time.Now() -+ newCert := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Hour*24*90)) -+ if err := man.cachePut(context.Background(), exampleCertKey, newCert); err != nil { -+ t.Fatal(err) -+ } -+ newLeaf, err := validCert(exampleCertKey, newCert.Certificate, newCert.PrivateKey.(crypto.Signer), now) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // set internal state to an almost expired cert -+ oldCert := ca.LeafCert(exampleDomain, "ECDSA", now.Add(-2*time.Hour), now.Add(time.Minute)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ oldLeaf, err := validCert(exampleCertKey, oldCert.Certificate, oldCert.PrivateKey.(crypto.Signer), now) -+ if err != nil { -+ t.Fatal(err) -+ } -+ man.stateMu.Lock() -+ if man.state == nil { -+ man.state = make(map[certKey]*certState) -+ } -+ s := &certState{ -+ key: oldCert.PrivateKey.(crypto.Signer), -+ cert: oldCert.Certificate, -+ leaf: oldLeaf, -+ } -+ man.state[exampleCertKey] = s -+ man.stateMu.Unlock() -+ -+ // verify the renewal accepted the newer cached cert -+ defer func() { -+ // Stop the timers that read and execute testDidRenewLoop before restoring it. -+ // Otherwise the timer callback may race with the deferred write. -+ man.stopRenew() -+ testDidRenewLoop = func(next time.Duration, err error) {} -+ }() -+ renewed := make(chan bool, 1) -+ testDidRenewLoop = func(next time.Duration, err error) { -+ defer func() { -+ select { -+ case renewed <- true: -+ default: -+ // The renewal timer uses a random backoff. If the first renewal fails for -+ // some reason, we could end up with multiple calls here before the test -+ // stops the timer. -+ } -+ }() -+ -+ if err != nil { -+ t.Errorf("testDidRenewLoop: %v", err) -+ } -+ // Next should be about 90 days -+ // Previous expiration was within 1 min. -+ future := 88 * 24 * time.Hour -+ if next < future { -+ t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future) -+ } -+ -+ // ensure the cached cert was not modified -+ tlscert, err := man.cacheGet(context.Background(), exampleCertKey) -+ if err != nil { -+ t.Errorf("man.cacheGet: %v", err) -+ return -+ } -+ if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { -+ t.Errorf("cache leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) -+ } -+ -+ // verify the old cert is also replaced in memory -+ man.stateMu.Lock() -+ defer man.stateMu.Unlock() -+ s := man.state[exampleCertKey] -+ if s == nil { -+ t.Errorf("m.state[%q] is nil", exampleCertKey) -+ return -+ } -+ stateKey := s.key.Public().(*ecdsa.PublicKey) -+ if !stateKey.Equal(newLeaf.PublicKey) { -+ t.Error("state key was not updated from cache") -+ return -+ } -+ tlscert, err = s.tlscert() -+ if err != nil { -+ t.Errorf("s.tlscert: %v", err) -+ return -+ } -+ if !tlscert.Leaf.NotAfter.Equal(newLeaf.NotAfter) { -+ t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) -+ } -+ } -+ -+ // assert the expiring cert is returned from state -+ hello := clientHelloInfo(exampleDomain, algECDSA) -+ tlscert, err := man.GetCertificate(hello) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if !oldLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { -+ t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, oldLeaf.NotAfter) -+ } -+ -+ // trigger renew -+ man.startRenew(exampleCertKey, s.key, s.leaf.NotAfter) -+ <-renewed -+ func() { -+ man.renewalMu.Lock() -+ defer man.renewalMu.Unlock() -+ -+ // verify the private key is replaced in the renewal state -+ r := man.renewal[exampleCertKey] -+ if r == nil { -+ t.Errorf("m.renewal[%q] is nil", exampleCertKey) -+ return -+ } -+ renewalKey := r.key.Public().(*ecdsa.PublicKey) -+ if !renewalKey.Equal(newLeaf.PublicKey) { -+ t.Error("renewal private key was not updated from cache") -+ } -+ }() -+ -+ // assert the new cert is returned from state after renew -+ hello = clientHelloInfo(exampleDomain, algECDSA) -+ tlscert, err = man.GetCertificate(hello) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if !newLeaf.NotAfter.Equal(tlscert.Leaf.NotAfter) { -+ t.Errorf("state leaf.NotAfter = %v; want == %v", tlscert.Leaf.NotAfter, newLeaf.NotAfter) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/http.go b/ms_mod/golang.org/x/crypto/acme/http.go -new file mode 100644 -index 00000000000000..58836e5d303e01 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/http.go -@@ -0,0 +1,325 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/rand" -+ "encoding/json" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ "net/http" -+ "strconv" -+ "strings" -+ "time" -+) -+ -+// retryTimer encapsulates common logic for retrying unsuccessful requests. -+// It is not safe for concurrent use. -+type retryTimer struct { -+ // backoffFn provides backoff delay sequence for retries. -+ // See Client.RetryBackoff doc comment. -+ backoffFn func(n int, r *http.Request, res *http.Response) time.Duration -+ // n is the current retry attempt. -+ n int -+} -+ -+func (t *retryTimer) inc() { -+ t.n++ -+} -+ -+// backoff pauses the current goroutine as described in Client.RetryBackoff. -+func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error { -+ d := t.backoffFn(t.n, r, res) -+ if d <= 0 { -+ return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n) -+ } -+ wakeup := time.NewTimer(d) -+ defer wakeup.Stop() -+ select { -+ case <-ctx.Done(): -+ return ctx.Err() -+ case <-wakeup.C: -+ return nil -+ } -+} -+ -+func (c *Client) retryTimer() *retryTimer { -+ f := c.RetryBackoff -+ if f == nil { -+ f = defaultBackoff -+ } -+ return &retryTimer{backoffFn: f} -+} -+ -+// defaultBackoff provides default Client.RetryBackoff implementation -+// using a truncated exponential backoff algorithm, -+// as described in Client.RetryBackoff. -+// -+// The n argument is always bounded between 1 and 30. -+// The returned value is always greater than 0. -+func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration { -+ const max = 10 * time.Second -+ var jitter time.Duration -+ if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { -+ // Set the minimum to 1ms to avoid a case where -+ // an invalid Retry-After value is parsed into 0 below, -+ // resulting in the 0 returned value which would unintentionally -+ // stop the retries. -+ jitter = (1 + time.Duration(x.Int64())) * time.Millisecond -+ } -+ if v, ok := res.Header["Retry-After"]; ok { -+ return retryAfter(v[0]) + jitter -+ } -+ -+ if n < 1 { -+ n = 1 -+ } -+ if n > 30 { -+ n = 30 -+ } -+ d := time.Duration(1< max { -+ return max -+ } -+ return d -+} -+ -+// retryAfter parses a Retry-After HTTP header value, -+// trying to convert v into an int (seconds) or use http.ParseTime otherwise. -+// It returns zero value if v cannot be parsed. -+func retryAfter(v string) time.Duration { -+ if i, err := strconv.Atoi(v); err == nil { -+ return time.Duration(i) * time.Second -+ } -+ t, err := http.ParseTime(v) -+ if err != nil { -+ return 0 -+ } -+ return t.Sub(timeNow()) -+} -+ -+// resOkay is a function that reports whether the provided response is okay. -+// It is expected to keep the response body unread. -+type resOkay func(*http.Response) bool -+ -+// wantStatus returns a function which reports whether the code -+// matches the status code of a response. -+func wantStatus(codes ...int) resOkay { -+ return func(res *http.Response) bool { -+ for _, code := range codes { -+ if code == res.StatusCode { -+ return true -+ } -+ } -+ return false -+ } -+} -+ -+// get issues an unsigned GET request to the specified URL. -+// It returns a non-error value only when ok reports true. -+// -+// get retries unsuccessful attempts according to c.RetryBackoff -+// until the context is done or a non-retriable error is received. -+func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) { -+ retry := c.retryTimer() -+ for { -+ req, err := http.NewRequest("GET", url, nil) -+ if err != nil { -+ return nil, err -+ } -+ res, err := c.doNoRetry(ctx, req) -+ switch { -+ case err != nil: -+ return nil, err -+ case ok(res): -+ return res, nil -+ case isRetriable(res.StatusCode): -+ retry.inc() -+ resErr := responseError(res) -+ res.Body.Close() -+ // Ignore the error value from retry.backoff -+ // and return the one from last retry, as received from the CA. -+ if retry.backoff(ctx, req, res) != nil { -+ return nil, resErr -+ } -+ default: -+ defer res.Body.Close() -+ return nil, responseError(res) -+ } -+ } -+} -+ -+// postAsGet is POST-as-GET, a replacement for GET in RFC 8555 -+// as described in https://tools.ietf.org/html/rfc8555#section-6.3. -+// It makes a POST request in KID form with zero JWS payload. -+// See nopayload doc comments in jws.go. -+func (c *Client) postAsGet(ctx context.Context, url string, ok resOkay) (*http.Response, error) { -+ return c.post(ctx, nil, url, noPayload, ok) -+} -+ -+// post issues a signed POST request in JWS format using the provided key -+// to the specified URL. If key is nil, c.Key is used instead. -+// It returns a non-error value only when ok reports true. -+// -+// post retries unsuccessful attempts according to c.RetryBackoff -+// until the context is done or a non-retriable error is received. -+// It uses postNoRetry to make individual requests. -+func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) { -+ retry := c.retryTimer() -+ for { -+ res, req, err := c.postNoRetry(ctx, key, url, body) -+ if err != nil { -+ return nil, err -+ } -+ if ok(res) { -+ return res, nil -+ } -+ resErr := responseError(res) -+ res.Body.Close() -+ switch { -+ // Check for bad nonce before isRetriable because it may have been returned -+ // with an unretriable response code such as 400 Bad Request. -+ case isBadNonce(resErr): -+ // Consider any previously stored nonce values to be invalid. -+ c.clearNonces() -+ case !isRetriable(res.StatusCode): -+ return nil, resErr -+ } -+ retry.inc() -+ // Ignore the error value from retry.backoff -+ // and return the one from last retry, as received from the CA. -+ if err := retry.backoff(ctx, req, res); err != nil { -+ return nil, resErr -+ } -+ } -+} -+ -+// postNoRetry signs the body with the given key and POSTs it to the provided url. -+// It is used by c.post to retry unsuccessful attempts. -+// The body argument must be JSON-serializable. -+// -+// If key argument is nil, c.Key is used to sign the request. -+// If key argument is nil and c.accountKID returns a non-zero keyID, -+// the request is sent in KID form. Otherwise, JWK form is used. -+// -+// In practice, when interfacing with RFC-compliant CAs most requests are sent in KID form -+// and JWK is used only when KID is unavailable: new account endpoint and certificate -+// revocation requests authenticated by a cert key. -+// See jwsEncodeJSON for other details. -+func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) { -+ kid := noKeyID -+ if key == nil { -+ if c.Key == nil { -+ return nil, nil, errors.New("acme: Client.Key must be populated to make POST requests") -+ } -+ key = c.Key -+ kid = c.accountKID(ctx) -+ } -+ nonce, err := c.popNonce(ctx, url) -+ if err != nil { -+ return nil, nil, err -+ } -+ b, err := jwsEncodeJSON(body, key, kid, nonce, url) -+ if err != nil { -+ return nil, nil, err -+ } -+ req, err := http.NewRequest("POST", url, bytes.NewReader(b)) -+ if err != nil { -+ return nil, nil, err -+ } -+ req.Header.Set("Content-Type", "application/jose+json") -+ res, err := c.doNoRetry(ctx, req) -+ if err != nil { -+ return nil, nil, err -+ } -+ c.addNonce(res.Header) -+ return res, req, nil -+} -+ -+// doNoRetry issues a request req, replacing its context (if any) with ctx. -+func (c *Client) doNoRetry(ctx context.Context, req *http.Request) (*http.Response, error) { -+ req.Header.Set("User-Agent", c.userAgent()) -+ res, err := c.httpClient().Do(req.WithContext(ctx)) -+ if err != nil { -+ select { -+ case <-ctx.Done(): -+ // Prefer the unadorned context error. -+ // (The acme package had tests assuming this, previously from ctxhttp's -+ // behavior, predating net/http supporting contexts natively) -+ // TODO(bradfitz): reconsider this in the future. But for now this -+ // requires no test updates. -+ return nil, ctx.Err() -+ default: -+ return nil, err -+ } -+ } -+ return res, nil -+} -+ -+func (c *Client) httpClient() *http.Client { -+ if c.HTTPClient != nil { -+ return c.HTTPClient -+ } -+ return http.DefaultClient -+} -+ -+// packageVersion is the version of the module that contains this package, for -+// sending as part of the User-Agent header. It's set in version_go112.go. -+var packageVersion string -+ -+// userAgent returns the User-Agent header value. It includes the package name, -+// the module version (if available), and the c.UserAgent value (if set). -+func (c *Client) userAgent() string { -+ ua := "golang.org/x/crypto/acme" -+ if packageVersion != "" { -+ ua += "@" + packageVersion -+ } -+ if c.UserAgent != "" { -+ ua = c.UserAgent + " " + ua -+ } -+ return ua -+} -+ -+// isBadNonce reports whether err is an ACME "badnonce" error. -+func isBadNonce(err error) bool { -+ // According to the spec badNonce is urn:ietf:params:acme:error:badNonce. -+ // However, ACME servers in the wild return their versions of the error. -+ // See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 -+ // and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66. -+ ae, ok := err.(*Error) -+ return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") -+} -+ -+// isRetriable reports whether a request can be retried -+// based on the response status code. -+// -+// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code. -+// Callers should parse the response and check with isBadNonce. -+func isRetriable(code int) bool { -+ return code <= 399 || code >= 500 || code == http.StatusTooManyRequests -+} -+ -+// responseError creates an error of Error type from resp. -+func responseError(resp *http.Response) error { -+ // don't care if ReadAll returns an error: -+ // json.Unmarshal will fail in that case anyway -+ b, _ := io.ReadAll(resp.Body) -+ e := &wireError{Status: resp.StatusCode} -+ if err := json.Unmarshal(b, e); err != nil { -+ // this is not a regular error response: -+ // populate detail with anything we received, -+ // e.Status will already contain HTTP response code value -+ e.Detail = string(b) -+ if e.Detail == "" { -+ e.Detail = resp.Status -+ } -+ } -+ return e.error(resp.Header) -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/http_test.go b/ms_mod/golang.org/x/crypto/acme/http_test.go -new file mode 100644 -index 00000000000000..d124e4e219abe6 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/http_test.go -@@ -0,0 +1,255 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "context" -+ "fmt" -+ "io" -+ "net/http" -+ "net/http/httptest" -+ "reflect" -+ "strings" -+ "testing" -+ "time" -+) -+ -+func TestDefaultBackoff(t *testing.T) { -+ tt := []struct { -+ nretry int -+ retryAfter string // Retry-After header -+ out time.Duration // expected min; max = min + jitter -+ }{ -+ {-1, "", time.Second}, // verify the lower bound is 1 -+ {0, "", time.Second}, // verify the lower bound is 1 -+ {100, "", 10 * time.Second}, // verify the ceiling -+ {1, "3600", time.Hour}, // verify the header value is used -+ {1, "", 1 * time.Second}, -+ {2, "", 2 * time.Second}, -+ {3, "", 4 * time.Second}, -+ {4, "", 8 * time.Second}, -+ } -+ for i, test := range tt { -+ r := httptest.NewRequest("GET", "/", nil) -+ resp := &http.Response{Header: http.Header{}} -+ if test.retryAfter != "" { -+ resp.Header.Set("Retry-After", test.retryAfter) -+ } -+ d := defaultBackoff(test.nretry, r, resp) -+ max := test.out + time.Second // + max jitter -+ if d < test.out || max < d { -+ t.Errorf("%d: defaultBackoff(%v) = %v; want between %v and %v", i, test.nretry, d, test.out, max) -+ } -+ } -+} -+ -+func TestErrorResponse(t *testing.T) { -+ s := `{ -+ "status": 400, -+ "type": "urn:acme:error:xxx", -+ "detail": "text" -+ }` -+ res := &http.Response{ -+ StatusCode: 400, -+ Status: "400 Bad Request", -+ Body: io.NopCloser(strings.NewReader(s)), -+ Header: http.Header{"X-Foo": {"bar"}}, -+ } -+ err := responseError(res) -+ v, ok := err.(*Error) -+ if !ok { -+ t.Fatalf("err = %+v (%T); want *Error type", err, err) -+ } -+ if v.StatusCode != 400 { -+ t.Errorf("v.StatusCode = %v; want 400", v.StatusCode) -+ } -+ if v.ProblemType != "urn:acme:error:xxx" { -+ t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType) -+ } -+ if v.Detail != "text" { -+ t.Errorf("v.Detail = %q; want text", v.Detail) -+ } -+ if !reflect.DeepEqual(v.Header, res.Header) { -+ t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header) -+ } -+} -+ -+func TestPostWithRetries(t *testing.T) { -+ var count int -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ count++ -+ w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) -+ if r.Method == "HEAD" { -+ // We expect the client to do 2 head requests to fetch -+ // nonces, one to start and another after getting badNonce -+ return -+ } -+ -+ head, err := decodeJWSHead(r.Body) -+ switch { -+ case err != nil: -+ t.Errorf("decodeJWSHead: %v", err) -+ case head.Nonce == "": -+ t.Error("head.Nonce is empty") -+ case head.Nonce == "nonce1": -+ // Return a badNonce error to force the call to retry. -+ w.Header().Set("Retry-After", "0") -+ w.WriteHeader(http.StatusBadRequest) -+ w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`)) -+ return -+ } -+ // Make client.Authorize happy; we're not testing its result. -+ w.WriteHeader(http.StatusCreated) -+ w.Write([]byte(`{"status":"valid"}`)) -+ })) -+ defer ts.Close() -+ -+ client := &Client{ -+ Key: testKey, -+ DirectoryURL: ts.URL, -+ dir: &Directory{AuthzURL: ts.URL}, -+ } -+ // This call will fail with badNonce, causing a retry -+ if _, err := client.Authorize(context.Background(), "example.com"); err != nil { -+ t.Errorf("client.Authorize 1: %v", err) -+ } -+ if count != 3 { -+ t.Errorf("total requests count: %d; want 3", count) -+ } -+} -+ -+func TestRetryErrorType(t *testing.T) { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Replay-Nonce", "nonce") -+ w.WriteHeader(http.StatusTooManyRequests) -+ w.Write([]byte(`{"type":"rateLimited"}`)) -+ })) -+ defer ts.Close() -+ -+ client := &Client{ -+ Key: testKey, -+ RetryBackoff: func(n int, r *http.Request, res *http.Response) time.Duration { -+ // Do no retries. -+ return 0 -+ }, -+ dir: &Directory{AuthzURL: ts.URL}, -+ } -+ -+ t.Run("post", func(t *testing.T) { -+ testRetryErrorType(t, func() error { -+ _, err := client.Authorize(context.Background(), "example.com") -+ return err -+ }) -+ }) -+ t.Run("get", func(t *testing.T) { -+ testRetryErrorType(t, func() error { -+ _, err := client.GetAuthorization(context.Background(), ts.URL) -+ return err -+ }) -+ }) -+} -+ -+func testRetryErrorType(t *testing.T, callClient func() error) { -+ t.Helper() -+ err := callClient() -+ if err == nil { -+ t.Fatal("client.Authorize returned nil error") -+ } -+ acmeErr, ok := err.(*Error) -+ if !ok { -+ t.Fatalf("err is %v (%T); want *Error", err, err) -+ } -+ if acmeErr.StatusCode != http.StatusTooManyRequests { -+ t.Errorf("acmeErr.StatusCode = %d; want %d", acmeErr.StatusCode, http.StatusTooManyRequests) -+ } -+ if acmeErr.ProblemType != "rateLimited" { -+ t.Errorf("acmeErr.ProblemType = %q; want 'rateLimited'", acmeErr.ProblemType) -+ } -+} -+ -+func TestRetryBackoffArgs(t *testing.T) { -+ const resCode = http.StatusInternalServerError -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Replay-Nonce", "test-nonce") -+ w.WriteHeader(resCode) -+ })) -+ defer ts.Close() -+ -+ // Canceled in backoff. -+ ctx, cancel := context.WithCancel(context.Background()) -+ -+ var nretry int -+ backoff := func(n int, r *http.Request, res *http.Response) time.Duration { -+ nretry++ -+ if n != nretry { -+ t.Errorf("n = %d; want %d", n, nretry) -+ } -+ if nretry == 3 { -+ cancel() -+ } -+ -+ if r == nil { -+ t.Error("r is nil") -+ } -+ if res.StatusCode != resCode { -+ t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, resCode) -+ } -+ return time.Millisecond -+ } -+ -+ client := &Client{ -+ Key: testKey, -+ RetryBackoff: backoff, -+ dir: &Directory{AuthzURL: ts.URL}, -+ } -+ if _, err := client.Authorize(ctx, "example.com"); err == nil { -+ t.Error("err is nil") -+ } -+ if nretry != 3 { -+ t.Errorf("nretry = %d; want 3", nretry) -+ } -+} -+ -+func TestUserAgent(t *testing.T) { -+ for _, custom := range []string{"", "CUSTOM_UA"} { -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ t.Log(r.UserAgent()) -+ if s := "golang.org/x/crypto/acme"; !strings.Contains(r.UserAgent(), s) { -+ t.Errorf("expected User-Agent to contain %q, got %q", s, r.UserAgent()) -+ } -+ if !strings.Contains(r.UserAgent(), custom) { -+ t.Errorf("expected User-Agent to contain %q, got %q", custom, r.UserAgent()) -+ } -+ -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"newOrder": "sure"}`)) -+ })) -+ defer ts.Close() -+ -+ client := &Client{ -+ Key: testKey, -+ DirectoryURL: ts.URL, -+ UserAgent: custom, -+ } -+ if _, err := client.Discover(context.Background()); err != nil { -+ t.Errorf("client.Discover: %v", err) -+ } -+ } -+} -+ -+func TestAccountKidLoop(t *testing.T) { -+ // if Client.postNoRetry is called with a nil key argument -+ // then Client.Key must be set, otherwise we fall into an -+ // infinite loop (which also causes a deadlock). -+ client := &Client{dir: &Directory{OrderURL: ":)"}} -+ _, _, err := client.postNoRetry(context.Background(), nil, "", nil) -+ if err == nil { -+ t.Fatal("Client.postNoRetry didn't fail with a nil key") -+ } -+ expected := "acme: Client.Key must be populated to make POST requests" -+ if err.Error() != expected { -+ t.Fatalf("Unexpected error returned: wanted %q, got %q", expected, err.Error()) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go b/ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go -new file mode 100644 -index 00000000000000..25dba0c50e951f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/internal/acmeprobe/prober.go -@@ -0,0 +1,433 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// The acmeprober program runs against an actual ACME CA implementation. -+// It spins up an HTTP server to fulfill authorization challenges -+// or execute a DNS script to provision a response to dns-01 challenge. -+// -+// For http-01 and tls-alpn-01 challenge types this requires the ACME CA -+// to be able to reach the HTTP server. -+// -+// A usage example: -+// -+// go run prober.go \ -+// -d https://acme-staging-v02.api.letsencrypt.org/directory \ -+// -f order \ -+// -t http-01 \ -+// -a :8080 \ -+// -domain some.example.org -+// -+// The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 -+// in order for the test to be able to fulfill http-01 challenge. -+// To test tls-alpn-01 challenge, 443 port would need to be tunneled -+// to 0.0.0.0:8080. -+// When running with dns-01 challenge type, use -s argument instead of -a. -+package main -+ -+import ( -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/tls" -+ "crypto/x509" -+ "encoding/pem" -+ "errors" -+ "flag" -+ "fmt" -+ "log" -+ "net" -+ "net/http" -+ "os" -+ "os/exec" -+ "strings" -+ "time" -+ -+ "golang.org/x/crypto/acme" -+) -+ -+var ( -+ // ACME CA directory URL. -+ // Let's Encrypt v2 prod: https://acme-v02.api.letsencrypt.org/directory -+ // Let's Encrypt v2 staging: https://acme-staging-v02.api.letsencrypt.org/directory -+ // See the following for more CAs implementing ACME protocol: -+ // https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment#CAs_&_PKIs_that_offer_ACME_certificates -+ directory = flag.String("d", "", "ACME directory URL.") -+ reginfo = flag.String("r", "", "ACME account registration info.") -+ flow = flag.String("f", "", `Flow to run: "order" or "preauthz" (RFC8555).`) -+ chaltyp = flag.String("t", "", "Challenge type: tls-alpn-01, http-01 or dns-01.") -+ addr = flag.String("a", "", "Local server address for tls-alpn-01 and http-01.") -+ dnsscript = flag.String("s", "", "Script to run for provisioning dns-01 challenges.") -+ domain = flag.String("domain", "", "Space separate domain identifiers.") -+ ipaddr = flag.String("ip", "", "Space separate IP address identifiers.") -+) -+ -+func main() { -+ flag.Usage = func() { -+ fmt.Fprintln(flag.CommandLine.Output(), ` -+The prober program runs against an actual ACME CA implementation. -+It spins up an HTTP server to fulfill authorization challenges -+or execute a DNS script to provision a response to dns-01 challenge. -+ -+For http-01 and tls-alpn-01 challenge types this requires the ACME CA -+to be able to reach the HTTP server. -+ -+A usage example: -+ -+ go run prober.go \ -+ -d https://acme-staging-v02.api.letsencrypt.org/directory \ -+ -f order \ -+ -t http-01 \ -+ -a :8080 \ -+ -domain some.example.org -+ -+The above assumes a TCP tunnel from some.example.org:80 to 0.0.0.0:8080 -+in order for the test to be able to fulfill http-01 challenge. -+To test tls-alpn-01 challenge, 443 port would need to be tunneled -+to 0.0.0.0:8080. -+When running with dns-01 challenge type, use -s argument instead of -a. -+ `) -+ flag.PrintDefaults() -+ } -+ flag.Parse() -+ -+ identifiers := acme.DomainIDs(strings.Fields(*domain)...) -+ identifiers = append(identifiers, acme.IPIDs(strings.Fields(*ipaddr)...)...) -+ if len(identifiers) == 0 { -+ log.Fatal("at least one domain or IP addr identifier is required") -+ } -+ -+ // Duration of the whole run. -+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) -+ defer cancel() -+ -+ // Create and register a new account. -+ akey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ log.Fatal(err) -+ } -+ cl := &acme.Client{Key: akey, DirectoryURL: *directory} -+ a := &acme.Account{Contact: strings.Fields(*reginfo)} -+ if _, err := cl.Register(ctx, a, acme.AcceptTOS); err != nil { -+ log.Fatalf("Register: %v", err) -+ } -+ -+ // Run the desired flow test. -+ p := &prober{ -+ client: cl, -+ chalType: *chaltyp, -+ localAddr: *addr, -+ dnsScript: *dnsscript, -+ } -+ switch *flow { -+ case "order": -+ p.runOrder(ctx, identifiers) -+ case "preauthz": -+ p.runPreauthz(ctx, identifiers) -+ default: -+ log.Fatalf("unknown flow: %q", *flow) -+ } -+ if len(p.errors) > 0 { -+ os.Exit(1) -+ } -+} -+ -+type prober struct { -+ client *acme.Client -+ chalType string -+ localAddr string -+ dnsScript string -+ -+ errors []error -+} -+ -+func (p *prober) errorf(format string, a ...interface{}) { -+ err := fmt.Errorf(format, a...) -+ log.Print(err) -+ p.errors = append(p.errors, err) -+} -+ -+func (p *prober) runOrder(ctx context.Context, identifiers []acme.AuthzID) { -+ // Create a new order and pick a challenge. -+ // Note that Let's Encrypt will reply with 400 error:malformed -+ // "NotBefore and NotAfter are not supported" when providing a NotAfter -+ // value like WithOrderNotAfter(time.Now().Add(24 * time.Hour)). -+ o, err := p.client.AuthorizeOrder(ctx, identifiers) -+ if err != nil { -+ log.Fatalf("AuthorizeOrder: %v", err) -+ } -+ -+ var zurls []string -+ for _, u := range o.AuthzURLs { -+ z, err := p.client.GetAuthorization(ctx, u) -+ if err != nil { -+ log.Fatalf("GetAuthorization(%q): %v", u, err) -+ } -+ log.Printf("%+v", z) -+ if z.Status != acme.StatusPending { -+ log.Printf("authz status is %q; skipping", z.Status) -+ continue -+ } -+ if err := p.fulfill(ctx, z); err != nil { -+ log.Fatalf("fulfill(%s): %v", z.URI, err) -+ } -+ zurls = append(zurls, z.URI) -+ log.Printf("authorized for %+v", z.Identifier) -+ } -+ -+ log.Print("all challenges are done") -+ if _, err := p.client.WaitOrder(ctx, o.URI); err != nil { -+ log.Fatalf("WaitOrder(%q): %v", o.URI, err) -+ } -+ csr, certkey := newCSR(identifiers) -+ der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) -+ if err != nil { -+ log.Fatalf("CreateOrderCert: %v", err) -+ } -+ log.Printf("cert URL: %s", curl) -+ if err := checkCert(der, identifiers); err != nil { -+ p.errorf("invalid cert: %v", err) -+ } -+ -+ // Deactivate all authorizations we satisfied earlier. -+ for _, v := range zurls { -+ if err := p.client.RevokeAuthorization(ctx, v); err != nil { -+ p.errorf("RevokAuthorization(%q): %v", v, err) -+ continue -+ } -+ } -+ // Deactivate the account. We don't need it for any further calls. -+ if err := p.client.DeactivateReg(ctx); err != nil { -+ p.errorf("DeactivateReg: %v", err) -+ } -+ // Try revoking the issued cert using its private key. -+ if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { -+ p.errorf("RevokeCert: %v", err) -+ } -+} -+ -+func (p *prober) runPreauthz(ctx context.Context, identifiers []acme.AuthzID) { -+ dir, err := p.client.Discover(ctx) -+ if err != nil { -+ log.Fatalf("Discover: %v", err) -+ } -+ if dir.AuthzURL == "" { -+ log.Fatal("CA does not support pre-authorization") -+ } -+ -+ var zurls []string -+ for _, id := range identifiers { -+ z, err := authorize(ctx, p.client, id) -+ if err != nil { -+ log.Fatalf("AuthorizeID(%+v): %v", z, err) -+ } -+ if z.Status == acme.StatusValid { -+ log.Printf("authz %s is valid; skipping", z.URI) -+ continue -+ } -+ if err := p.fulfill(ctx, z); err != nil { -+ log.Fatalf("fulfill(%s): %v", z.URI, err) -+ } -+ zurls = append(zurls, z.URI) -+ log.Printf("authorized for %+v", id) -+ } -+ -+ // We should be all set now. -+ // Expect all authorizations to be satisfied. -+ log.Print("all challenges are done") -+ o, err := p.client.AuthorizeOrder(ctx, identifiers) -+ if err != nil { -+ log.Fatalf("AuthorizeOrder: %v", err) -+ } -+ waitCtx, cancel := context.WithTimeout(ctx, time.Minute) -+ defer cancel() -+ if _, err := p.client.WaitOrder(waitCtx, o.URI); err != nil { -+ log.Fatalf("WaitOrder(%q): %v", o.URI, err) -+ } -+ csr, certkey := newCSR(identifiers) -+ der, curl, err := p.client.CreateOrderCert(ctx, o.FinalizeURL, csr, true) -+ if err != nil { -+ log.Fatalf("CreateOrderCert: %v", err) -+ } -+ log.Printf("cert URL: %s", curl) -+ if err := checkCert(der, identifiers); err != nil { -+ p.errorf("invalid cert: %v", err) -+ } -+ -+ // Deactivate all authorizations we satisfied earlier. -+ for _, v := range zurls { -+ if err := p.client.RevokeAuthorization(ctx, v); err != nil { -+ p.errorf("RevokeAuthorization(%q): %v", v, err) -+ continue -+ } -+ } -+ // Deactivate the account. We don't need it for any further calls. -+ if err := p.client.DeactivateReg(ctx); err != nil { -+ p.errorf("DeactivateReg: %v", err) -+ } -+ // Try revoking the issued cert using its private key. -+ if err := p.client.RevokeCert(ctx, certkey, der[0], acme.CRLReasonCessationOfOperation); err != nil { -+ p.errorf("RevokeCert: %v", err) -+ } -+} -+ -+func (p *prober) fulfill(ctx context.Context, z *acme.Authorization) error { -+ var chal *acme.Challenge -+ for i, c := range z.Challenges { -+ log.Printf("challenge %d: %+v", i, c) -+ if c.Type == p.chalType { -+ log.Printf("picked %s for authz %s", c.URI, z.URI) -+ chal = c -+ } -+ } -+ if chal == nil { -+ return fmt.Errorf("challenge type %q wasn't offered for authz %s", p.chalType, z.URI) -+ } -+ -+ switch chal.Type { -+ case "tls-alpn-01": -+ return p.runTLSALPN01(ctx, z, chal) -+ case "http-01": -+ return p.runHTTP01(ctx, z, chal) -+ case "dns-01": -+ return p.runDNS01(ctx, z, chal) -+ default: -+ return fmt.Errorf("unknown challenge type %q", chal.Type) -+ } -+} -+ -+func (p *prober) runTLSALPN01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { -+ tokenCert, err := p.client.TLSALPN01ChallengeCert(chal.Token, z.Identifier.Value) -+ if err != nil { -+ return fmt.Errorf("TLSALPN01ChallengeCert: %v", err) -+ } -+ s := &http.Server{ -+ Addr: p.localAddr, -+ TLSConfig: &tls.Config{ -+ NextProtos: []string{acme.ALPNProto}, -+ GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { -+ log.Printf("hello: %+v", hello) -+ return &tokenCert, nil -+ }, -+ }, -+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ log.Printf("%s %s", r.Method, r.URL) -+ w.WriteHeader(http.StatusNotFound) -+ }), -+ } -+ go s.ListenAndServeTLS("", "") -+ defer s.Close() -+ -+ if _, err := p.client.Accept(ctx, chal); err != nil { -+ return fmt.Errorf("Accept(%q): %v", chal.URI, err) -+ } -+ _, zerr := p.client.WaitAuthorization(ctx, z.URI) -+ return zerr -+} -+ -+func (p *prober) runHTTP01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { -+ body, err := p.client.HTTP01ChallengeResponse(chal.Token) -+ if err != nil { -+ return fmt.Errorf("HTTP01ChallengeResponse: %v", err) -+ } -+ s := &http.Server{ -+ Addr: p.localAddr, -+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ log.Printf("%s %s", r.Method, r.URL) -+ if r.URL.Path != p.client.HTTP01ChallengePath(chal.Token) { -+ w.WriteHeader(http.StatusNotFound) -+ return -+ } -+ w.Write([]byte(body)) -+ }), -+ } -+ go s.ListenAndServe() -+ defer s.Close() -+ -+ if _, err := p.client.Accept(ctx, chal); err != nil { -+ return fmt.Errorf("Accept(%q): %v", chal.URI, err) -+ } -+ _, zerr := p.client.WaitAuthorization(ctx, z.URI) -+ return zerr -+} -+ -+func (p *prober) runDNS01(ctx context.Context, z *acme.Authorization, chal *acme.Challenge) error { -+ token, err := p.client.DNS01ChallengeRecord(chal.Token) -+ if err != nil { -+ return fmt.Errorf("DNS01ChallengeRecord: %v", err) -+ } -+ -+ name := fmt.Sprintf("_acme-challenge.%s", z.Identifier.Value) -+ cmd := exec.CommandContext(ctx, p.dnsScript, name, token) -+ cmd.Stdin = os.Stdin -+ cmd.Stdout = os.Stdout -+ cmd.Stderr = os.Stderr -+ if err := cmd.Run(); err != nil { -+ return fmt.Errorf("%s: %v", p.dnsScript, err) -+ } -+ -+ if _, err := p.client.Accept(ctx, chal); err != nil { -+ return fmt.Errorf("Accept(%q): %v", chal.URI, err) -+ } -+ _, zerr := p.client.WaitAuthorization(ctx, z.URI) -+ return zerr -+} -+ -+func authorize(ctx context.Context, client *acme.Client, id acme.AuthzID) (*acme.Authorization, error) { -+ if id.Type == "ip" { -+ return client.AuthorizeIP(ctx, id.Value) -+ } -+ return client.Authorize(ctx, id.Value) -+} -+ -+func checkCert(derChain [][]byte, id []acme.AuthzID) error { -+ if len(derChain) == 0 { -+ return errors.New("cert chain is zero bytes") -+ } -+ for i, b := range derChain { -+ crt, err := x509.ParseCertificate(b) -+ if err != nil { -+ return fmt.Errorf("%d: ParseCertificate: %v", i, err) -+ } -+ log.Printf("%d: serial: 0x%s", i, crt.SerialNumber) -+ log.Printf("%d: subject: %s", i, crt.Subject) -+ log.Printf("%d: issuer: %s", i, crt.Issuer) -+ log.Printf("%d: expires in %.1f day(s)", i, time.Until(crt.NotAfter).Hours()/24) -+ if i > 0 { // not a leaf cert -+ continue -+ } -+ p := &pem.Block{Type: "CERTIFICATE", Bytes: b} -+ log.Printf("%d: leaf:\n%s", i, pem.EncodeToMemory(p)) -+ for _, v := range id { -+ if err := crt.VerifyHostname(v.Value); err != nil { -+ return err -+ } -+ } -+ } -+ return nil -+} -+ -+func newCSR(identifiers []acme.AuthzID) ([]byte, crypto.Signer) { -+ var csr x509.CertificateRequest -+ for _, id := range identifiers { -+ switch id.Type { -+ case "dns": -+ csr.DNSNames = append(csr.DNSNames, id.Value) -+ case "ip": -+ csr.IPAddresses = append(csr.IPAddresses, net.ParseIP(id.Value)) -+ default: -+ panic(fmt.Sprintf("newCSR: unknown identifier type %q", id.Type)) -+ } -+ } -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(fmt.Sprintf("newCSR: ecdsa.GenerateKey for a cert: %v", err)) -+ } -+ b, err := x509.CreateCertificateRequest(rand.Reader, &csr, k) -+ if err != nil { -+ panic(fmt.Sprintf("newCSR: x509.CreateCertificateRequest: %v", err)) -+ } -+ return b, k -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/jws.go b/ms_mod/golang.org/x/crypto/acme/jws.go -new file mode 100644 -index 00000000000000..b38828d85935c3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/jws.go -@@ -0,0 +1,257 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/hmac" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/sha256" -+ _ "crypto/sha512" // need for EC keys -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/json" -+ "errors" -+ "fmt" -+ "math/big" -+) -+ -+// KeyID is the account key identity provided by a CA during registration. -+type KeyID string -+ -+// noKeyID indicates that jwsEncodeJSON should compute and use JWK instead of a KID. -+// See jwsEncodeJSON for details. -+const noKeyID = KeyID("") -+ -+// noPayload indicates jwsEncodeJSON will encode zero-length octet string -+// in a JWS request. This is called POST-as-GET in RFC 8555 and is used to make -+// authenticated GET requests via POSTing with an empty payload. -+// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details. -+const noPayload = "" -+ -+// noNonce indicates that the nonce should be omitted from the protected header. -+// See jwsEncodeJSON for details. -+const noNonce = "" -+ -+// jsonWebSignature can be easily serialized into a JWS following -+// https://tools.ietf.org/html/rfc7515#section-3.2. -+type jsonWebSignature struct { -+ Protected string `json:"protected"` -+ Payload string `json:"payload"` -+ Sig string `json:"signature"` -+} -+ -+// jwsEncodeJSON signs claimset using provided key and a nonce. -+// The result is serialized in JSON format containing either kid or jwk -+// fields based on the provided KeyID value. -+// -+// The claimset is marshalled using json.Marshal unless it is a string. -+// In which case it is inserted directly into the message. -+// -+// If kid is non-empty, its quoted value is inserted in the protected header -+// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted -+// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive. -+// -+// If nonce is non-empty, its quoted value is inserted in the protected header. -+// -+// See https://tools.ietf.org/html/rfc7515#section-7. -+func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) { -+ if key == nil { -+ return nil, errors.New("nil key") -+ } -+ alg, sha := jwsHasher(key.Public()) -+ if alg == "" || !sha.Available() { -+ return nil, ErrUnsupportedKey -+ } -+ headers := struct { -+ Alg string `json:"alg"` -+ KID string `json:"kid,omitempty"` -+ JWK json.RawMessage `json:"jwk,omitempty"` -+ Nonce string `json:"nonce,omitempty"` -+ URL string `json:"url"` -+ }{ -+ Alg: alg, -+ Nonce: nonce, -+ URL: url, -+ } -+ switch kid { -+ case noKeyID: -+ jwk, err := jwkEncode(key.Public()) -+ if err != nil { -+ return nil, err -+ } -+ headers.JWK = json.RawMessage(jwk) -+ default: -+ headers.KID = string(kid) -+ } -+ phJSON, err := json.Marshal(headers) -+ if err != nil { -+ return nil, err -+ } -+ phead := base64.RawURLEncoding.EncodeToString([]byte(phJSON)) -+ var payload string -+ if val, ok := claimset.(string); ok { -+ payload = val -+ } else { -+ cs, err := json.Marshal(claimset) -+ if err != nil { -+ return nil, err -+ } -+ payload = base64.RawURLEncoding.EncodeToString(cs) -+ } -+ hash := sha.New() -+ hash.Write([]byte(phead + "." + payload)) -+ sig, err := jwsSign(key, sha, hash.Sum(nil)) -+ if err != nil { -+ return nil, err -+ } -+ enc := jsonWebSignature{ -+ Protected: phead, -+ Payload: payload, -+ Sig: base64.RawURLEncoding.EncodeToString(sig), -+ } -+ return json.Marshal(&enc) -+} -+ -+// jwsWithMAC creates and signs a JWS using the given key and the HS256 -+// algorithm. kid and url are included in the protected header. rawPayload -+// should not be base64-URL-encoded. -+func jwsWithMAC(key []byte, kid, url string, rawPayload []byte) (*jsonWebSignature, error) { -+ if len(key) == 0 { -+ return nil, errors.New("acme: cannot sign JWS with an empty MAC key") -+ } -+ header := struct { -+ Algorithm string `json:"alg"` -+ KID string `json:"kid"` -+ URL string `json:"url,omitempty"` -+ }{ -+ // Only HMAC-SHA256 is supported. -+ Algorithm: "HS256", -+ KID: kid, -+ URL: url, -+ } -+ rawProtected, err := json.Marshal(header) -+ if err != nil { -+ return nil, err -+ } -+ protected := base64.RawURLEncoding.EncodeToString(rawProtected) -+ payload := base64.RawURLEncoding.EncodeToString(rawPayload) -+ -+ h := hmac.New(sha256.New, key) -+ if _, err := h.Write([]byte(protected + "." + payload)); err != nil { -+ return nil, err -+ } -+ mac := h.Sum(nil) -+ -+ return &jsonWebSignature{ -+ Protected: protected, -+ Payload: payload, -+ Sig: base64.RawURLEncoding.EncodeToString(mac), -+ }, nil -+} -+ -+// jwkEncode encodes public part of an RSA or ECDSA key into a JWK. -+// The result is also suitable for creating a JWK thumbprint. -+// https://tools.ietf.org/html/rfc7517 -+func jwkEncode(pub crypto.PublicKey) (string, error) { -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ // https://tools.ietf.org/html/rfc7518#section-6.3.1 -+ n := pub.N -+ e := big.NewInt(int64(pub.E)) -+ // Field order is important. -+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. -+ return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, -+ base64.RawURLEncoding.EncodeToString(e.Bytes()), -+ base64.RawURLEncoding.EncodeToString(n.Bytes()), -+ ), nil -+ case *ecdsa.PublicKey: -+ // https://tools.ietf.org/html/rfc7518#section-6.2.1 -+ p := pub.Curve.Params() -+ n := p.BitSize / 8 -+ if p.BitSize%8 != 0 { -+ n++ -+ } -+ x := pub.X.Bytes() -+ if n > len(x) { -+ x = append(make([]byte, n-len(x)), x...) -+ } -+ y := pub.Y.Bytes() -+ if n > len(y) { -+ y = append(make([]byte, n-len(y)), y...) -+ } -+ // Field order is important. -+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. -+ return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, -+ p.Name, -+ base64.RawURLEncoding.EncodeToString(x), -+ base64.RawURLEncoding.EncodeToString(y), -+ ), nil -+ } -+ return "", ErrUnsupportedKey -+} -+ -+// jwsSign signs the digest using the given key. -+// The hash is unused for ECDSA keys. -+func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) { -+ switch pub := key.Public().(type) { -+ case *rsa.PublicKey: -+ return key.Sign(rand.Reader, digest, hash) -+ case *ecdsa.PublicKey: -+ sigASN1, err := key.Sign(rand.Reader, digest, hash) -+ if err != nil { -+ return nil, err -+ } -+ -+ var rs struct{ R, S *big.Int } -+ if _, err := asn1.Unmarshal(sigASN1, &rs); err != nil { -+ return nil, err -+ } -+ -+ rb, sb := rs.R.Bytes(), rs.S.Bytes() -+ size := pub.Params().BitSize / 8 -+ if size%8 > 0 { -+ size++ -+ } -+ sig := make([]byte, size*2) -+ copy(sig[size-len(rb):], rb) -+ copy(sig[size*2-len(sb):], sb) -+ return sig, nil -+ } -+ return nil, ErrUnsupportedKey -+} -+ -+// jwsHasher indicates suitable JWS algorithm name and a hash function -+// to use for signing a digest with the provided key. -+// It returns ("", 0) if the key is not supported. -+func jwsHasher(pub crypto.PublicKey) (string, crypto.Hash) { -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ return "RS256", crypto.SHA256 -+ case *ecdsa.PublicKey: -+ switch pub.Params().Name { -+ case "P-256": -+ return "ES256", crypto.SHA256 -+ case "P-384": -+ return "ES384", crypto.SHA384 -+ case "P-521": -+ return "ES512", crypto.SHA512 -+ } -+ } -+ return "", 0 -+} -+ -+// JWKThumbprint creates a JWK thumbprint out of pub -+// as specified in https://tools.ietf.org/html/rfc7638. -+func JWKThumbprint(pub crypto.PublicKey) (string, error) { -+ jwk, err := jwkEncode(pub) -+ if err != nil { -+ return "", err -+ } -+ b := sha256.Sum256([]byte(jwk)) -+ return base64.RawURLEncoding.EncodeToString(b[:]), nil -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/jws_test.go b/ms_mod/golang.org/x/crypto/acme/jws_test.go -new file mode 100644 -index 00000000000000..d5f00ba2d32458 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/jws_test.go -@@ -0,0 +1,550 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "crypto/sha256" -+ "crypto/x509" -+ "encoding/base64" -+ "encoding/json" -+ "encoding/pem" -+ "fmt" -+ "io" -+ "math/big" -+ "testing" -+) -+ -+// The following shell command alias is used in the comments -+// throughout this file: -+// alias b64raw="base64 -w0 | tr -d '=' | tr '/+' '_-'" -+ -+const ( -+ // Modulus in raw base64: -+ // 4xgZ3eRPkwoRvy7qeRUbmMDe0V-xH9eWLdu0iheeLlrmD2mqWXfP9IeSKApbn34 -+ // g8TuAS9g5zhq8ELQ3kmjr-KV86GAMgI6VAcGlq3QrzpTCf_30Ab7-zawrfRaFON -+ // a1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosqEXeaIkVYBEhbh -+ // Nu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZfoyFyek380mHg -+ // JAumQ_I2fjj98_97mk3ihOY4AgVdCDj1z_GCoZkG5Rq7nbCGyosyKWyDX00Zs-n -+ // NqVhoLeIvXC4nnWdJMZ6rogxyQQ -+ testKeyPEM = ` -+-----BEGIN RSA PRIVATE KEY----- -+MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq -+WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30 -+Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq -+EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf -+oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy -+KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV -+9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H -+r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm -+ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP -+G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS -+zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6 -+9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s -+8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc -+7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL -+qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ -+Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU -+RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o -+JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd -+4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt -+jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q -+YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73 -+c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G -+N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7 -+EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO -+9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx -+-----END RSA PRIVATE KEY----- -+` -+ -+ // This thumbprint is for the testKey defined above. -+ testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ" -+ -+ // openssl ecparam -name secp256k1 -genkey -noout -+ testKeyECPEM = ` -+-----BEGIN EC PRIVATE KEY----- -+MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49 -+AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5 -+QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ== -+-----END EC PRIVATE KEY----- -+` -+ // openssl ecparam -name secp384r1 -genkey -noout -+ testKeyEC384PEM = ` -+-----BEGIN EC PRIVATE KEY----- -+MIGkAgEBBDAQ4lNtXRORWr1bgKR1CGysr9AJ9SyEk4jiVnlUWWUChmSNL+i9SLSD -+Oe/naPqXJ6CgBwYFK4EEACKhZANiAAQzKtj+Ms0vHoTX5dzv3/L5YMXOWuI5UKRj -+JigpahYCqXD2BA1j0E/2xt5vlPf+gm0PL+UHSQsCokGnIGuaHCsJAp3ry0gHQEke -+WYXapUUFdvaK1R2/2hn5O+eiQM8YzCg= -+-----END EC PRIVATE KEY----- -+` -+ // openssl ecparam -name secp521r1 -genkey -noout -+ testKeyEC512PEM = ` -+-----BEGIN EC PRIVATE KEY----- -+MIHcAgEBBEIBSNZKFcWzXzB/aJClAb305ibalKgtDA7+70eEkdPt28/3LZMM935Z -+KqYHh/COcxuu3Kt8azRAUz3gyr4zZKhlKUSgBwYFK4EEACOhgYkDgYYABAHUNKbx -+7JwC7H6pa2sV0tERWhHhB3JmW+OP6SUgMWryvIKajlx73eS24dy4QPGrWO9/ABsD -+FqcRSkNVTXnIv6+0mAF25knqIBIg5Q8M9BnOu9GGAchcwt3O7RDHmqewnJJDrbjd -+GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ== -+-----END EC PRIVATE KEY----- -+` -+ // 1. openssl ec -in key.pem -noout -text -+ // 2. remove first byte, 04 (the header); the rest is X and Y -+ // 3. convert each with: echo | xxd -r -p | b64raw -+ testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ" -+ testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk" -+ testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt" -+ testKeyEC384PubY = "Dy_lB0kLAqJBpyBrmhwrCQKd68tIB0BJHlmF2qVFBXb2itUdv9oZ-TvnokDPGMwo" -+ testKeyEC512PubX = "AdQ0pvHsnALsfqlraxXS0RFaEeEHcmZb44_pJSAxavK8gpqOXHvd5Lbh3LhA8atY738AGwMWpxFKQ1VNeci_r7SY" -+ testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax" -+ -+ // echo -n '{"crv":"P-256","kty":"EC","x":"","y":""}' | \ -+ // openssl dgst -binary -sha256 | b64raw -+ testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU" -+) -+ -+var ( -+ testKey *rsa.PrivateKey -+ testKeyEC *ecdsa.PrivateKey -+ testKeyEC384 *ecdsa.PrivateKey -+ testKeyEC512 *ecdsa.PrivateKey -+) -+ -+func init() { -+ testKey = parseRSA(testKeyPEM, "testKeyPEM") -+ testKeyEC = parseEC(testKeyECPEM, "testKeyECPEM") -+ testKeyEC384 = parseEC(testKeyEC384PEM, "testKeyEC384PEM") -+ testKeyEC512 = parseEC(testKeyEC512PEM, "testKeyEC512PEM") -+} -+ -+func decodePEM(s, name string) []byte { -+ d, _ := pem.Decode([]byte(s)) -+ if d == nil { -+ panic("no block found in " + name) -+ } -+ return d.Bytes -+} -+ -+func parseRSA(s, name string) *rsa.PrivateKey { -+ b := decodePEM(s, name) -+ k, err := x509.ParsePKCS1PrivateKey(b) -+ if err != nil { -+ panic(fmt.Sprintf("%s: %v", name, err)) -+ } -+ return k -+} -+ -+func parseEC(s, name string) *ecdsa.PrivateKey { -+ b := decodePEM(s, name) -+ k, err := x509.ParseECPrivateKey(b) -+ if err != nil { -+ panic(fmt.Sprintf("%s: %v", name, err)) -+ } -+ return k -+} -+ -+func TestJWSEncodeJSON(t *testing.T) { -+ claims := struct{ Msg string }{"Hello JWS"} -+ // JWS signed with testKey and "nonce" as the nonce value -+ // JSON-serialized JWS fields are split for easier testing -+ const ( -+ // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce","url":"url"} -+ protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + -+ "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + -+ "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + -+ "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" + -+ "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" + -+ "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" + -+ "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" + -+ "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + -+ "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + -+ "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + -+ "UVEifSwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" -+ // {"Msg":"Hello JWS"} -+ payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" -+ // printf '.' | openssl dgst -binary -sha256 -sign testKey | b64raw -+ signature = "YFyl_xz1E7TR-3E1bIuASTr424EgCvBHjt25WUFC2VaDjXYV0Rj_" + -+ "Hd3dJ_2IRqBrXDZZ2n4ZeA_4mm3QFwmwyeDwe2sWElhb82lCZ8iX" + -+ "uFnjeOmSOjx-nWwPa5ibCXzLq13zZ-OBV1Z4oN_TuailQeRoSfA3" + -+ "nO8gG52mv1x2OMQ5MAFtt8jcngBLzts4AyhI6mBJ2w7Yaj3ZCriq" + -+ "DWA3GLFvvHdW1Ba9Z01wtGT2CuZI7DUk_6Qj1b3BkBGcoKur5C9i" + -+ "bUJtCkABwBMvBQNyD3MmXsrRFRTgvVlyU_yMaucYm7nmzEr_2PaQ" + -+ "50rFt_9qOfJ4sfbLtG1Wwae57BQx1g" -+ ) -+ -+ b, err := jwsEncodeJSON(claims, testKey, noKeyID, "nonce", "url") -+ if err != nil { -+ t.Fatal(err) -+ } -+ var jws struct{ Protected, Payload, Signature string } -+ if err := json.Unmarshal(b, &jws); err != nil { -+ t.Fatal(err) -+ } -+ if jws.Protected != protected { -+ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) -+ } -+ if jws.Payload != payload { -+ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) -+ } -+ if jws.Signature != signature { -+ t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature) -+ } -+} -+ -+func TestJWSEncodeNoNonce(t *testing.T) { -+ kid := KeyID("https://example.org/account/1") -+ claims := "RawString" -+ const ( -+ // {"alg":"ES256","kid":"https://example.org/account/1","nonce":"nonce","url":"url"} -+ protected = "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYWNjb3VudC8xIiwidXJsIjoidXJsIn0" -+ // "Raw String" -+ payload = "RawString" -+ ) -+ -+ b, err := jwsEncodeJSON(claims, testKeyEC, kid, "", "url") -+ if err != nil { -+ t.Fatal(err) -+ } -+ var jws struct{ Protected, Payload, Signature string } -+ if err := json.Unmarshal(b, &jws); err != nil { -+ t.Fatal(err) -+ } -+ if jws.Protected != protected { -+ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) -+ } -+ if jws.Payload != payload { -+ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) -+ } -+ -+ sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) -+ if err != nil { -+ t.Fatalf("jws.Signature: %v", err) -+ } -+ r, s := big.NewInt(0), big.NewInt(0) -+ r.SetBytes(sig[:len(sig)/2]) -+ s.SetBytes(sig[len(sig)/2:]) -+ h := sha256.Sum256([]byte(protected + "." + payload)) -+ if !ecdsa.Verify(testKeyEC.Public().(*ecdsa.PublicKey), h[:], r, s) { -+ t.Error("invalid signature") -+ } -+} -+ -+func TestJWSEncodeKID(t *testing.T) { -+ kid := KeyID("https://example.org/account/1") -+ claims := struct{ Msg string }{"Hello JWS"} -+ // JWS signed with testKeyEC -+ const ( -+ // {"alg":"ES256","kid":"https://example.org/account/1","nonce":"nonce","url":"url"} -+ protected = "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5" + -+ "vcmcvYWNjb3VudC8xIiwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" -+ // {"Msg":"Hello JWS"} -+ payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" -+ ) -+ -+ b, err := jwsEncodeJSON(claims, testKeyEC, kid, "nonce", "url") -+ if err != nil { -+ t.Fatal(err) -+ } -+ var jws struct{ Protected, Payload, Signature string } -+ if err := json.Unmarshal(b, &jws); err != nil { -+ t.Fatal(err) -+ } -+ if jws.Protected != protected { -+ t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) -+ } -+ if jws.Payload != payload { -+ t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) -+ } -+ -+ sig, err := base64.RawURLEncoding.DecodeString(jws.Signature) -+ if err != nil { -+ t.Fatalf("jws.Signature: %v", err) -+ } -+ r, s := big.NewInt(0), big.NewInt(0) -+ r.SetBytes(sig[:len(sig)/2]) -+ s.SetBytes(sig[len(sig)/2:]) -+ h := sha256.Sum256([]byte(protected + "." + payload)) -+ if !ecdsa.Verify(testKeyEC.Public().(*ecdsa.PublicKey), h[:], r, s) { -+ t.Error("invalid signature") -+ } -+} -+ -+func TestJWSEncodeJSONEC(t *testing.T) { -+ tt := []struct { -+ key *ecdsa.PrivateKey -+ x, y string -+ alg, crv string -+ }{ -+ {testKeyEC, testKeyECPubX, testKeyECPubY, "ES256", "P-256"}, -+ {testKeyEC384, testKeyEC384PubX, testKeyEC384PubY, "ES384", "P-384"}, -+ {testKeyEC512, testKeyEC512PubX, testKeyEC512PubY, "ES512", "P-521"}, -+ } -+ for i, test := range tt { -+ claims := struct{ Msg string }{"Hello JWS"} -+ b, err := jwsEncodeJSON(claims, test.key, noKeyID, "nonce", "url") -+ if err != nil { -+ t.Errorf("%d: %v", i, err) -+ continue -+ } -+ var jws struct{ Protected, Payload, Signature string } -+ if err := json.Unmarshal(b, &jws); err != nil { -+ t.Errorf("%d: %v", i, err) -+ continue -+ } -+ -+ b, err = base64.RawURLEncoding.DecodeString(jws.Protected) -+ if err != nil { -+ t.Errorf("%d: jws.Protected: %v", i, err) -+ } -+ var head struct { -+ Alg string -+ Nonce string -+ URL string `json:"url"` -+ KID string `json:"kid"` -+ JWK struct { -+ Crv string -+ Kty string -+ X string -+ Y string -+ } `json:"jwk"` -+ } -+ if err := json.Unmarshal(b, &head); err != nil { -+ t.Errorf("%d: jws.Protected: %v", i, err) -+ } -+ if head.Alg != test.alg { -+ t.Errorf("%d: head.Alg = %q; want %q", i, head.Alg, test.alg) -+ } -+ if head.Nonce != "nonce" { -+ t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce) -+ } -+ if head.URL != "url" { -+ t.Errorf("%d: head.URL = %q; want 'url'", i, head.URL) -+ } -+ if head.KID != "" { -+ // We used noKeyID in jwsEncodeJSON: expect no kid value. -+ t.Errorf("%d: head.KID = %q; want empty", i, head.KID) -+ } -+ if head.JWK.Crv != test.crv { -+ t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv) -+ } -+ if head.JWK.Kty != "EC" { -+ t.Errorf("%d: head.JWK.Kty = %q; want EC", i, head.JWK.Kty) -+ } -+ if head.JWK.X != test.x { -+ t.Errorf("%d: head.JWK.X = %q; want %q", i, head.JWK.X, test.x) -+ } -+ if head.JWK.Y != test.y { -+ t.Errorf("%d: head.JWK.Y = %q; want %q", i, head.JWK.Y, test.y) -+ } -+ } -+} -+ -+type customTestSigner struct { -+ sig []byte -+ pub crypto.PublicKey -+} -+ -+func (s *customTestSigner) Public() crypto.PublicKey { return s.pub } -+func (s *customTestSigner) Sign(io.Reader, []byte, crypto.SignerOpts) ([]byte, error) { -+ return s.sig, nil -+} -+ -+func TestJWSEncodeJSONCustom(t *testing.T) { -+ claims := struct{ Msg string }{"hello"} -+ const ( -+ // printf '{"Msg":"hello"}' | b64raw -+ payload = "eyJNc2ciOiJoZWxsbyJ9" -+ // printf 'testsig' | b64raw -+ testsig = "dGVzdHNpZw" -+ -+ // the example P256 curve point from https://tools.ietf.org/html/rfc7515#appendix-A.3.1 -+ // encoded as ASN.1… -+ es256stdsig = "MEUCIA7RIVN5Y2xIPC9/FVgH1AKjsigDOvl8fheBmsMWnqZlAiEA" + -+ "xQoH04w8cOXY8S2vCEpUgKZlkMXyk1Cajz9/ioOjVNU" -+ // …and RFC7518 (https://tools.ietf.org/html/rfc7518#section-3.4) -+ es256jwsig = "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw" + -+ "5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" -+ -+ // printf '{"alg":"ES256","jwk":{"crv":"P-256","kty":"EC","x":,"y":},"nonce":"nonce","url":"url"}' | b64raw -+ es256phead = "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0" + -+ "eSI6IkVDIiwieCI6IjVsaEV1ZzV4SzR4QkRaMm5BYmF4THRhTGl2" + -+ "ODVieEo3ZVBkMWRrTzIzSFEiLCJ5IjoiNGFpSzcyc0JlVUFHa3Yw" + -+ "VGFMc213b2tZVVl5TnhHc1M1RU1JS3dzTklLayJ9LCJub25jZSI6" + -+ "Im5vbmNlIiwidXJsIjoidXJsIn0" -+ -+ // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce","url":"url"} -+ rs256phead = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + -+ "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + -+ "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + -+ "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" + -+ "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" + -+ "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" + -+ "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" + -+ "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + -+ "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + -+ "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + -+ "UVEifSwibm9uY2UiOiJub25jZSIsInVybCI6InVybCJ9" -+ ) -+ -+ tt := []struct { -+ alg, phead string -+ pub crypto.PublicKey -+ stdsig, jwsig string -+ }{ -+ {"ES256", es256phead, testKeyEC.Public(), es256stdsig, es256jwsig}, -+ {"RS256", rs256phead, testKey.Public(), testsig, testsig}, -+ } -+ for _, tc := range tt { -+ tc := tc -+ t.Run(tc.alg, func(t *testing.T) { -+ stdsig, err := base64.RawStdEncoding.DecodeString(tc.stdsig) -+ if err != nil { -+ t.Errorf("couldn't decode test vector: %v", err) -+ } -+ signer := &customTestSigner{ -+ sig: stdsig, -+ pub: tc.pub, -+ } -+ -+ b, err := jwsEncodeJSON(claims, signer, noKeyID, "nonce", "url") -+ if err != nil { -+ t.Fatal(err) -+ } -+ var j jsonWebSignature -+ if err := json.Unmarshal(b, &j); err != nil { -+ t.Fatal(err) -+ } -+ if j.Protected != tc.phead { -+ t.Errorf("j.Protected = %q\nwant %q", j.Protected, tc.phead) -+ } -+ if j.Payload != payload { -+ t.Errorf("j.Payload = %q\nwant %q", j.Payload, payload) -+ } -+ if j.Sig != tc.jwsig { -+ t.Errorf("j.Sig = %q\nwant %q", j.Sig, tc.jwsig) -+ } -+ }) -+ } -+} -+ -+func TestJWSWithMAC(t *testing.T) { -+ // Example from RFC 7520 Section 4.4.3. -+ // https://tools.ietf.org/html/rfc7520#section-4.4.3 -+ b64Key := "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg" -+ rawPayload := []byte("It\xe2\x80\x99s a dangerous business, Frodo, going out your " + -+ "door. You step onto the road, and if you don't keep your feet, " + -+ "there\xe2\x80\x99s no knowing where you might be swept off " + -+ "to.") -+ protected := "eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LW" + -+ "VlZjMxNGJjNzAzNyJ9" -+ payload := "SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywg" + -+ "Z29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9h" + -+ "ZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXi" + -+ "gJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9m" + -+ "ZiB0by4" -+ sig := "s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0" -+ -+ key, err := base64.RawURLEncoding.DecodeString(b64Key) -+ if err != nil { -+ t.Fatalf("unable to decode key: %q", b64Key) -+ } -+ got, err := jwsWithMAC(key, "018c0ae5-4d9b-471b-bfd6-eef314bc7037", "", rawPayload) -+ if err != nil { -+ t.Fatalf("jwsWithMAC() = %q", err) -+ } -+ if got.Protected != protected { -+ t.Errorf("got.Protected = %q\nwant %q", got.Protected, protected) -+ } -+ if got.Payload != payload { -+ t.Errorf("got.Payload = %q\nwant %q", got.Payload, payload) -+ } -+ if got.Sig != sig { -+ t.Errorf("got.Signature = %q\nwant %q", got.Sig, sig) -+ } -+} -+ -+func TestJWSWithMACError(t *testing.T) { -+ p := "{}" -+ if _, err := jwsWithMAC(nil, "", "", []byte(p)); err == nil { -+ t.Errorf("jwsWithMAC(nil, ...) = success; want err") -+ } -+} -+ -+func TestJWKThumbprintRSA(t *testing.T) { -+ // Key example from RFC 7638 -+ const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" + -+ "VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" + -+ "4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" + -+ "W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" + -+ "1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" + -+ "aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw" -+ const base64E = "AQAB" -+ const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" -+ -+ b, err := base64.RawURLEncoding.DecodeString(base64N) -+ if err != nil { -+ t.Fatalf("Error parsing example key N: %v", err) -+ } -+ n := new(big.Int).SetBytes(b) -+ -+ b, err = base64.RawURLEncoding.DecodeString(base64E) -+ if err != nil { -+ t.Fatalf("Error parsing example key E: %v", err) -+ } -+ e := new(big.Int).SetBytes(b) -+ -+ pub := &rsa.PublicKey{N: n, E: int(e.Uint64())} -+ th, err := JWKThumbprint(pub) -+ if err != nil { -+ t.Error(err) -+ } -+ if th != expected { -+ t.Errorf("thumbprint = %q; want %q", th, expected) -+ } -+} -+ -+func TestJWKThumbprintEC(t *testing.T) { -+ // Key example from RFC 7520 -+ // expected was computed with -+ // printf '{"crv":"P-521","kty":"EC","x":"","y":""}' | \ -+ // openssl dgst -binary -sha256 | b64raw -+ const ( -+ base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" + -+ "KqjqvjyekWF-7ytDyRXYgCF5cj0Kt" -+ base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" + -+ "QkAgDPrwQrJmbnX9cwlGfP-HqHZR1" -+ expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M" -+ ) -+ -+ b, err := base64.RawURLEncoding.DecodeString(base64X) -+ if err != nil { -+ t.Fatalf("Error parsing example key X: %v", err) -+ } -+ x := new(big.Int).SetBytes(b) -+ -+ b, err = base64.RawURLEncoding.DecodeString(base64Y) -+ if err != nil { -+ t.Fatalf("Error parsing example key Y: %v", err) -+ } -+ y := new(big.Int).SetBytes(b) -+ -+ pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y} -+ th, err := JWKThumbprint(pub) -+ if err != nil { -+ t.Error(err) -+ } -+ if th != expected { -+ t.Errorf("thumbprint = %q; want %q", th, expected) -+ } -+} -+ -+func TestJWKThumbprintErrUnsupportedKey(t *testing.T) { -+ _, err := JWKThumbprint(struct{}{}) -+ if err != ErrUnsupportedKey { -+ t.Errorf("err = %q; want %q", err, ErrUnsupportedKey) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/rfc8555.go b/ms_mod/golang.org/x/crypto/acme/rfc8555.go -new file mode 100644 -index 00000000000000..3152e531b65cf4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/rfc8555.go -@@ -0,0 +1,476 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "context" -+ "crypto" -+ "encoding/base64" -+ "encoding/json" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "io" -+ "net/http" -+ "time" -+) -+ -+// DeactivateReg permanently disables an existing account associated with c.Key. -+// A deactivated account can no longer request certificate issuance or access -+// resources related to the account, such as orders or authorizations. -+// -+// It only works with CAs implementing RFC 8555. -+func (c *Client) DeactivateReg(ctx context.Context) error { -+ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID -+ return err -+ } -+ url := string(c.accountKID(ctx)) -+ if url == "" { -+ return ErrNoAccount -+ } -+ req := json.RawMessage(`{"status": "deactivated"}`) -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return err -+ } -+ res.Body.Close() -+ return nil -+} -+ -+// registerRFC is equivalent to c.Register but for CAs implementing RFC 8555. -+// It expects c.Discover to have already been called. -+func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) { -+ c.cacheMu.Lock() // guard c.kid access -+ defer c.cacheMu.Unlock() -+ -+ req := struct { -+ TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"` -+ Contact []string `json:"contact,omitempty"` -+ ExternalAccountBinding *jsonWebSignature `json:"externalAccountBinding,omitempty"` -+ }{ -+ Contact: acct.Contact, -+ } -+ if c.dir.Terms != "" { -+ req.TermsAgreed = prompt(c.dir.Terms) -+ } -+ -+ // set 'externalAccountBinding' field if requested -+ if acct.ExternalAccountBinding != nil { -+ eabJWS, err := c.encodeExternalAccountBinding(acct.ExternalAccountBinding) -+ if err != nil { -+ return nil, fmt.Errorf("acme: failed to encode external account binding: %v", err) -+ } -+ req.ExternalAccountBinding = eabJWS -+ } -+ -+ res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus( -+ http.StatusOK, // account with this key already registered -+ http.StatusCreated, // new account created -+ )) -+ if err != nil { -+ return nil, err -+ } -+ -+ defer res.Body.Close() -+ a, err := responseAccount(res) -+ if err != nil { -+ return nil, err -+ } -+ // Cache Account URL even if we return an error to the caller. -+ // It is by all means a valid and usable "kid" value for future requests. -+ c.KID = KeyID(a.URI) -+ if res.StatusCode == http.StatusOK { -+ return nil, ErrAccountAlreadyExists -+ } -+ return a, nil -+} -+ -+// encodeExternalAccountBinding will encode an external account binding stanza -+// as described in https://tools.ietf.org/html/rfc8555#section-7.3.4. -+func (c *Client) encodeExternalAccountBinding(eab *ExternalAccountBinding) (*jsonWebSignature, error) { -+ jwk, err := jwkEncode(c.Key.Public()) -+ if err != nil { -+ return nil, err -+ } -+ return jwsWithMAC(eab.Key, eab.KID, c.dir.RegURL, []byte(jwk)) -+} -+ -+// updateRegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555. -+// It expects c.Discover to have already been called. -+func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) { -+ url := string(c.accountKID(ctx)) -+ if url == "" { -+ return nil, ErrNoAccount -+ } -+ req := struct { -+ Contact []string `json:"contact,omitempty"` -+ }{ -+ Contact: a.Contact, -+ } -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ return responseAccount(res) -+} -+ -+// getRegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555. -+// It expects c.Discover to have already been called. -+func (c *Client) getRegRFC(ctx context.Context) (*Account, error) { -+ req := json.RawMessage(`{"onlyReturnExisting": true}`) -+ res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK)) -+ if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" { -+ return nil, ErrNoAccount -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ defer res.Body.Close() -+ return responseAccount(res) -+} -+ -+func responseAccount(res *http.Response) (*Account, error) { -+ var v struct { -+ Status string -+ Contact []string -+ Orders string -+ } -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: invalid account response: %v", err) -+ } -+ return &Account{ -+ URI: res.Header.Get("Location"), -+ Status: v.Status, -+ Contact: v.Contact, -+ OrdersURL: v.Orders, -+ }, nil -+} -+ -+// accountKeyRollover attempts to perform account key rollover. -+// On success it will change client.Key to the new key. -+func (c *Client) accountKeyRollover(ctx context.Context, newKey crypto.Signer) error { -+ dir, err := c.Discover(ctx) // Also required by c.accountKID -+ if err != nil { -+ return err -+ } -+ kid := c.accountKID(ctx) -+ if kid == noKeyID { -+ return ErrNoAccount -+ } -+ oldKey, err := jwkEncode(c.Key.Public()) -+ if err != nil { -+ return err -+ } -+ payload := struct { -+ Account string `json:"account"` -+ OldKey json.RawMessage `json:"oldKey"` -+ }{ -+ Account: string(kid), -+ OldKey: json.RawMessage(oldKey), -+ } -+ inner, err := jwsEncodeJSON(payload, newKey, noKeyID, noNonce, dir.KeyChangeURL) -+ if err != nil { -+ return err -+ } -+ -+ res, err := c.post(ctx, nil, dir.KeyChangeURL, base64.RawURLEncoding.EncodeToString(inner), wantStatus(http.StatusOK)) -+ if err != nil { -+ return err -+ } -+ defer res.Body.Close() -+ c.Key = newKey -+ return nil -+} -+ -+// AuthorizeOrder initiates the order-based application for certificate issuance, -+// as opposed to pre-authorization in Authorize. -+// It is only supported by CAs implementing RFC 8555. -+// -+// The caller then needs to fetch each authorization with GetAuthorization, -+// identify those with StatusPending status and fulfill a challenge using Accept. -+// Once all authorizations are satisfied, the caller will typically want to poll -+// order status using WaitOrder until it's in StatusReady state. -+// To finalize the order and obtain a certificate, the caller submits a CSR with CreateOrderCert. -+func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error) { -+ dir, err := c.Discover(ctx) -+ if err != nil { -+ return nil, err -+ } -+ -+ req := struct { -+ Identifiers []wireAuthzID `json:"identifiers"` -+ NotBefore string `json:"notBefore,omitempty"` -+ NotAfter string `json:"notAfter,omitempty"` -+ }{} -+ for _, v := range id { -+ req.Identifiers = append(req.Identifiers, wireAuthzID{ -+ Type: v.Type, -+ Value: v.Value, -+ }) -+ } -+ for _, o := range opt { -+ switch o := o.(type) { -+ case orderNotBeforeOpt: -+ req.NotBefore = time.Time(o).Format(time.RFC3339) -+ case orderNotAfterOpt: -+ req.NotAfter = time.Time(o).Format(time.RFC3339) -+ default: -+ // Package's fault if we let this happen. -+ panic(fmt.Sprintf("unsupported order option type %T", o)) -+ } -+ } -+ -+ res, err := c.post(ctx, nil, dir.OrderURL, req, wantStatus(http.StatusCreated)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ return responseOrder(res) -+} -+ -+// GetOrder retrives an order identified by the given URL. -+// For orders created with AuthorizeOrder, the url value is Order.URI. -+// -+// If a caller needs to poll an order until its status is final, -+// see the WaitOrder method. -+func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ return responseOrder(res) -+} -+ -+// WaitOrder polls an order from the given URL until it is in one of the final states, -+// StatusReady, StatusValid or StatusInvalid, the CA responded with a non-retryable error -+// or the context is done. -+// -+// It returns a non-nil Order only if its Status is StatusReady or StatusValid. -+// In all other cases WaitOrder returns an error. -+// If the Status is StatusInvalid, the returned error is of type *OrderError. -+func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) { -+ if _, err := c.Discover(ctx); err != nil { -+ return nil, err -+ } -+ for { -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ o, err := responseOrder(res) -+ res.Body.Close() -+ switch { -+ case err != nil: -+ // Skip and retry. -+ case o.Status == StatusInvalid: -+ return nil, &OrderError{OrderURL: o.URI, Status: o.Status} -+ case o.Status == StatusReady || o.Status == StatusValid: -+ return o, nil -+ } -+ -+ d := retryAfter(res.Header.Get("Retry-After")) -+ if d == 0 { -+ // Default retry-after. -+ // Same reasoning as in WaitAuthorization. -+ d = time.Second -+ } -+ t := time.NewTimer(d) -+ select { -+ case <-ctx.Done(): -+ t.Stop() -+ return nil, ctx.Err() -+ case <-t.C: -+ // Retry. -+ } -+ } -+} -+ -+func responseOrder(res *http.Response) (*Order, error) { -+ var v struct { -+ Status string -+ Expires time.Time -+ Identifiers []wireAuthzID -+ NotBefore time.Time -+ NotAfter time.Time -+ Error *wireError -+ Authorizations []string -+ Finalize string -+ Certificate string -+ } -+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil { -+ return nil, fmt.Errorf("acme: error reading order: %v", err) -+ } -+ o := &Order{ -+ URI: res.Header.Get("Location"), -+ Status: v.Status, -+ Expires: v.Expires, -+ NotBefore: v.NotBefore, -+ NotAfter: v.NotAfter, -+ AuthzURLs: v.Authorizations, -+ FinalizeURL: v.Finalize, -+ CertURL: v.Certificate, -+ } -+ for _, id := range v.Identifiers { -+ o.Identifiers = append(o.Identifiers, AuthzID{Type: id.Type, Value: id.Value}) -+ } -+ if v.Error != nil { -+ o.Error = v.Error.error(nil /* headers */) -+ } -+ return o, nil -+} -+ -+// CreateOrderCert submits the CSR (Certificate Signing Request) to a CA at the specified URL. -+// The URL is the FinalizeURL field of an Order created with AuthorizeOrder. -+// -+// If the bundle argument is true, the returned value also contain the CA (issuer) -+// certificate chain. Otherwise, only a leaf certificate is returned. -+// The returned URL can be used to re-fetch the certificate using FetchCert. -+// -+// This method is only supported by CAs implementing RFC 8555. See CreateCert for pre-RFC CAs. -+// -+// CreateOrderCert returns an error if the CA's response is unreasonably large. -+// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features. -+func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) { -+ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID -+ return nil, "", err -+ } -+ -+ // RFC describes this as "finalize order" request. -+ req := struct { -+ CSR string `json:"csr"` -+ }{ -+ CSR: base64.RawURLEncoding.EncodeToString(csr), -+ } -+ res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, "", err -+ } -+ defer res.Body.Close() -+ o, err := responseOrder(res) -+ if err != nil { -+ return nil, "", err -+ } -+ -+ // Wait for CA to issue the cert if they haven't. -+ if o.Status != StatusValid { -+ o, err = c.WaitOrder(ctx, o.URI) -+ } -+ if err != nil { -+ return nil, "", err -+ } -+ // The only acceptable status post finalize and WaitOrder is "valid". -+ if o.Status != StatusValid { -+ return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status} -+ } -+ crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle) -+ return crt, o.CertURL, err -+} -+ -+// fetchCertRFC downloads issued certificate from the given URL. -+// It expects the CA to respond with PEM-encoded certificate chain. -+// -+// The URL argument is the CertURL field of Order. -+func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][]byte, error) { -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ // Get all the bytes up to a sane maximum. -+ // Account very roughly for base64 overhead. -+ const max = maxCertChainSize + maxCertChainSize/33 -+ b, err := io.ReadAll(io.LimitReader(res.Body, max+1)) -+ if err != nil { -+ return nil, fmt.Errorf("acme: fetch cert response stream: %v", err) -+ } -+ if len(b) > max { -+ return nil, errors.New("acme: certificate chain is too big") -+ } -+ -+ // Decode PEM chain. -+ var chain [][]byte -+ for { -+ var p *pem.Block -+ p, b = pem.Decode(b) -+ if p == nil { -+ break -+ } -+ if p.Type != "CERTIFICATE" { -+ return nil, fmt.Errorf("acme: invalid PEM cert type %q", p.Type) -+ } -+ -+ chain = append(chain, p.Bytes) -+ if !bundle { -+ return chain, nil -+ } -+ if len(chain) > maxChainLen { -+ return nil, errors.New("acme: certificate chain is too long") -+ } -+ } -+ if len(chain) == 0 { -+ return nil, errors.New("acme: certificate chain is empty") -+ } -+ return chain, nil -+} -+ -+// sends a cert revocation request in either JWK form when key is non-nil or KID form otherwise. -+func (c *Client) revokeCertRFC(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { -+ req := &struct { -+ Cert string `json:"certificate"` -+ Reason int `json:"reason"` -+ }{ -+ Cert: base64.RawURLEncoding.EncodeToString(cert), -+ Reason: int(reason), -+ } -+ res, err := c.post(ctx, key, c.dir.RevokeURL, req, wantStatus(http.StatusOK)) -+ if err != nil { -+ if isAlreadyRevoked(err) { -+ // Assume it is not an error to revoke an already revoked cert. -+ return nil -+ } -+ return err -+ } -+ defer res.Body.Close() -+ return nil -+} -+ -+func isAlreadyRevoked(err error) bool { -+ e, ok := err.(*Error) -+ return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked" -+} -+ -+// ListCertAlternates retrieves any alternate certificate chain URLs for the -+// given certificate chain URL. These alternate URLs can be passed to FetchCert -+// in order to retrieve the alternate certificate chains. -+// -+// If there are no alternate issuer certificate chains, a nil slice will be -+// returned. -+func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) { -+ if _, err := c.Discover(ctx); err != nil { // required by c.accountKID -+ return nil, err -+ } -+ -+ res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) -+ if err != nil { -+ return nil, err -+ } -+ defer res.Body.Close() -+ -+ // We don't need the body but we need to discard it so we don't end up -+ // preventing keep-alive -+ if _, err := io.Copy(io.Discard, res.Body); err != nil { -+ return nil, fmt.Errorf("acme: cert alternates response stream: %v", err) -+ } -+ alts := linkHeader(res.Header, "alternate") -+ return alts, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/rfc8555_test.go b/ms_mod/golang.org/x/crypto/acme/rfc8555_test.go -new file mode 100644 -index 00000000000000..d65720a356e81a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/rfc8555_test.go -@@ -0,0 +1,1017 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "bytes" -+ "context" -+ "crypto/hmac" -+ "crypto/rand" -+ "crypto/sha256" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/base64" -+ "encoding/json" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ "net/http" -+ "net/http/httptest" -+ "reflect" -+ "strings" -+ "sync" -+ "testing" -+ "time" -+) -+ -+// While contents of this file is pertinent only to RFC8555, -+// it is complementary to the tests in the other _test.go files -+// many of which are valid for both pre- and RFC8555. -+// This will make it easier to clean up the tests once non-RFC compliant -+// code is removed. -+ -+func TestRFC_Discover(t *testing.T) { -+ const ( -+ nonce = "https://example.com/acme/new-nonce" -+ reg = "https://example.com/acme/new-acct" -+ order = "https://example.com/acme/new-order" -+ authz = "https://example.com/acme/new-authz" -+ revoke = "https://example.com/acme/revoke-cert" -+ keychange = "https://example.com/acme/key-change" -+ metaTerms = "https://example.com/acme/terms/2017-5-30" -+ metaWebsite = "https://www.example.com/" -+ metaCAA = "example.com" -+ ) -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Content-Type", "application/json") -+ fmt.Fprintf(w, `{ -+ "newNonce": %q, -+ "newAccount": %q, -+ "newOrder": %q, -+ "newAuthz": %q, -+ "revokeCert": %q, -+ "keyChange": %q, -+ "meta": { -+ "termsOfService": %q, -+ "website": %q, -+ "caaIdentities": [%q], -+ "externalAccountRequired": true -+ } -+ }`, nonce, reg, order, authz, revoke, keychange, metaTerms, metaWebsite, metaCAA) -+ })) -+ defer ts.Close() -+ c := &Client{DirectoryURL: ts.URL} -+ dir, err := c.Discover(context.Background()) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if dir.NonceURL != nonce { -+ t.Errorf("dir.NonceURL = %q; want %q", dir.NonceURL, nonce) -+ } -+ if dir.RegURL != reg { -+ t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg) -+ } -+ if dir.OrderURL != order { -+ t.Errorf("dir.OrderURL = %q; want %q", dir.OrderURL, order) -+ } -+ if dir.AuthzURL != authz { -+ t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz) -+ } -+ if dir.RevokeURL != revoke { -+ t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke) -+ } -+ if dir.KeyChangeURL != keychange { -+ t.Errorf("dir.KeyChangeURL = %q; want %q", dir.KeyChangeURL, keychange) -+ } -+ if dir.Terms != metaTerms { -+ t.Errorf("dir.Terms = %q; want %q", dir.Terms, metaTerms) -+ } -+ if dir.Website != metaWebsite { -+ t.Errorf("dir.Website = %q; want %q", dir.Website, metaWebsite) -+ } -+ if len(dir.CAA) == 0 || dir.CAA[0] != metaCAA { -+ t.Errorf("dir.CAA = %q; want [%q]", dir.CAA, metaCAA) -+ } -+ if !dir.ExternalAccountRequired { -+ t.Error("dir.Meta.ExternalAccountRequired is false") -+ } -+} -+ -+func TestRFC_popNonce(t *testing.T) { -+ var count int -+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ // The Client uses only Directory.NonceURL when specified. -+ // Expect no other URL paths. -+ if r.URL.Path != "/new-nonce" { -+ t.Errorf("r.URL.Path = %q; want /new-nonce", r.URL.Path) -+ } -+ if count > 0 { -+ w.WriteHeader(http.StatusTooManyRequests) -+ return -+ } -+ count++ -+ w.Header().Set("Replay-Nonce", "second") -+ })) -+ cl := &Client{ -+ DirectoryURL: ts.URL, -+ dir: &Directory{NonceURL: ts.URL + "/new-nonce"}, -+ } -+ cl.addNonce(http.Header{"Replay-Nonce": {"first"}}) -+ -+ for i, nonce := range []string{"first", "second"} { -+ v, err := cl.popNonce(context.Background(), "") -+ if err != nil { -+ t.Errorf("%d: cl.popNonce: %v", i, err) -+ } -+ if v != nonce { -+ t.Errorf("%d: cl.popNonce = %q; want %q", i, v, nonce) -+ } -+ } -+ // No more nonces and server replies with an error past first nonce fetch. -+ // Expected to fail. -+ if _, err := cl.popNonce(context.Background(), ""); err == nil { -+ t.Error("last cl.popNonce returned nil error") -+ } -+} -+ -+func TestRFC_postKID(t *testing.T) { -+ var ts *httptest.Server -+ ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ switch r.URL.Path { -+ case "/new-nonce": -+ w.Header().Set("Replay-Nonce", "nonce") -+ case "/new-account": -+ w.Header().Set("Location", "/account-1") -+ w.Write([]byte(`{"status":"valid"}`)) -+ case "/post": -+ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx -+ head, err := decodeJWSHead(bytes.NewReader(b)) -+ if err != nil { -+ t.Errorf("decodeJWSHead: %v", err) -+ return -+ } -+ if head.KID != "/account-1" { -+ t.Errorf("head.KID = %q; want /account-1", head.KID) -+ } -+ if len(head.JWK) != 0 { -+ t.Errorf("head.JWK = %q; want zero map", head.JWK) -+ } -+ if v := ts.URL + "/post"; head.URL != v { -+ t.Errorf("head.URL = %q; want %q", head.URL, v) -+ } -+ -+ var payload struct{ Msg string } -+ decodeJWSRequest(t, &payload, bytes.NewReader(b)) -+ if payload.Msg != "ping" { -+ t.Errorf("payload.Msg = %q; want ping", payload.Msg) -+ } -+ w.Write([]byte("pong")) -+ default: -+ t.Errorf("unhandled %s %s", r.Method, r.URL) -+ w.WriteHeader(http.StatusBadRequest) -+ } -+ })) -+ defer ts.Close() -+ -+ ctx := context.Background() -+ cl := &Client{ -+ Key: testKey, -+ DirectoryURL: ts.URL, -+ dir: &Directory{ -+ NonceURL: ts.URL + "/new-nonce", -+ RegURL: ts.URL + "/new-account", -+ OrderURL: "/force-rfc-mode", -+ }, -+ } -+ req := json.RawMessage(`{"msg":"ping"}`) -+ res, err := cl.post(ctx, nil /* use kid */, ts.URL+"/post", req, wantStatus(http.StatusOK)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer res.Body.Close() -+ b, _ := io.ReadAll(res.Body) // don't care about err - just checking b -+ if string(b) != "pong" { -+ t.Errorf("res.Body = %q; want pong", b) -+ } -+} -+ -+// acmeServer simulates a subset of RFC 8555 compliant CA. -+// -+// TODO: We also have x/crypto/acme/autocert/acmetest and startACMEServerStub in autocert_test.go. -+// It feels like this acmeServer is a sweet spot between usefulness and added complexity. -+// Also, acmetest and startACMEServerStub were both written for draft-02, no RFC support. -+// The goal is to consolidate all into one ACME test server. -+type acmeServer struct { -+ ts *httptest.Server -+ handler map[string]http.HandlerFunc // keyed by r.URL.Path -+ -+ mu sync.Mutex -+ nnonce int -+} -+ -+func newACMEServer() *acmeServer { -+ return &acmeServer{handler: make(map[string]http.HandlerFunc)} -+} -+ -+func (s *acmeServer) handle(path string, f func(http.ResponseWriter, *http.Request)) { -+ s.handler[path] = http.HandlerFunc(f) -+} -+ -+func (s *acmeServer) start() { -+ s.ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Content-Type", "application/json") -+ -+ // Directory request. -+ if r.URL.Path == "/" { -+ fmt.Fprintf(w, `{ -+ "newNonce": %q, -+ "newAccount": %q, -+ "newOrder": %q, -+ "newAuthz": %q, -+ "revokeCert": %q, -+ "keyChange": %q, -+ "meta": {"termsOfService": %q} -+ }`, -+ s.url("/acme/new-nonce"), -+ s.url("/acme/new-account"), -+ s.url("/acme/new-order"), -+ s.url("/acme/new-authz"), -+ s.url("/acme/revoke-cert"), -+ s.url("/acme/key-change"), -+ s.url("/terms"), -+ ) -+ return -+ } -+ -+ // All other responses contain a nonce value unconditionally. -+ w.Header().Set("Replay-Nonce", s.nonce()) -+ if r.URL.Path == "/acme/new-nonce" { -+ return -+ } -+ -+ h := s.handler[r.URL.Path] -+ if h == nil { -+ w.WriteHeader(http.StatusBadRequest) -+ fmt.Fprintf(w, "Unhandled %s", r.URL.Path) -+ return -+ } -+ h.ServeHTTP(w, r) -+ })) -+} -+ -+func (s *acmeServer) close() { -+ s.ts.Close() -+} -+ -+func (s *acmeServer) url(path string) string { -+ return s.ts.URL + path -+} -+ -+func (s *acmeServer) nonce() string { -+ s.mu.Lock() -+ defer s.mu.Unlock() -+ s.nnonce++ -+ return fmt.Sprintf("nonce%d", s.nnonce) -+} -+ -+func (s *acmeServer) error(w http.ResponseWriter, e *wireError) { -+ w.WriteHeader(e.Status) -+ json.NewEncoder(w).Encode(e) -+} -+ -+func TestRFC_Register(t *testing.T) { -+ const email = "mailto:user@example.org" -+ -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusCreated) // 201 means new account created -+ fmt.Fprintf(w, `{ -+ "status": "valid", -+ "contact": [%q], -+ "orders": %q -+ }`, email, s.url("/accounts/1/orders")) -+ -+ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx -+ head, err := decodeJWSHead(bytes.NewReader(b)) -+ if err != nil { -+ t.Errorf("decodeJWSHead: %v", err) -+ return -+ } -+ if len(head.JWK) == 0 { -+ t.Error("head.JWK is empty") -+ } -+ -+ var req struct{ Contact []string } -+ decodeJWSRequest(t, &req, bytes.NewReader(b)) -+ if len(req.Contact) != 1 || req.Contact[0] != email { -+ t.Errorf("req.Contact = %q; want [%q]", req.Contact, email) -+ } -+ }) -+ s.start() -+ defer s.close() -+ -+ ctx := context.Background() -+ cl := &Client{ -+ Key: testKeyEC, -+ DirectoryURL: s.url("/"), -+ } -+ -+ var didPrompt bool -+ a := &Account{Contact: []string{email}} -+ acct, err := cl.Register(ctx, a, func(tos string) bool { -+ didPrompt = true -+ terms := s.url("/terms") -+ if tos != terms { -+ t.Errorf("tos = %q; want %q", tos, terms) -+ } -+ return true -+ }) -+ if err != nil { -+ t.Fatal(err) -+ } -+ okAccount := &Account{ -+ URI: s.url("/accounts/1"), -+ Status: StatusValid, -+ Contact: []string{email}, -+ OrdersURL: s.url("/accounts/1/orders"), -+ } -+ if !reflect.DeepEqual(acct, okAccount) { -+ t.Errorf("acct = %+v; want %+v", acct, okAccount) -+ } -+ if !didPrompt { -+ t.Error("tos prompt wasn't called") -+ } -+ if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) { -+ t.Errorf("account kid = %q; want %q", v, okAccount.URI) -+ } -+} -+ -+func TestRFC_RegisterExternalAccountBinding(t *testing.T) { -+ eab := &ExternalAccountBinding{ -+ KID: "kid-1", -+ Key: []byte("secret"), -+ } -+ -+ type protected struct { -+ Algorithm string `json:"alg"` -+ KID string `json:"kid"` -+ URL string `json:"url"` -+ } -+ const email = "mailto:user@example.org" -+ -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ if r.Method != "POST" { -+ t.Errorf("r.Method = %q; want POST", r.Method) -+ } -+ -+ var j struct { -+ Protected string -+ Contact []string -+ TermsOfServiceAgreed bool -+ ExternalaccountBinding struct { -+ Protected string -+ Payload string -+ Signature string -+ } -+ } -+ decodeJWSRequest(t, &j, r.Body) -+ protData, err := base64.RawURLEncoding.DecodeString(j.ExternalaccountBinding.Protected) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ var prot protected -+ err = json.Unmarshal(protData, &prot) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if !reflect.DeepEqual(j.Contact, []string{email}) { -+ t.Errorf("j.Contact = %v; want %v", j.Contact, []string{email}) -+ } -+ if !j.TermsOfServiceAgreed { -+ t.Error("j.TermsOfServiceAgreed = false; want true") -+ } -+ -+ // Ensure same KID. -+ if prot.KID != eab.KID { -+ t.Errorf("j.ExternalAccountBinding.KID = %s; want %s", prot.KID, eab.KID) -+ } -+ // Ensure expected Algorithm. -+ if prot.Algorithm != "HS256" { -+ t.Errorf("j.ExternalAccountBinding.Alg = %s; want %s", -+ prot.Algorithm, "HS256") -+ } -+ -+ // Ensure same URL as outer JWS. -+ url := fmt.Sprintf("http://%s/acme/new-account", r.Host) -+ if prot.URL != url { -+ t.Errorf("j.ExternalAccountBinding.URL = %s; want %s", -+ prot.URL, url) -+ } -+ -+ // Ensure payload is base64URL encoded string of JWK in outer JWS -+ jwk, err := jwkEncode(testKeyEC.Public()) -+ if err != nil { -+ t.Fatal(err) -+ } -+ decodedPayload, err := base64.RawURLEncoding.DecodeString(j.ExternalaccountBinding.Payload) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if jwk != string(decodedPayload) { -+ t.Errorf("j.ExternalAccountBinding.Payload = %s; want %s", decodedPayload, jwk) -+ } -+ -+ // Check signature on inner external account binding JWS -+ hmac := hmac.New(sha256.New, []byte("secret")) -+ _, err = hmac.Write([]byte(j.ExternalaccountBinding.Protected + "." + j.ExternalaccountBinding.Payload)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ mac := hmac.Sum(nil) -+ encodedMAC := base64.RawURLEncoding.EncodeToString(mac) -+ -+ if !bytes.Equal([]byte(encodedMAC), []byte(j.ExternalaccountBinding.Signature)) { -+ t.Errorf("j.ExternalAccountBinding.Signature = %v; want %v", -+ []byte(j.ExternalaccountBinding.Signature), encodedMAC) -+ } -+ -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusCreated) -+ b, _ := json.Marshal([]string{email}) -+ fmt.Fprintf(w, `{"status":"valid","orders":"%s","contact":%s}`, s.url("/accounts/1/orders"), b) -+ }) -+ s.start() -+ defer s.close() -+ -+ ctx := context.Background() -+ cl := &Client{ -+ Key: testKeyEC, -+ DirectoryURL: s.url("/"), -+ } -+ -+ var didPrompt bool -+ a := &Account{Contact: []string{email}, ExternalAccountBinding: eab} -+ acct, err := cl.Register(ctx, a, func(tos string) bool { -+ didPrompt = true -+ terms := s.url("/terms") -+ if tos != terms { -+ t.Errorf("tos = %q; want %q", tos, terms) -+ } -+ return true -+ }) -+ if err != nil { -+ t.Fatal(err) -+ } -+ okAccount := &Account{ -+ URI: s.url("/accounts/1"), -+ Status: StatusValid, -+ Contact: []string{email}, -+ OrdersURL: s.url("/accounts/1/orders"), -+ } -+ if !reflect.DeepEqual(acct, okAccount) { -+ t.Errorf("acct = %+v; want %+v", acct, okAccount) -+ } -+ if !didPrompt { -+ t.Error("tos prompt wasn't called") -+ } -+ if v := cl.accountKID(ctx); v != KeyID(okAccount.URI) { -+ t.Errorf("account kid = %q; want %q", v, okAccount.URI) -+ } -+} -+ -+func TestRFC_RegisterExisting(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) // 200 means account already exists -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ _, err := cl.Register(context.Background(), &Account{}, AcceptTOS) -+ if err != ErrAccountAlreadyExists { -+ t.Errorf("err = %v; want %v", err, ErrAccountAlreadyExists) -+ } -+ kid := KeyID(s.url("/accounts/1")) -+ if v := cl.accountKID(context.Background()); v != kid { -+ t.Errorf("account kid = %q; want %q", v, kid) -+ } -+} -+ -+func TestRFC_UpdateReg(t *testing.T) { -+ const email = "mailto:user@example.org" -+ -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ var didUpdate bool -+ s.handle("/accounts/1", func(w http.ResponseWriter, r *http.Request) { -+ didUpdate = true -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ -+ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx -+ head, err := decodeJWSHead(bytes.NewReader(b)) -+ if err != nil { -+ t.Errorf("decodeJWSHead: %v", err) -+ return -+ } -+ if len(head.JWK) != 0 { -+ t.Error("head.JWK is non-zero") -+ } -+ kid := s.url("/accounts/1") -+ if head.KID != kid { -+ t.Errorf("head.KID = %q; want %q", head.KID, kid) -+ } -+ -+ var req struct{ Contact []string } -+ decodeJWSRequest(t, &req, bytes.NewReader(b)) -+ if len(req.Contact) != 1 || req.Contact[0] != email { -+ t.Errorf("req.Contact = %q; want [%q]", req.Contact, email) -+ } -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ _, err := cl.UpdateReg(context.Background(), &Account{Contact: []string{email}}) -+ if err != nil { -+ t.Error(err) -+ } -+ if !didUpdate { -+ t.Error("UpdateReg didn't update the account") -+ } -+} -+ -+func TestRFC_GetReg(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ -+ head, err := decodeJWSHead(r.Body) -+ if err != nil { -+ t.Errorf("decodeJWSHead: %v", err) -+ return -+ } -+ if len(head.JWK) == 0 { -+ t.Error("head.JWK is empty") -+ } -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ acct, err := cl.GetReg(context.Background(), "") -+ if err != nil { -+ t.Fatal(err) -+ } -+ okAccount := &Account{ -+ URI: s.url("/accounts/1"), -+ Status: StatusValid, -+ } -+ if !reflect.DeepEqual(acct, okAccount) { -+ t.Errorf("acct = %+v; want %+v", acct, okAccount) -+ } -+} -+ -+func TestRFC_GetRegNoAccount(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ s.error(w, &wireError{ -+ Status: http.StatusBadRequest, -+ Type: "urn:ietf:params:acme:error:accountDoesNotExist", -+ }) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ if _, err := cl.GetReg(context.Background(), ""); err != ErrNoAccount { -+ t.Errorf("err = %v; want %v", err, ErrNoAccount) -+ } -+} -+ -+func TestRFC_GetRegOtherError(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.WriteHeader(http.StatusBadRequest) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ if _, err := cl.GetReg(context.Background(), ""); err == nil || err == ErrNoAccount { -+ t.Errorf("GetReg: %v; want any other non-nil err", err) -+ } -+} -+ -+func TestRFC_AccountKeyRollover(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ s.handle("/acme/key-change", func(w http.ResponseWriter, r *http.Request) { -+ w.WriteHeader(http.StatusOK) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ if err := cl.AccountKeyRollover(context.Background(), testKeyEC384); err != nil { -+ t.Errorf("AccountKeyRollover: %v, wanted no error", err) -+ } else if cl.Key != testKeyEC384 { -+ t.Error("AccountKeyRollover did not rotate the client key") -+ } -+} -+ -+func TestRFC_DeactivateReg(t *testing.T) { -+ const email = "mailto:user@example.org" -+ curStatus := StatusValid -+ -+ type account struct { -+ Status string `json:"status"` -+ Contact []string `json:"contact"` -+ AcceptTOS bool `json:"termsOfServiceAgreed"` -+ Orders string `json:"orders"` -+ } -+ -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) // 200 means existing account -+ json.NewEncoder(w).Encode(account{ -+ Status: curStatus, -+ Contact: []string{email}, -+ AcceptTOS: true, -+ Orders: s.url("/accounts/1/orders"), -+ }) -+ -+ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx -+ head, err := decodeJWSHead(bytes.NewReader(b)) -+ if err != nil { -+ t.Errorf("decodeJWSHead: %v", err) -+ return -+ } -+ if len(head.JWK) == 0 { -+ t.Error("head.JWK is empty") -+ } -+ -+ var req struct { -+ Status string `json:"status"` -+ Contact []string `json:"contact"` -+ AcceptTOS bool `json:"termsOfServiceAgreed"` -+ OnlyExisting bool `json:"onlyReturnExisting"` -+ } -+ decodeJWSRequest(t, &req, bytes.NewReader(b)) -+ if !req.OnlyExisting { -+ t.Errorf("req.OnlyReturnExisting = %t; want = %t", req.OnlyExisting, true) -+ } -+ }) -+ s.handle("/accounts/1", func(w http.ResponseWriter, r *http.Request) { -+ if curStatus == StatusValid { -+ curStatus = StatusDeactivated -+ w.WriteHeader(http.StatusOK) -+ } else { -+ s.error(w, &wireError{ -+ Status: http.StatusUnauthorized, -+ Type: "urn:ietf:params:acme:error:unauthorized", -+ }) -+ } -+ var req account -+ b, _ := io.ReadAll(r.Body) // check err later in decodeJWSxxx -+ head, err := decodeJWSHead(bytes.NewReader(b)) -+ if err != nil { -+ t.Errorf("decodeJWSHead: %v", err) -+ return -+ } -+ if len(head.JWK) != 0 { -+ t.Error("head.JWK is not empty") -+ } -+ if !strings.HasSuffix(head.KID, "/accounts/1") { -+ t.Errorf("head.KID = %q; want suffix /accounts/1", head.KID) -+ } -+ -+ decodeJWSRequest(t, &req, bytes.NewReader(b)) -+ if req.Status != StatusDeactivated { -+ t.Errorf("req.Status = %q; want = %q", req.Status, StatusDeactivated) -+ } -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ if err := cl.DeactivateReg(context.Background()); err != nil { -+ t.Errorf("DeactivateReg: %v, wanted no error", err) -+ } -+ if err := cl.DeactivateReg(context.Background()); err == nil { -+ t.Errorf("DeactivateReg: %v, wanted error for unauthorized", err) -+ } -+} -+ -+func TestRF_DeactivateRegNoAccount(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ s.error(w, &wireError{ -+ Status: http.StatusBadRequest, -+ Type: "urn:ietf:params:acme:error:accountDoesNotExist", -+ }) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ if err := cl.DeactivateReg(context.Background()); !errors.Is(err, ErrNoAccount) { -+ t.Errorf("DeactivateReg: %v, wanted ErrNoAccount", err) -+ } -+} -+ -+func TestRFC_AuthorizeOrder(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ s.handle("/acme/new-order", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/orders/1")) -+ w.WriteHeader(http.StatusCreated) -+ fmt.Fprintf(w, `{ -+ "status": "pending", -+ "expires": "2019-09-01T00:00:00Z", -+ "notBefore": "2019-08-31T00:00:00Z", -+ "notAfter": "2019-09-02T00:00:00Z", -+ "identifiers": [{"type":"dns", "value":"example.org"}], -+ "authorizations": [%q] -+ }`, s.url("/authz/1")) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ o, err := cl.AuthorizeOrder(context.Background(), DomainIDs("example.org"), -+ WithOrderNotBefore(time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC)), -+ WithOrderNotAfter(time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC)), -+ ) -+ if err != nil { -+ t.Fatal(err) -+ } -+ okOrder := &Order{ -+ URI: s.url("/orders/1"), -+ Status: StatusPending, -+ Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC), -+ NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC), -+ NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC), -+ Identifiers: []AuthzID{AuthzID{Type: "dns", Value: "example.org"}}, -+ AuthzURLs: []string{s.url("/authz/1")}, -+ } -+ if !reflect.DeepEqual(o, okOrder) { -+ t.Errorf("AuthorizeOrder = %+v; want %+v", o, okOrder) -+ } -+} -+ -+func TestRFC_GetOrder(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/orders/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{ -+ "status": "invalid", -+ "expires": "2019-09-01T00:00:00Z", -+ "notBefore": "2019-08-31T00:00:00Z", -+ "notAfter": "2019-09-02T00:00:00Z", -+ "identifiers": [{"type":"dns", "value":"example.org"}], -+ "authorizations": ["/authz/1"], -+ "finalize": "/orders/1/fin", -+ "certificate": "/orders/1/cert", -+ "error": {"type": "badRequest"} -+ }`)) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ o, err := cl.GetOrder(context.Background(), s.url("/orders/1")) -+ if err != nil { -+ t.Fatal(err) -+ } -+ okOrder := &Order{ -+ URI: s.url("/orders/1"), -+ Status: StatusInvalid, -+ Expires: time.Date(2019, 9, 1, 0, 0, 0, 0, time.UTC), -+ NotBefore: time.Date(2019, 8, 31, 0, 0, 0, 0, time.UTC), -+ NotAfter: time.Date(2019, 9, 2, 0, 0, 0, 0, time.UTC), -+ Identifiers: []AuthzID{AuthzID{Type: "dns", Value: "example.org"}}, -+ AuthzURLs: []string{"/authz/1"}, -+ FinalizeURL: "/orders/1/fin", -+ CertURL: "/orders/1/cert", -+ Error: &Error{ProblemType: "badRequest"}, -+ } -+ if !reflect.DeepEqual(o, okOrder) { -+ t.Errorf("GetOrder = %+v\nwant %+v", o, okOrder) -+ } -+} -+ -+func TestRFC_WaitOrder(t *testing.T) { -+ for _, st := range []string{StatusReady, StatusValid} { -+ t.Run(st, func(t *testing.T) { -+ testWaitOrderStatus(t, st) -+ }) -+ } -+} -+ -+func testWaitOrderStatus(t *testing.T, okStatus string) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ var count int -+ s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/orders/1")) -+ w.WriteHeader(http.StatusOK) -+ s := StatusPending -+ if count > 0 { -+ s = okStatus -+ } -+ fmt.Fprintf(w, `{"status": %q}`, s) -+ count++ -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ order, err := cl.WaitOrder(context.Background(), s.url("/orders/1")) -+ if err != nil { -+ t.Fatalf("WaitOrder: %v", err) -+ } -+ if order.Status != okStatus { -+ t.Errorf("order.Status = %q; want %q", order.Status, okStatus) -+ } -+} -+ -+func TestRFC_WaitOrderError(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.WriteHeader(http.StatusOK) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ var count int -+ s.handle("/orders/1", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/orders/1")) -+ w.WriteHeader(http.StatusOK) -+ s := StatusPending -+ if count > 0 { -+ s = StatusInvalid -+ } -+ fmt.Fprintf(w, `{"status": %q}`, s) -+ count++ -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ _, err := cl.WaitOrder(context.Background(), s.url("/orders/1")) -+ if err == nil { -+ t.Fatal("WaitOrder returned nil error") -+ } -+ e, ok := err.(*OrderError) -+ if !ok { -+ t.Fatalf("err = %v (%T); want OrderError", err, err) -+ } -+ if e.OrderURL != s.url("/orders/1") { -+ t.Errorf("e.OrderURL = %q; want %q", e.OrderURL, s.url("/orders/1")) -+ } -+ if e.Status != StatusInvalid { -+ t.Errorf("e.Status = %q; want %q", e.Status, StatusInvalid) -+ } -+} -+ -+func TestRFC_CreateOrderCert(t *testing.T) { -+ q := &x509.CertificateRequest{ -+ Subject: pkix.Name{CommonName: "example.org"}, -+ } -+ csr, err := x509.CreateCertificateRequest(rand.Reader, q, testKeyEC) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ tmpl := &x509.Certificate{SerialNumber: big.NewInt(1)} -+ leaf, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testKeyEC.PublicKey, testKeyEC) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ s := newACMEServer() -+ s.handle("/acme/new-account", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/accounts/1")) -+ w.Write([]byte(`{"status": "valid"}`)) -+ }) -+ var count int -+ s.handle("/pleaseissue", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Location", s.url("/pleaseissue")) -+ st := StatusProcessing -+ if count > 0 { -+ st = StatusValid -+ } -+ fmt.Fprintf(w, `{"status":%q, "certificate":%q}`, st, s.url("/crt")) -+ count++ -+ }) -+ s.handle("/crt", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Content-Type", "application/pem-certificate-chain") -+ pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: leaf}) -+ }) -+ s.start() -+ defer s.close() -+ ctx := context.Background() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ cert, curl, err := cl.CreateOrderCert(ctx, s.url("/pleaseissue"), csr, true) -+ if err != nil { -+ t.Fatalf("CreateOrderCert: %v", err) -+ } -+ if _, err := x509.ParseCertificate(cert[0]); err != nil { -+ t.Errorf("ParseCertificate: %v", err) -+ } -+ if !reflect.DeepEqual(cert[0], leaf) { -+ t.Errorf("cert and leaf bytes don't match") -+ } -+ if u := s.url("/crt"); curl != u { -+ t.Errorf("curl = %q; want %q", curl, u) -+ } -+} -+ -+func TestRFC_AlreadyRevokedCert(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/acme/revoke-cert", func(w http.ResponseWriter, r *http.Request) { -+ s.error(w, &wireError{ -+ Status: http.StatusBadRequest, -+ Type: "urn:ietf:params:acme:error:alreadyRevoked", -+ }) -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ err := cl.RevokeCert(context.Background(), testKeyEC, []byte{0}, CRLReasonUnspecified) -+ if err != nil { -+ t.Fatalf("RevokeCert: %v", err) -+ } -+} -+ -+func TestRFC_ListCertAlternates(t *testing.T) { -+ s := newACMEServer() -+ s.handle("/crt", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Content-Type", "application/pem-certificate-chain") -+ w.Header().Add("Link", `;rel="alternate"`) -+ w.Header().Add("Link", `; rel="alternate"`) -+ w.Header().Add("Link", `; rel="index"`) -+ }) -+ s.handle("/crt2", func(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Content-Type", "application/pem-certificate-chain") -+ }) -+ s.start() -+ defer s.close() -+ -+ cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")} -+ crts, err := cl.ListCertAlternates(context.Background(), s.url("/crt")) -+ if err != nil { -+ t.Fatalf("ListCertAlternates: %v", err) -+ } -+ want := []string{"https://example.com/crt/2", "https://example.com/crt/3"} -+ if !reflect.DeepEqual(crts, want) { -+ t.Errorf("ListCertAlternates(/crt): %v; want %v", crts, want) -+ } -+ crts, err = cl.ListCertAlternates(context.Background(), s.url("/crt2")) -+ if err != nil { -+ t.Fatalf("ListCertAlternates: %v", err) -+ } -+ if crts != nil { -+ t.Errorf("ListCertAlternates(/crt2): %v; want nil", crts) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/types.go b/ms_mod/golang.org/x/crypto/acme/types.go -new file mode 100644 -index 00000000000000..4888726fecdea8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/types.go -@@ -0,0 +1,614 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "crypto" -+ "crypto/x509" -+ "errors" -+ "fmt" -+ "net/http" -+ "strings" -+ "time" -+) -+ -+// ACME status values of Account, Order, Authorization and Challenge objects. -+// See https://tools.ietf.org/html/rfc8555#section-7.1.6 for details. -+const ( -+ StatusDeactivated = "deactivated" -+ StatusExpired = "expired" -+ StatusInvalid = "invalid" -+ StatusPending = "pending" -+ StatusProcessing = "processing" -+ StatusReady = "ready" -+ StatusRevoked = "revoked" -+ StatusUnknown = "unknown" -+ StatusValid = "valid" -+) -+ -+// CRLReasonCode identifies the reason for a certificate revocation. -+type CRLReasonCode int -+ -+// CRL reason codes as defined in RFC 5280. -+const ( -+ CRLReasonUnspecified CRLReasonCode = 0 -+ CRLReasonKeyCompromise CRLReasonCode = 1 -+ CRLReasonCACompromise CRLReasonCode = 2 -+ CRLReasonAffiliationChanged CRLReasonCode = 3 -+ CRLReasonSuperseded CRLReasonCode = 4 -+ CRLReasonCessationOfOperation CRLReasonCode = 5 -+ CRLReasonCertificateHold CRLReasonCode = 6 -+ CRLReasonRemoveFromCRL CRLReasonCode = 8 -+ CRLReasonPrivilegeWithdrawn CRLReasonCode = 9 -+ CRLReasonAACompromise CRLReasonCode = 10 -+) -+ -+var ( -+ // ErrUnsupportedKey is returned when an unsupported key type is encountered. -+ ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported") -+ -+ // ErrAccountAlreadyExists indicates that the Client's key has already been registered -+ // with the CA. It is returned by Register method. -+ ErrAccountAlreadyExists = errors.New("acme: account already exists") -+ -+ // ErrNoAccount indicates that the Client's key has not been registered with the CA. -+ ErrNoAccount = errors.New("acme: account does not exist") -+) -+ -+// A Subproblem describes an ACME subproblem as reported in an Error. -+type Subproblem struct { -+ // Type is a URI reference that identifies the problem type, -+ // typically in a "urn:acme:error:xxx" form. -+ Type string -+ // Detail is a human-readable explanation specific to this occurrence of the problem. -+ Detail string -+ // Instance indicates a URL that the client should direct a human user to visit -+ // in order for instructions on how to agree to the updated Terms of Service. -+ // In such an event CA sets StatusCode to 403, Type to -+ // "urn:ietf:params:acme:error:userActionRequired", and adds a Link header with relation -+ // "terms-of-service" containing the latest TOS URL. -+ Instance string -+ // Identifier may contain the ACME identifier that the error is for. -+ Identifier *AuthzID -+} -+ -+func (sp Subproblem) String() string { -+ str := fmt.Sprintf("%s: ", sp.Type) -+ if sp.Identifier != nil { -+ str += fmt.Sprintf("[%s: %s] ", sp.Identifier.Type, sp.Identifier.Value) -+ } -+ str += sp.Detail -+ return str -+} -+ -+// Error is an ACME error, defined in Problem Details for HTTP APIs doc -+// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem. -+type Error struct { -+ // StatusCode is The HTTP status code generated by the origin server. -+ StatusCode int -+ // ProblemType is a URI reference that identifies the problem type, -+ // typically in a "urn:acme:error:xxx" form. -+ ProblemType string -+ // Detail is a human-readable explanation specific to this occurrence of the problem. -+ Detail string -+ // Instance indicates a URL that the client should direct a human user to visit -+ // in order for instructions on how to agree to the updated Terms of Service. -+ // In such an event CA sets StatusCode to 403, ProblemType to -+ // "urn:ietf:params:acme:error:userActionRequired" and a Link header with relation -+ // "terms-of-service" containing the latest TOS URL. -+ Instance string -+ // Header is the original server error response headers. -+ // It may be nil. -+ Header http.Header -+ // Subproblems may contain more detailed information about the individual problems -+ // that caused the error. This field is only sent by RFC 8555 compatible ACME -+ // servers. Defined in RFC 8555 Section 6.7.1. -+ Subproblems []Subproblem -+} -+ -+func (e *Error) Error() string { -+ str := fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail) -+ if len(e.Subproblems) > 0 { -+ str += fmt.Sprintf("; subproblems:") -+ for _, sp := range e.Subproblems { -+ str += fmt.Sprintf("\n\t%s", sp) -+ } -+ } -+ return str -+} -+ -+// AuthorizationError indicates that an authorization for an identifier -+// did not succeed. -+// It contains all errors from Challenge items of the failed Authorization. -+type AuthorizationError struct { -+ // URI uniquely identifies the failed Authorization. -+ URI string -+ -+ // Identifier is an AuthzID.Value of the failed Authorization. -+ Identifier string -+ -+ // Errors is a collection of non-nil error values of Challenge items -+ // of the failed Authorization. -+ Errors []error -+} -+ -+func (a *AuthorizationError) Error() string { -+ e := make([]string, len(a.Errors)) -+ for i, err := range a.Errors { -+ e[i] = err.Error() -+ } -+ -+ if a.Identifier != "" { -+ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; ")) -+ } -+ -+ return fmt.Sprintf("acme: authorization error: %s", strings.Join(e, "; ")) -+} -+ -+// OrderError is returned from Client's order related methods. -+// It indicates the order is unusable and the clients should start over with -+// AuthorizeOrder. -+// -+// The clients can still fetch the order object from CA using GetOrder -+// to inspect its state. -+type OrderError struct { -+ OrderURL string -+ Status string -+} -+ -+func (oe *OrderError) Error() string { -+ return fmt.Sprintf("acme: order %s status: %s", oe.OrderURL, oe.Status) -+} -+ -+// RateLimit reports whether err represents a rate limit error and -+// any Retry-After duration returned by the server. -+// -+// See the following for more details on rate limiting: -+// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6 -+func RateLimit(err error) (time.Duration, bool) { -+ e, ok := err.(*Error) -+ if !ok { -+ return 0, false -+ } -+ // Some CA implementations may return incorrect values. -+ // Use case-insensitive comparison. -+ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") { -+ return 0, false -+ } -+ if e.Header == nil { -+ return 0, true -+ } -+ return retryAfter(e.Header.Get("Retry-After")), true -+} -+ -+// Account is a user account. It is associated with a private key. -+// Non-RFC 8555 fields are empty when interfacing with a compliant CA. -+type Account struct { -+ // URI is the account unique ID, which is also a URL used to retrieve -+ // account data from the CA. -+ // When interfacing with RFC 8555-compliant CAs, URI is the "kid" field -+ // value in JWS signed requests. -+ URI string -+ -+ // Contact is a slice of contact info used during registration. -+ // See https://tools.ietf.org/html/rfc8555#section-7.3 for supported -+ // formats. -+ Contact []string -+ -+ // Status indicates current account status as returned by the CA. -+ // Possible values are StatusValid, StatusDeactivated, and StatusRevoked. -+ Status string -+ -+ // OrdersURL is a URL from which a list of orders submitted by this account -+ // can be fetched. -+ OrdersURL string -+ -+ // The terms user has agreed to. -+ // A value not matching CurrentTerms indicates that the user hasn't agreed -+ // to the actual Terms of Service of the CA. -+ // -+ // It is non-RFC 8555 compliant. Package users can store the ToS they agree to -+ // during Client's Register call in the prompt callback function. -+ AgreedTerms string -+ -+ // Actual terms of a CA. -+ // -+ // It is non-RFC 8555 compliant. Use Directory's Terms field. -+ // When a CA updates their terms and requires an account agreement, -+ // a URL at which instructions to do so is available in Error's Instance field. -+ CurrentTerms string -+ -+ // Authz is the authorization URL used to initiate a new authz flow. -+ // -+ // It is non-RFC 8555 compliant. Use Directory's AuthzURL or OrderURL. -+ Authz string -+ -+ // Authorizations is a URI from which a list of authorizations -+ // granted to this account can be fetched via a GET request. -+ // -+ // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. -+ Authorizations string -+ -+ // Certificates is a URI from which a list of certificates -+ // issued for this account can be fetched via a GET request. -+ // -+ // It is non-RFC 8555 compliant and is obsoleted by OrdersURL. -+ Certificates string -+ -+ // ExternalAccountBinding represents an arbitrary binding to an account of -+ // the CA which the ACME server is tied to. -+ // See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. -+ ExternalAccountBinding *ExternalAccountBinding -+} -+ -+// ExternalAccountBinding contains the data needed to form a request with -+// an external account binding. -+// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details. -+type ExternalAccountBinding struct { -+ // KID is the Key ID of the symmetric MAC key that the CA provides to -+ // identify an external account from ACME. -+ KID string -+ -+ // Key is the bytes of the symmetric key that the CA provides to identify -+ // the account. Key must correspond to the KID. -+ Key []byte -+} -+ -+func (e *ExternalAccountBinding) String() string { -+ return fmt.Sprintf("&{KID: %q, Key: redacted}", e.KID) -+} -+ -+// Directory is ACME server discovery data. -+// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details. -+type Directory struct { -+ // NonceURL indicates an endpoint where to fetch fresh nonce values from. -+ NonceURL string -+ -+ // RegURL is an account endpoint URL, allowing for creating new accounts. -+ // Pre-RFC 8555 CAs also allow modifying existing accounts at this URL. -+ RegURL string -+ -+ // OrderURL is used to initiate the certificate issuance flow -+ // as described in RFC 8555. -+ OrderURL string -+ -+ // AuthzURL is used to initiate identifier pre-authorization flow. -+ // Empty string indicates the flow is unsupported by the CA. -+ AuthzURL string -+ -+ // CertURL is a new certificate issuance endpoint URL. -+ // It is non-RFC 8555 compliant and is obsoleted by OrderURL. -+ CertURL string -+ -+ // RevokeURL is used to initiate a certificate revocation flow. -+ RevokeURL string -+ -+ // KeyChangeURL allows to perform account key rollover flow. -+ KeyChangeURL string -+ -+ // Term is a URI identifying the current terms of service. -+ Terms string -+ -+ // Website is an HTTP or HTTPS URL locating a website -+ // providing more information about the ACME server. -+ Website string -+ -+ // CAA consists of lowercase hostname elements, which the ACME server -+ // recognises as referring to itself for the purposes of CAA record validation -+ // as defined in RFC 6844. -+ CAA []string -+ -+ // ExternalAccountRequired indicates that the CA requires for all account-related -+ // requests to include external account binding information. -+ ExternalAccountRequired bool -+} -+ -+// Order represents a client's request for a certificate. -+// It tracks the request flow progress through to issuance. -+type Order struct { -+ // URI uniquely identifies an order. -+ URI string -+ -+ // Status represents the current status of the order. -+ // It indicates which action the client should take. -+ // -+ // Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid. -+ // Pending means the CA does not believe that the client has fulfilled the requirements. -+ // Ready indicates that the client has fulfilled all the requirements and can submit a CSR -+ // to obtain a certificate. This is done with Client's CreateOrderCert. -+ // Processing means the certificate is being issued. -+ // Valid indicates the CA has issued the certificate. It can be downloaded -+ // from the Order's CertURL. This is done with Client's FetchCert. -+ // Invalid means the certificate will not be issued. Users should consider this order -+ // abandoned. -+ Status string -+ -+ // Expires is the timestamp after which CA considers this order invalid. -+ Expires time.Time -+ -+ // Identifiers contains all identifier objects which the order pertains to. -+ Identifiers []AuthzID -+ -+ // NotBefore is the requested value of the notBefore field in the certificate. -+ NotBefore time.Time -+ -+ // NotAfter is the requested value of the notAfter field in the certificate. -+ NotAfter time.Time -+ -+ // AuthzURLs represents authorizations to complete before a certificate -+ // for identifiers specified in the order can be issued. -+ // It also contains unexpired authorizations that the client has completed -+ // in the past. -+ // -+ // Authorization objects can be fetched using Client's GetAuthorization method. -+ // -+ // The required authorizations are dictated by CA policies. -+ // There may not be a 1:1 relationship between the identifiers and required authorizations. -+ // Required authorizations can be identified by their StatusPending status. -+ // -+ // For orders in the StatusValid or StatusInvalid state these are the authorizations -+ // which were completed. -+ AuthzURLs []string -+ -+ // FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate -+ // once all the authorizations are satisfied. -+ FinalizeURL string -+ -+ // CertURL points to the certificate that has been issued in response to this order. -+ CertURL string -+ -+ // The error that occurred while processing the order as received from a CA, if any. -+ Error *Error -+} -+ -+// OrderOption allows customizing Client.AuthorizeOrder call. -+type OrderOption interface { -+ privateOrderOpt() -+} -+ -+// WithOrderNotBefore sets order's NotBefore field. -+func WithOrderNotBefore(t time.Time) OrderOption { -+ return orderNotBeforeOpt(t) -+} -+ -+// WithOrderNotAfter sets order's NotAfter field. -+func WithOrderNotAfter(t time.Time) OrderOption { -+ return orderNotAfterOpt(t) -+} -+ -+type orderNotBeforeOpt time.Time -+ -+func (orderNotBeforeOpt) privateOrderOpt() {} -+ -+type orderNotAfterOpt time.Time -+ -+func (orderNotAfterOpt) privateOrderOpt() {} -+ -+// Authorization encodes an authorization response. -+type Authorization struct { -+ // URI uniquely identifies a authorization. -+ URI string -+ -+ // Status is the current status of an authorization. -+ // Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated, -+ // StatusExpired and StatusRevoked. -+ Status string -+ -+ // Identifier is what the account is authorized to represent. -+ Identifier AuthzID -+ -+ // The timestamp after which the CA considers the authorization invalid. -+ Expires time.Time -+ -+ // Wildcard is true for authorizations of a wildcard domain name. -+ Wildcard bool -+ -+ // Challenges that the client needs to fulfill in order to prove possession -+ // of the identifier (for pending authorizations). -+ // For valid authorizations, the challenge that was validated. -+ // For invalid authorizations, the challenge that was attempted and failed. -+ // -+ // RFC 8555 compatible CAs require users to fuflfill only one of the challenges. -+ Challenges []*Challenge -+ -+ // A collection of sets of challenges, each of which would be sufficient -+ // to prove possession of the identifier. -+ // Clients must complete a set of challenges that covers at least one set. -+ // Challenges are identified by their indices in the challenges array. -+ // If this field is empty, the client needs to complete all challenges. -+ // -+ // This field is unused in RFC 8555. -+ Combinations [][]int -+} -+ -+// AuthzID is an identifier that an account is authorized to represent. -+type AuthzID struct { -+ Type string // The type of identifier, "dns" or "ip". -+ Value string // The identifier itself, e.g. "example.org". -+} -+ -+// DomainIDs creates a slice of AuthzID with "dns" identifier type. -+func DomainIDs(names ...string) []AuthzID { -+ a := make([]AuthzID, len(names)) -+ for i, v := range names { -+ a[i] = AuthzID{Type: "dns", Value: v} -+ } -+ return a -+} -+ -+// IPIDs creates a slice of AuthzID with "ip" identifier type. -+// Each element of addr is textual form of an address as defined -+// in RFC 1123 Section 2.1 for IPv4 and in RFC 5952 Section 4 for IPv6. -+func IPIDs(addr ...string) []AuthzID { -+ a := make([]AuthzID, len(addr)) -+ for i, v := range addr { -+ a[i] = AuthzID{Type: "ip", Value: v} -+ } -+ return a -+} -+ -+// wireAuthzID is ACME JSON representation of authorization identifier objects. -+type wireAuthzID struct { -+ Type string `json:"type"` -+ Value string `json:"value"` -+} -+ -+// wireAuthz is ACME JSON representation of Authorization objects. -+type wireAuthz struct { -+ Identifier wireAuthzID -+ Status string -+ Expires time.Time -+ Wildcard bool -+ Challenges []wireChallenge -+ Combinations [][]int -+ Error *wireError -+} -+ -+func (z *wireAuthz) authorization(uri string) *Authorization { -+ a := &Authorization{ -+ URI: uri, -+ Status: z.Status, -+ Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, -+ Expires: z.Expires, -+ Wildcard: z.Wildcard, -+ Challenges: make([]*Challenge, len(z.Challenges)), -+ Combinations: z.Combinations, // shallow copy -+ } -+ for i, v := range z.Challenges { -+ a.Challenges[i] = v.challenge() -+ } -+ return a -+} -+ -+func (z *wireAuthz) error(uri string) *AuthorizationError { -+ err := &AuthorizationError{ -+ URI: uri, -+ Identifier: z.Identifier.Value, -+ } -+ -+ if z.Error != nil { -+ err.Errors = append(err.Errors, z.Error.error(nil)) -+ } -+ -+ for _, raw := range z.Challenges { -+ if raw.Error != nil { -+ err.Errors = append(err.Errors, raw.Error.error(nil)) -+ } -+ } -+ -+ return err -+} -+ -+// Challenge encodes a returned CA challenge. -+// Its Error field may be non-nil if the challenge is part of an Authorization -+// with StatusInvalid. -+type Challenge struct { -+ // Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01". -+ Type string -+ -+ // URI is where a challenge response can be posted to. -+ URI string -+ -+ // Token is a random value that uniquely identifies the challenge. -+ Token string -+ -+ // Status identifies the status of this challenge. -+ // In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid, -+ // and StatusInvalid. -+ Status string -+ -+ // Validated is the time at which the CA validated this challenge. -+ // Always zero value in pre-RFC 8555. -+ Validated time.Time -+ -+ // Error indicates the reason for an authorization failure -+ // when this challenge was used. -+ // The type of a non-nil value is *Error. -+ Error error -+} -+ -+// wireChallenge is ACME JSON challenge representation. -+type wireChallenge struct { -+ URL string `json:"url"` // RFC -+ URI string `json:"uri"` // pre-RFC -+ Type string -+ Token string -+ Status string -+ Validated time.Time -+ Error *wireError -+} -+ -+func (c *wireChallenge) challenge() *Challenge { -+ v := &Challenge{ -+ URI: c.URL, -+ Type: c.Type, -+ Token: c.Token, -+ Status: c.Status, -+ } -+ if v.URI == "" { -+ v.URI = c.URI // c.URL was empty; use legacy -+ } -+ if v.Status == "" { -+ v.Status = StatusPending -+ } -+ if c.Error != nil { -+ v.Error = c.Error.error(nil) -+ } -+ return v -+} -+ -+// wireError is a subset of fields of the Problem Details object -+// as described in https://tools.ietf.org/html/rfc7807#section-3.1. -+type wireError struct { -+ Status int -+ Type string -+ Detail string -+ Instance string -+ Subproblems []Subproblem -+} -+ -+func (e *wireError) error(h http.Header) *Error { -+ err := &Error{ -+ StatusCode: e.Status, -+ ProblemType: e.Type, -+ Detail: e.Detail, -+ Instance: e.Instance, -+ Header: h, -+ Subproblems: e.Subproblems, -+ } -+ return err -+} -+ -+// CertOption is an optional argument type for the TLS ChallengeCert methods for -+// customizing a temporary certificate for TLS-based challenges. -+type CertOption interface { -+ privateCertOpt() -+} -+ -+// WithKey creates an option holding a private/public key pair. -+// The private part signs a certificate, and the public part represents the signee. -+func WithKey(key crypto.Signer) CertOption { -+ return &certOptKey{key} -+} -+ -+type certOptKey struct { -+ key crypto.Signer -+} -+ -+func (*certOptKey) privateCertOpt() {} -+ -+// WithTemplate creates an option for specifying a certificate template. -+// See x509.CreateCertificate for template usage details. -+// -+// In TLS ChallengeCert methods, the template is also used as parent, -+// resulting in a self-signed certificate. -+// The DNSNames field of t is always overwritten for tls-sni challenge certs. -+func WithTemplate(t *x509.Certificate) CertOption { -+ return (*certOptTemplate)(t) -+} -+ -+type certOptTemplate x509.Certificate -+ -+func (*certOptTemplate) privateCertOpt() {} -diff --git a/ms_mod/golang.org/x/crypto/acme/types_test.go b/ms_mod/golang.org/x/crypto/acme/types_test.go -new file mode 100644 -index 00000000000000..59ce7e7602ca31 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/types_test.go -@@ -0,0 +1,219 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package acme -+ -+import ( -+ "errors" -+ "net/http" -+ "reflect" -+ "testing" -+ "time" -+) -+ -+func TestExternalAccountBindingString(t *testing.T) { -+ eab := ExternalAccountBinding{ -+ KID: "kid", -+ Key: []byte("key"), -+ } -+ got := eab.String() -+ want := `&{KID: "kid", Key: redacted}` -+ if got != want { -+ t.Errorf("eab.String() = %q, want: %q", got, want) -+ } -+} -+ -+func TestRateLimit(t *testing.T) { -+ now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC) -+ f := timeNow -+ defer func() { timeNow = f }() -+ timeNow = func() time.Time { return now } -+ -+ h120, hTime := http.Header{}, http.Header{} -+ h120.Set("Retry-After", "120") -+ hTime.Set("Retry-After", "Tue Apr 27 11:00:00 2017") -+ -+ err1 := &Error{ -+ ProblemType: "urn:ietf:params:acme:error:nolimit", -+ Header: h120, -+ } -+ err2 := &Error{ -+ ProblemType: "urn:ietf:params:acme:error:rateLimited", -+ Header: h120, -+ } -+ err3 := &Error{ -+ ProblemType: "urn:ietf:params:acme:error:rateLimited", -+ Header: nil, -+ } -+ err4 := &Error{ -+ ProblemType: "urn:ietf:params:acme:error:rateLimited", -+ Header: hTime, -+ } -+ -+ tt := []struct { -+ err error -+ res time.Duration -+ ok bool -+ }{ -+ {nil, 0, false}, -+ {errors.New("dummy"), 0, false}, -+ {err1, 0, false}, -+ {err2, 2 * time.Minute, true}, -+ {err3, 0, true}, -+ {err4, time.Hour, true}, -+ } -+ for i, test := range tt { -+ res, ok := RateLimit(test.err) -+ if ok != test.ok { -+ t.Errorf("%d: RateLimit(%+v): ok = %v; want %v", i, test.err, ok, test.ok) -+ continue -+ } -+ if res != test.res { -+ t.Errorf("%d: RateLimit(%+v) = %v; want %v", i, test.err, res, test.res) -+ } -+ } -+} -+ -+func TestAuthorizationError(t *testing.T) { -+ tests := []struct { -+ desc string -+ err *AuthorizationError -+ msg string -+ }{ -+ { -+ desc: "when auth error identifier is set", -+ err: &AuthorizationError{ -+ Identifier: "domain.com", -+ Errors: []error{ -+ (&wireError{ -+ Status: 403, -+ Type: "urn:ietf:params:acme:error:caa", -+ Detail: "CAA record for domain.com prevents issuance", -+ }).error(nil), -+ }, -+ }, -+ msg: "acme: authorization error for domain.com: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance", -+ }, -+ -+ { -+ desc: "when auth error identifier is unset", -+ err: &AuthorizationError{ -+ Errors: []error{ -+ (&wireError{ -+ Status: 403, -+ Type: "urn:ietf:params:acme:error:caa", -+ Detail: "CAA record for domain.com prevents issuance", -+ }).error(nil), -+ }, -+ }, -+ msg: "acme: authorization error: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance", -+ }, -+ } -+ -+ for _, tt := range tests { -+ if tt.err.Error() != tt.msg { -+ t.Errorf("got: %s\nwant: %s", tt.err, tt.msg) -+ } -+ } -+} -+ -+func TestSubproblems(t *testing.T) { -+ tests := []struct { -+ wire wireError -+ expectedOut Error -+ }{ -+ { -+ wire: wireError{ -+ Status: 1, -+ Type: "urn:error", -+ Detail: "it's an error", -+ }, -+ expectedOut: Error{ -+ StatusCode: 1, -+ ProblemType: "urn:error", -+ Detail: "it's an error", -+ }, -+ }, -+ { -+ wire: wireError{ -+ Status: 1, -+ Type: "urn:error", -+ Detail: "it's an error", -+ Subproblems: []Subproblem{ -+ { -+ Type: "urn:error:sub", -+ Detail: "it's a subproblem", -+ }, -+ }, -+ }, -+ expectedOut: Error{ -+ StatusCode: 1, -+ ProblemType: "urn:error", -+ Detail: "it's an error", -+ Subproblems: []Subproblem{ -+ { -+ Type: "urn:error:sub", -+ Detail: "it's a subproblem", -+ }, -+ }, -+ }, -+ }, -+ { -+ wire: wireError{ -+ Status: 1, -+ Type: "urn:error", -+ Detail: "it's an error", -+ Subproblems: []Subproblem{ -+ { -+ Type: "urn:error:sub", -+ Detail: "it's a subproblem", -+ Identifier: &AuthzID{Type: "dns", Value: "example"}, -+ }, -+ }, -+ }, -+ expectedOut: Error{ -+ StatusCode: 1, -+ ProblemType: "urn:error", -+ Detail: "it's an error", -+ Subproblems: []Subproblem{ -+ { -+ Type: "urn:error:sub", -+ Detail: "it's a subproblem", -+ Identifier: &AuthzID{Type: "dns", Value: "example"}, -+ }, -+ }, -+ }, -+ }, -+ } -+ -+ for _, tc := range tests { -+ out := tc.wire.error(nil) -+ if !reflect.DeepEqual(*out, tc.expectedOut) { -+ t.Errorf("Unexpected error: wanted %v, got %v", tc.expectedOut, *out) -+ } -+ } -+} -+ -+func TestErrorStringerWithSubproblems(t *testing.T) { -+ err := Error{ -+ StatusCode: 1, -+ ProblemType: "urn:error", -+ Detail: "it's an error", -+ Subproblems: []Subproblem{ -+ { -+ Type: "urn:error:sub", -+ Detail: "it's a subproblem", -+ }, -+ { -+ Type: "urn:error:sub", -+ Detail: "it's a subproblem", -+ Identifier: &AuthzID{Type: "dns", Value: "example"}, -+ }, -+ }, -+ } -+ expectedStr := "1 urn:error: it's an error; subproblems:\n\turn:error:sub: it's a subproblem\n\turn:error:sub: [dns: example] it's a subproblem" -+ if err.Error() != expectedStr { -+ t.Errorf("Unexpected error string: wanted %q, got %q", expectedStr, err.Error()) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/acme/version_go112.go b/ms_mod/golang.org/x/crypto/acme/version_go112.go -new file mode 100644 -index 00000000000000..b9efdb59e5851c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/acme/version_go112.go -@@ -0,0 +1,28 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.12 -+// +build go1.12 -+ -+package acme -+ -+import "runtime/debug" -+ -+func init() { -+ // Set packageVersion if the binary was built in modules mode and x/crypto -+ // was not replaced with a different module. -+ info, ok := debug.ReadBuildInfo() -+ if !ok { -+ return -+ } -+ for _, m := range info.Deps { -+ if m.Path != "golang.org/x/crypto" { -+ continue -+ } -+ if m.Replace == nil { -+ packageVersion = m.Version -+ } -+ break -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/argon2/argon2.go b/ms_mod/golang.org/x/crypto/argon2/argon2.go -new file mode 100644 -index 00000000000000..29f0a2de4514b6 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/argon2.go -@@ -0,0 +1,283 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package argon2 implements the key derivation function Argon2. -+// Argon2 was selected as the winner of the Password Hashing Competition and can -+// be used to derive cryptographic keys from passwords. -+// -+// For a detailed specification of Argon2 see [1]. -+// -+// If you aren't sure which function you need, use Argon2id (IDKey) and -+// the parameter recommendations for your scenario. -+// -+// # Argon2i -+// -+// Argon2i (implemented by Key) is the side-channel resistant version of Argon2. -+// It uses data-independent memory access, which is preferred for password -+// hashing and password-based key derivation. Argon2i requires more passes over -+// memory than Argon2id to protect from trade-off attacks. The recommended -+// parameters (taken from [2]) for non-interactive operations are time=3 and to -+// use the maximum available memory. -+// -+// # Argon2id -+// -+// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining -+// Argon2i and Argon2d. It uses data-independent memory access for the first -+// half of the first iteration over the memory and data-dependent memory access -+// for the rest. Argon2id is side-channel resistant and provides better brute- -+// force cost savings due to time-memory tradeoffs than Argon2i. The recommended -+// parameters for non-interactive operations (taken from [2]) are time=1 and to -+// use the maximum available memory. -+// -+// [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf -+// [2] https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03#section-9.3 -+package argon2 -+ -+import ( -+ "encoding/binary" -+ "sync" -+ -+ "golang.org/x/crypto/blake2b" -+) -+ -+// The Argon2 version implemented by this package. -+const Version = 0x13 -+ -+const ( -+ argon2d = iota -+ argon2i -+ argon2id -+) -+ -+// Key derives a key from the password, salt, and cost parameters using Argon2i -+// returning a byte slice of length keyLen that can be used as cryptographic -+// key. The CPU cost and parallelism degree must be greater than zero. -+// -+// For example, you can get a derived key for e.g. AES-256 (which needs a -+// 32-byte key) by doing: -+// -+// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32) -+// -+// The draft RFC recommends[2] time=3, and memory=32*1024 is a sensible number. -+// If using that amount of memory (32 MB) is not possible in some contexts then -+// the time parameter can be increased to compensate. -+// -+// The time parameter specifies the number of passes over the memory and the -+// memory parameter specifies the size of the memory in KiB. For example -+// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be -+// adjusted to the number of available CPUs. The cost parameters should be -+// increased as memory latency and CPU parallelism increases. Remember to get a -+// good random salt. -+func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { -+ return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) -+} -+ -+// IDKey derives a key from the password, salt, and cost parameters using -+// Argon2id returning a byte slice of length keyLen that can be used as -+// cryptographic key. The CPU cost and parallelism degree must be greater than -+// zero. -+// -+// For example, you can get a derived key for e.g. AES-256 (which needs a -+// 32-byte key) by doing: -+// -+// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32) -+// -+// The draft RFC recommends[2] time=1, and memory=64*1024 is a sensible number. -+// If using that amount of memory (64 MB) is not possible in some contexts then -+// the time parameter can be increased to compensate. -+// -+// The time parameter specifies the number of passes over the memory and the -+// memory parameter specifies the size of the memory in KiB. For example -+// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be -+// adjusted to the numbers of available CPUs. The cost parameters should be -+// increased as memory latency and CPU parallelism increases. Remember to get a -+// good random salt. -+func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { -+ return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen) -+} -+ -+func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { -+ if time < 1 { -+ panic("argon2: number of rounds too small") -+ } -+ if threads < 1 { -+ panic("argon2: parallelism degree too low") -+ } -+ h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode) -+ -+ memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads)) -+ if memory < 2*syncPoints*uint32(threads) { -+ memory = 2 * syncPoints * uint32(threads) -+ } -+ B := initBlocks(&h0, memory, uint32(threads)) -+ processBlocks(B, time, memory, uint32(threads), mode) -+ return extractKey(B, memory, uint32(threads), keyLen) -+} -+ -+const ( -+ blockLength = 128 -+ syncPoints = 4 -+) -+ -+type block [blockLength]uint64 -+ -+func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte { -+ var ( -+ h0 [blake2b.Size + 8]byte -+ params [24]byte -+ tmp [4]byte -+ ) -+ -+ b2, _ := blake2b.New512(nil) -+ binary.LittleEndian.PutUint32(params[0:4], threads) -+ binary.LittleEndian.PutUint32(params[4:8], keyLen) -+ binary.LittleEndian.PutUint32(params[8:12], memory) -+ binary.LittleEndian.PutUint32(params[12:16], time) -+ binary.LittleEndian.PutUint32(params[16:20], uint32(Version)) -+ binary.LittleEndian.PutUint32(params[20:24], uint32(mode)) -+ b2.Write(params[:]) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(password))) -+ b2.Write(tmp[:]) -+ b2.Write(password) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt))) -+ b2.Write(tmp[:]) -+ b2.Write(salt) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(key))) -+ b2.Write(tmp[:]) -+ b2.Write(key) -+ binary.LittleEndian.PutUint32(tmp[:], uint32(len(data))) -+ b2.Write(tmp[:]) -+ b2.Write(data) -+ b2.Sum(h0[:0]) -+ return h0 -+} -+ -+func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block { -+ var block0 [1024]byte -+ B := make([]block, memory) -+ for lane := uint32(0); lane < threads; lane++ { -+ j := lane * (memory / threads) -+ binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane) -+ -+ binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0) -+ blake2bHash(block0[:], h0[:]) -+ for i := range B[j+0] { -+ B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:]) -+ } -+ -+ binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1) -+ blake2bHash(block0[:], h0[:]) -+ for i := range B[j+1] { -+ B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:]) -+ } -+ } -+ return B -+} -+ -+func processBlocks(B []block, time, memory, threads uint32, mode int) { -+ lanes := memory / threads -+ segments := lanes / syncPoints -+ -+ processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) { -+ var addresses, in, zero block -+ if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { -+ in[0] = uint64(n) -+ in[1] = uint64(lane) -+ in[2] = uint64(slice) -+ in[3] = uint64(memory) -+ in[4] = uint64(time) -+ in[5] = uint64(mode) -+ } -+ -+ index := uint32(0) -+ if n == 0 && slice == 0 { -+ index = 2 // we have already generated the first two blocks -+ if mode == argon2i || mode == argon2id { -+ in[6]++ -+ processBlock(&addresses, &in, &zero) -+ processBlock(&addresses, &addresses, &zero) -+ } -+ } -+ -+ offset := lane*lanes + slice*segments + index -+ var random uint64 -+ for index < segments { -+ prev := offset - 1 -+ if index == 0 && slice == 0 { -+ prev += lanes // last block in lane -+ } -+ if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { -+ if index%blockLength == 0 { -+ in[6]++ -+ processBlock(&addresses, &in, &zero) -+ processBlock(&addresses, &addresses, &zero) -+ } -+ random = addresses[index%blockLength] -+ } else { -+ random = B[prev][0] -+ } -+ newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index) -+ processBlockXOR(&B[offset], &B[prev], &B[newOffset]) -+ index, offset = index+1, offset+1 -+ } -+ wg.Done() -+ } -+ -+ for n := uint32(0); n < time; n++ { -+ for slice := uint32(0); slice < syncPoints; slice++ { -+ var wg sync.WaitGroup -+ for lane := uint32(0); lane < threads; lane++ { -+ wg.Add(1) -+ go processSegment(n, slice, lane, &wg) -+ } -+ wg.Wait() -+ } -+ } -+ -+} -+ -+func extractKey(B []block, memory, threads, keyLen uint32) []byte { -+ lanes := memory / threads -+ for lane := uint32(0); lane < threads-1; lane++ { -+ for i, v := range B[(lane*lanes)+lanes-1] { -+ B[memory-1][i] ^= v -+ } -+ } -+ -+ var block [1024]byte -+ for i, v := range B[memory-1] { -+ binary.LittleEndian.PutUint64(block[i*8:], v) -+ } -+ key := make([]byte, keyLen) -+ blake2bHash(key, block[:]) -+ return key -+} -+ -+func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 { -+ refLane := uint32(rand>>32) % threads -+ if n == 0 && slice == 0 { -+ refLane = lane -+ } -+ m, s := 3*segments, ((slice+1)%syncPoints)*segments -+ if lane == refLane { -+ m += index -+ } -+ if n == 0 { -+ m, s = slice*segments, 0 -+ if slice == 0 || lane == refLane { -+ m += index -+ } -+ } -+ if index == 0 || lane == refLane { -+ m-- -+ } -+ return phi(rand, uint64(m), uint64(s), refLane, lanes) -+} -+ -+func phi(rand, m, s uint64, lane, lanes uint32) uint32 { -+ p := rand & 0xFFFFFFFF -+ p = (p * p) >> 32 -+ p = (p * m) >> 32 -+ return lane*lanes + uint32((s+m-(p+1))%uint64(lanes)) -+} -diff --git a/ms_mod/golang.org/x/crypto/argon2/argon2_test.go b/ms_mod/golang.org/x/crypto/argon2/argon2_test.go -new file mode 100644 -index 00000000000000..775b97a4048d6d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/argon2_test.go -@@ -0,0 +1,233 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package argon2 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "testing" -+) -+ -+var ( -+ genKatPassword = []byte{ -+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -+ } -+ genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} -+ genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03} -+ genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04} -+) -+ -+func TestArgon2(t *testing.T) { -+ defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4) -+ -+ if useSSE4 { -+ t.Log("SSE4.1 version") -+ testArgon2i(t) -+ testArgon2d(t) -+ testArgon2id(t) -+ useSSE4 = false -+ } -+ t.Log("generic version") -+ testArgon2i(t) -+ testArgon2d(t) -+ testArgon2id(t) -+} -+ -+func testArgon2d(t *testing.T) { -+ want := []byte{ -+ 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97, -+ 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94, -+ 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1, -+ 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb, -+ } -+ hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) -+ if !bytes.Equal(hash, want) { -+ t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) -+ } -+} -+ -+func testArgon2i(t *testing.T) { -+ want := []byte{ -+ 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa, -+ 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1, -+ 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2, -+ 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8, -+ } -+ hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) -+ if !bytes.Equal(hash, want) { -+ t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) -+ } -+} -+ -+func testArgon2id(t *testing.T) { -+ want := []byte{ -+ 0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c, -+ 0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9, -+ 0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e, -+ 0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59, -+ } -+ hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) -+ if !bytes.Equal(hash, want) { -+ t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) -+ } -+} -+ -+func TestVectors(t *testing.T) { -+ password, salt := []byte("password"), []byte("somesalt") -+ for i, v := range testVectors { -+ want, err := hex.DecodeString(v.hash) -+ if err != nil { -+ t.Fatalf("Test %d: failed to decode hash: %v", i, err) -+ } -+ hash := deriveKey(v.mode, password, salt, nil, nil, v.time, v.memory, v.threads, uint32(len(want))) -+ if !bytes.Equal(hash, want) { -+ t.Errorf("Test %d - got: %s want: %s", i, hex.EncodeToString(hash), hex.EncodeToString(want)) -+ } -+ } -+} -+ -+func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) { -+ password := []byte("password") -+ salt := []byte("choosing random salts is hard") -+ b.ReportAllocs() -+ for i := 0; i < b.N; i++ { -+ deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen) -+ } -+} -+ -+func BenchmarkArgon2i(b *testing.B) { -+ b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) }) -+ b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) }) -+ b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) }) -+} -+ -+func BenchmarkArgon2d(b *testing.B) { -+ b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) }) -+ b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) }) -+ b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) }) -+} -+ -+func BenchmarkArgon2id(b *testing.B) { -+ b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) }) -+ b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) }) -+ b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) }) -+ b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) }) -+} -+ -+// Generated with the CLI of https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf -+var testVectors = []struct { -+ mode int -+ time, memory uint32 -+ threads uint8 -+ hash string -+}{ -+ { -+ mode: argon2i, time: 1, memory: 64, threads: 1, -+ hash: "b9c401d1844a67d50eae3967dc28870b22e508092e861a37", -+ }, -+ { -+ mode: argon2d, time: 1, memory: 64, threads: 1, -+ hash: "8727405fd07c32c78d64f547f24150d3f2e703a89f981a19", -+ }, -+ { -+ mode: argon2id, time: 1, memory: 64, threads: 1, -+ hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb", -+ }, -+ { -+ mode: argon2i, time: 2, memory: 64, threads: 1, -+ hash: "8cf3d8f76a6617afe35fac48eb0b7433a9a670ca4a07ed64", -+ }, -+ { -+ mode: argon2d, time: 2, memory: 64, threads: 1, -+ hash: "3be9ec79a69b75d3752acb59a1fbb8b295a46529c48fbb75", -+ }, -+ { -+ mode: argon2id, time: 2, memory: 64, threads: 1, -+ hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7", -+ }, -+ { -+ mode: argon2i, time: 2, memory: 64, threads: 2, -+ hash: "2089f3e78a799720f80af806553128f29b132cafe40d059f", -+ }, -+ { -+ mode: argon2d, time: 2, memory: 64, threads: 2, -+ hash: "68e2462c98b8bc6bb60ec68db418ae2c9ed24fc6748a40e9", -+ }, -+ { -+ mode: argon2id, time: 2, memory: 64, threads: 2, -+ hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362", -+ }, -+ { -+ mode: argon2i, time: 3, memory: 256, threads: 2, -+ hash: "f5bbf5d4c3836af13193053155b73ec7476a6a2eb93fd5e6", -+ }, -+ { -+ mode: argon2d, time: 3, memory: 256, threads: 2, -+ hash: "f4f0669218eaf3641f39cc97efb915721102f4b128211ef2", -+ }, -+ { -+ mode: argon2id, time: 3, memory: 256, threads: 2, -+ hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b", -+ }, -+ { -+ mode: argon2i, time: 4, memory: 4096, threads: 4, -+ hash: "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7", -+ }, -+ { -+ mode: argon2d, time: 4, memory: 4096, threads: 4, -+ hash: "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d", -+ }, -+ { -+ mode: argon2id, time: 4, memory: 4096, threads: 4, -+ hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a", -+ }, -+ { -+ mode: argon2i, time: 4, memory: 1024, threads: 8, -+ hash: "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17", -+ }, -+ { -+ mode: argon2d, time: 4, memory: 1024, threads: 8, -+ hash: "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9", -+ }, -+ { -+ mode: argon2id, time: 4, memory: 1024, threads: 8, -+ hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f", -+ }, -+ { -+ mode: argon2i, time: 2, memory: 64, threads: 3, -+ hash: "5cab452fe6b8479c8661def8cd703b611a3905a6d5477fe6", -+ }, -+ { -+ mode: argon2d, time: 2, memory: 64, threads: 3, -+ hash: "22474a423bda2ccd36ec9afd5119e5c8949798cadf659f51", -+ }, -+ { -+ mode: argon2id, time: 2, memory: 64, threads: 3, -+ hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079", -+ }, -+ { -+ mode: argon2i, time: 3, memory: 1024, threads: 6, -+ hash: "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced", -+ }, -+ { -+ mode: argon2d, time: 3, memory: 1024, threads: 6, -+ hash: "a3351b0319a53229152023d9206902f4ef59661cdca89481", -+ }, -+ { -+ mode: argon2id, time: 3, memory: 1024, threads: 6, -+ hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016", -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/argon2/blake2b.go b/ms_mod/golang.org/x/crypto/argon2/blake2b.go -new file mode 100644 -index 00000000000000..10f46948dc1053 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/blake2b.go -@@ -0,0 +1,53 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package argon2 -+ -+import ( -+ "encoding/binary" -+ "hash" -+ -+ "golang.org/x/crypto/blake2b" -+) -+ -+// blake2bHash computes an arbitrary long hash value of in -+// and writes the hash to out. -+func blake2bHash(out []byte, in []byte) { -+ var b2 hash.Hash -+ if n := len(out); n < blake2b.Size { -+ b2, _ = blake2b.New(n, nil) -+ } else { -+ b2, _ = blake2b.New512(nil) -+ } -+ -+ var buffer [blake2b.Size]byte -+ binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out))) -+ b2.Write(buffer[:4]) -+ b2.Write(in) -+ -+ if len(out) <= blake2b.Size { -+ b2.Sum(out[:0]) -+ return -+ } -+ -+ outLen := len(out) -+ b2.Sum(buffer[:0]) -+ b2.Reset() -+ copy(out, buffer[:32]) -+ out = out[32:] -+ for len(out) > blake2b.Size { -+ b2.Write(buffer[:]) -+ b2.Sum(buffer[:0]) -+ copy(out, buffer[:32]) -+ out = out[32:] -+ b2.Reset() -+ } -+ -+ if outLen%blake2b.Size > 0 { // outLen > 64 -+ r := ((outLen + 31) / 32) - 2 // βŒˆΟ„ /32βŒ‰-2 -+ b2, _ = blake2b.New(outLen-32*r, nil) -+ } -+ b2.Write(buffer[:]) -+ b2.Sum(out[:0]) -+} -diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go -new file mode 100644 -index 00000000000000..a014ac92aa9f30 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.go -@@ -0,0 +1,61 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+package argon2 -+ -+import "golang.org/x/sys/cpu" -+ -+func init() { -+ useSSE4 = cpu.X86.HasSSE41 -+} -+ -+//go:noescape -+func mixBlocksSSE2(out, a, b, c *block) -+ -+//go:noescape -+func xorBlocksSSE2(out, a, b, c *block) -+ -+//go:noescape -+func blamkaSSE4(b *block) -+ -+func processBlockSSE(out, in1, in2 *block, xor bool) { -+ var t block -+ mixBlocksSSE2(&t, in1, in2, &t) -+ if useSSE4 { -+ blamkaSSE4(&t) -+ } else { -+ for i := 0; i < blockLength; i += 16 { -+ blamkaGeneric( -+ &t[i+0], &t[i+1], &t[i+2], &t[i+3], -+ &t[i+4], &t[i+5], &t[i+6], &t[i+7], -+ &t[i+8], &t[i+9], &t[i+10], &t[i+11], -+ &t[i+12], &t[i+13], &t[i+14], &t[i+15], -+ ) -+ } -+ for i := 0; i < blockLength/8; i += 2 { -+ blamkaGeneric( -+ &t[i], &t[i+1], &t[16+i], &t[16+i+1], -+ &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], -+ &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], -+ &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], -+ ) -+ } -+ } -+ if xor { -+ xorBlocksSSE2(out, in1, in2, &t) -+ } else { -+ mixBlocksSSE2(out, in1, in2, &t) -+ } -+} -+ -+func processBlock(out, in1, in2 *block) { -+ processBlockSSE(out, in1, in2, false) -+} -+ -+func processBlockXOR(out, in1, in2 *block) { -+ processBlockSSE(out, in1, in2, true) -+} -diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s -new file mode 100644 -index 00000000000000..b2cc0515049a7a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/blamka_amd64.s -@@ -0,0 +1,244 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA Β·c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA Β·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL Β·c40<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA Β·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL Β·c48<>(SB), (NOPTR+RODATA), $16 -+ -+#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v6, t1; \ -+ PUNPCKLQDQ v6, t2; \ -+ PUNPCKHQDQ v7, v6; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ v7, t2; \ -+ MOVO t1, v7; \ -+ MOVO v2, t1; \ -+ PUNPCKHQDQ t2, v7; \ -+ PUNPCKLQDQ v3, t2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v3 -+ -+#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v2, t1; \ -+ PUNPCKLQDQ v2, t2; \ -+ PUNPCKHQDQ v3, v2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ v3, t2; \ -+ MOVO t1, v3; \ -+ MOVO v6, t1; \ -+ PUNPCKHQDQ t2, v3; \ -+ PUNPCKLQDQ v7, t2; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v7 -+ -+#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \ -+ MOVO v0, t0; \ -+ PMULULQ v2, t0; \ -+ PADDQ v2, v0; \ -+ PADDQ t0, v0; \ -+ PADDQ t0, v0; \ -+ PXOR v0, v6; \ -+ PSHUFD $0xB1, v6, v6; \ -+ MOVO v4, t0; \ -+ PMULULQ v6, t0; \ -+ PADDQ v6, v4; \ -+ PADDQ t0, v4; \ -+ PADDQ t0, v4; \ -+ PXOR v4, v2; \ -+ PSHUFB c40, v2; \ -+ MOVO v0, t0; \ -+ PMULULQ v2, t0; \ -+ PADDQ v2, v0; \ -+ PADDQ t0, v0; \ -+ PADDQ t0, v0; \ -+ PXOR v0, v6; \ -+ PSHUFB c48, v6; \ -+ MOVO v4, t0; \ -+ PMULULQ v6, t0; \ -+ PADDQ v6, v4; \ -+ PADDQ t0, v4; \ -+ PADDQ t0, v4; \ -+ PXOR v4, v2; \ -+ MOVO v2, t0; \ -+ PADDQ v2, t0; \ -+ PSRLQ $63, v2; \ -+ PXOR t0, v2; \ -+ MOVO v1, t0; \ -+ PMULULQ v3, t0; \ -+ PADDQ v3, v1; \ -+ PADDQ t0, v1; \ -+ PADDQ t0, v1; \ -+ PXOR v1, v7; \ -+ PSHUFD $0xB1, v7, v7; \ -+ MOVO v5, t0; \ -+ PMULULQ v7, t0; \ -+ PADDQ v7, v5; \ -+ PADDQ t0, v5; \ -+ PADDQ t0, v5; \ -+ PXOR v5, v3; \ -+ PSHUFB c40, v3; \ -+ MOVO v1, t0; \ -+ PMULULQ v3, t0; \ -+ PADDQ v3, v1; \ -+ PADDQ t0, v1; \ -+ PADDQ t0, v1; \ -+ PXOR v1, v7; \ -+ PSHUFB c48, v7; \ -+ MOVO v5, t0; \ -+ PMULULQ v7, t0; \ -+ PADDQ v7, v5; \ -+ PADDQ t0, v5; \ -+ PADDQ t0, v5; \ -+ PXOR v5, v3; \ -+ MOVO v3, t0; \ -+ PADDQ v3, t0; \ -+ PSRLQ $63, v3; \ -+ PXOR t0, v3 -+ -+#define LOAD_MSG_0(block, off) \ -+ MOVOU 8*(off+0)(block), X0; \ -+ MOVOU 8*(off+2)(block), X1; \ -+ MOVOU 8*(off+4)(block), X2; \ -+ MOVOU 8*(off+6)(block), X3; \ -+ MOVOU 8*(off+8)(block), X4; \ -+ MOVOU 8*(off+10)(block), X5; \ -+ MOVOU 8*(off+12)(block), X6; \ -+ MOVOU 8*(off+14)(block), X7 -+ -+#define STORE_MSG_0(block, off) \ -+ MOVOU X0, 8*(off+0)(block); \ -+ MOVOU X1, 8*(off+2)(block); \ -+ MOVOU X2, 8*(off+4)(block); \ -+ MOVOU X3, 8*(off+6)(block); \ -+ MOVOU X4, 8*(off+8)(block); \ -+ MOVOU X5, 8*(off+10)(block); \ -+ MOVOU X6, 8*(off+12)(block); \ -+ MOVOU X7, 8*(off+14)(block) -+ -+#define LOAD_MSG_1(block, off) \ -+ MOVOU 8*off+0*8(block), X0; \ -+ MOVOU 8*off+16*8(block), X1; \ -+ MOVOU 8*off+32*8(block), X2; \ -+ MOVOU 8*off+48*8(block), X3; \ -+ MOVOU 8*off+64*8(block), X4; \ -+ MOVOU 8*off+80*8(block), X5; \ -+ MOVOU 8*off+96*8(block), X6; \ -+ MOVOU 8*off+112*8(block), X7 -+ -+#define STORE_MSG_1(block, off) \ -+ MOVOU X0, 8*off+0*8(block); \ -+ MOVOU X1, 8*off+16*8(block); \ -+ MOVOU X2, 8*off+32*8(block); \ -+ MOVOU X3, 8*off+48*8(block); \ -+ MOVOU X4, 8*off+64*8(block); \ -+ MOVOU X5, 8*off+80*8(block); \ -+ MOVOU X6, 8*off+96*8(block); \ -+ MOVOU X7, 8*off+112*8(block) -+ -+#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \ -+ LOAD_MSG_0(block, off); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ STORE_MSG_0(block, off) -+ -+#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \ -+ LOAD_MSG_1(block, off); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ -+ STORE_MSG_1(block, off) -+ -+// func blamkaSSE4(b *block) -+TEXT Β·blamkaSSE4(SB), 4, $0-8 -+ MOVQ b+0(FP), AX -+ -+ MOVOU Β·c40<>(SB), X10 -+ MOVOU Β·c48<>(SB), X11 -+ -+ BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11) -+ BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11) -+ -+ BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11) -+ BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11) -+ RET -+ -+// func mixBlocksSSE2(out, a, b, c *block) -+TEXT Β·mixBlocksSSE2(SB), 4, $0-32 -+ MOVQ out+0(FP), DX -+ MOVQ a+8(FP), AX -+ MOVQ b+16(FP), BX -+ MOVQ a+24(FP), CX -+ MOVQ $128, BP -+ -+loop: -+ MOVOU 0(AX), X0 -+ MOVOU 0(BX), X1 -+ MOVOU 0(CX), X2 -+ PXOR X1, X0 -+ PXOR X2, X0 -+ MOVOU X0, 0(DX) -+ ADDQ $16, AX -+ ADDQ $16, BX -+ ADDQ $16, CX -+ ADDQ $16, DX -+ SUBQ $2, BP -+ JA loop -+ RET -+ -+// func xorBlocksSSE2(out, a, b, c *block) -+TEXT Β·xorBlocksSSE2(SB), 4, $0-32 -+ MOVQ out+0(FP), DX -+ MOVQ a+8(FP), AX -+ MOVQ b+16(FP), BX -+ MOVQ a+24(FP), CX -+ MOVQ $128, BP -+ -+loop: -+ MOVOU 0(AX), X0 -+ MOVOU 0(BX), X1 -+ MOVOU 0(CX), X2 -+ MOVOU 0(DX), X3 -+ PXOR X1, X0 -+ PXOR X2, X0 -+ PXOR X3, X0 -+ MOVOU X0, 0(DX) -+ ADDQ $16, AX -+ ADDQ $16, BX -+ ADDQ $16, CX -+ ADDQ $16, DX -+ SUBQ $2, BP -+ JA loop -+ RET -diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_generic.go b/ms_mod/golang.org/x/crypto/argon2/blamka_generic.go -new file mode 100644 -index 00000000000000..a481b2243f855f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/blamka_generic.go -@@ -0,0 +1,163 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package argon2 -+ -+var useSSE4 bool -+ -+func processBlockGeneric(out, in1, in2 *block, xor bool) { -+ var t block -+ for i := range t { -+ t[i] = in1[i] ^ in2[i] -+ } -+ for i := 0; i < blockLength; i += 16 { -+ blamkaGeneric( -+ &t[i+0], &t[i+1], &t[i+2], &t[i+3], -+ &t[i+4], &t[i+5], &t[i+6], &t[i+7], -+ &t[i+8], &t[i+9], &t[i+10], &t[i+11], -+ &t[i+12], &t[i+13], &t[i+14], &t[i+15], -+ ) -+ } -+ for i := 0; i < blockLength/8; i += 2 { -+ blamkaGeneric( -+ &t[i], &t[i+1], &t[16+i], &t[16+i+1], -+ &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], -+ &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], -+ &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], -+ ) -+ } -+ if xor { -+ for i := range t { -+ out[i] ^= in1[i] ^ in2[i] ^ t[i] -+ } -+ } else { -+ for i := range t { -+ out[i] = in1[i] ^ in2[i] ^ t[i] -+ } -+ } -+} -+ -+func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) { -+ v00, v01, v02, v03 := *t00, *t01, *t02, *t03 -+ v04, v05, v06, v07 := *t04, *t05, *t06, *t07 -+ v08, v09, v10, v11 := *t08, *t09, *t10, *t11 -+ v12, v13, v14, v15 := *t12, *t13, *t14, *t15 -+ -+ v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) -+ v12 ^= v00 -+ v12 = v12>>32 | v12<<32 -+ v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) -+ v04 ^= v08 -+ v04 = v04>>24 | v04<<40 -+ -+ v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) -+ v12 ^= v00 -+ v12 = v12>>16 | v12<<48 -+ v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) -+ v04 ^= v08 -+ v04 = v04>>63 | v04<<1 -+ -+ v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) -+ v13 ^= v01 -+ v13 = v13>>32 | v13<<32 -+ v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) -+ v05 ^= v09 -+ v05 = v05>>24 | v05<<40 -+ -+ v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) -+ v13 ^= v01 -+ v13 = v13>>16 | v13<<48 -+ v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) -+ v05 ^= v09 -+ v05 = v05>>63 | v05<<1 -+ -+ v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) -+ v14 ^= v02 -+ v14 = v14>>32 | v14<<32 -+ v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) -+ v06 ^= v10 -+ v06 = v06>>24 | v06<<40 -+ -+ v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) -+ v14 ^= v02 -+ v14 = v14>>16 | v14<<48 -+ v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) -+ v06 ^= v10 -+ v06 = v06>>63 | v06<<1 -+ -+ v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) -+ v15 ^= v03 -+ v15 = v15>>32 | v15<<32 -+ v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) -+ v07 ^= v11 -+ v07 = v07>>24 | v07<<40 -+ -+ v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) -+ v15 ^= v03 -+ v15 = v15>>16 | v15<<48 -+ v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) -+ v07 ^= v11 -+ v07 = v07>>63 | v07<<1 -+ -+ v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) -+ v15 ^= v00 -+ v15 = v15>>32 | v15<<32 -+ v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) -+ v05 ^= v10 -+ v05 = v05>>24 | v05<<40 -+ -+ v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) -+ v15 ^= v00 -+ v15 = v15>>16 | v15<<48 -+ v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) -+ v05 ^= v10 -+ v05 = v05>>63 | v05<<1 -+ -+ v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) -+ v12 ^= v01 -+ v12 = v12>>32 | v12<<32 -+ v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) -+ v06 ^= v11 -+ v06 = v06>>24 | v06<<40 -+ -+ v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) -+ v12 ^= v01 -+ v12 = v12>>16 | v12<<48 -+ v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) -+ v06 ^= v11 -+ v06 = v06>>63 | v06<<1 -+ -+ v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) -+ v13 ^= v02 -+ v13 = v13>>32 | v13<<32 -+ v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) -+ v07 ^= v08 -+ v07 = v07>>24 | v07<<40 -+ -+ v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) -+ v13 ^= v02 -+ v13 = v13>>16 | v13<<48 -+ v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) -+ v07 ^= v08 -+ v07 = v07>>63 | v07<<1 -+ -+ v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) -+ v14 ^= v03 -+ v14 = v14>>32 | v14<<32 -+ v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) -+ v04 ^= v09 -+ v04 = v04>>24 | v04<<40 -+ -+ v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) -+ v14 ^= v03 -+ v14 = v14>>16 | v14<<48 -+ v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) -+ v04 ^= v09 -+ v04 = v04>>63 | v04<<1 -+ -+ *t00, *t01, *t02, *t03 = v00, v01, v02, v03 -+ *t04, *t05, *t06, *t07 = v04, v05, v06, v07 -+ *t08, *t09, *t10, *t11 = v08, v09, v10, v11 -+ *t12, *t13, *t14, *t15 = v12, v13, v14, v15 -+} -diff --git a/ms_mod/golang.org/x/crypto/argon2/blamka_ref.go b/ms_mod/golang.org/x/crypto/argon2/blamka_ref.go -new file mode 100644 -index 00000000000000..167c59d2d5ab74 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/argon2/blamka_ref.go -@@ -0,0 +1,16 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package argon2 -+ -+func processBlock(out, in1, in2 *block) { -+ processBlockGeneric(out, in1, in2, false) -+} -+ -+func processBlockXOR(out, in1, in2 *block) { -+ processBlockGeneric(out, in1, in2, true) -+} -diff --git a/ms_mod/golang.org/x/crypto/bcrypt/base64.go b/ms_mod/golang.org/x/crypto/bcrypt/base64.go -new file mode 100644 -index 00000000000000..fc311609081849 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bcrypt/base64.go -@@ -0,0 +1,35 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bcrypt -+ -+import "encoding/base64" -+ -+const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -+ -+var bcEncoding = base64.NewEncoding(alphabet) -+ -+func base64Encode(src []byte) []byte { -+ n := bcEncoding.EncodedLen(len(src)) -+ dst := make([]byte, n) -+ bcEncoding.Encode(dst, src) -+ for dst[n-1] == '=' { -+ n-- -+ } -+ return dst[:n] -+} -+ -+func base64Decode(src []byte) ([]byte, error) { -+ numOfEquals := 4 - (len(src) % 4) -+ for i := 0; i < numOfEquals; i++ { -+ src = append(src, '=') -+ } -+ -+ dst := make([]byte, bcEncoding.DecodedLen(len(src))) -+ n, err := bcEncoding.Decode(dst, src) -+ if err != nil { -+ return nil, err -+ } -+ return dst[:n], nil -+} -diff --git a/ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go -new file mode 100644 -index 00000000000000..5577c0f939a23e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt.go -@@ -0,0 +1,304 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package bcrypt implements Provos and MaziΓ¨res's bcrypt adaptive hashing -+// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf -+package bcrypt // import "golang.org/x/crypto/bcrypt" -+ -+// The code is a port of Provos and MaziΓ¨res's C implementation. -+import ( -+ "crypto/rand" -+ "crypto/subtle" -+ "errors" -+ "fmt" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/blowfish" -+) -+ -+const ( -+ MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword -+ MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword -+ DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword -+) -+ -+// The error returned from CompareHashAndPassword when a password and hash do -+// not match. -+var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") -+ -+// The error returned from CompareHashAndPassword when a hash is too short to -+// be a bcrypt hash. -+var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") -+ -+// The error returned from CompareHashAndPassword when a hash was created with -+// a bcrypt algorithm newer than this implementation. -+type HashVersionTooNewError byte -+ -+func (hv HashVersionTooNewError) Error() string { -+ return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) -+} -+ -+// The error returned from CompareHashAndPassword when a hash starts with something other than '$' -+type InvalidHashPrefixError byte -+ -+func (ih InvalidHashPrefixError) Error() string { -+ return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) -+} -+ -+type InvalidCostError int -+ -+func (ic InvalidCostError) Error() string { -+ return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), MinCost, MaxCost) -+} -+ -+const ( -+ majorVersion = '2' -+ minorVersion = 'a' -+ maxSaltSize = 16 -+ maxCryptedHashSize = 23 -+ encodedSaltSize = 22 -+ encodedHashSize = 31 -+ minHashSize = 59 -+) -+ -+// magicCipherData is an IV for the 64 Blowfish encryption calls in -+// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. -+var magicCipherData = []byte{ -+ 0x4f, 0x72, 0x70, 0x68, -+ 0x65, 0x61, 0x6e, 0x42, -+ 0x65, 0x68, 0x6f, 0x6c, -+ 0x64, 0x65, 0x72, 0x53, -+ 0x63, 0x72, 0x79, 0x44, -+ 0x6f, 0x75, 0x62, 0x74, -+} -+ -+type hashed struct { -+ hash []byte -+ salt []byte -+ cost int // allowed range is MinCost to MaxCost -+ major byte -+ minor byte -+} -+ -+// ErrPasswordTooLong is returned when the password passed to -+// GenerateFromPassword is too long (i.e. > 72 bytes). -+var ErrPasswordTooLong = errors.New("bcrypt: password length exceeds 72 bytes") -+ -+// GenerateFromPassword returns the bcrypt hash of the password at the given -+// cost. If the cost given is less than MinCost, the cost will be set to -+// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, -+// to compare the returned hashed password with its cleartext version. -+// GenerateFromPassword does not accept passwords longer than 72 bytes, which -+// is the longest password bcrypt will operate on. -+func GenerateFromPassword(password []byte, cost int) ([]byte, error) { -+ if len(password) > 72 { -+ return nil, ErrPasswordTooLong -+ } -+ p, err := newFromPassword(password, cost) -+ if err != nil { -+ return nil, err -+ } -+ return p.Hash(), nil -+} -+ -+// CompareHashAndPassword compares a bcrypt hashed password with its possible -+// plaintext equivalent. Returns nil on success, or an error on failure. -+func CompareHashAndPassword(hashedPassword, password []byte) error { -+ p, err := newFromHash(hashedPassword) -+ if err != nil { -+ return err -+ } -+ -+ otherHash, err := bcrypt(password, p.cost, p.salt) -+ if err != nil { -+ return err -+ } -+ -+ otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} -+ if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { -+ return nil -+ } -+ -+ return ErrMismatchedHashAndPassword -+} -+ -+// Cost returns the hashing cost used to create the given hashed -+// password. When, in the future, the hashing cost of a password system needs -+// to be increased in order to adjust for greater computational power, this -+// function allows one to establish which passwords need to be updated. -+func Cost(hashedPassword []byte) (int, error) { -+ p, err := newFromHash(hashedPassword) -+ if err != nil { -+ return 0, err -+ } -+ return p.cost, nil -+} -+ -+func newFromPassword(password []byte, cost int) (*hashed, error) { -+ if cost < MinCost { -+ cost = DefaultCost -+ } -+ p := new(hashed) -+ p.major = majorVersion -+ p.minor = minorVersion -+ -+ err := checkCost(cost) -+ if err != nil { -+ return nil, err -+ } -+ p.cost = cost -+ -+ unencodedSalt := make([]byte, maxSaltSize) -+ _, err = io.ReadFull(rand.Reader, unencodedSalt) -+ if err != nil { -+ return nil, err -+ } -+ -+ p.salt = base64Encode(unencodedSalt) -+ hash, err := bcrypt(password, p.cost, p.salt) -+ if err != nil { -+ return nil, err -+ } -+ p.hash = hash -+ return p, err -+} -+ -+func newFromHash(hashedSecret []byte) (*hashed, error) { -+ if len(hashedSecret) < minHashSize { -+ return nil, ErrHashTooShort -+ } -+ p := new(hashed) -+ n, err := p.decodeVersion(hashedSecret) -+ if err != nil { -+ return nil, err -+ } -+ hashedSecret = hashedSecret[n:] -+ n, err = p.decodeCost(hashedSecret) -+ if err != nil { -+ return nil, err -+ } -+ hashedSecret = hashedSecret[n:] -+ -+ // The "+2" is here because we'll have to append at most 2 '=' to the salt -+ // when base64 decoding it in expensiveBlowfishSetup(). -+ p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) -+ copy(p.salt, hashedSecret[:encodedSaltSize]) -+ -+ hashedSecret = hashedSecret[encodedSaltSize:] -+ p.hash = make([]byte, len(hashedSecret)) -+ copy(p.hash, hashedSecret) -+ -+ return p, nil -+} -+ -+func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { -+ cipherData := make([]byte, len(magicCipherData)) -+ copy(cipherData, magicCipherData) -+ -+ c, err := expensiveBlowfishSetup(password, uint32(cost), salt) -+ if err != nil { -+ return nil, err -+ } -+ -+ for i := 0; i < 24; i += 8 { -+ for j := 0; j < 64; j++ { -+ c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) -+ } -+ } -+ -+ // Bug compatibility with C bcrypt implementations. We only encode 23 of -+ // the 24 bytes encrypted. -+ hsh := base64Encode(cipherData[:maxCryptedHashSize]) -+ return hsh, nil -+} -+ -+func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { -+ csalt, err := base64Decode(salt) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Bug compatibility with C bcrypt implementations. They use the trailing -+ // NULL in the key string during expansion. -+ // We copy the key to prevent changing the underlying array. -+ ckey := append(key[:len(key):len(key)], 0) -+ -+ c, err := blowfish.NewSaltedCipher(ckey, csalt) -+ if err != nil { -+ return nil, err -+ } -+ -+ var i, rounds uint64 -+ rounds = 1 << cost -+ for i = 0; i < rounds; i++ { -+ blowfish.ExpandKey(ckey, c) -+ blowfish.ExpandKey(csalt, c) -+ } -+ -+ return c, nil -+} -+ -+func (p *hashed) Hash() []byte { -+ arr := make([]byte, 60) -+ arr[0] = '$' -+ arr[1] = p.major -+ n := 2 -+ if p.minor != 0 { -+ arr[2] = p.minor -+ n = 3 -+ } -+ arr[n] = '$' -+ n++ -+ copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) -+ n += 2 -+ arr[n] = '$' -+ n++ -+ copy(arr[n:], p.salt) -+ n += encodedSaltSize -+ copy(arr[n:], p.hash) -+ n += encodedHashSize -+ return arr[:n] -+} -+ -+func (p *hashed) decodeVersion(sbytes []byte) (int, error) { -+ if sbytes[0] != '$' { -+ return -1, InvalidHashPrefixError(sbytes[0]) -+ } -+ if sbytes[1] > majorVersion { -+ return -1, HashVersionTooNewError(sbytes[1]) -+ } -+ p.major = sbytes[1] -+ n := 3 -+ if sbytes[2] != '$' { -+ p.minor = sbytes[2] -+ n++ -+ } -+ return n, nil -+} -+ -+// sbytes should begin where decodeVersion left off. -+func (p *hashed) decodeCost(sbytes []byte) (int, error) { -+ cost, err := strconv.Atoi(string(sbytes[0:2])) -+ if err != nil { -+ return -1, err -+ } -+ err = checkCost(cost) -+ if err != nil { -+ return -1, err -+ } -+ p.cost = cost -+ return 3, nil -+} -+ -+func (p *hashed) String() string { -+ return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) -+} -+ -+func checkCost(cost int) error { -+ if cost < MinCost || cost > MaxCost { -+ return InvalidCostError(cost) -+ } -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go -new file mode 100644 -index 00000000000000..8b589e36527a25 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bcrypt/bcrypt_test.go -@@ -0,0 +1,250 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bcrypt -+ -+import ( -+ "bytes" -+ "fmt" -+ "testing" -+) -+ -+func TestBcryptingIsEasy(t *testing.T) { -+ pass := []byte("mypassword") -+ hp, err := GenerateFromPassword(pass, 0) -+ if err != nil { -+ t.Fatalf("GenerateFromPassword error: %s", err) -+ } -+ -+ if CompareHashAndPassword(hp, pass) != nil { -+ t.Errorf("%v should hash %s correctly", hp, pass) -+ } -+ -+ notPass := "notthepass" -+ err = CompareHashAndPassword(hp, []byte(notPass)) -+ if err != ErrMismatchedHashAndPassword { -+ t.Errorf("%v and %s should be mismatched", hp, notPass) -+ } -+} -+ -+func TestBcryptingIsCorrect(t *testing.T) { -+ pass := []byte("allmine") -+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe") -+ expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") -+ -+ hash, err := bcrypt(pass, 10, salt) -+ if err != nil { -+ t.Fatalf("bcrypt blew up: %v", err) -+ } -+ if !bytes.HasSuffix(expectedHash, hash) { -+ t.Errorf("%v should be the suffix of %v", hash, expectedHash) -+ } -+ -+ h, err := newFromHash(expectedHash) -+ if err != nil { -+ t.Errorf("Unable to parse %s: %v", string(expectedHash), err) -+ } -+ -+ // This is not the safe way to compare these hashes. We do this only for -+ // testing clarity. Use bcrypt.CompareHashAndPassword() -+ if err == nil && !bytes.Equal(expectedHash, h.Hash()) { -+ t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash) -+ } -+} -+ -+func TestVeryShortPasswords(t *testing.T) { -+ key := []byte("k") -+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe") -+ _, err := bcrypt(key, 10, salt) -+ if err != nil { -+ t.Errorf("One byte key resulted in error: %s", err) -+ } -+} -+ -+func TestTooLongPasswordsWork(t *testing.T) { -+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe") -+ // One byte over the usual 56 byte limit that blowfish has -+ tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456") -+ tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C") -+ hash, err := bcrypt(tooLongPass, 10, salt) -+ if err != nil { -+ t.Fatalf("bcrypt blew up on long password: %v", err) -+ } -+ if !bytes.HasSuffix(tooLongExpected, hash) { -+ t.Errorf("%v should be the suffix of %v", hash, tooLongExpected) -+ } -+} -+ -+type InvalidHashTest struct { -+ err error -+ hash []byte -+} -+ -+var invalidTests = []InvalidHashTest{ -+ {ErrHashTooShort, []byte("$2a$10$fooo")}, -+ {ErrHashTooShort, []byte("$2a")}, -+ {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, -+ {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, -+ {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")}, -+} -+ -+func TestInvalidHashErrors(t *testing.T) { -+ check := func(name string, expected, err error) { -+ if err == nil { -+ t.Errorf("%s: Should have returned an error", name) -+ } -+ if err != nil && err != expected { -+ t.Errorf("%s gave err %v but should have given %v", name, err, expected) -+ } -+ } -+ for _, iht := range invalidTests { -+ _, err := newFromHash(iht.hash) -+ check("newFromHash", iht.err, err) -+ err = CompareHashAndPassword(iht.hash, []byte("anything")) -+ check("CompareHashAndPassword", iht.err, err) -+ } -+} -+ -+func TestUnpaddedBase64Encoding(t *testing.T) { -+ original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30} -+ encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe") -+ -+ encoded := base64Encode(original) -+ -+ if !bytes.Equal(encodedOriginal, encoded) { -+ t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal) -+ } -+ -+ decoded, err := base64Decode(encodedOriginal) -+ if err != nil { -+ t.Fatalf("base64Decode blew up: %s", err) -+ } -+ -+ if !bytes.Equal(decoded, original) { -+ t.Errorf("Decoded %v should have equaled %v", decoded, original) -+ } -+} -+ -+func TestCost(t *testing.T) { -+ suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C" -+ for _, vers := range []string{"2a", "2"} { -+ for _, cost := range []int{4, 10} { -+ s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix) -+ h := []byte(s) -+ actual, err := Cost(h) -+ if err != nil { -+ t.Errorf("Cost, error: %s", err) -+ continue -+ } -+ if actual != cost { -+ t.Errorf("Cost, expected: %d, actual: %d", cost, actual) -+ } -+ } -+ } -+ _, err := Cost([]byte("$a$a$" + suffix)) -+ if err == nil { -+ t.Errorf("Cost, malformed but no error returned") -+ } -+} -+ -+func TestCostValidationInHash(t *testing.T) { -+ if testing.Short() { -+ return -+ } -+ -+ pass := []byte("mypassword") -+ -+ for c := 0; c < MinCost; c++ { -+ p, _ := newFromPassword(pass, c) -+ if p.cost != DefaultCost { -+ t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost) -+ } -+ } -+ -+ p, _ := newFromPassword(pass, 14) -+ if p.cost != 14 { -+ t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost) -+ } -+ -+ hp, _ := newFromHash(p.Hash()) -+ if p.cost != hp.cost { -+ t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost) -+ } -+ -+ _, err := newFromPassword(pass, 32) -+ if err == nil { -+ t.Fatalf("newFromPassword: should return a cost error") -+ } -+ if err != InvalidCostError(32) { -+ t.Errorf("newFromPassword: should return cost error, got %#v", err) -+ } -+} -+ -+func TestCostReturnsWithLeadingZeroes(t *testing.T) { -+ hp, _ := newFromPassword([]byte("abcdefgh"), 7) -+ cost := hp.Hash()[4:7] -+ expected := []byte("07$") -+ -+ if !bytes.Equal(expected, cost) { -+ t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected) -+ } -+} -+ -+func TestMinorNotRequired(t *testing.T) { -+ noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga") -+ h, err := newFromHash(noMinorHash) -+ if err != nil { -+ t.Fatalf("No minor hash blew up: %s", err) -+ } -+ if h.minor != 0 { -+ t.Errorf("Should leave minor version at 0, but was %d", h.minor) -+ } -+ -+ if !bytes.Equal(noMinorHash, h.Hash()) { -+ t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash()) -+ } -+} -+ -+func BenchmarkEqual(b *testing.B) { -+ b.StopTimer() -+ passwd := []byte("somepasswordyoulike") -+ hash, _ := GenerateFromPassword(passwd, DefaultCost) -+ b.StartTimer() -+ for i := 0; i < b.N; i++ { -+ CompareHashAndPassword(hash, passwd) -+ } -+} -+ -+func BenchmarkDefaultCost(b *testing.B) { -+ b.StopTimer() -+ passwd := []byte("mylongpassword1234") -+ b.StartTimer() -+ for i := 0; i < b.N; i++ { -+ GenerateFromPassword(passwd, DefaultCost) -+ } -+} -+ -+// See Issue https://github.com/golang/go/issues/20425. -+func TestNoSideEffectsFromCompare(t *testing.T) { -+ source := []byte("passw0rd123456") -+ password := source[:len(source)-6] -+ token := source[len(source)-6:] -+ want := make([]byte, len(source)) -+ copy(want, source) -+ -+ wantHash := []byte("$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa") -+ _ = CompareHashAndPassword(wantHash, password) -+ -+ got := bytes.Join([][]byte{password, token}, []byte("")) -+ if !bytes.Equal(got, want) { -+ t.Errorf("got=%q want=%q", got, want) -+ } -+} -+ -+func TestPasswordTooLong(t *testing.T) { -+ _, err := GenerateFromPassword(make([]byte, 73), 1) -+ if err != ErrPasswordTooLong { -+ t.Errorf("unexpected error: got %q, want %q", err, ErrPasswordTooLong) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b.go -new file mode 100644 -index 00000000000000..d2e98d4295bdb8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b.go -@@ -0,0 +1,291 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 -+// and the extendable output function (XOF) BLAKE2Xb. -+// -+// BLAKE2b is optimized for 64-bit platformsβ€”including NEON-enabled ARMsβ€”and -+// produces digests of any size between 1 and 64 bytes. -+// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf -+// and for BLAKE2Xb see https://blake2.net/blake2x.pdf -+// -+// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). -+// If you need a secret-key MAC (message authentication code), use the New512 -+// function with a non-nil key. -+// -+// BLAKE2X is a construction to compute hash values larger than 64 bytes. It -+// can produce hash values between 0 and 4 GiB. -+package blake2b -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "hash" -+) -+ -+const ( -+ // The blocksize of BLAKE2b in bytes. -+ BlockSize = 128 -+ // The hash size of BLAKE2b-512 in bytes. -+ Size = 64 -+ // The hash size of BLAKE2b-384 in bytes. -+ Size384 = 48 -+ // The hash size of BLAKE2b-256 in bytes. -+ Size256 = 32 -+) -+ -+var ( -+ useAVX2 bool -+ useAVX bool -+ useSSE4 bool -+) -+ -+var ( -+ errKeySize = errors.New("blake2b: invalid key size") -+ errHashSize = errors.New("blake2b: invalid hash size") -+) -+ -+var iv = [8]uint64{ -+ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, -+ 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, -+} -+ -+// Sum512 returns the BLAKE2b-512 checksum of the data. -+func Sum512(data []byte) [Size]byte { -+ var sum [Size]byte -+ checkSum(&sum, Size, data) -+ return sum -+} -+ -+// Sum384 returns the BLAKE2b-384 checksum of the data. -+func Sum384(data []byte) [Size384]byte { -+ var sum [Size]byte -+ var sum384 [Size384]byte -+ checkSum(&sum, Size384, data) -+ copy(sum384[:], sum[:Size384]) -+ return sum384 -+} -+ -+// Sum256 returns the BLAKE2b-256 checksum of the data. -+func Sum256(data []byte) [Size256]byte { -+ var sum [Size]byte -+ var sum256 [Size256]byte -+ checkSum(&sum, Size256, data) -+ copy(sum256[:], sum[:Size256]) -+ return sum256 -+} -+ -+// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil -+// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } -+ -+// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil -+// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } -+ -+// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil -+// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } -+ -+// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. -+// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. -+// The hash size can be a value between 1 and 64 but it is highly recommended to use -+// values equal or greater than: -+// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). -+// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). -+// When the key is nil, the returned hash.Hash implements BinaryMarshaler -+// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. -+func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } -+ -+func newDigest(hashSize int, key []byte) (*digest, error) { -+ if hashSize < 1 || hashSize > Size { -+ return nil, errHashSize -+ } -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ d := &digest{ -+ size: hashSize, -+ keyLen: len(key), -+ } -+ copy(d.key[:], key) -+ d.Reset() -+ return d, nil -+} -+ -+func checkSum(sum *[Size]byte, hashSize int, data []byte) { -+ h := iv -+ h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) -+ var c [2]uint64 -+ -+ if length := len(data); length > BlockSize { -+ n := length &^ (BlockSize - 1) -+ if length == n { -+ n -= BlockSize -+ } -+ hashBlocks(&h, &c, 0, data[:n]) -+ data = data[n:] -+ } -+ -+ var block [BlockSize]byte -+ offset := copy(block[:], data) -+ remaining := uint64(BlockSize - offset) -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) -+ -+ for i, v := range h[:(hashSize+7)/8] { -+ binary.LittleEndian.PutUint64(sum[8*i:], v) -+ } -+} -+ -+type digest struct { -+ h [8]uint64 -+ c [2]uint64 -+ size int -+ block [BlockSize]byte -+ offset int -+ -+ key [BlockSize]byte -+ keyLen int -+} -+ -+const ( -+ magic = "b2b" -+ marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 -+) -+ -+func (d *digest) MarshalBinary() ([]byte, error) { -+ if d.keyLen != 0 { -+ return nil, errors.New("crypto/blake2b: cannot marshal MACs") -+ } -+ b := make([]byte, 0, marshaledSize) -+ b = append(b, magic...) -+ for i := 0; i < 8; i++ { -+ b = appendUint64(b, d.h[i]) -+ } -+ b = appendUint64(b, d.c[0]) -+ b = appendUint64(b, d.c[1]) -+ // Maximum value for size is 64 -+ b = append(b, byte(d.size)) -+ b = append(b, d.block[:]...) -+ b = append(b, byte(d.offset)) -+ return b, nil -+} -+ -+func (d *digest) UnmarshalBinary(b []byte) error { -+ if len(b) < len(magic) || string(b[:len(magic)]) != magic { -+ return errors.New("crypto/blake2b: invalid hash state identifier") -+ } -+ if len(b) != marshaledSize { -+ return errors.New("crypto/blake2b: invalid hash state size") -+ } -+ b = b[len(magic):] -+ for i := 0; i < 8; i++ { -+ b, d.h[i] = consumeUint64(b) -+ } -+ b, d.c[0] = consumeUint64(b) -+ b, d.c[1] = consumeUint64(b) -+ d.size = int(b[0]) -+ b = b[1:] -+ copy(d.block[:], b[:BlockSize]) -+ b = b[BlockSize:] -+ d.offset = int(b[0]) -+ return nil -+} -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Size() int { return d.size } -+ -+func (d *digest) Reset() { -+ d.h = iv -+ d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ if d.keyLen > 0 { -+ d.block = d.key -+ d.offset = BlockSize -+ } -+} -+ -+func (d *digest) Write(p []byte) (n int, err error) { -+ n = len(p) -+ -+ if d.offset > 0 { -+ remaining := BlockSize - d.offset -+ if n <= remaining { -+ d.offset += copy(d.block[d.offset:], p) -+ return -+ } -+ copy(d.block[d.offset:], p[:remaining]) -+ hashBlocks(&d.h, &d.c, 0, d.block[:]) -+ d.offset = 0 -+ p = p[remaining:] -+ } -+ -+ if length := len(p); length > BlockSize { -+ nn := length &^ (BlockSize - 1) -+ if length == nn { -+ nn -= BlockSize -+ } -+ hashBlocks(&d.h, &d.c, 0, p[:nn]) -+ p = p[nn:] -+ } -+ -+ if len(p) > 0 { -+ d.offset += copy(d.block[:], p) -+ } -+ -+ return -+} -+ -+func (d *digest) Sum(sum []byte) []byte { -+ var hash [Size]byte -+ d.finalize(&hash) -+ return append(sum, hash[:d.size]...) -+} -+ -+func (d *digest) finalize(hash *[Size]byte) { -+ var block [BlockSize]byte -+ copy(block[:], d.block[:d.offset]) -+ remaining := uint64(BlockSize - d.offset) -+ -+ c := d.c -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ h := d.h -+ hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) -+ -+ for i, v := range h { -+ binary.LittleEndian.PutUint64(hash[8*i:], v) -+ } -+} -+ -+func appendUint64(b []byte, x uint64) []byte { -+ var a [8]byte -+ binary.BigEndian.PutUint64(a[:], x) -+ return append(b, a[:]...) -+} -+ -+func appendUint32(b []byte, x uint32) []byte { -+ var a [4]byte -+ binary.BigEndian.PutUint32(a[:], x) -+ return append(b, a[:]...) -+} -+ -+func consumeUint64(b []byte) ([]byte, uint64) { -+ x := binary.BigEndian.Uint64(b) -+ return b[8:], x -+} -+ -+func consumeUint32(b []byte) ([]byte, uint32) { -+ x := binary.BigEndian.Uint32(b) -+ return b[4:], x -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go -new file mode 100644 -index 00000000000000..56bfaaa17da6de ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go -@@ -0,0 +1,38 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.7 && amd64 && gc && !purego -+// +build go1.7,amd64,gc,!purego -+ -+package blake2b -+ -+import "golang.org/x/sys/cpu" -+ -+func init() { -+ useAVX2 = cpu.X86.HasAVX2 -+ useAVX = cpu.X86.HasAVX -+ useSSE4 = cpu.X86.HasSSE41 -+} -+ -+//go:noescape -+func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+//go:noescape -+func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ switch { -+ case useAVX2: -+ hashBlocksAVX2(h, c, flag, blocks) -+ case useAVX: -+ hashBlocksAVX(h, c, flag, blocks) -+ case useSSE4: -+ hashBlocksSSE4(h, c, flag, blocks) -+ default: -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s -new file mode 100644 -index 00000000000000..4b9daa18d9d9c3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s -@@ -0,0 +1,745 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.7 && amd64 && gc && !purego -+// +build go1.7,amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA Β·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -+DATA Β·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -+DATA Β·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b -+DATA Β·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 -+GLOBL Β·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 -+ -+DATA Β·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 -+DATA Β·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -+DATA Β·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b -+DATA Β·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 -+GLOBL Β·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 -+ -+DATA Β·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA Β·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+DATA Β·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 -+DATA Β·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL Β·AVX2_c40<>(SB), (NOPTR+RODATA), $32 -+ -+DATA Β·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA Β·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+DATA Β·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 -+DATA Β·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL Β·AVX2_c48<>(SB), (NOPTR+RODATA), $32 -+ -+DATA Β·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -+DATA Β·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -+GLOBL Β·AVX_iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -+DATA Β·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -+GLOBL Β·AVX_iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 -+DATA Β·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -+GLOBL Β·AVX_iv2<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -+DATA Β·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -+GLOBL Β·AVX_iv3<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA Β·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL Β·AVX_c40<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA Β·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL Β·AVX_c48<>(SB), (NOPTR+RODATA), $16 -+ -+#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 -+#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 -+#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e -+#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 -+#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 -+ -+#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ -+ VPADDQ m0, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFD $-79, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPSHUFB c40, Y1, Y1; \ -+ VPADDQ m1, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFB c48, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPADDQ Y1, Y1, t; \ -+ VPSRLQ $63, Y1, Y1; \ -+ VPXOR t, Y1, Y1; \ -+ VPERMQ_0x39_Y1_Y1; \ -+ VPERMQ_0x4E_Y2_Y2; \ -+ VPERMQ_0x93_Y3_Y3; \ -+ VPADDQ m2, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFD $-79, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPSHUFB c40, Y1, Y1; \ -+ VPADDQ m3, Y0, Y0; \ -+ VPADDQ Y1, Y0, Y0; \ -+ VPXOR Y0, Y3, Y3; \ -+ VPSHUFB c48, Y3, Y3; \ -+ VPADDQ Y3, Y2, Y2; \ -+ VPXOR Y2, Y1, Y1; \ -+ VPADDQ Y1, Y1, t; \ -+ VPSRLQ $63, Y1, Y1; \ -+ VPXOR t, Y1, Y1; \ -+ VPERMQ_0x39_Y3_Y3; \ -+ VPERMQ_0x4E_Y2_Y2; \ -+ VPERMQ_0x93_Y1_Y1 -+ -+#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E -+#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 -+#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E -+#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 -+#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E -+ -+#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n -+#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n -+#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n -+#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n -+#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n -+ -+#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 -+#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 -+#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 -+#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 -+#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 -+ -+#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 -+#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 -+ -+#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 -+#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 -+ -+// load msg: Y12 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ -+ VMOVQ_SI_X12(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X12(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y12, Y12 -+ -+// load msg: Y13 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ -+ VMOVQ_SI_X13(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X13(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y13, Y13 -+ -+// load msg: Y14 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ -+ VMOVQ_SI_X14(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X14(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y14, Y14 -+ -+// load msg: Y15 = (i0, i1, i2, i3) -+// i0, i1, i2, i3 must not be 0 -+#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ -+ VMOVQ_SI_X15(i0*8); \ -+ VMOVQ_SI_X11(i2*8); \ -+ VPINSRQ_1_SI_X15(i1*8); \ -+ VPINSRQ_1_SI_X11(i3*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ -+ VMOVQ_SI_X12_0; \ -+ VMOVQ_SI_X11(4*8); \ -+ VPINSRQ_1_SI_X12(2*8); \ -+ VPINSRQ_1_SI_X11(6*8); \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ -+ LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ -+ LOAD_MSG_AVX2_Y15(9, 11, 13, 15) -+ -+#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ -+ LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ -+ LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ -+ VMOVQ_SI_X11(11*8); \ -+ VPSHUFD $0x4E, 0*8(SI), X14; \ -+ VPINSRQ_1_SI_X11(5*8); \ -+ VINSERTI128 $1, X11, Y14, Y14; \ -+ LOAD_MSG_AVX2_Y15(12, 2, 7, 3) -+ -+#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ -+ VMOVQ_SI_X11(5*8); \ -+ VMOVDQU 11*8(SI), X12; \ -+ VPINSRQ_1_SI_X11(15*8); \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ VMOVQ_SI_X13(8*8); \ -+ VMOVQ_SI_X11(2*8); \ -+ VPINSRQ_1_SI_X13_0; \ -+ VPINSRQ_1_SI_X11(13*8); \ -+ VINSERTI128 $1, X11, Y13, Y13; \ -+ LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ -+ LOAD_MSG_AVX2_Y15(14, 6, 1, 4) -+ -+#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ -+ LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ -+ LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ -+ LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ -+ VMOVQ_SI_X15(6*8); \ -+ VMOVQ_SI_X11_0; \ -+ VPINSRQ_1_SI_X15(10*8); \ -+ VPINSRQ_1_SI_X11(8*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ -+ LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ -+ VMOVQ_SI_X13_0; \ -+ VMOVQ_SI_X11(4*8); \ -+ VPINSRQ_1_SI_X13(7*8); \ -+ VPINSRQ_1_SI_X11(15*8); \ -+ VINSERTI128 $1, X11, Y13, Y13; \ -+ LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ -+ LOAD_MSG_AVX2_Y15(1, 12, 8, 13) -+ -+#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ -+ VMOVQ_SI_X12(2*8); \ -+ VMOVQ_SI_X11_0; \ -+ VPINSRQ_1_SI_X12(6*8); \ -+ VPINSRQ_1_SI_X11(8*8); \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ -+ LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ -+ LOAD_MSG_AVX2_Y15(13, 5, 14, 9) -+ -+#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ -+ LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ -+ LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ -+ VMOVQ_SI_X14_0; \ -+ VPSHUFD $0x4E, 8*8(SI), X11; \ -+ VPINSRQ_1_SI_X14(6*8); \ -+ VINSERTI128 $1, X11, Y14, Y14; \ -+ LOAD_MSG_AVX2_Y15(7, 3, 2, 11) -+ -+#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ -+ LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ -+ LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ -+ LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ -+ VMOVQ_SI_X15_0; \ -+ VMOVQ_SI_X11(6*8); \ -+ VPINSRQ_1_SI_X15(4*8); \ -+ VPINSRQ_1_SI_X11(10*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ -+ VMOVQ_SI_X12(6*8); \ -+ VMOVQ_SI_X11(11*8); \ -+ VPINSRQ_1_SI_X12(14*8); \ -+ VPINSRQ_1_SI_X11_0; \ -+ VINSERTI128 $1, X11, Y12, Y12; \ -+ LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ -+ VMOVQ_SI_X11(1*8); \ -+ VMOVDQU 12*8(SI), X14; \ -+ VPINSRQ_1_SI_X11(10*8); \ -+ VINSERTI128 $1, X11, Y14, Y14; \ -+ VMOVQ_SI_X15(2*8); \ -+ VMOVDQU 4*8(SI), X11; \ -+ VPINSRQ_1_SI_X15(7*8); \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ -+ LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ -+ VMOVQ_SI_X13(2*8); \ -+ VPSHUFD $0x4E, 5*8(SI), X11; \ -+ VPINSRQ_1_SI_X13(4*8); \ -+ VINSERTI128 $1, X11, Y13, Y13; \ -+ LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ -+ VMOVQ_SI_X15(11*8); \ -+ VMOVQ_SI_X11(12*8); \ -+ VPINSRQ_1_SI_X15(14*8); \ -+ VPINSRQ_1_SI_X11_0; \ -+ VINSERTI128 $1, X11, Y15, Y15 -+ -+// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+TEXT Β·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment -+ MOVQ h+0(FP), AX -+ MOVQ c+8(FP), BX -+ MOVQ flag+16(FP), CX -+ MOVQ blocks_base+24(FP), SI -+ MOVQ blocks_len+32(FP), DI -+ -+ MOVQ SP, DX -+ ADDQ $31, DX -+ ANDQ $~31, DX -+ -+ MOVQ CX, 16(DX) -+ XORQ CX, CX -+ MOVQ CX, 24(DX) -+ -+ VMOVDQU Β·AVX2_c40<>(SB), Y4 -+ VMOVDQU Β·AVX2_c48<>(SB), Y5 -+ -+ VMOVDQU 0(AX), Y8 -+ VMOVDQU 32(AX), Y9 -+ VMOVDQU Β·AVX2_iv0<>(SB), Y6 -+ VMOVDQU Β·AVX2_iv1<>(SB), Y7 -+ -+ MOVQ 0(BX), R8 -+ MOVQ 8(BX), R9 -+ MOVQ R9, 8(DX) -+ -+loop: -+ ADDQ $128, R8 -+ MOVQ R8, 0(DX) -+ CMPQ R8, $128 -+ JGE noinc -+ INCQ R9 -+ MOVQ R9, 8(DX) -+ -+noinc: -+ VMOVDQA Y8, Y0 -+ VMOVDQA Y9, Y1 -+ VMOVDQA Y6, Y2 -+ VPXOR 0(DX), Y7, Y3 -+ -+ LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() -+ VMOVDQA Y12, 32(DX) -+ VMOVDQA Y13, 64(DX) -+ VMOVDQA Y14, 96(DX) -+ VMOVDQA Y15, 128(DX) -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() -+ VMOVDQA Y12, 160(DX) -+ VMOVDQA Y13, 192(DX) -+ VMOVDQA Y14, 224(DX) -+ VMOVDQA Y15, 256(DX) -+ -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() -+ ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) -+ -+ ROUND_AVX2(32(DX), 64(DX), 96(DX), 128(DX), Y10, Y4, Y5) -+ ROUND_AVX2(160(DX), 192(DX), 224(DX), 256(DX), Y10, Y4, Y5) -+ -+ VPXOR Y0, Y8, Y8 -+ VPXOR Y1, Y9, Y9 -+ VPXOR Y2, Y8, Y8 -+ VPXOR Y3, Y9, Y9 -+ -+ LEAQ 128(SI), SI -+ SUBQ $128, DI -+ JNE loop -+ -+ MOVQ R8, 0(BX) -+ MOVQ R9, 8(BX) -+ -+ VMOVDQU Y8, 0(AX) -+ VMOVDQU Y9, 32(AX) -+ VZEROUPPER -+ -+ RET -+ -+#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA -+#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB -+#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF -+#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD -+#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE -+ -+#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 -+#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF -+#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 -+#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF -+#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 -+#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 -+#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF -+#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF -+ -+#define SHUFFLE_AVX() \ -+ VMOVDQA X6, X13; \ -+ VMOVDQA X2, X14; \ -+ VMOVDQA X4, X6; \ -+ VPUNPCKLQDQ_X13_X13_X15; \ -+ VMOVDQA X5, X4; \ -+ VMOVDQA X6, X5; \ -+ VPUNPCKHQDQ_X15_X7_X6; \ -+ VPUNPCKLQDQ_X7_X7_X15; \ -+ VPUNPCKHQDQ_X15_X13_X7; \ -+ VPUNPCKLQDQ_X3_X3_X15; \ -+ VPUNPCKHQDQ_X15_X2_X2; \ -+ VPUNPCKLQDQ_X14_X14_X15; \ -+ VPUNPCKHQDQ_X15_X3_X3; \ -+ -+#define SHUFFLE_AVX_INV() \ -+ VMOVDQA X2, X13; \ -+ VMOVDQA X4, X14; \ -+ VPUNPCKLQDQ_X2_X2_X15; \ -+ VMOVDQA X5, X4; \ -+ VPUNPCKHQDQ_X15_X3_X2; \ -+ VMOVDQA X14, X5; \ -+ VPUNPCKLQDQ_X3_X3_X15; \ -+ VMOVDQA X6, X14; \ -+ VPUNPCKHQDQ_X15_X13_X3; \ -+ VPUNPCKLQDQ_X7_X7_X15; \ -+ VPUNPCKHQDQ_X15_X6_X6; \ -+ VPUNPCKLQDQ_X14_X14_X15; \ -+ VPUNPCKHQDQ_X15_X7_X7; \ -+ -+#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ -+ VPADDQ m0, v0, v0; \ -+ VPADDQ v2, v0, v0; \ -+ VPADDQ m1, v1, v1; \ -+ VPADDQ v3, v1, v1; \ -+ VPXOR v0, v6, v6; \ -+ VPXOR v1, v7, v7; \ -+ VPSHUFD $-79, v6, v6; \ -+ VPSHUFD $-79, v7, v7; \ -+ VPADDQ v6, v4, v4; \ -+ VPADDQ v7, v5, v5; \ -+ VPXOR v4, v2, v2; \ -+ VPXOR v5, v3, v3; \ -+ VPSHUFB c40, v2, v2; \ -+ VPSHUFB c40, v3, v3; \ -+ VPADDQ m2, v0, v0; \ -+ VPADDQ v2, v0, v0; \ -+ VPADDQ m3, v1, v1; \ -+ VPADDQ v3, v1, v1; \ -+ VPXOR v0, v6, v6; \ -+ VPXOR v1, v7, v7; \ -+ VPSHUFB c48, v6, v6; \ -+ VPSHUFB c48, v7, v7; \ -+ VPADDQ v6, v4, v4; \ -+ VPADDQ v7, v5, v5; \ -+ VPXOR v4, v2, v2; \ -+ VPXOR v5, v3, v3; \ -+ VPADDQ v2, v2, t0; \ -+ VPSRLQ $63, v2, v2; \ -+ VPXOR t0, v2, v2; \ -+ VPADDQ v3, v3, t0; \ -+ VPSRLQ $63, v3, v3; \ -+ VPXOR t0, v3, v3 -+ -+// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) -+// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 -+#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ -+ VMOVQ_SI_X12(i0*8); \ -+ VMOVQ_SI_X13(i2*8); \ -+ VMOVQ_SI_X14(i4*8); \ -+ VMOVQ_SI_X15(i6*8); \ -+ VPINSRQ_1_SI_X12(i1*8); \ -+ VPINSRQ_1_SI_X13(i3*8); \ -+ VPINSRQ_1_SI_X14(i5*8); \ -+ VPINSRQ_1_SI_X15(i7*8) -+ -+// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) -+#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ -+ VMOVQ_SI_X12_0; \ -+ VMOVQ_SI_X13(4*8); \ -+ VMOVQ_SI_X14(1*8); \ -+ VMOVQ_SI_X15(5*8); \ -+ VPINSRQ_1_SI_X12(2*8); \ -+ VPINSRQ_1_SI_X13(6*8); \ -+ VPINSRQ_1_SI_X14(3*8); \ -+ VPINSRQ_1_SI_X15(7*8) -+ -+// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) -+#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ -+ VPSHUFD $0x4E, 0*8(SI), X12; \ -+ VMOVQ_SI_X13(11*8); \ -+ VMOVQ_SI_X14(12*8); \ -+ VMOVQ_SI_X15(7*8); \ -+ VPINSRQ_1_SI_X13(5*8); \ -+ VPINSRQ_1_SI_X14(2*8); \ -+ VPINSRQ_1_SI_X15(3*8) -+ -+// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) -+#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ -+ VMOVDQU 11*8(SI), X12; \ -+ VMOVQ_SI_X13(5*8); \ -+ VMOVQ_SI_X14(8*8); \ -+ VMOVQ_SI_X15(2*8); \ -+ VPINSRQ_1_SI_X13(15*8); \ -+ VPINSRQ_1_SI_X14_0; \ -+ VPINSRQ_1_SI_X15(13*8) -+ -+// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) -+#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ -+ VMOVQ_SI_X12(2*8); \ -+ VMOVQ_SI_X13(4*8); \ -+ VMOVQ_SI_X14(6*8); \ -+ VMOVQ_SI_X15_0; \ -+ VPINSRQ_1_SI_X12(5*8); \ -+ VPINSRQ_1_SI_X13(15*8); \ -+ VPINSRQ_1_SI_X14(10*8); \ -+ VPINSRQ_1_SI_X15(8*8) -+ -+// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) -+#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ -+ VMOVQ_SI_X12(9*8); \ -+ VMOVQ_SI_X13(2*8); \ -+ VMOVQ_SI_X14_0; \ -+ VMOVQ_SI_X15(4*8); \ -+ VPINSRQ_1_SI_X12(5*8); \ -+ VPINSRQ_1_SI_X13(10*8); \ -+ VPINSRQ_1_SI_X14(7*8); \ -+ VPINSRQ_1_SI_X15(15*8) -+ -+// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) -+#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ -+ VMOVQ_SI_X12(2*8); \ -+ VMOVQ_SI_X13_0; \ -+ VMOVQ_SI_X14(12*8); \ -+ VMOVQ_SI_X15(11*8); \ -+ VPINSRQ_1_SI_X12(6*8); \ -+ VPINSRQ_1_SI_X13(8*8); \ -+ VPINSRQ_1_SI_X14(10*8); \ -+ VPINSRQ_1_SI_X15(3*8) -+ -+// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) -+#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ -+ MOVQ 0*8(SI), X12; \ -+ VPSHUFD $0x4E, 8*8(SI), X13; \ -+ MOVQ 7*8(SI), X14; \ -+ MOVQ 2*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(6*8); \ -+ VPINSRQ_1_SI_X14(3*8); \ -+ VPINSRQ_1_SI_X15(11*8) -+ -+// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) -+#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ -+ MOVQ 6*8(SI), X12; \ -+ MOVQ 11*8(SI), X13; \ -+ MOVQ 15*8(SI), X14; \ -+ MOVQ 3*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(14*8); \ -+ VPINSRQ_1_SI_X13_0; \ -+ VPINSRQ_1_SI_X14(9*8); \ -+ VPINSRQ_1_SI_X15(8*8) -+ -+// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) -+#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ -+ MOVQ 5*8(SI), X12; \ -+ MOVQ 8*8(SI), X13; \ -+ MOVQ 0*8(SI), X14; \ -+ MOVQ 6*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(15*8); \ -+ VPINSRQ_1_SI_X13(2*8); \ -+ VPINSRQ_1_SI_X14(4*8); \ -+ VPINSRQ_1_SI_X15(10*8) -+ -+// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) -+#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ -+ VMOVDQU 12*8(SI), X12; \ -+ MOVQ 1*8(SI), X13; \ -+ MOVQ 2*8(SI), X14; \ -+ VPINSRQ_1_SI_X13(10*8); \ -+ VPINSRQ_1_SI_X14(7*8); \ -+ VMOVDQU 4*8(SI), X15 -+ -+// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) -+#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ -+ MOVQ 15*8(SI), X12; \ -+ MOVQ 3*8(SI), X13; \ -+ MOVQ 11*8(SI), X14; \ -+ MOVQ 12*8(SI), X15; \ -+ VPINSRQ_1_SI_X12(9*8); \ -+ VPINSRQ_1_SI_X13(13*8); \ -+ VPINSRQ_1_SI_X14(14*8); \ -+ VPINSRQ_1_SI_X15_0 -+ -+// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+TEXT Β·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment -+ MOVQ h+0(FP), AX -+ MOVQ c+8(FP), BX -+ MOVQ flag+16(FP), CX -+ MOVQ blocks_base+24(FP), SI -+ MOVQ blocks_len+32(FP), DI -+ -+ MOVQ SP, R10 -+ ADDQ $15, R10 -+ ANDQ $~15, R10 -+ -+ VMOVDQU Β·AVX_c40<>(SB), X0 -+ VMOVDQU Β·AVX_c48<>(SB), X1 -+ VMOVDQA X0, X8 -+ VMOVDQA X1, X9 -+ -+ VMOVDQU Β·AVX_iv3<>(SB), X0 -+ VMOVDQA X0, 0(R10) -+ XORQ CX, 0(R10) // 0(R10) = Β·AVX_iv3 ^ (CX || 0) -+ -+ VMOVDQU 0(AX), X10 -+ VMOVDQU 16(AX), X11 -+ VMOVDQU 32(AX), X2 -+ VMOVDQU 48(AX), X3 -+ -+ MOVQ 0(BX), R8 -+ MOVQ 8(BX), R9 -+ -+loop: -+ ADDQ $128, R8 -+ CMPQ R8, $128 -+ JGE noinc -+ INCQ R9 -+ -+noinc: -+ VMOVQ_R8_X15 -+ VPINSRQ_1_R9_X15 -+ -+ VMOVDQA X10, X0 -+ VMOVDQA X11, X1 -+ VMOVDQU Β·AVX_iv0<>(SB), X4 -+ VMOVDQU Β·AVX_iv1<>(SB), X5 -+ VMOVDQU Β·AVX_iv2<>(SB), X6 -+ -+ VPXOR X15, X6, X6 -+ VMOVDQA 0(R10), X7 -+ -+ LOAD_MSG_AVX_0_2_4_6_1_3_5_7() -+ VMOVDQA X12, 16(R10) -+ VMOVDQA X13, 32(R10) -+ VMOVDQA X14, 48(R10) -+ VMOVDQA X15, 64(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) -+ VMOVDQA X12, 80(R10) -+ VMOVDQA X13, 96(R10) -+ VMOVDQA X14, 112(R10) -+ VMOVDQA X15, 128(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) -+ VMOVDQA X12, 144(R10) -+ VMOVDQA X13, 160(R10) -+ VMOVDQA X14, 176(R10) -+ VMOVDQA X15, 192(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_1_0_11_5_12_2_7_3() -+ VMOVDQA X12, 208(R10) -+ VMOVDQA X13, 224(R10) -+ VMOVDQA X14, 240(R10) -+ VMOVDQA X15, 256(R10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_11_12_5_15_8_0_2_13() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_2_5_4_15_6_10_0_8() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_9_5_2_10_0_7_4_15() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_2_6_0_8_12_10_11_3() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_0_6_9_8_7_3_2_11() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_5_15_8_2_0_4_6_10() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX_6_14_11_0_15_9_3_8() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_12_13_1_10_2_7_4_5() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX() -+ LOAD_MSG_AVX_15_9_3_13_11_14_12_0() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X15, X8, X9) -+ SHUFFLE_AVX() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X15, X8, X9) -+ SHUFFLE_AVX() -+ HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X15, X8, X9) -+ SHUFFLE_AVX_INV() -+ -+ VMOVDQU 32(AX), X14 -+ VMOVDQU 48(AX), X15 -+ VPXOR X0, X10, X10 -+ VPXOR X1, X11, X11 -+ VPXOR X2, X14, X14 -+ VPXOR X3, X15, X15 -+ VPXOR X4, X10, X10 -+ VPXOR X5, X11, X11 -+ VPXOR X6, X14, X2 -+ VPXOR X7, X15, X3 -+ VMOVDQU X2, 32(AX) -+ VMOVDQU X3, 48(AX) -+ -+ LEAQ 128(SI), SI -+ SUBQ $128, DI -+ JNE loop -+ -+ VMOVDQU X10, 0(AX) -+ VMOVDQU X11, 16(AX) -+ -+ MOVQ R8, 0(BX) -+ MOVQ R9, 8(BX) -+ VZEROUPPER -+ -+ RET -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go -new file mode 100644 -index 00000000000000..5fa1b32841df3a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.go -@@ -0,0 +1,25 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !go1.7 && amd64 && gc && !purego -+// +build !go1.7,amd64,gc,!purego -+ -+package blake2b -+ -+import "golang.org/x/sys/cpu" -+ -+func init() { -+ useSSE4 = cpu.X86.HasSSE41 -+} -+ -+//go:noescape -+func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+ -+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ if useSSE4 { -+ hashBlocksSSE4(h, c, flag, blocks) -+ } else { -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s -new file mode 100644 -index 00000000000000..ae75eb9afcd7a1 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_amd64.s -@@ -0,0 +1,279 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA Β·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -+DATA Β·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -+GLOBL Β·iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -+DATA Β·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -+GLOBL Β·iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·iv2<>+0x00(SB)/8, $0x510e527fade682d1 -+DATA Β·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -+GLOBL Β·iv2<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -+DATA Β·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -+GLOBL Β·iv3<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·c40<>+0x00(SB)/8, $0x0201000706050403 -+DATA Β·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -+GLOBL Β·c40<>(SB), (NOPTR+RODATA), $16 -+ -+DATA Β·c48<>+0x00(SB)/8, $0x0100070605040302 -+DATA Β·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -+GLOBL Β·c48<>(SB), (NOPTR+RODATA), $16 -+ -+#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v6, t1; \ -+ PUNPCKLQDQ v6, t2; \ -+ PUNPCKHQDQ v7, v6; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ v7, t2; \ -+ MOVO t1, v7; \ -+ MOVO v2, t1; \ -+ PUNPCKHQDQ t2, v7; \ -+ PUNPCKLQDQ v3, t2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v3 -+ -+#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ -+ MOVO v4, t1; \ -+ MOVO v5, v4; \ -+ MOVO t1, v5; \ -+ MOVO v2, t1; \ -+ PUNPCKLQDQ v2, t2; \ -+ PUNPCKHQDQ v3, v2; \ -+ PUNPCKHQDQ t2, v2; \ -+ PUNPCKLQDQ v3, t2; \ -+ MOVO t1, v3; \ -+ MOVO v6, t1; \ -+ PUNPCKHQDQ t2, v3; \ -+ PUNPCKLQDQ v7, t2; \ -+ PUNPCKHQDQ t2, v6; \ -+ PUNPCKLQDQ t1, t2; \ -+ PUNPCKHQDQ t2, v7 -+ -+#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ -+ PADDQ m0, v0; \ -+ PADDQ m1, v1; \ -+ PADDQ v2, v0; \ -+ PADDQ v3, v1; \ -+ PXOR v0, v6; \ -+ PXOR v1, v7; \ -+ PSHUFD $0xB1, v6, v6; \ -+ PSHUFD $0xB1, v7, v7; \ -+ PADDQ v6, v4; \ -+ PADDQ v7, v5; \ -+ PXOR v4, v2; \ -+ PXOR v5, v3; \ -+ PSHUFB c40, v2; \ -+ PSHUFB c40, v3; \ -+ PADDQ m2, v0; \ -+ PADDQ m3, v1; \ -+ PADDQ v2, v0; \ -+ PADDQ v3, v1; \ -+ PXOR v0, v6; \ -+ PXOR v1, v7; \ -+ PSHUFB c48, v6; \ -+ PSHUFB c48, v7; \ -+ PADDQ v6, v4; \ -+ PADDQ v7, v5; \ -+ PXOR v4, v2; \ -+ PXOR v5, v3; \ -+ MOVOU v2, t0; \ -+ PADDQ v2, t0; \ -+ PSRLQ $63, v2; \ -+ PXOR t0, v2; \ -+ MOVOU v3, t0; \ -+ PADDQ v3, t0; \ -+ PSRLQ $63, v3; \ -+ PXOR t0, v3 -+ -+#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ -+ MOVQ i0*8(src), m0; \ -+ PINSRQ $1, i1*8(src), m0; \ -+ MOVQ i2*8(src), m1; \ -+ PINSRQ $1, i3*8(src), m1; \ -+ MOVQ i4*8(src), m2; \ -+ PINSRQ $1, i5*8(src), m2; \ -+ MOVQ i6*8(src), m3; \ -+ PINSRQ $1, i7*8(src), m3 -+ -+// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) -+TEXT Β·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment -+ MOVQ h+0(FP), AX -+ MOVQ c+8(FP), BX -+ MOVQ flag+16(FP), CX -+ MOVQ blocks_base+24(FP), SI -+ MOVQ blocks_len+32(FP), DI -+ -+ MOVQ SP, R10 -+ ADDQ $15, R10 -+ ANDQ $~15, R10 -+ -+ MOVOU Β·iv3<>(SB), X0 -+ MOVO X0, 0(R10) -+ XORQ CX, 0(R10) // 0(R10) = Β·iv3 ^ (CX || 0) -+ -+ MOVOU Β·c40<>(SB), X13 -+ MOVOU Β·c48<>(SB), X14 -+ -+ MOVOU 0(AX), X12 -+ MOVOU 16(AX), X15 -+ -+ MOVQ 0(BX), R8 -+ MOVQ 8(BX), R9 -+ -+loop: -+ ADDQ $128, R8 -+ CMPQ R8, $128 -+ JGE noinc -+ INCQ R9 -+ -+noinc: -+ MOVQ R8, X8 -+ PINSRQ $1, R9, X8 -+ -+ MOVO X12, X0 -+ MOVO X15, X1 -+ MOVOU 32(AX), X2 -+ MOVOU 48(AX), X3 -+ MOVOU Β·iv0<>(SB), X4 -+ MOVOU Β·iv1<>(SB), X5 -+ MOVOU Β·iv2<>(SB), X6 -+ -+ PXOR X8, X6 -+ MOVO 0(R10), X7 -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) -+ MOVO X8, 16(R10) -+ MOVO X9, 32(R10) -+ MOVO X10, 48(R10) -+ MOVO X11, 64(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) -+ MOVO X8, 80(R10) -+ MOVO X9, 96(R10) -+ MOVO X10, 112(R10) -+ MOVO X11, 128(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) -+ MOVO X8, 144(R10) -+ MOVO X9, 160(R10) -+ MOVO X10, 176(R10) -+ MOVO X11, 192(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) -+ MOVO X8, 208(R10) -+ MOVO X9, 224(R10) -+ MOVO X10, 240(R10) -+ MOVO X11, 256(R10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X11, X13, X14) -+ SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) -+ HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X11, X13, X14) -+ SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) -+ -+ MOVOU 32(AX), X10 -+ MOVOU 48(AX), X11 -+ PXOR X0, X12 -+ PXOR X1, X15 -+ PXOR X2, X10 -+ PXOR X3, X11 -+ PXOR X4, X12 -+ PXOR X5, X15 -+ PXOR X6, X10 -+ PXOR X7, X11 -+ MOVOU X10, 32(AX) -+ MOVOU X11, 48(AX) -+ -+ LEAQ 128(SI), SI -+ SUBQ $128, DI -+ JNE loop -+ -+ MOVOU X12, 0(AX) -+ MOVOU X15, 16(AX) -+ -+ MOVQ R8, 0(BX) -+ MOVQ R9, 8(BX) -+ -+ RET -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go -new file mode 100644 -index 00000000000000..3168a8aa3c834a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_generic.go -@@ -0,0 +1,182 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2b -+ -+import ( -+ "encoding/binary" -+ "math/bits" -+) -+ -+// the precomputed values for BLAKE2b -+// there are 12 16-byte arrays - one for each round -+// the entries are calculated from the sigma constants. -+var precomputed = [12][16]byte{ -+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, -+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, -+ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, -+ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, -+ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, -+ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, -+ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, -+ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, -+ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, -+ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, -+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first -+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second -+} -+ -+func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ var m [16]uint64 -+ c0, c1 := c[0], c[1] -+ -+ for i := 0; i < len(blocks); { -+ c0 += BlockSize -+ if c0 < BlockSize { -+ c1++ -+ } -+ -+ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] -+ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] -+ v12 ^= c0 -+ v13 ^= c1 -+ v14 ^= flag -+ -+ for j := range m { -+ m[j] = binary.LittleEndian.Uint64(blocks[i:]) -+ i += 8 -+ } -+ -+ for j := range precomputed { -+ s := &(precomputed[j]) -+ -+ v0 += m[s[0]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft64(v12, -32) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft64(v4, -24) -+ v1 += m[s[1]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft64(v13, -32) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft64(v5, -24) -+ v2 += m[s[2]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft64(v14, -32) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft64(v6, -24) -+ v3 += m[s[3]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft64(v15, -32) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft64(v7, -24) -+ -+ v0 += m[s[4]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft64(v12, -16) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft64(v4, -63) -+ v1 += m[s[5]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft64(v13, -16) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft64(v5, -63) -+ v2 += m[s[6]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft64(v14, -16) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft64(v6, -63) -+ v3 += m[s[7]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft64(v15, -16) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft64(v7, -63) -+ -+ v0 += m[s[8]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft64(v15, -32) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft64(v5, -24) -+ v1 += m[s[9]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft64(v12, -32) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft64(v6, -24) -+ v2 += m[s[10]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft64(v13, -32) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft64(v7, -24) -+ v3 += m[s[11]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft64(v14, -32) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft64(v4, -24) -+ -+ v0 += m[s[12]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft64(v15, -16) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft64(v5, -63) -+ v1 += m[s[13]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft64(v12, -16) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft64(v6, -63) -+ v2 += m[s[14]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft64(v13, -16) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft64(v7, -63) -+ v3 += m[s[15]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft64(v14, -16) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft64(v4, -63) -+ -+ } -+ -+ h[0] ^= v0 ^ v8 -+ h[1] ^= v1 ^ v9 -+ h[2] ^= v2 ^ v10 -+ h[3] ^= v3 ^ v11 -+ h[4] ^= v4 ^ v12 -+ h[5] ^= v5 ^ v13 -+ h[6] ^= v6 ^ v14 -+ h[7] ^= v7 ^ v15 -+ } -+ c[0], c[1] = c0, c1 -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go -new file mode 100644 -index 00000000000000..b0137cdf025cb1 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_ref.go -@@ -0,0 +1,12 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package blake2b -+ -+func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { -+ hashBlocksGeneric(h, c, flag, blocks) -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go b/ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go -new file mode 100644 -index 00000000000000..723327ab563e5e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2b_test.go -@@ -0,0 +1,847 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2b -+ -+import ( -+ "bytes" -+ "encoding" -+ "encoding/hex" -+ "fmt" -+ "hash" -+ "io" -+ "testing" -+) -+ -+func fromHex(s string) []byte { -+ b, err := hex.DecodeString(s) -+ if err != nil { -+ panic(err) -+ } -+ return b -+} -+ -+func TestHashes(t *testing.T) { -+ defer func(sse4, avx, avx2 bool) { -+ useSSE4, useAVX, useAVX2 = sse4, avx, avx2 -+ }(useSSE4, useAVX, useAVX2) -+ -+ if useAVX2 { -+ t.Log("AVX2 version") -+ testHashes(t) -+ useAVX2 = false -+ } -+ if useAVX { -+ t.Log("AVX version") -+ testHashes(t) -+ useAVX = false -+ } -+ if useSSE4 { -+ t.Log("SSE4 version") -+ testHashes(t) -+ useSSE4 = false -+ } -+ t.Log("generic version") -+ testHashes(t) -+} -+ -+func TestHashes2X(t *testing.T) { -+ defer func(sse4, avx, avx2 bool) { -+ useSSE4, useAVX, useAVX2 = sse4, avx, avx2 -+ }(useSSE4, useAVX, useAVX2) -+ -+ if useAVX2 { -+ t.Log("AVX2 version") -+ testHashes2X(t) -+ useAVX2 = false -+ } -+ if useAVX { -+ t.Log("AVX version") -+ testHashes2X(t) -+ useAVX = false -+ } -+ if useSSE4 { -+ t.Log("SSE4 version") -+ testHashes2X(t) -+ useSSE4 = false -+ } -+ t.Log("generic version") -+ testHashes2X(t) -+} -+ -+func TestMarshal(t *testing.T) { -+ input := make([]byte, 255) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ for _, size := range []int{Size, Size256, Size384, 12, 25, 63} { -+ for i := 0; i < 256; i++ { -+ h, err := New(size, nil) -+ if err != nil { -+ t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) -+ } -+ h2, err := New(size, nil) -+ if err != nil { -+ t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) -+ } -+ -+ h.Write(input[:i/2]) -+ halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() -+ if err != nil { -+ t.Fatalf("size=%d, len(input)=%d: could not marshal: %v", size, i, err) -+ } -+ err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) -+ if err != nil { -+ t.Fatalf("size=%d, len(input)=%d: could not unmarshal: %v", size, i, err) -+ } -+ -+ h.Write(input[i/2 : i]) -+ sum := h.Sum(nil) -+ h2.Write(input[i/2 : i]) -+ sum2 := h2.Sum(nil) -+ -+ if !bytes.Equal(sum, sum2) { -+ t.Fatalf("size=%d, len(input)=%d: results do not match; sum = %v, sum2 = %v", size, i, sum, sum2) -+ } -+ -+ h3, err := New(size, nil) -+ if err != nil { -+ t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) -+ } -+ h3.Write(input[:i]) -+ sum3 := h3.Sum(nil) -+ if !bytes.Equal(sum, sum3) { -+ t.Fatalf("size=%d, len(input)=%d: sum = %v, want %v", size, i, sum, sum3) -+ } -+ } -+ } -+} -+ -+func testHashes(t *testing.T) { -+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") -+ -+ input := make([]byte, 255) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ -+ for i, expectedHex := range hashes { -+ h, err := New512(key) -+ if err != nil { -+ t.Fatalf("#%d: error from New512: %v", i, err) -+ } -+ -+ h.Write(input[:i]) -+ sum := h.Sum(nil) -+ -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(input[j : j+1]) -+ } -+ -+ sum = h.Sum(sum[:0]) -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ } -+} -+ -+func testHashes2X(t *testing.T) { -+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") -+ -+ input := make([]byte, 256) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ -+ for i, expectedHex := range hashes2X { -+ length := uint32(len(expectedHex) / 2) -+ sum := make([]byte, int(length)) -+ -+ h, err := NewXOF(length, key) -+ if err != nil { -+ t.Fatalf("#%d: error from NewXOF: %v", i, err) -+ } -+ -+ if _, err := h.Write(input); err != nil { -+ t.Fatalf("#%d (single write): error from Write: %v", i, err) -+ } -+ if _, err := h.Read(sum); err != nil { -+ t.Fatalf("#%d (single write): error from Read: %v", i, err) -+ } -+ if n, err := h.Read(sum); n != 0 || err != io.EOF { -+ t.Fatalf("#%d (single write): Read did not return (0, io.EOF) after exhaustion, got (%v, %v)", i, n, err) -+ } -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ -+ h.Reset() -+ for j := 0; j < len(input); j++ { -+ h.Write(input[j : j+1]) -+ } -+ for j := 0; j < len(sum); j++ { -+ h = h.Clone() -+ if _, err := h.Read(sum[j : j+1]); err != nil { -+ t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) -+ } -+ } -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ } -+ -+ h, err := NewXOF(OutputLengthUnknown, key) -+ if err != nil { -+ t.Fatalf("#unknown length: error from NewXOF: %v", err) -+ } -+ if _, err := h.Write(input); err != nil { -+ t.Fatalf("#unknown length: error from Write: %v", err) -+ } -+ -+ var result [64]byte -+ if n, err := h.Read(result[:]); err != nil { -+ t.Fatalf("#unknown length: error from Read: %v", err) -+ } else if n != len(result) { -+ t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) -+ } -+ -+ const expected = "3dbba8516da76bf7330055c66ea36cf1005e92714262b24d9710f51d9e126406e1bcd6497059f9331f1091c3634b695428d475ed432f987040575520a1c29f5e" -+ if fmt.Sprintf("%x", result) != expected { -+ t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) -+ } -+} -+ -+func generateSequence(out []byte, seed uint32) { -+ a := 0xDEAD4BAD * seed // prime -+ b := uint32(1) -+ -+ for i := range out { // fill the buf -+ a, b = b, a+b -+ out[i] = byte(b >> 24) -+ } -+} -+ -+func computeMAC(msg []byte, hashSize int, key []byte) (sum []byte) { -+ var h hash.Hash -+ switch hashSize { -+ case Size: -+ h, _ = New512(key) -+ case Size384: -+ h, _ = New384(key) -+ case Size256: -+ h, _ = New256(key) -+ case 20: -+ h, _ = newDigest(20, key) -+ default: -+ panic("unexpected hashSize") -+ } -+ -+ h.Write(msg) -+ return h.Sum(sum) -+} -+ -+func computeHash(msg []byte, hashSize int) (sum []byte) { -+ switch hashSize { -+ case Size: -+ hash := Sum512(msg) -+ return hash[:] -+ case Size384: -+ hash := Sum384(msg) -+ return hash[:] -+ case Size256: -+ hash := Sum256(msg) -+ return hash[:] -+ case 20: -+ var hash [64]byte -+ checkSum(&hash, 20, msg) -+ return hash[:20] -+ default: -+ panic("unexpected hashSize") -+ } -+} -+ -+// Test function from RFC 7693. -+func TestSelfTest(t *testing.T) { -+ hashLens := [4]int{20, 32, 48, 64} -+ msgLens := [6]int{0, 3, 128, 129, 255, 1024} -+ -+ msg := make([]byte, 1024) -+ key := make([]byte, 64) -+ -+ h, _ := New256(nil) -+ for _, hashSize := range hashLens { -+ for _, msgLength := range msgLens { -+ generateSequence(msg[:msgLength], uint32(msgLength)) // unkeyed hash -+ -+ md := computeHash(msg[:msgLength], hashSize) -+ h.Write(md) -+ -+ generateSequence(key[:], uint32(hashSize)) // keyed hash -+ md = computeMAC(msg[:msgLength], hashSize, key[:hashSize]) -+ h.Write(md) -+ } -+ } -+ -+ sum := h.Sum(nil) -+ expected := [32]byte{ -+ 0xc2, 0x3a, 0x78, 0x00, 0xd9, 0x81, 0x23, 0xbd, -+ 0x10, 0xf5, 0x06, 0xc6, 0x1e, 0x29, 0xda, 0x56, -+ 0x03, 0xd7, 0x63, 0xb8, 0xbb, 0xad, 0x2e, 0x73, -+ 0x7f, 0x5e, 0x76, 0x5a, 0x7b, 0xcc, 0xd4, 0x75, -+ } -+ if !bytes.Equal(sum, expected[:]) { -+ t.Fatalf("got %x, wanted %x", sum, expected) -+ } -+} -+ -+// Benchmarks -+ -+func benchmarkSum(b *testing.B, size int) { -+ data := make([]byte, size) -+ b.SetBytes(int64(size)) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ Sum512(data) -+ } -+} -+ -+func benchmarkWrite(b *testing.B, size int) { -+ data := make([]byte, size) -+ h, _ := New512(nil) -+ b.SetBytes(int64(size)) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ h.Write(data) -+ } -+} -+ -+func BenchmarkWrite128(b *testing.B) { benchmarkWrite(b, 128) } -+func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } -+ -+func BenchmarkSum128(b *testing.B) { benchmarkSum(b, 128) } -+func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } -+ -+// These values were taken from https://blake2.net/blake2b-test.txt. -+var hashes = []string{ -+ "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568", -+ "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd", -+ "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965", -+ "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1", -+ "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac", -+ "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb", -+ "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f", -+ "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52", -+ "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9", -+ "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637", -+ "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd", -+ "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b", -+ "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563", -+ "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355", -+ "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6", -+ "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e", -+ "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93", -+ "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1", -+ "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670", -+ "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9", -+ "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c", -+ "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd", -+ "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152", -+ "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9", -+ "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f", -+ "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b", -+ "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764", -+ "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d", -+ "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55", -+ "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b", -+ "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e", -+ "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7", -+ "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991", -+ "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347", -+ "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82", -+ "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42", -+ "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327", -+ "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760", -+ "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252", -+ "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55", -+ "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1", -+ "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee", -+ "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa", -+ "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7", -+ "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071", -+ "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4", -+ "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf", -+ "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d", -+ "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8", -+ "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487", -+ "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c", -+ "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2", -+ "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa", -+ "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33", -+ "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d", -+ "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e", -+ "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2", -+ "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4", -+ "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2", -+ "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a", -+ "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564", -+ "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f", -+ "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9", -+ "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa", -+ "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022", -+ "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c", -+ "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc", -+ "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f", -+ "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b", -+ "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866", -+ "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d", -+ "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8", -+ "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4", -+ "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3", -+ "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e", -+ "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745", -+ "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545", -+ "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063", -+ "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd", -+ "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a", -+ "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed", -+ "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd", -+ "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275", -+ "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897", -+ "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430", -+ "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab", -+ "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f", -+ "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46", -+ "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29", -+ "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab", -+ "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8", -+ "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a", -+ "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec", -+ "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79", -+ "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24", -+ "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b", -+ "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5", -+ "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463", -+ "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4", -+ "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3", -+ "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9", -+ "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d", -+ "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4", -+ "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a", -+ "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6", -+ "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73", -+ "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6", -+ "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6", -+ "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3", -+ "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa", -+ "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3", -+ "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b", -+ "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f", -+ "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc", -+ "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200", -+ "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6", -+ "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8", -+ "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f", -+ "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a", -+ "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e", -+ "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935", -+ "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74", -+ "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0", -+ "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c", -+ "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145", -+ "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f", -+ "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0", -+ "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb", -+ "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4", -+ "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91", -+ "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89", -+ "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444", -+ "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a", -+ "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414", -+ "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49", -+ "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b", -+ "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0", -+ "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469", -+ "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3", -+ "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd", -+ "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8", -+ "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21", -+ "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989", -+ "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1", -+ "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399", -+ "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0", -+ "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723", -+ "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff", -+ "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc", -+ "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38", -+ "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a", -+ "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051", -+ "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca", -+ "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4", -+ "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677", -+ "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1", -+ "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce", -+ "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347", -+ "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91", -+ "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209", -+ "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659", -+ "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381", -+ "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56", -+ "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7", -+ "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f", -+ "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972", -+ "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe", -+ "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e", -+ "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be", -+ "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8", -+ "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc", -+ "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8", -+ "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0", -+ "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc", -+ "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979", -+ "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29", -+ "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d", -+ "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108", -+ "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45", -+ "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4", -+ "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267", -+ "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d", -+ "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb", -+ "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813", -+ "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc", -+ "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29", -+ "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc", -+ "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16", -+ "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1", -+ "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c", -+ "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7", -+ "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a", -+ "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa", -+ "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e", -+ "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc", -+ "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5", -+ "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a", -+ "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3", -+ "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc", -+ "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d", -+ "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff", -+ "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb", -+ "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4", -+ "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc", -+ "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902", -+ "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e", -+ "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08", -+ "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816", -+ "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406", -+ "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4", -+ "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d", -+ "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d", -+ "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900", -+ "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06", -+ "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01", -+ "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0", -+ "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94", -+ "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02", -+ "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492", -+ "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2", -+ "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c", -+ "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb", -+ "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077", -+ "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727", -+ "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd", -+ "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c", -+ "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0", -+ "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403", -+ "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391", -+ "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8", -+ "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605", -+ "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9", -+ "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d", -+ "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe", -+ "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe", -+ "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1", -+ "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3", -+ "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb", -+ "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b", -+ "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef", -+ "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253", -+ "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec", -+ "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a", -+ "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473", -+ "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837", -+ "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a", -+ "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1", -+ "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d", -+ "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9", -+ "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537", -+ "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7", -+ "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2", -+ "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338", -+ "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15", -+ "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9", -+ "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461", -+} -+ -+var hashes2X = []string{ -+ "64", -+ "f457", -+ "e8c045", -+ "a74c6d0d", -+ "eb02ae482a", -+ "be65b981275e", -+ "8540ccd083a455", -+ "074a02fa58d7c7c0", -+ "da6da05e10db3022b6", -+ "542a5aae2f28f2c3b68c", -+ "ca3af2afc4afe891da78b1", -+ "e0f66b8dcebf4edc85f12c85", -+ "744224d383733b3fa2c53bfcf5", -+ "b09b653e85b72ef5cdf8fcfa95f3", -+ "dd51877f31f1cf7b9f68bbb09064a3", -+ "f5ebf68e7ebed6ad445ffc0c47e82650", -+ "ebdcfe03bcb7e21a9091202c5938c0a1bb", -+ "860fa5a72ff92efafc48a89df1632a4e2809", -+ "0d6d49daa26ae2818041108df3ce0a4db48c8d", -+ "e5d7e1bc5715f5ae991e4043e39533af5d53e47f", -+ "5232028a43b9d4dfa7f37439b49495926481ab8a29", -+ "c118803c922f9ae2397fb676a2ab7603dd9c29c21fe4", -+ "2af924f48b9bd7076bfd68794bba6402e2a7ae048de3ea", -+ "61255ac38231087c79ea1a0fa14538c26be1c851b6f318c0", -+ "f9712b8e42f0532162822f142cb946c40369f2f0e77b6b186e", -+ "76da0b89558df66f9b1e66a61d1e795b178ce77a359087793ff2", -+ "9036fd1eb32061bdecebc4a32aa524b343b8098a16768ee774d93c", -+ "f4ce5a05934e125d159678bea521f585574bcf9572629f155f63efcc", -+ "5e1c0d9fae56393445d3024d6b82692d1339f7b5936f68b062c691d3bf", -+ "538e35f3e11111d7c4bab69f83b30ade4f67addf1f45cdd2ac74bf299509", -+ "17572c4dcbb17faf8785f3bba9f6903895394352eae79b01ebd758377694cc", -+ "29f6bb55de7f8868e053176c878c9fe6c2055c4c5413b51ab0386c277fdbac75", -+ "bad026c8b2bd3d294907f2280a7145253ec2117d76e3800357be6d431b16366e41", -+ "386b7cb6e0fd4b27783125cbe80065af8eb9981fafc3ed18d8120863d972fa7427d9", -+ "06e8e6e26e756fff0b83b226dce974c21f970e44fb5b3e5bbada6e4b12f81cca666f48", -+ "2f9bd300244f5bc093ba6dcdb4a89fa29da22b1de9d2c9762af919b5fedf6998fbda305b", -+ "cf6bdcc46d788074511f9e8f0a4b86704365b2d3f98340b8db53920c385b959a38c8869ae7", -+ "1171e603e5cdeb4cda8fd7890222dd8390ede87b6f3284cac0f0d832d8250c9200715af7913d", -+ "bda7b2ad5d02bd35ffb009bdd72b7d7bc9c28b3a32f32b0ba31d6cbd3ee87c60b7b98c03404621", -+ "2001455324e748503aa08eff2fb2e52ae0170e81a6e9368ada054a36ca340fb779393fb045ac72b3", -+ "45f0761aefafbf87a68f9f1f801148d9bba52616ad5ee8e8ac9207e9846a782f487d5cca8b20355a18", -+ "3a7e05708be62f087f17b41ac9f20e4ef8115c5ab6d08e84d46af8c273fb46d3ce1aabebae5eea14e018", -+ "ea318da9d042ca337ccdfb2bee3e96ecb8f907876c8d143e8e44569178353c2e593e4a82c265931ba1dd79", -+ "e0f7c08f5bd712f87094b04528fadb283d83c9ceb82a3e39ec31c19a42a1a1c3bee5613b5640abe069b0d690", -+ "d35e63fb1f3f52ab8f7c6cd7c8247e9799042e53922fbaea808ab979fa0c096588cfea3009181d2f93002dfc11", -+ "b8b0ab69e3ae55a8699eb481dd665b6a2424c89bc6b7cca02d15fdf1b9854139cab49d34de498b50b2c7e8b910cf", -+ "fb65e3222a2950eae1701d4cdd4736266f65bf2c0d2e77968996eadb60ef74fb786f6234973a2524bdfe32d100aa0e", -+ "f28b4bb3a2e2c4d5c01a23ff134558559a2d3d704b75402983ee4e0f71d273ae056842c4153b18ee5c47e2bfa54313d4", -+ "7bb78794e58a53c3e4b1aeb161e756af051583d14e0a5a3205e094b7c9a8cf62d098fa9ea1db12f330a51ab9852c17f983", -+ "a879a8ebae4d0987789bcc58ec3448e35ba1fa1ee58c668d8295aba4eaeaf2762b053a677e25404f635a53037996974d418a", -+ "695865b353ec701ecc1cb38f3154489eed0d39829fc192bb68db286d20fa0a64235cde5639137819f7e99f86bd89afcef84a0f", -+ "a6ec25f369f71176952fb9b33305dc768589a6070463ee4c35996e1ced4964a865a5c3dc8f0d809eab71366450de702318e4834d", -+ "604749f7bfadb069a036409ffac5ba291fa05be8cba2f141554132f56d9bcb88d1ce12f2004cd3ade1aa66a26e6ef64e327514096d", -+ "daf9fa7dc2464a899533594e7916fc9bc585bd29dd60c930f3bfa78bc47f6c8439448043a45119fc9228c15bce5fd24f46baf9de736b", -+ "943ea5647a8666763084da6a6f15dcf0e8dc24f27fd0d9194805d25180fe3a6d98f4b2b5e0d6a04e9b41869817030f16ae975dd41fc35c", -+ "af4f73cbfc093760dfeb52d57ef45207bbd1a515f5523404e5d95a73c237d97ae65bd195b472de6d514c2c448b12fafc282166da132258e9", -+ "605f4ed72ed7f5046a342fe4cf6808100d4632e610d59f7ebb016e367d0ff0a95cf45b02c727ba71f147e95212f52046804d376c918cadd260", -+ "3750d8ab0a6b13f78e51d321dfd1aa801680e958de45b7b977d05732ee39f856b27cb2bcce8fbf3db6666d35e21244c2881fdcc27fbfea6b1672", -+ "8f1b929e80ab752b58abe9731b7b34eb61369536995abef1c0980d93903c1880da3637d367456895f0cb4769d6de3a979e38ed6f5f6ac4d48e9b32", -+ "d8469b7aa538b36cdc711a591d60dafecca22bd421973a70e2deef72f69d8014a6f0064eabfbebf5383cbb90f452c6e113d2110e4b1092c54a38b857", -+ "7d1f1ad2029f4880e1898af8289c23bc933a40863cc4ab697fead79c58b6b8e25b68cf5324579b0fe879fe7a12e6d03907f0140dfe7b29d33d6109ecf1", -+ "87a77aca6d551642288a0dff66078225ae39d288801607429d6725ca949eed7a6f199dd8a65523b4ee7cfa4187400e96597bfffc3e38ade0ae0ab88536a9", -+ "e101f43179d8e8546e5ce6a96d7556b7e6b9d4a7d00e7aade5579d085d527ce34a9329551ebcaf6ba946949bbe38e30a62ae344c1950b4bde55306b3bac432", -+ "4324561d76c370ef35ac36a4adf8f3773a50d86504bd284f71f7ce9e2bc4c1f1d34a7fb2d67561d101955d448b67577eb30dfee96a95c7f921ef53e20be8bc44", -+ "78f0ed6e220b3da3cc9381563b2f72c8dc830cb0f39a48c6ae479a6a78dcfa94002631dec467e9e9b47cc8f0887eb680e340aec3ec009d4a33d241533c76c8ca8c", -+ "9f6589c31a472e0a736f4eb22b6c70a9d332cc15304ccb66a6b97cd051b6ed82f8990e1d9bee2e4bb1c3c45e550ae0e7b96e93ae23f2fb8f63b309131e72b36cba6a", -+ "c138077ee4ed3d7ffa85ba851dfdf6e9843fc1dc00889d117237bfaad9aa757192f73556b959f98e6d24886ce48869f2a01a48c371785f12b6484eb2078f08c22066e1", -+ "f83e7c9e0954a500576ea1fc90a3db2cbd7994eaef647dab5b34e88ab9dc0b47addbc807b21c8e6dd3d0bd357f008471d4f3e0abb18450e1d4919e03a34545b9643f870e", -+ "3277a11f2628544fc66f50428f1ad56bcba6ee36ba2ca6ecdf7e255effc0c30235c039d13e01f04cf1efe95b5c2033ab72adda30994b62f2851d17c9920eadca9a251752dc", -+ "c2a834281a06fe7b730d3a03f90761daf02714c066e33fc07e1f59ac801ec2f4433486b5a2da8faa51a0cf3c34e29b2960cd0013378938dbd47c3a3d12d70db01d7d06c3e91e", -+ "47680182924a51cabe142a6175c9253e8ba7ea579ece8d9bcb78b1e9ca00db844fa08abcf41702bd758ee2c608d9612fed50e85854469cb4ef3038acf1e35b6ba4390561d8ae82", -+ "cec45830cd71869e83b109a99a3cd7d935f83a95de7c582f3adbd34e4938fa2f3f922f52f14f169c38cc6618d3f306a8a4d607b345b8a9c48017136fbf825aecf7b620e85f837fae", -+ "46fb53c70ab105079d5d78dc60eaa30d938f26e4d0b9df122e21ec85deda94744c1daf8038b8a6652d1ff3e7e15376f5abd30e564784a999f665078340d66b0e939e0c2ef03f9c08bb", -+ "7b0dcb52791a170cc52f2e8b95d8956f325c3751d3ef3b2b83b41d82d4496b46228a750d02b71a96012e56b0720949ca77dc68be9b1ef1ad6d6a5ceb86bf565cb972279039e209dddcdc", -+ "7153fd43e6b05f5e1a4401e0fef954a737ed142ec2f60bc4daeef9ce73ea1b40a0fcaf1a1e03a3513f930dd5335723632f59f7297fe3a98b68e125eadf478eb045ed9fc4ee566d13f537f5", -+ "c7f569c79c801dab50e9d9ca6542f25774b3841e49c83efe0b89109f569509ce7887bc0d2b57b50320eb81fab9017f16c4c870e59edb6c26620d93748500231d70a36f48a7c60747ca2d5986", -+ "0a81e0c547648595adca65623ce783411aac7f7d30c3ad269efafab288e7186f6895261972f5137877669c550f34f5128850ebb50e1884814ea1055ee29a866afd04b2087abed02d9592573428", -+ "6a7b6769e1f1c95314b0c7fe77013567891bd23416374f23e4f43e27bc4c55cfada13b53b1581948e07fb96a50676baa2756db0988077b0f27d36ac088e0ff0fe72eda1e8eb4b8facff3218d9af0", -+ "a399474595cb1ccab6107f18e80f03b1707745c7bf769fc9f260094dc9f8bc6fe09271cb0b131ebb2acd073de4a6521c8368e664278be86be216d1622393f23435fae4fbc6a2e7c961282a777c2d75", -+ "4f0fc590b2755a515ae6b46e9628092369d9c8e589e3239320639aa8f7aa44f8111c7c4b3fdbe6e55e036fbf5ebc9c0aa87a4e66851c11e86f6cbf0bd9eb1c98a378c7a7d3af900f55ee108b59bc9e5c", -+ "ed96a046f08dd675107331d267379c6fce3c352a9f8d7b243008a74cb4e9410836afaabe871dab6038ca94ce5f6d41fa922ce08aba58169f94cfc86d9f688f396abd24c11a6a9b0830572105a477c33e92", -+ "379955f539abf0eb2972ee99ed9546c4bbee363403991833005dc27904c271ef22a799bc32cb39f08d2e4ba6717d55153feb692d7c5efae70890bf29d96df02333c7b05ccc314e4835b018fec9141a82c745", -+ "e16cc8d41b96547ede0d0cf4d908c5fa393399daa4a9696e76a4c1f6a2a9fef70f17fb53551a8145ed88f18db8fe780a079d94732437023f7c1d1849ef69ad536a76204239e8ba5d97e507c36c7d042f87fe0e", -+ "a81de50750ece3f84536728f227208bf01ec5b7721579d007de72c88ee20663318332efe5bc7c09ad1fa8342be51f0609046ccf760a7957a7d8dc88941adb93666a4521ebe76618e5ddc2dd3261493d400b50073", -+ "b72c5fb7c7f60d243928fa41a2d711157b96aef290185c64b4de3dcfa3d644da67a8f37c2ac55caad79ec695a473e8b481f658c497edb8a191526592b11a412282d2a4010c90ef4647bd6ce745ebc9244a71d4876b", -+ "9550703877079c90e200e830f277b605624954c549e729c359ee01ee2b07741ecc4255cb37f96682dafcdbaade1063e2c5ccbd1918fb669926a67744101fb6de3ac016be4c74165a1e5a696b704ba2ebf4a953d44b95", -+ "a17eb44d4de502dc04a80d5a5e9507d17f27c96467f24c79b06bc98a4c410741d4ac2db98ec02c2a976d788531f1a4451b6c6204cef6dae1b6ebbcd0bde23e6fffb02754043c8fd3c783d90a670b16879ce68b5554fe1c", -+ "41d3ea1eaba5be4a206732dbb5b70b79b66a6e5908795ad4fb7cf9e67efb13f06fef8f90acb080ce082aadec6a1b543af759ab63fa6f1d3941186482b0c2b312f1151ea8386253a13ed3708093279b8eb04185636488b226", -+ "5e7cdd8373dc42a243c96013cd29df9283b5f28bb50453a903c85e2ce57f35861bf93f03029072b70dac0804e7d51fd0c578c8d9fa619f1e9ce3d8044f65d55634dba611280c1d5cfb59c836a595c803124f696b07ddfac718", -+ "26a14c4aa168907cb5de0d12a82e1373a128fb21f2ed11feba108b1bebce934ad63ed89f4ed7ea5e0bc8846e4fc10142f82de0bebd39d68f7874f615c3a9c896bab34190e85df05aaa316e14820b5e478d838fa89dfc94a7fc1e", -+ "0211dfc3c35881adc170e4ba6daab1b702dff88933db9a6829a76b8f4a7c2a6d658117132a974f0a0b3a38ceea1efc2488da21905345909e1d859921dc2b5054f09bce8eeb91fa2fc6d048ce00b9cd655e6aafbdaa3a2f19270a16", -+ "ddf015b01b68c4f5f72c3145d54049867d99ee6bef24282abf0eecdb506e295bacf8f23ffa65a4cd891f76a046b9dd82cae43a8d01e18a8dff3b50aeb92672be69d7c087ec1fa2d3b2a39196ea5b49b7baede37a586fea71aded587f", -+ "6ee721f71ca4dd5c9ce7873c5c04c6ce76a2c824b984251c15535afc96adc9a4d48ca314bfeb6b8ee65092f14cf2a7ca9614e1dcf24c2a7f0f0c11207d3d8aed4af92873b56e8b9ba2fbd659c3f4ca90fa24f113f74a37181bf0fdf758", -+ "689bd150e65ac123612524f720f54def78c095eaab8a87b8bcc72b443408e3227f5c8e2bd5af9bcac684d497bc3e41b7a022c28fb5458b95e8dfa2e8caccde0492936ff1902476bb7b4ef2125b19aca2cd3384d922d9f36dddbcd96ae0d6", -+ "3a3c0ef066fa4390ec76ad6be1dc9c31ddf45fef43fbfa1f49b439caa2eb9f3042253a9853e96a9cf86b4f873785a5d2c5d3b05f6501bc876e09031188e05f48937bf3c9b667d14800db62437590b84ce96aa70bb5141ee2ea41b55a6fd944", -+ "741ce384e5e0edaebb136701ce38b3d33215415197758ae81235307a4115777d4dab23891db530c6d28f63a957428391421f742789a0e04c99c828373d9903b64dd57f26b3a38b67df829ae243feef731ead0abfca049924667fdec49d40f665", -+ "a513f450d66cd5a48a115aee862c65b26e836f35a5eb6894a80519e2cd96cc4cad8ed7eb922b4fc9bbc55c973089d627b1da9c3a95f6c019ef1d47143cc545b15e4244424be28199c51a5efc7234dcd94e72d229897c392af85f523c2633427825", -+ "71f1554d2d49bb7bd9e62e71fa049fb54a2c097032f61ebda669b3e1d4593962e47fc62a0ab5d85706aebd6a2f9a192c88aa1ee2f6a46710cf4af6d3c25b7e68ad5c3db23ac009c8f13625ff85dc8e50a9a1b2682d3329330b973ec8cbb7bb73b2bd", -+ "167cc1067bc08a8d2c1a0c10041ebe1fc327b37043f6bd8f1c63569e9d36ded58519e66b162f34b6d8f1107ef1e3de199d97b36b44141a1fc4f49b883f40507ff11f909a017869dc8a2357fc7336ae68703d25f75710b0ff5f9765321c0fa53a51675c", -+ "cb859b35dc70e264efaad2a809fea1e71cd4a3f924be3b5a13f8687a1166b538c40b2ad51d5c3e47b0de482497382673140f547068ff0b3b0fb7501209e1bf36082509ae85f60bb98fd02ac50d883a1a8daa704952d83c1f6da60c9624bc7c99912930bf", -+ "afb1f0c6b7125b04fa2578dd40f60cb411b35ebc7026c702e25b3f0ae3d4695d44cfdf37cb755691dd9c365edadf21ee44245620e6a24d4c2497135b37cd7ac67e3bd0aaee9f63f107746f9b88859ea902bc7d6895406aa2161f480cad56327d0a5bba2836", -+ "13e9c0522587460d90c7cb354604de8f1bf850e75b4b176bda92862d35ec810861f7d5e7ff6ba9302f2c2c8642ff8b7776a2f53665790f570fcef3cac069a90d50db42227331c4affb33d6c040d75b9aeafc9086eb83ced38bb02c759e95ba08c92b17031288", -+ "0549812d62d3ed497307673a4806a21060987a4dbbf43d352b9b170a29240954cf04bc3e1e250476e6800b79e843a8bd8253b7d743de01ab336e978d4bea384eaff700ce020691647411b10a60acacb6f8837fb08ad666b8dcc9eaa87ccb42aef6914a3f3bc30a", -+ "3a263efbe1f2d463f20526e1d0fd735035fd3f808925f058b32c4d8788aeeab9b8ce233b3c34894731cd73361f465bd350395aebcabd2fb63010298ca025d849c1fa3cd573309b74d7f824bbfe383f09db24bcc565f636b877333206a6ad70815c3bef5574c5fc1c", -+ "3c6a7d8a84ef7e3eaa812fc1eb8e85105467230d2c9e4562edbfd808f4d1ac15d16b786cc6a02959c2bc17149c2ce74c6f85ee5ef22a8a96b9be1f197cffd214c1ab02a06a9227f37cd432579f8c28ff2b5ac91cca8ffe6240932739d56788c354e92c591e1dd76499", -+ "b571859294b02af17541a0b5e899a5f67d6f5e36d38255bc417486e69240db56b09cf2607fbf4f95d085a779358a8a8b41f36503438c1860c8f361ce0f2783a08b21bd7232b50ca6d35428335272a5c05b436b2631d8d5c84d60e8040083768ce56a250727fb0579dd5c", -+ "98ee1b7269d2a0dd490ca38d447279870ea55326571a1b430adbb2cf65c492131136f504145df3ab113a13abfb72c33663266b8bc9c458db4bf5d7ef03e1d3b8a99d5de0c024be8fabc8dc4f5dac82a0342d8ed65c329e7018d6997e69e29a01350516c86beaf153da65ac", -+ "41c5c95f088df320d35269e5bf86d10248f17aec6776f0fe653f1c356aae409788c938befeb67c86d1c8870e8099ca0ce61a80fbb5a6654c44529368f70fc9b9c2f912f5092047d0ffc339577d24142300e34948e086f62e23ecaca410d24f8a36b5c8c5a80e0926bc8aa16a", -+ "9f93c41f533b2a82a4df893c78faaaa793c1506974ba2a604cd33101713ca4adfd30819ffd8403402b8d40aff78106f3357f3e2c24312c0d3603a17184d7b999fc9908d14d50192aebabd90d05073da7af4be37dd3d81c90acc80e8333df546f17ab6874f1ec204392d1c0571e", -+ "3da5207245ac270a915fc91cdb314e5a2577c4f8e269c4e701f0d7493ba716de79935918b917a2bd5db98050dbd1eb3894b65fac5abf13e075abebc011e651c03cafb6127147771a5c8418223e1548137a89206635c26ca9c235ccc108dc25cf846e4732444bd0c2782b197b262b", -+ "96011af3965bb941dc8f749932ea484eccb9ba94e34b39f24c1e80410f96ce1d4f6e0aa5be606def4f54301e930493d4b55d484d93ab9dd4dc2c9cfb79345363af31ad42f4bd1aa6c77b8afc9f0d551bef7570b13b927afe3e7ac4de7603a0876d5edb1ad9be05e9ee8b53941e8f59", -+ "51dbbf2a7ca224e524e3454fe82ddc901fafd2120fa8603bc343f129484e9600f688586e040566de0351d1693829045232d04ff31aa6b80125c763faab2a9b233313d931903dcfaba490538b06e4688a35886dc24cdd32a13875e6acf45454a8eb8a315ab95e608ad8b6a49aef0e299a", -+ "5a6a422529e22104681e8b18d64bc0463a45df19ae2633751c7aae412c250f8fb2cd5e1270d3d0cf009c8aa69688ccd4e2b6536f5747a5bc479b20c135bf4e89d33a26118705a614c6be7ecfe766932471ad4ba01c4f045b1abb5070f90ec78439a27a1788db9327d1c32f939e5fb1d5ba", -+ "5d26c983642093cb12ff0afabd87b7c56e211d01844ad6da3f623b9f20a0c968034299f2a65e6673530c5980a532beb831c7d0697d12760445986681076dfb6fae5f3a4d8f17a0db5008ce8619f566d2cfe4cf2a6d6f9c3664e3a48564a351c0b3c945c5ee24587521e4112c57e318be1b6a", -+ "52641dbc6e36be4d905d8d60311e303e8e859cc47901ce30d6f67f152343e3c4030e3a33463793c19effd81fb7c4d631a9479a7505a983a052b1e948ce093b30efa595fab3a00f4cef9a2f664ceeb07ec61719212d58966bca9f00a7d7a8cb4024cf6476bab7fbccee5fd4e7c3f5e2b2975aa2", -+ "a34ce135b37bf3db1c4aaa4878b4499bd2ee17b85578fcaf605d41e1826b45fdaa1b083d8235dc642787f11469a5493e36806504fe2a2063905e821475e2d5ee217057950370492f5024995e77b82aa51b4f5bd8ea24dc71e0a8a640b0592c0d80c24a726169cf0a10b40944747113d03b52708c", -+ "46b3cdf4946e15a5334fc3244d6680f5fc132afa67bf43bfade23d0c9e0ec64e7dab76faaeca1870c05f96b7d019411d8b0873d9fed04fa5057c039d5949a4d592827f619471359d6171691cfa8a5d7cb07ef2804f6ccad4821c56d4988bea7765f660f09ef87405f0a80bcf8559efa111f2a0b419", -+ "8b9fc21691477f11252fca050b121c5334eb4280aa11659e267297de1fec2b2294c7ccee9b59a149b9930b08bd320d3943130930a7d931b71d2f10234f4480c67f1de883d9894ada5ed5071660e221d78ae402f1f05af47761e13fec979f2671e3c63fb0ae7aa1327cf9b8313adab90794a52686bbc4", -+ "cd6598924ce847de7ff45b20ac940aa6292a8a99b56a74eddc24f2cfb45797188614a21d4e8867e23ff75afd7cd324248d58fcf1ddc73fbd115dfa8c09e62022fab540a59f87c989c12a86ded05130939f00cd2f3b512963dfe0289f0e54acad881c1027d2a0292138fdee902d67d9669c0ca1034a9456", -+ "594e1cd7337248704e691854af0fdb021067ddf7832b049ba7b684438c32b029eded2df2c89a6ff5f2f2c311522ae2dc6db5a815afc60637b15ec24ef9541f1550409db2a006da3affffe548a1eaee7bd114e9b805d0756c8e90c4dc33cb05226bc2b393b18d953f8730d4c7ae693159cdba758ad28964e2", -+ "1f0d292453f04406ada8be4c161b82e3cdd69099a8637659e0ee40b8f6da46005cfc6085db9804852decfbe9f7b4dda019a7112612895a144ed430a960c8b2f5458d3d56b7f427cee6358915aee7146278aed2a0296cdd929e4d21ef95a3adf8b7a6beba673cdccdbdcfb2474711732d972ad054b2dc64f38d", -+ "b65a72d4e1f9f9f75911cc46ad0806b9b18c87d105332a3fe183f45f063a746c892dc6c4b9181b1485b3e3a2cc3b453eba2d4c39d6905a774ed3fb755468beb190925ecd8e57ecb0d985125741650c6b6a1b2a3a50e93e3892c21d47ed5884eed83aa94e1602288f2f49fe286624de9d01fcb54433a0dc4ad70b", -+ "705ce0ffa469250782aff725248fc88fe98eb76659e8407edc1c4842c9867d61fe64fb86f74e980598b92bc213d06f337bd5654fc28643c7ba769a4c31563427543c00808b627a19c90d86c322f33566ce020121cc322229c3337943d46f68ef939d613dcef0077269f88151d6398b6b009abb763410b154ad76a3", -+ "7fa881ce87498440ab6af13854f0d851a7e0404de33896999a9b3292a5d2f5b3ad033530c558168fe5d2fdb9b89a2354c46cf32a0e612afc6c6485d789511bfef26800c74bf1a4cfbe30bda310d5f6029c3dccdedb6149e4971274e276dccfabd63bc4b9955e8303feb57f8a688db55ecb4b33d1f9fe1b3a8ba7ac32", -+ "23a98f71c01c0408ae16843dc03be7db0aeaf055f951709d4e0dfdf64fffbffaf900ee592ee10929648e56f6c1e9f5be5793f7df66453eb56502c7c56c0f0c88da77abc8fa371e434104627ef7c663c49f40998dbad63fa6c7aa4fac17ae138d8bbe081f9bd168cd33c1fbc92fa35ed687679f48a64b87db1fe5bae675", -+ "7b8970b6a33237e5a7bcb39272703edb92285c55842b30b9a48834b1b507cc02a6764739f2f7ee6ae02a7b715a1c455e59e8c77a1ae98abb10161853f1234d20da99016588cd8602d6b7ec7e177d4011edfa61e6b3766a3c6f8d6e9eac893c568903eb6e6aba9c4725774f6b4343b7acaa6c031593a36eef6c72806ff309", -+ "f7f4d328ba108b7b1de4443e889a985ed52f485f3ca4e0c246aa5526590cbed344e9f4fe53e4eea0e761c82324649206ca8c2b45152157d4115e68c818644b03b65bb47ad79f94d37cb03c1d953b74c2b8adfa0e1c418bda9c518ddcd7050e0f149044740a2b16479413b63fc13c36144f80c73687513dca761ba8642a8ae0", -+ "2d7dc80c19a1d12d5fe3963569547a5d1d3e821e6f06c5d5e2c09401f946c9f7e13cd019f2f9a878b62dd850453b6294b99ccaa068e542993524b0f63832d48e865be31e8ec1ee103c718340c904b32efb69170b67f038d50a3252794b1b4076c0620621ab3d91215d55ffea99f23d54e161a90d8d4902fda5931d9f6a27146a", -+ "77dff4c7ad30c954338c4b23639dae4b275086cbe654d401a2343528065e4c9f1f2eca22aa025d49ca823e76fdbb35df78b1e5075ff2c82b680bca385c6d57f7ea7d1030bb392527b25dd73e9eeff97bea397cf3b9dda0c817a9c870ed12c006cc054968c64000e0da874e9b7d7d621b0679866912243ea096c7b38a1344e98f74", -+ "83bed0d556798f2b419f7056e6d3ffada06e939b95a688d0ec8c6ac5ea45ab73a4cf01043e0a170766e21395f27ab4b78c435f5f0dfe6e93ab80df38610e41158429ddf20296f53a06a017723359fe22dc08b5da33f0800a4fe50118e8d7eab2f83a85cd764bf8a166903bd0e9dcfeeceba44ff4ca4439846458d31ea2bb564645d1", -+ "ea12cf5a113543e39504123036f15a5bafa9c555562469f99cd29996a4dfaaab2a34b00557ccf15f37fc0cc1b3be427e725f2cd952e50af7970dda9200cd5ce252b1f29c40067fea3027ed686190803b59d834179d1b8f5b55abe55ad174b2a1188f7753ec0ae2fc01316e7d498b68ee3598a0e9baaaa664a60f7fb4f90edbed494ad7", -+ "55266358332d8d9e68bd13432088beadf95833aab67a0eb3b10650414255f299e2670c3e1a5b2976159a46c72a7ce57d59b7be14c15798e09ed50fa312a431b0264d7a1396aa6168bde897e208ece53d2cfc83786113b1e6eac5e9bb98984abb6c8d64eebb991903254abc650c999bb9958a5d7937434b869bc940e21b9dc1cc8982f2ba", -+ "4d6104ded730aefe02873f4c741232c8234a6d66d85393aff57fbf56ba6347666988dfc4d58f3cc895a0da598822edeee4533d24ec0ee292fd5e1ad04898ffbc1ff4bef14dec220babcb0f28fffe32a6e2c28aaaac16442bf4feb02917d18bb3a415d84fa9358d5a9852688d846c92271911f934181c30f82434d915f93f155a1ffbf0b125", -+ "eb5f579a4c476af554aac11e5719d378549497e613b35a929d6f36bb8831d7a466aa76de9be24ebb55543f1c13924f64cfd648a5b3fa90387315c16174dbf1e9a183c196d9bb8f84af65f1f8212429aadc11ef2426d07d4716062b85c8d5d2dff8e21b9e62b7fa7dbd57d72633054b464fb28583a56ca13ccc5ddc74dae942492f31731e7046", -+ "ebddec3dcaf18063e45a76ebeac39af85a1adc2818881ccce48c106288f5988365cca2b4b1d7f037322da46840f42bebdcbc7193838d426e101087d8cea03aaff743d573eb4f4e9a71a2c884390769a6503874125d194bee8d46a3a0d5e4fcf28ff8465887d8e9df771d70157e75df3642b331d2778ceb32ceba868640171ab7a5d22eede1ee44", -+ "26d87ec70b57691e3bb359633d3ddba17f029d62cdfe977f5fd42274d79b444a32494d1c01e9f72d03cce78c806df96e93ea78da3a054209924ed765edc4d570f66168dc25ee3114e4017e387440349c8f0a94804761c3055f88e4fda2a49b860b1486a9609095f6250f268b6a4d1aecc03a505632ebf0b9dc22d0755a736faf7ad7000858b5864b", -+ "3880f5cc2d08fa70ef44b1f263fcf534d062a298c1bd5ee2eee8c3265806c4ce50b004f3a1fc1fa5b024aaac7f528c023c8181f67c6e1c357425dc4d573bd46b93a542afa3a19bdb140a2ce666e1a01f5c4d2dcd681fa9f5839b797813c394738d5ee4971386c12c7c117d17c7bec324b760aa30cda9ab2aa850284ba6fa97946f710f02449d1883c6", -+ "3317d2f452105dd3f4a96f9257af8285a80be58066b50f6f54bd633749b49f6ab9d57d45652d2ae852a2f6940cd5ec3159dd7f333358b12f502325df38843508faf7e246352d201280babd90b14fbf7722641c3601d0e458474439973c611bb5502fd0eb3078f87124ca7e1a016fcb6cfeff65f6a565985aca7122cfa8c5a11da0cb47797c5132333179", -+ "f2c5c955d0224e784a46b9125f8fef8a5e1271e145eb08bbbd07ca8e1cfc848cef14fa3b36221ac62006403dbb7f7d77958ccc54a8566c837858b809f3e310ace8ca682515bc655d2a397cab238a663b464d511f02dc5d033dad4cb5e0e519e94a54b62a3896e460ec70e5716b5921bf8396aa86a60123e6287e34570bb01bdc602e113670bf498af2ff10", -+ "180e275205691a83630cf4b0c7b80e6df8fad6ef1c23ba8013d2f09aef7abade1827f23af230de90676240b4b3b0673f8afdea0327330055041741f65560d90348de696d34ca80dfe8afae582fe4879d4594b80e9408fb53e800e01ca58552b905c365e7f1416e51c080f517d6bbd30e64ae1535d59decdc76c6624d737868f49f2f719da39ba1344d59eab9", -+ "c517a84e4631a7f65ace170d1e5c2fdb259841535d88da323e68c0883e6af7b041cfe05908815a5a9d1b14fa712c2c16fadcf1ca54d3aa954d411240df331b2aebdfb65aced84d0b8aace56ec0aa7c13ec7d75ca883b6bcf6db74c9e98463c484a8262684f29910373430651f90ecffe18b072170e61ee58de20e2a6ff67b3ab00fccbb80af943f20b56b98107", -+ "d1a56a5ee990e02b84b5862fde62f69ec07567be2d7ccb769a461c4989d11fdda6c945d942fb8b2da795ed97e43a5b7dbdde7f8fd2ff7154544336d5c50fb7380341e660d4898c7fbc39b2b782f28defac6873523c7c1de8e52c65e4395c686ba483c35a220b0416d46357a063fa4c33fa9c52d5c207a1304ae141c791e62ba6a7374ed922b8dd94079b72b69302", -+ "4720b88d6bfb1ab43958e26827730d852d9ec30173ebd0fe0d273edcece2e788558984cd9306fe5978086a5cb6d37975755d2a3daeb16f99a8a11544b8247a8b7ed5587afc5bea1daf85dcea5703c5905cf56ae7cc76408ccabb8fcc25cacc5ff456db3f62fa559c45b9c71505eb5073df1f10fc4c9060843f0cd68bbb4e8edfb48d0fd81d9c21e53b28a2aae4f7ba", -+ "f4639b511db9e092823d47d2947efacbaae0e5b912dec3b284d2350b9262f3a51796a0cd9f8bc5a65879d6578ec24a060e293100c2e12ad82d5b2a0e9d22965858030e7cdf2ab3562bfa8ac084c6e8237aa22f54b94c4e92d69f22169ced6c85a293f5e16bfc326153bf629cdd6393675c6627cd949cd367eef02e0f54779f4d5210197698e4754a5fe490a3a7521c1c", -+ "3d9e7a860a718565e3670c29079ce80e381969fea91017cfd5952e0d8a4a79bb08e2cd1e26161f30ee03a24891d1bfa8c212861b51618d07429fb48000ff87ef09c6fca526567777e9c076d58a642d5c521b1caa5fb0fb3a4b8982dc14a444732b72b239b8f01fc8ba8ee86b3013b5d3e98a92b2aeaecd4879fca5d5e9e0bd880dbfffa6f96f94f3998812aac6a714f331", -+ "4d9bf551d7fd531e7482e2ec875c0651b0bcc6caa738f7497befd11e67ae0e036c9d7ae4301cc3c7906f0d0e1ed4738753f414f9b3cd9b8a71176e325c4c74ce020680ecbfb146889597f5b40487e93f974cd866817fb9fb24c7c7c16177e6e120bfe349e83aa82ba40e59e917565788658a2b254f25cf99bc65070b3794cea2259eb10e42bb54852cba3110baa773dcd70c", -+ "b91f65ab5bc059bfa5b43b6ebae243b1c46826f3da061338b5af02b2da76bb5ebad2b426de3c3134a633499c7c36a120369727cb48a0c6cbab0acecdda137057159aa117a5d687c4286868f561a272e0c18966b2fec3e55d75abea818ce2d339e26adc005c2658493fe06271ad0cc33fcb25065e6a2a286af45a518aee5e2532f81ec9256f93ff2d0d41c9b9a2efdb1a2af899", -+ "736f6e387acb9acbee026a6080f8a9eb8dbb5d7c54ac7053ce75dd184b2cb7b942e22a3497419ddb3a04cf9e4eb9340a1a6f9474c06ee1dcfc8513979fee1fc4768087617fd424f4d65f54782c787a1d2de6efc81534343e855f20b3f3589027a5436201eee747d45b9b8375e4294d72ab6a52e04dfbb2914db92ee58f134b026527ed52d4f794459e02a43a17b0d51ea69bd7f3", -+ "9242d3eb31d26d923b99d66954cfade94f25a18912e6356810b63b971ae74bb53bc58b3c01424208ea1e0b1499936daea27e63d904f9ed65fdf69de40780a3027b2e89d94bdf214f585472613ce328f628f4f0d56217dfb53db5f7a07f54c8d71db16e27de7cdb8d23988837b49b65c12f1771d979e8b192c9f4a16b8d9fba917bcf74ce5a82aac2075608ba6c2d485fa59864b9de", -+ "5da68704f4b592d41f08aca08f62d85e2e2466e5f3be010315d11d113db674c4b98764a509a2f5aacc7ae72c9deff2bcc42810b47f64d429b35745b9efff0b18c58653461e968aaa3c2c7fc455bc5771a8f10cd184be831040df767201ab8d32cb9a58c89afbebecb524502c9b940c1b838f8361bbcde90d272715017f67609ea39b20fac985332d82daaa023999e3f8bfa5f3758bb8", -+ "71ea2af9c8ac2e5ae44a176662882e01027ca3cdb41ec2c6785606a07d7231cd4a2bded7155c2feef3d44d8fd42afa73265cef826f6e03aa761c5c51d5b1f129ddc27503ff50d9c2d748322df4b13dd5cdc7d46381528ab22b79b0049011e4d2e57fe2735e0d58d8d56e92c75dbeac8c76c4239d7f3f24fb56697593b3e4afa6671d5bbc96c079a1c154fe20212ade67b05d49ceaa7a84", -+ "1d133170582fa4bff59a21953ebbc01bc202d43cd79c083d1f5c02fa15a43a0f519e36acb710bdabac880f04bc003800641c2487930de9c03c0e0deb347fa815efca0a38c6c5de694db698743bc955581f6a945deec4ae988ef7cdf40498b77796ddea3fae0ea844891ab751c7ee20917c5a4af53cd4ebd82170078f41ada2795e6eea17593fa90cbf5290a1095e299fc7f507f360f187cd", -+ "5ec4ac45d48fc15c72471d795066bdf8e99a483d5fdd599511b9cdc408de7c0616491b73924d0266da34a495331a935c4b8884f57d7ad8cce4cbe586875aa52482215ed39d7626cce55d50349c7767981c8bd6890f132a196184247343566fc972b86fe3c5369d6a6519e9f07942f0522b77ad01c751dcf7defe31e471a0ec00963765dd8518144a3b8c3c978ad108056516a25dbe3092e73c", -+ "0d5e74b78290c689f2b3cfea45fc9b6a84c822639cd438a7f05c07c374adced42cdc12d2a9233a4ffe80307efc1ac13cb04300e165f8d90dd01c0ea955e7657332c6e86ad6b43e78ba4c13c675aed83192d8427866fb6484e6a3071b2369a46fba9005f31232da7ffec7952f831aaaddf63e225263531c2cf387f8cc14fa856c8795137142c3a52ffa69b8e30ebc88ce3bbc227597bcc8dddd89", -+ "a0fe36f983259921dc2fa7d89002b3066241d63bfc2448caf7e10522a35562be0bfedc3dce49cfce2e614a04d4c64cfc0ab898873a7fc26928dc1927c009d12f6f9b7a278205d3d0057604f4ac746f8b9287c3bc6b929832bf253b6586192ac43fdd29ba585dbd9059aab9c6ff6000a7867c67fec1457b733f6b620881166b8fed92bc8d84f0426002e7be7fcd6ee0abf3755e2babfe5636ca0b37", -+ "1d29b6d8eca793bb801becf90b7d7de215b17618ec32340da4bac707cdbb58b951d5036ec02e105d83b5960e2a72002d19b7fa8e1128cc7c5049ed1f76b82a59eac6ed09e56eb73d9ade38a6739f0e07155afa6ec0d9f5cf13c4b30f5f9a465b162a9c3ba04b5a0b3363c2a63f13f2a3b57c590ec6aa7f64f4dcf7f1582d0ca157eb3b3e53b20e306b1f24e9bda87397d413f01b453ceffeca1fb1e7", -+ "6a2860c110cd0fc5a19bcaafcd30762ee10242d34739638e716bd89fd537ea4dc630e6f85d1bd88a25ad3892ca554c232c9830bd56980c9f08d378d28f7fa6fa7df4fcbf6ad98b1adfff3ec1f63310e50f920c99a5200b8e64c2c2ca249399a149942261f737d5d72da949e914c024d57c4b639cb89990fed2b38a37e5bcd24d17ca12dfcd36ce04691fd03c32f6ed5de2a2191ed7c826375ba81f78d0", -+ "7132aa291ddc9210c60dbe7eb3c19f9053f2dd74742cf57fdc5df98312adbf4710a73245de4a0c3b24e21ab8b466a77ae29d15500d5142555ef3088cbccbe685ed9119a10755148f0b9f0dbcf02b2b9bcadc8517c88346ea4e78285e9cbab122f824cc18faf53b742a87c008bb6aa47eed8e1c8709b8c2b9adb4cc4f07fb423e5830a8e503ab4f7945a2a02ab0a019b65d4fd71dc364d07bdc6e637990e3", -+ "3e664da330f2c6007bff0d5101d88288aaacd3c07913c09e871cce16e55a39fde1ce4db6b8379977c46cce08983ca686778afe0a77a41baf447854b9aa286c398c2b83c95a127b053101b6799c1638e5efd67273b2618df6ec0b96d8d040e8c1ee01a99b9b5c8fe63fea2f749e6c90d31f6fae4e1469ac09884c4fe1a8539acb313f42c941224a0e79c059e18affc2bcb6724975c436f7bf949ebdd8aef51c", -+ "7a6ea63a271eb49470f5ce77519ed61ae9b2f1be07a96855726bc3df1d0723af3a703fdfc2e739c9d31d25814daf661a23558b50982e66ee37ad880f5c8f11c8130fac8a5d0250583700d5a324894fae6d61993f6bf9327214f8674649f355b23fd634940b2c467973a839e659169c773119919f5b81ee171edb2e5f6940d7551f9e5a70625d9ea88711ad0ed8ab2da720ad358bef954456cb2d5636425717c2", -+ "c5106bbda114168c449172e49590c7eeb827fa4e1a2a7a87a3c1f721a9047d0c0a50fbf244731be1b7eb1a2ef30f5ae846a9f38f0df44f32af61b68dbdcd0226e741dfb6ef81a2503691af5e4b3171f48c59ba4ef91eba344b5b697f261df7bbbb734ca6e6daebaa4a179feb17002823281b8534d55a6531c59305f6e3fd3fa63b747bcf0deb654c392a02fe687a269effb1238f38bcaea6b208b221c45fe7fbe7", -+ "597716a5ebeebc4bf524c15518816f0b5dcda39cc833c3d66b6368ce39f3fd02ceba8d12072bfe6137c68d3acd50c849873150928b320b4fbc31c1456679ea1d0acaeeabf666d1f1bad3e6b9312c5cbdecf9b799d3e30b0316bed5f41245107b693366accc8b2bcef2a6be54209ffabc0bb6f93377abdcd57d1b25a89e046f16d8fd00f99d1c0cd247aafa72234386ae484510c084ee609f08aad32a005a0a5710cb", -+ "0771ffe789f4135704b6970b617bae41666bc9a6939d47bd04282e140d5a861c44cf05e0aa57190f5b02e298f1431265a365d29e3127d6fccd86ec0df600e26bcdda2d8f487d2e4b38fbb20f1667591f9b5730930788f2691b9ee1564829d1ada15fffc53e785e0c5e5dd11705a5a71e390ca66f4a592785be188fefe89b4bd085b2024b22a210cb7f4a71c2ad215f082ec63746c7367c22aedb5601f513d9f1ffc1f3", -+ "be6556c94313739c115895a7bad2b620c0708e24f0390daa55521c31d2c6782acf41156271238885c367a57c72b4fe999c160e804ad58d8e565edbce14a2dd90e443eb80626b3eab9d7ab75d6f8a062d7ca89b7af8eb292c98eaf87ad1dfd0db103d1bb6188bd7e7a63502153cf3ce23d43b60c5782602bac8ad92fb2324f5a79453898c5de18415639ecc5c7974d3077f76fc1df5b956723bb19a624d7ea3ec13ba3d86", -+ "4bc33729f14cd2f1dc2ff459abee8f6860dda1062845e4adab78b53c835d106bdfa35dd9e77219eaef403d4e80488ca6bd1c93dd76ef9d543fbb7c8904dccc5f71509a6214f73d0f4e467c3e038ea639b29e7fc442ee29f57117740576188ada15a739827c647a46b0271817ab235c023c30c90f2115e5c90cd8501e7b286962fc66ffc3fe7e8978746168314908a41998bd83a1eeffda9d714b864f4d490fdeb9c7a6edfa", -+ "ab12faea205b3d3a803cf6cb32b9698c32301a1e7f7c6c23a20174c95e98b7c3cfe93fffb3c970face8f5751312a261741141b948d777b8a2ea286fe69fc8ac84d34116a4674bb09a1a0b6af90a748e511749de4697908f4acb22be08e96ebc58ab1690acf73914286c198a2b57f1dd70ea8a52325d3045b8bdfe9a09792521526b7564a2a5fcd01e291f1f8894017ce7d3e8a5dba15332fb410fcfc8d62195a48a9e7c86fc4", -+ "7d421e59a567af70594757a49809a9c22e07fe14061090b9a041875bb77933deae36c823a9b47044fa0599187c75426b6b5ed94982ab1af7882d9e952eca399ee80a8903c4bc8ebe7a0fb035b6b26a2a013536e57fa9c94b16f8c2753c9dd79fb568f638966b06da81ce87cd77ac0793b7a36c45b8687c995bf4414d28289dbee977e77bf05d931b4feaa359a397ca41be529910077c8d498e0e8fb06e8e660cc6ebf07b77a02f", -+ "0c18ab727725d62fd3a2714b7185c09faca130438eff1675b38beca7f93a6962d7b98cb300ea33067a2035cdd694348784aa2eda2f16c731eca119a050d3b3ce7d5c0fd6c234354a1da98c0642451922f670984d035f8c6f35031d6188bbeb31a95e99e21b26f6eb5e2af3c7f8eea426357b3b5f83e0029f4c4732bca366c9aa625748297f039327c276cd8d9c9bf692a47af098aa50ca97b99961bef8bc2a7a802e0b8cfdb84319", -+ "92d5909d18a8b2b9971cd1627b461e98a74ba377186a6a9df5bd133635250b300abccb2254cacb775df6d99f7c7d0952653c28e6909b9f9a45adce691f7adc1afffcd9b06e49f775364cc2c62825b9c1a86089080e26b57e732aac98d80d009bfe50df01b95205aa07ed8ec5c873da3b92d00d53af825aa64b3c634c5ece40bff152c331222d3453fd92e0ca17cef19ecb96a6eed4961b627aca48b12fecd091754f770d52ba861546", -+ "802f22e4a388e874927fef24c797408254e03910bab5bf372320207f8067f2b1ea543917d4a27df89f5bf936ba12e04302bde23119533d0976beca9e20cc16b4dbf17a2ddc44b66aba76c61ad59d5e90de02a88327ead0a8b75463a1a68e307a6e2e53ecc1986274b9ee80bc9f3140671d5285bc5fb57b281042a8978a1175900c6073fd7bd740122956602c1aa773dd2896674d0a6beab24454b107f7c847acb31a0d332b4dfc5e3f2f", -+ "3844fe65db11c92fb90bf15e2e0cd216b5b5be91604baf3b84a0ca480e41ecfaca3709b32f8c6e8761406a635b88eec91e075c48799a16ca08f295d9766d74475c47f3f2a274eae8a6ee1d191a7f37ee413a4bf42cad52acd5564a651715ae42ac2cddd52f819c692ecdef52ecb763270322cdca7bd5aef71428fa73e844568b96b43c89bf1ed42a0abf209ffad0eeec286c6f141e8af073ba4adfbbdeda253752ae36c9957dfc905b4c49", -+ "329377f7bf3c8d74991a7d61b0cf39baff5d485d79751b0d5ad017d23bec570fb19810105bab79ab5acb102ab972165224d4ec888ec7de5148077fa9c1bb6820e0d91ae4e2591a21fec2f820606ce4bafc1e377f8dc3a5bd1a9e2772a57abccd0b757164d768872c91d02789545ab5b203f688d71dd08522a3fd2f5bcd7df507aebf1ca27ddff0a82afb7aa9c180008f49d1325adf97d047e77238fc75f56356de4e87d8c961575c9f6362c9", -+ "f7f269929b0d71ea8eef7120e55ccba691c582dd534692abef35c0fe9dec7dae973cd9702e5ad420d278fe0e653fdcb22fdcb63148109ec7e94f2d0750b28157dd1764376ae10fdb0a4aef3b304bd82793e0595f941226a2d72abbc929f53134dc495b0d65ced409914f94c2523f3dfbbdeeac84ae247ab5d1b9ea33dce1a808885a55be1f3683b46f4be73d9b62eec2585f690056858dfc427aabf591cd276724885bcd4c00b93bb51fb7484d", -+ "ac022309aa2c4d7fb628255b8b7fb4c3e3ae64b1cb65e0de711a6def1653d95d8088871cb8905fe8ae76423604988a8f77589f3f776dc1e4b30dbe9dd262b2187db02518a132d219bd1a06ebac13132b5164b6c420b37dd2ccee7d69b3b7fa12e54f0a53b853d490a68379ea1fa2d79762830ffb71bf86aab506b51f85c4b6a41b69325c7d0c7aa85b93b7144489d213e8f33dbb879fce22849865337b620b155cb2d2d36a68832889e30194d36d", -+ "d009c2b78a8f02e5e5dbb586ef71fc324b375092e15913ca1a5bfd22d516baadb96867bee3562e77c4a4852344a1a76c30728be5e22400b4cc41711f66754c246a520498d8c24f0205b9c873748dbeb67fe1ad099ad04cf89f4b517f0aa481136d9f6de2d727df01c6aa4099da59d4382b51e25fd47c33d9842c32b62331e50794bfe8b61b3ba9de1b8b704779c6d65edff3af00f121ab4a7ea384edabe47c6d0098a48991f387ca4444135ec59d46", -+ "c00bab36cce69899817d1425016d222d7303197ed3e3fdcac744705e7f178a1ac745968900f69299163e19b3161f3e0a4cc55aa2e4e71e0ee6ac427d1f4d14e063f68d303ddfbb18118335cfa7a6a90d99c38319ee76f7a884846a9e0b68030bf28e78bfbd56359b9368842814da42b04cb0e307d5d846dc22f049147bae31b9a956d17676a8cc348dafa3cabc2007a30e730e3894dddf9999fb8819086311f0703e141613ed6dcd7af8510e2dc435b0", -+ "c9789152a9fc29698d49ed95f09bd11b75f18a8c5615a73dbe54ae5e550027fd0ae6a8b60667040c1b12de3d1ee3f6bf061c78c951a3210effc912e19f482dd4de152063c588c44903bc11761706fd935afa040df085b08144d83d0dde32b46ab52f4fae98ac116c7ff11d7f553450c2e37b9c5f0b1dd9e0b8640a24cba6f2a5246c41f197f46e3dc8a29131c79bef3351c6e277a0a34442274d546ccd058891277473d668420f121750d19cd684267405", -+ "06a15a0731ce52557e368bcbaa11ef3399299e36fb9f2eda6e5726907c1d29c5c6fc581405ba48c7e2e522206a8f128d7c1c939d1132a00bd7d6366aa82724e968964eb2e373563f607dfa649590dcf5589114df69da5547fef8d1604cc4c6de1ed5783c8746918a4dd31168d6bc8784cd0c769206bd803d6ca8557b66748770402b075ef44b38157d4c0da7c6281725a2065d087b1f7b23455fa673bdeeba45b983311c44eabe9ef4b7bde3420ae9881863", -+ "d08aacef2d7a41aec09473bd8a44f628e15addb7b9e5b77a1e09c8ab4942f379a0bfcb324d580b774666f18ae78dd36710824ff12393f059068fe4b559c53662c2b0e6c69e23785c8f32554e837ec1714bee902e60737b639dd933af4f68cb9d7de77e1f3b28e5b122891afce62b79acd5b1ab4ba411662cc77d806449e69c5a45a143b742d98ac84a0826d68433b9b700ace6cd472ba2d58a90847f42ce9c43f38ffc017db4bf40450b2eee1f4594dc740c0f", -+ "6a6058b0a498b7ea76a93c646eb9b8629f0cba4a0c726420c5f67ba9b0412cade356abdf0a4fb94384bad32ce0d5dd9e23dcaae1d6f28ff8683616b30f1392890c67b3a2c04b360893b801f127e527e4da82e239f4c878da13f4a4f1c76db07190e77ec123995168102fb274434a2d1e12913b9b5cbab4aacaad2bd89d88b3ca2b8e60dacf7c22c9379097ff60880f552e320ca3b571994f52534470feee2b39e0dadb5cd88257a3e459a4cc6f12f17b8d54e1bb", -+ "adeced01fc5671531cbb45679f5ddd42b3a95151677b6125aaf6f5e8f82fbabaa5ecf7c3552c2458587224f0042870f178f5fca5465250e75d71352e652eeed23cdb7f915f5ebb44099b6db116ca1be45530ac8ed32b7f161d60ed4397ad3d7d649ae6bf75ca5bec891d8e595605be9764f3a03965e1fe0eaffbf212e3df4f0fa35e08ff9d0091e6d4ac4748edfe43b611085a6ffec163014655fdd839fd9e81b63b1fa8cae4ec335ec343289758e389a79ceedfae", -+ "d014592f3a83ba40af366f137c674724916c3cdd3f6cf9d4c5c7c8d6d51ebf26e315e2c12b3546be56fb52382904046ecbd2f5b883aa4ff473de6f0c26ab862c3fa34bf3d880cc1911ce39a4088c6617c179dc5faf68a2c488bbde12d67b50f73abcfab0e3b062e68c95363e11f5f1de8ec36ed01ea21442518089045df67d346135283ad5b3fff80cf57f20876849f6db9fa139728358415a90610f69ec720fc92d8234e3e122551e9df2c644c4a2c4e3734d07de8e", -+ "c0d0c37838873ba8757d6e41b409605043bc1635edcd731219587676d94217e9f0ab44b71de25000661ce7303b7015f45e6eaa7b7ebef92b8f4a34c902c908d2172185505fa33aca5a41be83079316cdfdd430fc2c45f505f85d867e6d516f7e1bf19c001d9f43018968aab65ec031b3801399231c83ec9e622dab5629922a6b424cab938c135ff7310501c2c02971bfd2f577e25904d1a618baf0859f77f4e8b1d0cde9544e95ec52ff710c0672fdb3d891feeea2b017", -+ "7022e7f00902219ba97baa0e940e8ac7727f58955aa068c29680fac4a16bcd812c03eeb5adbcfe867a7f7c6b5d89f4641adb9173b76a1a8438866f9b4f640ce2aedf5f1080c890bcf515b4be4e3e512352f1e5323c62ec46cb73f3d71be8235fee55a154763f7c3f9aeb61ffd28f4cd93d3310f608e2133586bf1ab3f102de96f64c68a4668de8acb2a76a7ce0cddddc8fa3df5e9d230823da16ed9ebb402d36e38e6e018795e5a71517ecab5f9ca472b9ced8ff69d2d195", -+ "acaf4baf3681ab865ab9abfae41697141ead9d5e98523c2e0e1eeb6373dd15405242a3393611e19b693cabaa4e45ac866cc66663a6e898dc73095a4132d43fb78ff7166724f06562fc6c546c78f2d5087467fcfb780478ec871ac38d9516c2f62bdb66c00218747e959b24f1f1795fafe39ee4109a1f84e3f82e96436a3f8e2c74ef1a665b0daaa459c7a80757b52c905e2fb4e30c4a3f882e87bce35d70e2925a1671205c28c89886a49e045e31434abaab4a7aed077ff22c", -+ "84cb6ec8a2da4f6c3b15edf77f9af9e44e13d67acc17b24bd4c7a33980f37050c0301ba3aa15ad92efe842cd3ebd3636cf945bb1f199fe0682037b9dacf86f162dadabfa625239c37f8b8db9901df0e618ff56fa62a57499f7ba83baebc085eaf3dda850835520344a67e09419368d81012168e5de5ea45158397af9a5c6a1657b26f319b66f816cd2c28996547d697e8df2bb163ccb9dda4d6691dffd102a13667ab9cde60ffbfb872187d9c425a7f67c1d9fffff9276ed0aeb", -+ "6a52c9bbbba454c14540b2be58230d78ecbeb391646a0c6fcce2f789086a78364b81ae85d5396d7cfa8b46bda41e3083ec5cf7b4c47dc601c8a697df52f557defca248506dbebab25657f5a561d09625b7f4b2f0119a12beeac087efc9d350a735c35d2431c1da7dda99befb17f41a3dc4da0f00bb95366be128538ce27763d81f832fe3c1d4efc07b5b08ad8dc9e65fb5e48546664e18cb2d3bb3fe1f56fa7aae718c5e3bbdeaf70e15023f6a25b72a2d177fcfd04211d40664fe", -+ "c3c4d3b31f1f5f9538923df3478c84fffaef411520a542da9a220ee4132eabb9d718b5076fb2f985485e8ba058330aed27ddfd3afa3db34aa60301088caec3d0053828c0c2bc87e2e61db5ea5a29f62fdad9c8b5fc5063ec4ee865e5b2e35fac0c7a835d5f57a1b1079833c25fc38fcb14311c54f8a3bd251bca19342d69e5785f9c2e43cf189d421c76c8e8db925d70fa0fae5ee3a28c4047c23a2b8a167ce53f35ced33bec822b88b06f41558c47d4fed1bfa3e21eb060df4d8ba1", -+ "8d55e92136992ba23856c1aea109766fc44772477efc932b3194af2265e433ed77d63b44d2a1cff2e8680eff120a430fe012f0f09c6201d546e13ad46fc4ce910eab27bb1569879abed2d9c37fae9f1267c2216ec5debcb20d4de58461a621e6ce8946899de81c0add44d35e27b7982a97f2a5e6314901caebe41dbba35f48bc9244ca6dca2bdde7306435892f287036df088633a070c2e385815ab3e2bfc1a47c05a5b9fe0e80dd6e38e4713a70c8f82bd32475eea8400c7bc67f59cf", -+ "5016284e20362610fa05ca9d789cad25f6d43263787e7e085476764ce4a8908ce99b262b375e9d106170b1bec1f473d5e777e0c1896533040e39c8c1465e07907ef5860e14e4d8310013e35f12090e0bfc687474b1f15f3dd2033a0edac5246102da4deec7e188c3517d84d9c2a0a4497a4c5f82a30f1ba009e45ee6eb3ab4368c720ea6feee428ffd2c4cc52debb8d634a64176572c72368f94a66689f23f8a01218f532117af5a8060d140e7ca435a92882fcb5630ebe14a4805f1dc83", -+ "05456ec59b8d41bbd736727976b96b38c43827f9e16169be673ff37870c2ecd5f0d1ea1a136be4cc7b047a02a4421d484fd2a12ece418e42ee391a13a0b1df5a0162b29ab70d3fe3e04ba6ab26b37d62b7cf05a5e2f033611bf970b8e1f30e198e483e740fa9618c1e8677e07b61296b94a9787a68fba622d7653b5568f4a8628025939b0f74389ea8fced6098c065bf2a869fd8e07d705eadb53006be2abb716a3114ceb0236d7e916f037cb954cf977720855d12be76d900ca124a2a66bb", -+ "eb6f60b83fcee77060ff346aaf6ec34d82a8af469947d3b5074cde8eb26566eb1fa039bcc707738df1e95869bd827c246e88436f0614d9834ead5392ef376105c4a9f370071cdeaaff6ca0f18b74c3a48d19a717253c49bd9009ccbfdd5728a08b7d112a2ed8dbafbbb46d7a75dc9a05e09bfde1a0a92d74a51887f9d123d7896e9f9d0057b660ed7d55454c069d3c5260411db4cdc67e7b74f680d7ac4b9dcc2f8baf72e15e6b3cafebcdf449a6436ed2c398b675f79c644747c57553bf7ea2", -+ "187a88e88514f6c4157c1ba40b442baae1ae563a6c989277443b12a219aa484cb9fa8adbb9a29d429f50155321b15664926317477079c7060dfdaa84c1d74bba78892c34e6f21ad35208d2ae622012401696bff5cd57b6485944b3db7b9071fa5f57fbfb1085d91bb9cff5808d662cdc6c8157249478262c44b7fbc397ed42a4977b202e817717bfccc9f0467294062313f7705251ed09573f16d23429361fada259dfb300369c4198f07341b38e84d02cdb74af5de6aab1fc2026208ea7c418c0", -+ "be31bc96606d0fab007e5caeded2f1c9f747c759777e9b6eef962bed49e45a1d4fc993e279d024915e600865ecb087b960584be18c41114d3c43f92169b9e0e1f85a0ebcd4e196376ccdc920e66103cd3b1c58407d0aafd0e003c4e341a1daddb9f4faba974362a32f35db83384b05ae8e3322d728893861afd8b1c940de5a17f691e763ce4969b6d94f67fb4a0235d100225bd8602f291388f0ca4a568748ad0d6040f1262eac2aede6cd27419bb78a394c1ffad72c262be8c3f9d9619d633e51d0", -+ "4d83d85ca838b4518588f2a90228a4dd18f14dd5b4c012d26298a97d848abbd825d221d02cceb6e8c701b4ad00e1dee4889b5c533e4bb60f1f41a4a61ee5478be2c1b1016c30345afd7a5253668260515e70751f22c8b4022d7fe4877d7bbce90b46531507dd3e89549e7fd58ea28f4cb23d33662bd003c1345ba94cc4b06867f778957901a8c441bee0f3b12e16463a51f7e50690356971dd73a686a49fda1eae46c9d54fba262811d698025d0ee053f1c58591c3bb3cbde69de0b31549ef5b69cf10", -+ "cdeb07d36dc5f9a1cd717a9e9cca37a2ce93caa298eee63571f7d6c5fde2a11c666cf53cf2dcb41ca2ea2319e7230ca68e38c647905928713a13982bf47fe33d7095ebd50b2df976208920a43eb2e29b942f32467403c45cea18bf44e0f6aeb155b48a8e5c471fec972a9d62f7ae093d2758f0aaec7ca50cb4725bfa219f1a3a46ad6bde7361f445f86b94d66b8ece080e56c510250693a5d0ea0ae87b4421860b853bcf0381eae4f1bf7c5c0472a93ad18407bc88475ab8560d344a921d3e86a02da397", -+ "a598fad52852c5d51ae3b10528fc1f722e21d44fbd42ae5acdf20e85a28532e646a223d27fd907bfd38eb8bb75175636892f8242877aab89e8c0824d368f3339ce7a82aa4e5af6db1f3b588a4d667a00f67bee37cfd2724dde06d2909fb9e58d892f4cfd2c4ca85acdf8256f5458b030a6bda151154ff2e6d7a8da90b54a2884c8a99fab5a4ac211ff23dc0975f4f592fd1b6b9dc7783bdcd2d4ca4e68d2902f2013e122cb62e2bff6b0a98ec55ba25837e21f1cfe67739b568d43e6413dab2bd1dc471e5a", -+ "17b68c74c9fe4926e8102070916a4e381b9fe25f5973c9bd4b04ce25749fc18931f37a65a356d3f5e5a1ef125d546f4f0ea797c15fb2efea6fbfcc5739c564693d47adeb12dcb3d98a2830719b13247792cb2491dca159a28138c6cff925aca42f4fdb02e73fbd508ec49b25c60703a7595a3e8f44b155b371d525e48e7e5dc84ac7b17c52bf5e526a67e7187234a2f19f57c548c70fc0b27183df73ffa53fa58b658034c896fa791ae9a7fd2620f5e46ce84c842a6e60e9324ae4db224ffc87d9617cb85ca2", -+ "b9e4267ea39e1de1fed0579f93bb351007c9f8fcdd811053fae33f09e2753d7428f04e1a9efcd45ea701a5d87a35b3afb2e6b65365dee6ead0bbb611b7797b212ac688653f542e604a39df277f12514ddfee3b4e27b98395c2cd97a203f1f1153c50327965770802ec2c9783edc428271762b275471e7ac65ac36523df28b0d7e6e6ccc7674268a132a63411fc82c0738dbb68af003b769a0bf9e6587b36476cb465350fee13f88ea355d47ffac7b0f964f4139db11b7642cb8d75fe1bc74d859b6d9e884f75ac", -+ "8ca704fe7208fe5f9c23110c0b3b4eee0ef632cae82bda68d8db2436ad409aa05cf159223586e1e6d8bdae9f316ea786809fbe7fe81ec61c61552d3a83cd6beaf652d1263862664df6aae321d0323440430f400f291c3efbe5d5c690b0cc6b0bf871b3933befb40bc870e2ee1ebb68025a2dcc11b68daadef6be29b5f21e440374301bde1e80dcfade4c9d681480e65ec494a6af48df232c3d51447b9d06be714949249c44c43cf73ed13ef0d533e770284e51369d94ae241a5fb2f163893071b2b4c118aeaf9eae", -+ "4fd8dd01012bb4df82bf42e0683f998e6f52dd9c5617bae33f867d6c0b69798cead8179346d70acc941abbbdd26e3229d5651361d2252c72ff22db2938d06ff6fc29a42fdf800ae967d06479bc7bbb8e71f40b1190a4b7189ffc9a7096cdb76d40aec424e1388e1eb7ef4ac3b34f3f089da8fda7d1927f5d775c0b2801d22dd1265c973158f640cec93edfed06dc80b20ef8c496b98289d54d46ccd205951cbb0f4e7daeb866b60bacb483411e4382b6f04d472843186bd0e31fbaa93e5c901ec028efafeb45fc551a", -+ "e9ee1b22b04b321a5fdd8301627011f583887d77560fb0f35552e207561f81e38ac58a0d0aeaf832d1ee72d913720d01f75574e9a321864fe95f4d0d8f0b8db97649a53e71e940aede5c40b4b9105daa42a6fb2811b61209247534cbaf830b07abe338d75d2f5f4eb1c3cf151e9edabe2c8d5f6fff08fac1495ef48160b100d30dcb0676700bcceb28723a29980ab0766a93abb8cb3d1963007db8458ed99b689d2a7c28c788743c80e8c1239b20982c81dadd0eed6740c65fbc4ef15c7b5569cb9fc997c6550a34b3b2", -+ "ec01e3a60964360f7f23ab0b22e021815765ad706f242265ebc19a2bb9e4eac94393952dcf61aae47682671a10f9165f0b20adf83a6706bfbdcf04c6faba6114653a35584267267873291c6fe7ff5f7695243143421509502c8875aafa9e9afe5be5ef2c851c7f35d69be5d3896000ccdbbfab5c238bb34d607cfe2d55d748880545b4aa7ca61137992925189025c62654b1f20d49c3ccd75aa73ce99cd7258dabedd6480a9f5185531fc0118beb68cc0a9cd182f6973287cf9252e12be5b619f15c25b65c71b7a316ebfd", -+ "db51a2f84704b78414093aa93708ec5e78573595c6e3a16c9e15744fa0f98ec78a1b3ed1e16f9717c01f6cab1bff0d56367ffc516c2e33261074935e0735ccf0d018744b4d28450f9a4db0dcf7ff504d3183aa967f76a507357948da9018fc38f150db53e2df6cea14466f03792f8bc11bdb5266dd6d508cde9e12ff04305c0295de29de19d491ad86e766774bb517e7e65befb1c5e2c267f013e235d8483e177214f89978b4cdc81aa7eff8b39f2825ad3a1b6ac1424e30edd49b067d770f16e74dd7a9c3af2ad74289a676", -+ "00e40f30ae3746edad0f5dd03d0e640933cf3d1694804c1e1ed6399ac36611d405196ee48f129344a8512feda16a354517871322bd5d9c6a1b592933eab531923efb393ffb23d9109cbe1075cebfa5fb917b40df028a621460ff6783c798792cb1d9635b5a6f84ec13918fa302924649b5c7fcb1f7007f0d2f06e9cfd7c27491e565a96c68a0c3644f92cd8f38857258c33801c5d537a83dfe583cba59d7eec7e394199c0a2660a62fabe3ed2099d57f315a6cd8de1a4ade29d977f15d65759cff433e5ac0c182aef3761163e1", -+ "3c5ea24d0d9b618294a263f062b2414a722be4eb10dfc346a6ec3b821d7396eba61cd6ef33618b04cd087a811f299d4606820227f16000d7c839062b96d3e3f59cd1a082448d13fc8f56b3fa7fb5f66d0350aa3b72dd7c165d590282f7da2e12cfe9e60e1796122bb8c2d40fdc2997af634b9c6b127a893dfb3467909378300db3da911be1d7b616bb8e0572433e65527e15d936500a2c60e9f9909dcf22ab5e4b6700f0238c205b4a813626fac3d945bab2637fb08203044a73d20c9a3fcf7c3fc4eb7807c3276dd5f73ce89597", -+ "9271aeeebfac46f4de85df78f1bfd36136aa8905e15835c9e1941176f71e3aa5b1b131843d40479735e23e182a2bd71f66f6149dccb7ed8c16469079dc8590bbf165374951785f4531f7e7361de62f936cfb23a2b5bdf186632e7042a0dd451fdc9b7208f923f3a5f250ae590ec348c63a16c3aacaf7379f53b5dd4152dcd40d23e683e2156e64c592ffc07e2cd6bbeebef4dd590b2f6b2bcbf08fcd111c079f5c4033adb6c17574f8756ecd87be27eff1d7c8e8d0324438d59ae171d5a17128fbcb5533d921bd044a2038a5046b33", -+ "4e3e533d5bcb15793d1b9d0468aaee801f32fdb486b11027183553a09ddbee8213924296f2815dc61577297459e834bf1c7a53f87d43782209e589b8295219ba7073a8fff18ad647fdb474fa39e1faa69911bf83438d5f64fe52f38ce6a991f25812c8f548de7bf2fdea7e9b4782beb4011d3567184c817521a2ba0ebad75b892f7f8e35d68b099827a1b08a84ec5e8125651d6f260295684d0ab1011a9209d2bdeb75128bf5364774d7df91e0746b7b08bda9185035f4f226e7d0a1946fcaa9c607a66b185d8546aac2800e85b74e67", -+ "b5d89fa2d94531093365d1259cc6fe8827fea48e6374c8b9a8c4d2209c280fa5c44958a1847222a692a59e6aa2696e6cdc8a543dd89b0ce03bc293b4e78d6ef48e1839694ccd5c65661143095c705b07e3ced84a0f5959114dd89deb956ab3fac8130eb4a878278205b801ae41a29e34146192308c4e759b374757b0c3b00319bce92a1b95a4d2ee179fd6714ff96155d26f693a5bc973f84ac8b3b91e3926276297532d98b46992a3f104c08100bf1671c43134bac280c617da711e90a0100137525375ebb12802a428885ae7fce6514a", -+ "40e3d8048fc10650cb8a7fc2e7113e26dec34f9ca2d5129cd10a8e8e44d113d61ee48c7d003e19fd307fc6debd70feb30243f298c510ccc4418355ce143066f067ad7c6de7288c3080e7ad46a23c8d34deb55a43e652fe90444ad3c57d3ec1e1c489d63ef915a24bc74a7925a0a7b1e1523f21ca8fee78df24e3d0a68d0013423db97c280799a0618229c0f2c167289a891e5c8d6661ab21285951c31710e3b5fe55f6347fe16d9b40507948a59252efeb616df83e5c098b07d0a7247cd371daff0e50491c582503fd89f79ba94d6af9ed76", -+ "1fa444de01dd3901e2b4684e3d7a799ffa02d85afd35fb30fe4c9d672837bee6dd8a3b8608b4bb5e589220ad5a854f46b46e41c6d57ad124a46beab4169ff69fee7e3838a6165e19dad8eb5d7bf53d4edd3cd2769daf219510a02fdd2afe0c0e1da3cd30fcd1aa88b68965586f07a25a1720fbd90a096ea30fc8e945e3637d7857c8a9c0ab4154ffb2000e57b5f9adfa4e4eaf8065bc3c2b2e75f495963325588785a6ce417dcddffd299873b15dcccca128d63cd4eeeadb64cda28099a9ad7c80d34844901f26b88b00b9aafeb2f90286d29d", -+ "fde0a0d9d813983bd1f55cf778a003a2023b34a555322ab280584537bc6bdd844d22a7d6066c18da83ec09f3d8d5a1aab4be0d5ce19b436052f6e259a4b49017a1f47f1fe2bf115d5bc8599fb216351c60dd6b1bedb2e6f4dcadf424b833501b6f099cbfad9e2290680fb69c25032b42a6274f7cb9b5c5950401354838a45f7cb77b95bf54718e2f3d3d9fb91eb2311903980277396398d9736d8e92fd838594ac8a537c6c529db5a8a4f89290e6ba6f20ac0e5ed6fef40901d0e0e8e3e502990811f9acaae555dd54eb1bcd96b513e2fe751bec", -+ "9f8e0caec87858599f5ab29bff86da78a841a918a023a111098687ecdf2747612d3f3809d9ca400b878bd4f92c43a1004f1c17c7f19a3cd1ce449bd2b23aff551623c37dd8c0be56bf3fd857b500c2b9f9ccea62481944090a3cf3b6ee81d9af8eeb60f65ef150f9fa4d3ed6ce4762d3d4f174ee8ccd460c25cafac0ea5ec8a6a4b2f9e8c0520cb7061155e532cb65f188b01e4b9086db951f504b060c296b326b3fc1c590498ecce594f828f4a10ea416675720ae505295d38a791bd0e93f428448a8f4c1fc0af53604a9e8255384d29ae5c334e2", -+ "33d1e683a4c97ee6bbaa5f9df1a88cb53b7f3c157b6045d70a56fda0ccbd3a1fa1f049cd564da072b53f415bf5fb843771c1d2551fd075d33377362b2f7c0645f9723123d11975991db8a2b518f02e2c7c30342a044754290bae2c77496d755e5981f12e6b0a0174280b958bf11ed628a9062775993ced04bf752ea8d165e3ac2177d7cd1b9371c44efa98f0b3e68602a839d384eec007979f46429dafb138cbc231ad928a9f65f7d66fac77416395e8f1debaaf76ec2e4e03e8674102cd26f614739f3ec9f949033df1fb97e87c2326d65aef94ed5f", -+ "180048f09d0b480887af7fd548a85abf605440c1ddde6afe4c30c30670233f7bf928f43b4681f59279ebbda5e8f8f2a1abefdee129e18ac60f9224e90b38b0aabd01308e0a27f41b6fb2ee07ee176ec9048c5fe33c3f7c791469c81f30e28170585b9f3e7e3c8c2e9d74370cb4518f13bf2dee048cbd98ffa32d85e43bcc64a626b40efb51ce712925fdd6fee006dc68b88004a81549d2121986dd1966084cd654a7c6686b3bae32afbd9625e09344e85cf9611ea08dfce835a2e5b3726e69ae8a76a97db60fcc539944ba4b1e8449e4d9802ae99fae86", -+ "13c0bc2f5eb887cd90eae426143764cf82b3545998c386007cca871890912217aa143ac4ed4ddb5a7495b704aa4de18419b8664b15bc26cfc6596a4d2ae408f98b47a566476d5802d594ba84c2f538def9d016661f6404bb2337a3932a24f6e30073a6c9c274b940c62c727242e24466084a3ea336365d71ea8fa6499c0ea8d59eea505f1126b99c795023c4963aa0d99323d0391e8701110edf551b2d3799e1063ca443f1add162156e445502ca1a052fe70c289838593b58839fc63de128a03e2bbf389e22ae0cf957fd03315ee407b096cc1cfd92dee6", -+ "6f1eb607d679efef065df08987a1174aab41bdac8aece7726dfa65805d6fff5b3d17a672d96b770dc32165f144f0f7324822a5c87563b7cd9e37a742ae83ef245d09006d91576f435a03476f509ea2936636232f66aa7f6cdf1ac187bbd1fcb8e20f8791866e60ed96c73374c12ac16795e999b891c64507d2dbd97e5fc29fac750ad27f2937cbcd29fdafccf27ab22453834d475f6186eaf975a36fad5c8bd61c21da554e1ded46c4c39765dcf5c8f5ccfb49b6a4dc562c919d0c7d8940ec536ab2448ec3c9a9c8b0e8fd4870cad9de2577c7b0c38563f355", -+ "dcdd993c94d3acbc555f464871a32c5da6f13b3d5bbc3e34429705e8ad2e76393fdd96a69a94acb652f5dc3c120d41187e9aa919669f727c4868013b0cb6acc165c1b7706c52248e15c3bf81eb6c147619467945c7c48fa14a73e7c3d5bec91706c567145342a026c9d97eff97ec672c5debb9df1a998083b0b0081d65c517b3e5634c95e347e781aa30ca1c8af815e2e494d844e847fdcb41622894a518dc36571123a40bfdbe8c4f4cff44d83c61dd9dcd24c464c53b395edb31efee9f3aa080e87cdc3d22d613ae84a53c9249c32c96f9a3bc4629bb126a70", -+ "49971f9823e63c3a72574d977953329e813b22a8387cd13f56d8ea77a5d1a8a20012632d1d8732bbcb9f756b9675aab5db927beacab7ca263e5718b8dfa7b2eed9a91bf5ed163b16139d45f7b8cc7e3f7bdda6202106f67dfb23b7c315ee3e17a09d466b1e6b13e7c7428184a979f5358667b4fa8bd40bcc8ea46058db44587a85377ac46bf155136c09ac58cb6c27f28e17028c91e7e8f74d5b500e56293b316974f02b9d9ea205d9b6ac4cfb74eb8eb0c944577fd2f41316368307beab3e327bf7dbaa0a4428836ec4e895dea635234abeaf113ceeadac33c7a3", -+ "c57a9cc958cee983599b04fe694f15fb470fcbc53e4bfcc00a27351b12d5d2434444253ad4184e87b81b738922ffd7ff1dc1e54f39c5518b49fb8fe50d63e3935f99e4bd125e8dc0ba8a17fd62de709339a43fabe15cf86d96a54010112170c340cfac4132182eed7301402bc7c8276089dec38488af145cb6222525894658f03501204b7a66aba0be1b557b28a2f652d66f7313ed825ecc4d8596c1be7420d4425b86a1a90a5b7f30d0f24e0d1aae0eb619ca457a71699e44be612a4011c597ee80b94d5507e429d7fc6af22579cd6ad642723b05ef169fade526fb", -+ "0568a672cd1ecbaa947045b712e2ac27995392fbef8f9488f79803cbee561c212287f080eca95adb5ba42739d78e3ba667f06045d87850d3a0499358649caa257ad29f1a9c511e7054db20554d15cbb55ff854afa45cae475c729cea72ede953522031865bc02b95589ed4d9841c552a8cc94904a93ed09ed77222f6c178195056be59bc4e96a815adf534e6b466fb47e262ff79c803c157a21b6e2269c2e0abeb494113cd868d8466e82d4b2f6a28b73645853d96bc9242515d803e33294848d3fe42fdff68da53c03491636beede47ff1399dd3d54a5e914d55d7adf", -+ "3f19f61a4cd085796731ac9f85a75a8bce77031932c31762d87d8b8d07b8bd19ff78d6b7d1bd1e87f3a4f41aad03b6c4d17a6cbc86be55f7c8b88ada047bb04f8d49f1c34bcf81cc0f3389ad01a758fc7eeb0072aa9ad1481992bfdde82e438e75590a4423832dfbe3756e2229ea873bc3606e6d72174cb2163bf40b5d49c81009dab85ecc03e311351bbf96e32c030a2b276a7698cb25bc2c967acb3213161a1fdde7d912cd6a804490f8056c47da1333f6e35c41e749c2c23919cb9af5eec5652e6e072b034fb1682e9aaa194a9c0bd456ea0b008d14dbce37967a7a8e", -+ "705f98f632d99d3651793825c38dc4deda56c59eac539da6a0159c83131cf8ab6f2ee0c3b74111fde351f7aa1a8c500a0cecab17c212d2c58ca09eae608c8eefc922b9902ef8d6832f799ba48c3c28aa702b3242107edeba01daafe424406a3822965056cfe8783455a671e93b1e2eae2321364f1871471c82124df33bc09e1b52882bd7e1c4c7d0b2f3dd4a28c2a002a43246768af0700f9659de99d62167be93177aabf19d678e79e9c726ac510d94e74873eda99620a3961930cd91937c88a06d8153d64fd60da7ca38cf26d1d4f04a0df273f52127c53fdc593f0f8df9", -+ "ea6f8e977c954657b45f25480ff42c36c7a10c77caa26eb1c907062e24fbca5aebc65cacca0de10abea8c78322f08672e13d8ac16996eca1aa17402eaea4c1cc6c800b22dc18cb8d620192d74bac02c07b5cfa61e513c7f28b7e29b9700e0e442720bf4c669d4995da19d19f841d9eb68cc74153592591e3bf059ef616b95305aa453b32fe99a91afb35bd482cf2b7aa42702837a53be3c38883d2963020e347556f841254ec6b85854485fe8c520b05f2ea67a9bf3981555c20991e2bacd4db5b418228b6002d8d41c025cb472bf5443aaa885974a408ea7f2e3f932c600deb", -+ "408190134ed06556811b1af808ab2d986aff152a28de2c41a2207c0ccc18125ac20f48384de89ea7c80cda1da14e60cc1599943646b4c0082bbcda2d9fa55a13e9df2934edf15eb4fd41f25fa3dd706ab6de522ed351b106321e494e7a27d5f7caf44ec6fadf1122d227eefc0f57aefc140d2c63d07dcbfd65790b1099745ed042cfd1548242076b98e616b76ff0d53db5179df8dd62c06a36a8b9e95a671e2a9b9dd3fb187a31ae5828d218ec5851913e0b52e2532bd4bf9e7b349f32de2b6d5d3cdf9f372d49617b6220c93c05962327e99a0480488443349f0fd54c1860f7c8", -+ "5f9e5c6f38573a85010a9d84d33f29c057003b2645e3ea6f72cbc7af95d197ce6a06b13fea81722853e6991791b8b15091cd066f5ed913592ed3d3af5370d39ba22beeb2a582a414b16824b77e194a094c2afdcc09aa73ce36f4943cca5ae32c5017dc398801dd92a47382d9327c9f6cffd38ca4167cd836f7855fc5ff048d8efba378cdde224905a0425e6b1de061fc951c5e624a5153b008ad41160a710b3ff2081748d5e02deb9f841f4fc6cf4a15153dd4fe874fd447482696283e79ee0e6bc8c1c0409baa5ab02c5209c319e3169b2476149c0c6e541c6197ca46e004eef533", -+ "218c6b3508aec69574f2b5039b30b942b72a8349d05f48ff945bbbe5c8957d5a6199492a6bf54bab821c9377e2edfa4c908384664d2c80112d5e805d66e0a551b941021be17dd20bd825bea9a3b6afb1b8c605805b3bda58750f03ea5c953a698494b425d8980c69f34d1c3f6b5866e8717031152a127215c256e08873c21b0f5cc85875d0f7c94601659150c04cd5fe5d381ba29983a2d94fcd3a65a94c53c7279cd000dddd4253d8cff8d7f6ace10247fe3bc30d63ba4bb54f557b3d22a3924369430d71ab37b701e9500bda70b5a643704858beed4726a889b6c9c91584194c68f1", -+ "dac26aa7273fc25d6e044c79fc2bfa46e59892a42bbca59a86826c91e76ab03e4bd9f7c0b5f08d1931d88b36ea77d94f7ba67cd4f1d3086e529427201119096ae066ae6f170940830ed7900de7bb9d66e09788287403a4ecc93c6da975d2fb08e918840a236c15f5d3a8f7375c2eeebbf6f01a6e7f29ca2b8d42df158414c320777433663c59fdcd1f39ca68e3473db721be7ce8c6dba5fddc024f94fedb286b0477581d451313ca8c737484daf60d67f9b2d56d4bcc271f7e9ae958c7f258efbc74d25753e0516f28282461941bf2dcc7dd8c7df6173b89760cefcac07190243ff863fb", -+ "c46e6512e6797cc7a54254a1b26b2de29aa83d6c4b1ea5a2786fbcec388270625b12635eae39e1fba013f8a65219421bca8b52a8ddfd431cda60299bdf160734d5a7450ec79620058522702174ae451b9bfa7c4a455fbbee3e1d048c7d4bac5131018228f137c8e130440c7059b4f15eaa34ce872a851a16ce86f982df78a00be4d564da2003a450ddee9ab43ea876b8b4b65c84f0b39265fd5456417afb5bc54997c986e66fc222f2123ba5e719c4d6b9a177b188277df384f1125821cf19d5248cef0be183ccdc84ac194506f740ed2188b2689ea4c9236a9e9e3a2fff85b6af4e9b49a3", -+ "1ccd4d278d67b65cf2564ecd4de1b55fe07adc80e1f735fe2f08ea53fd3977323689122c29c798957abaff6aba09bdcbf661d77f4dc8913ab1fe2bef38846166e3834785e7105d746484eff8c656af5d8c7854abc1c62b7fadb65521dc6f793d978bda9838eb3800417d32e8a24d8c8cb1d18a5de6ca79d9e1b0ff9aa25e6218fe944cf18666fecc1e31334b390260dbe0997539e1b02f6366b2aea4f4a21efe04f4b97568fcb39e59919d5ebac6543d5d0f48fc66b923c34aac377dc95c20329b837b6ed5e8d9a3d2089cd0d8f025658006ff41cbdaccca618822ca590ab155253f8bc1c7f5", -+ "9875209588395ee3c9fdd793fd48717cc84c8c3ea622b2ccc4a1be4448e6034b7810569855255031f10be5ffd714b05f9ce01972d712d40abf03d4d0ce175813a7a668f761324996093fc2aa5912f7fc2abdadd8775d2b4d9ad492216293381460ed8f6db3d641d1525f4242c348bbfe504c704f215dc461de51b5c75c1aae967936963848f16c673eca5e78dfd47eb19001d52d1bcf96c98956dad5ddf594a5da757e7ca35f2f69803b784e66ac5a58b75c228b8266ec592505e5d1ca87d81225738855f15bc0914677e81593fd409e77d159f8a908f67788de9eb06c5561547aada96c47c535", -+ "40c90e375e366f3756d89091eb3eed9fe0fbfc5638700af4617d358812bac53124a2205dd6756456787d49cd6a35e302479a0992288f47532e4ea7ab62fc5ad5adc690a5d9a446f7e035ad4641bd8dae83946aee3338ec984ccb5cc633e1409f2531eeffe05532a8b0062ba99454c9aeabf8ecb94db195af7032bfebc22912f49d39330add47ff8fa5720612d697f0b602738930e060a1bb214efc5e292224cf34e29deaea6b1b1ff847e94ecc997325ac38df61db45d82bf0e74a664d2fe085c20b04c39e90d6a170b68d2f1d373f00c731c524456ada73d659aaac9df3191a7a3865083343fc13", -+ "e8800d82e072210ca6d7fa2472028974780b76aad4bcb9ad362422dd05ae3232668251d164daa375a43b26a38cce28dbeb3dee1a4a579f70d0fe7febb29b5ece8aa836e050fb3d188c63aa9c3c0da6c717d86458a6096b5effceb964efdec7035960c09ccd10dea3c5f1c7f9f478d5887ebbe2e15c5ff85dbacbc444bb951c4eec7abecb89ed80187e409e2972ffe1a5f01562af109f2cf09471cf72cf83a3bb8f4e2ef38ed0e326b698296394e5b2718a5000c01425708e8ad0461e62462d8819c2377f13ab1be2c7c9f33dc06fe23cad27b87569f2ce2e56e4b2c60c7b1b3d370841d89ebdc1f192", -+ "796d6d1447d5b7e8c55cd8b2f8b7010db39f27565f907e3fc0e464ea2d4bb52b37f10e7c6dcfc59231b9cdee12c32aeb4adbc42b86e86eb6defb5b69e6ca75e1f4d0dae3e124e5a1b8b6697f7e10b0403f1f0a5ff848eef3752837a9ba17780f16a9a709188a8d5b89a2fa74adb2e651163b1c2b3d261e225c9158dcd9eb7ac3d6704cee290cdff6bcb3cb90cee030aa0d19d4693655c3c30ac6fc06d2ae37787c47126d57ed9a6bef5f8a6c56859aefc08755739a95aac57a4dd916a92ba9f3afbf969df8085949615033365c751a9a3e1a18cee98a69d22e64009bebf8307169b6c61de0617ecfafdf", -+ "4f9057183566153cf337b07c3f5556006de54c56b2a1e5326c07aaeabd1886ec6f1641358925db232b2f0dbf75229c796a7395b2f934c1f99090bec1123f3c841b1cb3c5b1ec42ed5408f2940f0c48a9470b852c46d6557853d459cecd2c32bbcd8ee21fa11e385eef0857cba4d8545a61b52a484cdd779db4739fbc7aa9860dcabe0488b98fa0b60c3f7d6153db279000a52ffb573dab37d2ab1896a90e5deb7ac6bbe56239085c325d83a917dc6e8a448425b718c2356b9f3066163555ec444f372e184e02c8c4c69b1c1c2ae2b51e45b98f73d933d18750968945ca85d6bbb22014b4c4015262e3c40d", -+ "79dcca7d8b81a61359e4aece21f3df7b99518ce70bd2f57a18bab5e7114af2add0a0cea7f319d69f231f060e0a539d9a23fb3e95451ce8c6340cfb09edf931df84203a39226dd9eb278f11b691ef612585b973daab373e65d11325898badf6732100371fd759960fa8fec373268421d28bffdb9b12a430b92fe4b07566ca0c89e616e49f8fc75ccd9cdc66db820d7c02e109aa5ed86b89770262918a518f90a2292f6b68d68ae03992e4259a17a23c84ec2a417f082b5abf3a26e44d2278ecb8ba9456965303a75f25394d1aaf5544590e74b14d8a4cc4050be2b0ebcfe4d2db6b12a02c68a3bcdda70301f3", -+ "848755dc31e25e9a42f9ec12d847d19f292c14c162c9aba49e972cb123b58b8e57bb263a923929833373858594ff52dbc298dbbc078599194e4c07b0e5fc1e10808bbacdb6e93c72b333685cf961f28eb0d5a395c63266b01f130d25db384b356e5da6d01042fc2359581b89c63b3bb2d1ce897fbc9e83fe85d9666cb60e6a8c657f70caad5387b8a045bf91095606802c8424ea8ac52ef29386dc46183378a5fcb2cb927428b8c070f1c42aafd3bc70ca25437807696a46873cfeb7b80ba2ebc3c4272443d445e46343a1465253a9eebd532a0d1d2c18264b91ff45159f245404ae9335f2af55c802772426b4", -+ "ecaa6e999ef355a0768730edb835db411829a3764f79d764bb5682af6d00f51b313e017b83fffe2e332cd4a3de0a81d6a52084d5748346a1f81eb9b183ff6d93d05edc00e938d001c90872dfe234e8dd085f639af168af4a07e18f1c56ca6c7c1addffc4a70eb4660666dda0321636c3f83479ad3b64e23d749620413a2ecdcc52ad4e6e63f2b817ce99c15b5d2da3792721d7158297cce65e0c04fe810d7e2434b969e4c7892b3840623e153576356e9a696fd9e7a801c25de621a7849da3f99158d3d09bf039f43c510c8ffb00fa3e9a3c12d2c8062dd25b8dabe53d8581e30427e81c3dfc2d455352487e1255", -+ "23a3fe80e3636313fdf922a1359514d9f31775e1adf24285e8001c04dbce866df055edf25b506e18953492a173ba5aa0c1ec758123406a97025ba9b6b7a97eb14734424d1a7841ec0eaeba0051d6e9734263bea1af9895a3b8c83d8c854da2ae7832bdd7c285b73f8113c3821cced38b3656b4e6369a9f8327cd368f04128f1d78b6b4260f55995277feffa15e34532cd0306c1f47354667c17018ee012a791af2dbbc7afc92c388008c601740cccbbe66f1eb06ea657e9d478066c2bd2093ab62cd94abadc002722f50968e8acf361658fc64f50685a5b1b004888b3b4f64a4ddb67bec7e4ac64c9ee8deeda896b9", -+ "758f3567cd992228386a1c01930f7c52a9dcce28fdc1aaa54b0fed97d9a54f1df805f31bac12d559e90a2063cd7df8311a148f6904f78c5440f75e49877c0c0855d59c7f7ee52837e6ef3e54a568a7b38a0d5b896e298c8e46a56d24d8cabda8aeff85a622a3e7c87483ba921f34156defd185f608e2241224286e38121a162c2ba7604f68484717196f6628861a948180e8f06c6cc1ec66d032cf8d16da039cd74277cde31e535bc1692a44046e16881c954af3cd91dc49b443a3680e4bc42a954a46ebd1368b1398edd7580f935514b15c7fbfa9b40048a35122283af731f5e460aa85b66e65f49a9d158699bd2870", -+ "fe511e86971cea2b6af91b2afa898d9b067fa71780790bb409189f5debe719f405e16acf7c4306a6e6ac5cd535290efe088943b9e6c5d25bfc508023c1b105d20d57252fee8cdbddb4d34a6ec2f72e8d55be55afcafd2e922ab8c31888bec4e816d04f0b2cd23df6e04720969c5152b3563c6da37e4608554cc7b8715bc10aba6a2e3b6fbcd35408df0dd73a9076bfad32b741fcdb0edfb563b3f753508b9b26f0a91673255f9bcda2b9a120f6bfa0632b6551ca517d846a747b66ebda1b2170891ece94c19ce8bf682cc94afdf0053fba4e4f0530935c07cdd6f879c999a8c4328ef6d3e0a37974a230ada83910604337", -+ "a6024f5b959698c0de45f4f29e1803f99dc8112989c536e5a1337e281bc856ff721e986de183d7b0ea9eb61166830ae5d6d6bc857dc833ff189b52889b8e2bd3f35b4937624d9b36dc5f19db44f0772508029784c7dac9568d28609058bc437e2f79f95b12307d8a8fb042d7fd6ee910a9e8df609ede3283f958ba918a9925a0b1d0f9f9f232062315f28a52cbd60e71c09d83e0f6600f508f0ae8ad7642c080ffc618fcd2314e26f67f1529342569f6df37017f7e3b2dac32ad88d56d175ab22205ee7e3ee94720d76933a21132e110fefbb0689a3adbaa4c685f43652136d09b3a359b5c671e38f11915cb5612db2ae294", -+ "af6de0e227bd78494acb559ddf34d8a7d55a03912384831be21c38376f39cda8a864aff7a48aed758f6bdf777779a669068a75ce82a06f6b3325c855ed83daf5513a078a61f7dc6c1622a633367e5f3a33e765c8ec5d8d54f48494006fdbf8922063e5340013e312871b7f8f8e5ea439c0d4cb78e2f19dd11f010729b692c65dd0d347f0ce53de9d849224666ea2f6487f1c6f953e8f9dbfd3d6de291c3e9d045e633cfd83c89d2f2327d0b2f31f72ac1604a3db1febc5f22cad08153278047210cc2894582c251a014c652e3951593e70e52a5d7451be8924b64f85c8247dab6268d24710b39fc1c07b4ac829fbda34ed79b5", -+ "d7314e8b1ff82100b8f5870da62b61c31ab37ace9e6a7b6f7d294571523783c1fdedcbc00dd487dd6f848c34aab493507d07071b5eb59d1a2346068c7f356755fbde3d2cab67514f8c3a12d6ff9f96a977a9ac9263491bd33122a904da5386b943d35a6ba383932df07f259b6b45f69e9b27b4ca124fb3ae143d709853eed86690bc2754d5f8865c355a44b5279d8eb31cdc00f7407fb5f5b34edc57fc7ace943565da2222dc80632ccf42f2f125ceb19714ea964c2e50603c9f8960c3f27c2ed0e18a559931c4352bd7422109a28c5e145003f55c9b7c664fdc985168868950396eaf6fefc7b73d815c1aca721d7c67da632925", -+ "2928b55c0e4d0f5cb4b60af59e9a702e3d616a8cf427c8bb03981fb8c29026d8f7d89161f36c11654f9a5e8ccb703595a58d671ecdc22c6a784abe363158682be4643002a7da5c9d268a30ea9a8d4cc24f562ab59f55c2b43af7dbcecc7e5ebe7494e82d74145a1e7d442125eb0431c5ea0939b27afa47f8ca97849f341f707660c7fbe49b7a0712fbcb6f7562ae2961425f27c7779c7534ecdeb8047ff3cb89a25159f3e1cefe42f9ef16426241f2c4d62c11d7ac43c4500dfcd184436bb4ef33260366f875230f26d81613c334dbda4736ba9d1d2966502914ec01bbe72d885606ec11da7a2cb01b29d35eebedbb0ecc73ed6c35", -+ "fd993f50e8a68c7b2c7f87511ce65b93c0aa94dcbdf2c9cca93816f0f3b2ab34c62c586fc507b4900a34cf9d0517e0fe10a89d154c5419c1f5e38de00e8834fe3dc1032abdeb10729a81655a69a12856a78ca6e12110580de879b086fd6608726541cfa9616326bdd36064bc0d1e5f9c93b41278bff6a13b2494b81e238c0c45aea1b07d855e8f3fe1478e373bd9d3957cf8a5e5b9003386793d994c7c575cff2322e2428cbbaa4f47560316ae3354a7478842ff7cc5dcbacb6e871e72b36f06d63a9aaeb9044cfb7974afdc238a5816f537dcf33ee40b4e1a5eb3cff2402b46d548264e133008d284f11b7e4e450bc3c5ff9f79b9c4", -+ "8df21892f5fc303b0de4adef1970186db6fe71bb3ea3094922e13afcfabf1d0be009f36d6f6310c5f9fda51f1a946507a055b645c296370440e5e83d8e906a2fb51f2b42de8856a81a4f28a73a8825c68ea08e5e366730bce8047011cb7d6d9be8c6f4211308fad21856284d5bc47d199988e0abf5badf8693ceeed0a2d98e8ae94b7775a42925edb1f697ffbd8e806af23145054a85e071819cca4cd48875290ca65e5ee72a9a54ff9f19c10ef4adaf8d04c9a9afcc73853fc128bbebc61f78702787c966ca6e1b1a0e4dab646acdfcd3c6bf3e5cfbec5ebe3e06c8abaa1de56e48421d87c46b5c78030afcafd91f27e7d7c85eb4872b", -+ "48ec6ec520f8e593d7b3f653eb15553de246723b81a6d0c3221aaa42a37420fba98a23796338dff5f845dce6d5a449be5ecc1887356619270461087e08d05fb60433a83d7bd00c002b09ea210b428965124b9b27d9105a71c826c1a2491cfd60e4cfa86c2da0c7100a8dc1c3f2f94b280d54e01e043acf0e966200d9fa8a41daf3b9382820786c75cadbb8841a1b2be5b6cbeb64878e4a231ae063a99b4e2308960ef0c8e2a16bb3545cc43bdf171493fb89a84f47e7973dc60cf75aeeca71e0a7ebe17d161d4fb9fe009941cc438f16a5bae6c99fcad08cac486eb2a48060b023d8730bf1d82fe60a2f036e6f52a5bff95f43bbe088933f", -+ "f4d84ed3e564c102600a795eaa9b1eaf4ad12f1a4deca1d042a0a2750ddf6201db03073d8bf553cb9dde48a1b0083827a609f7242b86584cc180964ae794b12ce55661e00e36a6ba4dbc389e6a5a85f1b45df9af7ead1b0a54db56e68639b9d438a91504e82c35d40c7bc7e048a53ac0b04accd0dadf4ac9884b0ca0e3cb5ba4336e3581be4c4760a553823ffa283a1120d4e145af56a59f2533903650f0b9e9ad9fe2e8a3c3c3dd03a1fcb709032c8835324839c735b0c051d0cbd8b5d867617c11023432e4bd275d3d0eb98a0b6cf58071a5b712922f2bc751ac7c2588c447444cde2f37a8ea5ec126425bf517e0d17c9e2999f52fee14b3", -+ "2ccea21bac9c2b70d3923309cbf2d7cb7abd1fcc8b8b002688870a80029c62397350c3c898194e5deea360bb963d26d485cb7963f8167586976ec0556950b2e86135f4a2800991ce8473bfd44a3c5e937a48b5e355ba5141bccf2131a83988d9d2a9e8e7635a956105b3512c05ef708139ced51d7a4e204c12d8a49a21e8dc6de2629a2fd092326885d9f218745fe09f6d91fb6afce250a30a63689534b6be1f26899ffa3767d835cf586aa47776700f94241bc999b1e3deefe188f37ff734f5f16ee6a00914323dc7b8a143c9137cdcc5cd08ae9566f04bb2941532674c97dff6ffa5ce3405ef8e5d27ec403114253dd6394c0167d72a0044c5", -+ "2b681c6398aee63bf862770341648bbcd31d7de7903c5903fe3d9469311320bb24d914f2af0cdca199c97214c7c679dc32a2800ba484a03c010ea6be3bb9f2c87e30a98b606050b8a3f297f12b8f92caaeceb3e844652115934874e0a1ab093a73d759b53f6a6c3096940dd22c2bb96ce6820a7b9c6d71a208de9892aa6a7209b0fff56a0cafea52b952cdd6f5752cff3309d448800b4e4c878aa595595b56b12b83fcd6ca89520c7da664e449d7b4438fc455888aad5de0fad9a06eed14afd3513b5ebbffe01775549b701181bd26370764f56eba52fdb24286ad1ac0f5418a7c429f7dfc7f3168437fa8eed7a2ed7c723a485e4c3ed14dea2e07", -+ "aadfd505a89f4aade2c3018258a7e039401b1fc6a7f3d87910dddbb880d372ec8a13c70d92245de5b8e5f9a285c33b99dc82fa2b22decee72b93a72211656ad7a52696c8e570f78be28c0e427a371dafde856e8d5ed24f83b0660b51e7fac05d93a8666dfde6def59af863f80f3e5f6801182c87422203df390dcb736b8f830052a8832eeeb0b4e27e732aaf793d166b5a3ec7745aeef3766937c2b75a276bddd145f6010c29d035e343e267cb2d828436876ec3a7ebe3b6347d4172f7a99d6821ce152e039e53deb33340b324c7f068ffb94b3cde35a8eaa12d15c3806a7ad0acec3e8c7078c1d32a28fd3eec9f32cb86e4c22166ff69e83785e851", -+ "1605b8cce529a9d6262fd4390d9e4ae5e14e0adc0ec89b028ef68dd0f373ea259aaa96f2967091dd0874c0105385e9e6da9ca68297c31afa44ef834535fb302ce5b4e49edacbbdf359fe1228a8172495b3e57014c27edd58b685110980056c50c398a64f4923f2d720b4df16d75cb36b4233660694182099c35028a972519c24764fc94e18e582b24deb3491535fc06b83837c7958522800e822201d694af0bd0aa3834e17d4b1ba36f470905ae5f8bbeeb6c4c8604d8af02baa347b07086d6989867ddd5e8e8ed7740c3469bfa2810519c55c6add1332c4c54ee9097961d6741cb12a09713a0d07645f784f42f5ad94b48b836b34263130b0483f15e3", -+ "ff9c6125b2f60bfd6c2427b279df070e430075096647599bdc68c531152c58e13858b82385d78c856092d6c74106e87ccf51ac7e673936332d9b223444eaa0e762ee258d8a733d3a515ec68ed73285e5ca183ae3278b4820b0ab2797feb1e7d8cc864df585dfb5ebe02a993325a9ad5e2d7d49d3132cf66013898351d044e0fe908ccdfeeebf651983601e3673a1f92d36510c0cc19b2e75856db8e4a41f92a51efa66d6cc22e414944c2c34a5a89ccde0be76f51410824e330d8e7c613194338c93732e8aea651fca18bcf1ac1824340c5553aff1e58d4ab8d7c8842b4712021e517cd6c140f6743c69c7bee05b10a8f24050a8caa4f96d1664909c5a06", -+ "6e85c2f8e1fdc3aaeb969da1258cb504bbf0070cd03d23b3fb5ee08feea5ee2e0ee1c71a5d0f4f701b351f4e4b4d74cb1e2ae6184814f77b62d2f08134b7236ebf6b67d8a6c9f01b4248b30667c555f5d8646dbfe291151b23c9c9857e33a4d5c847be29a5ee7b402e03bac02d1a4319acc0dd8f25e9c7a266f5e5c896cc11b5b238df96a0963ae806cb277abc515c298a3e61a3036b177acf87a56ca4478c4c6d0d468913de602ec891318bbaf52c97a77c35c5b7d164816cf24e4c4b0b5f45853882f716d61eb947a45ce2efa78f1c70a918512af1ad536cbe6148083385b34e207f5f690d7a954021e4b5f4258a385fd8a87809a481f34202af4caccb82", -+ "1e9b2c454e9de3a2d723d850331037dbf54133dbe27488ff757dd255833a27d8eb8a128ad12d0978b6884e25737086a704fb289aaaccf930d5b582ab4df1f55f0c429b6875edec3fe45464fa74164be056a55e243c4222c586bec5b18f39036aa903d98180f24f83d09a454dfa1e03a60e6a3ba4613e99c35f874d790174ee48a557f4f021ade4d1b278d7997ef094569b37b3db0505951e9ee8400adaea275c6db51b325ee730c69df97745b556ae41cd98741e28aa3a49544541eeb3da1b1e8fa4e8e9100d66dd0c7f5e2c271b1ecc077de79c462b9fe4c273543ecd82a5bea63c5acc01eca5fb780c7d7c8c9fe208ae8bd50cad1769693d92c6c8649d20d8", -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/blake2x.go b/ms_mod/golang.org/x/crypto/blake2b/blake2x.go -new file mode 100644 -index 00000000000000..52c414db0e64d7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/blake2x.go -@@ -0,0 +1,177 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2b -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "io" -+) -+ -+// XOF defines the interface to hash functions that -+// support arbitrary-length output. -+type XOF interface { -+ // Write absorbs more data into the hash's state. It panics if called -+ // after Read. -+ io.Writer -+ -+ // Read reads more output from the hash. It returns io.EOF if the limit -+ // has been reached. -+ io.Reader -+ -+ // Clone returns a copy of the XOF in its current state. -+ Clone() XOF -+ -+ // Reset resets the XOF to its initial state. -+ Reset() -+} -+ -+// OutputLengthUnknown can be used as the size argument to NewXOF to indicate -+// the length of the output is not known in advance. -+const OutputLengthUnknown = 0 -+ -+// magicUnknownOutputLength is a magic value for the output size that indicates -+// an unknown number of output bytes. -+const magicUnknownOutputLength = (1 << 32) - 1 -+ -+// maxOutputLength is the absolute maximum number of bytes to produce when the -+// number of output bytes is unknown. -+const maxOutputLength = (1 << 32) * 64 -+ -+// NewXOF creates a new variable-output-length hash. The hash either produce a -+// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes -+// (size == OutputLengthUnknown). In the latter case, an absolute limit of -+// 256GiB applies. -+// -+// A non-nil key turns the hash into a MAC. The key must between -+// zero and 32 bytes long. -+func NewXOF(size uint32, key []byte) (XOF, error) { -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ if size == magicUnknownOutputLength { -+ // 2^32-1 indicates an unknown number of bytes and thus isn't a -+ // valid length. -+ return nil, errors.New("blake2b: XOF length too large") -+ } -+ if size == OutputLengthUnknown { -+ size = magicUnknownOutputLength -+ } -+ x := &xof{ -+ d: digest{ -+ size: Size, -+ keyLen: len(key), -+ }, -+ length: size, -+ } -+ copy(x.d.key[:], key) -+ x.Reset() -+ return x, nil -+} -+ -+type xof struct { -+ d digest -+ length uint32 -+ remaining uint64 -+ cfg, root, block [Size]byte -+ offset int -+ nodeOffset uint32 -+ readMode bool -+} -+ -+func (x *xof) Write(p []byte) (n int, err error) { -+ if x.readMode { -+ panic("blake2b: write to XOF after read") -+ } -+ return x.d.Write(p) -+} -+ -+func (x *xof) Clone() XOF { -+ clone := *x -+ return &clone -+} -+ -+func (x *xof) Reset() { -+ x.cfg[0] = byte(Size) -+ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length -+ binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length -+ x.cfg[17] = byte(Size) // inner hash size -+ -+ x.d.Reset() -+ x.d.h[1] ^= uint64(x.length) << 32 -+ -+ x.remaining = uint64(x.length) -+ if x.remaining == magicUnknownOutputLength { -+ x.remaining = maxOutputLength -+ } -+ x.offset, x.nodeOffset = 0, 0 -+ x.readMode = false -+} -+ -+func (x *xof) Read(p []byte) (n int, err error) { -+ if !x.readMode { -+ x.d.finalize(&x.root) -+ x.readMode = true -+ } -+ -+ if x.remaining == 0 { -+ return 0, io.EOF -+ } -+ -+ n = len(p) -+ if uint64(n) > x.remaining { -+ n = int(x.remaining) -+ p = p[:n] -+ } -+ -+ if x.offset > 0 { -+ blockRemaining := Size - x.offset -+ if n < blockRemaining { -+ x.offset += copy(p, x.block[x.offset:]) -+ x.remaining -= uint64(n) -+ return -+ } -+ copy(p, x.block[x.offset:]) -+ p = p[blockRemaining:] -+ x.offset = 0 -+ x.remaining -= uint64(blockRemaining) -+ } -+ -+ for len(p) >= Size { -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ copy(p, x.block[:]) -+ p = p[Size:] -+ x.remaining -= uint64(Size) -+ } -+ -+ if todo := len(p); todo > 0 { -+ if x.remaining < uint64(Size) { -+ x.cfg[0] = byte(x.remaining) -+ } -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ x.offset = copy(p, x.block[:todo]) -+ x.remaining -= uint64(todo) -+ } -+ return -+} -+ -+func (d *digest) initConfig(cfg *[Size]byte) { -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ for i := range d.h { -+ d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2b/register.go b/ms_mod/golang.org/x/crypto/blake2b/register.go -new file mode 100644 -index 00000000000000..9d8633963cb6e1 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2b/register.go -@@ -0,0 +1,33 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.9 -+// +build go1.9 -+ -+package blake2b -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ newHash256 := func() hash.Hash { -+ h, _ := New256(nil) -+ return h -+ } -+ newHash384 := func() hash.Hash { -+ h, _ := New384(nil) -+ return h -+ } -+ -+ newHash512 := func() hash.Hash { -+ h, _ := New512(nil) -+ return h -+ } -+ -+ crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) -+ crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) -+ crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s.go -new file mode 100644 -index 00000000000000..e3f46aab3a1aff ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s.go -@@ -0,0 +1,246 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 -+// and the extendable output function (XOF) BLAKE2Xs. -+// -+// BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any -+// size between 1 and 32 bytes. -+// For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf -+// and for BLAKE2Xs see https://blake2.net/blake2x.pdf -+// -+// If you aren't sure which function you need, use BLAKE2s (Sum256 or New256). -+// If you need a secret-key MAC (message authentication code), use the New256 -+// function with a non-nil key. -+// -+// BLAKE2X is a construction to compute hash values larger than 32 bytes. It -+// can produce hash values between 0 and 65535 bytes. -+package blake2s // import "golang.org/x/crypto/blake2s" -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "hash" -+) -+ -+const ( -+ // The blocksize of BLAKE2s in bytes. -+ BlockSize = 64 -+ -+ // The hash size of BLAKE2s-256 in bytes. -+ Size = 32 -+ -+ // The hash size of BLAKE2s-128 in bytes. -+ Size128 = 16 -+) -+ -+var errKeySize = errors.New("blake2s: invalid key size") -+ -+var iv = [8]uint32{ -+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, -+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, -+} -+ -+// Sum256 returns the BLAKE2s-256 checksum of the data. -+func Sum256(data []byte) [Size]byte { -+ var sum [Size]byte -+ checkSum(&sum, Size, data) -+ return sum -+} -+ -+// New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil -+// key turns the hash into a MAC. The key must between zero and 32 bytes long. -+// When the key is nil, the returned hash.Hash implements BinaryMarshaler -+// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. -+func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } -+ -+// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a -+// non-empty key. Note that a 128-bit digest is too small to be secure as a -+// cryptographic hash and should only be used as a MAC, thus the key argument -+// is not optional. -+func New128(key []byte) (hash.Hash, error) { -+ if len(key) == 0 { -+ return nil, errors.New("blake2s: a key is required for a 128-bit hash") -+ } -+ return newDigest(Size128, key) -+} -+ -+func newDigest(hashSize int, key []byte) (*digest, error) { -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ d := &digest{ -+ size: hashSize, -+ keyLen: len(key), -+ } -+ copy(d.key[:], key) -+ d.Reset() -+ return d, nil -+} -+ -+func checkSum(sum *[Size]byte, hashSize int, data []byte) { -+ var ( -+ h [8]uint32 -+ c [2]uint32 -+ ) -+ -+ h = iv -+ h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24) -+ -+ if length := len(data); length > BlockSize { -+ n := length &^ (BlockSize - 1) -+ if length == n { -+ n -= BlockSize -+ } -+ hashBlocks(&h, &c, 0, data[:n]) -+ data = data[n:] -+ } -+ -+ var block [BlockSize]byte -+ offset := copy(block[:], data) -+ remaining := uint32(BlockSize - offset) -+ -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) -+ -+ for i, v := range h { -+ binary.LittleEndian.PutUint32(sum[4*i:], v) -+ } -+} -+ -+type digest struct { -+ h [8]uint32 -+ c [2]uint32 -+ size int -+ block [BlockSize]byte -+ offset int -+ -+ key [BlockSize]byte -+ keyLen int -+} -+ -+const ( -+ magic = "b2s" -+ marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1 -+) -+ -+func (d *digest) MarshalBinary() ([]byte, error) { -+ if d.keyLen != 0 { -+ return nil, errors.New("crypto/blake2s: cannot marshal MACs") -+ } -+ b := make([]byte, 0, marshaledSize) -+ b = append(b, magic...) -+ for i := 0; i < 8; i++ { -+ b = appendUint32(b, d.h[i]) -+ } -+ b = appendUint32(b, d.c[0]) -+ b = appendUint32(b, d.c[1]) -+ // Maximum value for size is 32 -+ b = append(b, byte(d.size)) -+ b = append(b, d.block[:]...) -+ b = append(b, byte(d.offset)) -+ return b, nil -+} -+ -+func (d *digest) UnmarshalBinary(b []byte) error { -+ if len(b) < len(magic) || string(b[:len(magic)]) != magic { -+ return errors.New("crypto/blake2s: invalid hash state identifier") -+ } -+ if len(b) != marshaledSize { -+ return errors.New("crypto/blake2s: invalid hash state size") -+ } -+ b = b[len(magic):] -+ for i := 0; i < 8; i++ { -+ b, d.h[i] = consumeUint32(b) -+ } -+ b, d.c[0] = consumeUint32(b) -+ b, d.c[1] = consumeUint32(b) -+ d.size = int(b[0]) -+ b = b[1:] -+ copy(d.block[:], b[:BlockSize]) -+ b = b[BlockSize:] -+ d.offset = int(b[0]) -+ return nil -+} -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Size() int { return d.size } -+ -+func (d *digest) Reset() { -+ d.h = iv -+ d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24) -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ if d.keyLen > 0 { -+ d.block = d.key -+ d.offset = BlockSize -+ } -+} -+ -+func (d *digest) Write(p []byte) (n int, err error) { -+ n = len(p) -+ -+ if d.offset > 0 { -+ remaining := BlockSize - d.offset -+ if n <= remaining { -+ d.offset += copy(d.block[d.offset:], p) -+ return -+ } -+ copy(d.block[d.offset:], p[:remaining]) -+ hashBlocks(&d.h, &d.c, 0, d.block[:]) -+ d.offset = 0 -+ p = p[remaining:] -+ } -+ -+ if length := len(p); length > BlockSize { -+ nn := length &^ (BlockSize - 1) -+ if length == nn { -+ nn -= BlockSize -+ } -+ hashBlocks(&d.h, &d.c, 0, p[:nn]) -+ p = p[nn:] -+ } -+ -+ d.offset += copy(d.block[:], p) -+ return -+} -+ -+func (d *digest) Sum(sum []byte) []byte { -+ var hash [Size]byte -+ d.finalize(&hash) -+ return append(sum, hash[:d.size]...) -+} -+ -+func (d *digest) finalize(hash *[Size]byte) { -+ var block [BlockSize]byte -+ h := d.h -+ c := d.c -+ -+ copy(block[:], d.block[:d.offset]) -+ remaining := uint32(BlockSize - d.offset) -+ if c[0] < remaining { -+ c[1]-- -+ } -+ c[0] -= remaining -+ -+ hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) -+ for i, v := range h { -+ binary.LittleEndian.PutUint32(hash[4*i:], v) -+ } -+} -+ -+func appendUint32(b []byte, x uint32) []byte { -+ var a [4]byte -+ binary.BigEndian.PutUint32(a[:], x) -+ return append(b, a[:]...) -+} -+ -+func consumeUint32(b []byte) ([]byte, uint32) { -+ x := binary.BigEndian.Uint32(b) -+ return b[4:], x -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go -new file mode 100644 -index 00000000000000..b4463fb4dc0e2f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.go -@@ -0,0 +1,33 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build 386 && gc && !purego -+// +build 386,gc,!purego -+ -+package blake2s -+ -+import "golang.org/x/sys/cpu" -+ -+var ( -+ useSSE4 = false -+ useSSSE3 = cpu.X86.HasSSSE3 -+ useSSE2 = cpu.X86.HasSSE2 -+) -+ -+//go:noescape -+func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ switch { -+ case useSSSE3: -+ hashBlocksSSSE3(h, c, flag, blocks) -+ case useSSE2: -+ hashBlocksSSE2(h, c, flag, blocks) -+ default: -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s -new file mode 100644 -index 00000000000000..603d00ca3201dc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_386.s -@@ -0,0 +1,430 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build 386 && gc && !purego -+// +build 386,gc,!purego -+ -+#include "textflag.h" -+ -+DATA iv0<>+0x00(SB)/4, $0x6a09e667 -+DATA iv0<>+0x04(SB)/4, $0xbb67ae85 -+DATA iv0<>+0x08(SB)/4, $0x3c6ef372 -+DATA iv0<>+0x0c(SB)/4, $0xa54ff53a -+GLOBL iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA iv1<>+0x00(SB)/4, $0x510e527f -+DATA iv1<>+0x04(SB)/4, $0x9b05688c -+DATA iv1<>+0x08(SB)/4, $0x1f83d9ab -+DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 -+GLOBL iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol16<>+0x00(SB)/8, $0x0504070601000302 -+DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -+GLOBL rol16<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol8<>+0x00(SB)/8, $0x0407060500030201 -+DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 -+GLOBL rol8<>(SB), (NOPTR+RODATA), $16 -+ -+DATA counter<>+0x00(SB)/8, $0x40 -+DATA counter<>+0x08(SB)/8, $0x0 -+GLOBL counter<>(SB), (NOPTR+RODATA), $16 -+ -+#define ROTL_SSE2(n, t, v) \ -+ MOVO v, t; \ -+ PSLLL $n, t; \ -+ PSRLL $(32-n), v; \ -+ PXOR t, v -+ -+#define ROTL_SSSE3(c, v) \ -+ PSHUFB c, v -+ -+#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+#define PRECOMPUTE(dst, off, src, t) \ -+ MOVL 0*4(src), t; \ -+ MOVL t, 0*4+off+0(dst); \ -+ MOVL t, 9*4+off+64(dst); \ -+ MOVL t, 5*4+off+128(dst); \ -+ MOVL t, 14*4+off+192(dst); \ -+ MOVL t, 4*4+off+256(dst); \ -+ MOVL t, 2*4+off+320(dst); \ -+ MOVL t, 8*4+off+384(dst); \ -+ MOVL t, 12*4+off+448(dst); \ -+ MOVL t, 3*4+off+512(dst); \ -+ MOVL t, 15*4+off+576(dst); \ -+ MOVL 1*4(src), t; \ -+ MOVL t, 4*4+off+0(dst); \ -+ MOVL t, 8*4+off+64(dst); \ -+ MOVL t, 14*4+off+128(dst); \ -+ MOVL t, 5*4+off+192(dst); \ -+ MOVL t, 12*4+off+256(dst); \ -+ MOVL t, 11*4+off+320(dst); \ -+ MOVL t, 1*4+off+384(dst); \ -+ MOVL t, 6*4+off+448(dst); \ -+ MOVL t, 10*4+off+512(dst); \ -+ MOVL t, 3*4+off+576(dst); \ -+ MOVL 2*4(src), t; \ -+ MOVL t, 1*4+off+0(dst); \ -+ MOVL t, 13*4+off+64(dst); \ -+ MOVL t, 6*4+off+128(dst); \ -+ MOVL t, 8*4+off+192(dst); \ -+ MOVL t, 2*4+off+256(dst); \ -+ MOVL t, 0*4+off+320(dst); \ -+ MOVL t, 14*4+off+384(dst); \ -+ MOVL t, 11*4+off+448(dst); \ -+ MOVL t, 12*4+off+512(dst); \ -+ MOVL t, 4*4+off+576(dst); \ -+ MOVL 3*4(src), t; \ -+ MOVL t, 5*4+off+0(dst); \ -+ MOVL t, 15*4+off+64(dst); \ -+ MOVL t, 9*4+off+128(dst); \ -+ MOVL t, 1*4+off+192(dst); \ -+ MOVL t, 11*4+off+256(dst); \ -+ MOVL t, 7*4+off+320(dst); \ -+ MOVL t, 13*4+off+384(dst); \ -+ MOVL t, 3*4+off+448(dst); \ -+ MOVL t, 6*4+off+512(dst); \ -+ MOVL t, 10*4+off+576(dst); \ -+ MOVL 4*4(src), t; \ -+ MOVL t, 2*4+off+0(dst); \ -+ MOVL t, 1*4+off+64(dst); \ -+ MOVL t, 15*4+off+128(dst); \ -+ MOVL t, 10*4+off+192(dst); \ -+ MOVL t, 6*4+off+256(dst); \ -+ MOVL t, 8*4+off+320(dst); \ -+ MOVL t, 3*4+off+384(dst); \ -+ MOVL t, 13*4+off+448(dst); \ -+ MOVL t, 14*4+off+512(dst); \ -+ MOVL t, 5*4+off+576(dst); \ -+ MOVL 5*4(src), t; \ -+ MOVL t, 6*4+off+0(dst); \ -+ MOVL t, 11*4+off+64(dst); \ -+ MOVL t, 2*4+off+128(dst); \ -+ MOVL t, 9*4+off+192(dst); \ -+ MOVL t, 1*4+off+256(dst); \ -+ MOVL t, 13*4+off+320(dst); \ -+ MOVL t, 4*4+off+384(dst); \ -+ MOVL t, 8*4+off+448(dst); \ -+ MOVL t, 15*4+off+512(dst); \ -+ MOVL t, 7*4+off+576(dst); \ -+ MOVL 6*4(src), t; \ -+ MOVL t, 3*4+off+0(dst); \ -+ MOVL t, 7*4+off+64(dst); \ -+ MOVL t, 13*4+off+128(dst); \ -+ MOVL t, 12*4+off+192(dst); \ -+ MOVL t, 10*4+off+256(dst); \ -+ MOVL t, 1*4+off+320(dst); \ -+ MOVL t, 9*4+off+384(dst); \ -+ MOVL t, 14*4+off+448(dst); \ -+ MOVL t, 0*4+off+512(dst); \ -+ MOVL t, 6*4+off+576(dst); \ -+ MOVL 7*4(src), t; \ -+ MOVL t, 7*4+off+0(dst); \ -+ MOVL t, 14*4+off+64(dst); \ -+ MOVL t, 10*4+off+128(dst); \ -+ MOVL t, 0*4+off+192(dst); \ -+ MOVL t, 5*4+off+256(dst); \ -+ MOVL t, 9*4+off+320(dst); \ -+ MOVL t, 12*4+off+384(dst); \ -+ MOVL t, 1*4+off+448(dst); \ -+ MOVL t, 13*4+off+512(dst); \ -+ MOVL t, 2*4+off+576(dst); \ -+ MOVL 8*4(src), t; \ -+ MOVL t, 8*4+off+0(dst); \ -+ MOVL t, 5*4+off+64(dst); \ -+ MOVL t, 4*4+off+128(dst); \ -+ MOVL t, 15*4+off+192(dst); \ -+ MOVL t, 14*4+off+256(dst); \ -+ MOVL t, 3*4+off+320(dst); \ -+ MOVL t, 11*4+off+384(dst); \ -+ MOVL t, 10*4+off+448(dst); \ -+ MOVL t, 7*4+off+512(dst); \ -+ MOVL t, 1*4+off+576(dst); \ -+ MOVL 9*4(src), t; \ -+ MOVL t, 12*4+off+0(dst); \ -+ MOVL t, 2*4+off+64(dst); \ -+ MOVL t, 11*4+off+128(dst); \ -+ MOVL t, 4*4+off+192(dst); \ -+ MOVL t, 0*4+off+256(dst); \ -+ MOVL t, 15*4+off+320(dst); \ -+ MOVL t, 10*4+off+384(dst); \ -+ MOVL t, 7*4+off+448(dst); \ -+ MOVL t, 5*4+off+512(dst); \ -+ MOVL t, 9*4+off+576(dst); \ -+ MOVL 10*4(src), t; \ -+ MOVL t, 9*4+off+0(dst); \ -+ MOVL t, 4*4+off+64(dst); \ -+ MOVL t, 8*4+off+128(dst); \ -+ MOVL t, 13*4+off+192(dst); \ -+ MOVL t, 3*4+off+256(dst); \ -+ MOVL t, 5*4+off+320(dst); \ -+ MOVL t, 7*4+off+384(dst); \ -+ MOVL t, 15*4+off+448(dst); \ -+ MOVL t, 11*4+off+512(dst); \ -+ MOVL t, 0*4+off+576(dst); \ -+ MOVL 11*4(src), t; \ -+ MOVL t, 13*4+off+0(dst); \ -+ MOVL t, 10*4+off+64(dst); \ -+ MOVL t, 0*4+off+128(dst); \ -+ MOVL t, 3*4+off+192(dst); \ -+ MOVL t, 9*4+off+256(dst); \ -+ MOVL t, 6*4+off+320(dst); \ -+ MOVL t, 15*4+off+384(dst); \ -+ MOVL t, 4*4+off+448(dst); \ -+ MOVL t, 2*4+off+512(dst); \ -+ MOVL t, 12*4+off+576(dst); \ -+ MOVL 12*4(src), t; \ -+ MOVL t, 10*4+off+0(dst); \ -+ MOVL t, 12*4+off+64(dst); \ -+ MOVL t, 1*4+off+128(dst); \ -+ MOVL t, 6*4+off+192(dst); \ -+ MOVL t, 13*4+off+256(dst); \ -+ MOVL t, 4*4+off+320(dst); \ -+ MOVL t, 0*4+off+384(dst); \ -+ MOVL t, 2*4+off+448(dst); \ -+ MOVL t, 8*4+off+512(dst); \ -+ MOVL t, 14*4+off+576(dst); \ -+ MOVL 13*4(src), t; \ -+ MOVL t, 14*4+off+0(dst); \ -+ MOVL t, 3*4+off+64(dst); \ -+ MOVL t, 7*4+off+128(dst); \ -+ MOVL t, 2*4+off+192(dst); \ -+ MOVL t, 15*4+off+256(dst); \ -+ MOVL t, 12*4+off+320(dst); \ -+ MOVL t, 6*4+off+384(dst); \ -+ MOVL t, 0*4+off+448(dst); \ -+ MOVL t, 9*4+off+512(dst); \ -+ MOVL t, 11*4+off+576(dst); \ -+ MOVL 14*4(src), t; \ -+ MOVL t, 11*4+off+0(dst); \ -+ MOVL t, 0*4+off+64(dst); \ -+ MOVL t, 12*4+off+128(dst); \ -+ MOVL t, 7*4+off+192(dst); \ -+ MOVL t, 8*4+off+256(dst); \ -+ MOVL t, 14*4+off+320(dst); \ -+ MOVL t, 2*4+off+384(dst); \ -+ MOVL t, 5*4+off+448(dst); \ -+ MOVL t, 1*4+off+512(dst); \ -+ MOVL t, 13*4+off+576(dst); \ -+ MOVL 15*4(src), t; \ -+ MOVL t, 15*4+off+0(dst); \ -+ MOVL t, 6*4+off+64(dst); \ -+ MOVL t, 3*4+off+128(dst); \ -+ MOVL t, 11*4+off+192(dst); \ -+ MOVL t, 7*4+off+256(dst); \ -+ MOVL t, 10*4+off+320(dst); \ -+ MOVL t, 5*4+off+384(dst); \ -+ MOVL t, 9*4+off+448(dst); \ -+ MOVL t, 4*4+off+512(dst); \ -+ MOVL t, 8*4+off+576(dst) -+ -+// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT Β·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment -+ MOVL h+0(FP), AX -+ MOVL c+4(FP), BX -+ MOVL flag+8(FP), CX -+ MOVL blocks_base+12(FP), SI -+ MOVL blocks_len+16(FP), DX -+ -+ MOVL SP, DI -+ ADDL $15, DI -+ ANDL $~15, DI -+ -+ MOVL CX, 8(DI) -+ MOVL 0(BX), CX -+ MOVL CX, 0(DI) -+ MOVL 4(BX), CX -+ MOVL CX, 4(DI) -+ XORL CX, CX -+ MOVL CX, 12(DI) -+ -+ MOVOU 0(AX), X0 -+ MOVOU 16(AX), X1 -+ MOVOU counter<>(SB), X2 -+ -+loop: -+ MOVO X0, X4 -+ MOVO X1, X5 -+ MOVOU iv0<>(SB), X6 -+ MOVOU iv1<>(SB), X7 -+ -+ MOVO 0(DI), X3 -+ PADDQ X2, X3 -+ PXOR X3, X7 -+ MOVO X3, 0(DI) -+ -+ PRECOMPUTE(DI, 16, SI, CX) -+ ROUND_SSE2(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3) -+ ROUND_SSE2(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3) -+ -+ PXOR X4, X0 -+ PXOR X5, X1 -+ PXOR X6, X0 -+ PXOR X7, X1 -+ -+ LEAL 64(SI), SI -+ SUBL $64, DX -+ JNE loop -+ -+ MOVL 0(DI), CX -+ MOVL CX, 0(BX) -+ MOVL 4(DI), CX -+ MOVL CX, 4(BX) -+ -+ MOVOU X0, 0(AX) -+ MOVOU X1, 16(AX) -+ -+ RET -+ -+// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT Β·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment -+ MOVL h+0(FP), AX -+ MOVL c+4(FP), BX -+ MOVL flag+8(FP), CX -+ MOVL blocks_base+12(FP), SI -+ MOVL blocks_len+16(FP), DX -+ -+ MOVL SP, DI -+ ADDL $15, DI -+ ANDL $~15, DI -+ -+ MOVL CX, 8(DI) -+ MOVL 0(BX), CX -+ MOVL CX, 0(DI) -+ MOVL 4(BX), CX -+ MOVL CX, 4(DI) -+ XORL CX, CX -+ MOVL CX, 12(DI) -+ -+ MOVOU 0(AX), X0 -+ MOVOU 16(AX), X1 -+ MOVOU counter<>(SB), X2 -+ -+loop: -+ MOVO X0, 656(DI) -+ MOVO X1, 672(DI) -+ MOVO X0, X4 -+ MOVO X1, X5 -+ MOVOU iv0<>(SB), X6 -+ MOVOU iv1<>(SB), X7 -+ -+ MOVO 0(DI), X3 -+ PADDQ X2, X3 -+ PXOR X3, X7 -+ MOVO X3, 0(DI) -+ -+ MOVOU rol16<>(SB), X0 -+ MOVOU rol8<>(SB), X1 -+ -+ PRECOMPUTE(DI, 16, SI, CX) -+ ROUND_SSSE3(X4, X5, X6, X7, 16(DI), 32(DI), 48(DI), 64(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+64(DI), 32+64(DI), 48+64(DI), 64+64(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+128(DI), 32+128(DI), 48+128(DI), 64+128(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+192(DI), 32+192(DI), 48+192(DI), 64+192(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+256(DI), 32+256(DI), 48+256(DI), 64+256(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+320(DI), 32+320(DI), 48+320(DI), 64+320(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+384(DI), 32+384(DI), 48+384(DI), 64+384(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+448(DI), 32+448(DI), 48+448(DI), 64+448(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+512(DI), 32+512(DI), 48+512(DI), 64+512(DI), X3, X0, X1) -+ ROUND_SSSE3(X4, X5, X6, X7, 16+576(DI), 32+576(DI), 48+576(DI), 64+576(DI), X3, X0, X1) -+ -+ MOVO 656(DI), X0 -+ MOVO 672(DI), X1 -+ PXOR X4, X0 -+ PXOR X5, X1 -+ PXOR X6, X0 -+ PXOR X7, X1 -+ -+ LEAL 64(SI), SI -+ SUBL $64, DX -+ JNE loop -+ -+ MOVL 0(DI), CX -+ MOVL CX, 0(BX) -+ MOVL 4(DI), CX -+ MOVL CX, 4(BX) -+ -+ MOVOU X0, 0(AX) -+ MOVOU X1, 16(AX) -+ -+ RET -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go -new file mode 100644 -index 00000000000000..becdaa120ff8db ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.go -@@ -0,0 +1,38 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+package blake2s -+ -+import "golang.org/x/sys/cpu" -+ -+var ( -+ useSSE4 = cpu.X86.HasSSE41 -+ useSSSE3 = cpu.X86.HasSSSE3 -+ useSSE2 = cpu.X86.HasSSE2 -+) -+ -+//go:noescape -+func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+//go:noescape -+func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+ -+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ switch { -+ case useSSE4: -+ hashBlocksSSE4(h, c, flag, blocks) -+ case useSSSE3: -+ hashBlocksSSSE3(h, c, flag, blocks) -+ case useSSE2: -+ hashBlocksSSE2(h, c, flag, blocks) -+ default: -+ hashBlocksGeneric(h, c, flag, blocks) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s -new file mode 100644 -index 00000000000000..e9df7a7c2199e8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_amd64.s -@@ -0,0 +1,433 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+DATA iv0<>+0x00(SB)/4, $0x6a09e667 -+DATA iv0<>+0x04(SB)/4, $0xbb67ae85 -+DATA iv0<>+0x08(SB)/4, $0x3c6ef372 -+DATA iv0<>+0x0c(SB)/4, $0xa54ff53a -+GLOBL iv0<>(SB), (NOPTR+RODATA), $16 -+ -+DATA iv1<>+0x00(SB)/4, $0x510e527f -+DATA iv1<>+0x04(SB)/4, $0x9b05688c -+DATA iv1<>+0x08(SB)/4, $0x1f83d9ab -+DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 -+GLOBL iv1<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol16<>+0x00(SB)/8, $0x0504070601000302 -+DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -+GLOBL rol16<>(SB), (NOPTR+RODATA), $16 -+ -+DATA rol8<>+0x00(SB)/8, $0x0407060500030201 -+DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 -+GLOBL rol8<>(SB), (NOPTR+RODATA), $16 -+ -+DATA counter<>+0x00(SB)/8, $0x40 -+DATA counter<>+0x08(SB)/8, $0x0 -+GLOBL counter<>(SB), (NOPTR+RODATA), $16 -+ -+#define ROTL_SSE2(n, t, v) \ -+ MOVO v, t; \ -+ PSLLL $n, t; \ -+ PSRLL $(32-n), v; \ -+ PXOR t, v -+ -+#define ROTL_SSSE3(c, v) \ -+ PSHUFB c, v -+ -+#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(16, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSE2(24, t, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ -+ PADDL m0, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m1, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v1, v1; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v3, v3; \ -+ PADDL m2, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c16, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(20, t, v1); \ -+ PADDL m3, v0; \ -+ PADDL v1, v0; \ -+ PXOR v0, v3; \ -+ ROTL_SSSE3(c8, v3); \ -+ PADDL v3, v2; \ -+ PXOR v2, v1; \ -+ ROTL_SSE2(25, t, v1); \ -+ PSHUFL $0x39, v3, v3; \ -+ PSHUFL $0x4E, v2, v2; \ -+ PSHUFL $0x93, v1, v1 -+ -+ -+#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \ -+ MOVL i0*4(src), m0; \ -+ PINSRD $1, i1*4(src), m0; \ -+ PINSRD $2, i2*4(src), m0; \ -+ PINSRD $3, i3*4(src), m0; \ -+ MOVL i4*4(src), m1; \ -+ PINSRD $1, i5*4(src), m1; \ -+ PINSRD $2, i6*4(src), m1; \ -+ PINSRD $3, i7*4(src), m1; \ -+ MOVL i8*4(src), m2; \ -+ PINSRD $1, i9*4(src), m2; \ -+ PINSRD $2, i10*4(src), m2; \ -+ PINSRD $3, i11*4(src), m2; \ -+ MOVL i12*4(src), m3; \ -+ PINSRD $1, i13*4(src), m3; \ -+ PINSRD $2, i14*4(src), m3; \ -+ PINSRD $3, i15*4(src), m3 -+ -+#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \ -+ MOVQ 0*4(src), R8; \ -+ MOVQ 2*4(src), R9; \ -+ MOVQ 4*4(src), R10; \ -+ MOVQ 6*4(src), R11; \ -+ MOVQ 8*4(src), R12; \ -+ MOVQ 10*4(src), R13; \ -+ MOVQ 12*4(src), R14; \ -+ MOVQ 14*4(src), R15; \ -+ \ -+ MOVL R8, 0*4+off+0(dst); \ -+ MOVL R8, 9*4+off+64(dst); \ -+ MOVL R8, 5*4+off+128(dst); \ -+ MOVL R8, 14*4+off+192(dst); \ -+ MOVL R8, 4*4+off+256(dst); \ -+ MOVL R8, 2*4+off+320(dst); \ -+ MOVL R8, 8*4+off+384(dst); \ -+ MOVL R8, 12*4+off+448(dst); \ -+ MOVL R8, 3*4+off+512(dst); \ -+ MOVL R8, 15*4+off+576(dst); \ -+ SHRQ $32, R8; \ -+ MOVL R8, 4*4+off+0(dst); \ -+ MOVL R8, 8*4+off+64(dst); \ -+ MOVL R8, 14*4+off+128(dst); \ -+ MOVL R8, 5*4+off+192(dst); \ -+ MOVL R8, 12*4+off+256(dst); \ -+ MOVL R8, 11*4+off+320(dst); \ -+ MOVL R8, 1*4+off+384(dst); \ -+ MOVL R8, 6*4+off+448(dst); \ -+ MOVL R8, 10*4+off+512(dst); \ -+ MOVL R8, 3*4+off+576(dst); \ -+ \ -+ MOVL R9, 1*4+off+0(dst); \ -+ MOVL R9, 13*4+off+64(dst); \ -+ MOVL R9, 6*4+off+128(dst); \ -+ MOVL R9, 8*4+off+192(dst); \ -+ MOVL R9, 2*4+off+256(dst); \ -+ MOVL R9, 0*4+off+320(dst); \ -+ MOVL R9, 14*4+off+384(dst); \ -+ MOVL R9, 11*4+off+448(dst); \ -+ MOVL R9, 12*4+off+512(dst); \ -+ MOVL R9, 4*4+off+576(dst); \ -+ SHRQ $32, R9; \ -+ MOVL R9, 5*4+off+0(dst); \ -+ MOVL R9, 15*4+off+64(dst); \ -+ MOVL R9, 9*4+off+128(dst); \ -+ MOVL R9, 1*4+off+192(dst); \ -+ MOVL R9, 11*4+off+256(dst); \ -+ MOVL R9, 7*4+off+320(dst); \ -+ MOVL R9, 13*4+off+384(dst); \ -+ MOVL R9, 3*4+off+448(dst); \ -+ MOVL R9, 6*4+off+512(dst); \ -+ MOVL R9, 10*4+off+576(dst); \ -+ \ -+ MOVL R10, 2*4+off+0(dst); \ -+ MOVL R10, 1*4+off+64(dst); \ -+ MOVL R10, 15*4+off+128(dst); \ -+ MOVL R10, 10*4+off+192(dst); \ -+ MOVL R10, 6*4+off+256(dst); \ -+ MOVL R10, 8*4+off+320(dst); \ -+ MOVL R10, 3*4+off+384(dst); \ -+ MOVL R10, 13*4+off+448(dst); \ -+ MOVL R10, 14*4+off+512(dst); \ -+ MOVL R10, 5*4+off+576(dst); \ -+ SHRQ $32, R10; \ -+ MOVL R10, 6*4+off+0(dst); \ -+ MOVL R10, 11*4+off+64(dst); \ -+ MOVL R10, 2*4+off+128(dst); \ -+ MOVL R10, 9*4+off+192(dst); \ -+ MOVL R10, 1*4+off+256(dst); \ -+ MOVL R10, 13*4+off+320(dst); \ -+ MOVL R10, 4*4+off+384(dst); \ -+ MOVL R10, 8*4+off+448(dst); \ -+ MOVL R10, 15*4+off+512(dst); \ -+ MOVL R10, 7*4+off+576(dst); \ -+ \ -+ MOVL R11, 3*4+off+0(dst); \ -+ MOVL R11, 7*4+off+64(dst); \ -+ MOVL R11, 13*4+off+128(dst); \ -+ MOVL R11, 12*4+off+192(dst); \ -+ MOVL R11, 10*4+off+256(dst); \ -+ MOVL R11, 1*4+off+320(dst); \ -+ MOVL R11, 9*4+off+384(dst); \ -+ MOVL R11, 14*4+off+448(dst); \ -+ MOVL R11, 0*4+off+512(dst); \ -+ MOVL R11, 6*4+off+576(dst); \ -+ SHRQ $32, R11; \ -+ MOVL R11, 7*4+off+0(dst); \ -+ MOVL R11, 14*4+off+64(dst); \ -+ MOVL R11, 10*4+off+128(dst); \ -+ MOVL R11, 0*4+off+192(dst); \ -+ MOVL R11, 5*4+off+256(dst); \ -+ MOVL R11, 9*4+off+320(dst); \ -+ MOVL R11, 12*4+off+384(dst); \ -+ MOVL R11, 1*4+off+448(dst); \ -+ MOVL R11, 13*4+off+512(dst); \ -+ MOVL R11, 2*4+off+576(dst); \ -+ \ -+ MOVL R12, 8*4+off+0(dst); \ -+ MOVL R12, 5*4+off+64(dst); \ -+ MOVL R12, 4*4+off+128(dst); \ -+ MOVL R12, 15*4+off+192(dst); \ -+ MOVL R12, 14*4+off+256(dst); \ -+ MOVL R12, 3*4+off+320(dst); \ -+ MOVL R12, 11*4+off+384(dst); \ -+ MOVL R12, 10*4+off+448(dst); \ -+ MOVL R12, 7*4+off+512(dst); \ -+ MOVL R12, 1*4+off+576(dst); \ -+ SHRQ $32, R12; \ -+ MOVL R12, 12*4+off+0(dst); \ -+ MOVL R12, 2*4+off+64(dst); \ -+ MOVL R12, 11*4+off+128(dst); \ -+ MOVL R12, 4*4+off+192(dst); \ -+ MOVL R12, 0*4+off+256(dst); \ -+ MOVL R12, 15*4+off+320(dst); \ -+ MOVL R12, 10*4+off+384(dst); \ -+ MOVL R12, 7*4+off+448(dst); \ -+ MOVL R12, 5*4+off+512(dst); \ -+ MOVL R12, 9*4+off+576(dst); \ -+ \ -+ MOVL R13, 9*4+off+0(dst); \ -+ MOVL R13, 4*4+off+64(dst); \ -+ MOVL R13, 8*4+off+128(dst); \ -+ MOVL R13, 13*4+off+192(dst); \ -+ MOVL R13, 3*4+off+256(dst); \ -+ MOVL R13, 5*4+off+320(dst); \ -+ MOVL R13, 7*4+off+384(dst); \ -+ MOVL R13, 15*4+off+448(dst); \ -+ MOVL R13, 11*4+off+512(dst); \ -+ MOVL R13, 0*4+off+576(dst); \ -+ SHRQ $32, R13; \ -+ MOVL R13, 13*4+off+0(dst); \ -+ MOVL R13, 10*4+off+64(dst); \ -+ MOVL R13, 0*4+off+128(dst); \ -+ MOVL R13, 3*4+off+192(dst); \ -+ MOVL R13, 9*4+off+256(dst); \ -+ MOVL R13, 6*4+off+320(dst); \ -+ MOVL R13, 15*4+off+384(dst); \ -+ MOVL R13, 4*4+off+448(dst); \ -+ MOVL R13, 2*4+off+512(dst); \ -+ MOVL R13, 12*4+off+576(dst); \ -+ \ -+ MOVL R14, 10*4+off+0(dst); \ -+ MOVL R14, 12*4+off+64(dst); \ -+ MOVL R14, 1*4+off+128(dst); \ -+ MOVL R14, 6*4+off+192(dst); \ -+ MOVL R14, 13*4+off+256(dst); \ -+ MOVL R14, 4*4+off+320(dst); \ -+ MOVL R14, 0*4+off+384(dst); \ -+ MOVL R14, 2*4+off+448(dst); \ -+ MOVL R14, 8*4+off+512(dst); \ -+ MOVL R14, 14*4+off+576(dst); \ -+ SHRQ $32, R14; \ -+ MOVL R14, 14*4+off+0(dst); \ -+ MOVL R14, 3*4+off+64(dst); \ -+ MOVL R14, 7*4+off+128(dst); \ -+ MOVL R14, 2*4+off+192(dst); \ -+ MOVL R14, 15*4+off+256(dst); \ -+ MOVL R14, 12*4+off+320(dst); \ -+ MOVL R14, 6*4+off+384(dst); \ -+ MOVL R14, 0*4+off+448(dst); \ -+ MOVL R14, 9*4+off+512(dst); \ -+ MOVL R14, 11*4+off+576(dst); \ -+ \ -+ MOVL R15, 11*4+off+0(dst); \ -+ MOVL R15, 0*4+off+64(dst); \ -+ MOVL R15, 12*4+off+128(dst); \ -+ MOVL R15, 7*4+off+192(dst); \ -+ MOVL R15, 8*4+off+256(dst); \ -+ MOVL R15, 14*4+off+320(dst); \ -+ MOVL R15, 2*4+off+384(dst); \ -+ MOVL R15, 5*4+off+448(dst); \ -+ MOVL R15, 1*4+off+512(dst); \ -+ MOVL R15, 13*4+off+576(dst); \ -+ SHRQ $32, R15; \ -+ MOVL R15, 15*4+off+0(dst); \ -+ MOVL R15, 6*4+off+64(dst); \ -+ MOVL R15, 3*4+off+128(dst); \ -+ MOVL R15, 11*4+off+192(dst); \ -+ MOVL R15, 7*4+off+256(dst); \ -+ MOVL R15, 10*4+off+320(dst); \ -+ MOVL R15, 5*4+off+384(dst); \ -+ MOVL R15, 9*4+off+448(dst); \ -+ MOVL R15, 4*4+off+512(dst); \ -+ MOVL R15, 8*4+off+576(dst) -+ -+#define BLAKE2s_SSE2() \ -+ PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8); \ -+ ROUND_SSE2(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8) -+ -+#define BLAKE2s_SSSE3() \ -+ PRECOMPUTE_MSG(BP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16(BP), 32(BP), 48(BP), 64(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+64(BP), 32+64(BP), 48+64(BP), 64+64(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+128(BP), 32+128(BP), 48+128(BP), 64+128(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+192(BP), 32+192(BP), 48+192(BP), 64+192(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+256(BP), 32+256(BP), 48+256(BP), 64+256(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+320(BP), 32+320(BP), 48+320(BP), 64+320(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+384(BP), 32+384(BP), 48+384(BP), 64+384(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+448(BP), 32+448(BP), 48+448(BP), 64+448(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+512(BP), 32+512(BP), 48+512(BP), 64+512(BP), X8, X13, X14); \ -+ ROUND_SSSE3(X4, X5, X6, X7, 16+576(BP), 32+576(BP), 48+576(BP), 64+576(BP), X8, X13, X14) -+ -+#define BLAKE2s_SSE4() \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ -+ LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \ -+ ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) -+ -+#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \ -+ MOVQ h, AX; \ -+ MOVQ c, BX; \ -+ MOVL flag, CX; \ -+ MOVQ blocks_base, SI; \ -+ MOVQ blocks_len, DX; \ -+ \ -+ MOVQ SP, BP; \ -+ ADDQ $15, BP; \ -+ ANDQ $~15, BP; \ -+ \ -+ MOVQ 0(BX), R9; \ -+ MOVQ R9, 0(BP); \ -+ MOVQ CX, 8(BP); \ -+ \ -+ MOVOU 0(AX), X0; \ -+ MOVOU 16(AX), X1; \ -+ MOVOU iv0<>(SB), X2; \ -+ MOVOU iv1<>(SB), X3 \ -+ \ -+ MOVOU counter<>(SB), X12; \ -+ MOVOU rol16<>(SB), X13; \ -+ MOVOU rol8<>(SB), X14; \ -+ MOVO 0(BP), X15; \ -+ \ -+ loop: \ -+ MOVO X0, X4; \ -+ MOVO X1, X5; \ -+ MOVO X2, X6; \ -+ MOVO X3, X7; \ -+ \ -+ PADDQ X12, X15; \ -+ PXOR X15, X7; \ -+ \ -+ BLAKE2s_FUNC(); \ -+ \ -+ PXOR X4, X0; \ -+ PXOR X5, X1; \ -+ PXOR X6, X0; \ -+ PXOR X7, X1; \ -+ \ -+ LEAQ 64(SI), SI; \ -+ SUBQ $64, DX; \ -+ JNE loop; \ -+ \ -+ MOVO X15, 0(BP); \ -+ MOVQ 0(BP), R9; \ -+ MOVQ R9, 0(BX); \ -+ \ -+ MOVOU X0, 0(AX); \ -+ MOVOU X1, 16(AX) -+ -+// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT Β·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment -+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2) -+ RET -+ -+// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT Β·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment -+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3) -+ RET -+ -+// func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) -+TEXT Β·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment -+ HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) -+ RET -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go -new file mode 100644 -index 00000000000000..24a1ff22adcff0 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_generic.go -@@ -0,0 +1,178 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2s -+ -+import ( -+ "math/bits" -+) -+ -+// the precomputed values for BLAKE2s -+// there are 10 16-byte arrays - one for each round -+// the entries are calculated from the sigma constants. -+var precomputed = [10][16]byte{ -+ {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, -+ {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, -+ {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, -+ {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, -+ {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, -+ {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, -+ {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, -+ {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, -+ {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, -+ {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, -+} -+ -+func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ var m [16]uint32 -+ c0, c1 := c[0], c[1] -+ -+ for i := 0; i < len(blocks); { -+ c0 += BlockSize -+ if c0 < BlockSize { -+ c1++ -+ } -+ -+ v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] -+ v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] -+ v12 ^= c0 -+ v13 ^= c1 -+ v14 ^= flag -+ -+ for j := range m { -+ m[j] = uint32(blocks[i]) | uint32(blocks[i+1])<<8 | uint32(blocks[i+2])<<16 | uint32(blocks[i+3])<<24 -+ i += 4 -+ } -+ -+ for k := range precomputed { -+ s := &(precomputed[k]) -+ -+ v0 += m[s[0]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft32(v12, -16) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft32(v4, -12) -+ v1 += m[s[1]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft32(v13, -16) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft32(v5, -12) -+ v2 += m[s[2]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft32(v14, -16) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft32(v6, -12) -+ v3 += m[s[3]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft32(v15, -16) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft32(v7, -12) -+ -+ v0 += m[s[4]] -+ v0 += v4 -+ v12 ^= v0 -+ v12 = bits.RotateLeft32(v12, -8) -+ v8 += v12 -+ v4 ^= v8 -+ v4 = bits.RotateLeft32(v4, -7) -+ v1 += m[s[5]] -+ v1 += v5 -+ v13 ^= v1 -+ v13 = bits.RotateLeft32(v13, -8) -+ v9 += v13 -+ v5 ^= v9 -+ v5 = bits.RotateLeft32(v5, -7) -+ v2 += m[s[6]] -+ v2 += v6 -+ v14 ^= v2 -+ v14 = bits.RotateLeft32(v14, -8) -+ v10 += v14 -+ v6 ^= v10 -+ v6 = bits.RotateLeft32(v6, -7) -+ v3 += m[s[7]] -+ v3 += v7 -+ v15 ^= v3 -+ v15 = bits.RotateLeft32(v15, -8) -+ v11 += v15 -+ v7 ^= v11 -+ v7 = bits.RotateLeft32(v7, -7) -+ -+ v0 += m[s[8]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft32(v15, -16) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft32(v5, -12) -+ v1 += m[s[9]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft32(v12, -16) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft32(v6, -12) -+ v2 += m[s[10]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft32(v13, -16) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft32(v7, -12) -+ v3 += m[s[11]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft32(v14, -16) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft32(v4, -12) -+ -+ v0 += m[s[12]] -+ v0 += v5 -+ v15 ^= v0 -+ v15 = bits.RotateLeft32(v15, -8) -+ v10 += v15 -+ v5 ^= v10 -+ v5 = bits.RotateLeft32(v5, -7) -+ v1 += m[s[13]] -+ v1 += v6 -+ v12 ^= v1 -+ v12 = bits.RotateLeft32(v12, -8) -+ v11 += v12 -+ v6 ^= v11 -+ v6 = bits.RotateLeft32(v6, -7) -+ v2 += m[s[14]] -+ v2 += v7 -+ v13 ^= v2 -+ v13 = bits.RotateLeft32(v13, -8) -+ v8 += v13 -+ v7 ^= v8 -+ v7 = bits.RotateLeft32(v7, -7) -+ v3 += m[s[15]] -+ v3 += v4 -+ v14 ^= v3 -+ v14 = bits.RotateLeft32(v14, -8) -+ v9 += v14 -+ v4 ^= v9 -+ v4 = bits.RotateLeft32(v4, -7) -+ } -+ -+ h[0] ^= v0 ^ v8 -+ h[1] ^= v1 ^ v9 -+ h[2] ^= v2 ^ v10 -+ h[3] ^= v3 ^ v11 -+ h[4] ^= v4 ^ v12 -+ h[5] ^= v5 ^ v13 -+ h[6] ^= v6 ^ v14 -+ h[7] ^= v7 ^ v15 -+ } -+ c[0], c[1] = c0, c1 -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go -new file mode 100644 -index 00000000000000..799dba0c415853 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_ref.go -@@ -0,0 +1,18 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (!amd64 && !386) || !gc || purego -+// +build !amd64,!386 !gc purego -+ -+package blake2s -+ -+var ( -+ useSSE4 = false -+ useSSSE3 = false -+ useSSE2 = false -+) -+ -+func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { -+ hashBlocksGeneric(h, c, flag, blocks) -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go b/ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go -new file mode 100644 -index 00000000000000..cde79fb1cd0c87 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2s_test.go -@@ -0,0 +1,1050 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2s -+ -+import ( -+ "bytes" -+ "encoding" -+ "encoding/hex" -+ "fmt" -+ "testing" -+) -+ -+func TestHashes(t *testing.T) { -+ defer func(sse2, ssse3, sse4 bool) { -+ useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4 -+ }(useSSE2, useSSSE3, useSSE4) -+ -+ if useSSE4 { -+ t.Log("SSE4 version") -+ testHashes(t) -+ testHashes128(t) -+ useSSE4 = false -+ } -+ if useSSSE3 { -+ t.Log("SSSE3 version") -+ testHashes(t) -+ testHashes128(t) -+ useSSSE3 = false -+ } -+ if useSSE2 { -+ t.Log("SSE2 version") -+ testHashes(t) -+ testHashes128(t) -+ useSSE2 = false -+ } -+ -+ t.Log("generic version") -+ testHashes(t) -+ testHashes128(t) -+} -+ -+func TestHashes2X(t *testing.T) { -+ defer func(sse2, ssse3, sse4 bool) { -+ useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4 -+ }(useSSE2, useSSSE3, useSSE4) -+ -+ if useSSE4 { -+ t.Log("SSE4 version") -+ testHashes2X(t) -+ useSSE4 = false -+ } -+ if useSSSE3 { -+ t.Log("SSSE3 version") -+ testHashes2X(t) -+ useSSSE3 = false -+ } -+ if useSSE2 { -+ t.Log("SSE2 version") -+ testHashes2X(t) -+ useSSE2 = false -+ } -+ -+ t.Log("generic version") -+ testHashes2X(t) -+} -+ -+func TestMarshal(t *testing.T) { -+ input := make([]byte, 255) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ for i := 0; i < 256; i++ { -+ h, err := New256(nil) -+ if err != nil { -+ t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) -+ } -+ h2, err := New256(nil) -+ if err != nil { -+ t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) -+ } -+ -+ h.Write(input[:i/2]) -+ halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() -+ if err != nil { -+ t.Fatalf("len(input)=%d: could not marshal: %v", i, err) -+ } -+ err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) -+ if err != nil { -+ t.Fatalf("len(input)=%d: could not unmarshal: %v", i, err) -+ } -+ -+ h.Write(input[i/2 : i]) -+ sum := h.Sum(nil) -+ h2.Write(input[i/2 : i]) -+ sum2 := h2.Sum(nil) -+ -+ if !bytes.Equal(sum, sum2) { -+ t.Fatalf("len(input)=%d: results do not match; sum = %v, sum2 = %v", i, sum, sum2) -+ } -+ -+ h3, err := New256(nil) -+ if err != nil { -+ t.Fatalf("len(input)=%d: error from New256(nil): %v", i, err) -+ } -+ h3.Write(input[:i]) -+ sum3 := h3.Sum(nil) -+ if !bytes.Equal(sum, sum3) { -+ t.Fatalf("len(input)=%d: sum = %v, want %v", i, sum, sum3) -+ } -+ } -+} -+ -+func testHashes(t *testing.T) { -+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") -+ -+ input := make([]byte, 255) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ -+ for i, expectedHex := range hashes { -+ h, err := New256(key) -+ if err != nil { -+ t.Fatalf("#%d: error from New256: %v", i, err) -+ } -+ -+ h.Write(input[:i]) -+ sum := h.Sum(nil) -+ -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(input[j : j+1]) -+ } -+ -+ sum = h.Sum(sum[:0]) -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ } -+} -+ -+func testHashes128(t *testing.T) { -+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") -+ -+ input := make([]byte, 255) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ -+ for i, expectedHex := range hashes128 { -+ h, err := New128(key) -+ if err != nil { -+ t.Fatalf("#%d: error from New128: %v", i, err) -+ } -+ -+ h.Write(input[:i]) -+ sum := h.Sum(nil) -+ -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(input[j : j+1]) -+ } -+ -+ sum = h.Sum(sum[:0]) -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ } -+} -+ -+func testHashes2X(t *testing.T) { -+ key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") -+ -+ input := make([]byte, 256) -+ for i := range input { -+ input[i] = byte(i) -+ } -+ -+ for i, expectedHex := range hashes2X { -+ length := uint16(len(expectedHex) / 2) -+ sum := make([]byte, int(length)) -+ -+ h, err := NewXOF(length, key) -+ if err != nil { -+ t.Fatalf("#%d: error from NewXOF: %v", i, err) -+ } -+ -+ if _, err := h.Write(input); err != nil { -+ t.Fatalf("#%d (single write): error from Write: %v", i, err) -+ } -+ if _, err := h.Read(sum); err != nil { -+ t.Fatalf("#%d (single write): error from Read: %v", i, err) -+ } -+ -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ -+ h.Reset() -+ for j := 0; j < len(input); j++ { -+ h.Write(input[j : j+1]) -+ } -+ for j := 0; j < len(sum); j++ { -+ h = h.Clone() -+ if _, err := h.Read(sum[j : j+1]); err != nil { -+ t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) -+ } -+ } -+ if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { -+ t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) -+ } -+ } -+ -+ h, err := NewXOF(OutputLengthUnknown, key) -+ if err != nil { -+ t.Fatalf("#unknown length: error from NewXOF: %v", err) -+ } -+ if _, err := h.Write(input); err != nil { -+ t.Fatalf("#unknown length: error from Write: %v", err) -+ } -+ -+ var result [64]byte -+ if n, err := h.Read(result[:]); err != nil { -+ t.Fatalf("#unknown length: error from Read: %v", err) -+ } else if n != len(result) { -+ t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) -+ } -+ -+ const expected = "2a9a6977d915a2c4dd07dbcafe1918bf1682e56d9c8e567ecd19bfd7cd93528833c764d12b34a5e2a219c9fd463dab45e972c5574d73f45de5b2e23af72530d8" -+ if fmt.Sprintf("%x", result) != expected { -+ t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) -+ } -+} -+ -+// Benchmarks -+ -+func benchmarkSum(b *testing.B, size int) { -+ data := make([]byte, size) -+ b.SetBytes(int64(size)) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ Sum256(data) -+ } -+} -+ -+func benchmarkWrite(b *testing.B, size int) { -+ data := make([]byte, size) -+ h, _ := New256(nil) -+ b.SetBytes(int64(size)) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ h.Write(data) -+ } -+} -+ -+func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64) } -+func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } -+ -+func BenchmarkSum64(b *testing.B) { benchmarkSum(b, 64) } -+func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } -+ -+// hashes is taken from https://blake2.net/blake2s-test.txt -+var hashes = []string{ -+ "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49", -+ "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1", -+ "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803", -+ "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b", -+ "f6c3fbadb4cc687a0064a5be6e791bec63b868ad62fba61b3757ef9ca52e05b2", -+ "49c1f21188dfd769aea0e911dd6b41f14dab109d2b85977aa3088b5c707e8598", -+ "fdd8993dcd43f696d44f3cea0ff35345234ec8ee083eb3cada017c7f78c17143", -+ "e6c8125637438d0905b749f46560ac89fd471cf8692e28fab982f73f019b83a9", -+ "19fc8ca6979d60e6edd3b4541e2f967ced740df6ec1eaebbfe813832e96b2974", -+ "a6ad777ce881b52bb5a4421ab6cdd2dfba13e963652d4d6d122aee46548c14a7", -+ "f5c4b2ba1a00781b13aba0425242c69cb1552f3f71a9a3bb22b4a6b4277b46dd", -+ "e33c4c9bd0cc7e45c80e65c77fa5997fec7002738541509e68a9423891e822a3", -+ "fba16169b2c3ee105be6e1e650e5cbf40746b6753d036ab55179014ad7ef6651", -+ "f5c4bec6d62fc608bf41cc115f16d61c7efd3ff6c65692bbe0afffb1fede7475", -+ "a4862e76db847f05ba17ede5da4e7f91b5925cf1ad4ba12732c3995742a5cd6e", -+ "65f4b860cd15b38ef814a1a804314a55be953caa65fd758ad989ff34a41c1eea", -+ "19ba234f0a4f38637d1839f9d9f76ad91c8522307143c97d5f93f69274cec9a7", -+ "1a67186ca4a5cb8e65fca0e2ecbc5ddc14ae381bb8bffeb9e0a103449e3ef03c", -+ "afbea317b5a2e89c0bd90ccf5d7fd0ed57fe585e4be3271b0a6bf0f5786b0f26", -+ "f1b01558ce541262f5ec34299d6fb4090009e3434be2f49105cf46af4d2d4124", -+ "13a0a0c86335635eaa74ca2d5d488c797bbb4f47dc07105015ed6a1f3309efce", -+ "1580afeebebb346f94d59fe62da0b79237ead7b1491f5667a90e45edf6ca8b03", -+ "20be1a875b38c573dd7faaa0de489d655c11efb6a552698e07a2d331b5f655c3", -+ "be1fe3c4c04018c54c4a0f6b9a2ed3c53abe3a9f76b4d26de56fc9ae95059a99", -+ "e3e3ace537eb3edd8463d9ad3582e13cf86533ffde43d668dd2e93bbdbd7195a", -+ "110c50c0bf2c6e7aeb7e435d92d132ab6655168e78a2decdec3330777684d9c1", -+ "e9ba8f505c9c80c08666a701f3367e6cc665f34b22e73c3c0417eb1c2206082f", -+ "26cd66fca02379c76df12317052bcafd6cd8c3a7b890d805f36c49989782433a", -+ "213f3596d6e3a5d0e9932cd2159146015e2abc949f4729ee2632fe1edb78d337", -+ "1015d70108e03be1c702fe97253607d14aee591f2413ea6787427b6459ff219a", -+ "3ca989de10cfe609909472c8d35610805b2f977734cf652cc64b3bfc882d5d89", -+ "b6156f72d380ee9ea6acd190464f2307a5c179ef01fd71f99f2d0f7a57360aea", -+ "c03bc642b20959cbe133a0303e0c1abff3e31ec8e1a328ec8565c36decff5265", -+ "2c3e08176f760c6264c3a2cd66fec6c3d78de43fc192457b2a4a660a1e0eb22b", -+ "f738c02f3c1b190c512b1a32deabf353728e0e9ab034490e3c3409946a97aeec", -+ "8b1880df301cc963418811088964839287ff7fe31c49ea6ebd9e48bdeee497c5", -+ "1e75cb21c60989020375f1a7a242839f0b0b68973a4c2a05cf7555ed5aaec4c1", -+ "62bf8a9c32a5bccf290b6c474d75b2a2a4093f1a9e27139433a8f2b3bce7b8d7", -+ "166c8350d3173b5e702b783dfd33c66ee0432742e9b92b997fd23c60dc6756ca", -+ "044a14d822a90cacf2f5a101428adc8f4109386ccb158bf905c8618b8ee24ec3", -+ "387d397ea43a994be84d2d544afbe481a2000f55252696bba2c50c8ebd101347", -+ "56f8ccf1f86409b46ce36166ae9165138441577589db08cbc5f66ca29743b9fd", -+ "9706c092b04d91f53dff91fa37b7493d28b576b5d710469df79401662236fc03", -+ "877968686c068ce2f7e2adcff68bf8748edf3cf862cfb4d3947a3106958054e3", -+ "8817e5719879acf7024787eccdb271035566cfa333e049407c0178ccc57a5b9f", -+ "8938249e4b50cadaccdf5b18621326cbb15253e33a20f5636e995d72478de472", -+ "f164abba4963a44d107257e3232d90aca5e66a1408248c51741e991db5227756", -+ "d05563e2b1cba0c4a2a1e8bde3a1a0d9f5b40c85a070d6f5fb21066ead5d0601", -+ "03fbb16384f0a3866f4c3117877666efbf124597564b293d4aab0d269fabddfa", -+ "5fa8486ac0e52964d1881bbe338eb54be2f719549224892057b4da04ba8b3475", -+ "cdfabcee46911111236a31708b2539d71fc211d9b09c0d8530a11e1dbf6eed01", -+ "4f82de03b9504793b82a07a0bdcdff314d759e7b62d26b784946b0d36f916f52", -+ "259ec7f173bcc76a0994c967b4f5f024c56057fb79c965c4fae41875f06a0e4c", -+ "193cc8e7c3e08bb30f5437aa27ade1f142369b246a675b2383e6da9b49a9809e", -+ "5c10896f0e2856b2a2eee0fe4a2c1633565d18f0e93e1fab26c373e8f829654d", -+ "f16012d93f28851a1eb989f5d0b43f3f39ca73c9a62d5181bff237536bd348c3", -+ "2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806", -+ "ddb8782485e900bc60bcf4c33a6fd585680cc683d516efa03eb9985fad8715fb", -+ "4c4d6e71aea05786413148fc7a786b0ecaf582cff1209f5a809fba8504ce662c", -+ "fb4c5e86d7b2229b99b8ba6d94c247ef964aa3a2bae8edc77569f28dbbff2d4e", -+ "e94f526de9019633ecd54ac6120f23958d7718f1e7717bf329211a4faeed4e6d", -+ "cbd6660a10db3f23f7a03d4b9d4044c7932b2801ac89d60bc9eb92d65a46c2a0", -+ "8818bbd3db4dc123b25cbba5f54c2bc4b3fcf9bf7d7a7709f4ae588b267c4ece", -+ "c65382513f07460da39833cb666c5ed82e61b9e998f4b0c4287cee56c3cc9bcd", -+ "8975b0577fd35566d750b362b0897a26c399136df07bababbde6203ff2954ed4", -+ "21fe0ceb0052be7fb0f004187cacd7de67fa6eb0938d927677f2398c132317a8", -+ "2ef73f3c26f12d93889f3c78b6a66c1d52b649dc9e856e2c172ea7c58ac2b5e3", -+ "388a3cd56d73867abb5f8401492b6e2681eb69851e767fd84210a56076fb3dd3", -+ "af533e022fc9439e4e3cb838ecd18692232adf6fe9839526d3c3dd1b71910b1a", -+ "751c09d41a9343882a81cd13ee40818d12eb44c6c7f40df16e4aea8fab91972a", -+ "5b73ddb68d9d2b0aa265a07988d6b88ae9aac582af83032f8a9b21a2e1b7bf18", -+ "3da29126c7c5d7f43e64242a79feaa4ef3459cdeccc898ed59a97f6ec93b9dab", -+ "566dc920293da5cb4fe0aa8abda8bbf56f552313bff19046641e3615c1e3ed3f", -+ "4115bea02f73f97f629e5c5590720c01e7e449ae2a6697d4d2783321303692f9", -+ "4ce08f4762468a7670012164878d68340c52a35e66c1884d5c864889abc96677", -+ "81ea0b7804124e0c22ea5fc71104a2afcb52a1fa816f3ecb7dcb5d9dea1786d0", -+ "fe362733b05f6bedaf9379d7f7936ede209b1f8323c3922549d9e73681b5db7b", -+ "eff37d30dfd20359be4e73fdf40d27734b3df90a97a55ed745297294ca85d09f", -+ "172ffc67153d12e0ca76a8b6cd5d4731885b39ce0cac93a8972a18006c8b8baf", -+ "c47957f1cc88e83ef9445839709a480a036bed5f88ac0fcc8e1e703ffaac132c", -+ "30f3548370cfdceda5c37b569b6175e799eef1a62aaa943245ae7669c227a7b5", -+ "c95dcb3cf1f27d0eef2f25d2413870904a877c4a56c2de1e83e2bc2ae2e46821", -+ "d5d0b5d705434cd46b185749f66bfb5836dcdf6ee549a2b7a4aee7f58007caaf", -+ "bbc124a712f15d07c300e05b668389a439c91777f721f8320c1c9078066d2c7e", -+ "a451b48c35a6c7854cfaae60262e76990816382ac0667e5a5c9e1b46c4342ddf", -+ "b0d150fb55e778d01147f0b5d89d99ecb20ff07e5e6760d6b645eb5b654c622b", -+ "34f737c0ab219951eee89a9f8dac299c9d4c38f33fa494c5c6eefc92b6db08bc", -+ "1a62cc3a00800dcbd99891080c1e098458193a8cc9f970ea99fbeff00318c289", -+ "cfce55ebafc840d7ae48281c7fd57ec8b482d4b704437495495ac414cf4a374b", -+ "6746facf71146d999dabd05d093ae586648d1ee28e72617b99d0f0086e1e45bf", -+ "571ced283b3f23b4e750bf12a2caf1781847bd890e43603cdc5976102b7bb11b", -+ "cfcb765b048e35022c5d089d26e85a36b005a2b80493d03a144e09f409b6afd1", -+ "4050c7a27705bb27f42089b299f3cbe5054ead68727e8ef9318ce6f25cd6f31d", -+ "184070bd5d265fbdc142cd1c5cd0d7e414e70369a266d627c8fba84fa5e84c34", -+ "9edda9a4443902a9588c0d0ccc62b930218479a6841e6fe7d43003f04b1fd643", -+ "e412feef7908324a6da1841629f35d3d358642019310ec57c614836b63d30763", -+ "1a2b8edff3f9acc1554fcbae3cf1d6298c6462e22e5eb0259684f835012bd13f", -+ "288c4ad9b9409762ea07c24a41f04f69a7d74bee2d95435374bde946d7241c7b", -+ "805691bb286748cfb591d3aebe7e6f4e4dc6e2808c65143cc004e4eb6fd09d43", -+ "d4ac8d3a0afc6cfa7b460ae3001baeb36dadb37da07d2e8ac91822df348aed3d", -+ "c376617014d20158bced3d3ba552b6eccf84e62aa3eb650e90029c84d13eea69", -+ "c41f09f43cecae7293d6007ca0a357087d5ae59be500c1cd5b289ee810c7b082", -+ "03d1ced1fba5c39155c44b7765cb760c78708dcfc80b0bd8ade3a56da8830b29", -+ "09bde6f152218dc92c41d7f45387e63e5869d807ec70b821405dbd884b7fcf4b", -+ "71c9036e18179b90b37d39e9f05eb89cc5fc341fd7c477d0d7493285faca08a4", -+ "5916833ebb05cd919ca7fe83b692d3205bef72392b2cf6bb0a6d43f994f95f11", -+ "f63aab3ec641b3b024964c2b437c04f6043c4c7e0279239995401958f86bbe54", -+ "f172b180bfb09740493120b6326cbdc561e477def9bbcfd28cc8c1c5e3379a31", -+ "cb9b89cc18381dd9141ade588654d4e6a231d5bf49d4d59ac27d869cbe100cf3", -+ "7bd8815046fdd810a923e1984aaebdcdf84d87c8992d68b5eeb460f93eb3c8d7", -+ "607be66862fd08ee5b19facac09dfdbcd40c312101d66e6ebd2b841f1b9a9325", -+ "9fe03bbe69ab1834f5219b0da88a08b30a66c5913f0151963c360560db0387b3", -+ "90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c", -+ "336ea0530f4a7469126e0218587ebbde3358a0b31c29d200f7dc7eb15c6aadd8", -+ "a79e76dc0abca4396f0747cd7b748df913007626b1d659da0c1f78b9303d01a3", -+ "44e78a773756e0951519504d7038d28d0213a37e0ce375371757bc996311e3b8", -+ "77ac012a3f754dcfeab5eb996be9cd2d1f96111b6e49f3994df181f28569d825", -+ "ce5a10db6fccdaf140aaa4ded6250a9c06e9222bc9f9f3658a4aff935f2b9f3a", -+ "ecc203a7fe2be4abd55bb53e6e673572e0078da8cd375ef430cc97f9f80083af", -+ "14a5186de9d7a18b0412b8563e51cc5433840b4a129a8ff963b33a3c4afe8ebb", -+ "13f8ef95cb86e6a638931c8e107673eb76ba10d7c2cd70b9d9920bbeed929409", -+ "0b338f4ee12f2dfcb78713377941e0b0632152581d1332516e4a2cab1942cca4", -+ "eaab0ec37b3b8ab796e9f57238de14a264a076f3887d86e29bb5906db5a00e02", -+ "23cb68b8c0e6dc26dc27766ddc0a13a99438fd55617aa4095d8f969720c872df", -+ "091d8ee30d6f2968d46b687dd65292665742de0bb83dcc0004c72ce10007a549", -+ "7f507abc6d19ba00c065a876ec5657868882d18a221bc46c7a6912541f5bc7ba", -+ "a0607c24e14e8c223db0d70b4d30ee88014d603f437e9e02aa7dafa3cdfbad94", -+ "ddbfea75cc467882eb3483ce5e2e756a4f4701b76b445519e89f22d60fa86e06", -+ "0c311f38c35a4fb90d651c289d486856cd1413df9b0677f53ece2cd9e477c60a", -+ "46a73a8dd3e70f59d3942c01df599def783c9da82fd83222cd662b53dce7dbdf", -+ "ad038ff9b14de84a801e4e621ce5df029dd93520d0c2fa38bff176a8b1d1698c", -+ "ab70c5dfbd1ea817fed0cd067293abf319e5d7901c2141d5d99b23f03a38e748", -+ "1fffda67932b73c8ecaf009a3491a026953babfe1f663b0697c3c4ae8b2e7dcb", -+ "b0d2cc19472dd57f2b17efc03c8d58c2283dbb19da572f7755855aa9794317a0", -+ "a0d19a6ee33979c325510e276622df41f71583d07501b87071129a0ad94732a5", -+ "724642a7032d1062b89e52bea34b75df7d8fe772d9fe3c93ddf3c4545ab5a99b", -+ "ade5eaa7e61f672d587ea03dae7d7b55229c01d06bc0a5701436cbd18366a626", -+ "013b31ebd228fcdda51fabb03bb02d60ac20ca215aafa83bdd855e3755a35f0b", -+ "332ed40bb10dde3c954a75d7b8999d4b26a1c063c1dc6e32c1d91bab7bbb7d16", -+ "c7a197b3a05b566bcc9facd20e441d6f6c2860ac9651cd51d6b9d2cdeeea0390", -+ "bd9cf64ea8953c037108e6f654914f3958b68e29c16700dc184d94a21708ff60", -+ "8835b0ac021151df716474ce27ce4d3c15f0b2dab48003cf3f3efd0945106b9a", -+ "3bfefa3301aa55c080190cffda8eae51d9af488b4c1f24c3d9a75242fd8ea01d", -+ "08284d14993cd47d53ebaecf0df0478cc182c89c00e1859c84851686ddf2c1b7", -+ "1ed7ef9f04c2ac8db6a864db131087f27065098e69c3fe78718d9b947f4a39d0", -+ "c161f2dcd57e9c1439b31a9dd43d8f3d7dd8f0eb7cfac6fb25a0f28e306f0661", -+ "c01969ad34c52caf3dc4d80d19735c29731ac6e7a92085ab9250c48dea48a3fc", -+ "1720b3655619d2a52b3521ae0e49e345cb3389ebd6208acaf9f13fdacca8be49", -+ "756288361c83e24c617cf95c905b22d017cdc86f0bf1d658f4756c7379873b7f", -+ "e7d0eda3452693b752abcda1b55e276f82698f5f1605403eff830bea0071a394", -+ "2c82ecaa6b84803e044af63118afe544687cb6e6c7df49ed762dfd7c8693a1bc", -+ "6136cbf4b441056fa1e2722498125d6ded45e17b52143959c7f4d4e395218ac2", -+ "721d3245aafef27f6a624f47954b6c255079526ffa25e9ff77e5dcff473b1597", -+ "9dd2fbd8cef16c353c0ac21191d509eb28dd9e3e0d8cea5d26ca839393851c3a", -+ "b2394ceacdebf21bf9df2ced98e58f1c3a4bbbff660dd900f62202d6785cc46e", -+ "57089f222749ad7871765f062b114f43ba20ec56422a8b1e3f87192c0ea718c6", -+ "e49a9459961cd33cdf4aae1b1078a5dea7c040e0fea340c93a724872fc4af806", -+ "ede67f720effd2ca9c88994152d0201dee6b0a2d2c077aca6dae29f73f8b6309", -+ "e0f434bf22e3088039c21f719ffc67f0f2cb5e98a7a0194c76e96bf4e8e17e61", -+ "277c04e2853484a4eba910ad336d01b477b67cc200c59f3c8d77eef8494f29cd", -+ "156d5747d0c99c7f27097d7b7e002b2e185cb72d8dd7eb424a0321528161219f", -+ "20ddd1ed9b1ca803946d64a83ae4659da67fba7a1a3eddb1e103c0f5e03e3a2c", -+ "f0af604d3dabbf9a0f2a7d3dda6bd38bba72c6d09be494fcef713ff10189b6e6", -+ "9802bb87def4cc10c4a5fd49aa58dfe2f3fddb46b4708814ead81d23ba95139b", -+ "4f8ce1e51d2fe7f24043a904d898ebfc91975418753413aa099b795ecb35cedb", -+ "bddc6514d7ee6ace0a4ac1d0e068112288cbcf560454642705630177cba608bd", -+ "d635994f6291517b0281ffdd496afa862712e5b3c4e52e4cd5fdae8c0e72fb08", -+ "878d9ca600cf87e769cc305c1b35255186615a73a0da613b5f1c98dbf81283ea", -+ "a64ebe5dc185de9fdde7607b6998702eb23456184957307d2fa72e87a47702d6", -+ "ce50eab7b5eb52bdc9ad8e5a480ab780ca9320e44360b1fe37e03f2f7ad7de01", -+ "eeddb7c0db6e30abe66d79e327511e61fcebbc29f159b40a86b046ecf0513823", -+ "787fc93440c1ec96b5ad01c16cf77916a1405f9426356ec921d8dff3ea63b7e0", -+ "7f0d5eab47eefda696c0bf0fbf86ab216fce461e9303aba6ac374120e890e8df", -+ "b68004b42f14ad029f4c2e03b1d5eb76d57160e26476d21131bef20ada7d27f4", -+ "b0c4eb18ae250b51a41382ead92d0dc7455f9379fc9884428e4770608db0faec", -+ "f92b7a870c059f4d46464c824ec96355140bdce681322cc3a992ff103e3fea52", -+ "5364312614813398cc525d4c4e146edeb371265fba19133a2c3d2159298a1742", -+ "f6620e68d37fb2af5000fc28e23b832297ecd8bce99e8be4d04e85309e3d3374", -+ "5316a27969d7fe04ff27b283961bffc3bf5dfb32fb6a89d101c6c3b1937c2871", -+ "81d1664fdf3cb33c24eebac0bd64244b77c4abea90bbe8b5ee0b2aafcf2d6a53", -+ "345782f295b0880352e924a0467b5fbc3e8f3bfbc3c7e48b67091fb5e80a9442", -+ "794111ea6cd65e311f74ee41d476cb632ce1e4b051dc1d9e9d061a19e1d0bb49", -+ "2a85daf6138816b99bf8d08ba2114b7ab07975a78420c1a3b06a777c22dd8bcb", -+ "89b0d5f289ec16401a069a960d0b093e625da3cf41ee29b59b930c5820145455", -+ "d0fdcb543943fc27d20864f52181471b942cc77ca675bcb30df31d358ef7b1eb", -+ "b17ea8d77063c709d4dc6b879413c343e3790e9e62ca85b7900b086f6b75c672", -+ "e71a3e2c274db842d92114f217e2c0eac8b45093fdfd9df4ca7162394862d501", -+ "c0476759ab7aa333234f6b44f5fd858390ec23694c622cb986e769c78edd733e", -+ "9ab8eabb1416434d85391341d56993c55458167d4418b19a0f2ad8b79a83a75b", -+ "7992d0bbb15e23826f443e00505d68d3ed7372995a5c3e498654102fbcd0964e", -+ "c021b30085151435df33b007ccecc69df1269f39ba25092bed59d932ac0fdc28", -+ "91a25ec0ec0d9a567f89c4bfe1a65a0e432d07064b4190e27dfb81901fd3139b", -+ "5950d39a23e1545f301270aa1a12f2e6c453776e4d6355de425cc153f9818867", -+ "d79f14720c610af179a3765d4b7c0968f977962dbf655b521272b6f1e194488e", -+ "e9531bfc8b02995aeaa75ba27031fadbcbf4a0dab8961d9296cd7e84d25d6006", -+ "34e9c26a01d7f16181b454a9d1623c233cb99d31c694656e9413aca3e918692f", -+ "d9d7422f437bd439ddd4d883dae2a08350173414be78155133fff1964c3d7972", -+ "4aee0c7aaf075414ff1793ead7eaca601775c615dbd60b640b0a9f0ce505d435", -+ "6bfdd15459c83b99f096bfb49ee87b063d69c1974c6928acfcfb4099f8c4ef67", -+ "9fd1c408fd75c336193a2a14d94f6af5adf050b80387b4b010fb29f4cc72707c", -+ "13c88480a5d00d6c8c7ad2110d76a82d9b70f4fa6696d4e5dd42a066dcaf9920", -+ "820e725ee25fe8fd3a8d5abe4c46c3ba889de6fa9191aa22ba67d5705421542b", -+ "32d93a0eb02f42fbbcaf2bad0085b282e46046a4df7ad10657c9d6476375b93e", -+ "adc5187905b1669cd8ec9c721e1953786b9d89a9bae30780f1e1eab24a00523c", -+ "e90756ff7f9ad810b239a10ced2cf9b2284354c1f8c7e0accc2461dc796d6e89", -+ "1251f76e56978481875359801db589a0b22f86d8d634dc04506f322ed78f17e8", -+ "3afa899fd980e73ecb7f4d8b8f291dc9af796bc65d27f974c6f193c9191a09fd", -+ "aa305be26e5deddc3c1010cbc213f95f051c785c5b431e6a7cd048f161787528", -+ "8ea1884ff32e9d10f039b407d0d44e7e670abd884aeee0fb757ae94eaa97373d", -+ "d482b2155d4dec6b4736a1f1617b53aaa37310277d3fef0c37ad41768fc235b4", -+ "4d413971387e7a8898a8dc2a27500778539ea214a2dfe9b3d7e8ebdce5cf3db3", -+ "696e5d46e6c57e8796e4735d08916e0b7929b3cf298c296d22e9d3019653371c", -+ "1f5647c1d3b088228885865c8940908bf40d1a8272821973b160008e7a3ce2eb", -+ "b6e76c330f021a5bda65875010b0edf09126c0f510ea849048192003aef4c61c", -+ "3cd952a0beada41abb424ce47f94b42be64e1ffb0fd0782276807946d0d0bc55", -+ "98d92677439b41b7bb513312afb92bcc8ee968b2e3b238cecb9b0f34c9bb63d0", -+ "ecbca2cf08ae57d517ad16158a32bfa7dc0382eaeda128e91886734c24a0b29d", -+ "942cc7c0b52e2b16a4b89fa4fc7e0bf609e29a08c1a8543452b77c7bfd11bb28", -+ "8a065d8b61a0dffb170d5627735a76b0e9506037808cba16c345007c9f79cf8f", -+ "1b9fa19714659c78ff413871849215361029ac802b1cbcd54e408bd87287f81f", -+ "8dab071bcd6c7292a9ef727b4ae0d86713301da8618d9a48adce55f303a869a1", -+ "8253e3e7c7b684b9cb2beb014ce330ff3d99d17abbdbabe4f4d674ded53ffc6b", -+ "f195f321e9e3d6bd7d074504dd2ab0e6241f92e784b1aa271ff648b1cab6d7f6", -+ "27e4cc72090f241266476a7c09495f2db153d5bcbd761903ef79275ec56b2ed8", -+ "899c2405788e25b99a1846355e646d77cf400083415f7dc5afe69d6e17c00023", -+ "a59b78c4905744076bfee894de707d4f120b5c6893ea0400297d0bb834727632", -+ "59dc78b105649707a2bb4419c48f005400d3973de3736610230435b10424b24f", -+ "c0149d1d7e7a6353a6d906efe728f2f329fe14a4149a3ea77609bc42b975ddfa", -+ "a32f241474a6c16932e9243be0cf09bcdc7e0ca0e7a6a1b9b1a0f01e41502377", -+ "b239b2e4f81841361c1339f68e2c359f929af9ad9f34e01aab4631ad6d5500b0", -+ "85fb419c7002a3e0b4b6ea093b4c1ac6936645b65dac5ac15a8528b7b94c1754", -+ "9619720625f190b93a3fad186ab314189633c0d3a01e6f9bc8c4a8f82f383dbf", -+ "7d620d90fe69fa469a6538388970a1aa09bb48a2d59b347b97e8ce71f48c7f46", -+ "294383568596fb37c75bbacd979c5ff6f20a556bf8879cc72924855df9b8240e", -+ "16b18ab314359c2b833c1c6986d48c55a9fc97cde9a3c1f10a3177140f73f738", -+ "8cbbdd14bc33f04cf45813e4a153a273d36adad5ce71f499eeb87fb8ac63b729", -+ "69c9a498db174ecaefcc5a3ac9fdedf0f813a5bec727f1e775babdec7718816e", -+ "b462c3be40448f1d4f80626254e535b08bc9cdcff599a768578d4b2881a8e3f0", -+ "553e9d9c5f360ac0b74a7d44e5a391dad4ced03e0c24183b7e8ecabdf1715a64", -+ "7a7c55a56fa9ae51e655e01975d8a6ff4ae9e4b486fcbe4eac044588f245ebea", -+ "2afdf3c82abc4867f5de111286c2b3be7d6e48657ba923cfbf101a6dfcf9db9a", -+ "41037d2edcdce0c49b7fb4a6aa0999ca66976c7483afe631d4eda283144f6dfc", -+ "c4466f8497ca2eeb4583a0b08e9d9ac74395709fda109d24f2e4462196779c5d", -+ "75f609338aa67d969a2ae2a2362b2da9d77c695dfd1df7224a6901db932c3364", -+ "68606ceb989d5488fc7cf649f3d7c272ef055da1a93faecd55fe06f6967098ca", -+ "44346bdeb7e052f6255048f0d9b42c425bab9c3dd24168212c3ecf1ebf34e6ae", -+ "8e9cf6e1f366471f2ac7d2ee9b5e6266fda71f8f2e4109f2237ed5f8813fc718", -+ "84bbeb8406d250951f8c1b3e86a7c010082921833dfd9555a2f909b1086eb4b8", -+ "ee666f3eef0f7e2a9c222958c97eaf35f51ced393d714485ab09a069340fdf88", -+ "c153d34a65c47b4a62c5cacf24010975d0356b2f32c8f5da530d338816ad5de6", -+ "9fc5450109e1b779f6c7ae79d56c27635c8dd426c5a9d54e2578db989b8c3b4e", -+ "d12bf3732ef4af5c22fa90356af8fc50fcb40f8f2ea5c8594737a3b3d5abdbd7", -+ "11030b9289bba5af65260672ab6fee88b87420acef4a1789a2073b7ec2f2a09e", -+ "69cb192b8444005c8c0ceb12c846860768188cda0aec27a9c8a55cdee2123632", -+ "db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83", -+ "3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd", -+} -+ -+var hashes128 = []string{ -+ "9536f9b267655743dee97b8a670f9f53", -+ "13bacfb85b48a1223c595f8c1e7e82cb", -+ "d47a9b1645e2feae501cd5fe44ce6333", -+ "1e2a79436a7796a3e9826bfedf07659f", -+ "7640360ed3c4f3054dba79a21dda66b7", -+ "d1207ac2bf5ac84fc9ef016da5a46a86", -+ "3123987871e59305ece3125abfc0099a", -+ "cf9e072ad522f2cda2d825218086731c", -+ "95d22870392efe2846b12b6e8e84efbb", -+ "7d63c30e2d51333f245601b038c0b93b", -+ "ed608b98e13976bdf4bedc63fa35e443", -+ "ed704b5cd1abf8e0dd67a6ac667a3fa5", -+ "77dc70109827dc74c70fd26cba379ae5", -+ "d2bf34508b07825ee934f33958f4560e", -+ "a340baa7b8a93a6e658adef42e78eeb7", -+ "b85c5ceaecbe9a251eac76f6932ba395", -+ "246519722001f6e8e97a2183f5985e53", -+ "5bce5aa0b7c6cac2ecf6406183cd779a", -+ "13408f1647c02f6efd0047ad8344f695", -+ "a63970f196760aa36cb965ab62f0e0fa", -+ "bc26f48421dd99fd45e15e736d3e7dac", -+ "4c6f70f9e3237cde918afb52d26f1823", -+ "45ed610cfbc37db80c4bf0eef14ae8d6", -+ "87c4c150705ea5078209ec008200539c", -+ "54de21f5e0e6f2afe04daeb822b6931e", -+ "9732a04e505064e19de3d542e7e71631", -+ "d2bd27e95531d6957eef511c4ba64ad4", -+ "7a36c9f70dcc7c3063b547101a5f6c35", -+ "322007d1a44c4257bc7903b183305529", -+ "dbcc9a09f412290ca2e0d53dfd142ddb", -+ "df12ed43b8e53a56db20e0f83764002c", -+ "d114cc11e7d5b33a360c45f18d4c7c6e", -+ "c43b5e836af88620a8a71b1652cb8640", -+ "9491c653e8867ed73c1b4ac6b5a9bb4d", -+ "06d0e988df94ada6c6f9f36f588ab7c5", -+ "561efad2480e93262c8eeaa3677615c4", -+ "ba8ffc702e5adc93503045eca8702312", -+ "5782be6ccdc78c8425285e85de8ccdc6", -+ "aa1c4393e4c07b53ea6e2b5b1e970771", -+ "42a229dc50e52271c51e8666023ebc1e", -+ "53706110e919f84de7f8d6c7f0e7b831", -+ "fc5ac8ee39cc1dd1424391323e2901bd", -+ "bed27b62ff66cac2fbb68193c727106a", -+ "cd5e689b96d0b9ea7e08dac36f7b211e", -+ "0b4c7f604eba058d18e322c6e1baf173", -+ "eb838227fdfad09a27f0f8413120675d", -+ "3149cf9d19a7fd529e6154a8b4c3b3ad", -+ "ca1e20126df930fd5fb7afe4422191e5", -+ "b23398f910599f3c09b6549fa81bcb46", -+ "27fb17c11b34fa5d8b5afe5ee3321ead", -+ "0f665f5f04cf2d46b7fead1a1f328158", -+ "8f068be73b3681f99f3b282e3c02bba5", -+ "ba189bbd13808dcf4e002a4dd21660d5", -+ "2732dcd1b16668ae6ab6a61595d0d62a", -+ "d410ccdd059f0e02b472ec9ec54bdd3c", -+ "b2eaa07b055b3a03a399971327f7e8c2", -+ "2e8a225655e9f99b69c60dc8b4d8e566", -+ "4eb55416c853f2152e67f8a224133cec", -+ "49552403790d8de0505a8e317a443687", -+ "7f2747cd41f56942752e868212c7d5ac", -+ "02a28f10e193b430df7112d2d98cf759", -+ "d4213404a9f1cf759017747cf5958270", -+ "faa34884344f9c65e944882db8476d34", -+ "ece382a8bd5018f1de5da44b72cea75b", -+ "f1efa90d2547036841ecd3627fafbc36", -+ "811ff8686d23a435ecbd0bdafcd27b1b", -+ "b21beea9c7385f657a76558530438721", -+ "9cb969da4f1b4fc5b13bf78fe366f0c4", -+ "8850d16d7b614d3268ccfa009d33c7fc", -+ "aa98a2b6176ea86415b9aff3268c6f6d", -+ "ec3e1efa5ed195eff667e16b1af1e39e", -+ "e40787dca57411d2630db2de699beb08", -+ "554835890735babd06318de23d31e78a", -+ "493957feecddc302ee2bb2086b6ebfd3", -+ "f6069709ad5b0139163717e9ce1114ab", -+ "ba5ed386098da284484b211555505a01", -+ "9244c8dfad8cbb68c118fa51465b3ae4", -+ "51e309a5008eb1f5185e5cc007cfb36f", -+ "6ce9ff712121b4f6087955f4911eafd4", -+ "59b51d8dcda031218ccdd7c760828155", -+ "0012878767a3d4f1c8194458cf1f8832", -+ "82900708afd5b6582dc16f008c655edd", -+ "21302c7e39b5a4cdf1d6f86b4f00c9b4", -+ "e894c7431591eab8d1ce0fe2aa1f01df", -+ "b67e1c40ee9d988226d605621854d955", -+ "6237bdafa34137cbbec6be43ea9bd22c", -+ "4172a8e19b0dcb09b978bb9eff7af52b", -+ "5714abb55bd4448a5a6ad09fbd872fdf", -+ "7ce1700bef423e1f958a94a77a94d44a", -+ "3742ec50cded528527775833453e0b26", -+ "5d41b135724c7c9c689495324b162f18", -+ "85c523333c6442c202e9e6e0f1185f93", -+ "5c71f5222d40ff5d90e7570e71ab2d30", -+ "6e18912e83d012efb4c66250ced6f0d9", -+ "4add4448c2e35e0b138a0bac7b4b1775", -+ "c0376c6bc5e7b8b9d2108ec25d2aab53", -+ "f72261d5ed156765c977751c8a13fcc1", -+ "cff4156c48614b6ceed3dd6b9058f17e", -+ "36bfb513f76c15f514bcb593419835aa", -+ "166bf48c6bffaf8291e6fdf63854bef4", -+ "0b67d33f8b859c3157fbabd9e6e47ed0", -+ "e4da659ca76c88e73a9f9f10f3d51789", -+ "33c1ae2a86b3f51c0642e6ed5b5aa1f1", -+ "27469b56aca2334449c1cf4970dcd969", -+ "b7117b2e363378aa0901b0d6a9f6ddc0", -+ "a9578233b09e5cd5231943fdb12cd90d", -+ "486d7d75253598b716a068243c1c3e89", -+ "66f6b02d682b78ffdc85e9ec86852489", -+ "38a07b9a4b228fbcc305476e4d2e05d2", -+ "aedb61c7970e7d05bf9002dae3c6858c", -+ "c03ef441f7dd30fdb61ad2d4d8e4c7da", -+ "7f45cc1eea9a00cb6aeb2dd748361190", -+ "a59538b358459132e55160899e47bd65", -+ "137010fef72364411820c3fbed15c8df", -+ "d8362b93fc504500dbd33ac74e1b4d70", -+ "a7e49f12c8f47e3b29cf8c0889b0a9c8", -+ "072e94ffbfc684bd8ab2a1b9dade2fd5", -+ "5ab438584bd2229e452052e002631a5f", -+ "f233d14221097baef57d3ec205c9e086", -+ "3a95db000c4a8ff98dc5c89631a7f162", -+ "0544f18c2994ab4ddf1728f66041ff16", -+ "0bc02116c60a3cc331928d6c9d3ba37e", -+ "b189dca6cb5b813c74200834fba97f29", -+ "ac8aaab075b4a5bc24419da239212650", -+ "1e9f19323dc71c29ae99c479dc7e8df9", -+ "12d944c3fa7caa1b3d62adfc492274dd", -+ "b4c68f1fffe8f0030e9b18aad8c9dc96", -+ "25887fab1422700d7fa3edc0b20206e2", -+ "8c09f698d03eaf88abf69f8147865ef6", -+ "5c363ae42a5bec26fbc5e996428d9bd7", -+ "7fdfc2e854fbb3928150d5e3abcf56d6", -+ "f0c944023f714df115f9e4f25bcdb89b", -+ "6d19534b4c332741c8ddd79a9644de2d", -+ "32595eb23764fbfc2ee7822649f74a12", -+ "5a51391aab33c8d575019b6e76ae052a", -+ "98b861ce2c620f10f913af5d704a5afd", -+ "b7fe2fc8b77fb1ce434f8465c7ddf793", -+ "0e8406e0cf8e9cc840668ece2a0fc64e", -+ "b89922db99c58f6a128ccffe19b6ce60", -+ "e1be9af665f0932b77d7f5631a511db7", -+ "74b96f20f58de8dc9ff5e31f91828523", -+ "36a4cfef5a2a7d8548db6710e50b3009", -+ "007e95e8d3b91948a1dedb91f75de76b", -+ "a87a702ce08f5745edf765bfcd5fbe0d", -+ "847e69a388a749a9c507354d0dddfe09", -+ "07176eefbc107a78f058f3d424ca6a54", -+ "ad7e80682333b68296f6cb2b4a8e446d", -+ "53c4aba43896ae422e5de5b9edbd46bf", -+ "33bd6c20ca2a7ab916d6e98003c6c5f8", -+ "060d088ea94aa093f9981a79df1dfcc8", -+ "5617b214b9df08d4f11e58f5e76d9a56", -+ "ca3a60ee85bd971e1daf9f7db059d909", -+ "cd2b7754505d8c884eddf736f1ec613e", -+ "f496163b252f1439e7e113ba2ecabd8e", -+ "5719c7dcf9d9f756d6213354acb7d5cf", -+ "6f7dd40b245c54411e7a9be83ae5701c", -+ "c8994dd9fdeb077a45ea04a30358b637", -+ "4b1184f1e35458c1c747817d527a252f", -+ "fc7df674afeac7a3fd994183f4c67a74", -+ "4f68e05ce4dcc533acf9c7c01d95711e", -+ "d4ebc59e918400720035dfc88e0c486a", -+ "d3105dd6fa123e543b0b3a6e0eeaea9e", -+ "874196128ed443f5bdb2800ca048fcad", -+ "01645f134978dc8f9cf0abc93b53780e", -+ "5b8b64caa257873a0ffd47c981ef6c3f", -+ "4ee208fc50ba0a6e65c5b58cec44c923", -+ "53f409a52427b3b7ffabb057ca088428", -+ "c1d6cd616f5341a93d921e356e5887a9", -+ "e85c20fea67fa7320dc23379181183c8", -+ "7912b6409489df001b7372bc94aebde7", -+ "e559f761ec866a87f1f331767fafc60f", -+ "20a6f5a36bc37043d977ed7708465ef8", -+ "6a72f526965ab120826640dd784c6cc4", -+ "bf486d92ad68e87c613689dd370d001b", -+ "d339fd0eb35edf3abd6419c8d857acaf", -+ "9521cd7f32306d969ddabc4e6a617f52", -+ "a1cd9f3e81520842f3cf6cc301cb0021", -+ "18e879b6f154492d593edd3f4554e237", -+ "66e2329c1f5137589e051592587e521e", -+ "e899566dd6c3e82cbc83958e69feb590", -+ "8a4b41d7c47e4e80659d77b4e4bfc9ae", -+ "f1944f6fcfc17803405a1101998c57dd", -+ "f6bcec07567b4f72851b307139656b18", -+ "22e7bb256918fe9924dce9093e2d8a27", -+ "dd25b925815fe7b50b7079f5f65a3970", -+ "0457f10f299acf0c230dd4007612e58f", -+ "ecb420c19efd93814fae2964d69b54af", -+ "14eb47b06dff685d88751c6e32789db4", -+ "e8f072dbb50d1ab6654aa162604a892d", -+ "69cff9c62092332f03a166c7b0034469", -+ "d3619f98970b798ca32c6c14cd25af91", -+ "2246d423774ee9d51a551e89c0539d9e", -+ "75e5d1a1e374a04a699247dad827b6cf", -+ "6d087dd1d4cd15bf47db07c7a96b1db8", -+ "967e4c055ac51b4b2a3e506cebd5826f", -+ "7417aa79247e473401bfa92a25b62e2a", -+ "24f3f4956da34b5c533d9a551ccd7b16", -+ "0c40382de693a5304e2331eb951cc962", -+ "9436f949d51b347db5c8e6258dafaaac", -+ "d2084297fe84c4ba6e04e4fb73d734fe", -+ "42a6f8ff590af21b512e9e088257aa34", -+ "c484ad06b1cdb3a54f3f6464a7a2a6fd", -+ "1b8ac860f5ceb4365400a201ed2917aa", -+ "c43eadabbe7b7473f3f837fc52650f54", -+ "0e5d3205406126b1f838875deb150d6a", -+ "6bf4946f8ec8a9c417f50cd1e67565be", -+ "42f09a2522314799c95b3fc121a0e3e8", -+ "06b8f1487f691a3f7c3f74e133d55870", -+ "1a70a65fb4f314dcf6a31451a9d2704f", -+ "7d4acdd0823279fd28a1e48b49a04669", -+ "09545cc8822a5dfc93bbab708fd69174", -+ "efc063db625013a83c9a426d39a9bddb", -+ "213bbf89b3f5be0ffdb14854bbcb2588", -+ "b69624d89fe2774df9a6f43695d755d4", -+ "c0f9ff9ded82bd73c512e365a894774d", -+ "d1b68507ed89c17ead6f69012982db71", -+ "14cf16db04648978e35c44850855d1b0", -+ "9f254d4eccab74cd91d694df863650a8", -+ "8f8946e2967baa4a814d36ff01d20813", -+ "6b9dc4d24ecba166cb2915d7a6cba43b", -+ "eb35a80418a0042b850e294db7898d4d", -+ "f55f925d280c637d54055c9df088ef5f", -+ "f48427a04f67e33f3ba0a17f7c9704a7", -+ "4a9f5bfcc0321aea2eced896cee65894", -+ "8723a67d1a1df90f1cef96e6fe81e702", -+ "c166c343ee25998f80bad4067960d3fd", -+ "dab67288d16702e676a040fd42344d73", -+ "c8e9e0d80841eb2c116dd14c180e006c", -+ "92294f546bacf0dea9042c93ecba8b34", -+ "013705b1502b37369ad22fe8237d444e", -+ "9b97f8837d5f2ebab0768fc9a6446b93", -+ "7e7e5236b05ec35f89edf8bf655498e7", -+ "7be8f2362c174c776fb9432fe93bf259", -+ "2422e80420276d2df5702c6470879b01", -+ "df645795db778bcce23bbe819a76ba48", -+ "3f97a4ac87dfc58761cda1782d749074", -+ "50e3f45df21ebfa1b706b9c0a1c245a8", -+ "7879541c7ff612c7ddf17cb8f7260183", -+ "67f6542b903b7ba1945eba1a85ee6b1c", -+ "b34b73d36ab6234b8d3f5494d251138e", -+ "0aea139641fdba59ab1103479a96e05f", -+ "02776815a87b8ba878453666d42afe3c", -+ "5929ab0a90459ebac5a16e2fb37c847e", -+ "c244def5b20ce0468f2b5012d04ac7fd", -+ "12116add6fefce36ed8a0aeccce9b6d3", -+ "3cd743841e9d8b878f34d91b793b4fad", -+ "45e87510cf5705262185f46905fae35f", -+ "276047016b0bfb501b2d4fc748165793", -+ "ddd245df5a799417d350bd7f4e0b0b7e", -+ "d34d917a54a2983f3fdbc4b14caae382", -+ "7730fbc09d0c1fb1939a8fc436f6b995", -+ "eb4899ef257a1711cc9270a19702e5b5", -+ "8a30932014bce35bba620895d374df7a", -+ "1924aabf9c50aa00bee5e1f95b5d9e12", -+ "1758d6f8b982aec9fbe50f20e3082b46", -+ "cd075928ab7e6883e697fe7fd3ac43ee", -+} -+ -+// hashes2X is taken from -+// https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2-kat.json -+var hashes2X = []string{ -+ "0e", -+ "5196", -+ "ad6bad", -+ "d8e4b32f", -+ "8eb89056f3", -+ "410497c2ed72", -+ "f0de771b375c90", -+ "8662db8685033611", -+ "9ef9f1eed88a3f52ca", -+ "08225082df0d2b0a815e", -+ "0f6e84a17439f1bc97c299", -+ "895ec39c78d3556cefdbfabc", -+ "2b396b3fa90ab556079a79b44d", -+ "abae26501c4c1d6123c0f2289111", -+ "bca098df9099b3f785a37ba40fce5f", -+ "19b827f054b67a120f11efb0d690be70", -+ "b88d32a338fd60b58570fda228a121113b", -+ "3f30143af1cad33f9b794576e078cc79062e", -+ "ffddb58d9aa8d38086fcdae07e6653e8f31dfc", -+ "abb99c2e74a74556919040ca0cd857c95ec985e9", -+ "71f13f89af55ba936f8a7188ee93d2e8fb0cf2a720", -+ "99734fdf0eef4838a7515426f4c59b800854e2fcdc1c", -+ "579b1652aa1f5779d2b0e61868af856855020bdd44d7a7", -+ "1383d4ab4a6d8672b4075d421a159f69380ff47e4bb518d5", -+ "d3fa1412712dbbab71d4c6265dc1585c8dcc73380cf807f76a", -+ "1d57868a71e7245667780455d9aaa9e0683baf08fbaf946091c2", -+ "ef80418fe7049c6251ed7960a6b0e9def0da2749781994b24593a0", -+ "ef91cb81e4bfb50231e89475e251e2ef2fde59357551cd227588b63f", -+ "d7f398a5d21c3139cff0562a84f154b6953c7bc18a5f4b60491c196b6d", -+ "0a2abc6d38f30aef253579a4088c5b9aec64391f37d576eb06a300c193a5", -+ "02dd758fa23113a14fd94830e50e0f6b86faec4e551e808b0ca8d00fef2a15", -+ "a4fe2bd0f96a215fa7164ae1a405f4030a586c12b0c29806a099d7d7fdd8dd72", -+ "7dce710a20f42ab687ec6ea83b53faaa418229ce0d5a2ff2a5e66defb0b65c03c9", -+ "0320c40b5eea641d0bc25420b7545ac1d796b61563728a4dc451207f1addeedcf860", -+ "460539415f2baeb626fad748dee0eb3e9f27221661160e13edf39d1b5d476ee0672400", -+ "02de8ffa5b9c748164f99ed9d678b02e53f4ae88fb26c6d94a8cefc328725a692eae78c2", -+ "348a61a0136436136910262ad67ef20644b32c15456d5fad6b1679386d0bea87cc1a2e2b5e", -+ "24c32966c803434d48d2283482ee8f404f598cf7a17961748125d2ed1da987039b1ce00f2ba7", -+ "bd07cb16121d3b47adf03b96c41c947beadc01e40548e0d0773e61780d48d33a0e2a675ca681a6", -+ "a35844e34c20b4b9371b6c52fac412afe5d80a4c1e40aa3a0e5a729dc3d41c2c3719d096f616f0ba", -+ "6df1efbb4567747fe98d218935612f8835852dde2ce3dec767792d7f1d876cdae0056fef085245449d", -+ "48d6094af78bd38d8f4b39c54279b80ef617bc6ad21def0b2c62113b656c5d6a55aea2e3fde94a254b92", -+ "cd6e684759d2f19083164712c2aca0038442efb5b646594396b1fccdbd21203290f44cfdecca0373b3801b", -+ "155dfbf26103c8354362663677fa27d0e1ce3487a821a2a7171014c1bd5dd071f4974df272b1374765b8f2e1", -+ "15b11067f311efa4ee813dbca48d690dc92780656bc4d4c56510523190a240180867c829a8b8b9844175a8aa23", -+ "9bc27953a17fb84d5eabe95b4ea6bc03ea450274abccfb6f3938ded8560fb59662459a11a86b0e0f32fbea6bb1f8", -+ "03b78fb0b34fb8662accdf350a6be75ace9789653ee4375d351e871f6a98ac5e782ca4b4a717665d25e49a5ae25d81", -+ "687e9a6fda6e2ce0e40e4d30fef38c31e3513d2892bbe85c991fc3715947e42bc49bcd079a40ed061c2c3665efe555ab", -+ "f3886027d2049a8909e26545bd202d6a6fa2a6f815d31c7d520f705a81fa606dd695369c37aee4fa77dc645e9b05813ceb", -+ "e4a412ccd20b97797d91ccc286904fcd17c5afe8bed0618f1af333c052c473cd327637d951c32e4af047106036a3bc8c1c45", -+ "92f4b8c240a28b6238bc2eabadaf2ff3c4bfe0e6c61268ace6aebdeb0691450caea4287db8b329bde96af8cdb8a0fe2f57ef2d", -+ "e506834b3445e1a9a9b7bae844e91e0834512a06c0dc75fa4604e3b903c4e23616f2e0c78b5cc496660b4a13064bb1138edef4ff", -+ "27031955a40d8dbd1591f26e3c26e367a3c68f8204a396c6a4ba34b89672896d11276966a42bd516716f35ed63e442e116dbcf35da", -+ "646b1635c68d2328dddd5ac26eb9877c24c28390a45753a65044c3136ae2fe4fb40d09bf555271646d3dceb1ab1b7c8d8e421f553f94", -+ "f6171f8d833743bdee7cc8f8b29c38614e1d2d8d6a5fff68bec2c0f4dd463d7941ff5c368e2683d8f1dc97119bde2b73ca412718bc8cb1", -+ "45db1c478b040aa2e23fb4427017079810775c62abe737e82ec0ef8dcd0fc51f521f29fe6412fff7eac9beb7bcf75f483f3f8b971e42454b", -+ "500dab14687db3ca3dde9304af5f54194b37bdf475628af46b07bfbf6bc2b64ecef284b17f9d1d9be41794699bc0e76c2878b3a55730f7142d", -+ "31bba2efc7b3f415c3f031d4c06bb590ae40085ad157370af30238e03e25a359c9e133212ed34b7a006f839173b577e7015a87fdff2270fafddb", -+ "0600b3fb4b5e1ed0c8b2698ac1d9905e67e027390764821f963ad8d2b33cbc378b9c25c3ee422992d22b760222ed5697be0576d73938ae9d634ed7", -+ "4c0ca4f177d132594a4c613bad68da24c564efa3b4da0d0a903f26534a2e09f8d799d10e78f48ccdb0203954a36c5cf1bf24c076632c2b022b041200", -+ "97aacf2e1b013677b2e14084f097cb1e64d7b3fa36f097e189d86dc4a263bcc46817cd1ee6ff0c7ccd9acef63201cdc0e36254e19204a7388643bb571f", -+ "71fd6846ce7adb0843d6063546a16b79b54ad6c0f018a479a45817624fa221f63525084860559d1a0679c8d89a80701c62743ec2da8419d503f8f0cd7946", -+ "f73dfb046def3362d6de36077dae2cee2587fe95fe0800548bb7d99737897096ba59052e0dadcc1fb0ccb5535391875328637a0376a43a4d89366758dfe3e2", -+ "ec470d0aa932c78c5bcf86203ec0014314114765fa679c3daef214f883a17e1b4ca12f44433772a6e4ef685c904b2fc35586c6bd88f325b965968b06d808d73f", -+ "cf601753ffa09fe48a8a84c37769991e96290e200bbaf1910c57760f989bd0c72e6128e294528ee861ad7eee70d589de3cf4a0c35f7197e1925a64d0133628d87d", -+ "f15413f7d6fc54bb55829f698da92ee42fcf58dde1aa1bd07d438ecdc32ad6bf2bcdbecc99f18ed43e81b33065af5a4ca29960ae50553e610c0bbf4153d580e73dbb", -+ "84b1738adb9757fb9402ef7113581291136184d7ae35fe0b6a738da6acb0889d4d5bac7a957024e3709fa80c77d3859871ed1aa25cf488e438a2d24cfadce6008761dd", -+ "e02814bb81f250c1835a05108396b74c7878e737654bb83155e241774d04e639bbc571b413cd9349092f926c8a149a53cd33e9b63f370b6d460e504199d2e7d849db6cbe", -+ "aeee4a789956ec0913592c30ce4f9c544894da77ba447c84df3be2c869100e4df8f7e316445d844b31c3209abcc912f647735fd4a7136c2f35c6fda5b2e6708f5ca951b2b0", -+ "8cfd11ca385de3c843de84c830d59278fe79b70fb5ddbfbfc1ddefeb22c329ef2f607d1d1abbd1cd0d0cc7c5d3ed922add76aadca0d2f57b66cb16c582b6f18f60aee2f7509b", -+ "852e5ce2047d8d8b42b4c7e4987b95d23e8026a202d4567951bbbd23111e389fe33a736318546a914d2bddedfbf53846036ad9e35f29318b1f96e33eba08f071d6dc665149feb6", -+ "f225c23164979d0d13874a90ee291627e4f61a672a5578506fd3d65a12cb48a182f78350dc24c637b2f3950dc4882a5c1d5d5bad551c6f3e0093aa87e962bea51566af3791d52d65", -+ "5f33864d882455f8ef046aed64e2d1691e5c1555e333b0852750592e6f00d3b5ec941d0c00e99629612795d5870cf93c984b45e4464ba072a34903b400a42824ac13da28c7c1cb1959", -+ "7baaee7c3eb68c18c5ae1d45ba381803de34e36a52e2d7ccc9d48a297273c4d8644b473195bc23005f7a4f5ca790b1fa11f6a96e585e635513f11745dd97a69c1222204ab28d3c7735df", -+ "d0a2a3fc450ef9af7ae982041feb2842901026467d87839c33b4a9e081ea63d5be60ae99ca6e42393ded45255b8f42886f87ba0310572d9f0d8b5a07ff4b6bae1f30559a844983cc568560", -+ "3aa4164462b3e7044c35b08b047b924790f6d5c520b1df4305b5d41f4717e81f0cd4bccb9a5a6594773832b8707443adde4047caaed2293f92234df257df54ed275a9658fab483d0576d33a9", -+ "c8b4239fd7f1b893d978268f77f6505b5775d89090374322d40083b0f4c437423f670ca213f7fe05c61069725da2561646eefaea597ac48e293fbad44c2872046857e56d04a426a84008cefd71", -+ "f94839a7024c0a16971271b6727c081770110c957b1f2e03be03d2200b565cf8240f2873b0426042aaea996a1784fadb2b27f23bc1a521b4f7320dfbed86cd38d75141365ba9b443defc0a3b4078", -+ "8af934fdc8b3376ca09bdd89f9057ed38b656bff96a8f8a3038d456a265689ca32036670cb01469cc6e958cc4a46f1e80d700ae56659828a65c0456b8e55f28f255bc86ce48e44377bf1f9970b617d", -+ "ada572989e42f0e38c1f7c22b46bb52a84df8f7b3b773c9f17a5823e59a9725248d703efb4cb011abc9474e8e711666ed3cfa60db48480a8160615dfabad761bc0eb843d2e46299c59b61a15b4422fdf", -+ "b11f1ea52a7e4bd2a5cf1e234b7c9eb909fb45860080f0a6bdb5517a37b5b7cd90f3a9e2297f995e96c293189b807a7bf6e7633bebbc36674544db5f18dd33020aeaf50ee832efe4d3d053873fd31ce3b9", -+ "e54b006cd96c43d19787c1ab1e08ea0f8922bdb7142e748212e7912a1f2c0a4fad1b9f5209c30960b8b83ef4960e929b155a8a48c8fb7ce4326915950cede6b98a96b6f1ecb12715b713985dacd1c1180413", -+ "ee2c2f31a414ccd8f6a790f55e09155fd50aac2a878f9014f6c6035cae9186f90cdef0b7adf3e207c3d24ddfba8cd321b2e9228b02a1182b6973da6698071fce8cc0a23a7bf0d5aefd21ab1b8dc7818549bba3", -+ "6d6810793bad6c7efe8fd56cac04a0fb8717a44c09cbfaebce196a80ac318c79ca5c2db54fee8191ee2d305b690a92bd9e2c947a3c29342a93ac05796484638787a184e4525e82aeb9afa2f9480caebb91014c51", -+ "91e4694366cff84854872667fd168d2d42eca9070cdc92fca9936e8361e7266931f418450d098a42686241d08024dd72f0024d22ba644bd414245e78608942321ff61860ba1245f83c88592dc7995c49c0c53aa8a9", -+ "608aa620a5cf145f4477694407ccd8faa3182465b29ae98d96a42f7409434c21e4671bcae079f6871a09d8f2965e4926a9b08277d32f9dd6a474e3a9fb232f27fc4235df9c02abf67f7e540ca9ddc270ee91b23a5b57", -+ "c14f75e92f75f4356ab01c8792af13383e7fef2ffb3064de55e8da0a50511fea364ccd8140134872adccad197228319260a7b77b67a39677a0dcdcadfb750333ac8e032121e278bdcdbed5e452dae0416011186d9ebf29", -+ "03fcb9f6e1f058091b11351e775184ff2cd1f31ee846c6ea8efd49dd344f4af473f92eb44eba8a019776f77bb24e294aa9f962b39feecf7c59d46f1a606f89b1e81c2715ac9aa252e9ce941d091ffb99bb52404961794cf8", -+ "11e189b1d90fcfe8111c79c5351d826f5ec15a602af3b71d50bc7ed813f36c9a682520984ae911669d3c3036223a53176794c7e17929efab2b1c5b500f24f8c83d3db5d1029c5714c6fd34eb800a913985c218071677b9885c", -+ "69f8f5db3ab0321a708ab2f4234645dade6bfda495851dbe7257f2b72e3e8378b9fa8120bc836b737a675271e519b4712d2b56b359e0f2234ba7552dd4828b939e0542e729878ac1f81b6ce14cb573e76af3a6aa227f95b2350e", -+ "be734d78fae92cacb009cc400e023086bc3a3a10e8ca7cb4d553ea85314f51383660b8508e8477af60baf7e07c04cc9e094690ae12c73e5f089763201b4b48d664b94b4f5820bd1540f4a84100fdf8fce7f6466aa5d5c34fcbab45", -+ "d61b77032403f9b6ea5ad2b760eb0157545e37f1712ec44d7926ccf130e8fc0fe8e9b15570a6214c3899a074811486182b250dc97ebdd3b61403614d935cd0a61c0899f31b0e49b81c8a9a4fe8409822c470aacfde229d965dd62f51", -+ "c31bd548e36d5fae95ed8fa6e807642711c897f0fcc3b0d00bd317ed2bca73412064618c6a84a61c71bce3e963333b0266a5656571dcc4ba8a8c9d84af4bdb445c34a7aef445b15d77698e0b13c436c928cc7fa7acd5f68867e8132993", -+ "9903b8adab803d085b634bfae2e109dd247a7d6249f203403216d9f7410c36142df8fa56fb4d6f78136eef5817bad5ea3608439bb19336628c37d42db16ab2df8018b773baedafb77278a50926370b48bd81710203c7abc7b4043f9a1751", -+ "4dadaf0d6a96022c8ce40d48f460526d9956da33260e1770315ead420da75b122c762762aa3ddc1aef9070ff2298b2304cf90443318b17183b60778f3859b141053e5827decfff27ff106a48cfdb0371d0ef614fc7400e860b676df3176d1a", -+ "314dda800f2f494ca9c9678f178940d2284cb29c51cb01ca2019a9bede0cdc50f8ecf2a77e238b884867e78e691461a66100b38f374c4ccac80309641533a3217eca7e6b9a9af01c026201f0afaec5a61629a59eb530c3cb81934b0cb5b45eae", -+ "4658b7500951f75c84e4509d74047ca621009835c0152f03c9f96ca73beb29608c44390ba4473323e621284be872bdb72175628780113e470036265d11dfcb284ac04604e667f1e4c1d357a411d3100d4d9f84a14a6fabd1e3f4de0ac81af50179", -+ "491f877592837e7912f16b73ee1fb06f4633d854a5723e156978f48ec48fbd8b5e863c24d838ff95fa865155d07e5513df42c8bb7706f8e3806b705866475c0ac04bbe5aa4b91b7dc373e82153483b1b03304a1a791b058926c1becd069509cbf46e", -+ "231034720c719ab31f7c146a702a971f5943b70086b80a2a3eb928fa9380b7a1ad8773bfd0739142d2ad6e19819765ca54f92db5f16c1df5fa4b445c266215a92527bd4ef50ed277b9a21aee3fb7a8128c14ce084f53eac878a7a660b7c011eb1a33c5", -+ "3366860c77804fe0b4f368b02bb5b0d150821d957e3ba37842da9fc8d336e9d702c8446ecafbd19d79b868702f32405853bc17695873a7306e0ce4573cd9ac0b7fc7dd35534d7635198d152a1802f7d8d6a4bb07600fcdaacfaa1c3f40a09bc02e974c99", -+ "ccbbbe621f910a95835f5f8d74b21e13f8a4b03f72f91f37b5c7e995aa3cd5539508d5e234e77a4668a42c239b2d13ef0e55ecf85142055e3f8a7e46320e21324a6b88e6c823ac04b485125c2aa59b61476481208f92ea4dd330cb18777c1cf0df7cd07893", -+ "87faf0e49e7e5ab66ee3147921f8817867fe637d4ab694c33ee8009c759e7d707f44c69c1b9754e2b4f8f47b25f51cd01de7273f548f4952e8efc4d9044c6ea72d1d5857e0ffeb3f44b0c88cb67683401cfb2f1d17f0ca5696641bef28d7579f68d9d066d968", -+ "38c876a007ec727c92e2503990c4d9407cea2271026aee88cd7b16c4396f00cc4b760576adf2d683713a3f6063cc13ecd7e4f3b6148ad914ca89f34d1375aa4c8e2033f1315153189507bfd116b07fc4bc14f751bbbb0e752f621153ae8df4d68491a22430b309", -+ "87d636a33dbd9ad81ecd6f3569e418bf8a972f97c5644787b99c361195231a72455a121dd7b3254d6ff80101a0a1e2b1eb1ca4866bd23063fe007310c88c4a2ab3b49f14755cd0ee0e5ffa2fd0d2c0ea41d89e67a27a8f6c94b134ba8d361491b3c20bacac3d226b", -+ "b021af793badbb857f9a353e320450c44c1030fce3885e6b271bcc02e6af65fdc5be4dc483ff44bd5d539ed1e7eb7efe3001252e92a87df8227ace601047e101c871d29302b3cb6c6f4639078afc81c4c0f4c2e04688612ecf3f7be1d58ea92894a5dab49b949f2089", -+ "c5c1f2fbf2c8504a686b615278fc6221858d401b7fe790b75fb6bca6885cdd128e9142bf925471ee126f9e62d984de1c30c9c677eff5fdbd5eb0fa4ef3bff6a831056cea20fd61cf44d56ffc5bda0e8472ecdc67946d63c40db4ba882bc4dfa16d8ddac600570b9b6bf3", -+ "88f8cc0daeaeaea7ab0520a311dff91b1fd9a7a3ec778c333422c9f3eb0bc183acc80dfefb17a5ac5f95c490693c45666ec69234919b83244003191bad837aa2a237daeb427e07b9e7aa6ca94b1db03d54ee8f4fe8d0802cb14a6599005eb6326eefe5008d9098d40aa851", -+ "2eb6b1a58e7fe39ff915ac84c2f21a22432c4f0d260380a3f993310af048b11647f95d23adf8a746500833ee4e467fb52ea9f1039519fa58bcb0f1d0151558147b3c92b83730aba0e20eeeea2b75f3ff3ad79f2f8a46cbbadb114a52e32f018342aeeaf827e03ad6d583bbce", -+ "3ba7dcd16a98be1df6b904457709b906cbf8d39516ef107006c0bf363db79f91aaae033466624d30858e61c2c368599963e49f22446e4473aa0df06e9c734e183a941510d540536377072334910e9cef56bc66c12df310ecd4b9dc14207439c1da0ac08bdd9be9f2c840df207e", -+ "a34a7926324ea96867dac6f0dba51d753268e497b1c4f272918c7eb0e34120be65b7b5ba044d583141ec3ea16fcedae6197116b16562fb0706a89dc8efd3ba173ccd0fd7d84d480e0a3dda3b580c326aa1caca623879b0fb91e7d173998889da704eda6495023b5ad4c9ad406298", -+ "5ef97d80b90d5c716322d9ba645a0e1b7a403968258a7d43d310320f60f96235f50e9f22cac0ad239636521fa0607d2f471051b505b371d88778c46fe6787d47a91a5bec4e3900fe6ed22918226fc9fbb3f70ee733c369420612b76b5f55988d757c891d7005d17ee55783fe506202", -+ "140d2c08dae0553f6a49585fd5c217796279152b2e100ebde6812d6e5f6b862b2a3a484aed4d6226197e511be2d7f05f55a916e32534ddcb81bdcf499c3f44f526eb515cc3b6fa4c4039ad251253241f541558bba7413ca29318a414179048a054104e433c674ca2d4b3a4c181878727", -+ "29fdfc1e859b001ee104d107216b5299a792d26b2418e823e0381fa390380d654e4a0a0720ba5ff59b2ff22d8c4e013284f980911dcfec7f0dca2f89867f311ced1ac8a14d669ef1114504a5b7626f67b22ecd86469800f1575543b72ab1d4c5c10ee08f06159a4a3e1ae09937f12aa173", -+ "52dfb643832a598a10786a430fc484d6370a05356ee61c80a101dbbcfac75847fba78e27e537cc4eb918eb5ab40b968d0fb23506fee2ad37e12fb7534fb55a9e50902b69ceb78d51db449cbe2d1fc0a8c0022d8a82e2182b0a059035e5f6c4f4cc90278518e178becfbea814f317f9e7c051", -+ "d32f69c6a8ee00ca83b82eaf82e312fbb00d9b2f6202412a1ffc6890b4509bbbeda4c4a90e8f7bca37e7fd82bd23307e2342d27aa10039a83da55e84ce273822740510e4ec239d73c52b0cbc245ad523af961994f19db225212bf4cc160f68a84760233952a8e09f2c963be9bb1d71ca4bb265", -+ "d1e603a46aa49ee1a9ded63918f80feca5fc22fb45f659fd837ff79be5ad7faf0bbd9c4ba91628ee293b478a7e6a7bd433fa265c20e5941b9ea7edc906055ce9799cbb06d0b33ae7ed7f4b918cc082c3d4a1ac317a4acec175a73cc3eeb7cb97d96d24133a29c19375c57f3a4105519846dd14d4", -+ "b45ac88fac2e8d8f5a4a90930cd7523730733369af9e39bf1ffb833c01108952198301f4619f04b9c399fef04c214bad3358999967c474b67a7c06457a1d61f9466489ed5c0c64c6cdc83027386d6263491d18e81ae8d68ca4e396a71207adaaa60997d0dca867065e68852e6dba9669b62dc7672b", -+ "d5f2893edd67f8a4b5245a616039ffe459d50e3d103ad4675102028f2c497ea69bf52fa62cd9e84f30ae2ea40449302932bbb0a5e426a054f166fdbe92c744314cc0a0aa58bbc3a8739f7e099961219ec208a8d01c1ae8a2a2b06534bf822aaa00ca96218e430f0389c69c7f3fd195e128c38d484ff6", -+ "37279a76e79f33f8b52f29358841db9ec2e03cc86d09a335f5a35c0a31a1db3e9c4eb7b1d1b978332f47f8c3e5409d4e443e1d15342a316f442e3bfa151f6a0d216df2443d80cbcf12c101c51f2946d81161583218584640f4f9c10de3bb3f4772bd3a0f4a365f444777456b913592719818afb26472b6", -+ "a46d252a0addf504ad2541e7d992cbed58a22ea5679980fb0df072d37540a77dd0a1448bdb7f172da7da19d6e4180a29356ecb2a8b5199b59a24e7028bb4521f3281313d2c00da9e1d284972ab6527066e9d508d68094c6aa03537226ef19c28d47f91dddebfcc796ec4221642ddf9de5b80b3b90c22d9e7", -+ "060c18d8b57b5e6572dee194c69e265c2743a48d4185a802eaa8d4dbd4c66c9ff725c93667f1fb816418f18c5f9be55e38b7718a9250bc06284bd834c7bd6dfcd11a97c14779ac539629bcd6e15b5fca3466d14fe60d8671af0fb8b080218703bc1c21563b8f640fde0304a3f4aeb9ec0482f880b5be0daa74", -+ "8f2f42bc01acca20d36054ec81272da60580a9a5414697e0bdb4e44a4ab18b8e690c8056d32f6eaaf9ee08f3448f1f23b9844cf33fb4a93cba5e8157b00b2179d18b6aa7215ae4e9dc9ad52484ad4bfb3688fc80565ddb246dd6db8f0937e01b0d2f2e2a64ad87e03c2a4ad74af5ab97976379445b96404f1d71", -+ "ccb9e524051cca0578aa1cb437116a01c400338f371f9e57525214ad5143b9c3416897eae8e584ce79347297071f67041f921cbc381c2be0b310b8004d039c7cc08cb8ff30ef83c3db413f3fb9c799e31cd930f64da1592ec980cc19830b2a448594cb12a61fc7a229e9c59fe1d66179772865894afd068f0942e5", -+ "3eb5dc42172022ab7d0bc465a3c725b2d82ee8d9844b396913ceb8a885323dbbbf9ef4ed549724cc96d451ea1d1d44a8175a75f2a7d44bb8bfc2c2dffed00db0328cfde52bf9171f4025770abbe59b3aefd8151c480bafa09f613955fd571e5d8c0d4936c670d182cf119c068d420ded12af694d63cd5aef2f4f6f71", -+ "20ea77e58e41337ad63f149ed962a8210b6efa3747fe9bea317c4b48f9641f7145b7906ed020a7ae7d2ee59435392edc32aee7eff978a661375af723fbd440dd84e4a152f2e6ef66f4ab1046b22c77ac52717de721dfe39aa8ba8cd5da27baca00cc1fffe12c52382f0ee83ad1418f4c6a122effaf7471e1e125d7e7ba", -+ "95c662b835171fa23f948c3c3ed27bab9b3c367bbfe267fe65f8037a35b50cd7fc6030bfce4000425ef646c34793f0762635ae70487a0216ef7428da622be895d1b6040423246511c2370d6876a5c5d2df8bbd48fb14f787b632ad2c1f5a927fdf36bc493c1c8606accfa52de33258669f7d2d73c9c81119591c8ea2b0ef", -+ "f708a230675d83299cc43167a771602d52fa37cbc068ef9128ef60d186e5d98efb8c98798da619d2011bf4673214f4a4c82e4b11156f6292f6e676d5b84dc1b81e7cc811b0d37310ac58da1bfcb339f6ba689d80dd876b82d131e03f450c6c9f15c3a3b3d4db43c273c94ed1d1bd6d369c4d30256ff80ea626bda56a6b94ea", -+ "f8417766ce86b275f2b7fec49da832ab9bf9cb6fdfe1b916979ae5b69176d7e0293f8d34cb55cf2b4264a8d671370cb595c419c1a3ce5b8afa642208481333522005fbe48cdc700e47b29254b79f685e1e91e7e34121784f53bd6a7d9fb6369571bba992c54316a54e309bbc2d488e9f4233d51d72a0dd8845772377f2c0feb9", -+ "3479e04efa2318afc441931a7d0134abc2f04227239fa5a6ae40f25189da1f1f313732026631969d3761aea0c478528b129808955be429136eeff003779dd0b8757e3b802bdff0f5f957e19278eabad72764aa74d469231e935f4c80040462ab56094e4a69a82346b3aeb075e73a8e30318e46fdaec0a42f17ccf5b592fb800613", -+ "03df0e061fa2ae63b42f94a1ba387661760deaab3ec8ffabcaff20eeed8d0717d8d09a0eafd9bde04e97b9501ac0c6f4255331f787d16054873f0673a3b42ce23b75a3b38c1ebcc04306d086c57a79d6095d8ce78e082a66c9efca7c2650c1046c6e0bbce0b2cba27c3824333e50e046e2a7703d3328ab3b82c9d6a51bc99b9516ff", -+ "76b488b801932932beefffdd8c19cf5b4632306e69e37e6a837e9a20c8e073bcadd5640549faa4972ebd7ee55cb2425b74cb041a52dd401b1a531beb6dfb23c4cfe74bc84f034156c8f55050ca93236eb73c4e2595d9fbf93dc49e1ec9a31705359732dda73f737ec4274e5c82626dc4ec929e5e2c7a2f5f5fb666181922bd8be575e3", -+ "ff17f6ef13abc0426b03d309dc6e8eeb822300f7b87eff4f9c44140a424098fd2aef860e5646066d22f5e8ed1e82a459c9b9ad7b9d5978c29718e17bff4eeefd1a80ba48108b551e62cd8be919e29edea8fbd5a96dfc97d01058d226105cfcdec0fba5d70769039c77be10bd182bd67f431e4b48b3345f534f08a4beb49628515d3e0b67", -+ "95b9d7b5b88431445ec80df511d4d106db2da75a2ba201484f90699157e5954d31a19f34d8f11524c1dabd88b9c3adcdba0520b2bdc8485def670409d1cd3707ff5f3e9dffe1bca56a23f254bf24770e2e636755f215814c8e897a062fd84c9f3f3fd62d16c6672a2578db26f65851b2c9f50e0f42685733a12dd9828cee198eb7c835b066", -+ "010e2192db21f3d49f96ba542b9977588025d823fc941c1c02d982eae87fb58c200b70b88d41bbe8ab0b0e8d6e0f14f7da03fde25e10148887d698289d2f686fa1408501422e1250af6b63e8bb30aac23dcdec4bba9c517361dff6dff5e6c6d9adcf42e1606e451b0004de10d90f0aed30dd853a7143e9e3f9256a1e638793713013ebee79d5", -+ "02aaf6b569e8e5b703ff5f28ccb6b89bf879b7311ea7f1a25edd372db62de8e000219afc1ad67e7909cc2f7c714c6fc63ba341062cebf24780980899950afc35cef38086ee88991e3002ae17c07fd8a16a49a8a90fc5540be0956dff95390c3d37629949de99920d93096eb35cf0427f75a6561cf68326e129dbeffb8772bfdce245d320f922ae", -+ "70752b3f18713e2f533246a2a46e38a83cc36dfccec07c1030b5204cba4432700735a8cee538b078d281a2d0262110381c5815a112bb84404f55af91652bd17502dd75e4910e062943d8a736ae3eecdfdd8e3f83e0a5e2ddeeff0ccbdadaddc95391310fc657a59724f7e6560c37dc1d5bb5db40170190f04a274c864ade9687c0f6a2a48283177a", -+ "01f3c1333b44077c518cc594d0fb90c37651fb7b2442e71fc0a5611097f1cf7bcfaf11c8e0ac1b1cab54afba15bb9332df6bc64d8032368e3f686c8324b0114e0979dad78a5ccd3fff88bbe89eef89c4be586ca092addef552ed33224e85d8c2f4fba85ac7735f34b6aa5ae5299154f861a9fb83046b0e8fca4db32c1343e02676f283975f43c086cf", -+ "509283ebc99ff8d87902fa00e2d2a6fa239e335fb840dbd0fdbab6ed2d95e8275402523f7ce9a2fabd4b6c9b533288fbe914bde84365a204711d0977a7d698f4614385984dd4c137e4820035dd6737da364edff1bb62283e87a8c7ae8637314fe9b5777ec4ec21276dafedb2ad5ee1aa0ac99e34a6c01c055c8a239fd28681607f65143082cd4553c529", -+ "c17e417e876db4e123c631f7136b8a85bfd6ce66a69180d0cd5ecfd6f037bb1c7bd7908d51f2c485bf9e92c0e1799ee5f6ab834ee481f5eb1a8020205adb4d0f90126d4e7c2c859c5a5f644bdfa9c649ff4f168e834de6f9769429732099d46d0af506ab86c6fd92175159bbc05c75db8e1fa867e6030d64250008d64c857c47caec3dc8b2ffb384d0193e", -+ "950988fbe9d62a66f5f2c492bc8dc944a78eb3796ec37ba94b6a81a9d402ccad03cd8497fff74c5f4a03081c5fecec48574fecb21c1de261332c23108195d3f6a96ff8e433a1a30eda53dd5bb414973334f8cde5510ff759f7c17046cbb5acd8e8c4a6eecf2a9121ec3fc4b22c4daa72678194ce809024cd45c4ebb9ccdb6f854205cdb624f0787480d8034d", -+ "552a212c403b473741da8e9c7b916d5e5e9bcc9949021ae1ca1ed46b7d4a98addbb604d9fff56175b7e0367db26c9635fa7813653dc8d610befdd09ec41e99b192a716106f4299eec8b940863e5a59cf26cdc2cd0c3017f9b4f215812bed15f69e77edf672178e13c55580982f01fcc2fa131ec3d736a55d56504c545f4be50fee83f1263e4d3f3c877cc6242c", -+ "b00c4283dd3d9cd26e44bd97cede6c771cb14f2571b51cfdaae4309560ffd165da025a1bbd31096c3aa8286e2d6dcc3e681b8d01f2c5064ea26dfd0b5156b7a7f5d1e046c5bd1628f8fdae24b03bdf7cf7366900cc013a8cbed9d7f5937c914b08f8c27683b956e1279812d04288515333fc6aba3684dde2292951f0610649d90fe61606630fc6a4cd383649252c", -+ "f6e79457bb6d0884dd223be2cf5ae412a1ed425f1e4012f75951b096aea3b9f3581f9013bcae1aff2d3fc1e5c7e06f24af6d53c2c5c238b71c71cc670b05a7ee5204400026a5c4e5ddec3ad96771e49fae4b0f75ec58049ad9d972e5749a32d90f847f1ed2a1bab83db181e541cf5c8adb6b29ecc64dc25add491d408d3eb3ddcb013de7f5ffb6de9dd7ff300a5fc6", -+ "fe1d71e1d5efa3f712d23216ee8ee9139e66bd648b83efc02cdb4d45a28cf36759ff190a84d14d9471477abefb5aea4111110336143dd80cf81e02f268120cc07d746538f968e9876bff8358d390f5b8e7eafa61ecd236cedaf276bd61865fdd3424988201dcdeda2e3e0c33c9e3b3670125dd1049106cc6df5695fb2dca443233ff440f265bbff055483bac1e859b83", -+ "4c80163562872a965dedd8725652906156ada6e9d999027d96f49289edb92f9ef043e9d7c3377e091b27f85275499454af32317535997fb4aaeaf93565ad481ff7d45d2abddd4df4b60f71a6923ec30496c6ae534dc5427107ab4c5e656a322c7ab058d4c13ec0ebafa76576560697ac98f84aa4a554f98ec87134c0d7dca9184cf70412a324aac91823c0aca02537d197", -+ "fdd58c5ffe88665beb7073c8f4c22472f4bc9390cdd27a42622ca55978b000ab7579f795d4de0dfcaf521b8268980ef1d20277b07567985c0fd5030784ad6c32541ac24e99ab706105a2255fc32935c0fce6fdad9bb224d94ae4eae2a3ff08836618a3adf193630647bce1952b69da4de360f59da303519278bfd39b733cf66820a5e9e971b702f45998b69a0889f4bec8ec", -+ "ff38b15aba3794e2c81d88003e045ac6cbfc9f4833cdf896cefd8ac0c88674727ad9a9fcb9ef36574deea480e6f6e8691c8390ad73b8ea0eb3665c914b0d886546948e67d7987eea248b5feb52346ffdd965d5c835144c3bc63daf325e74b11267e32e58a914ae4521a668839d9445fececa49c5fba41f9e171698bbc7c6c97fa163a377a96456958d6e1d74f91ada56a30df8", -+ "f048c19328d60b4e59ed76940415b2c84c23883198bba5699efb0a1774ad5da6d15390c7b55d77d66f37448fe08107f42a5336408d5322f4b630e3275865fc66dccab39f6e13fabc133e5a441fe352d81c7cd9a25f145a6e2e2417d3b0bbc79eafcd7ad688c02011fd268dd44ac3f4f87b37a84a46fd9e9975962fba92c9a3486deb0c45f6a2e044df4bb79f0feeea432c5008b0", -+ "1b3e5fe6f113cce28a6f8d6f7809d3cec398cabffe9ff2ff10a7fec29a4ee4b54186063fd5307a2be393c9ecd75a37620bdb94c9c18da69b658579676ec90351d10dc33a7cb3b75798b1234f9f684d4a73a0fab2df3d5d6fdb1c1b1514d0935c1f2dd21486f91c2595b2f8f8a500ff443b9305270fb6f3da7961d9316d4ed6a135a31c4a3611d40e6585bbb34f498cd5b9a5d92676", -+ "740db337baa12b16897f17a85fa5685acc85e48338867f8ac9c0198dd650f5dfa7c17725c1262c72207e365c8aa45ffaab6470a0e5afefbfc3bb702a9766064f28cc8b796878dfdd3ca9d0216c14941438fc541fb5be0a13d29a996c5c985db4f630df067a5626db5dcd8df3a2bff17dc446e46e4079b8815da4318cb228c7722684e2a795a0ca56f500ea51951a6a385385d886f678", -+ "1465f2d578d167faa017fe8f763ce3cc8dc1e8371d774ed2a8803f12585296ee71a1f2253dd16b717a81f91f0f3641018a0111182b4e65d884b0a3d0292631ad807cdccc88bdeecb476e76f72b5246a630aff6e2401fa9570f85acb73ccb4e19ef04a932a03d7b7985dbe1e5bb410df517fe362321469e6f8b0e0cef6c31d7aa8ec06aa220620d66cc0e133fdee963589b12320fc9678e", -+ "80c051952fa6f3ef6af0f1759ec3e83c8eb91abee1de360bfa09e74b05af2475a0dbf8f9135aa25892919bbe0515898cfb6f88abc9e1891f2b2180bb97370f578973d55c13c35edb22ed80647c2a7e2884d1ccb2dc2f92d7b6ec5843ade13a608a31190ce965bde97161c4d4af1d91ca9962053f9aa51865bdf04fc23fa35a6fc3c8e888941263a26ed66c2dd0b29b2325dfbd1227c5091c", -+ "9c1e2a1aed6406052eed12b4495365f2f80e9c9645473f3549b607f20910bcd16dc3a4b173ac8d128129cdb7c76ebbc8e9a2a1ba0d822c66b367e790a69ac71f0a60ed4bff0e979148e3f3ee6607c76dbc572ee5ff17c27e4b52adebb4bedddff517f591a1977299c7cb01106f1453b098d29848ba3751c816215bb0d090c50f9e445b41b2c49d4eec83b92ce6c269ce835fd279e7cbbb5e47", -+ "466abda8944d0329d2975c0f2e2afc901f117887af301881f63b714f49a2f692fa63a8871fc0b301fe8573dc9b2689880cd8969e5072c57671e0633b041481dab25e65c9de404af033a11a8070c8ab70ca6d465318501afdd9940c7efbe1bb6d49581c222fad251dba4ee0a98efe22a3c4f74da05844523b30bbad6b080ac8df70a02da80bc9d477dfb869adb211e209a316d5dd1fd89a6b8f8e", -+ "0e89a873e07799ba9372fc95d483193bd91a1ee6cc186374b51c8e4d1f40dd3d30e08f7feecfffbea5395d480ee588a294b96304b04f1ee7bbf6200cc8876395d1db3ac813e1019bb68d27204e514fe4a61ad2cbd1782dca0e38b5538c5390bca626c5895b745cfca5dac636fd4f37fed9014ab46ae1156c7789bbcbb956ff7ee5ce9effa560731d26783dc6ae8bddd53a5d28133614d0ddeddd9c", -+ "fdde2b80bc7a577ef0a6c03e59512bd5b62c265d860b75416ef0ce374d544cbb4e3a5dbd31e3b43e82975090c28bc77d1bdec907aeceb5d1c8b71375b6d631b84a46153f5f1d195bfcb2af6f597a9cdc83782c5bbbb58c5188a87ebf375eee5212fa52523820a83106e8ecd52bedd60d95cd646159774389c07e1adcaa6b6f649408f33399ec6e507d61659696b3dd249996892d5986b654d94ff337", -+ "f5d7d66929afcdff04de30e83f248e69e89604daea782e1d82d8032e91a95c1d6fb2f5578f79b51be4397e4cd7cbc608ce143fdddbc6fb6c43ffdd394a7df0124353b919aeeac025f3eb11ff246c3b9657c1a947fc534ce48e18feffada8797037c6bc7e2d9a9e2e019fe65627b3feb28e446473e3bd413047a2587f0be6a103403cb3c33fdc212dca14d8e386aa511c22308e632f5f9528dbabaf2deb", -+ "332990a8dba55f977bc814436cf386ebbf10cb487a5f6ce83e13741bac670c6810284fbbe4e303547ef411e964fae82854e8c13cf56979b89ecfedd337aad78260060122d13dfbbf8497acb2066ed89e30a1d5c11008bd4d145b5ec353956310536304d8b8bba0793baec6d8f3ff49718a56e6694f8122078265cf5731d9ba61292c1219a1affb3679576d4998290aba3684a205c3469d40761a5c4e96b2", -+ "efbdff285027610f03182009c89b953f19721cfcdb8accd74bab6ec4bdf3f555ab902cb0dd91284269d140638aaabd211748aa4da3b18cddc653b57e461b9ad8491807c535c08fe97d89eb587c6af19ca152e72479626ab764e8b62da89fefc8354c75a44851f985746d78715a5a92798dac1a4222be27897b3f0aa63d596aa7378545f49b259aa8518c3def8a2ec8f7aa956c43668c8717052035a7c36b47", -+ "0eea9bb83bdc324fd21b03669aa922fbebc448e7d25e210294c07862cfa6e061731dfb67b4810633f4dbe2130d90fa1c65843af436e74219d213c4458dcac1c48ec4541fc6e3b7918ab2bc621aedda53658050900c3865ca57cd5dfa1d28576827401956d2dd8b861fa90ab11bb0b544ded9bd3d62e3278ed484e17db8f2d5dc5ea4d19a0e15134ba6986714c2b22c59c2f0e517b74eb92ce40d2f5b89e6d79f", -+ "25da9f90d2d3f81b420ea5b03be69df8ccf05f91cc46d9ace62c7f56ead9de4af576fbeee747b906aad69e59104523fe03e1a0a4d5d902352df18d18dc8225855c46fefeec9bd09c508c916995ed4161ee633f6e6291cb16e8cac7edcce213417d34a2c1edea84a0e613278b1e853e25fb4d66ff4c7ee4584e7f9b681c319c874d43502534e8c16a57b1ae7cc0723783807738a55b661e617ee285bdb8b845607f", -+ "a76b6f81372df09322098868d469fb3fb9beafc5edb32c674974ca7032966aaca5b5c9bffef87bfe626bd8e33d1c5f054f7d5acd3b91ff95324d1ae39eb905b9f2694fe5cb03486cee86d2f661a751b0e6c716a61d1d405494c2d4e32bf803803dc02dba2c06eecf6f97fb1f6c5fd10cfc4215c06d627c46b6a16da0854e4c7c873d50aa1bd396b35961b5fa31ac962575230c07c369f8fbc1ff2256b47383a3df2a", -+ "f9db613812f2259972d91b1598ffb166031b339913925ee385f03b3b35dc4b2f1ae78a3c3d99c6ff6a07be129ce1f4b8d994d24988d7fbd31f20535d36ab6bd0592cfb4f8c1ed9244c7fa8a3c46e91272a1a40c6cfcf261c5658476c59793bf1a3775086e41a0492f88a31e2d9d1ce75cf1c6b4b928b3545d838d1de6b61b735d921bcf72e4e0615e9ff969ef76b4b947026cb016e2660ba39b0c4c953369a52c210de", -+ "e601c7e75f80b10a2d15b06c521618ddc1836fe9b024458385c53cbfcedd79f3b4239598cd7b9f72c42dec0b29dda9d4fa842173558ed16c2c0969f7117157317b57266990855b9acbf510e76310ebe4b96c0de47d7f6b00bb88d06fad2c2f01610b9a686079f3ed84613ba477922502bc2305681cd8dd465e70e357534503b7cbc68070ad16d9c51de96ccf0aae1599299331c5655b801fd1dd48dddf6902d0e9579f0c", -+ "ee5ff4ca16d1bde59ffaf2d064eac9141c1d8f120ea2bda942b7956ba3effc5f1e725a3b40b0b9223a14d7a50df1681d14ca0e0eda7bb09c428fa3b2701f83a7a3e139485a118f6287d266dbc7fe68c87b35becabc7782537c79cb8165bdc40cc103d7b6d4b627fafa0e4113f92341ab90ceab594bfae20dadbfafd401684584598941f1ffb8e23dc8a04ecd15376cda6d849fe0dfd177538c62413622d172d9d46e05c450", -+ "1daca80db6ed9cb162ae24aae07c02f4126f07cd09ecee8e798fa1bc25c26c644333b63731b4ebc3f287f2318a820c32a3a55fc976576bc936f7384e2553d2891e3771ff24dd4c7f0256906460a8f12d30ed2b23583a0259cb00a9065a757d654d6e4603e7c7eb4a8426b527ae8a849d9350e9094b890367df3e8b23ad2df4d7dcce416bd8ea3badd037f53f7b07c02e5926515f196d62aeb9b8b14c863f067fc12c5dfc90db", -+ "27ff4e58a34ff1fcd66855d014ea17889a3cf0021a9fea3fabfd5b270ae770f40b5439e00c0d26bd9766f6fb0b4f23c5fcc195edf6d04bf708e5b0bced4f5c256e5ae47cc5651e51cd9fe9dc5d101439b9bc5cc24f76a8e8847c72686e2af1ce7098ad7bc104dad00c096a6d48b6453322e9cd6773fb91fb1eabd05dc5185a9aea07a2f64c6fea9897681b4428aaffe1fe5fd3e8ceb890b12169ec9d51eaabf0ca3d5ba415770d", -+ "75e2fb56327983b04f640717be8cba6fef3655b4d8e5539587d6478356ec397efaed818b8425d052778eb30ef0dee656c52c2aeab079ed496ae4441a365f2130432c87ba757e25b4511656ad15e2eff84d342331fd2814d1f1d11af65d98a424c115ba183437c0d0aa55f5c44b8685028a47d89d0d36a0f20aed510c366ab338f074a941b404fb349caaec821e0850a627777cc8f5abce6b509290027a2a28ff1db62a5ed2f95fc6", -+ "c6ae8b6a060917cd498aa7874ad44baff73efc89a023d9f3e9d12c03d0b7f5bcb5e24e1bc2ab2f2c67b9a9d36ff8beb51b5affd4a3510361001c80642955b22ea4bf28b81a5affe5ecdbabd8d17960a6af3825a4522fe76b3d720b5d06e66bff5379d7a8de1f5cc3e7bb75163a854d77d9b3949bf904b6c4e568682f0dab7f217f80da7303cfdc9a53c17b6b51d8ddff0ce49541e0c7d7b2eed82a9d6be4aec73274c30895f5f0f5fa", -+ "606c9a15a89cd66a00f26122e33ab0a08c4f73f073d843e0f6a4c1618271cfd64e52a055327deaaea8841bdd5b778ebbbd46fbc5f43362326208fdb0d0f93153c57072e2e84cecfe3b45accae7cf9dd1b3eaf9d8250d8174b3dade2256ecc8c3acc77f79d1bf9795a53c46c0f04196d8b492608a9f2a0f0b80294e2abe012dc01e60af94323c467f44c536bf375cddbb068c78432843703dd00544f4fff3eaa1a5a1467afaae7815f80d", -+ "88b383cb266937c4259fc65b9005a8c190ee6cc4b7d3575900e6f3f091d0a2cefa26e601259ffb3fd03083270eb63db1ffb8b4515ec454d12f0944f8f9f6869eedc2c5f1689766a748d74e79ad83ff6a1639aefdec6109342dead31e9cead50bcc00c5b2206e8aaa47fdd01397b141880490174141a1e6e19268378c1b54a84aba60ca711fd72f7df88e120dfea2caa140085a0cf73342f3c588b7edfb5b5e5ccabd68a32364746d92d536", -+ "dc0b293f1ba02a326743509f41efdfeeac1efc45137ac03e397a3273a1f586a0190cfb4ea96d6c13ca692a4de6de905c8338c3e29a04cbae76272f568b9d795cea5d758106b9d9cff6f80ef650d6b7c428ea3946c3acc594907fe4227ed68faf31f2f6775f1be5139dc0b4d73ed6308fa226b9077561c9e4c7a4df68cc6b819b0f463a11b9a09682ba99752c4db7aea9beac1d9279f2c2675d42b551d27aa2c1c34125e32f2f6f45c35bca45", -+ "5d801a7413311e1d1b19b3c321542b22e2a4ccbe340545d272abede9223741d9835a0fc80cc9da97a13f8bb4110eb4ad71093efba165b1edad0da01da89d86726e0d8e42ae003b4b50297d233c87da08406f0e7fc58ba6da5ee5ba3d2d7142cbe6632734eb2e7b7863c15cc82198ee8f9a0ae0b7f93bdbda1ed269b3824d5d3c8e78513815b17a4c0cc8c9706b9c77423a309ae3fd98e1e05cdbe9e2577834fd71f964301b10b66c316a2d8f2c", -+ "2fd32a2bc15a9e96a100624404fd0a4e54ba9f8c0543d8ccf7c5c2e35f5e8c3c11dfd497320aa903900a4ca55a2b323b3ac4a7cfcd01bf0b448db8829072bee6b77c3d7bec2e1d8b414d907288d4a804d2379546ef2e2dc628269589164b13fceb32dba6fd5d48a956ce0b5c3eb28d894a95af58bf52f0d6d6cbe51317152744b4ccfc918ed17fa6856478d580b389016b772e1d02e57d2217a204e25361d91d4845a3fa20fefe2c5004f1f89ff7", -+ "f537b437662759bef8bd64368536b9c64fffbddc5e2cbdad465c3966b7f2c4bc5b96767ef40a1c144a4f1cd49edc4cc5b57e7eb30d9b90108f6fd3c0dc8a8808b9e0bd13aa3d661c4863637c5e4ba286553694a60bef18801299ae349df53a355051dcc46a7d003c4aa613808f430e9db8ca7dfe0b3f0a4c5ab6eb306aeb53e11a01f910064fbe6ca78b2a94fac34a2602f73de3f275953e13ff5c6bb5c39b82321ead17ec0f8ecc479e6afbc926e1", -+ "1dd9fb7d5b5d5074971e69300720014deba6fbdb942bd29704cdfcd40fa5281d2a1b9f5b776183e03ff99c29587f10e8d325cb49c5c93e94f5132741b92c4086eec1374dea5c1e772cbb230c7b31f3e962eb572be810076bdb926b63732522cdf815c3ab99bbc164a1036aab103cac7b823dd21a911aec9bc794028f07b7f839bae0e68211286441f1c8d3a35b281fd321312577bbda04f643ecb2a74ec4527bb5148dbccbeba749f5ea19b6072366ba", -+ "5bd63737449de2d20ca63943953338ecf4cdd6cd0a726241adb04376385a809cc6ba0f3482a310746fbc2cd5eb214f03a14cdc548777fb0d048d659cd75a962e490c4fe47affc2430a34b10275e4c76752a115aae3a24d4fb4fad89ce4d79d65de10292f3490bfdaeabfae08ed51bda6ec8230e66cb07ddbeec26e3ef68dd71c852900659fcf0c963f4574ffe4626a33db9abf0873dde68b21138498b81e8cc44d354be4073615889a7ddff633b5447d38", -+ "a683ec8250506571f9c640fb1837e1ebb06f123e745f95e521e4ea7a0b2b08a514bbe5bdfd316903d1d6a05f5a143d94dab61d8a3a146ab40b2d6b72df2f0e945875a8aa7051ed115975f6f1567cfcbf04c5e11e3a7027b8e179ba00739181ba10b028e3df7259d0712f4a6cef96469ff737865b85fee2c2db02a6423e32505381e18a1e0b4ce3c7998b8d6b1b5e09c3a280b85486d0984c9e193b0ad2043c2bc4ad04f5b00a73956715937eebf6b3e27afc", -+ "4df9d160b8e81c42930c48956fcb46b20b6656ee30e5a51dd6317876dc33e0160d31280fc185e58479f994991d575a917073b4439919c9ac49b6a7c3f985211d084c82c9d5c5b9a2d29c5699a22e79de3958d7b0e856b9aa97493cd4563aaa04fa3977a9bb89e0bc06a82296bdc76d20c8d393770176d648712454305fdfcf4e117d05acb5a5b006a9f8d0dc66dca708c4e4103ca825d2331750685c44ce3d9b3e753455580f4d6ac4533edeeb02cebec7cc84", -+ "67bb59c3ef5ee8bc79b89a673e331e581215076cc36b68f517ca0a74f74efafe9dcc240e6d8ca4b21019c27d6c9289f4419b4f218eeb39eb741c5ebebfe0ed2f6faeec5e8c477acf71907990e8e288f4d4049111779b0635c7bbec16b76493f1c22f645745fdac2b383679fee573e4f47af45ee08d84f63a5ace4ee1c06fa41e2e6e14b7bc392e38426813087a3a461efc62ed1941dc8f1728a2bdc04fde72a0b786558783c84abd4bd100e4926979a0a5e707b1", -+ "d341147169d2937ff2373bd0a9aefa77968ec8f0d993c6f9881eb174a1911e05cdc45993cb86d149a754bbe321ae38363f9518c50dd3faf087ffeeeb6a058b226ccab7858c00ba6de0e8f4d034b1d27508da5cc473f3a413189ee6fd912d7750486912944d4dc34405ce5ccc3885fb0aabcb922bcfa9081d0ab84c288022bd501235a835eb2e1124ed1d48fd4f8682da8e7919321031326502273375625c4e3a7282b9f53452195e53c6b4b57cd5c66f621bed1814", -+ "27e7872a54dfff359ea7f0fca256983f7600236e716e111be15a1fe72eb66923ea60038ca2953b0286447dfe4fe853ca13c4d1ddc7a578f1fc5fc8598b05809ad0c64a4363c0228f8d15e28280837a16a5c4dadab681e28968ae17934639fbc124bc59212138e494eecad48f6546c38366f1b7b2a0f56f579f41fb3aef75dc5a0958b25deaa50cb7fd1c69816aa9a51874a98e57911a33daf773c6e6166cecfeec7a0cf54df01ab4b931984f54424e92e08cd92d5e43", -+ "13dcc9c2783b3fbf6711d02505b924e72ec6736131159017b966dda90986b97522bf52fd15fc0560ecb91e2175322334aaaa0097e1f3777c0be6d5d3de18ed6fa3444133486068a777443a8d0fa212ca46994944555c87ad1fb3a367db711c7ebd8f7a7a6dbb3a0207de85851d1b0ad2f4149bdd5a5ba0e1a81ff742df95edee850c0de20e90dd01753137cb8f2c64e5e4638ceb893a3879ae2c049aa5bce44d56bf3f325b6c5029b2b8e1b2da8de7d4e48ca7d8f6fbdc", -+ "9ca875115b109eab538d4ec7023600ad953cacdb49b5abe263e68b48eafac89a15e803e838d048d9625972f271cc8f36344bed7bab69abf0bf05979a4cfff273b82f9961626509765fcb4b4e7fa48212bcb3ab2b1f2dd5e2af768cba6300a813514dd13e4d269e3d36548af0cacdb18bb2439ec9459f6d847d39f5598304ec46a26d75de1f9f0c2a88db915bd26e45e1f1e68c5b5b50d1890e97a3803c36755f026863d14176b8b57f42e91d3ff37787f9b38e333e9f0433", -+ "ec006ac11e6d62b6d9b32ebe2e18c002353a9ffd5dfbc5161ab887770ddd9b8c0e19e5321e5bc105add22e473050b71f0399327c7eba1ef809f8667c1f4e2c7172e10e753705e9a083f5bce88d77521225ecd9e89f1e1caed367fb0275dc28f620fbd67e6b176c9ae5d2659e6ec662116c9f2bbca3a93043233a4861e0688db6dc1800f752c5d58aa5033c250c891d9126e534ed921a9026eb333333fa8292059b8b446f336ca6a0cb4c7946b6aea3831653122f154a4ea1d7", -+ "23deadc94481ce28188f3a0ca3e85431964cb31b60fabf381e6bd45ef0332bd4dde774b0281d317dc2e7d0c298fcf8625fa734126968df8b68ef8a35c325d84ba4fc53936ff3ffdd8838d2a8cabf8a9cac54aa444ed9875944e55994a22f7fa8538b1e983b57d9215fac5c0052029644044e790ce2f5044655608c1d7ad3bb862203ba3aba3b526606f273d342ed5721648e3f600942d3f7546f679161436389d879dd8094e1bd1b1e12cde15cd3cda4c30a40835665e4e5cf94", -+ "94701e06340114f9cf715a1fb659988d33db59e87bc4844b1500448960af757b5282f6d52967a6ae11aa4ecfc6818c962b084c811a57724f5d401191567f24ce917e4f8c3963474fdc9d2c8613c16f62446448b6da6eeae54d672825ed7606a90e4611d0e318ff00566862c955b636b5e81fec3362e8672ad2a6d222a515cf410482836deba092a51a4d464dfbbab35c50a33437ac16a88256e9e23ddd3c827cc58d3e5000ee90b12e4c5175c5733662d4848ae0d406c2f0a4f498", -+ "735b0758d5a331b2304f01081172eb95ae4115de651b1a6693c5b9543de33df25d9f421dbaeca033fc8bff57313b482778005aa9fdcbca65c643da2f3320e34197868eec3848ff3c70d7ac7d910fc332e9a359f892ae01641be253013b554a0d3f249b3586b1857e5a0f9482ebd91432a852b221f4287a6e81ed24e8064645d5b28ab9a13b26cc1420ce73dbc47b31acf8a871601022ce23bc443b1222ce9a037a2fe5226295feb4efd4fd671338f459ae146032697cf82fc55c8fbf", -+ "c48d94f14549352790079fee69e3e72ebaa380510e3581a0824066413e7044a36ad08affbf9b52b21963d2f8e092ff0ac1c973c423ade3ece5d3bca852b894675e8173290529226939c24109f50b8b0d5c9f762ff10388833d99bea99c5ef3ebb2a9d19d2231e67ca6c9056d8834730605897426cd069cbeb6a46b9f5332be73ab45c03fcc35c2d91f22bf3861b2b2549f9ec8798aeff83ceaf707325c77e7389b388de8dab7c7c63a4110ec156c5145e42203c4a8e3d071a7cb83b4cd", -+ "553e9e0de274167ecdd7b5fc85f9c0e665be7c22c93ddc6ec840ce171cf5d1d1a476743eb7ea0c9492eac5a4c9837c62a91dd1a6ea9e6fff1f1470b22cc62359474a6ba0b0334b2739528454470f4e14b9c4eeb6fd2cdd7e7c6f97668eebd1000bef4388015630a8332de7b17c2004060ecb11e58029b3f9575040a5dd4e294e7c78e4fc99e4390c56534a4e933d9a45460f62ffaaba25da293f7765cd7a4ce78c28a85013b893a0099c1c128b01ee66a76f051dc1409bf4176e5afec90e", -+ "dea8f97c66a3e375d0a3412105ed4f0784f3973ec8c57b4f553d3da40fd4cfd39761de563ec96a9178804641f7ebbee48caf9dec17a14bc8246618b22e683c0090259e3db19dc5b6175710df80cdc735a92a990a3cfb166461ae713adda7d9fa3c4cf9f409b1467f3cf85d2141ef3f119d1c53f23c0380b1ebd728d7e932c535965bca41a414b6ea5bf0f9a381e098d282a554a25ce41980d7c7be75ff5ce4b1e54cc61e683f1dd817b8e2c1a430d7f895e5e7af13912cc110f0bbb95372fb", -+ "9dfda2e2f732867e60ed2b5fa99ab88eb82dc7a54334d02031258beef75fa4bd6962a1083b9c29e4eeb3e5ab8065f3e2fc732675b8d7705c16cfb4ef7305eb58120f1af5ddc55872a2cbde3a48661a0598f48f63e2e9aadc603545e2b6001748e3af9e86e1830af7b84ffd3e8f16679213d37cac91f07af0af02b37f5ed946ef5c955b60d488acc6ae736b10459ca7dabeacd7dabcfd656511ac913174f6d99327be59befe3e463a49afbb5235f0ce2840588c6edfbaaba00a4211c0764dd638", -+ "ddcd23e8b9dc8889b8599c721e7f8ecc2cbdca03e5a8fd5105f7f2941daec4e2906c654210bdd478374ddee43ee749a920ee91872e057a1157d384dcd111266221b3c79774476b4862fe450704ff2c5353e9a936cac87c96515c28ed4c830335a55d084cb5873c5fd2dd907f3266d8eb7bf13b6dd7cd4966982a0949efd8e428dae13daee549e01cc3c226211d6307823f742c5ef2155601a4644c46eddd603d4abd959c6d242e427768df3b1e22d87971df58a1564b38311a897c85b497a72556", -+ "39016647acfbc63fe55a74598bc1956eaf4e0cb49d532c5d8323fc6a3f15a0231597f06eafd74ad245e672bf6b21e4da503cb5bf9d15e9038ef354b38807564d91f38b4258378ccd9b9420a1562d7136196822a1291c913d83c4cd99fd8d420990c72cdc47607124de21da8d9c7f472fdcc780379f186a04da93cd87628abf323c8dadcd7fb8fbade37d7d2b5c9f9fc524ff77494c98f42f2158a6f68c906105ca9e8bb2df463863cfc1e9008d8344f55c4e3203dde6699b59812d49ce1279fa1c86", -+ "02cff7567067cbca5911664c6bd7daaf484181edd2a771d0b64566c3ab08d382e83932cdd7b4dbf86c9cdd1a4c353a511e68afb6746a507a9cd385c198246f4543d606c6149a5384e4ff54c1b90d663dc7a4b91aeac3cf716db7ca6f9a1914e3a33efe82e7ccc4215999c0b012782402db4726db1d7d1c73571d45739aa6fcb5a20eeb54a84d5f99902a8d356cbf95f34c9c28c8f2badfbc08c69233514493c0c04963268c88bc54039ab2999c7b06cba405936dfc43b48cb53f62e18e7ff8ff3f6eb9", -+ "5764812ae6ab9491d8d295a0299228ec7146148ff373241a510faee7db7080706a8dada87938bf726c754e416c8c63c0ac617266a0a4863c2582412bf0f53b827e9a3465949a03dc2db3cb10b8c75e45cb9bf65410a0f6e6410b7f71f3a7e229e647cbbd5a54904bb96f8358adea1aaa0e845ac2838f6dd16936baa15a7c755af8029ef50aed3066d375d3265eaaa38822d11b173f4a1de39461d17d1629c8df7334d8da1b6401daaf7f34b2b48d6556ae99cd29ed1073926bcda867421832a4c36c7095", -+ "4df3043cf0f90462b37d9106e67366d112e4938c4f06abae97869531af89e9feebce0812dffe71a226de5dc36be652e26ef6a4be47d9b2db5cdd43809a565e4fc0988bfe82037c505dd276b757b785203249fd083fb474a25acccc9f38dc5164ff9097e05989aa6e280739a755231f93670e7226e22046914c155bf33d135b3f736ccca84cc47ae643215a054b54b7e13ffcd7ad73cced9279dc3210b80700fcc757acfb64c68e0bc4da05aac2b6a99d5582e79b303c88a7ac4dd8ed4289516bba0e243527", -+ "bf041a11622715426c3a755c637d5f478dd7da949e50f05377bf333f1c62c671ebdbf9467d37b780c25f7af9d453fc67fafb2f065a3f9f15d4c3561eeaa73fa6c813bf96dcf02430a2e6b65da8d174d2558110dc1208bdcb7898e2670894c0b9e2c894da3b130f57a90ec8ea1bffd27a37b4da4645c546b2b141db4e2c919154dac00e78dd3eb6e4445974e3bb07905982da35e4069ee8f8c5acd0efcfa5c981b4fd5d42da83c633e3e35ebdc959bd14c8bacb52212b4334f94aa64d2ee183861db35d2d8a94", -+ "a170ceda0613adc9c3a1e427f07beacf3b16ed69fb42b6bc09a38d803f632ad2929dba215b85683b74e2feb1d18fe17d0ea0db84d1be4e2e73476917a2a4cff51d6eca7c5e82232afde00dd2286a4c20eb09800b4d5d80e7ea35b6965b9792d99e399abda8cf32174ae2b7414b9bdb9d63e148f7357635a7310b130c939593cd3479164724011966c4232142df9966f09422f34f20b30af4b640a2c6d3dd985fe0ba3dfa9083cbb9b8dfe540ff9f6c608d18481213040768ef33300d773f9890c724ead320a1e7", -+ "929477e9c2d0bbad3429a0e0de776695255013108261dc6404cb09828770e274d8bb650a50e490dfe917fc2047b0f8ee72e105927d9fa70523c727778cbf6ae876d641ad562938c870d12f2e047bb78920739dba0c3f8ce1fb77589623a5f1625f5d6ab81940c7dfc3dc3a641d82b2813629bab8282999317d6b93842334f123fb4693a9c2c9d8ba9bfc746642dfbd045cd2021b272eab7358aa954d453da53fc5392dfa7eb881f6f53809b692d27f3366595ff403289efcc691e118b4744a1147071d8909bef1e8", -+ "3e98bb14fff5bdf7db38a3960dc55ca7d02333daed8712cca13dd5bffd114636559279db72554cc0a0ee1f7e15557d77cab0f2f1131f94fe698db81be38300a856a5eca85e5cf915fb7b6f38ccd2f27350e62cc30ce10ffe835118be3d435d2342ed3d06199b7e20c8e34d68902f0ab8745bd8b7d5b863d525c1f5906d2dca598db8a0f1e67736182cac15677579c58b8c670cae1be3e3c882153b2aa2988933e579ec2d6dbb00c671da64443dfc027dee6dfc3233c99758304570a982bf9b2eb59ccd70d0b54c4b54", -+ "aa12c7fa50ffdc2811c1872e4bee15f43e6909212385c872eb489f7e06dc1787043f56126f8373bdfa4b3f61405c73dd4dfd3f40aa5cd207e8520849c26f67716a46c0989a99efff42f24e0736e327af8e607c401a1bac77341e9a78c91e35d55b2457bdd5317a405a1fcf7a2a23de68ef92b65819e8aa3807c545361dfc9fe89125123492da958dc313cb5d03cb4b192c54ac6b27fcbc498652f5ed36b587bb74942b3ad453a8d79e5ddc06ebf806dad5046b73251064582ef5777dc530f8701701761884783fdf197f", -+ "83e615cf6e17a29e63945710b548a6d9935850eec69830841e26cb6071e908bf72c87cf079ffb34c5eb1a390def72d004a9488224a18e189aa1092a0f1135712834d257a53dc1d0e2c6417d8f472ff13b181910f4c93a307420d44beec8875d5219a3160b8e921434ddf3f71d68db1c1d5c39d68edb7a604792f8b4e31ecda7895c99fc7031a5b98a22009c1da005ac8fd2da0b5d742743f5712d12fd76d11a18e487776ce21ca0d6e5ab9ca6d8c394c321b91c14e291399a642721361811a73b7392e8603a3004e7060bf", -+ "ae1a8f7bfe4b1a0fa94708921dadb2c20b938239d7b9a2c7c598528f20f49764d322ebe85a5b2ea15563cf2f2304baf55d6607c52e2e1160859dcb7af6d7856899eada0e9128a180d3de6fed9334ba52b80c5c362d5591a0ec30f86d37a399927eb1c53076a12d26775522c511c83eb5b7abc2a00bd2dfd5627a8febba53d85f9b74c4b7f0c862ddb0d9298899b646b774d6cc23e4e23ab47174fccd34499253996d5e0917210e2f6daa1685f89f2f1fdfd5509ebc38191d539ecfb54ff0f5bbe6ef36ea35d425af6462f518", -+ "1d033e06be253ab800c8176d3a9650ab2a5bcaa03e11ea95fb9ab3834b41eb0d1b2bcecfe219364c3104ef65a8d692bd77c798548b7d9a8faf7f5172db24ec7c93006d6e9839368291b8277a82c034a3731f1b2e298d6e0282ec8a7902e4f844d132f1d261d171375c646065e201849f2df73e3748d853a3122c2206aac92fea448500c5418ecfb3d80e0e6c0d51f85831ce74f6c659cc291f5348a1ef8b949f1b2a753633e382f40c1bd1b2f44748ea61127b6f568255ae25e1da9f52c8c53cd62cd482788ae430388a92694c", -+ "104bc838b16a641749dcf73c57b207ea3bcc84381170e4ca362065a3d492e892b426a1f4fd82f69461d1ce1f3aaf8fc291ea30d6667e7e1aea4c44f7d52a5fa6d34709e6658483260ff5da76bfb74e7d194ad40dcac00daf0e45e74db4bc2248100a8b256b257278c3c98f1f2e3a80cdb812352aaf4155b3a4033999fb9fe7f506994fcf3a8db31e9e5ca8ef8c2e9c6326ca5b0803724ba641950eca877fe6ed6afc2e014651c56d0e6a61eaff7c5ed0b861d4bebe42904c0a568c26aa8abb2e97da2bfb40f14eafb6bf16cd208f", -+ "5b92e4a175437d0a53eb10de2c56401720b11715a034459ebf506c3fd6534b5e817a0f09deac4bcfd353301d8d031b1331582ac09189b48e6ccea444655866c4bbd123d45ebabb774f877cf12d33b84cfca4a6a94f3f98869fcf2bbb6cc1b964c2438c2f348bcdf9001dce60a4706d20c169a040baa61cbeb0b8e58d505e6e3739ab03e110ae7efdf91347474033defbd1e86af322ec6456d3394699ca7ca6a29a70d9b10a38fe666eab2858bfe12dacb31568549c826c15af5b6fddf779954351be1872f04e53db7b3b5fbf61fd18", -+ "401cc7bd9f8227efaed70dad83fc8db3bd38efc166f0f11ab142c565c68ba9db680423a3d698b6f3476ef440051fd20b93f6a2ed045825567df5a65e3f62e4442ec396ad260a16a13a1dee46c7e8d88bdd7edf223ab76a9a787c1f4fe9925c051a4ca0e77a0e78baa29f36d193c862fd3a60653f544ea9e3f75f2f553891be8c1fb882f6a6aad118f576f3c2793efc67221b37a45ab6137434f6228cb002fc137b91fb8572c757f00736879453d64a8a868c131810ffdad9e9d028d132157ecb1da675d54047d19b27d3258c9b1bca0a", -+ "c20cf0354982ca6a19d9a4dbf78f810934db2373941a12c263adefa61a5f385c859bc47028829c531dc25ccc0004c7510e707175a102ec3c4b4c933e3f52033e67476ff5f864c446c042a21e6037f7798363d20267891b965879fde80af6b59d77862e3a229af01b7ac78b578e94bd9f9b073c38a627c1864df0083aabb17024bdab6c3c0f0f73d31d59480523a2f23b78baa0385c15f290114305d7f98786b7dbc17a8c2aad97448e8ea389e68ef71091a6a9735ac12ca5497b9171da11a93c28d3273f58b74e2e46279d3ce9d0b20d19", -+ "e2365c2754073b511f16a1881ff8a537541ca7362ae7b84223d3c7d1d49d03a37d6d05dd2b819af9705c015dacc9dda83474eb14b7d5fce6e8a8f8c58e870149338d320e5ae476da6749af45e65ffed550d225a39dc74ffd93ba7da476985d6f44e90fc8e82454496260458431804d802fe804d825f611772f9710667377adfb1a11e4275bcecb42175c515f6a9439a359824f82cc9d480954364e6693099a821ace362e6c7ecbe68be8823bb5b49b4f23ad81b64139e3b63d9d4d298a842f013ef0d91ce7915ee8f816c70ba2aa3994216f", -+ "9c43944676fe859327096f82049cf69e48b98715878400fdf2805e0d5ee642e6cc9c43739f418b701348a033c5cb96bf8702fcd2fac9be58262a843c1e4155ed8a1724b6ebf7cce659d88a95a0c54deb2d7d9574a45219b6419ee173d1d8fad3ace47c962b349abe1048565df85bbd0eb9b11698258c23598023a00fdd26573e41951452027125c6e894a97736ecd63fd15b29a55d8dd9dab7e2e18f541a2e341890a61b7c896e7dc67aa82f3479dacd4a8ec7558d40c34d9ae4060e13718d676c2450258d83de8a86e012813693098c165b4e", -+ "1c707c29582d98a0e99639211102f3f041660ca03ad0939fe3855b8c1b22d6a9b8673c93e3eabc0ab231509b2b0d73c76a290a363943d12d2ff0ea30c6dd54eda753767effe04cabb4c3966388fa4c83a1906a0f48519a5fba9aeb585e0f8c45d6123a75ebe98fd1d0272f733a3925119481a321fe7509346c05128302851ba17a137f956f184e057a305e79a148727a5926de6854eb0314d5492fd735fa773d99ea34c95ca7546bd3a3aa8e66bcc6d860cec3d35d0e2165d5fbe8be99b6e7967df6693e5a6243e94c9c4a2528ae6305cbeca209", -+ "8f1e88103ffa378f062cade0ec509bec99a5c73fb273e79dbef24abf718ac26ac23dfd2b8932038ed3cb9637b71643c161142019f45b25b4fa4c52356737a27027e805ec635154327a66bfe64efc6285cca98c34edc7fb6c0766970a545342cf840aec0a5ba1dd3c6949be4fe97b0f8c8186de07536fd9074db34d09b2f08af9dcf9424d6edbf9cd044102c0e5dc35aff78c36d079dbd2c500e19c8c985ae2abaf6b2a20716bb719754a8840ce97632116c4d0b0e3c83ccca27f11c4204b76b5d6cfe6348a9615d8e4af53500dc4c2cabf12ec8c76", -+ "b9a0c28f1a6156992c103a84655fc6e654fa6e45e45819513afa797024717c00cc195994512fd53ecd1e12dac4d2448e0c40308382312084d2111f7db147b2e6589ce6d977f6115f629508167df8f45bac98abd49f6b272bcc4fd874dd5e29fb6daceb2d727a2a892194cfb9269eda00626ac89b4e74bd29b21e9f6ef18cb69889a02d4f0a06a2e5718899c1dc3b051c2cfa29653e782f87fefa478e6465bf5ff27f8b6abdb500077aac97100bd955ec535a587d66f23354be51cd8170289344bac9451f74e8aee3639f7c09981f4885e018912324d7", -+ "456844a34ae1074246f8f71eeef2010ec8733265bed7c1cc60043d770edfa320cbd4284a94be2574337e16d27f125074ebd7e99031f7abb4547b9540a7b0b5148ef501b550dd929f3dfe39ac65519f563e9254424aaafa05b1d37c16c771882e9e25d4906ac58603da749adf686932cd73d81e2658134fe69294c7a521d257eaf2110c667fc9d6f09b52d24b93910e532184eeb96eae9d9c9750ac3c39e79367431ac1af7011172d0a8be46a31010219a0310a733068c589bfc4748f3626aa4ff8d355cc893d05111c287c9992e95ad47481a6c42d6eca", -+ "c5c4b9900b9727bdc24baa544cad5faf8340be6b3759361f53889f71f5f4b224aa0090d875a00ea7116772117dbefc3a81c6950ca7ceeae71e4ba975c50d61fec82e6d9448d3a0dfd10bb087bdf0673e3e19fa2aaa7e97eebf71f11b86034fcf5a61240c71444ac3da15ef09b27b3523d37d309e8722380f835c1aee4a767bb027ec0674040853e5b53d6a31657f51acff6d2487860becd5ce695696cfe5937f4a0217b69e01cc6facc24dfe5f5230b8692a0b718e3b3c789d682db36101795a9a5f8bbb838c3679be72f7941a1db180135347d0a884ab7c", -+ "1781df2fedd2c39137854737d054cd3ed16b0ade411e41d97888ac900fdb46d9ae26b3d2dd07e118fd57eabd0dfd03a55793c76420666444865371adffc9b2f35068a0d70f9cfda1ac27ccb4beff4ffa5b8bb8bddac843386675c38a181fd0d935d6d51b25d78e7ff4ecef27a9853c0f0d2879c395ed1c4883987d123890d04f851c3e042e1164c68c0d503de16816f4b0e554236e5f4c339ea11d01ce652f6208f78f457a2417a97c0a6a240f443262def4b6763abf53e597bf1a28f907dc7cbdc751a234ea7d75710ad5ab0c37e8e9805102a375abd44011", -+ "8963552ad1e729ead07750df599d734157aaa4bcdcac17e8eb19b4f99cdb162686ff433137aa4e8a0cc8df0053999196262115aec326cf37567d9ba4760e0ad21d5763977f1ab9b35c0fc667890fa87fc946ceb776a811b5adc69446bfb8f5d9908029dc5aa38db816e4a4e8f98e5a48cf0a01627031c5bd1ced8bc1940dcafe4ae2f1199b186468eafc07e96a89d95dc18ef0fed3eda5b58ce58f221a47ba5311313cc680367eeb058fafc7bcadce5f520b6371489d9e529278ae6ee2650a85aed82896879038bbd9aa8d685fc9528943ccf2235cdf69a86464", -+ "23ceae3008085134433f5de4b47bafe0f443d443491e6cd47b216dd2dcc3da65239515a6e6b9beb9a939ae9f1f1f5e11f88326475e0962f319d9bf75ddfb4a46e7cc3f799d7547f3c0b2e089018b75787b82ea1a7295e7411f4852f94c94170e98bb0647923b8eb7d184038e56560da46085540cbfef82b6b577c445d038f6c93fbfdfc96ab3a0191d20a57b8610efb4cc45cd95198198e6f80ac46b0601511885f650eb00992605be903bcb46cd53c360c6f86e476c4c9ca4ad052eb572bbf26eb81dd9c73bcbec137aea6ee27aa97dadf7bef733fa1555019dab", -+ "c0fd31e82c996d7edef095cccfcf669accb85a483ea9c59f368cc980f73da7202a95c5156c34192ae4ebf773c1a683c079b17ac9d08b4265b4054fcddaf6666ca50f38f1a2ef2497459a68c06837363a526e850ecfbd223f55dba67db017eadb7a9139abb5bf3854834478b838aafa16c5ee90ea52fb2f7b8db2bcefb85b06fc455c2b6c27d0af9a49dbf2f313bf2599370637393e7972b31d8bf6759f3e6115c618e672831f84d76ba1879c754144e1df4d56b1e264b1797dcb8ab165040c8d20b931071081d7f74fbff590bdc8e888e71acc6a720270da8db7c821", -+ "936fdab91fba396e4a8754a97a04ba333daadc29885c9d0c8fea3387165278f4974e468fea57f2bfd8428c4d0f010833283db73735d39de0c0cb5898d0c06c0ecd05f61098935cb6130a8da60d1a6c2ecfe420f972263fff5a631b09e81c837183c5528bb1c740b36fc39cb082f3383c2b4afb25d04ad1d1f4af63dcf26a0bf5a647cd2e35a51cc119c4dc5031f5715b3bfa1f2b92de06bdac0d670fdd30980f32c51f3936b51e5db6b95a8d36279da5faa4c4e454f2b7e54e9f488071011c7f6f9b63da260a2e46d796d36c9a9dcae88085806a10a77bbb670d475778", -+ "a55fe162b287bd6eebd6cf7e7aeea8672322d924ae42c7404ff89aedb98943f3755d2889bca488cc7000e6e9b8e7a0ef289273cd29c44cc600e330d1775e3cb767f12150e1615dca8c3f67466463a3ca993a1b788cf67a7a35b95dfff954206eb5ea1e1bf7fb06482a551625b5c9fd9a86e8414c8cf79d3a14104a153cbe04aac5172aa4c4a89349f5856c4262dd1d7317a7544c9afbbed449e7dcc2b58d9df6c9c9ed3883e42e80f5c2433550f30e73c7bce0fccdd880adc19282a392dae26a0108e7faf168cfc15937aeb046d60712603286b8ddfb27916b79242d56f1", -+ "2bd6976592408cdbc4e41dcd3ecfbb786775ddedef914d9058e6753f839fdfe15b17d549dbc084aa6cdf3befa0158aa84c5d58c5876144fd7e6c41ab7d42419d0dd353732e0e6d3fafc4f5626c07433390a4fd467197e85b5de7e2cf1c26cc575356adedcc0740008523b503df12ff571387726c5ccb280376d19cbacb1d7ce7aab8b13292c6a8b8881e949cbf6d4610d16ebba1d46cdb8d0459596e0aa683d0307bd926e14de19b9bfeaefa29d91b82248604673a455520cbb64eef3f38cfad8e126a3b1cfa1aaba53a784c8ae0c50279c0ecdab54095d36f67ace9b8ebbb", -+ "71913ae2b1c8729ed6da003c24a1d4f96e28d7faf55ca14ee0b2865282b9b61103ce6ee0b00b00aacf2081adedea5616f9dfd22c6d6d4f5907bcc02eb33edf92de0bd479794f51246d9b612b4543f6ff633c4fc83bfa6144c9d26721cdc690a3d5a8db54d8bc7873bfd32924eeb502810732b5ac2f1852bb021c401d26c39aa3b7eb09083093a9e89bf889b53383b5af61110aca1b9fdf38908c7d5a184fc5f46b3423a66a2749feb8de2c541c563987278dbd0513d99b732411012b5b75e385510de5f6839c3797dc094c9501d5f0504b06b43efb6e746f2129ca189c1da424", -+ "9d048a83294de08d3063d2ee4b4f3106641d9b340a3785c076233686dd3382d9064a349c9eaa78028d35652078b583e3f708e036eb2ced3f7f0e936c0fd98f5d0f8aa91b8d9badef298bd0c06843831279e7c0c67ca7e572f552cfdd984c12e924c08c13aeec6f7e13d161785546ebfd794b5d6a92a4744e52c4cab1d0df93b9468be6e264e8cfcc488f9c3c1817cbe501f4b9cc5999483b7433aea777226b25273a6ef2331b5f3b6db8091591e8e276015da3ef78bb2ee0526ffe23def2d8d193cbe594e8ced1f3d216fcedae2a1eb288da82e34cf98aebc28def658ee0849ae7", -+ "3251c96cbf82ee2e5264528c0b6cdfc23d20e1eb2d6441b5d62f0fd24c692a0d45a8bc8aac32884b7141ac0f4f113ec9fc7f6b4db3d696374177f9a42d602ca471275b928f639105a55b846da9ac7274cc37de8c38541f6895f94d72a81e117844b46601c201f7189b935a96e42505f2098ac985d92dfe86349a706ef6325b3c2e4060ced3c453e68ed09e043bcc75846b80118dc53530248da250fb57922d0afa53a7b2c89161aa4fa372a46b2a8e1307741cecedf585d2f998a9d496763800b6965c38a5d8aa566c709f13699c8185ab4fd8fdc8b824f4dd6d1c255b4788f50574", -+ "2de31dbc8a012254586f3229d3524fc529554e98850d30acdfc11406bba6a142029126ac165ee90b2de7509fc3571a8ee12e16b05054eb8baea879d135b39627f0d8331be3e66bc720c2096ce74e437daebf3bc53d8f2ccc228c3256d3edb6e9ae7c354a0c9350e6d663a9a30630bf9da3d96b96608a2a171ae28105714058b6c4b38a36c56561c4612c32aad25c65b7fb6faa4e4ecd44ebf9b2fad42ff9a807cda2581614fd30d41a7436069399b8d4f062a37a5bd4066a93d541fa5797a7d3e7dc9c4c40f0bbf5256f71613240f9ef128b3423eacaf428ada06b6a531f835281e4f3", -+ "07dadee629a08223dcd7ec441287b4c5e26347451d9c003e3a8496b4ea313b51126283a6720d7851e24423d9c9c818b4601247178f38a61f45fd4c8596d79529d416834226666a2c8552bbc901cc5cc3406a18fc88077fea52e1b620748553052ab7788c0d025b095b736fbe714cb3a968ec16b5917652eba2d7cf32ef3140d6c27b25d053e9786d24cd09a5306a0ef55e46201faa6196a91084267d7a7b5ca57c2efdeb2cb97d682d2a191b915553c8933f1d1b7faf0b4a1d83ef611f1e44438bc1c3d860fbfd12b5f26e5a6889a31ce26ae6a55c7a563b5816d113423ef3f25fa9befc", -+ "1d94166bb387526d519c4ce150221954da8930f66765fe6a5504e30a69962d595cfdd07a82c003843598864261f053bdb6f5086d516c261e089caa89990f0967605768ae9200bdfe4dcd7b77a93265cb33d9851a2a1036113c732bf3f37534530641300f0620de5c16101e16f4baf39d9fcbfcb01c52afce0992c329d8dbb438c314eee995c5020611d6f889e06b8a032785cba9a415580dbf752b5e510523c89f478cc6f047bd926f51e4a965c9749d1e76379c0e7e5b56803893bafaa4d2892b4c52f143b2fa777cd1035ea418684b8019df084f9a3f1f768753096621f342895c510d01", -+ "fc0073f199ed8a1d6edc8e7bdf182670003108d82b283aba82326e856f8de378987a03d0fe8d2041440fd29d51c63796aab44090d2b14ee00859b3a08cbe88f724badcd3c401226c5db8b307b8deea5be305412b080e9f99cf79d6d08d3646f347a7afebb62912e3e246e2e726f9aec5c101d916e47f984507b1d65d313697256c77da7eca3bc5811c87bee02a2826cefff0d92bae989609aaf95d70561b40d98474c37277c884aed887a1606d206b11e8a8a71d1f1d19319557b57351228ff0404be700a6cc56c0a30f3d4b7a0a046463fdaf19e7d5f59e155f378e35baa33db1e881f2207f", -+ "f42a6a91278d6a076feba985b1cf4ce0af1fa9d6d039c136e8971e665ff088a10b6b9a379a6f5526fc5957773a0ccb8972a4a19be0745ac13937030a54b18dee4f4c5df47a58a33a7516b90e646e5da999166ab0e52f457f7c9b7e391836a687eaae37b377e59a4c995ab0c57162c307ab951a9ba6590f429cd27250e7010eb794ec1b1ec35f8aad189b2fd3e8aff24d93601d91a4884e6f84b02757ce7620a02901519fccfda52f68ad6df709d112a9c25d66bcbb9622806427ca8b8d346b6db05874bde800cde9cf17df4b05baab0f133febd1ebbb053b49c109a7f5b1f864a304d10288e2f0", -+ "bbcefaf4a0739509f8a2f831c954071aac52e60cfa882a867b8b910dcf7edf92e1c0692bb027bc378c460a01cb6ecc8f2a012dd84ee5a678cd497b1457b6d393421fbee98ff544fc7eba24cbc3aae506254d9a2d74dde74437ce4c8a69010718506bf4c5943342a942e5e2d3406a3016280b6e37954c5d5e763346251afb0b746cad68cac757f9df765e092518729cfb9a5e76300c124e708ca33591a369767ffb63933cb72fba67beb2223d98984d0b75eb5d1a38615913747b520b3d613c715c0c77d2987bb88f3c419bcc5d38573cf4a8a4f550b2d876f05ca252d88c70a561d869a5018b32f7", -+ "dc2437010cb05d9cab2af5c275e1d2acd627ce19fb86355df91fb8d059e60d591663c8eb077d48388c9a321057a98136f49f0098348d9f29d808936f98bb1787c7ac75fb14f6076dfd2de5b59b1fa4848cabaa9a99a091dc24b561911c392ecdbe53f4adae82b852d830adea3a10490c908e337ce0a6d12354ce05a37ad3a06696b66820af8a1f67e6287533fd6f38a5f6ad1c6b078c08baf2c37d2683af01e6a5b33796c8ae48935a888f9bd265f4f11a4e27c433b8b1c9afd140bcd21a07e24378ad6badde8e47c57e3340f49e2406e8d49afadd65eaaa4c3d078c27d7e42118cb86cd248100a356", -+ "6c290db326dd3152e6fa9b9c0cd7d49e50a0221b96e32f5f34a8cb7d0c2edd3e937a7d025d6999b7b468add4d6894d8f7aceaabc18f4d9c171f1fe95ea1ae8570382a8450fbc595d95b1f51d24e1abc2970b0e1d20ca40aa21bdfb3656adf2f19882eda606f5ef1c03174e1d94c8d12f0fee8dce6852f42a364eeafa27a7971d4379405db8e46baac4d685b969238e5df06292a6c790bf1994a051b038e1d8db91e1bc4804f32443781c34a552ed2e8100cea374e77af56ba0e11c45990d3ba68df9087b1f4968cbcbb1c42f99b7267c76af926ff3134e093df28fab039cad420c6b70f2d9b5e678c155", -+ "ac724a22ebabaedbbb052953e3c264a4b6440f313bad501cdc1484b64f33402a2230898776db5c818c28035ffae6ea24abd04b7159e42159833903a0c23a7c564f7645e49ddedb748fd9e51bd6cbf2eced98caaa35226970f003ce1fd260ac5795e096f1c04aebf8fd36e5e2adeea929b5e963a3cb71d6b55c85bb7d3a2b03a7e74b4416de8fa68950168d7c3ae8ed2e29bad1e8a182a7c5418e5d564373163778cd3c34e9d320eb1a60480a8f98b12e0026cbd7752e6079812e3767d9f55f3f10b8c214a6eceb2a58954091a06b33862af171a9b60bf2c6a44e8766e6c56e98092c56f2a8510f6d05c103", -+ "8c70114f7cffb375c2b9a06e27297a5c32418b2daf68af5bbedcc7106edbc070e764bf40c1f8eb15079e2ab77f898afff3490108ed9afb7ea9cb05df41d263be0e42d2321d3d2656622d7bd232bf68d37375fe7314b09cba66f19c8b59424198ee69e7a9f3de0ecce0685127807ce336fa479ccaf7aa1ebc4e406271ce6c4923ec36093516498cc227f9218869346c80ba5ae83e023aca0ae2bc86b5bf5d115a4616b6587cb869d92f8c780ab70d5766de07a204af5e1c8dbba622516d2e911b36c82e4687e4d258ea616c07f76ff0baa376c8d5975cffac0b25817f779ae3ce88b72eb47e378484ce999bf0", -+ "0733d59f041036398233fd47a84b93f6778ae5259ef5d62aa3b9faedec34c7edb570c18b2a5d2c4c55cf656d98a1ae396d45a3b746b7ad6f07312c3d05d1a50ffa90bcdcdba105e25b7b0c52664223f8c2476925d46dc6ea2406ded7d0b0b292f6656cebcc7616cfa4b82aec68b35d1da67f6ed2bf0171849d6bb65128d8a140ea5cf97f1003f8d7093bee077be78def4f7bd2caccbf0644f26b26285225142c40038484c3bb9ba9597744f4389e76dca3eb695c33ccc621cab1fb603cb3535a0ad318d220385d5e94f8674f3d55e97e097f8d5c049e911946afbfce783819951d65d6bff4567dc951390d1aaa", -+ "398ddbba3dcb5642c102efa841c1fcdaf067062e7eef8e2ee0cd73d7f77e57372d6ee1a9b7b6f86ad12d575001ae71f593449cb5a476c6bfeddaa2af0f9239c1d7effdedf66ceaf413707b5ab9661a7cc0ef8cfe4d1651579c4f0f64e2d12a52653c54f2dd60864e769eab8a627c89c56ee93365d031f0d2523cb95664b1575d51b122f33c9e94de75432a690658c977b68aa5b721a393f9b9b3b612c10e920a7d510c6d8460b35f8614c42f5d2c241a01b28105aa7c1b521ac63ebbedafac6d5a38c898e8590f918a1927bc53aecc2b1c8b18d7df9107c6997d9b3fa4b0bdb1c603da619d9e75670b97a5b40f06", -+ "ef07bbc7c4150dd47f8c69a7989948fe831dc798b0424dcd6551bfa8e88216095a7e5d720909bf3d23526b9ba464b66ff6b63a7337c31451ab9a15f04ead809a62bb52206237de77597a730106d02d227dd6099ea9ee2a92cdc446ac3b9d024e32255adb3e9b56b561c431e0b5a721f0336f19568a5335d0ebc6c73ed8ff2c15e219477d9e4b67f2928e251f8a61a2848857e037d010806c718ab062967fd8e85f3722252957923f5f9005aae47b4b1b3fa464e3ba9df573a56055f17e903126fbbcb6cb96de92fe617c97f84ef3ba0d8f2651dc4aa80c157f372ae1bc02e5067ad076f3fe48bb72c0f3c99273f82b", -+ "c7076986d2333f3a6752adf11f1a9e5c6bc4755f341073cc86a9c7519c8db029d5ae833fdf3fee826ff4692c57880c5074620ea97c00f1dde1e8a0f18501627984ded4d1b5c4af35be5cc1bcc868060a49a968dc0547acde490b4c68d79924a93a986aa0ad060c7de706e8a99ce8f84a4f8707b52a8ee122b763ba580d6b1f35f6af25094c69f49247da96c836991851ad36f60bf577863d7471608a012afa7a56656abeee7cd9b4f1f4d9d13a8526c0f33cd251caf7486639e787250390e7e488e9ec311fc3d847a7266cc59bcc2bc34192554aa57cf25db10ce04bdabef3fde6db85f55195ecc2ff892b2e268ebea6", -+ "01789f40d42d8d3e4a416fd9ae7de78c3a30507809eda200e1afaaf8d7020cd1fad18eba62d821946f220506cf105ff0e2069a771a2c233714afa6b2f695497e4b95c9693dbb93ec4c9a14720676aa87ee31dd34e4e081756477032b4a57b328285f2cdec1b269754c474936927e93acc26012aff1bb36f30c2402aca0a9b9ce9568f5000e2c934263933b436c94f8d6589c89db7edabc5d03a8fe795fe50c5166beab64ed7c22662b984ae2c66dbe4c090b0df603b27c759278f8d66859afea3f6a8f02c2c2a2202b9fc29132256f164b5050a803b43688dc4c9ba86374a3522afba5d1a19bb3820b883aebc267627095", -+ "2c61944bd6a50da00ebb951d2b67d79fc6b6fb5aca83b1de3dbd7690ab756bb1e1a21051ccf1e24136ac8ccb42a2ee10be94d2cb9289d5f52b6f90e9d07a3478f36a1eb7d08c3dec52ca154fd1427ba92a4ecbe73a71bceafbd26e9a39d50821e2876d3a0c0e6e373b9795dbf72ea29cc439ff42706be798c90d4617b39c90ec84bf9fb699dc8a9a34e25d81759d6c57df45efb1d0d68aa51278564b99633ed5dc464bb7d53c5c21f798f33bcd868657ecfe75a1ed8149d394b398969ef624831b30f1458465bfd2fdf3f284f2ffc54bf2817b5fab2e02056e864f78bb6fd870c64f3609dab218f25da8060f756e45121e79", -+ "942fa0c68cc72f69518a3a7aac0cde45bab0e928b5cb2bd24d049fc313f74b6afa87c4e34150484f3b5200163f8a6472d04777928ecc49319539fc17d71a38090f55a74f757fe45781a3c09f08dcd3dd4c73c8533a5e00cf8a86ebe77fe45be2848574f7c5d25e9a0632a60d2dd41febdbf987d2a0487e4a4ce6ed5f49f2d741a88ecac232b1498253fa4ee8147bbd0f600abdf295e81f7570015aac5fe6ca7bb4a99bb3fc54287106d7fc1132a574af49db82a7b9a5f33e193cde527ca2176c52cdab672165e0fe5720f71ada57ee90060aa069ae2a0bfe67c1b71b17c601c3c2224bf9891bc11ba216e3ebcb51fd95b8d7cb", -+ "0d68cfe9c087ec116fe7572042385159cc705960f842aabad1ed1387ec1697f4413a23c6090041328fedd4b626c6eeaac5b5a71acc1fd1bb8fbd228857ac5bd045c364be7a5a26338ff04c99c4c473cf445a891db6422d1bdef4533442df171643fc36a092fabb464298e4194c9e2950884de13d113ee24160a416404c16ddc5d2476cb3fb80da543e6ed9105f6003977acb34e1fdd2cbdf7a00d5ff84350b74ac231418c0d88269d02d824802791ff42a51cc835deb9869a6023f867f82ef6dc0bfb03e6dfa835646bb18a4074773486e308aa39e532aaea4e6fb35dcada7e060f8282c371ed26d22302323d4fd142a85534671", -+ "45e24b167a0bbef1bd8f79dd047763d0754f36a7b623f298059d177e8ac994945c37d2c4af06f01318960301595941124592f2995af1459d854339998d3ae17534df2d9793d6e203857d02c98a0cd88991e641b3e640090ba303f87b907dca8ca462fac19ad079b2c82ea5b521ab891b10138b083b3d9fa214a8fe60d1cb3599c5d199c61a2cfb7ee2f39e5a5abad5ac4998b707545f73e92128d21803420526d2598a53bb314adf29a0ef56b94bd2221601eb53ecb8540e8fffd38fba7bd827ef255e4ef55491475c0f383a241f81c72af4e1dbf2a65cd4d18a497615aa0de2791a3511a7977a8d4d41492bfa4085f2fd4e8f751d", -+ "1c1bb695ae90e6e33fc1e8b2a62ab98bf835ac7193440f2351c8cdd830472b637d2fd9c9013cb83caef506abc1c4f7567706db6046b1d184579c7a9223ab1b35e32898c70a3c27628123ffcfa518612f080a2c4a9f8e0a927a47dc98307d2b48de9d5dddcb5c82f0b0e4e610d44f1baa9bbbf7f5a727134680bb7d1327b73b52d8e5e36dbb53971e99e699d79f75a3fc01316bd7012947d119d6aeb7f75b8fbf0479c03002148553fa0da450fd59d4f1bebc252caa11ed9bec5b6ef54279b5f8382b61cffc67ec03f4baa7ea476c31364b86aa8ccad9fd0818717f0ced2dd49477874b4341c602d7a1beab860eb476c7e3ce597e6926", -+ "7a3cd9bb2277e2c7f1134fe7233f0f7883c2db9fba80aa5742b03041de0fe589d9e5ea84470dabf41bb66816f3e33ebf19a0ca5aba1004cf971249b258ff26a98dbd0c37ec6cd574854109433357720040bafed4531e0079186b1e853e0ced35d08d27f6d732ed6e2c6651b51cc15c420a24f2dc36c16ef4b3896df1bb03b3963f9aaeb02a48eac5772abd5948c2fd0db2bb74e3351e5eabd681c4f413655bd94dec96b1544c1d5d2d1df4bdc26020d25fe81d5238de824687a5505e1fbe08d11b3924b3ccc070fd225bf01eb79e3d21f7b62a836cd3bcc11c931669c37613470e356143df87c48848a829f5e018973a5db88eb6c60203", -+ "3f158afd0733fcc5dfe1efc2dd4eada732f942af734ee664955bb1ba613eafd0f349e7554a14d68200c62d8f2dca2ec8b81c8350735eaf437041f78b452598825b6899560963ade66a0fc74ad01f8343d1d19c7bb327a8dc14ffdb1c42fa72b2970d9155e2da6a2e6419d4117842d826ff38ffab9617307a0283d3ea28c8104ad9a6e087bb750ed1d10fd8f7100b1663682e979d80e43968c33d9eff66f4d1344e583ee521e78d0a2193c0577516b978339c143bfc689bc744bbc4a9163063de82c9706384b6b385e54666c86b34f23c1e25be293af06092ca31d857e11e5b2caf0d19dd3afbe85380878eda76d718b4bb869c67e044e242", -+ "a177af4387b9bfa3d59e97ee7b0ff5f4ae4a326fd9204c8d28831a67fcc385ee6c4828247b16d11aea9bb8cd9e6c4d2876c6b2fa6d5041ad39e1b04039071e29c4d86417e7eac4fc7d3823958a021823e2c880a757dfbcd0c8196371db5bbfac15e4d1a0596508b6d26f8c4a664924c95082d173f817995b44c4285d625d9b2f56c86632fe1295c5a8a7a3760028072bcb07bc245a705e7174d06b9d5c0c8ca495b9ac218f1921fa63f2db3fd148f07545366d008fb5aead7497d902b91fbaa39669929d4ae9d07df8557f1f0aed7b51252f10c6606e5ff3ede1327530ca356b4896ecf14bf7322d77fddfbe28d52f6de7f66eeb81704c87e2", -+ "01a15b9018e35cc342c926b01d03ad9db4993a6bf92e0555969fee90033f28f3ec234c1268b11b040dfa0770d4ceb39edfeb8ee6a589f4eebcc08d2d1b0a1a52953aa26eb44fdf4a2743c3dacb212a0c0f325572f645f53027b6f3c0c55abaeb1b0918c89bedcb5028f094d743ea354f8ff553c45f111a8fd5a14a4e5c835164747d302472e19a67da04b4c8e39756a9d248ce14d1ed43de75aca86850f2455eccd4639b2af035bb3f504cc9065d091c1c47e036083cb3fc50bf39292b11737c7ce0b49673ba93981de304dc65a671775b6ff927e3ff93850b214fffb5792105a4bdc81354d5b09e84afbdd1792b8fb4e9d0ae3dad2492b03282", -+ "24f07ae31279ceed18ec6d35990f21200934ad6b132c6c62e82fe92a40a0e60a5bed10720eff5a1f728971888682772b2d9060d4fee88f37d0824e7384dddcc549475f0e1a44eda4804778b62febe46e04657a20577ee70acb3425e334881eebd8ddf714ae8c527ea747e3367de384e595a43b299b6bb3f6b0a4716cf90038e0f75a47d5057d7fcc3c8a8f9224992c67f8ae0d3251ea09a24aed9ce57ab637f6b3cbb7083df62b6287f64d0877984c4249d113bdb2b07865082aa24cd7ec07061b17de320f51f29f25b82d7073d369cf2dbf96310c0c311997911b2cc02f606f9cd99663c57e78499192a2a78f9c9fa67013e0f9817287faa69b22", -+ "4aeb32bf9d050f10bea18d9f71b4afea7bd08550e574e7d50df234c7413668b297b6721d7a0f0bdcdcceb2f55adddea28cd59bd44be0c5ec067039e428706caae11f565d961ad6e7f4c51b0aed6d05cc5b8d826c4b9c39daefb6c7da46dce619a359dc9ce215a215218fa8d54ee0b4f301b6c201c7c2c5f7cb1c6e0cb76ba6c6e8f63ef7a5213d550b0d0857fa0ff9e3e38e497161617413ac066e2fa539520233193a5cb7baa0c2cb20b45e56bfed2c40a9544d1f230dd0cd6d4976e7cf51da8a13200c3957c0154c8237b2931ce19b824963ac576ea49b548cc6aa85c47796b470fb2c6308d88f390bb13607e294c84a838b2713b14ca6a5e8bcee", -+ "77e607478be5502432230c913d9ec82f967d87c0ee169a74076f989648853eca693277287f8a5b306bc94dfdbf64ca5cb5dfc0bc498589d51a691b8d57d4b0a9ee247d038fe1b5571183be3e75c37045bf1235863ff1b84b208c10e7f1a5ba54ff36af5b2870129867164d013e0a6d2cc067a3509bba2f46390302c80b651cf590ef69aad8effd94cab28a9b44be6a38b58cfc47c9c725d6fa467894163383b6873d10d263b1cbbad932ded59ab503920267ac026726f794a335a88f6ef564f8968c6fa6f5d3ea161eb6062ca349b9a0e4038273399cfa297a6b07ceda1ebaa99c9de2d935ee230a08c5a488ad46f3393243371d40916b8063cac9da63", -+ "50957c407519951bd32e45d21129d6b83436e520b0801ec8292d79a828106a41583a0d607f853dc4410e0a1427f7e873455a75df065cfc6eef970f7e49d123b346976460aadd91cf513c140c356442a84656904a8b1d708dc6089db371c36f4fe059c62302eaab3c06c0cb3b429961f899dcf99798464b8571a440cac7a52b495f32417af6bc8f58adc63647531f804b4e96273b29b42434c1236bde80ba3744fef7b1d11c2f9db332b35bc25123338ac9a0796aac213c9709b3c514ea7ecd80e22d3d8a74f28c8194418a6e1ff30714d0f5a61c068b73b2ba6cad14e05569b4a5a100da3f91429d6e3ffee10ceea057845ec6fc47a6c5125b22e598b2dc", -+ "f2273ec31e03cf42d9ca953f8b87e78c291cb538098e0f2436194b308ce30583f553fccb21ae6c2d58f3a5a2ca6037c1b8b7afb291009e4310a0c518e75314c5bb1e813bf521f56d0a4891d0772ad84f09a00634815029a3f9ad4e41eafb4a745e409ef3d4f0b1cf6232b70a5ce262b9432f096e834201a0992db5d09ffa5cbc5471460519a4bc7cdc33ae6dfe6ffc1e80ea5d29813136406499c3514186ced71854a340701519ef33b6c82ca67049ab58578ff49c4c4fbf7d97bfec2ecd8fbefec1b6d6467503fea9d26e134e8c35739a422647aaf4db29c9a32e3df36e5845791fdd75a70903e0ce808313a3327431b7772567f779bbaee2e134c109a387", -+ "5784e614d538f7f26c803191deb464a884817002988c36448dcbecfad1997fe51ab0b3853c51ed49ce9f4e477522fb3f32cc50515b753c18fb89a8d965afcf1ed5e099b22c4225732baeb986f5c5bc88e4582d27915e2a19126d3d4555fab4f6516a6a156dbfeed9e982fc589e33ce2b9e1ba2b416e11852ddeab93025974267ac82c84f071c3d07f215f47e3565fd1d962c76e0d635892ea71488273765887d31f250a26c4ddc377ed89b17326e259f6cc1de0e63158e83aebb7f5a7c08c63c767876c8203639958a407acca096d1f606c04b4f4b3fd771781a5901b1c3cee7c04c3b6870226eee309b74f51edbf70a3817cc8da87875301e04d0416a65dc5d", -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/blake2x.go b/ms_mod/golang.org/x/crypto/blake2s/blake2x.go -new file mode 100644 -index 00000000000000..828749ff01d153 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/blake2x.go -@@ -0,0 +1,178 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blake2s -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "io" -+) -+ -+// XOF defines the interface to hash functions that -+// support arbitrary-length output. -+type XOF interface { -+ // Write absorbs more data into the hash's state. It panics if called -+ // after Read. -+ io.Writer -+ -+ // Read reads more output from the hash. It returns io.EOF if the limit -+ // has been reached. -+ io.Reader -+ -+ // Clone returns a copy of the XOF in its current state. -+ Clone() XOF -+ -+ // Reset resets the XOF to its initial state. -+ Reset() -+} -+ -+// OutputLengthUnknown can be used as the size argument to NewXOF to indicate -+// the length of the output is not known in advance. -+const OutputLengthUnknown = 0 -+ -+// magicUnknownOutputLength is a magic value for the output size that indicates -+// an unknown number of output bytes. -+const magicUnknownOutputLength = 65535 -+ -+// maxOutputLength is the absolute maximum number of bytes to produce when the -+// number of output bytes is unknown. -+const maxOutputLength = (1 << 32) * 32 -+ -+// NewXOF creates a new variable-output-length hash. The hash either produce a -+// known number of bytes (1 <= size < 65535), or an unknown number of bytes -+// (size == OutputLengthUnknown). In the latter case, an absolute limit of -+// 128GiB applies. -+// -+// A non-nil key turns the hash into a MAC. The key must between -+// zero and 32 bytes long. -+func NewXOF(size uint16, key []byte) (XOF, error) { -+ if len(key) > Size { -+ return nil, errKeySize -+ } -+ if size == magicUnknownOutputLength { -+ // 2^16-1 indicates an unknown number of bytes and thus isn't a -+ // valid length. -+ return nil, errors.New("blake2s: XOF length too large") -+ } -+ if size == OutputLengthUnknown { -+ size = magicUnknownOutputLength -+ } -+ x := &xof{ -+ d: digest{ -+ size: Size, -+ keyLen: len(key), -+ }, -+ length: size, -+ } -+ copy(x.d.key[:], key) -+ x.Reset() -+ return x, nil -+} -+ -+type xof struct { -+ d digest -+ length uint16 -+ remaining uint64 -+ cfg, root, block [Size]byte -+ offset int -+ nodeOffset uint32 -+ readMode bool -+} -+ -+func (x *xof) Write(p []byte) (n int, err error) { -+ if x.readMode { -+ panic("blake2s: write to XOF after read") -+ } -+ return x.d.Write(p) -+} -+ -+func (x *xof) Clone() XOF { -+ clone := *x -+ return &clone -+} -+ -+func (x *xof) Reset() { -+ x.cfg[0] = byte(Size) -+ binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length -+ binary.LittleEndian.PutUint16(x.cfg[12:], x.length) // XOF length -+ x.cfg[15] = byte(Size) // inner hash size -+ -+ x.d.Reset() -+ x.d.h[3] ^= uint32(x.length) -+ -+ x.remaining = uint64(x.length) -+ if x.remaining == magicUnknownOutputLength { -+ x.remaining = maxOutputLength -+ } -+ x.offset, x.nodeOffset = 0, 0 -+ x.readMode = false -+} -+ -+func (x *xof) Read(p []byte) (n int, err error) { -+ if !x.readMode { -+ x.d.finalize(&x.root) -+ x.readMode = true -+ } -+ -+ if x.remaining == 0 { -+ return 0, io.EOF -+ } -+ -+ n = len(p) -+ if uint64(n) > x.remaining { -+ n = int(x.remaining) -+ p = p[:n] -+ } -+ -+ if x.offset > 0 { -+ blockRemaining := Size - x.offset -+ if n < blockRemaining { -+ x.offset += copy(p, x.block[x.offset:]) -+ x.remaining -= uint64(n) -+ return -+ } -+ copy(p, x.block[x.offset:]) -+ p = p[blockRemaining:] -+ x.offset = 0 -+ x.remaining -= uint64(blockRemaining) -+ } -+ -+ for len(p) >= Size { -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ copy(p, x.block[:]) -+ p = p[Size:] -+ x.remaining -= uint64(Size) -+ } -+ -+ if todo := len(p); todo > 0 { -+ if x.remaining < uint64(Size) { -+ x.cfg[0] = byte(x.remaining) -+ } -+ binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) -+ x.nodeOffset++ -+ -+ x.d.initConfig(&x.cfg) -+ x.d.Write(x.root[:]) -+ x.d.finalize(&x.block) -+ -+ x.offset = copy(p, x.block[:todo]) -+ x.remaining -= uint64(todo) -+ } -+ -+ return -+} -+ -+func (d *digest) initConfig(cfg *[Size]byte) { -+ d.offset, d.c[0], d.c[1] = 0, 0, 0 -+ for i := range d.h { -+ d.h[i] = iv[i] ^ binary.LittleEndian.Uint32(cfg[i*4:]) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blake2s/register.go b/ms_mod/golang.org/x/crypto/blake2s/register.go -new file mode 100644 -index 00000000000000..ef79ff3c67a18f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blake2s/register.go -@@ -0,0 +1,22 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.9 -+// +build go1.9 -+ -+package blake2s -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ newHash256 := func() hash.Hash { -+ h, _ := New256(nil) -+ return h -+ } -+ -+ crypto.RegisterHash(crypto.BLAKE2s_256, newHash256) -+} -diff --git a/ms_mod/golang.org/x/crypto/blowfish/block.go b/ms_mod/golang.org/x/crypto/blowfish/block.go -new file mode 100644 -index 00000000000000..9d80f19521b461 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blowfish/block.go -@@ -0,0 +1,159 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blowfish -+ -+// getNextWord returns the next big-endian uint32 value from the byte slice -+// at the given position in a circular manner, updating the position. -+func getNextWord(b []byte, pos *int) uint32 { -+ var w uint32 -+ j := *pos -+ for i := 0; i < 4; i++ { -+ w = w<<8 | uint32(b[j]) -+ j++ -+ if j >= len(b) { -+ j = 0 -+ } -+ } -+ *pos = j -+ return w -+} -+ -+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it -+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's -+// pi and substitution tables for calls to Encrypt. This is used, primarily, -+// by the bcrypt package to reuse the Blowfish key schedule during its -+// set up. It's unlikely that you need to use this directly. -+func ExpandKey(key []byte, c *Cipher) { -+ j := 0 -+ for i := 0; i < 18; i++ { -+ // Using inlined getNextWord for performance. -+ var d uint32 -+ for k := 0; k < 4; k++ { -+ d = d<<8 | uint32(key[j]) -+ j++ -+ if j >= len(key) { -+ j = 0 -+ } -+ } -+ c.p[i] ^= d -+ } -+ -+ var l, r uint32 -+ for i := 0; i < 18; i += 2 { -+ l, r = encryptBlock(l, r, c) -+ c.p[i], c.p[i+1] = l, r -+ } -+ -+ for i := 0; i < 256; i += 2 { -+ l, r = encryptBlock(l, r, c) -+ c.s0[i], c.s0[i+1] = l, r -+ } -+ for i := 0; i < 256; i += 2 { -+ l, r = encryptBlock(l, r, c) -+ c.s1[i], c.s1[i+1] = l, r -+ } -+ for i := 0; i < 256; i += 2 { -+ l, r = encryptBlock(l, r, c) -+ c.s2[i], c.s2[i+1] = l, r -+ } -+ for i := 0; i < 256; i += 2 { -+ l, r = encryptBlock(l, r, c) -+ c.s3[i], c.s3[i+1] = l, r -+ } -+} -+ -+// This is similar to ExpandKey, but folds the salt during the key -+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero -+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency -+// and specializing it here is useful. -+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { -+ j := 0 -+ for i := 0; i < 18; i++ { -+ c.p[i] ^= getNextWord(key, &j) -+ } -+ -+ j = 0 -+ var l, r uint32 -+ for i := 0; i < 18; i += 2 { -+ l ^= getNextWord(salt, &j) -+ r ^= getNextWord(salt, &j) -+ l, r = encryptBlock(l, r, c) -+ c.p[i], c.p[i+1] = l, r -+ } -+ -+ for i := 0; i < 256; i += 2 { -+ l ^= getNextWord(salt, &j) -+ r ^= getNextWord(salt, &j) -+ l, r = encryptBlock(l, r, c) -+ c.s0[i], c.s0[i+1] = l, r -+ } -+ -+ for i := 0; i < 256; i += 2 { -+ l ^= getNextWord(salt, &j) -+ r ^= getNextWord(salt, &j) -+ l, r = encryptBlock(l, r, c) -+ c.s1[i], c.s1[i+1] = l, r -+ } -+ -+ for i := 0; i < 256; i += 2 { -+ l ^= getNextWord(salt, &j) -+ r ^= getNextWord(salt, &j) -+ l, r = encryptBlock(l, r, c) -+ c.s2[i], c.s2[i+1] = l, r -+ } -+ -+ for i := 0; i < 256; i += 2 { -+ l ^= getNextWord(salt, &j) -+ r ^= getNextWord(salt, &j) -+ l, r = encryptBlock(l, r, c) -+ c.s3[i], c.s3[i+1] = l, r -+ } -+} -+ -+func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { -+ xl, xr := l, r -+ xl ^= c.p[0] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] -+ xr ^= c.p[17] -+ return xr, xl -+} -+ -+func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { -+ xl, xr := l, r -+ xl ^= c.p[17] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] -+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] -+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] -+ xr ^= c.p[0] -+ return xr, xl -+} -diff --git a/ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go b/ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go -new file mode 100644 -index 00000000000000..368ba872bfd5ef ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blowfish/blowfish_test.go -@@ -0,0 +1,274 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package blowfish -+ -+import "testing" -+ -+type CryptTest struct { -+ key []byte -+ in []byte -+ out []byte -+} -+ -+// Test vector values are from https://www.schneier.com/code/vectors.txt. -+var encryptTests = []CryptTest{ -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}}, -+ { -+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, -+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, -+ []byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}}, -+ { -+ []byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, -+ []byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}}, -+ { -+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, -+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, -+ []byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}}, -+ -+ { -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, -+ []byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}}, -+ { -+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}}, -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}}, -+ { -+ []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}}, -+ { -+ []byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57}, -+ []byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42}, -+ []byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}}, -+ { -+ []byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E}, -+ []byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA}, -+ []byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}}, -+ { -+ []byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86}, -+ []byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72}, -+ []byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}}, -+ { -+ []byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E}, -+ []byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A}, -+ []byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}}, -+ { -+ []byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6}, -+ []byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2}, -+ []byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}}, -+ { -+ []byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE}, -+ []byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A}, -+ []byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}}, -+ { -+ []byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6}, -+ []byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2}, -+ []byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}}, -+ { -+ []byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE}, -+ []byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A}, -+ []byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}}, -+ { -+ []byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16}, -+ []byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02}, -+ []byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}}, -+ { -+ []byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F}, -+ []byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A}, -+ []byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}}, -+ { -+ []byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46}, -+ []byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32}, -+ []byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}}, -+ { -+ []byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E}, -+ []byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA}, -+ []byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}}, -+ { -+ []byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76}, -+ []byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62}, -+ []byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}}, -+ { -+ []byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07}, -+ []byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2}, -+ []byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}}, -+ { -+ []byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F}, -+ []byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA}, -+ []byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}}, -+ { -+ []byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7}, -+ []byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92}, -+ []byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}}, -+ { -+ []byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF}, -+ []byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A}, -+ []byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}}, -+ { -+ []byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6}, -+ []byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2}, -+ []byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}}, -+ { -+ []byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF}, -+ []byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A}, -+ []byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}}, -+ { -+ []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}}, -+ { -+ []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E}, -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}}, -+ { -+ []byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE}, -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}}, -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, -+ []byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}}, -+ { -+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}}, -+ { -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}}, -+ { -+ []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, -+ []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, -+ []byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}}, -+} -+ -+func TestCipherEncrypt(t *testing.T) { -+ for i, tt := range encryptTests { -+ c, err := NewCipher(tt.key) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) -+ continue -+ } -+ ct := make([]byte, len(tt.out)) -+ c.Encrypt(ct, tt.in) -+ for j, v := range ct { -+ if v != tt.out[j] { -+ t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j]) -+ break -+ } -+ } -+ } -+} -+ -+func TestCipherDecrypt(t *testing.T) { -+ for i, tt := range encryptTests { -+ c, err := NewCipher(tt.key) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err) -+ continue -+ } -+ pt := make([]byte, len(tt.in)) -+ c.Decrypt(pt, tt.out) -+ for j, v := range pt { -+ if v != tt.in[j] { -+ t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j]) -+ break -+ } -+ } -+ } -+} -+ -+func TestSaltedCipherKeyLength(t *testing.T) { -+ if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) { -+ t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0)) -+ } -+ -+ // A 57-byte key. One over the typical blowfish restriction. -+ key := []byte("012345678901234567890123456789012345678901234567890123456") -+ if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil { -+ t.Errorf("NewSaltedCipher with long key, gave error %#v", err) -+ } -+} -+ -+// Test vectors generated with Blowfish from OpenSSH. -+var saltedVectors = [][8]byte{ -+ {0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e}, -+ {0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12}, -+ {0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad}, -+ {0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8}, -+ {0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8}, -+ {0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf}, -+ {0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9}, -+ {0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38}, -+ {0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4}, -+ {0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c}, -+ {0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5}, -+ {0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b}, -+ {0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47}, -+ {0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2}, -+ {0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19}, -+ {0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc}, -+ {0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93}, -+ {0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57}, -+ {0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08}, -+ {0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03}, -+ {0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f}, -+ {0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef}, -+ {0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71}, -+ {0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad}, -+ {0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe}, -+ {0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13}, -+ {0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe}, -+ {0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6}, -+ {0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6}, -+ {0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92}, -+ {0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56}, -+ {0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee}, -+} -+ -+func TestSaltedCipher(t *testing.T) { -+ var key, salt [32]byte -+ for i := range key { -+ key[i] = byte(i) -+ salt[i] = byte(i + 32) -+ } -+ for i, v := range saltedVectors { -+ c, err := NewSaltedCipher(key[:], salt[:i]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ var buf [8]byte -+ c.Encrypt(buf[:], buf[:]) -+ if v != buf { -+ t.Errorf("%d: expected %x, got %x", i, v, buf) -+ } -+ } -+} -+ -+func BenchmarkExpandKeyWithSalt(b *testing.B) { -+ key := make([]byte, 32) -+ salt := make([]byte, 16) -+ c, _ := NewCipher(key) -+ for i := 0; i < b.N; i++ { -+ expandKeyWithSalt(key, salt, c) -+ } -+} -+ -+func BenchmarkExpandKey(b *testing.B) { -+ key := make([]byte, 32) -+ c, _ := NewCipher(key) -+ for i := 0; i < b.N; i++ { -+ ExpandKey(key, c) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/blowfish/cipher.go b/ms_mod/golang.org/x/crypto/blowfish/cipher.go -new file mode 100644 -index 00000000000000..213bf204afea5b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blowfish/cipher.go -@@ -0,0 +1,99 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. -+// -+// Blowfish is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package blowfish // import "golang.org/x/crypto/blowfish" -+ -+// The code is a port of Bruce Schneier's C implementation. -+// See https://www.schneier.com/blowfish.html. -+ -+import "strconv" -+ -+// The Blowfish block size in bytes. -+const BlockSize = 8 -+ -+// A Cipher is an instance of Blowfish encryption using a particular key. -+type Cipher struct { -+ p [18]uint32 -+ s0, s1, s2, s3 [256]uint32 -+} -+ -+type KeySizeError int -+ -+func (k KeySizeError) Error() string { -+ return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) -+} -+ -+// NewCipher creates and returns a Cipher. -+// The key argument should be the Blowfish key, from 1 to 56 bytes. -+func NewCipher(key []byte) (*Cipher, error) { -+ var result Cipher -+ if k := len(key); k < 1 || k > 56 { -+ return nil, KeySizeError(k) -+ } -+ initCipher(&result) -+ ExpandKey(key, &result) -+ return &result, nil -+} -+ -+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key -+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is -+// sufficient and desirable. For bcrypt compatibility, the key can be over 56 -+// bytes. -+func NewSaltedCipher(key, salt []byte) (*Cipher, error) { -+ if len(salt) == 0 { -+ return NewCipher(key) -+ } -+ var result Cipher -+ if k := len(key); k < 1 { -+ return nil, KeySizeError(k) -+ } -+ initCipher(&result) -+ expandKeyWithSalt(key, salt, &result) -+ return &result, nil -+} -+ -+// BlockSize returns the Blowfish block size, 8 bytes. -+// It is necessary to satisfy the Block interface in the -+// package "crypto/cipher". -+func (c *Cipher) BlockSize() int { return BlockSize } -+ -+// Encrypt encrypts the 8-byte buffer src using the key k -+// and stores the result in dst. -+// Note that for amounts of data larger than a block, -+// it is not safe to just call Encrypt on successive blocks; -+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -+func (c *Cipher) Encrypt(dst, src []byte) { -+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ l, r = encryptBlock(l, r, c) -+ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) -+ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -+} -+ -+// Decrypt decrypts the 8-byte buffer src using the key k -+// and stores the result in dst. -+func (c *Cipher) Decrypt(dst, src []byte) { -+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ l, r = decryptBlock(l, r, c) -+ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) -+ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -+} -+ -+func initCipher(c *Cipher) { -+ copy(c.p[0:], p[0:]) -+ copy(c.s0[0:], s0[0:]) -+ copy(c.s1[0:], s1[0:]) -+ copy(c.s2[0:], s2[0:]) -+ copy(c.s3[0:], s3[0:]) -+} -diff --git a/ms_mod/golang.org/x/crypto/blowfish/const.go b/ms_mod/golang.org/x/crypto/blowfish/const.go -new file mode 100644 -index 00000000000000..d04077595abc44 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/blowfish/const.go -@@ -0,0 +1,199 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// The startup permutation array and substitution boxes. -+// They are the hexadecimal digits of PI; see: -+// https://www.schneier.com/code/constants.txt. -+ -+package blowfish -+ -+var s0 = [256]uint32{ -+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, -+ 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, -+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, -+ 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, -+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, -+ 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, -+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, -+ 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, -+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, -+ 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, -+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, -+ 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, -+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, -+ 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, -+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, -+ 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, -+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, -+ 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, -+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, -+ 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, -+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, -+ 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, -+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, -+ 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, -+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, -+ 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, -+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, -+ 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, -+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, -+ 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, -+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, -+ 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, -+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, -+ 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, -+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, -+ 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, -+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, -+ 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, -+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, -+ 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, -+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, -+ 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, -+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, -+} -+ -+var s1 = [256]uint32{ -+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, -+ 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, -+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, -+ 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, -+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, -+ 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, -+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, -+ 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, -+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, -+ 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, -+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, -+ 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, -+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, -+ 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, -+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, -+ 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, -+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, -+ 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, -+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, -+ 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, -+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, -+ 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, -+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, -+ 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, -+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, -+ 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, -+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, -+ 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, -+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, -+ 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, -+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, -+ 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, -+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, -+ 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, -+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, -+ 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, -+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, -+ 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, -+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, -+ 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, -+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, -+ 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, -+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, -+} -+ -+var s2 = [256]uint32{ -+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, -+ 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, -+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, -+ 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, -+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, -+ 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, -+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, -+ 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, -+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, -+ 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, -+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, -+ 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, -+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, -+ 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, -+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, -+ 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, -+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, -+ 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, -+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, -+ 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, -+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, -+ 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, -+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, -+ 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, -+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, -+ 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, -+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, -+ 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, -+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, -+ 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, -+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, -+ 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, -+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, -+ 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, -+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, -+ 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, -+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, -+ 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, -+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, -+ 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, -+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, -+ 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, -+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, -+} -+ -+var s3 = [256]uint32{ -+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, -+ 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, -+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, -+ 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, -+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, -+ 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, -+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, -+ 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, -+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, -+ 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, -+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, -+ 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, -+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, -+ 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, -+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, -+ 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, -+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, -+ 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, -+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, -+ 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, -+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, -+ 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, -+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, -+ 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, -+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, -+ 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, -+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, -+ 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, -+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, -+ 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, -+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, -+ 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, -+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, -+ 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, -+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, -+ 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, -+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, -+ 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, -+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, -+ 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, -+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, -+ 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, -+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, -+} -+ -+var p = [18]uint32{ -+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, -+ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, -+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/bn256.go b/ms_mod/golang.org/x/crypto/bn256/bn256.go -new file mode 100644 -index 00000000000000..5d6d198bcb1c4c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/bn256.go -@@ -0,0 +1,429 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package bn256 implements a particular bilinear group. -+// -+// Bilinear groups are the basis of many of the new cryptographic protocols -+// that have been proposed over the past decade. They consist of a triplet of -+// groups (G₁, Gβ‚‚ and GT) such that there exists a function e(g₁ˣ,gβ‚‚ΚΈ)=gTΛ£ΚΈ -+// (where gβ‚“ is a generator of the respective group). That function is called -+// a pairing function. -+// -+// This package specifically implements the Optimal Ate pairing over a 256-bit -+// Barreto-Naehrig curve as described in -+// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible -+// with the implementation described in that paper. -+// -+// This package previously claimed to operate at a 128-bit security level. -+// However, recent improvements in attacks mean that is no longer true. See -+// https://moderncrypto.org/mail-archive/curves/2016/000740.html. -+// -+// Deprecated: due to its weakened security, new systems should not rely on this -+// elliptic curve. This package is frozen, and not implemented in constant time. -+// There is a more complete implementation at github.com/cloudflare/bn256, but -+// note that it suffers from the same security issues of the underlying curve. -+package bn256 // import "golang.org/x/crypto/bn256" -+ -+import ( -+ "crypto/rand" -+ "io" -+ "math/big" -+) -+ -+// G1 is an abstract cyclic group. The zero value is suitable for use as the -+// output of an operation, but cannot be used as an input. -+type G1 struct { -+ p *curvePoint -+} -+ -+// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. -+func RandomG1(r io.Reader) (*big.Int, *G1, error) { -+ var k *big.Int -+ var err error -+ -+ for { -+ k, err = rand.Int(r, Order) -+ if err != nil { -+ return nil, nil, err -+ } -+ if k.Sign() > 0 { -+ break -+ } -+ } -+ -+ return k, new(G1).ScalarBaseMult(k), nil -+} -+ -+func (e *G1) String() string { -+ if e.p == nil { -+ return "bn256.G1" + newCurvePoint(nil).String() -+ } -+ return "bn256.G1" + e.p.String() -+} -+ -+// ScalarBaseMult sets e to g*k where g is the generator of the group and -+// then returns e. -+func (e *G1) ScalarBaseMult(k *big.Int) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Mul(curveGen, k, new(bnPool)) -+ return e -+} -+ -+// ScalarMult sets e to a*k and then returns e. -+func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Mul(a.p, k, new(bnPool)) -+ return e -+} -+ -+// Add sets e to a+b and then returns e. -+// -+// Warning: this function is not complete, it fails for a equal to b. -+func (e *G1) Add(a, b *G1) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Add(a.p, b.p, new(bnPool)) -+ return e -+} -+ -+// Neg sets e to -a and then returns e. -+func (e *G1) Neg(a *G1) *G1 { -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ e.p.Negative(a.p) -+ return e -+} -+ -+// Marshal converts n to a byte slice. -+func (e *G1) Marshal() []byte { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if e.p.IsInfinity() { -+ return make([]byte, numBytes*2) -+ } -+ -+ e.p.MakeAffine(nil) -+ -+ xBytes := new(big.Int).Mod(e.p.x, p).Bytes() -+ yBytes := new(big.Int).Mod(e.p.y, p).Bytes() -+ -+ ret := make([]byte, numBytes*2) -+ copy(ret[1*numBytes-len(xBytes):], xBytes) -+ copy(ret[2*numBytes-len(yBytes):], yBytes) -+ -+ return ret -+} -+ -+// Unmarshal sets e to the result of converting the output of Marshal back into -+// a group element and then returns e. -+func (e *G1) Unmarshal(m []byte) (*G1, bool) { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if len(m) != 2*numBytes { -+ return nil, false -+ } -+ -+ if e.p == nil { -+ e.p = newCurvePoint(nil) -+ } -+ -+ e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) -+ e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) -+ -+ if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { -+ // This is the point at infinity. -+ e.p.y.SetInt64(1) -+ e.p.z.SetInt64(0) -+ e.p.t.SetInt64(0) -+ } else { -+ e.p.z.SetInt64(1) -+ e.p.t.SetInt64(1) -+ -+ if !e.p.IsOnCurve() { -+ return nil, false -+ } -+ } -+ -+ return e, true -+} -+ -+// G2 is an abstract cyclic group. The zero value is suitable for use as the -+// output of an operation, but cannot be used as an input. -+type G2 struct { -+ p *twistPoint -+} -+ -+// RandomG2 returns x and gβ‚‚Λ£ where x is a random, non-zero number read from r. -+func RandomG2(r io.Reader) (*big.Int, *G2, error) { -+ var k *big.Int -+ var err error -+ -+ for { -+ k, err = rand.Int(r, Order) -+ if err != nil { -+ return nil, nil, err -+ } -+ if k.Sign() > 0 { -+ break -+ } -+ } -+ -+ return k, new(G2).ScalarBaseMult(k), nil -+} -+ -+func (e *G2) String() string { -+ if e.p == nil { -+ return "bn256.G2" + newTwistPoint(nil).String() -+ } -+ return "bn256.G2" + e.p.String() -+} -+ -+// ScalarBaseMult sets e to g*k where g is the generator of the group and -+// then returns out. -+func (e *G2) ScalarBaseMult(k *big.Int) *G2 { -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ e.p.Mul(twistGen, k, new(bnPool)) -+ return e -+} -+ -+// ScalarMult sets e to a*k and then returns e. -+func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ e.p.Mul(a.p, k, new(bnPool)) -+ return e -+} -+ -+// Add sets e to a+b and then returns e. -+// -+// Warning: this function is not complete, it fails for a equal to b. -+func (e *G2) Add(a, b *G2) *G2 { -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ e.p.Add(a.p, b.p, new(bnPool)) -+ return e -+} -+ -+// Marshal converts n into a byte slice. -+func (n *G2) Marshal() []byte { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if n.p.IsInfinity() { -+ return make([]byte, numBytes*4) -+ } -+ -+ n.p.MakeAffine(nil) -+ -+ xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes() -+ xyBytes := new(big.Int).Mod(n.p.x.y, p).Bytes() -+ yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes() -+ yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes() -+ -+ ret := make([]byte, numBytes*4) -+ copy(ret[1*numBytes-len(xxBytes):], xxBytes) -+ copy(ret[2*numBytes-len(xyBytes):], xyBytes) -+ copy(ret[3*numBytes-len(yxBytes):], yxBytes) -+ copy(ret[4*numBytes-len(yyBytes):], yyBytes) -+ -+ return ret -+} -+ -+// Unmarshal sets e to the result of converting the output of Marshal back into -+// a group element and then returns e. -+func (e *G2) Unmarshal(m []byte) (*G2, bool) { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if len(m) != 4*numBytes { -+ return nil, false -+ } -+ -+ if e.p == nil { -+ e.p = newTwistPoint(nil) -+ } -+ -+ e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) -+ e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) -+ e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) -+ e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) -+ -+ if e.p.x.x.Sign() == 0 && -+ e.p.x.y.Sign() == 0 && -+ e.p.y.x.Sign() == 0 && -+ e.p.y.y.Sign() == 0 { -+ // This is the point at infinity. -+ e.p.y.SetOne() -+ e.p.z.SetZero() -+ e.p.t.SetZero() -+ } else { -+ e.p.z.SetOne() -+ e.p.t.SetOne() -+ -+ if !e.p.IsOnCurve() { -+ return nil, false -+ } -+ } -+ -+ return e, true -+} -+ -+// GT is an abstract cyclic group. The zero value is suitable for use as the -+// output of an operation, but cannot be used as an input. -+type GT struct { -+ p *gfP12 -+} -+ -+func (e *GT) String() string { -+ if e.p == nil { -+ return "bn256.GT" + newGFp12(nil).String() -+ } -+ return "bn256.GT" + e.p.String() -+} -+ -+// ScalarMult sets e to a*k and then returns e. -+func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ e.p.Exp(a.p, k, new(bnPool)) -+ return e -+} -+ -+// Add sets e to a+b and then returns e. -+func (e *GT) Add(a, b *GT) *GT { -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ e.p.Mul(a.p, b.p, new(bnPool)) -+ return e -+} -+ -+// Neg sets e to -a and then returns e. -+func (e *GT) Neg(a *GT) *GT { -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ e.p.Invert(a.p, new(bnPool)) -+ return e -+} -+ -+// Marshal converts n into a byte slice. -+func (n *GT) Marshal() []byte { -+ n.p.Minimal() -+ -+ xxxBytes := n.p.x.x.x.Bytes() -+ xxyBytes := n.p.x.x.y.Bytes() -+ xyxBytes := n.p.x.y.x.Bytes() -+ xyyBytes := n.p.x.y.y.Bytes() -+ xzxBytes := n.p.x.z.x.Bytes() -+ xzyBytes := n.p.x.z.y.Bytes() -+ yxxBytes := n.p.y.x.x.Bytes() -+ yxyBytes := n.p.y.x.y.Bytes() -+ yyxBytes := n.p.y.y.x.Bytes() -+ yyyBytes := n.p.y.y.y.Bytes() -+ yzxBytes := n.p.y.z.x.Bytes() -+ yzyBytes := n.p.y.z.y.Bytes() -+ -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ ret := make([]byte, numBytes*12) -+ copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) -+ copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) -+ copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) -+ copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) -+ copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) -+ copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) -+ copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) -+ copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) -+ copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) -+ copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) -+ copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) -+ copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) -+ -+ return ret -+} -+ -+// Unmarshal sets e to the result of converting the output of Marshal back into -+// a group element and then returns e. -+func (e *GT) Unmarshal(m []byte) (*GT, bool) { -+ // Each value is a 256-bit number. -+ const numBytes = 256 / 8 -+ -+ if len(m) != 12*numBytes { -+ return nil, false -+ } -+ -+ if e.p == nil { -+ e.p = newGFp12(nil) -+ } -+ -+ e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) -+ e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) -+ e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) -+ e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) -+ e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) -+ e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) -+ e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) -+ e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) -+ e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) -+ e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) -+ e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) -+ e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) -+ -+ return e, true -+} -+ -+// Pair calculates an Optimal Ate pairing. -+func Pair(g1 *G1, g2 *G2) *GT { -+ return >{optimalAte(g2.p, g1.p, new(bnPool))} -+} -+ -+// bnPool implements a tiny cache of *big.Int objects that's used to reduce the -+// number of allocations made during processing. -+type bnPool struct { -+ bns []*big.Int -+ count int -+} -+ -+func (pool *bnPool) Get() *big.Int { -+ if pool == nil { -+ return new(big.Int) -+ } -+ -+ pool.count++ -+ l := len(pool.bns) -+ if l == 0 { -+ return new(big.Int) -+ } -+ -+ bn := pool.bns[l-1] -+ pool.bns = pool.bns[:l-1] -+ return bn -+} -+ -+func (pool *bnPool) Put(bn *big.Int) { -+ if pool == nil { -+ return -+ } -+ pool.bns = append(pool.bns, bn) -+ pool.count-- -+} -+ -+func (pool *bnPool) Count() int { -+ return pool.count -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/bn256_test.go b/ms_mod/golang.org/x/crypto/bn256/bn256_test.go -new file mode 100644 -index 00000000000000..1cec3884ecd4c9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/bn256_test.go -@@ -0,0 +1,304 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "math/big" -+ "testing" -+) -+ -+func TestGFp2Invert(t *testing.T) { -+ pool := new(bnPool) -+ -+ a := newGFp2(pool) -+ a.x.SetString("23423492374", 10) -+ a.y.SetString("12934872398472394827398470", 10) -+ -+ inv := newGFp2(pool) -+ inv.Invert(a, pool) -+ -+ b := newGFp2(pool).Mul(inv, a, pool) -+ if b.x.Int64() != 0 || b.y.Int64() != 1 { -+ t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y) -+ } -+ -+ a.Put(pool) -+ b.Put(pool) -+ inv.Put(pool) -+ -+ if c := pool.Count(); c > 0 { -+ t.Errorf("Pool count non-zero: %d\n", c) -+ } -+} -+ -+func isZero(n *big.Int) bool { -+ return new(big.Int).Mod(n, p).Int64() == 0 -+} -+ -+func isOne(n *big.Int) bool { -+ return new(big.Int).Mod(n, p).Int64() == 1 -+} -+ -+func TestGFp6Invert(t *testing.T) { -+ pool := new(bnPool) -+ -+ a := newGFp6(pool) -+ a.x.x.SetString("239487238491", 10) -+ a.x.y.SetString("2356249827341", 10) -+ a.y.x.SetString("082659782", 10) -+ a.y.y.SetString("182703523765", 10) -+ a.z.x.SetString("978236549263", 10) -+ a.z.y.SetString("64893242", 10) -+ -+ inv := newGFp6(pool) -+ inv.Invert(a, pool) -+ -+ b := newGFp6(pool).Mul(inv, a, pool) -+ if !isZero(b.x.x) || -+ !isZero(b.x.y) || -+ !isZero(b.y.x) || -+ !isZero(b.y.y) || -+ !isZero(b.z.x) || -+ !isOne(b.z.y) { -+ t.Fatalf("bad result for a^-1*a: %s", b) -+ } -+ -+ a.Put(pool) -+ b.Put(pool) -+ inv.Put(pool) -+ -+ if c := pool.Count(); c > 0 { -+ t.Errorf("Pool count non-zero: %d\n", c) -+ } -+} -+ -+func TestGFp12Invert(t *testing.T) { -+ pool := new(bnPool) -+ -+ a := newGFp12(pool) -+ a.x.x.x.SetString("239846234862342323958623", 10) -+ a.x.x.y.SetString("2359862352529835623", 10) -+ a.x.y.x.SetString("928836523", 10) -+ a.x.y.y.SetString("9856234", 10) -+ a.x.z.x.SetString("235635286", 10) -+ a.x.z.y.SetString("5628392833", 10) -+ a.y.x.x.SetString("252936598265329856238956532167968", 10) -+ a.y.x.y.SetString("23596239865236954178968", 10) -+ a.y.y.x.SetString("95421692834", 10) -+ a.y.y.y.SetString("236548", 10) -+ a.y.z.x.SetString("924523", 10) -+ a.y.z.y.SetString("12954623", 10) -+ -+ inv := newGFp12(pool) -+ inv.Invert(a, pool) -+ -+ b := newGFp12(pool).Mul(inv, a, pool) -+ if !isZero(b.x.x.x) || -+ !isZero(b.x.x.y) || -+ !isZero(b.x.y.x) || -+ !isZero(b.x.y.y) || -+ !isZero(b.x.z.x) || -+ !isZero(b.x.z.y) || -+ !isZero(b.y.x.x) || -+ !isZero(b.y.x.y) || -+ !isZero(b.y.y.x) || -+ !isZero(b.y.y.y) || -+ !isZero(b.y.z.x) || -+ !isOne(b.y.z.y) { -+ t.Fatalf("bad result for a^-1*a: %s", b) -+ } -+ -+ a.Put(pool) -+ b.Put(pool) -+ inv.Put(pool) -+ -+ if c := pool.Count(); c > 0 { -+ t.Errorf("Pool count non-zero: %d\n", c) -+ } -+} -+ -+func TestCurveImpl(t *testing.T) { -+ pool := new(bnPool) -+ -+ g := &curvePoint{ -+ pool.Get().SetInt64(1), -+ pool.Get().SetInt64(-2), -+ pool.Get().SetInt64(1), -+ pool.Get().SetInt64(0), -+ } -+ -+ x := pool.Get().SetInt64(32498273234) -+ X := newCurvePoint(pool).Mul(g, x, pool) -+ -+ y := pool.Get().SetInt64(98732423523) -+ Y := newCurvePoint(pool).Mul(g, y, pool) -+ -+ s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool) -+ s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool) -+ -+ if s1.x.Cmp(s2.x) != 0 || -+ s2.x.Cmp(s1.x) != 0 { -+ t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y) -+ } -+ -+ pool.Put(x) -+ X.Put(pool) -+ pool.Put(y) -+ Y.Put(pool) -+ s1.Put(pool) -+ s2.Put(pool) -+ g.Put(pool) -+ -+ if c := pool.Count(); c > 0 { -+ t.Errorf("Pool count non-zero: %d\n", c) -+ } -+} -+ -+func TestOrderG1(t *testing.T) { -+ g := new(G1).ScalarBaseMult(Order) -+ if !g.p.IsInfinity() { -+ t.Error("G1 has incorrect order") -+ } -+ -+ one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) -+ g.Add(g, one) -+ g.p.MakeAffine(nil) -+ if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 { -+ t.Errorf("1+0 != 1 in G1") -+ } -+} -+ -+func TestOrderG2(t *testing.T) { -+ g := new(G2).ScalarBaseMult(Order) -+ if !g.p.IsInfinity() { -+ t.Error("G2 has incorrect order") -+ } -+ -+ one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) -+ g.Add(g, one) -+ g.p.MakeAffine(nil) -+ if g.p.x.x.Cmp(one.p.x.x) != 0 || -+ g.p.x.y.Cmp(one.p.x.y) != 0 || -+ g.p.y.x.Cmp(one.p.y.x) != 0 || -+ g.p.y.y.Cmp(one.p.y.y) != 0 { -+ t.Errorf("1+0 != 1 in G2") -+ } -+} -+ -+func TestOrderGT(t *testing.T) { -+ gt := Pair(&G1{curveGen}, &G2{twistGen}) -+ g := new(GT).ScalarMult(gt, Order) -+ if !g.p.IsOne() { -+ t.Error("GT has incorrect order") -+ } -+} -+ -+func TestBilinearity(t *testing.T) { -+ for i := 0; i < 2; i++ { -+ a, p1, _ := RandomG1(rand.Reader) -+ b, p2, _ := RandomG2(rand.Reader) -+ e1 := Pair(p1, p2) -+ -+ e2 := Pair(&G1{curveGen}, &G2{twistGen}) -+ e2.ScalarMult(e2, a) -+ e2.ScalarMult(e2, b) -+ -+ minusE2 := new(GT).Neg(e2) -+ e1.Add(e1, minusE2) -+ -+ if !e1.p.IsOne() { -+ t.Fatalf("bad pairing result: %s", e1) -+ } -+ } -+} -+ -+func TestG1Marshal(t *testing.T) { -+ g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) -+ form := g.Marshal() -+ _, ok := new(G1).Unmarshal(form) -+ if !ok { -+ t.Fatalf("failed to unmarshal") -+ } -+ -+ g.ScalarBaseMult(Order) -+ form = g.Marshal() -+ g2, ok := new(G1).Unmarshal(form) -+ if !ok { -+ t.Fatalf("failed to unmarshal ∞") -+ } -+ if !g2.p.IsInfinity() { -+ t.Fatalf("∞ unmarshaled incorrectly") -+ } -+} -+ -+func TestG2Marshal(t *testing.T) { -+ g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) -+ form := g.Marshal() -+ _, ok := new(G2).Unmarshal(form) -+ if !ok { -+ t.Fatalf("failed to unmarshal") -+ } -+ -+ g.ScalarBaseMult(Order) -+ form = g.Marshal() -+ g2, ok := new(G2).Unmarshal(form) -+ if !ok { -+ t.Fatalf("failed to unmarshal ∞") -+ } -+ if !g2.p.IsInfinity() { -+ t.Fatalf("∞ unmarshaled incorrectly") -+ } -+} -+ -+func TestG1Identity(t *testing.T) { -+ g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0)) -+ if !g.p.IsInfinity() { -+ t.Error("failure") -+ } -+} -+ -+func TestG2Identity(t *testing.T) { -+ g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0)) -+ if !g.p.IsInfinity() { -+ t.Error("failure") -+ } -+} -+ -+func TestTripartiteDiffieHellman(t *testing.T) { -+ a, _ := rand.Int(rand.Reader, Order) -+ b, _ := rand.Int(rand.Reader, Order) -+ c, _ := rand.Int(rand.Reader, Order) -+ -+ pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) -+ qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) -+ pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) -+ qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) -+ pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) -+ qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) -+ -+ k1 := Pair(pb, qc) -+ k1.ScalarMult(k1, a) -+ k1Bytes := k1.Marshal() -+ -+ k2 := Pair(pc, qa) -+ k2.ScalarMult(k2, b) -+ k2Bytes := k2.Marshal() -+ -+ k3 := Pair(pa, qb) -+ k3.ScalarMult(k3, c) -+ k3Bytes := k3.Marshal() -+ -+ if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { -+ t.Errorf("keys didn't agree") -+ } -+} -+ -+func BenchmarkPairing(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ Pair(&G1{curveGen}, &G2{twistGen}) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/constants.go b/ms_mod/golang.org/x/crypto/bn256/constants.go -new file mode 100644 -index 00000000000000..1ccefc4982aa2a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/constants.go -@@ -0,0 +1,44 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+import ( -+ "math/big" -+) -+ -+func bigFromBase10(s string) *big.Int { -+ n, _ := new(big.Int).SetString(s, 10) -+ return n -+} -+ -+// u is the BN parameter that determines the prime: 1868033Β³. -+var u = bigFromBase10("6518589491078791937") -+ -+// p is a prime over which we form a basic field: 36u⁴+36uΒ³+24uΒ²+6u+1. -+var p = bigFromBase10("65000549695646603732796438742359905742825358107623003571877145026864184071783") -+ -+// Order is the number of elements in both G₁ and Gβ‚‚: 36u⁴+36uΒ³+18uΒ²+6u+1. -+var Order = bigFromBase10("65000549695646603732796438742359905742570406053903786389881062969044166799969") -+ -+// xiToPMinus1Over6 is ΞΎ^((p-1)/6) where ΞΎ = i+3. -+var xiToPMinus1Over6 = &gfP2{bigFromBase10("8669379979083712429711189836753509758585994370025260553045152614783263110636"), bigFromBase10("19998038925833620163537568958541907098007303196759855091367510456613536016040")} -+ -+// xiToPMinus1Over3 is ΞΎ^((p-1)/3) where ΞΎ = i+3. -+var xiToPMinus1Over3 = &gfP2{bigFromBase10("26098034838977895781559542626833399156321265654106457577426020397262786167059"), bigFromBase10("15931493369629630809226283458085260090334794394361662678240713231519278691715")} -+ -+// xiToPMinus1Over2 is ΞΎ^((p-1)/2) where ΞΎ = i+3. -+var xiToPMinus1Over2 = &gfP2{bigFromBase10("50997318142241922852281555961173165965672272825141804376761836765206060036244"), bigFromBase10("38665955945962842195025998234511023902832543644254935982879660597356748036009")} -+ -+// xiToPSquaredMinus1Over3 is ΞΎ^((pΒ²-1)/3) where ΞΎ = i+3. -+var xiToPSquaredMinus1Over3 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437752") -+ -+// xiTo2PSquaredMinus2Over3 is ΞΎ^((2pΒ²-2)/3) where ΞΎ = i+3 (a cubic root of unity, mod p). -+var xiTo2PSquaredMinus2Over3 = bigFromBase10("4985783334309134261147736404674766913742361673560802634030") -+ -+// xiToPSquaredMinus1Over6 is ΞΎ^((1pΒ²-1)/6) where ΞΎ = i+3 (a cubic root of -1, mod p). -+var xiToPSquaredMinus1Over6 = bigFromBase10("65000549695646603727810655408050771481677621702948236658134783353303381437753") -+ -+// xiTo2PMinus2Over3 is ΞΎ^((2p-2)/3) where ΞΎ = i+3. -+var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19885131339612776214803633203834694332692106372356013117629940868870585019582"), bigFromBase10("21645619881471562101905880913352894726728173167203616652430647841922248593627")} -diff --git a/ms_mod/golang.org/x/crypto/bn256/curve.go b/ms_mod/golang.org/x/crypto/bn256/curve.go -new file mode 100644 -index 00000000000000..63c052bc22f2bf ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/curve.go -@@ -0,0 +1,287 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+import ( -+ "math/big" -+) -+ -+// curvePoint implements the elliptic curve yΒ²=xΒ³+3. Points are kept in -+// Jacobian form and t=zΒ² when valid. G₁ is the set of points of this curve on -+// GF(p). -+type curvePoint struct { -+ x, y, z, t *big.Int -+} -+ -+var curveB = new(big.Int).SetInt64(3) -+ -+// curveGen is the generator of G₁. -+var curveGen = &curvePoint{ -+ new(big.Int).SetInt64(1), -+ new(big.Int).SetInt64(-2), -+ new(big.Int).SetInt64(1), -+ new(big.Int).SetInt64(1), -+} -+ -+func newCurvePoint(pool *bnPool) *curvePoint { -+ return &curvePoint{ -+ pool.Get(), -+ pool.Get(), -+ pool.Get(), -+ pool.Get(), -+ } -+} -+ -+func (c *curvePoint) String() string { -+ c.MakeAffine(new(bnPool)) -+ return "(" + c.x.String() + ", " + c.y.String() + ")" -+} -+ -+func (c *curvePoint) Put(pool *bnPool) { -+ pool.Put(c.x) -+ pool.Put(c.y) -+ pool.Put(c.z) -+ pool.Put(c.t) -+} -+ -+func (c *curvePoint) Set(a *curvePoint) { -+ c.x.Set(a.x) -+ c.y.Set(a.y) -+ c.z.Set(a.z) -+ c.t.Set(a.t) -+} -+ -+// IsOnCurve returns true iff c is on the curve where c must be in affine form. -+func (c *curvePoint) IsOnCurve() bool { -+ yy := new(big.Int).Mul(c.y, c.y) -+ xxx := new(big.Int).Mul(c.x, c.x) -+ xxx.Mul(xxx, c.x) -+ yy.Sub(yy, xxx) -+ yy.Sub(yy, curveB) -+ if yy.Sign() < 0 || yy.Cmp(p) >= 0 { -+ yy.Mod(yy, p) -+ } -+ return yy.Sign() == 0 -+} -+ -+func (c *curvePoint) SetInfinity() { -+ c.z.SetInt64(0) -+} -+ -+func (c *curvePoint) IsInfinity() bool { -+ return c.z.Sign() == 0 -+} -+ -+func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { -+ if a.IsInfinity() { -+ c.Set(b) -+ return -+ } -+ if b.IsInfinity() { -+ c.Set(a) -+ return -+ } -+ -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 -+ -+ // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] -+ // by [u1:s1:z1Β·z2] and [u2:s2:z1Β·z2] -+ // where u1 = x1Β·z2Β², s1 = y1Β·z2Β³ and u1 = x2Β·z1Β², s2 = y2Β·z1Β³ -+ z1z1 := pool.Get().Mul(a.z, a.z) -+ z1z1.Mod(z1z1, p) -+ z2z2 := pool.Get().Mul(b.z, b.z) -+ z2z2.Mod(z2z2, p) -+ u1 := pool.Get().Mul(a.x, z2z2) -+ u1.Mod(u1, p) -+ u2 := pool.Get().Mul(b.x, z1z1) -+ u2.Mod(u2, p) -+ -+ t := pool.Get().Mul(b.z, z2z2) -+ t.Mod(t, p) -+ s1 := pool.Get().Mul(a.y, t) -+ s1.Mod(s1, p) -+ -+ t.Mul(a.z, z1z1) -+ t.Mod(t, p) -+ s2 := pool.Get().Mul(b.y, t) -+ s2.Mod(s2, p) -+ -+ // Compute x = (2h)Β²(sΒ²-u1-u2) -+ // where s = (s2-s1)/(u2-u1) is the slope of the line through -+ // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. -+ // This is also: -+ // 4(s2-s1)Β² - 4hΒ²(u1+u2) = 4(s2-s1)Β² - 4hΒ³ - 4hΒ²(2u1) -+ // = rΒ² - j - 2v -+ // with the notations below. -+ h := pool.Get().Sub(u2, u1) -+ xEqual := h.Sign() == 0 -+ -+ t.Add(h, h) -+ // i = 4hΒ² -+ i := pool.Get().Mul(t, t) -+ i.Mod(i, p) -+ // j = 4hΒ³ -+ j := pool.Get().Mul(h, i) -+ j.Mod(j, p) -+ -+ t.Sub(s2, s1) -+ yEqual := t.Sign() == 0 -+ if xEqual && yEqual { -+ c.Double(a, pool) -+ return -+ } -+ r := pool.Get().Add(t, t) -+ -+ v := pool.Get().Mul(u1, i) -+ v.Mod(v, p) -+ -+ // t4 = 4(s2-s1)Β² -+ t4 := pool.Get().Mul(r, r) -+ t4.Mod(t4, p) -+ t.Add(v, v) -+ t6 := pool.Get().Sub(t4, j) -+ c.x.Sub(t6, t) -+ -+ // Set y = -(2h)Β³(s1 + s*(x/4hΒ²-u1)) -+ // This is also -+ // y = - 2Β·s1Β·j - (s2-s1)(2x - 2iΒ·u1) = r(v-x) - 2Β·s1Β·j -+ t.Sub(v, c.x) // t7 -+ t4.Mul(s1, j) // t8 -+ t4.Mod(t4, p) -+ t6.Add(t4, t4) // t9 -+ t4.Mul(r, t) // t10 -+ t4.Mod(t4, p) -+ c.y.Sub(t4, t6) -+ -+ // Set z = 2(u2-u1)Β·z1Β·z2 = 2hΒ·z1Β·z2 -+ t.Add(a.z, b.z) // t11 -+ t4.Mul(t, t) // t12 -+ t4.Mod(t4, p) -+ t.Sub(t4, z1z1) // t13 -+ t4.Sub(t, z2z2) // t14 -+ c.z.Mul(t4, h) -+ c.z.Mod(c.z, p) -+ -+ pool.Put(z1z1) -+ pool.Put(z2z2) -+ pool.Put(u1) -+ pool.Put(u2) -+ pool.Put(t) -+ pool.Put(s1) -+ pool.Put(s2) -+ pool.Put(h) -+ pool.Put(i) -+ pool.Put(j) -+ pool.Put(r) -+ pool.Put(v) -+ pool.Put(t4) -+ pool.Put(t6) -+} -+ -+func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 -+ A := pool.Get().Mul(a.x, a.x) -+ A.Mod(A, p) -+ B := pool.Get().Mul(a.y, a.y) -+ B.Mod(B, p) -+ C := pool.Get().Mul(B, B) -+ C.Mod(C, p) -+ -+ t := pool.Get().Add(a.x, B) -+ t2 := pool.Get().Mul(t, t) -+ t2.Mod(t2, p) -+ t.Sub(t2, A) -+ t2.Sub(t, C) -+ d := pool.Get().Add(t2, t2) -+ t.Add(A, A) -+ e := pool.Get().Add(t, A) -+ f := pool.Get().Mul(e, e) -+ f.Mod(f, p) -+ -+ t.Add(d, d) -+ c.x.Sub(f, t) -+ -+ t.Add(C, C) -+ t2.Add(t, t) -+ t.Add(t2, t2) -+ c.y.Sub(d, c.x) -+ t2.Mul(e, c.y) -+ t2.Mod(t2, p) -+ c.y.Sub(t2, t) -+ -+ t.Mul(a.y, a.z) -+ t.Mod(t, p) -+ c.z.Add(t, t) -+ -+ pool.Put(A) -+ pool.Put(B) -+ pool.Put(C) -+ pool.Put(t) -+ pool.Put(t2) -+ pool.Put(d) -+ pool.Put(e) -+ pool.Put(f) -+} -+ -+func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { -+ sum := newCurvePoint(pool) -+ sum.SetInfinity() -+ t := newCurvePoint(pool) -+ -+ for i := scalar.BitLen(); i >= 0; i-- { -+ t.Double(sum, pool) -+ if scalar.Bit(i) != 0 { -+ sum.Add(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ sum.Put(pool) -+ t.Put(pool) -+ return c -+} -+ -+// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets -+// c to 0 : 1 : 0. -+func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { -+ if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { -+ return c -+ } -+ if c.IsInfinity() { -+ c.x.SetInt64(0) -+ c.y.SetInt64(1) -+ c.z.SetInt64(0) -+ c.t.SetInt64(0) -+ return c -+ } -+ -+ zInv := pool.Get().ModInverse(c.z, p) -+ t := pool.Get().Mul(c.y, zInv) -+ t.Mod(t, p) -+ zInv2 := pool.Get().Mul(zInv, zInv) -+ zInv2.Mod(zInv2, p) -+ c.y.Mul(t, zInv2) -+ c.y.Mod(c.y, p) -+ t.Mul(c.x, zInv2) -+ t.Mod(t, p) -+ c.x.Set(t) -+ c.z.SetInt64(1) -+ c.t.SetInt64(1) -+ -+ pool.Put(zInv) -+ pool.Put(t) -+ pool.Put(zInv2) -+ -+ return c -+} -+ -+func (c *curvePoint) Negative(a *curvePoint) { -+ c.x.Set(a.x) -+ c.y.Neg(a.y) -+ c.z.Set(a.z) -+ c.t.SetInt64(0) -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/example_test.go b/ms_mod/golang.org/x/crypto/bn256/example_test.go -new file mode 100644 -index 00000000000000..b2d19807a25e6d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/example_test.go -@@ -0,0 +1,43 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+import ( -+ "crypto/rand" -+) -+ -+func ExamplePair() { -+ // This implements the tripartite Diffie-Hellman algorithm from "A One -+ // Round Protocol for Tripartite Diffie-Hellman", A. Joux. -+ // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf -+ -+ // Each of three parties, a, b and c, generate a private value. -+ a, _ := rand.Int(rand.Reader, Order) -+ b, _ := rand.Int(rand.Reader, Order) -+ c, _ := rand.Int(rand.Reader, Order) -+ -+ // Then each party calculates g₁ and gβ‚‚ times their private value. -+ pa := new(G1).ScalarBaseMult(a) -+ qa := new(G2).ScalarBaseMult(a) -+ -+ pb := new(G1).ScalarBaseMult(b) -+ qb := new(G2).ScalarBaseMult(b) -+ -+ pc := new(G1).ScalarBaseMult(c) -+ qc := new(G2).ScalarBaseMult(c) -+ -+ // Now each party exchanges its public values with the other two and -+ // all parties can calculate the shared key. -+ k1 := Pair(pb, qc) -+ k1.ScalarMult(k1, a) -+ -+ k2 := Pair(pc, qa) -+ k2.ScalarMult(k2, b) -+ -+ k3 := Pair(pa, qb) -+ k3.ScalarMult(k3, c) -+ -+ // k1, k2 and k3 will all be equal. -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/gfp12.go b/ms_mod/golang.org/x/crypto/bn256/gfp12.go -new file mode 100644 -index 00000000000000..2b0151ebcc4924 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/gfp12.go -@@ -0,0 +1,200 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+// For details of the algorithms used, see "Multiplication and Squaring on -+// Pairing-Friendly Fields, Devegili et al. -+// http://eprint.iacr.org/2006/471.pdf. -+ -+import ( -+ "math/big" -+) -+ -+// gfP12 implements the field of size pΒΉΒ² as a quadratic extension of gfP6 -+// where ω²=Ο„. -+type gfP12 struct { -+ x, y *gfP6 // value is xΟ‰ + y -+} -+ -+func newGFp12(pool *bnPool) *gfP12 { -+ return &gfP12{newGFp6(pool), newGFp6(pool)} -+} -+ -+func (e *gfP12) String() string { -+ return "(" + e.x.String() + "," + e.y.String() + ")" -+} -+ -+func (e *gfP12) Put(pool *bnPool) { -+ e.x.Put(pool) -+ e.y.Put(pool) -+} -+ -+func (e *gfP12) Set(a *gfP12) *gfP12 { -+ e.x.Set(a.x) -+ e.y.Set(a.y) -+ return e -+} -+ -+func (e *gfP12) SetZero() *gfP12 { -+ e.x.SetZero() -+ e.y.SetZero() -+ return e -+} -+ -+func (e *gfP12) SetOne() *gfP12 { -+ e.x.SetZero() -+ e.y.SetOne() -+ return e -+} -+ -+func (e *gfP12) Minimal() { -+ e.x.Minimal() -+ e.y.Minimal() -+} -+ -+func (e *gfP12) IsZero() bool { -+ e.Minimal() -+ return e.x.IsZero() && e.y.IsZero() -+} -+ -+func (e *gfP12) IsOne() bool { -+ e.Minimal() -+ return e.x.IsZero() && e.y.IsOne() -+} -+ -+func (e *gfP12) Conjugate(a *gfP12) *gfP12 { -+ e.x.Negative(a.x) -+ e.y.Set(a.y) -+ return a -+} -+ -+func (e *gfP12) Negative(a *gfP12) *gfP12 { -+ e.x.Negative(a.x) -+ e.y.Negative(a.y) -+ return e -+} -+ -+// Frobenius computes (xΟ‰+y)^p = x^p ω·ξ^((p-1)/6) + y^p -+func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { -+ e.x.Frobenius(a.x, pool) -+ e.y.Frobenius(a.y, pool) -+ e.x.MulScalar(e.x, xiToPMinus1Over6, pool) -+ return e -+} -+ -+// FrobeniusP2 computes (xΟ‰+y)^pΒ² = x^pΒ² ω·ξ^((pΒ²-1)/6) + y^pΒ² -+func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { -+ e.x.FrobeniusP2(a.x) -+ e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) -+ e.y.FrobeniusP2(a.y) -+ return e -+} -+ -+func (e *gfP12) Add(a, b *gfP12) *gfP12 { -+ e.x.Add(a.x, b.x) -+ e.y.Add(a.y, b.y) -+ return e -+} -+ -+func (e *gfP12) Sub(a, b *gfP12) *gfP12 { -+ e.x.Sub(a.x, b.x) -+ e.y.Sub(a.y, b.y) -+ return e -+} -+ -+func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { -+ tx := newGFp6(pool) -+ tx.Mul(a.x, b.y, pool) -+ t := newGFp6(pool) -+ t.Mul(b.x, a.y, pool) -+ tx.Add(tx, t) -+ -+ ty := newGFp6(pool) -+ ty.Mul(a.y, b.y, pool) -+ t.Mul(a.x, b.x, pool) -+ t.MulTau(t, pool) -+ e.y.Add(ty, t) -+ e.x.Set(tx) -+ -+ tx.Put(pool) -+ ty.Put(pool) -+ t.Put(pool) -+ return e -+} -+ -+func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { -+ e.x.Mul(a.x, b, pool) -+ e.y.Mul(a.y, b, pool) -+ return e -+} -+ -+func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { -+ sum := newGFp12(pool) -+ sum.SetOne() -+ t := newGFp12(pool) -+ -+ for i := power.BitLen() - 1; i >= 0; i-- { -+ t.Square(sum, pool) -+ if power.Bit(i) != 0 { -+ sum.Mul(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ -+ sum.Put(pool) -+ t.Put(pool) -+ -+ return c -+} -+ -+func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { -+ // Complex squaring algorithm -+ v0 := newGFp6(pool) -+ v0.Mul(a.x, a.y, pool) -+ -+ t := newGFp6(pool) -+ t.MulTau(a.x, pool) -+ t.Add(a.y, t) -+ ty := newGFp6(pool) -+ ty.Add(a.x, a.y) -+ ty.Mul(ty, t, pool) -+ ty.Sub(ty, v0) -+ t.MulTau(v0, pool) -+ ty.Sub(ty, t) -+ -+ e.y.Set(ty) -+ e.x.Double(v0) -+ -+ v0.Put(pool) -+ t.Put(pool) -+ ty.Put(pool) -+ -+ return e -+} -+ -+func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { -+ // See "Implementing cryptographic pairings", M. Scott, section 3.2. -+ // ftp://136.206.11.249/pub/crypto/pairings.pdf -+ t1 := newGFp6(pool) -+ t2 := newGFp6(pool) -+ -+ t1.Square(a.x, pool) -+ t2.Square(a.y, pool) -+ t1.MulTau(t1, pool) -+ t1.Sub(t2, t1) -+ t2.Invert(t1, pool) -+ -+ e.x.Negative(a.x) -+ e.y.Set(a.y) -+ e.MulScalar(e, t2, pool) -+ -+ t1.Put(pool) -+ t2.Put(pool) -+ -+ return e -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/gfp2.go b/ms_mod/golang.org/x/crypto/bn256/gfp2.go -new file mode 100644 -index 00000000000000..97f3f1f3fa1a0e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/gfp2.go -@@ -0,0 +1,219 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+// For details of the algorithms used, see "Multiplication and Squaring on -+// Pairing-Friendly Fields, Devegili et al. -+// http://eprint.iacr.org/2006/471.pdf. -+ -+import ( -+ "math/big" -+) -+ -+// gfP2 implements a field of size pΒ² as a quadratic extension of the base -+// field where iΒ²=-1. -+type gfP2 struct { -+ x, y *big.Int // value is xi+y. -+} -+ -+func newGFp2(pool *bnPool) *gfP2 { -+ return &gfP2{pool.Get(), pool.Get()} -+} -+ -+func (e *gfP2) String() string { -+ x := new(big.Int).Mod(e.x, p) -+ y := new(big.Int).Mod(e.y, p) -+ return "(" + x.String() + "," + y.String() + ")" -+} -+ -+func (e *gfP2) Put(pool *bnPool) { -+ pool.Put(e.x) -+ pool.Put(e.y) -+} -+ -+func (e *gfP2) Set(a *gfP2) *gfP2 { -+ e.x.Set(a.x) -+ e.y.Set(a.y) -+ return e -+} -+ -+func (e *gfP2) SetZero() *gfP2 { -+ e.x.SetInt64(0) -+ e.y.SetInt64(0) -+ return e -+} -+ -+func (e *gfP2) SetOne() *gfP2 { -+ e.x.SetInt64(0) -+ e.y.SetInt64(1) -+ return e -+} -+ -+func (e *gfP2) Minimal() { -+ if e.x.Sign() < 0 || e.x.Cmp(p) >= 0 { -+ e.x.Mod(e.x, p) -+ } -+ if e.y.Sign() < 0 || e.y.Cmp(p) >= 0 { -+ e.y.Mod(e.y, p) -+ } -+} -+ -+func (e *gfP2) IsZero() bool { -+ return e.x.Sign() == 0 && e.y.Sign() == 0 -+} -+ -+func (e *gfP2) IsOne() bool { -+ if e.x.Sign() != 0 { -+ return false -+ } -+ words := e.y.Bits() -+ return len(words) == 1 && words[0] == 1 -+} -+ -+func (e *gfP2) Conjugate(a *gfP2) *gfP2 { -+ e.y.Set(a.y) -+ e.x.Neg(a.x) -+ return e -+} -+ -+func (e *gfP2) Negative(a *gfP2) *gfP2 { -+ e.x.Neg(a.x) -+ e.y.Neg(a.y) -+ return e -+} -+ -+func (e *gfP2) Add(a, b *gfP2) *gfP2 { -+ e.x.Add(a.x, b.x) -+ e.y.Add(a.y, b.y) -+ return e -+} -+ -+func (e *gfP2) Sub(a, b *gfP2) *gfP2 { -+ e.x.Sub(a.x, b.x) -+ e.y.Sub(a.y, b.y) -+ return e -+} -+ -+func (e *gfP2) Double(a *gfP2) *gfP2 { -+ e.x.Lsh(a.x, 1) -+ e.y.Lsh(a.y, 1) -+ return e -+} -+ -+func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { -+ sum := newGFp2(pool) -+ sum.SetOne() -+ t := newGFp2(pool) -+ -+ for i := power.BitLen() - 1; i >= 0; i-- { -+ t.Square(sum, pool) -+ if power.Bit(i) != 0 { -+ sum.Mul(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ -+ sum.Put(pool) -+ t.Put(pool) -+ -+ return c -+} -+ -+// See "Multiplication and Squaring in Pairing-Friendly Fields", -+// http://eprint.iacr.org/2006/471.pdf -+func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { -+ tx := pool.Get().Mul(a.x, b.y) -+ t := pool.Get().Mul(b.x, a.y) -+ tx.Add(tx, t) -+ tx.Mod(tx, p) -+ -+ ty := pool.Get().Mul(a.y, b.y) -+ t.Mul(a.x, b.x) -+ ty.Sub(ty, t) -+ e.y.Mod(ty, p) -+ e.x.Set(tx) -+ -+ pool.Put(tx) -+ pool.Put(ty) -+ pool.Put(t) -+ -+ return e -+} -+ -+func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { -+ e.x.Mul(a.x, b) -+ e.y.Mul(a.y, b) -+ return e -+} -+ -+// MulXi sets e=ΞΎa where ΞΎ=i+3 and then returns e. -+func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { -+ // (xi+y)(i+3) = (3x+y)i+(3y-x) -+ tx := pool.Get().Lsh(a.x, 1) -+ tx.Add(tx, a.x) -+ tx.Add(tx, a.y) -+ -+ ty := pool.Get().Lsh(a.y, 1) -+ ty.Add(ty, a.y) -+ ty.Sub(ty, a.x) -+ -+ e.x.Set(tx) -+ e.y.Set(ty) -+ -+ pool.Put(tx) -+ pool.Put(ty) -+ -+ return e -+} -+ -+func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { -+ // Complex squaring algorithm: -+ // (xi+b)Β² = (x+y)(y-x) + 2*i*x*y -+ t1 := pool.Get().Sub(a.y, a.x) -+ t2 := pool.Get().Add(a.x, a.y) -+ ty := pool.Get().Mul(t1, t2) -+ ty.Mod(ty, p) -+ -+ t1.Mul(a.x, a.y) -+ t1.Lsh(t1, 1) -+ -+ e.x.Mod(t1, p) -+ e.y.Set(ty) -+ -+ pool.Put(t1) -+ pool.Put(t2) -+ pool.Put(ty) -+ -+ return e -+} -+ -+func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { -+ // See "Implementing cryptographic pairings", M. Scott, section 3.2. -+ // ftp://136.206.11.249/pub/crypto/pairings.pdf -+ t := pool.Get() -+ t.Mul(a.y, a.y) -+ t2 := pool.Get() -+ t2.Mul(a.x, a.x) -+ t.Add(t, t2) -+ -+ inv := pool.Get() -+ inv.ModInverse(t, p) -+ -+ e.x.Neg(a.x) -+ e.x.Mul(e.x, inv) -+ e.x.Mod(e.x, p) -+ -+ e.y.Mul(a.y, inv) -+ e.y.Mod(e.y, p) -+ -+ pool.Put(t) -+ pool.Put(t2) -+ pool.Put(inv) -+ -+ return e -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/gfp6.go b/ms_mod/golang.org/x/crypto/bn256/gfp6.go -new file mode 100644 -index 00000000000000..f98ae782cc154a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/gfp6.go -@@ -0,0 +1,296 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+// For details of the algorithms used, see "Multiplication and Squaring on -+// Pairing-Friendly Fields, Devegili et al. -+// http://eprint.iacr.org/2006/471.pdf. -+ -+import ( -+ "math/big" -+) -+ -+// gfP6 implements the field of size p⁢ as a cubic extension of gfP2 where τ³=ΞΎ -+// and ΞΎ=i+3. -+type gfP6 struct { -+ x, y, z *gfP2 // value is xτ² + yΟ„ + z -+} -+ -+func newGFp6(pool *bnPool) *gfP6 { -+ return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} -+} -+ -+func (e *gfP6) String() string { -+ return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" -+} -+ -+func (e *gfP6) Put(pool *bnPool) { -+ e.x.Put(pool) -+ e.y.Put(pool) -+ e.z.Put(pool) -+} -+ -+func (e *gfP6) Set(a *gfP6) *gfP6 { -+ e.x.Set(a.x) -+ e.y.Set(a.y) -+ e.z.Set(a.z) -+ return e -+} -+ -+func (e *gfP6) SetZero() *gfP6 { -+ e.x.SetZero() -+ e.y.SetZero() -+ e.z.SetZero() -+ return e -+} -+ -+func (e *gfP6) SetOne() *gfP6 { -+ e.x.SetZero() -+ e.y.SetZero() -+ e.z.SetOne() -+ return e -+} -+ -+func (e *gfP6) Minimal() { -+ e.x.Minimal() -+ e.y.Minimal() -+ e.z.Minimal() -+} -+ -+func (e *gfP6) IsZero() bool { -+ return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() -+} -+ -+func (e *gfP6) IsOne() bool { -+ return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() -+} -+ -+func (e *gfP6) Negative(a *gfP6) *gfP6 { -+ e.x.Negative(a.x) -+ e.y.Negative(a.y) -+ e.z.Negative(a.z) -+ return e -+} -+ -+func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { -+ e.x.Conjugate(a.x) -+ e.y.Conjugate(a.y) -+ e.z.Conjugate(a.z) -+ -+ e.x.Mul(e.x, xiTo2PMinus2Over3, pool) -+ e.y.Mul(e.y, xiToPMinus1Over3, pool) -+ return e -+} -+ -+// FrobeniusP2 computes (xτ²+yΟ„+z)^(pΒ²) = xΟ„^(2pΒ²) + yΟ„^(pΒ²) + z -+func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { -+ // Ο„^(2pΒ²) = τ²τ^(2pΒ²-2) = τ²ξ^((2pΒ²-2)/3) -+ e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) -+ // Ο„^(pΒ²) = ττ^(pΒ²-1) = τξ^((pΒ²-1)/3) -+ e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) -+ e.z.Set(a.z) -+ return e -+} -+ -+func (e *gfP6) Add(a, b *gfP6) *gfP6 { -+ e.x.Add(a.x, b.x) -+ e.y.Add(a.y, b.y) -+ e.z.Add(a.z, b.z) -+ return e -+} -+ -+func (e *gfP6) Sub(a, b *gfP6) *gfP6 { -+ e.x.Sub(a.x, b.x) -+ e.y.Sub(a.y, b.y) -+ e.z.Sub(a.z, b.z) -+ return e -+} -+ -+func (e *gfP6) Double(a *gfP6) *gfP6 { -+ e.x.Double(a.x) -+ e.y.Double(a.y) -+ e.z.Double(a.z) -+ return e -+} -+ -+func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { -+ // "Multiplication and Squaring on Pairing-Friendly Fields" -+ // Section 4, Karatsuba method. -+ // http://eprint.iacr.org/2006/471.pdf -+ -+ v0 := newGFp2(pool) -+ v0.Mul(a.z, b.z, pool) -+ v1 := newGFp2(pool) -+ v1.Mul(a.y, b.y, pool) -+ v2 := newGFp2(pool) -+ v2.Mul(a.x, b.x, pool) -+ -+ t0 := newGFp2(pool) -+ t0.Add(a.x, a.y) -+ t1 := newGFp2(pool) -+ t1.Add(b.x, b.y) -+ tz := newGFp2(pool) -+ tz.Mul(t0, t1, pool) -+ -+ tz.Sub(tz, v1) -+ tz.Sub(tz, v2) -+ tz.MulXi(tz, pool) -+ tz.Add(tz, v0) -+ -+ t0.Add(a.y, a.z) -+ t1.Add(b.y, b.z) -+ ty := newGFp2(pool) -+ ty.Mul(t0, t1, pool) -+ ty.Sub(ty, v0) -+ ty.Sub(ty, v1) -+ t0.MulXi(v2, pool) -+ ty.Add(ty, t0) -+ -+ t0.Add(a.x, a.z) -+ t1.Add(b.x, b.z) -+ tx := newGFp2(pool) -+ tx.Mul(t0, t1, pool) -+ tx.Sub(tx, v0) -+ tx.Add(tx, v1) -+ tx.Sub(tx, v2) -+ -+ e.x.Set(tx) -+ e.y.Set(ty) -+ e.z.Set(tz) -+ -+ t0.Put(pool) -+ t1.Put(pool) -+ tx.Put(pool) -+ ty.Put(pool) -+ tz.Put(pool) -+ v0.Put(pool) -+ v1.Put(pool) -+ v2.Put(pool) -+ return e -+} -+ -+func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { -+ e.x.Mul(a.x, b, pool) -+ e.y.Mul(a.y, b, pool) -+ e.z.Mul(a.z, b, pool) -+ return e -+} -+ -+func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { -+ e.x.MulScalar(a.x, b) -+ e.y.MulScalar(a.y, b) -+ e.z.MulScalar(a.z, b) -+ return e -+} -+ -+// MulTau computes τ·(aτ²+bΟ„+c) = bτ²+cΟ„+aΞΎ -+func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { -+ tz := newGFp2(pool) -+ tz.MulXi(a.x, pool) -+ ty := newGFp2(pool) -+ ty.Set(a.y) -+ e.y.Set(a.z) -+ e.x.Set(ty) -+ e.z.Set(tz) -+ tz.Put(pool) -+ ty.Put(pool) -+} -+ -+func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { -+ v0 := newGFp2(pool).Square(a.z, pool) -+ v1 := newGFp2(pool).Square(a.y, pool) -+ v2 := newGFp2(pool).Square(a.x, pool) -+ -+ c0 := newGFp2(pool).Add(a.x, a.y) -+ c0.Square(c0, pool) -+ c0.Sub(c0, v1) -+ c0.Sub(c0, v2) -+ c0.MulXi(c0, pool) -+ c0.Add(c0, v0) -+ -+ c1 := newGFp2(pool).Add(a.y, a.z) -+ c1.Square(c1, pool) -+ c1.Sub(c1, v0) -+ c1.Sub(c1, v1) -+ xiV2 := newGFp2(pool).MulXi(v2, pool) -+ c1.Add(c1, xiV2) -+ -+ c2 := newGFp2(pool).Add(a.x, a.z) -+ c2.Square(c2, pool) -+ c2.Sub(c2, v0) -+ c2.Add(c2, v1) -+ c2.Sub(c2, v2) -+ -+ e.x.Set(c2) -+ e.y.Set(c1) -+ e.z.Set(c0) -+ -+ v0.Put(pool) -+ v1.Put(pool) -+ v2.Put(pool) -+ c0.Put(pool) -+ c1.Put(pool) -+ c2.Put(pool) -+ xiV2.Put(pool) -+ -+ return e -+} -+ -+func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { -+ // See "Implementing cryptographic pairings", M. Scott, section 3.2. -+ // ftp://136.206.11.249/pub/crypto/pairings.pdf -+ -+ // Here we can give a short explanation of how it works: let j be a cubic root of -+ // unity in GF(pΒ²) so that 1+j+jΒ²=0. -+ // Then (xτ² + yΟ„ + z)(xj²τ² + yjΟ„ + z)(xjτ² + yjΒ²Ο„ + z) -+ // = (xτ² + yΟ„ + z)(Cτ²+BΟ„+A) -+ // = (xΒ³ΞΎΒ²+yΒ³ΞΎ+zΒ³-3ΞΎxyz) = F is an element of the base field (the norm). -+ // -+ // On the other hand (xj²τ² + yjΟ„ + z)(xjτ² + yjΒ²Ο„ + z) -+ // = τ²(yΒ²-ΞΎxz) + Ο„(ΞΎxΒ²-yz) + (zΒ²-ΞΎxy) -+ // -+ // So that's why A = (zΒ²-ΞΎxy), B = (ΞΎxΒ²-yz), C = (yΒ²-ΞΎxz) -+ t1 := newGFp2(pool) -+ -+ A := newGFp2(pool) -+ A.Square(a.z, pool) -+ t1.Mul(a.x, a.y, pool) -+ t1.MulXi(t1, pool) -+ A.Sub(A, t1) -+ -+ B := newGFp2(pool) -+ B.Square(a.x, pool) -+ B.MulXi(B, pool) -+ t1.Mul(a.y, a.z, pool) -+ B.Sub(B, t1) -+ -+ C := newGFp2(pool) -+ C.Square(a.y, pool) -+ t1.Mul(a.x, a.z, pool) -+ C.Sub(C, t1) -+ -+ F := newGFp2(pool) -+ F.Mul(C, a.y, pool) -+ F.MulXi(F, pool) -+ t1.Mul(A, a.z, pool) -+ F.Add(F, t1) -+ t1.Mul(B, a.x, pool) -+ t1.MulXi(t1, pool) -+ F.Add(F, t1) -+ -+ F.Invert(F, pool) -+ -+ e.x.Mul(C, F, pool) -+ e.y.Mul(B, F, pool) -+ e.z.Mul(A, F, pool) -+ -+ t1.Put(pool) -+ A.Put(pool) -+ B.Put(pool) -+ C.Put(pool) -+ F.Put(pool) -+ -+ return e -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/optate.go b/ms_mod/golang.org/x/crypto/bn256/optate.go -new file mode 100644 -index 00000000000000..7ae0746eb10b89 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/optate.go -@@ -0,0 +1,395 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { -+ // See the mixed addition algorithm from "Faster Computation of the -+ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf -+ -+ B := newGFp2(pool).Mul(p.x, r.t, pool) -+ -+ D := newGFp2(pool).Add(p.y, r.z) -+ D.Square(D, pool) -+ D.Sub(D, r2) -+ D.Sub(D, r.t) -+ D.Mul(D, r.t, pool) -+ -+ H := newGFp2(pool).Sub(B, r.x) -+ I := newGFp2(pool).Square(H, pool) -+ -+ E := newGFp2(pool).Add(I, I) -+ E.Add(E, E) -+ -+ J := newGFp2(pool).Mul(H, E, pool) -+ -+ L1 := newGFp2(pool).Sub(D, r.y) -+ L1.Sub(L1, r.y) -+ -+ V := newGFp2(pool).Mul(r.x, E, pool) -+ -+ rOut = newTwistPoint(pool) -+ rOut.x.Square(L1, pool) -+ rOut.x.Sub(rOut.x, J) -+ rOut.x.Sub(rOut.x, V) -+ rOut.x.Sub(rOut.x, V) -+ -+ rOut.z.Add(r.z, H) -+ rOut.z.Square(rOut.z, pool) -+ rOut.z.Sub(rOut.z, r.t) -+ rOut.z.Sub(rOut.z, I) -+ -+ t := newGFp2(pool).Sub(V, rOut.x) -+ t.Mul(t, L1, pool) -+ t2 := newGFp2(pool).Mul(r.y, J, pool) -+ t2.Add(t2, t2) -+ rOut.y.Sub(t, t2) -+ -+ rOut.t.Square(rOut.z, pool) -+ -+ t.Add(p.y, rOut.z) -+ t.Square(t, pool) -+ t.Sub(t, r2) -+ t.Sub(t, rOut.t) -+ -+ t2.Mul(L1, p.x, pool) -+ t2.Add(t2, t2) -+ a = newGFp2(pool) -+ a.Sub(t2, t) -+ -+ c = newGFp2(pool) -+ c.MulScalar(rOut.z, q.y) -+ c.Add(c, c) -+ -+ b = newGFp2(pool) -+ b.SetZero() -+ b.Sub(b, L1) -+ b.MulScalar(b, q.x) -+ b.Add(b, b) -+ -+ B.Put(pool) -+ D.Put(pool) -+ H.Put(pool) -+ I.Put(pool) -+ E.Put(pool) -+ J.Put(pool) -+ L1.Put(pool) -+ V.Put(pool) -+ t.Put(pool) -+ t2.Put(pool) -+ -+ return -+} -+ -+func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { -+ // See the doubling algorithm for a=0 from "Faster Computation of the -+ // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf -+ -+ A := newGFp2(pool).Square(r.x, pool) -+ B := newGFp2(pool).Square(r.y, pool) -+ C := newGFp2(pool).Square(B, pool) -+ -+ D := newGFp2(pool).Add(r.x, B) -+ D.Square(D, pool) -+ D.Sub(D, A) -+ D.Sub(D, C) -+ D.Add(D, D) -+ -+ E := newGFp2(pool).Add(A, A) -+ E.Add(E, A) -+ -+ G := newGFp2(pool).Square(E, pool) -+ -+ rOut = newTwistPoint(pool) -+ rOut.x.Sub(G, D) -+ rOut.x.Sub(rOut.x, D) -+ -+ rOut.z.Add(r.y, r.z) -+ rOut.z.Square(rOut.z, pool) -+ rOut.z.Sub(rOut.z, B) -+ rOut.z.Sub(rOut.z, r.t) -+ -+ rOut.y.Sub(D, rOut.x) -+ rOut.y.Mul(rOut.y, E, pool) -+ t := newGFp2(pool).Add(C, C) -+ t.Add(t, t) -+ t.Add(t, t) -+ rOut.y.Sub(rOut.y, t) -+ -+ rOut.t.Square(rOut.z, pool) -+ -+ t.Mul(E, r.t, pool) -+ t.Add(t, t) -+ b = newGFp2(pool) -+ b.SetZero() -+ b.Sub(b, t) -+ b.MulScalar(b, q.x) -+ -+ a = newGFp2(pool) -+ a.Add(r.x, E) -+ a.Square(a, pool) -+ a.Sub(a, A) -+ a.Sub(a, G) -+ t.Add(B, B) -+ t.Add(t, t) -+ a.Sub(a, t) -+ -+ c = newGFp2(pool) -+ c.Mul(rOut.z, r.t, pool) -+ c.Add(c, c) -+ c.MulScalar(c, q.y) -+ -+ A.Put(pool) -+ B.Put(pool) -+ C.Put(pool) -+ D.Put(pool) -+ E.Put(pool) -+ G.Put(pool) -+ t.Put(pool) -+ -+ return -+} -+ -+func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { -+ a2 := newGFp6(pool) -+ a2.x.SetZero() -+ a2.y.Set(a) -+ a2.z.Set(b) -+ a2.Mul(a2, ret.x, pool) -+ t3 := newGFp6(pool).MulScalar(ret.y, c, pool) -+ -+ t := newGFp2(pool) -+ t.Add(b, c) -+ t2 := newGFp6(pool) -+ t2.x.SetZero() -+ t2.y.Set(a) -+ t2.z.Set(t) -+ ret.x.Add(ret.x, ret.y) -+ -+ ret.y.Set(t3) -+ -+ ret.x.Mul(ret.x, t2, pool) -+ ret.x.Sub(ret.x, a2) -+ ret.x.Sub(ret.x, ret.y) -+ a2.MulTau(a2, pool) -+ ret.y.Add(ret.y, a2) -+ -+ a2.Put(pool) -+ t3.Put(pool) -+ t2.Put(pool) -+ t.Put(pool) -+} -+ -+// sixuPlus2NAF is 6u+2 in non-adjacent form. -+var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1} -+ -+// miller implements the Miller loop for calculating the Optimal Ate pairing. -+// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf -+func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { -+ ret := newGFp12(pool) -+ ret.SetOne() -+ -+ aAffine := newTwistPoint(pool) -+ aAffine.Set(q) -+ aAffine.MakeAffine(pool) -+ -+ bAffine := newCurvePoint(pool) -+ bAffine.Set(p) -+ bAffine.MakeAffine(pool) -+ -+ minusA := newTwistPoint(pool) -+ minusA.Negative(aAffine, pool) -+ -+ r := newTwistPoint(pool) -+ r.Set(aAffine) -+ -+ r2 := newGFp2(pool) -+ r2.Square(aAffine.y, pool) -+ -+ for i := len(sixuPlus2NAF) - 1; i > 0; i-- { -+ a, b, c, newR := lineFunctionDouble(r, bAffine, pool) -+ if i != len(sixuPlus2NAF)-1 { -+ ret.Square(ret, pool) -+ } -+ -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ -+ switch sixuPlus2NAF[i-1] { -+ case 1: -+ a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) -+ case -1: -+ a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) -+ default: -+ continue -+ } -+ -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ } -+ -+ // In order to calculate Q1 we have to convert q from the sextic twist -+ // to the full GF(p^12) group, apply the Frobenius there, and convert -+ // back. -+ // -+ // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just -+ // x for a moment, then after applying the Frobenius, we have xΜ„Ο‰^(2p) -+ // where xΜ„ is the conjugate of x. If we are going to apply the inverse -+ // isomorphism we need a value with a single coefficient of ω² so we -+ // rewrite this as xΜ„Ο‰^(2p-2)ω². ξ⁢ = Ο‰ and, due to the construction of -+ // p, 2p-2 is a multiple of six. Therefore we can rewrite as -+ // xΜ„ΞΎ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the -+ // ω². -+ // -+ // A similar argument can be made for the y value. -+ -+ q1 := newTwistPoint(pool) -+ q1.x.Conjugate(aAffine.x) -+ q1.x.Mul(q1.x, xiToPMinus1Over3, pool) -+ q1.y.Conjugate(aAffine.y) -+ q1.y.Mul(q1.y, xiToPMinus1Over2, pool) -+ q1.z.SetOne() -+ q1.t.SetOne() -+ -+ // For Q2 we are applying the pΒ² Frobenius. The two conjugations cancel -+ // out and we are left only with the factors from the isomorphism. In -+ // the case of x, we end up with a pure number which is why -+ // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We -+ // ignore this to end up with -Q2. -+ -+ minusQ2 := newTwistPoint(pool) -+ minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) -+ minusQ2.y.Set(aAffine.y) -+ minusQ2.z.SetOne() -+ minusQ2.t.SetOne() -+ -+ r2.Square(q1.y, pool) -+ a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ -+ r2.Square(minusQ2.y, pool) -+ a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) -+ mulLine(ret, a, b, c, pool) -+ a.Put(pool) -+ b.Put(pool) -+ c.Put(pool) -+ r.Put(pool) -+ r = newR -+ -+ aAffine.Put(pool) -+ bAffine.Put(pool) -+ minusA.Put(pool) -+ r.Put(pool) -+ r2.Put(pool) -+ -+ return ret -+} -+ -+// finalExponentiation computes the (pΒΉΒ²-1)/Order-th power of an element of -+// GF(pΒΉΒ²) to obtain an element of GT (steps 13-15 of algorithm 1 from -+// http://cryptojedi.org/papers/dclxvi-20100714.pdf) -+func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { -+ t1 := newGFp12(pool) -+ -+ // This is the p^6-Frobenius -+ t1.x.Negative(in.x) -+ t1.y.Set(in.y) -+ -+ inv := newGFp12(pool) -+ inv.Invert(in, pool) -+ t1.Mul(t1, inv, pool) -+ -+ t2 := newGFp12(pool).FrobeniusP2(t1, pool) -+ t1.Mul(t1, t2, pool) -+ -+ fp := newGFp12(pool).Frobenius(t1, pool) -+ fp2 := newGFp12(pool).FrobeniusP2(t1, pool) -+ fp3 := newGFp12(pool).Frobenius(fp2, pool) -+ -+ fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) -+ fu.Exp(t1, u, pool) -+ fu2.Exp(fu, u, pool) -+ fu3.Exp(fu2, u, pool) -+ -+ y3 := newGFp12(pool).Frobenius(fu, pool) -+ fu2p := newGFp12(pool).Frobenius(fu2, pool) -+ fu3p := newGFp12(pool).Frobenius(fu3, pool) -+ y2 := newGFp12(pool).FrobeniusP2(fu2, pool) -+ -+ y0 := newGFp12(pool) -+ y0.Mul(fp, fp2, pool) -+ y0.Mul(y0, fp3, pool) -+ -+ y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) -+ y1.Conjugate(t1) -+ y5.Conjugate(fu2) -+ y3.Conjugate(y3) -+ y4.Mul(fu, fu2p, pool) -+ y4.Conjugate(y4) -+ -+ y6 := newGFp12(pool) -+ y6.Mul(fu3, fu3p, pool) -+ y6.Conjugate(y6) -+ -+ t0 := newGFp12(pool) -+ t0.Square(y6, pool) -+ t0.Mul(t0, y4, pool) -+ t0.Mul(t0, y5, pool) -+ t1.Mul(y3, y5, pool) -+ t1.Mul(t1, t0, pool) -+ t0.Mul(t0, y2, pool) -+ t1.Square(t1, pool) -+ t1.Mul(t1, t0, pool) -+ t1.Square(t1, pool) -+ t0.Mul(t1, y1, pool) -+ t1.Mul(t1, y0, pool) -+ t0.Square(t0, pool) -+ t0.Mul(t0, t1, pool) -+ -+ inv.Put(pool) -+ t1.Put(pool) -+ t2.Put(pool) -+ fp.Put(pool) -+ fp2.Put(pool) -+ fp3.Put(pool) -+ fu.Put(pool) -+ fu2.Put(pool) -+ fu3.Put(pool) -+ fu2p.Put(pool) -+ fu3p.Put(pool) -+ y0.Put(pool) -+ y1.Put(pool) -+ y2.Put(pool) -+ y3.Put(pool) -+ y4.Put(pool) -+ y5.Put(pool) -+ y6.Put(pool) -+ -+ return t0 -+} -+ -+func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { -+ e := miller(a, b, pool) -+ ret := finalExponentiation(e, pool) -+ e.Put(pool) -+ -+ if a.IsInfinity() || b.IsInfinity() { -+ ret.SetOne() -+ } -+ -+ return ret -+} -diff --git a/ms_mod/golang.org/x/crypto/bn256/twist.go b/ms_mod/golang.org/x/crypto/bn256/twist.go -new file mode 100644 -index 00000000000000..056d80f18f0881 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/bn256/twist.go -@@ -0,0 +1,258 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bn256 -+ -+import ( -+ "math/big" -+) -+ -+// twistPoint implements the elliptic curve yΒ²=xΒ³+3/ΞΎ over GF(pΒ²). Points are -+// kept in Jacobian form and t=zΒ² when valid. The group Gβ‚‚ is the set of -+// n-torsion points of this curve over GF(pΒ²) (where n = Order) -+type twistPoint struct { -+ x, y, z, t *gfP2 -+} -+ -+var twistB = &gfP2{ -+ bigFromBase10("6500054969564660373279643874235990574282535810762300357187714502686418407178"), -+ bigFromBase10("45500384786952622612957507119651934019977750675336102500314001518804928850249"), -+} -+ -+// twistGen is the generator of group Gβ‚‚. -+var twistGen = &twistPoint{ -+ &gfP2{ -+ bigFromBase10("21167961636542580255011770066570541300993051739349375019639421053990175267184"), -+ bigFromBase10("64746500191241794695844075326670126197795977525365406531717464316923369116492"), -+ }, -+ &gfP2{ -+ bigFromBase10("20666913350058776956210519119118544732556678129809273996262322366050359951122"), -+ bigFromBase10("17778617556404439934652658462602675281523610326338642107814333856843981424549"), -+ }, -+ &gfP2{ -+ bigFromBase10("0"), -+ bigFromBase10("1"), -+ }, -+ &gfP2{ -+ bigFromBase10("0"), -+ bigFromBase10("1"), -+ }, -+} -+ -+func newTwistPoint(pool *bnPool) *twistPoint { -+ return &twistPoint{ -+ newGFp2(pool), -+ newGFp2(pool), -+ newGFp2(pool), -+ newGFp2(pool), -+ } -+} -+ -+func (c *twistPoint) String() string { -+ return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" -+} -+ -+func (c *twistPoint) Put(pool *bnPool) { -+ c.x.Put(pool) -+ c.y.Put(pool) -+ c.z.Put(pool) -+ c.t.Put(pool) -+} -+ -+func (c *twistPoint) Set(a *twistPoint) { -+ c.x.Set(a.x) -+ c.y.Set(a.y) -+ c.z.Set(a.z) -+ c.t.Set(a.t) -+} -+ -+// IsOnCurve returns true iff c is on the curve where c must be in affine form. -+func (c *twistPoint) IsOnCurve() bool { -+ pool := new(bnPool) -+ yy := newGFp2(pool).Square(c.y, pool) -+ xxx := newGFp2(pool).Square(c.x, pool) -+ xxx.Mul(xxx, c.x, pool) -+ yy.Sub(yy, xxx) -+ yy.Sub(yy, twistB) -+ yy.Minimal() -+ return yy.x.Sign() == 0 && yy.y.Sign() == 0 -+} -+ -+func (c *twistPoint) SetInfinity() { -+ c.z.SetZero() -+} -+ -+func (c *twistPoint) IsInfinity() bool { -+ return c.z.IsZero() -+} -+ -+func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { -+ // For additional comments, see the same function in curve.go. -+ -+ if a.IsInfinity() { -+ c.Set(b) -+ return -+ } -+ if b.IsInfinity() { -+ c.Set(a) -+ return -+ } -+ -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 -+ z1z1 := newGFp2(pool).Square(a.z, pool) -+ z2z2 := newGFp2(pool).Square(b.z, pool) -+ u1 := newGFp2(pool).Mul(a.x, z2z2, pool) -+ u2 := newGFp2(pool).Mul(b.x, z1z1, pool) -+ -+ t := newGFp2(pool).Mul(b.z, z2z2, pool) -+ s1 := newGFp2(pool).Mul(a.y, t, pool) -+ -+ t.Mul(a.z, z1z1, pool) -+ s2 := newGFp2(pool).Mul(b.y, t, pool) -+ -+ h := newGFp2(pool).Sub(u2, u1) -+ xEqual := h.IsZero() -+ -+ t.Add(h, h) -+ i := newGFp2(pool).Square(t, pool) -+ j := newGFp2(pool).Mul(h, i, pool) -+ -+ t.Sub(s2, s1) -+ yEqual := t.IsZero() -+ if xEqual && yEqual { -+ c.Double(a, pool) -+ return -+ } -+ r := newGFp2(pool).Add(t, t) -+ -+ v := newGFp2(pool).Mul(u1, i, pool) -+ -+ t4 := newGFp2(pool).Square(r, pool) -+ t.Add(v, v) -+ t6 := newGFp2(pool).Sub(t4, j) -+ c.x.Sub(t6, t) -+ -+ t.Sub(v, c.x) // t7 -+ t4.Mul(s1, j, pool) // t8 -+ t6.Add(t4, t4) // t9 -+ t4.Mul(r, t, pool) // t10 -+ c.y.Sub(t4, t6) -+ -+ t.Add(a.z, b.z) // t11 -+ t4.Square(t, pool) // t12 -+ t.Sub(t4, z1z1) // t13 -+ t4.Sub(t, z2z2) // t14 -+ c.z.Mul(t4, h, pool) -+ -+ z1z1.Put(pool) -+ z2z2.Put(pool) -+ u1.Put(pool) -+ u2.Put(pool) -+ t.Put(pool) -+ s1.Put(pool) -+ s2.Put(pool) -+ h.Put(pool) -+ i.Put(pool) -+ j.Put(pool) -+ r.Put(pool) -+ v.Put(pool) -+ t4.Put(pool) -+ t6.Put(pool) -+} -+ -+func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { -+ // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 -+ A := newGFp2(pool).Square(a.x, pool) -+ B := newGFp2(pool).Square(a.y, pool) -+ C := newGFp2(pool).Square(B, pool) -+ -+ t := newGFp2(pool).Add(a.x, B) -+ t2 := newGFp2(pool).Square(t, pool) -+ t.Sub(t2, A) -+ t2.Sub(t, C) -+ d := newGFp2(pool).Add(t2, t2) -+ t.Add(A, A) -+ e := newGFp2(pool).Add(t, A) -+ f := newGFp2(pool).Square(e, pool) -+ -+ t.Add(d, d) -+ c.x.Sub(f, t) -+ -+ t.Add(C, C) -+ t2.Add(t, t) -+ t.Add(t2, t2) -+ c.y.Sub(d, c.x) -+ t2.Mul(e, c.y, pool) -+ c.y.Sub(t2, t) -+ -+ t.Mul(a.y, a.z, pool) -+ c.z.Add(t, t) -+ -+ A.Put(pool) -+ B.Put(pool) -+ C.Put(pool) -+ t.Put(pool) -+ t2.Put(pool) -+ d.Put(pool) -+ e.Put(pool) -+ f.Put(pool) -+} -+ -+func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { -+ sum := newTwistPoint(pool) -+ sum.SetInfinity() -+ t := newTwistPoint(pool) -+ -+ for i := scalar.BitLen(); i >= 0; i-- { -+ t.Double(sum, pool) -+ if scalar.Bit(i) != 0 { -+ sum.Add(t, a, pool) -+ } else { -+ sum.Set(t) -+ } -+ } -+ -+ c.Set(sum) -+ sum.Put(pool) -+ t.Put(pool) -+ return c -+} -+ -+// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets -+// c to 0 : 1 : 0. -+func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { -+ if c.z.IsOne() { -+ return c -+ } -+ if c.IsInfinity() { -+ c.x.SetZero() -+ c.y.SetOne() -+ c.z.SetZero() -+ c.t.SetZero() -+ return c -+ } -+ -+ zInv := newGFp2(pool).Invert(c.z, pool) -+ t := newGFp2(pool).Mul(c.y, zInv, pool) -+ zInv2 := newGFp2(pool).Square(zInv, pool) -+ c.y.Mul(t, zInv2, pool) -+ t.Mul(c.x, zInv2, pool) -+ c.x.Set(t) -+ c.z.SetOne() -+ c.t.SetOne() -+ -+ zInv.Put(pool) -+ t.Put(pool) -+ zInv2.Put(pool) -+ -+ return c -+} -+ -+func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { -+ c.x.Set(a.x) -+ c.y.SetZero() -+ c.y.Sub(c.y, a.y) -+ c.z.Set(a.z) -+ c.t.SetZero() -+} -diff --git a/ms_mod/golang.org/x/crypto/cast5/cast5.go b/ms_mod/golang.org/x/crypto/cast5/cast5.go -new file mode 100644 -index 00000000000000..425e8eecb06beb ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cast5/cast5.go -@@ -0,0 +1,536 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package cast5 implements CAST5, as defined in RFC 2144. -+// -+// CAST5 is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package cast5 // import "golang.org/x/crypto/cast5" -+ -+import ( -+ "errors" -+ "math/bits" -+) -+ -+const BlockSize = 8 -+const KeySize = 16 -+ -+type Cipher struct { -+ masking [16]uint32 -+ rotate [16]uint8 -+} -+ -+func NewCipher(key []byte) (c *Cipher, err error) { -+ if len(key) != KeySize { -+ return nil, errors.New("CAST5: keys must be 16 bytes") -+ } -+ -+ c = new(Cipher) -+ c.keySchedule(key) -+ return -+} -+ -+func (c *Cipher) BlockSize() int { -+ return BlockSize -+} -+ -+func (c *Cipher) Encrypt(dst, src []byte) { -+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ -+ l, r = r, l^f1(r, c.masking[0], c.rotate[0]) -+ l, r = r, l^f2(r, c.masking[1], c.rotate[1]) -+ l, r = r, l^f3(r, c.masking[2], c.rotate[2]) -+ l, r = r, l^f1(r, c.masking[3], c.rotate[3]) -+ -+ l, r = r, l^f2(r, c.masking[4], c.rotate[4]) -+ l, r = r, l^f3(r, c.masking[5], c.rotate[5]) -+ l, r = r, l^f1(r, c.masking[6], c.rotate[6]) -+ l, r = r, l^f2(r, c.masking[7], c.rotate[7]) -+ -+ l, r = r, l^f3(r, c.masking[8], c.rotate[8]) -+ l, r = r, l^f1(r, c.masking[9], c.rotate[9]) -+ l, r = r, l^f2(r, c.masking[10], c.rotate[10]) -+ l, r = r, l^f3(r, c.masking[11], c.rotate[11]) -+ -+ l, r = r, l^f1(r, c.masking[12], c.rotate[12]) -+ l, r = r, l^f2(r, c.masking[13], c.rotate[13]) -+ l, r = r, l^f3(r, c.masking[14], c.rotate[14]) -+ l, r = r, l^f1(r, c.masking[15], c.rotate[15]) -+ -+ dst[0] = uint8(r >> 24) -+ dst[1] = uint8(r >> 16) -+ dst[2] = uint8(r >> 8) -+ dst[3] = uint8(r) -+ dst[4] = uint8(l >> 24) -+ dst[5] = uint8(l >> 16) -+ dst[6] = uint8(l >> 8) -+ dst[7] = uint8(l) -+} -+ -+func (c *Cipher) Decrypt(dst, src []byte) { -+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ -+ l, r = r, l^f1(r, c.masking[15], c.rotate[15]) -+ l, r = r, l^f3(r, c.masking[14], c.rotate[14]) -+ l, r = r, l^f2(r, c.masking[13], c.rotate[13]) -+ l, r = r, l^f1(r, c.masking[12], c.rotate[12]) -+ -+ l, r = r, l^f3(r, c.masking[11], c.rotate[11]) -+ l, r = r, l^f2(r, c.masking[10], c.rotate[10]) -+ l, r = r, l^f1(r, c.masking[9], c.rotate[9]) -+ l, r = r, l^f3(r, c.masking[8], c.rotate[8]) -+ -+ l, r = r, l^f2(r, c.masking[7], c.rotate[7]) -+ l, r = r, l^f1(r, c.masking[6], c.rotate[6]) -+ l, r = r, l^f3(r, c.masking[5], c.rotate[5]) -+ l, r = r, l^f2(r, c.masking[4], c.rotate[4]) -+ -+ l, r = r, l^f1(r, c.masking[3], c.rotate[3]) -+ l, r = r, l^f3(r, c.masking[2], c.rotate[2]) -+ l, r = r, l^f2(r, c.masking[1], c.rotate[1]) -+ l, r = r, l^f1(r, c.masking[0], c.rotate[0]) -+ -+ dst[0] = uint8(r >> 24) -+ dst[1] = uint8(r >> 16) -+ dst[2] = uint8(r >> 8) -+ dst[3] = uint8(r) -+ dst[4] = uint8(l >> 24) -+ dst[5] = uint8(l >> 16) -+ dst[6] = uint8(l >> 8) -+ dst[7] = uint8(l) -+} -+ -+type keyScheduleA [4][7]uint8 -+type keyScheduleB [4][5]uint8 -+ -+// keyScheduleRound contains the magic values for a round of the key schedule. -+// The keyScheduleA deals with the lines like: -+// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] -+// Conceptually, both x and z are in the same array, x first. The first -+// element describes which word of this array gets written to and the -+// second, which word gets read. So, for the line above, it's "4, 0", because -+// it's writing to the first word of z, which, being after x, is word 4, and -+// reading from the first word of x: word 0. -+// -+// Next are the indexes into the S-boxes. Now the array is treated as bytes. So -+// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear -+// that it's z that we're indexing. -+// -+// keyScheduleB deals with lines like: -+// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] -+// "K1" is ignored because key words are always written in order. So the five -+// elements are the S-box indexes. They use the same form as in keyScheduleA, -+// above. -+ -+type keyScheduleRound struct{} -+type keySchedule []keyScheduleRound -+ -+var schedule = []struct { -+ a keyScheduleA -+ b keyScheduleB -+}{ -+ { -+ keyScheduleA{ -+ {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8}, -+ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, -+ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, -+ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, -+ }, -+ keyScheduleB{ -+ {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2}, -+ {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6}, -+ {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9}, -+ {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc}, -+ }, -+ }, -+ { -+ keyScheduleA{ -+ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, -+ {1, 4, 0, 2, 1, 3, 16 + 2}, -+ {2, 5, 7, 6, 5, 4, 16 + 1}, -+ {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, -+ }, -+ keyScheduleB{ -+ {3, 2, 0xc, 0xd, 8}, -+ {1, 0, 0xe, 0xf, 0xd}, -+ {7, 6, 8, 9, 3}, -+ {5, 4, 0xa, 0xb, 7}, -+ }, -+ }, -+ { -+ keyScheduleA{ -+ {4, 0, 0xd, 0xf, 0xc, 0xe, 8}, -+ {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa}, -+ {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9}, -+ {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb}, -+ }, -+ keyScheduleB{ -+ {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9}, -+ {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc}, -+ {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2}, -+ {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6}, -+ }, -+ }, -+ { -+ keyScheduleA{ -+ {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0}, -+ {1, 4, 0, 2, 1, 3, 16 + 2}, -+ {2, 5, 7, 6, 5, 4, 16 + 1}, -+ {3, 7, 0xa, 9, 0xb, 8, 16 + 3}, -+ }, -+ keyScheduleB{ -+ {8, 9, 7, 6, 3}, -+ {0xa, 0xb, 5, 4, 7}, -+ {0xc, 0xd, 3, 2, 8}, -+ {0xe, 0xf, 1, 0, 0xd}, -+ }, -+ }, -+} -+ -+func (c *Cipher) keySchedule(in []byte) { -+ var t [8]uint32 -+ var k [32]uint32 -+ -+ for i := 0; i < 4; i++ { -+ j := i * 4 -+ t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3]) -+ } -+ -+ x := []byte{6, 7, 4, 5} -+ ki := 0 -+ -+ for half := 0; half < 2; half++ { -+ for _, round := range schedule { -+ for j := 0; j < 4; j++ { -+ var a [7]uint8 -+ copy(a[:], round.a[j][:]) -+ w := t[a[1]] -+ w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff] -+ w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff] -+ w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff] -+ w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff] -+ w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff] -+ t[a[0]] = w -+ } -+ -+ for j := 0; j < 4; j++ { -+ var b [5]uint8 -+ copy(b[:], round.b[j][:]) -+ w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff] -+ w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff] -+ w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff] -+ w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff] -+ w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff] -+ k[ki] = w -+ ki++ -+ } -+ } -+ } -+ -+ for i := 0; i < 16; i++ { -+ c.masking[i] = k[i] -+ c.rotate[i] = uint8(k[16+i] & 0x1f) -+ } -+} -+ -+// These are the three 'f' functions. See RFC 2144, section 2.2. -+func f1(d, m uint32, r uint8) uint32 { -+ t := m + d -+ I := bits.RotateLeft32(t, int(r)) -+ return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff] -+} -+ -+func f2(d, m uint32, r uint8) uint32 { -+ t := m ^ d -+ I := bits.RotateLeft32(t, int(r)) -+ return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff] -+} -+ -+func f3(d, m uint32, r uint8) uint32 { -+ t := m - d -+ I := bits.RotateLeft32(t, int(r)) -+ return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff] -+} -+ -+var sBox = [8][256]uint32{ -+ { -+ 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, -+ 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, -+ 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, -+ 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, -+ 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, -+ 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, -+ 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, -+ 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, -+ 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, -+ 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, -+ 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, -+ 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, -+ 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, -+ 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, -+ 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, -+ 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, -+ 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, -+ 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, -+ 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, -+ 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, -+ 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, -+ 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, -+ 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, -+ 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, -+ 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, -+ 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, -+ 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, -+ 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, -+ 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, -+ 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, -+ 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, -+ 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf, -+ }, -+ { -+ 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, -+ 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, -+ 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, -+ 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, -+ 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, -+ 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, -+ 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, -+ 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, -+ 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, -+ 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, -+ 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, -+ 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, -+ 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, -+ 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, -+ 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, -+ 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, -+ 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, -+ 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, -+ 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, -+ 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, -+ 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, -+ 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, -+ 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, -+ 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, -+ 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, -+ 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, -+ 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, -+ 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, -+ 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, -+ 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, -+ 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, -+ 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1, -+ }, -+ { -+ 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, -+ 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, -+ 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, -+ 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, -+ 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, -+ 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, -+ 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, -+ 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, -+ 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, -+ 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, -+ 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, -+ 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, -+ 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, -+ 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, -+ 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, -+ 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, -+ 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, -+ 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, -+ 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, -+ 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, -+ 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, -+ 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, -+ 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, -+ 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, -+ 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, -+ 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, -+ 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, -+ 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, -+ 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, -+ 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, -+ 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, -+ 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783, -+ }, -+ { -+ 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, -+ 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, -+ 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, -+ 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, -+ 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, -+ 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, -+ 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, -+ 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, -+ 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, -+ 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, -+ 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, -+ 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, -+ 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, -+ 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, -+ 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, -+ 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, -+ 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, -+ 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, -+ 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, -+ 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, -+ 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, -+ 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, -+ 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, -+ 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, -+ 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, -+ 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, -+ 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, -+ 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, -+ 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, -+ 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, -+ 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, -+ 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2, -+ }, -+ { -+ 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, -+ 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, -+ 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, -+ 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, -+ 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, -+ 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, -+ 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, -+ 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, -+ 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, -+ 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, -+ 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, -+ 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, -+ 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, -+ 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, -+ 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, -+ 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, -+ 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, -+ 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, -+ 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, -+ 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, -+ 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, -+ 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, -+ 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, -+ 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, -+ 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, -+ 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, -+ 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, -+ 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, -+ 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, -+ 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, -+ 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, -+ 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4, -+ }, -+ { -+ 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, -+ 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, -+ 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, -+ 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, -+ 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, -+ 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, -+ 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, -+ 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, -+ 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, -+ 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, -+ 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, -+ 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, -+ 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, -+ 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, -+ 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, -+ 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, -+ 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, -+ 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, -+ 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, -+ 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, -+ 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, -+ 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, -+ 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, -+ 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, -+ 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, -+ 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, -+ 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, -+ 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, -+ 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, -+ 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, -+ 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, -+ 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f, -+ }, -+ { -+ 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, -+ 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, -+ 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, -+ 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, -+ 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, -+ 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, -+ 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, -+ 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, -+ 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, -+ 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, -+ 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, -+ 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, -+ 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, -+ 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, -+ 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, -+ 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, -+ 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, -+ 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, -+ 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, -+ 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, -+ 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, -+ 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, -+ 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, -+ 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, -+ 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, -+ 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, -+ 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, -+ 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, -+ 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, -+ 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, -+ 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, -+ 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3, -+ }, -+ { -+ 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, -+ 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, -+ 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, -+ 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, -+ 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, -+ 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, -+ 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, -+ 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, -+ 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, -+ 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, -+ 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, -+ 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, -+ 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, -+ 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, -+ 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, -+ 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, -+ 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, -+ 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, -+ 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, -+ 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, -+ 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, -+ 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, -+ 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, -+ 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, -+ 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, -+ 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, -+ 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, -+ 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, -+ 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, -+ 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, -+ 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, -+ 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e, -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/cast5/cast5_test.go b/ms_mod/golang.org/x/crypto/cast5/cast5_test.go -new file mode 100644 -index 00000000000000..778b272a638885 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cast5/cast5_test.go -@@ -0,0 +1,106 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package cast5 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "testing" -+) -+ -+// This test vector is taken from RFC 2144, App B.1. -+// Since the other two test vectors are for reduced-round variants, we can't -+// use them. -+var basicTests = []struct { -+ key, plainText, cipherText string -+}{ -+ { -+ "0123456712345678234567893456789a", -+ "0123456789abcdef", -+ "238b4fe5847e44b2", -+ }, -+} -+ -+func TestBasic(t *testing.T) { -+ for i, test := range basicTests { -+ key, _ := hex.DecodeString(test.key) -+ plainText, _ := hex.DecodeString(test.plainText) -+ expected, _ := hex.DecodeString(test.cipherText) -+ -+ c, err := NewCipher(key) -+ if err != nil { -+ t.Errorf("#%d: failed to create Cipher: %s", i, err) -+ continue -+ } -+ var cipherText [BlockSize]byte -+ c.Encrypt(cipherText[:], plainText) -+ if !bytes.Equal(cipherText[:], expected) { -+ t.Errorf("#%d: got:%x want:%x", i, cipherText, expected) -+ } -+ -+ var plainTextAgain [BlockSize]byte -+ c.Decrypt(plainTextAgain[:], cipherText[:]) -+ if !bytes.Equal(plainTextAgain[:], plainText) { -+ t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText) -+ } -+ } -+} -+ -+// TestFull performs the test specified in RFC 2144, App B.2. -+// However, due to the length of time taken, it's disabled here and a more -+// limited version is included, below. -+func TestFull(t *testing.T) { -+ if testing.Short() { -+ // This is too slow for normal testing -+ return -+ } -+ -+ a, b := iterate(1000000) -+ -+ const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92" -+ const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e" -+ -+ if hex.EncodeToString(a) != expectedA { -+ t.Errorf("a: got:%x want:%s", a, expectedA) -+ } -+ if hex.EncodeToString(b) != expectedB { -+ t.Errorf("b: got:%x want:%s", b, expectedB) -+ } -+} -+ -+func iterate(iterations int) ([]byte, []byte) { -+ const initValueHex = "0123456712345678234567893456789a" -+ -+ initValue, _ := hex.DecodeString(initValueHex) -+ -+ var a, b [16]byte -+ copy(a[:], initValue) -+ copy(b[:], initValue) -+ -+ for i := 0; i < iterations; i++ { -+ c, _ := NewCipher(b[:]) -+ c.Encrypt(a[:8], a[:8]) -+ c.Encrypt(a[8:], a[8:]) -+ c, _ = NewCipher(a[:]) -+ c.Encrypt(b[:8], b[:8]) -+ c.Encrypt(b[8:], b[8:]) -+ } -+ -+ return a[:], b[:] -+} -+ -+func TestLimited(t *testing.T) { -+ a, b := iterate(1000) -+ -+ const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d" -+ const expectedB = "e5bf37eff14c456a40b21ce369370a9f" -+ -+ if hex.EncodeToString(a) != expectedA { -+ t.Errorf("a: got:%x want:%s", a, expectedA) -+ } -+ if hex.EncodeToString(b) != expectedB { -+ t.Errorf("b: got:%x want:%s", b, expectedB) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go -new file mode 100644 -index 00000000000000..94c71ac1ac863f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.go -@@ -0,0 +1,17 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.11 && gc && !purego -+// +build go1.11,gc,!purego -+ -+package chacha20 -+ -+const bufSize = 256 -+ -+//go:noescape -+func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) -+ -+func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { -+ xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s -new file mode 100644 -index 00000000000000..63cae9e6f0b1ba ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_arm64.s -@@ -0,0 +1,308 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.11 && gc && !purego -+// +build go1.11,gc,!purego -+ -+#include "textflag.h" -+ -+#define NUM_ROUNDS 10 -+ -+// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) -+TEXT Β·xorKeyStreamVX(SB), NOSPLIT, $0 -+ MOVD dst+0(FP), R1 -+ MOVD src+24(FP), R2 -+ MOVD src_len+32(FP), R3 -+ MOVD key+48(FP), R4 -+ MOVD nonce+56(FP), R6 -+ MOVD counter+64(FP), R7 -+ -+ MOVD $Β·constants(SB), R10 -+ MOVD $Β·incRotMatrix(SB), R11 -+ -+ MOVW (R7), R20 -+ -+ AND $~255, R3, R13 -+ ADD R2, R13, R12 // R12 for block end -+ AND $255, R3, R13 -+loop: -+ MOVD $NUM_ROUNDS, R21 -+ VLD1 (R11), [V30.S4, V31.S4] -+ -+ // load contants -+ // VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] -+ WORD $0x4D60E940 -+ -+ // load keys -+ // VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4] -+ WORD $0x4DFFE884 -+ // VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4] -+ WORD $0x4DFFE888 -+ SUB $32, R4 -+ -+ // load counter + nonce -+ // VLD1R (R7), [V12.S4] -+ WORD $0x4D40C8EC -+ -+ // VLD3R (R6), [V13.S4, V14.S4, V15.S4] -+ WORD $0x4D40E8CD -+ -+ // update counter -+ VADD V30.S4, V12.S4, V12.S4 -+ -+chacha: -+ // V0..V3 += V4..V7 -+ // V12..V15 <<<= ((V12..V15 XOR V0..V3), 16) -+ VADD V0.S4, V4.S4, V0.S4 -+ VADD V1.S4, V5.S4, V1.S4 -+ VADD V2.S4, V6.S4, V2.S4 -+ VADD V3.S4, V7.S4, V3.S4 -+ VEOR V12.B16, V0.B16, V12.B16 -+ VEOR V13.B16, V1.B16, V13.B16 -+ VEOR V14.B16, V2.B16, V14.B16 -+ VEOR V15.B16, V3.B16, V15.B16 -+ VREV32 V12.H8, V12.H8 -+ VREV32 V13.H8, V13.H8 -+ VREV32 V14.H8, V14.H8 -+ VREV32 V15.H8, V15.H8 -+ // V8..V11 += V12..V15 -+ // V4..V7 <<<= ((V4..V7 XOR V8..V11), 12) -+ VADD V8.S4, V12.S4, V8.S4 -+ VADD V9.S4, V13.S4, V9.S4 -+ VADD V10.S4, V14.S4, V10.S4 -+ VADD V11.S4, V15.S4, V11.S4 -+ VEOR V8.B16, V4.B16, V16.B16 -+ VEOR V9.B16, V5.B16, V17.B16 -+ VEOR V10.B16, V6.B16, V18.B16 -+ VEOR V11.B16, V7.B16, V19.B16 -+ VSHL $12, V16.S4, V4.S4 -+ VSHL $12, V17.S4, V5.S4 -+ VSHL $12, V18.S4, V6.S4 -+ VSHL $12, V19.S4, V7.S4 -+ VSRI $20, V16.S4, V4.S4 -+ VSRI $20, V17.S4, V5.S4 -+ VSRI $20, V18.S4, V6.S4 -+ VSRI $20, V19.S4, V7.S4 -+ -+ // V0..V3 += V4..V7 -+ // V12..V15 <<<= ((V12..V15 XOR V0..V3), 8) -+ VADD V0.S4, V4.S4, V0.S4 -+ VADD V1.S4, V5.S4, V1.S4 -+ VADD V2.S4, V6.S4, V2.S4 -+ VADD V3.S4, V7.S4, V3.S4 -+ VEOR V12.B16, V0.B16, V12.B16 -+ VEOR V13.B16, V1.B16, V13.B16 -+ VEOR V14.B16, V2.B16, V14.B16 -+ VEOR V15.B16, V3.B16, V15.B16 -+ VTBL V31.B16, [V12.B16], V12.B16 -+ VTBL V31.B16, [V13.B16], V13.B16 -+ VTBL V31.B16, [V14.B16], V14.B16 -+ VTBL V31.B16, [V15.B16], V15.B16 -+ -+ // V8..V11 += V12..V15 -+ // V4..V7 <<<= ((V4..V7 XOR V8..V11), 7) -+ VADD V12.S4, V8.S4, V8.S4 -+ VADD V13.S4, V9.S4, V9.S4 -+ VADD V14.S4, V10.S4, V10.S4 -+ VADD V15.S4, V11.S4, V11.S4 -+ VEOR V8.B16, V4.B16, V16.B16 -+ VEOR V9.B16, V5.B16, V17.B16 -+ VEOR V10.B16, V6.B16, V18.B16 -+ VEOR V11.B16, V7.B16, V19.B16 -+ VSHL $7, V16.S4, V4.S4 -+ VSHL $7, V17.S4, V5.S4 -+ VSHL $7, V18.S4, V6.S4 -+ VSHL $7, V19.S4, V7.S4 -+ VSRI $25, V16.S4, V4.S4 -+ VSRI $25, V17.S4, V5.S4 -+ VSRI $25, V18.S4, V6.S4 -+ VSRI $25, V19.S4, V7.S4 -+ -+ // V0..V3 += V5..V7, V4 -+ // V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16) -+ VADD V0.S4, V5.S4, V0.S4 -+ VADD V1.S4, V6.S4, V1.S4 -+ VADD V2.S4, V7.S4, V2.S4 -+ VADD V3.S4, V4.S4, V3.S4 -+ VEOR V15.B16, V0.B16, V15.B16 -+ VEOR V12.B16, V1.B16, V12.B16 -+ VEOR V13.B16, V2.B16, V13.B16 -+ VEOR V14.B16, V3.B16, V14.B16 -+ VREV32 V12.H8, V12.H8 -+ VREV32 V13.H8, V13.H8 -+ VREV32 V14.H8, V14.H8 -+ VREV32 V15.H8, V15.H8 -+ -+ // V10 += V15; V5 <<<= ((V10 XOR V5), 12) -+ // ... -+ VADD V15.S4, V10.S4, V10.S4 -+ VADD V12.S4, V11.S4, V11.S4 -+ VADD V13.S4, V8.S4, V8.S4 -+ VADD V14.S4, V9.S4, V9.S4 -+ VEOR V10.B16, V5.B16, V16.B16 -+ VEOR V11.B16, V6.B16, V17.B16 -+ VEOR V8.B16, V7.B16, V18.B16 -+ VEOR V9.B16, V4.B16, V19.B16 -+ VSHL $12, V16.S4, V5.S4 -+ VSHL $12, V17.S4, V6.S4 -+ VSHL $12, V18.S4, V7.S4 -+ VSHL $12, V19.S4, V4.S4 -+ VSRI $20, V16.S4, V5.S4 -+ VSRI $20, V17.S4, V6.S4 -+ VSRI $20, V18.S4, V7.S4 -+ VSRI $20, V19.S4, V4.S4 -+ -+ // V0 += V5; V15 <<<= ((V0 XOR V15), 8) -+ // ... -+ VADD V5.S4, V0.S4, V0.S4 -+ VADD V6.S4, V1.S4, V1.S4 -+ VADD V7.S4, V2.S4, V2.S4 -+ VADD V4.S4, V3.S4, V3.S4 -+ VEOR V0.B16, V15.B16, V15.B16 -+ VEOR V1.B16, V12.B16, V12.B16 -+ VEOR V2.B16, V13.B16, V13.B16 -+ VEOR V3.B16, V14.B16, V14.B16 -+ VTBL V31.B16, [V12.B16], V12.B16 -+ VTBL V31.B16, [V13.B16], V13.B16 -+ VTBL V31.B16, [V14.B16], V14.B16 -+ VTBL V31.B16, [V15.B16], V15.B16 -+ -+ // V10 += V15; V5 <<<= ((V10 XOR V5), 7) -+ // ... -+ VADD V15.S4, V10.S4, V10.S4 -+ VADD V12.S4, V11.S4, V11.S4 -+ VADD V13.S4, V8.S4, V8.S4 -+ VADD V14.S4, V9.S4, V9.S4 -+ VEOR V10.B16, V5.B16, V16.B16 -+ VEOR V11.B16, V6.B16, V17.B16 -+ VEOR V8.B16, V7.B16, V18.B16 -+ VEOR V9.B16, V4.B16, V19.B16 -+ VSHL $7, V16.S4, V5.S4 -+ VSHL $7, V17.S4, V6.S4 -+ VSHL $7, V18.S4, V7.S4 -+ VSHL $7, V19.S4, V4.S4 -+ VSRI $25, V16.S4, V5.S4 -+ VSRI $25, V17.S4, V6.S4 -+ VSRI $25, V18.S4, V7.S4 -+ VSRI $25, V19.S4, V4.S4 -+ -+ SUB $1, R21 -+ CBNZ R21, chacha -+ -+ // VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4] -+ WORD $0x4D60E950 -+ -+ // VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4] -+ WORD $0x4DFFE894 -+ VADD V30.S4, V12.S4, V12.S4 -+ VADD V16.S4, V0.S4, V0.S4 -+ VADD V17.S4, V1.S4, V1.S4 -+ VADD V18.S4, V2.S4, V2.S4 -+ VADD V19.S4, V3.S4, V3.S4 -+ // VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4] -+ WORD $0x4DFFE898 -+ // restore R4 -+ SUB $32, R4 -+ -+ // load counter + nonce -+ // VLD1R (R7), [V28.S4] -+ WORD $0x4D40C8FC -+ // VLD3R (R6), [V29.S4, V30.S4, V31.S4] -+ WORD $0x4D40E8DD -+ -+ VADD V20.S4, V4.S4, V4.S4 -+ VADD V21.S4, V5.S4, V5.S4 -+ VADD V22.S4, V6.S4, V6.S4 -+ VADD V23.S4, V7.S4, V7.S4 -+ VADD V24.S4, V8.S4, V8.S4 -+ VADD V25.S4, V9.S4, V9.S4 -+ VADD V26.S4, V10.S4, V10.S4 -+ VADD V27.S4, V11.S4, V11.S4 -+ VADD V28.S4, V12.S4, V12.S4 -+ VADD V29.S4, V13.S4, V13.S4 -+ VADD V30.S4, V14.S4, V14.S4 -+ VADD V31.S4, V15.S4, V15.S4 -+ -+ VZIP1 V1.S4, V0.S4, V16.S4 -+ VZIP2 V1.S4, V0.S4, V17.S4 -+ VZIP1 V3.S4, V2.S4, V18.S4 -+ VZIP2 V3.S4, V2.S4, V19.S4 -+ VZIP1 V5.S4, V4.S4, V20.S4 -+ VZIP2 V5.S4, V4.S4, V21.S4 -+ VZIP1 V7.S4, V6.S4, V22.S4 -+ VZIP2 V7.S4, V6.S4, V23.S4 -+ VZIP1 V9.S4, V8.S4, V24.S4 -+ VZIP2 V9.S4, V8.S4, V25.S4 -+ VZIP1 V11.S4, V10.S4, V26.S4 -+ VZIP2 V11.S4, V10.S4, V27.S4 -+ VZIP1 V13.S4, V12.S4, V28.S4 -+ VZIP2 V13.S4, V12.S4, V29.S4 -+ VZIP1 V15.S4, V14.S4, V30.S4 -+ VZIP2 V15.S4, V14.S4, V31.S4 -+ VZIP1 V18.D2, V16.D2, V0.D2 -+ VZIP2 V18.D2, V16.D2, V4.D2 -+ VZIP1 V19.D2, V17.D2, V8.D2 -+ VZIP2 V19.D2, V17.D2, V12.D2 -+ VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16] -+ -+ VZIP1 V22.D2, V20.D2, V1.D2 -+ VZIP2 V22.D2, V20.D2, V5.D2 -+ VZIP1 V23.D2, V21.D2, V9.D2 -+ VZIP2 V23.D2, V21.D2, V13.D2 -+ VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16] -+ VZIP1 V26.D2, V24.D2, V2.D2 -+ VZIP2 V26.D2, V24.D2, V6.D2 -+ VZIP1 V27.D2, V25.D2, V10.D2 -+ VZIP2 V27.D2, V25.D2, V14.D2 -+ VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16] -+ VZIP1 V30.D2, V28.D2, V3.D2 -+ VZIP2 V30.D2, V28.D2, V7.D2 -+ VZIP1 V31.D2, V29.D2, V11.D2 -+ VZIP2 V31.D2, V29.D2, V15.D2 -+ VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16] -+ VEOR V0.B16, V16.B16, V16.B16 -+ VEOR V1.B16, V17.B16, V17.B16 -+ VEOR V2.B16, V18.B16, V18.B16 -+ VEOR V3.B16, V19.B16, V19.B16 -+ VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1) -+ VEOR V4.B16, V20.B16, V20.B16 -+ VEOR V5.B16, V21.B16, V21.B16 -+ VEOR V6.B16, V22.B16, V22.B16 -+ VEOR V7.B16, V23.B16, V23.B16 -+ VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1) -+ VEOR V8.B16, V24.B16, V24.B16 -+ VEOR V9.B16, V25.B16, V25.B16 -+ VEOR V10.B16, V26.B16, V26.B16 -+ VEOR V11.B16, V27.B16, V27.B16 -+ VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1) -+ VEOR V12.B16, V28.B16, V28.B16 -+ VEOR V13.B16, V29.B16, V29.B16 -+ VEOR V14.B16, V30.B16, V30.B16 -+ VEOR V15.B16, V31.B16, V31.B16 -+ VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1) -+ -+ ADD $4, R20 -+ MOVW R20, (R7) // update counter -+ -+ CMP R2, R12 -+ BGT loop -+ -+ RET -+ -+ -+DATA Β·constants+0x00(SB)/4, $0x61707865 -+DATA Β·constants+0x04(SB)/4, $0x3320646e -+DATA Β·constants+0x08(SB)/4, $0x79622d32 -+DATA Β·constants+0x0c(SB)/4, $0x6b206574 -+GLOBL Β·constants(SB), NOPTR|RODATA, $32 -+ -+DATA Β·incRotMatrix+0x00(SB)/4, $0x00000000 -+DATA Β·incRotMatrix+0x04(SB)/4, $0x00000001 -+DATA Β·incRotMatrix+0x08(SB)/4, $0x00000002 -+DATA Β·incRotMatrix+0x0c(SB)/4, $0x00000003 -+DATA Β·incRotMatrix+0x10(SB)/4, $0x02010003 -+DATA Β·incRotMatrix+0x14(SB)/4, $0x06050407 -+DATA Β·incRotMatrix+0x18(SB)/4, $0x0A09080B -+DATA Β·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F -+GLOBL Β·incRotMatrix(SB), NOPTR|RODATA, $32 -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go -new file mode 100644 -index 00000000000000..93eb5ae6de6f33 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_generic.go -@@ -0,0 +1,398 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms -+// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01. -+package chacha20 -+ -+import ( -+ "crypto/cipher" -+ "encoding/binary" -+ "errors" -+ "math/bits" -+ -+ "golang.org/x/crypto/internal/alias" -+) -+ -+const ( -+ // KeySize is the size of the key used by this cipher, in bytes. -+ KeySize = 32 -+ -+ // NonceSize is the size of the nonce used with the standard variant of this -+ // cipher, in bytes. -+ // -+ // Note that this is too short to be safely generated at random if the same -+ // key is reused more than 2Β³Β² times. -+ NonceSize = 12 -+ -+ // NonceSizeX is the size of the nonce used with the XChaCha20 variant of -+ // this cipher, in bytes. -+ NonceSizeX = 24 -+) -+ -+// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key -+// and nonce. A *Cipher implements the cipher.Stream interface. -+type Cipher struct { -+ // The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter -+ // (incremented after each block), and 3 of nonce. -+ key [8]uint32 -+ counter uint32 -+ nonce [3]uint32 -+ -+ // The last len bytes of buf are leftover key stream bytes from the previous -+ // XORKeyStream invocation. The size of buf depends on how many blocks are -+ // computed at a time by xorKeyStreamBlocks. -+ buf [bufSize]byte -+ len int -+ -+ // overflow is set when the counter overflowed, no more blocks can be -+ // generated, and the next XORKeyStream call should panic. -+ overflow bool -+ -+ // The counter-independent results of the first round are cached after they -+ // are computed the first time. -+ precompDone bool -+ p1, p5, p9, p13 uint32 -+ p2, p6, p10, p14 uint32 -+ p3, p7, p11, p15 uint32 -+} -+ -+var _ cipher.Stream = (*Cipher)(nil) -+ -+// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given -+// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided, -+// the XChaCha20 construction will be used. It returns an error if key or nonce -+// have any other length. -+// -+// Note that ChaCha20, like all stream ciphers, is not authenticated and allows -+// attackers to silently tamper with the plaintext. For this reason, it is more -+// appropriate as a building block than as a standalone encryption mechanism. -+// Instead, consider using package golang.org/x/crypto/chacha20poly1305. -+func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) { -+ // This function is split into a wrapper so that the Cipher allocation will -+ // be inlined, and depending on how the caller uses the return value, won't -+ // escape to the heap. -+ c := &Cipher{} -+ return newUnauthenticatedCipher(c, key, nonce) -+} -+ -+func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) { -+ if len(key) != KeySize { -+ return nil, errors.New("chacha20: wrong key size") -+ } -+ if len(nonce) == NonceSizeX { -+ // XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a -+ // derived key, allowing it to operate on a nonce of 24 bytes. See -+ // draft-irtf-cfrg-xchacha-01, Section 2.3. -+ key, _ = HChaCha20(key, nonce[0:16]) -+ cNonce := make([]byte, NonceSize) -+ copy(cNonce[4:12], nonce[16:24]) -+ nonce = cNonce -+ } else if len(nonce) != NonceSize { -+ return nil, errors.New("chacha20: wrong nonce size") -+ } -+ -+ key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint -+ c.key = [8]uint32{ -+ binary.LittleEndian.Uint32(key[0:4]), -+ binary.LittleEndian.Uint32(key[4:8]), -+ binary.LittleEndian.Uint32(key[8:12]), -+ binary.LittleEndian.Uint32(key[12:16]), -+ binary.LittleEndian.Uint32(key[16:20]), -+ binary.LittleEndian.Uint32(key[20:24]), -+ binary.LittleEndian.Uint32(key[24:28]), -+ binary.LittleEndian.Uint32(key[28:32]), -+ } -+ c.nonce = [3]uint32{ -+ binary.LittleEndian.Uint32(nonce[0:4]), -+ binary.LittleEndian.Uint32(nonce[4:8]), -+ binary.LittleEndian.Uint32(nonce[8:12]), -+ } -+ return c, nil -+} -+ -+// The constant first 4 words of the ChaCha20 state. -+const ( -+ j0 uint32 = 0x61707865 // expa -+ j1 uint32 = 0x3320646e // nd 3 -+ j2 uint32 = 0x79622d32 // 2-by -+ j3 uint32 = 0x6b206574 // te k -+) -+ -+const blockSize = 64 -+ -+// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words. -+// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16 -+// words each round, in columnar or diagonal groups of 4 at a time. -+func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { -+ a += b -+ d ^= a -+ d = bits.RotateLeft32(d, 16) -+ c += d -+ b ^= c -+ b = bits.RotateLeft32(b, 12) -+ a += b -+ d ^= a -+ d = bits.RotateLeft32(d, 8) -+ c += d -+ b ^= c -+ b = bits.RotateLeft32(b, 7) -+ return a, b, c, d -+} -+ -+// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will -+// behave as if (64 * counter) bytes had been encrypted so far. -+// -+// To prevent accidental counter reuse, SetCounter panics if counter is less -+// than the current value. -+// -+// Note that the execution time of XORKeyStream is not independent of the -+// counter value. -+func (s *Cipher) SetCounter(counter uint32) { -+ // Internally, s may buffer multiple blocks, which complicates this -+ // implementation slightly. When checking whether the counter has rolled -+ // back, we must use both s.counter and s.len to determine how many blocks -+ // we have already output. -+ outputCounter := s.counter - uint32(s.len)/blockSize -+ if s.overflow || counter < outputCounter { -+ panic("chacha20: SetCounter attempted to rollback counter") -+ } -+ -+ // In the general case, we set the new counter value and reset s.len to 0, -+ // causing the next call to XORKeyStream to refill the buffer. However, if -+ // we're advancing within the existing buffer, we can save work by simply -+ // setting s.len. -+ if counter < s.counter { -+ s.len = int(s.counter-counter) * blockSize -+ } else { -+ s.counter = counter -+ s.len = 0 -+ } -+} -+ -+// XORKeyStream XORs each byte in the given slice with a byte from the -+// cipher's key stream. Dst and src must overlap entirely or not at all. -+// -+// If len(dst) < len(src), XORKeyStream will panic. It is acceptable -+// to pass a dst bigger than src, and in that case, XORKeyStream will -+// only update dst[:len(src)] and will not touch the rest of dst. -+// -+// Multiple calls to XORKeyStream behave as if the concatenation of -+// the src buffers was passed in a single run. That is, Cipher -+// maintains state and does not reset at each XORKeyStream call. -+func (s *Cipher) XORKeyStream(dst, src []byte) { -+ if len(src) == 0 { -+ return -+ } -+ if len(dst) < len(src) { -+ panic("chacha20: output smaller than input") -+ } -+ dst = dst[:len(src)] -+ if alias.InexactOverlap(dst, src) { -+ panic("chacha20: invalid buffer overlap") -+ } -+ -+ // First, drain any remaining key stream from a previous XORKeyStream. -+ if s.len != 0 { -+ keyStream := s.buf[bufSize-s.len:] -+ if len(src) < len(keyStream) { -+ keyStream = keyStream[:len(src)] -+ } -+ _ = src[len(keyStream)-1] // bounds check elimination hint -+ for i, b := range keyStream { -+ dst[i] = src[i] ^ b -+ } -+ s.len -= len(keyStream) -+ dst, src = dst[len(keyStream):], src[len(keyStream):] -+ } -+ if len(src) == 0 { -+ return -+ } -+ -+ // If we'd need to let the counter overflow and keep generating output, -+ // panic immediately. If instead we'd only reach the last block, remember -+ // not to generate any more output after the buffer is drained. -+ numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize -+ if s.overflow || uint64(s.counter)+numBlocks > 1<<32 { -+ panic("chacha20: counter overflow") -+ } else if uint64(s.counter)+numBlocks == 1<<32 { -+ s.overflow = true -+ } -+ -+ // xorKeyStreamBlocks implementations expect input lengths that are a -+ // multiple of bufSize. Platform-specific ones process multiple blocks at a -+ // time, so have bufSizes that are a multiple of blockSize. -+ -+ full := len(src) - len(src)%bufSize -+ if full > 0 { -+ s.xorKeyStreamBlocks(dst[:full], src[:full]) -+ } -+ dst, src = dst[full:], src[full:] -+ -+ // If using a multi-block xorKeyStreamBlocks would overflow, use the generic -+ // one that does one block at a time. -+ const blocksPerBuf = bufSize / blockSize -+ if uint64(s.counter)+blocksPerBuf > 1<<32 { -+ s.buf = [bufSize]byte{} -+ numBlocks := (len(src) + blockSize - 1) / blockSize -+ buf := s.buf[bufSize-numBlocks*blockSize:] -+ copy(buf, src) -+ s.xorKeyStreamBlocksGeneric(buf, buf) -+ s.len = len(buf) - copy(dst, buf) -+ return -+ } -+ -+ // If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and -+ // keep the leftover keystream for the next XORKeyStream invocation. -+ if len(src) > 0 { -+ s.buf = [bufSize]byte{} -+ copy(s.buf[:], src) -+ s.xorKeyStreamBlocks(s.buf[:], s.buf[:]) -+ s.len = bufSize - copy(dst, s.buf[:]) -+ } -+} -+ -+func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) { -+ if len(dst) != len(src) || len(dst)%blockSize != 0 { -+ panic("chacha20: internal error: wrong dst and/or src length") -+ } -+ -+ // To generate each block of key stream, the initial cipher state -+ // (represented below) is passed through 20 rounds of shuffling, -+ // alternatively applying quarterRounds by columns (like 1, 5, 9, 13) -+ // or by diagonals (like 1, 6, 11, 12). -+ // -+ // 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc -+ // 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk -+ // 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk -+ // 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn -+ // -+ // c=constant k=key b=blockcount n=nonce -+ var ( -+ c0, c1, c2, c3 = j0, j1, j2, j3 -+ c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3] -+ c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7] -+ _, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2] -+ ) -+ -+ // Three quarters of the first round don't depend on the counter, so we can -+ // calculate them here, and reuse them for multiple blocks in the loop, and -+ // for future XORKeyStream invocations. -+ if !s.precompDone { -+ s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13) -+ s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14) -+ s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15) -+ s.precompDone = true -+ } -+ -+ // A condition of len(src) > 0 would be sufficient, but this also -+ // acts as a bounds check elimination hint. -+ for len(src) >= 64 && len(dst) >= 64 { -+ // The remainder of the first column round. -+ fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter) -+ -+ // The second diagonal round. -+ x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15) -+ x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12) -+ x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13) -+ x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14) -+ -+ // The remaining 18 rounds. -+ for i := 0; i < 9; i++ { -+ // Column round. -+ x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) -+ x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) -+ x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) -+ x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) -+ -+ // Diagonal round. -+ x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) -+ x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) -+ x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) -+ x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) -+ } -+ -+ // Add back the initial state to generate the key stream, then -+ // XOR the key stream with the source and write out the result. -+ addXor(dst[0:4], src[0:4], x0, c0) -+ addXor(dst[4:8], src[4:8], x1, c1) -+ addXor(dst[8:12], src[8:12], x2, c2) -+ addXor(dst[12:16], src[12:16], x3, c3) -+ addXor(dst[16:20], src[16:20], x4, c4) -+ addXor(dst[20:24], src[20:24], x5, c5) -+ addXor(dst[24:28], src[24:28], x6, c6) -+ addXor(dst[28:32], src[28:32], x7, c7) -+ addXor(dst[32:36], src[32:36], x8, c8) -+ addXor(dst[36:40], src[36:40], x9, c9) -+ addXor(dst[40:44], src[40:44], x10, c10) -+ addXor(dst[44:48], src[44:48], x11, c11) -+ addXor(dst[48:52], src[48:52], x12, s.counter) -+ addXor(dst[52:56], src[52:56], x13, c13) -+ addXor(dst[56:60], src[56:60], x14, c14) -+ addXor(dst[60:64], src[60:64], x15, c15) -+ -+ s.counter += 1 -+ -+ src, dst = src[blockSize:], dst[blockSize:] -+ } -+} -+ -+// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes -+// key and a 16 bytes nonce. It returns an error if key or nonce have any other -+// length. It is used as part of the XChaCha20 construction. -+func HChaCha20(key, nonce []byte) ([]byte, error) { -+ // This function is split into a wrapper so that the slice allocation will -+ // be inlined, and depending on how the caller uses the return value, won't -+ // escape to the heap. -+ out := make([]byte, 32) -+ return hChaCha20(out, key, nonce) -+} -+ -+func hChaCha20(out, key, nonce []byte) ([]byte, error) { -+ if len(key) != KeySize { -+ return nil, errors.New("chacha20: wrong HChaCha20 key size") -+ } -+ if len(nonce) != 16 { -+ return nil, errors.New("chacha20: wrong HChaCha20 nonce size") -+ } -+ -+ x0, x1, x2, x3 := j0, j1, j2, j3 -+ x4 := binary.LittleEndian.Uint32(key[0:4]) -+ x5 := binary.LittleEndian.Uint32(key[4:8]) -+ x6 := binary.LittleEndian.Uint32(key[8:12]) -+ x7 := binary.LittleEndian.Uint32(key[12:16]) -+ x8 := binary.LittleEndian.Uint32(key[16:20]) -+ x9 := binary.LittleEndian.Uint32(key[20:24]) -+ x10 := binary.LittleEndian.Uint32(key[24:28]) -+ x11 := binary.LittleEndian.Uint32(key[28:32]) -+ x12 := binary.LittleEndian.Uint32(nonce[0:4]) -+ x13 := binary.LittleEndian.Uint32(nonce[4:8]) -+ x14 := binary.LittleEndian.Uint32(nonce[8:12]) -+ x15 := binary.LittleEndian.Uint32(nonce[12:16]) -+ -+ for i := 0; i < 10; i++ { -+ // Diagonal round. -+ x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) -+ x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) -+ x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) -+ x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) -+ -+ // Column round. -+ x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) -+ x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) -+ x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) -+ x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) -+ } -+ -+ _ = out[31] // bounds check elimination hint -+ binary.LittleEndian.PutUint32(out[0:4], x0) -+ binary.LittleEndian.PutUint32(out[4:8], x1) -+ binary.LittleEndian.PutUint32(out[8:12], x2) -+ binary.LittleEndian.PutUint32(out[12:16], x3) -+ binary.LittleEndian.PutUint32(out[16:20], x12) -+ binary.LittleEndian.PutUint32(out[20:24], x13) -+ binary.LittleEndian.PutUint32(out[24:28], x14) -+ binary.LittleEndian.PutUint32(out[28:32], x15) -+ return out, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go -new file mode 100644 -index 00000000000000..025b49897e32b2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_noasm.go -@@ -0,0 +1,14 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego -+// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego -+ -+package chacha20 -+ -+const bufSize = blockSize -+ -+func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) { -+ s.xorKeyStreamBlocksGeneric(dst, src) -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go -new file mode 100644 -index 00000000000000..da420b2e97b03c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.go -@@ -0,0 +1,17 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package chacha20 -+ -+const bufSize = 256 -+ -+//go:noescape -+func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) -+ -+func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { -+ chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter) -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s -new file mode 100644 -index 00000000000000..5c0fed26f85027 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_ppc64le.s -@@ -0,0 +1,450 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Based on CRYPTOGAMS code with the following comment: -+// # ==================================================================== -+// # Written by Andy Polyakov for the OpenSSL -+// # project. The module is, however, dual licensed under OpenSSL and -+// # CRYPTOGAMS licenses depending on where you obtain it. For further -+// # details see http://www.openssl.org/~appro/cryptogams/. -+// # ==================================================================== -+ -+// Code for the perl script that generates the ppc64 assembler -+// can be found in the cryptogams repository at the link below. It is based on -+// the original from openssl. -+ -+// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91 -+ -+// The differences in this and the original implementation are -+// due to the calling conventions and initialization of constants. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+ -+#define OUT R3 -+#define INP R4 -+#define LEN R5 -+#define KEY R6 -+#define CNT R7 -+#define TMP R15 -+ -+#define CONSTBASE R16 -+#define BLOCKS R17 -+ -+DATA consts<>+0x00(SB)/8, $0x3320646e61707865 -+DATA consts<>+0x08(SB)/8, $0x6b20657479622d32 -+DATA consts<>+0x10(SB)/8, $0x0000000000000001 -+DATA consts<>+0x18(SB)/8, $0x0000000000000000 -+DATA consts<>+0x20(SB)/8, $0x0000000000000004 -+DATA consts<>+0x28(SB)/8, $0x0000000000000000 -+DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d -+DATA consts<>+0x38(SB)/8, $0x0203000106070405 -+DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c -+DATA consts<>+0x48(SB)/8, $0x0102030005060704 -+DATA consts<>+0x50(SB)/8, $0x6170786561707865 -+DATA consts<>+0x58(SB)/8, $0x6170786561707865 -+DATA consts<>+0x60(SB)/8, $0x3320646e3320646e -+DATA consts<>+0x68(SB)/8, $0x3320646e3320646e -+DATA consts<>+0x70(SB)/8, $0x79622d3279622d32 -+DATA consts<>+0x78(SB)/8, $0x79622d3279622d32 -+DATA consts<>+0x80(SB)/8, $0x6b2065746b206574 -+DATA consts<>+0x88(SB)/8, $0x6b2065746b206574 -+DATA consts<>+0x90(SB)/8, $0x0000000100000000 -+DATA consts<>+0x98(SB)/8, $0x0000000300000002 -+GLOBL consts<>(SB), RODATA, $0xa0 -+ -+//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) -+TEXT Β·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 -+ MOVD out+0(FP), OUT -+ MOVD inp+8(FP), INP -+ MOVD len+16(FP), LEN -+ MOVD key+24(FP), KEY -+ MOVD counter+32(FP), CNT -+ -+ // Addressing for constants -+ MOVD $consts<>+0x00(SB), CONSTBASE -+ MOVD $16, R8 -+ MOVD $32, R9 -+ MOVD $48, R10 -+ MOVD $64, R11 -+ SRD $6, LEN, BLOCKS -+ // V16 -+ LXVW4X (CONSTBASE)(R0), VS48 -+ ADD $80,CONSTBASE -+ -+ // Load key into V17,V18 -+ LXVW4X (KEY)(R0), VS49 -+ LXVW4X (KEY)(R8), VS50 -+ -+ // Load CNT, NONCE into V19 -+ LXVW4X (CNT)(R0), VS51 -+ -+ // Clear V27 -+ VXOR V27, V27, V27 -+ -+ // V28 -+ LXVW4X (CONSTBASE)(R11), VS60 -+ -+ // splat slot from V19 -> V26 -+ VSPLTW $0, V19, V26 -+ -+ VSLDOI $4, V19, V27, V19 -+ VSLDOI $12, V27, V19, V19 -+ -+ VADDUWM V26, V28, V26 -+ -+ MOVD $10, R14 -+ MOVD R14, CTR -+ -+loop_outer_vsx: -+ // V0, V1, V2, V3 -+ LXVW4X (R0)(CONSTBASE), VS32 -+ LXVW4X (R8)(CONSTBASE), VS33 -+ LXVW4X (R9)(CONSTBASE), VS34 -+ LXVW4X (R10)(CONSTBASE), VS35 -+ -+ // splat values from V17, V18 into V4-V11 -+ VSPLTW $0, V17, V4 -+ VSPLTW $1, V17, V5 -+ VSPLTW $2, V17, V6 -+ VSPLTW $3, V17, V7 -+ VSPLTW $0, V18, V8 -+ VSPLTW $1, V18, V9 -+ VSPLTW $2, V18, V10 -+ VSPLTW $3, V18, V11 -+ -+ // VOR -+ VOR V26, V26, V12 -+ -+ // splat values from V19 -> V13, V14, V15 -+ VSPLTW $1, V19, V13 -+ VSPLTW $2, V19, V14 -+ VSPLTW $3, V19, V15 -+ -+ // splat const values -+ VSPLTISW $-16, V27 -+ VSPLTISW $12, V28 -+ VSPLTISW $8, V29 -+ VSPLTISW $7, V30 -+ -+loop_vsx: -+ VADDUWM V0, V4, V0 -+ VADDUWM V1, V5, V1 -+ VADDUWM V2, V6, V2 -+ VADDUWM V3, V7, V3 -+ -+ VXOR V12, V0, V12 -+ VXOR V13, V1, V13 -+ VXOR V14, V2, V14 -+ VXOR V15, V3, V15 -+ -+ VRLW V12, V27, V12 -+ VRLW V13, V27, V13 -+ VRLW V14, V27, V14 -+ VRLW V15, V27, V15 -+ -+ VADDUWM V8, V12, V8 -+ VADDUWM V9, V13, V9 -+ VADDUWM V10, V14, V10 -+ VADDUWM V11, V15, V11 -+ -+ VXOR V4, V8, V4 -+ VXOR V5, V9, V5 -+ VXOR V6, V10, V6 -+ VXOR V7, V11, V7 -+ -+ VRLW V4, V28, V4 -+ VRLW V5, V28, V5 -+ VRLW V6, V28, V6 -+ VRLW V7, V28, V7 -+ -+ VADDUWM V0, V4, V0 -+ VADDUWM V1, V5, V1 -+ VADDUWM V2, V6, V2 -+ VADDUWM V3, V7, V3 -+ -+ VXOR V12, V0, V12 -+ VXOR V13, V1, V13 -+ VXOR V14, V2, V14 -+ VXOR V15, V3, V15 -+ -+ VRLW V12, V29, V12 -+ VRLW V13, V29, V13 -+ VRLW V14, V29, V14 -+ VRLW V15, V29, V15 -+ -+ VADDUWM V8, V12, V8 -+ VADDUWM V9, V13, V9 -+ VADDUWM V10, V14, V10 -+ VADDUWM V11, V15, V11 -+ -+ VXOR V4, V8, V4 -+ VXOR V5, V9, V5 -+ VXOR V6, V10, V6 -+ VXOR V7, V11, V7 -+ -+ VRLW V4, V30, V4 -+ VRLW V5, V30, V5 -+ VRLW V6, V30, V6 -+ VRLW V7, V30, V7 -+ -+ VADDUWM V0, V5, V0 -+ VADDUWM V1, V6, V1 -+ VADDUWM V2, V7, V2 -+ VADDUWM V3, V4, V3 -+ -+ VXOR V15, V0, V15 -+ VXOR V12, V1, V12 -+ VXOR V13, V2, V13 -+ VXOR V14, V3, V14 -+ -+ VRLW V15, V27, V15 -+ VRLW V12, V27, V12 -+ VRLW V13, V27, V13 -+ VRLW V14, V27, V14 -+ -+ VADDUWM V10, V15, V10 -+ VADDUWM V11, V12, V11 -+ VADDUWM V8, V13, V8 -+ VADDUWM V9, V14, V9 -+ -+ VXOR V5, V10, V5 -+ VXOR V6, V11, V6 -+ VXOR V7, V8, V7 -+ VXOR V4, V9, V4 -+ -+ VRLW V5, V28, V5 -+ VRLW V6, V28, V6 -+ VRLW V7, V28, V7 -+ VRLW V4, V28, V4 -+ -+ VADDUWM V0, V5, V0 -+ VADDUWM V1, V6, V1 -+ VADDUWM V2, V7, V2 -+ VADDUWM V3, V4, V3 -+ -+ VXOR V15, V0, V15 -+ VXOR V12, V1, V12 -+ VXOR V13, V2, V13 -+ VXOR V14, V3, V14 -+ -+ VRLW V15, V29, V15 -+ VRLW V12, V29, V12 -+ VRLW V13, V29, V13 -+ VRLW V14, V29, V14 -+ -+ VADDUWM V10, V15, V10 -+ VADDUWM V11, V12, V11 -+ VADDUWM V8, V13, V8 -+ VADDUWM V9, V14, V9 -+ -+ VXOR V5, V10, V5 -+ VXOR V6, V11, V6 -+ VXOR V7, V8, V7 -+ VXOR V4, V9, V4 -+ -+ VRLW V5, V30, V5 -+ VRLW V6, V30, V6 -+ VRLW V7, V30, V7 -+ VRLW V4, V30, V4 -+ BC 16, LT, loop_vsx -+ -+ VADDUWM V12, V26, V12 -+ -+ WORD $0x13600F8C // VMRGEW V0, V1, V27 -+ WORD $0x13821F8C // VMRGEW V2, V3, V28 -+ -+ WORD $0x10000E8C // VMRGOW V0, V1, V0 -+ WORD $0x10421E8C // VMRGOW V2, V3, V2 -+ -+ WORD $0x13A42F8C // VMRGEW V4, V5, V29 -+ WORD $0x13C63F8C // VMRGEW V6, V7, V30 -+ -+ XXPERMDI VS32, VS34, $0, VS33 -+ XXPERMDI VS32, VS34, $3, VS35 -+ XXPERMDI VS59, VS60, $0, VS32 -+ XXPERMDI VS59, VS60, $3, VS34 -+ -+ WORD $0x10842E8C // VMRGOW V4, V5, V4 -+ WORD $0x10C63E8C // VMRGOW V6, V7, V6 -+ -+ WORD $0x13684F8C // VMRGEW V8, V9, V27 -+ WORD $0x138A5F8C // VMRGEW V10, V11, V28 -+ -+ XXPERMDI VS36, VS38, $0, VS37 -+ XXPERMDI VS36, VS38, $3, VS39 -+ XXPERMDI VS61, VS62, $0, VS36 -+ XXPERMDI VS61, VS62, $3, VS38 -+ -+ WORD $0x11084E8C // VMRGOW V8, V9, V8 -+ WORD $0x114A5E8C // VMRGOW V10, V11, V10 -+ -+ WORD $0x13AC6F8C // VMRGEW V12, V13, V29 -+ WORD $0x13CE7F8C // VMRGEW V14, V15, V30 -+ -+ XXPERMDI VS40, VS42, $0, VS41 -+ XXPERMDI VS40, VS42, $3, VS43 -+ XXPERMDI VS59, VS60, $0, VS40 -+ XXPERMDI VS59, VS60, $3, VS42 -+ -+ WORD $0x118C6E8C // VMRGOW V12, V13, V12 -+ WORD $0x11CE7E8C // VMRGOW V14, V15, V14 -+ -+ VSPLTISW $4, V27 -+ VADDUWM V26, V27, V26 -+ -+ XXPERMDI VS44, VS46, $0, VS45 -+ XXPERMDI VS44, VS46, $3, VS47 -+ XXPERMDI VS61, VS62, $0, VS44 -+ XXPERMDI VS61, VS62, $3, VS46 -+ -+ VADDUWM V0, V16, V0 -+ VADDUWM V4, V17, V4 -+ VADDUWM V8, V18, V8 -+ VADDUWM V12, V19, V12 -+ -+ CMPU LEN, $64 -+ BLT tail_vsx -+ -+ // Bottom of loop -+ LXVW4X (INP)(R0), VS59 -+ LXVW4X (INP)(R8), VS60 -+ LXVW4X (INP)(R9), VS61 -+ LXVW4X (INP)(R10), VS62 -+ -+ VXOR V27, V0, V27 -+ VXOR V28, V4, V28 -+ VXOR V29, V8, V29 -+ VXOR V30, V12, V30 -+ -+ STXVW4X VS59, (OUT)(R0) -+ STXVW4X VS60, (OUT)(R8) -+ ADD $64, INP -+ STXVW4X VS61, (OUT)(R9) -+ ADD $-64, LEN -+ STXVW4X VS62, (OUT)(R10) -+ ADD $64, OUT -+ BEQ done_vsx -+ -+ VADDUWM V1, V16, V0 -+ VADDUWM V5, V17, V4 -+ VADDUWM V9, V18, V8 -+ VADDUWM V13, V19, V12 -+ -+ CMPU LEN, $64 -+ BLT tail_vsx -+ -+ LXVW4X (INP)(R0), VS59 -+ LXVW4X (INP)(R8), VS60 -+ LXVW4X (INP)(R9), VS61 -+ LXVW4X (INP)(R10), VS62 -+ VXOR V27, V0, V27 -+ -+ VXOR V28, V4, V28 -+ VXOR V29, V8, V29 -+ VXOR V30, V12, V30 -+ -+ STXVW4X VS59, (OUT)(R0) -+ STXVW4X VS60, (OUT)(R8) -+ ADD $64, INP -+ STXVW4X VS61, (OUT)(R9) -+ ADD $-64, LEN -+ STXVW4X VS62, (OUT)(V10) -+ ADD $64, OUT -+ BEQ done_vsx -+ -+ VADDUWM V2, V16, V0 -+ VADDUWM V6, V17, V4 -+ VADDUWM V10, V18, V8 -+ VADDUWM V14, V19, V12 -+ -+ CMPU LEN, $64 -+ BLT tail_vsx -+ -+ LXVW4X (INP)(R0), VS59 -+ LXVW4X (INP)(R8), VS60 -+ LXVW4X (INP)(R9), VS61 -+ LXVW4X (INP)(R10), VS62 -+ -+ VXOR V27, V0, V27 -+ VXOR V28, V4, V28 -+ VXOR V29, V8, V29 -+ VXOR V30, V12, V30 -+ -+ STXVW4X VS59, (OUT)(R0) -+ STXVW4X VS60, (OUT)(R8) -+ ADD $64, INP -+ STXVW4X VS61, (OUT)(R9) -+ ADD $-64, LEN -+ STXVW4X VS62, (OUT)(R10) -+ ADD $64, OUT -+ BEQ done_vsx -+ -+ VADDUWM V3, V16, V0 -+ VADDUWM V7, V17, V4 -+ VADDUWM V11, V18, V8 -+ VADDUWM V15, V19, V12 -+ -+ CMPU LEN, $64 -+ BLT tail_vsx -+ -+ LXVW4X (INP)(R0), VS59 -+ LXVW4X (INP)(R8), VS60 -+ LXVW4X (INP)(R9), VS61 -+ LXVW4X (INP)(R10), VS62 -+ -+ VXOR V27, V0, V27 -+ VXOR V28, V4, V28 -+ VXOR V29, V8, V29 -+ VXOR V30, V12, V30 -+ -+ STXVW4X VS59, (OUT)(R0) -+ STXVW4X VS60, (OUT)(R8) -+ ADD $64, INP -+ STXVW4X VS61, (OUT)(R9) -+ ADD $-64, LEN -+ STXVW4X VS62, (OUT)(R10) -+ ADD $64, OUT -+ -+ MOVD $10, R14 -+ MOVD R14, CTR -+ BNE loop_outer_vsx -+ -+done_vsx: -+ // Increment counter by number of 64 byte blocks -+ MOVD (CNT), R14 -+ ADD BLOCKS, R14 -+ MOVD R14, (CNT) -+ RET -+ -+tail_vsx: -+ ADD $32, R1, R11 -+ MOVD LEN, CTR -+ -+ // Save values on stack to copy from -+ STXVW4X VS32, (R11)(R0) -+ STXVW4X VS36, (R11)(R8) -+ STXVW4X VS40, (R11)(R9) -+ STXVW4X VS44, (R11)(R10) -+ ADD $-1, R11, R12 -+ ADD $-1, INP -+ ADD $-1, OUT -+ -+looptail_vsx: -+ // Copying the result to OUT -+ // in bytes. -+ MOVBZU 1(R12), KEY -+ MOVBZU 1(INP), TMP -+ XOR KEY, TMP, KEY -+ MOVBU KEY, 1(OUT) -+ BC 16, LT, looptail_vsx -+ -+ // Clear the stack values -+ STXVW4X VS48, (R11)(R0) -+ STXVW4X VS48, (R11)(R8) -+ STXVW4X VS48, (R11)(R9) -+ STXVW4X VS48, (R11)(R10) -+ BR done_vsx -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go -new file mode 100644 -index 00000000000000..4652247b8a637e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.go -@@ -0,0 +1,28 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package chacha20 -+ -+import "golang.org/x/sys/cpu" -+ -+var haveAsm = cpu.S390X.HasVX -+ -+const bufSize = 256 -+ -+// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only -+// be called when the vector facility is available. Implementation in asm_s390x.s. -+// -+//go:noescape -+func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) -+ -+func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) { -+ if cpu.S390X.HasVX { -+ xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) -+ } else { -+ c.xorKeyStreamBlocksGeneric(dst, src) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s -new file mode 100644 -index 00000000000000..f3ef5a019d9593 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_s390x.s -@@ -0,0 +1,225 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "go_asm.h" -+#include "textflag.h" -+ -+// This is an implementation of the ChaCha20 encryption algorithm as -+// specified in RFC 7539. It uses vector instructions to compute -+// 4 keystream blocks in parallel (256 bytes) which are then XORed -+// with the bytes in the input slice. -+ -+GLOBL Β·constants<>(SB), RODATA|NOPTR, $32 -+// BSWAP: swap bytes in each 4-byte element -+DATA Β·constants<>+0x00(SB)/4, $0x03020100 -+DATA Β·constants<>+0x04(SB)/4, $0x07060504 -+DATA Β·constants<>+0x08(SB)/4, $0x0b0a0908 -+DATA Β·constants<>+0x0c(SB)/4, $0x0f0e0d0c -+// J0: [j0, j1, j2, j3] -+DATA Β·constants<>+0x10(SB)/4, $0x61707865 -+DATA Β·constants<>+0x14(SB)/4, $0x3320646e -+DATA Β·constants<>+0x18(SB)/4, $0x79622d32 -+DATA Β·constants<>+0x1c(SB)/4, $0x6b206574 -+ -+#define BSWAP V5 -+#define J0 V6 -+#define KEY0 V7 -+#define KEY1 V8 -+#define NONCE V9 -+#define CTR V10 -+#define M0 V11 -+#define M1 V12 -+#define M2 V13 -+#define M3 V14 -+#define INC V15 -+#define X0 V16 -+#define X1 V17 -+#define X2 V18 -+#define X3 V19 -+#define X4 V20 -+#define X5 V21 -+#define X6 V22 -+#define X7 V23 -+#define X8 V24 -+#define X9 V25 -+#define X10 V26 -+#define X11 V27 -+#define X12 V28 -+#define X13 V29 -+#define X14 V30 -+#define X15 V31 -+ -+#define NUM_ROUNDS 20 -+ -+#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \ -+ VAF a1, a0, a0 \ -+ VAF b1, b0, b0 \ -+ VAF c1, c0, c0 \ -+ VAF d1, d0, d0 \ -+ VX a0, a2, a2 \ -+ VX b0, b2, b2 \ -+ VX c0, c2, c2 \ -+ VX d0, d2, d2 \ -+ VERLLF $16, a2, a2 \ -+ VERLLF $16, b2, b2 \ -+ VERLLF $16, c2, c2 \ -+ VERLLF $16, d2, d2 \ -+ VAF a2, a3, a3 \ -+ VAF b2, b3, b3 \ -+ VAF c2, c3, c3 \ -+ VAF d2, d3, d3 \ -+ VX a3, a1, a1 \ -+ VX b3, b1, b1 \ -+ VX c3, c1, c1 \ -+ VX d3, d1, d1 \ -+ VERLLF $12, a1, a1 \ -+ VERLLF $12, b1, b1 \ -+ VERLLF $12, c1, c1 \ -+ VERLLF $12, d1, d1 \ -+ VAF a1, a0, a0 \ -+ VAF b1, b0, b0 \ -+ VAF c1, c0, c0 \ -+ VAF d1, d0, d0 \ -+ VX a0, a2, a2 \ -+ VX b0, b2, b2 \ -+ VX c0, c2, c2 \ -+ VX d0, d2, d2 \ -+ VERLLF $8, a2, a2 \ -+ VERLLF $8, b2, b2 \ -+ VERLLF $8, c2, c2 \ -+ VERLLF $8, d2, d2 \ -+ VAF a2, a3, a3 \ -+ VAF b2, b3, b3 \ -+ VAF c2, c3, c3 \ -+ VAF d2, d3, d3 \ -+ VX a3, a1, a1 \ -+ VX b3, b1, b1 \ -+ VX c3, c1, c1 \ -+ VX d3, d1, d1 \ -+ VERLLF $7, a1, a1 \ -+ VERLLF $7, b1, b1 \ -+ VERLLF $7, c1, c1 \ -+ VERLLF $7, d1, d1 -+ -+#define PERMUTE(mask, v0, v1, v2, v3) \ -+ VPERM v0, v0, mask, v0 \ -+ VPERM v1, v1, mask, v1 \ -+ VPERM v2, v2, mask, v2 \ -+ VPERM v3, v3, mask, v3 -+ -+#define ADDV(x, v0, v1, v2, v3) \ -+ VAF x, v0, v0 \ -+ VAF x, v1, v1 \ -+ VAF x, v2, v2 \ -+ VAF x, v3, v3 -+ -+#define XORV(off, dst, src, v0, v1, v2, v3) \ -+ VLM off(src), M0, M3 \ -+ PERMUTE(BSWAP, v0, v1, v2, v3) \ -+ VX v0, M0, M0 \ -+ VX v1, M1, M1 \ -+ VX v2, M2, M2 \ -+ VX v3, M3, M3 \ -+ VSTM M0, M3, off(dst) -+ -+#define SHUFFLE(a, b, c, d, t, u, v, w) \ -+ VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]} -+ VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]} -+ VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]} -+ VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]} -+ VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]} -+ VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]} -+ VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} -+ VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} -+ -+// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) -+TEXT Β·xorKeyStreamVX(SB), NOSPLIT, $0 -+ MOVD $Β·constants<>(SB), R1 -+ MOVD dst+0(FP), R2 // R2=&dst[0] -+ LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src) -+ MOVD key+48(FP), R5 // R5=key -+ MOVD nonce+56(FP), R6 // R6=nonce -+ MOVD counter+64(FP), R7 // R7=counter -+ -+ // load BSWAP and J0 -+ VLM (R1), BSWAP, J0 -+ -+ // setup -+ MOVD $95, R0 -+ VLM (R5), KEY0, KEY1 -+ VLL R0, (R6), NONCE -+ VZERO M0 -+ VLEIB $7, $32, M0 -+ VSRLB M0, NONCE, NONCE -+ -+ // initialize counter values -+ VLREPF (R7), CTR -+ VZERO INC -+ VLEIF $1, $1, INC -+ VLEIF $2, $2, INC -+ VLEIF $3, $3, INC -+ VAF INC, CTR, CTR -+ VREPIF $4, INC -+ -+chacha: -+ VREPF $0, J0, X0 -+ VREPF $1, J0, X1 -+ VREPF $2, J0, X2 -+ VREPF $3, J0, X3 -+ VREPF $0, KEY0, X4 -+ VREPF $1, KEY0, X5 -+ VREPF $2, KEY0, X6 -+ VREPF $3, KEY0, X7 -+ VREPF $0, KEY1, X8 -+ VREPF $1, KEY1, X9 -+ VREPF $2, KEY1, X10 -+ VREPF $3, KEY1, X11 -+ VLR CTR, X12 -+ VREPF $1, NONCE, X13 -+ VREPF $2, NONCE, X14 -+ VREPF $3, NONCE, X15 -+ -+ MOVD $(NUM_ROUNDS/2), R1 -+ -+loop: -+ ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11) -+ ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9) -+ -+ ADD $-1, R1 -+ BNE loop -+ -+ // decrement length -+ ADD $-256, R4 -+ -+ // rearrange vectors -+ SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) -+ ADDV(J0, X0, X1, X2, X3) -+ SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3) -+ ADDV(KEY0, X4, X5, X6, X7) -+ SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3) -+ ADDV(KEY1, X8, X9, X10, X11) -+ VAF CTR, X12, X12 -+ SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3) -+ ADDV(NONCE, X12, X13, X14, X15) -+ -+ // increment counters -+ VAF INC, CTR, CTR -+ -+ // xor keystream with plaintext -+ XORV(0*64, R2, R3, X0, X4, X8, X12) -+ XORV(1*64, R2, R3, X1, X5, X9, X13) -+ XORV(2*64, R2, R3, X2, X6, X10, X14) -+ XORV(3*64, R2, R3, X3, X7, X11, X15) -+ -+ // increment pointers -+ MOVD $256(R2), R2 -+ MOVD $256(R3), R3 -+ -+ CMPBNE R4, $0, chacha -+ -+ VSTEF $0, CTR, (R7) -+ RET -diff --git a/ms_mod/golang.org/x/crypto/chacha20/chacha_test.go b/ms_mod/golang.org/x/crypto/chacha20/chacha_test.go -new file mode 100644 -index 00000000000000..60b11d92f6f582 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/chacha_test.go -@@ -0,0 +1,274 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "fmt" -+ "math/rand" -+ "testing" -+) -+ -+func _() { -+ // Assert that bufSize is a multiple of blockSize. -+ var b [1]byte -+ _ = b[bufSize%blockSize] -+} -+ -+func hexDecode(s string) []byte { -+ ss, err := hex.DecodeString(s) -+ if err != nil { -+ panic(fmt.Sprintf("cannot decode input %#v: %v", s, err)) -+ } -+ return ss -+} -+ -+// Run the test cases with the input and output in different buffers. -+func TestNoOverlap(t *testing.T) { -+ for _, c := range testVectors { -+ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) -+ input := hexDecode(c.input) -+ output := make([]byte, len(input)) -+ s.XORKeyStream(output, input) -+ got := hex.EncodeToString(output) -+ if got != c.output { -+ t.Errorf("length=%v: got %#v, want %#v", len(input), got, c.output) -+ } -+ } -+} -+ -+// Run the test cases with the input and output overlapping entirely. -+func TestOverlap(t *testing.T) { -+ for _, c := range testVectors { -+ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) -+ data := hexDecode(c.input) -+ s.XORKeyStream(data, data) -+ got := hex.EncodeToString(data) -+ if got != c.output { -+ t.Errorf("length=%v: got %#v, want %#v", len(data), got, c.output) -+ } -+ } -+} -+ -+// Run the test cases with various source and destination offsets. -+func TestUnaligned(t *testing.T) { -+ const max = 8 // max offset (+1) to test -+ for _, c := range testVectors { -+ data := hexDecode(c.input) -+ input := make([]byte, len(data)+max) -+ output := make([]byte, len(data)+max) -+ for i := 0; i < max; i++ { // input offsets -+ for j := 0; j < max; j++ { // output offsets -+ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) -+ -+ input := input[i : i+len(data)] -+ output := output[j : j+len(data)] -+ -+ copy(input, data) -+ s.XORKeyStream(output, input) -+ got := hex.EncodeToString(output) -+ if got != c.output { -+ t.Errorf("length=%v: got %#v, want %#v", len(data), got, c.output) -+ } -+ } -+ } -+ } -+} -+ -+// Run the test cases by calling XORKeyStream multiple times. -+func TestStep(t *testing.T) { -+ // wide range of step sizes to try and hit edge cases -+ steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256} -+ rnd := rand.New(rand.NewSource(123)) -+ for _, c := range testVectors { -+ s, _ := NewUnauthenticatedCipher(hexDecode(c.key), hexDecode(c.nonce)) -+ input := hexDecode(c.input) -+ output := make([]byte, len(input)) -+ -+ // step through the buffers -+ i, step := 0, steps[rnd.Intn(len(steps))] -+ for i+step < len(input) { -+ s.XORKeyStream(output[i:i+step], input[i:i+step]) -+ if i+step < len(input) && output[i+step] != 0 { -+ t.Errorf("length=%v, i=%v, step=%v: output overwritten", len(input), i, step) -+ } -+ i += step -+ step = steps[rnd.Intn(len(steps))] -+ } -+ // finish the encryption -+ s.XORKeyStream(output[i:], input[i:]) -+ // ensure we tolerate a call with an empty input -+ s.XORKeyStream(output[len(output):], input[len(input):]) -+ -+ got := hex.EncodeToString(output) -+ if got != c.output { -+ t.Errorf("length=%v: got %#v, want %#v", len(input), got, c.output) -+ } -+ } -+} -+ -+func TestSetCounter(t *testing.T) { -+ newCipher := func() *Cipher { -+ s, _ := NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) -+ return s -+ } -+ s := newCipher() -+ src := bytes.Repeat([]byte("test"), 32) // two 64-byte blocks -+ dst1 := make([]byte, len(src)) -+ s.XORKeyStream(dst1, src) -+ // advance counter to 1 and xor second block -+ s = newCipher() -+ s.SetCounter(1) -+ dst2 := make([]byte, len(src)) -+ s.XORKeyStream(dst2[64:], src[64:]) -+ if !bytes.Equal(dst1[64:], dst2[64:]) { -+ t.Error("failed to produce identical output using SetCounter") -+ } -+ -+ // test again with unaligned blocks; SetCounter should reset the buffer -+ s = newCipher() -+ s.XORKeyStream(dst1[:70], src[:70]) -+ s = newCipher() -+ s.XORKeyStream([]byte{0}, []byte{0}) -+ s.SetCounter(1) -+ s.XORKeyStream(dst2[64:70], src[64:70]) -+ if !bytes.Equal(dst1[64:70], dst2[64:70]) { -+ t.Error("SetCounter did not reset buffer") -+ } -+ -+ // advancing to a lower counter value should cause a panic -+ panics := func(fn func()) (p bool) { -+ defer func() { p = recover() != nil }() -+ fn() -+ return -+ } -+ if !panics(func() { s.SetCounter(0) }) { -+ t.Error("counter decreasing should trigger a panic") -+ } -+} -+ -+func TestLastBlock(t *testing.T) { -+ panics := func(fn func()) (p bool) { -+ defer func() { p = recover() != nil }() -+ fn() -+ return -+ } -+ -+ checkLastBlock := func(b []byte) { -+ t.Helper() -+ // Hardcoded result to check all implementations generate the same output. -+ lastBlock := "ace4cd09e294d1912d4ad205d06f95d9c2f2bfcf453e8753f128765b62215f4d" + -+ "92c74f2f626c6a640c0b1284d839ec81f1696281dafc3e684593937023b58b1d" -+ if got := hex.EncodeToString(b); got != lastBlock { -+ t.Errorf("wrong output for the last block, got %q, want %q", got, lastBlock) -+ } -+ } -+ -+ // setting the counter to 0xffffffff and crypting multiple blocks should -+ // trigger a panic -+ s, _ := NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) -+ s.SetCounter(0xffffffff) -+ blocks := make([]byte, blockSize*2) -+ if !panics(func() { s.XORKeyStream(blocks, blocks) }) { -+ t.Error("crypting multiple blocks should trigger a panic") -+ } -+ -+ // setting the counter to 0xffffffff - 1 and crypting two blocks should not -+ // trigger a panic -+ s, _ = NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) -+ s.SetCounter(0xffffffff - 1) -+ if panics(func() { s.XORKeyStream(blocks, blocks) }) { -+ t.Error("crypting the last blocks should not trigger a panic") -+ } -+ checkLastBlock(blocks[blockSize:]) -+ // once all the keystream is spent, setting the counter should panic -+ if !panics(func() { s.SetCounter(0xffffffff) }) { -+ t.Error("setting the counter after overflow should trigger a panic") -+ } -+ // crypting a subsequent block *should* panic -+ block := make([]byte, blockSize) -+ if !panics(func() { s.XORKeyStream(block, block) }) { -+ t.Error("crypting after overflow should trigger a panic") -+ } -+ -+ // if we crypt less than a full block, we should be able to crypt the rest -+ // in a subsequent call without panicking -+ s, _ = NewUnauthenticatedCipher(make([]byte, KeySize), make([]byte, NonceSize)) -+ s.SetCounter(0xffffffff) -+ if panics(func() { s.XORKeyStream(block[:7], block[:7]) }) { -+ t.Error("crypting part of the last block should not trigger a panic") -+ } -+ if panics(func() { s.XORKeyStream(block[7:], block[7:]) }) { -+ t.Error("crypting part of the last block should not trigger a panic") -+ } -+ checkLastBlock(block) -+ // as before, a third call should trigger a panic because all keystream is spent -+ if !panics(func() { s.XORKeyStream(block[:1], block[:1]) }) { -+ t.Error("crypting after overflow should trigger a panic") -+ } -+} -+ -+func benchmarkChaCha20(b *testing.B, step, count int) { -+ tot := step * count -+ src := make([]byte, tot) -+ dst := make([]byte, tot) -+ key := make([]byte, KeySize) -+ nonce := make([]byte, NonceSize) -+ b.SetBytes(int64(tot)) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ c, _ := NewUnauthenticatedCipher(key, nonce) -+ for i := 0; i < tot; i += step { -+ c.XORKeyStream(dst[i:], src[i:i+step]) -+ } -+ } -+} -+ -+func BenchmarkChaCha20(b *testing.B) { -+ b.Run("64", func(b *testing.B) { -+ benchmarkChaCha20(b, 64, 1) -+ }) -+ b.Run("256", func(b *testing.B) { -+ benchmarkChaCha20(b, 256, 1) -+ }) -+ b.Run("10x25", func(b *testing.B) { -+ benchmarkChaCha20(b, 10, 25) -+ }) -+ b.Run("4096", func(b *testing.B) { -+ benchmarkChaCha20(b, 4096, 1) -+ }) -+ b.Run("100x40", func(b *testing.B) { -+ benchmarkChaCha20(b, 100, 40) -+ }) -+ b.Run("65536", func(b *testing.B) { -+ benchmarkChaCha20(b, 65536, 1) -+ }) -+ b.Run("1000x65", func(b *testing.B) { -+ benchmarkChaCha20(b, 1000, 65) -+ }) -+} -+ -+func TestHChaCha20(t *testing.T) { -+ // See draft-irtf-cfrg-xchacha-00, Section 2.2.1. -+ key := []byte{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} -+ nonce := []byte{0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, -+ 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27} -+ expected := []byte{0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, -+ 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, -+ 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, -+ 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, -+ } -+ result, err := HChaCha20(key[:], nonce[:]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if !bytes.Equal(expected, result) { -+ t.Errorf("want %x, got %x", expected, result) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/vectors_test.go b/ms_mod/golang.org/x/crypto/chacha20/vectors_test.go -new file mode 100644 -index 00000000000000..3d3bbcdc51d8a8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/vectors_test.go -@@ -0,0 +1,511 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20 -+ -+// Test vectors for ChaCha20 implementations. -+ -+type testCase struct { -+ nonce string -+ key string -+ input string -+ output string -+} -+ -+var testVectors = [...]testCase{ -+ { -+ // From libsodium/test/default/xchacha20.c -+ nonce: "c047548266b7c370d33566a2425cbf30d82d1eaf5294109e", -+ key: "9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232", -+ input: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ output: "a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc", -+ }, -+ { -+ // From draft-irtf-cfrg-xchacha-01 -+ nonce: "404142434445464748494a4b4c4d4e4f5051525354555658", -+ key: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", -+ input: "5468652064686f6c65202870726f6e6f756e6365642022646f6c65222920697320616c736f206b6e6f776e2061732074686520417369617469632077696c6420646f672c2072656420646f672c20616e642077686973746c696e6720646f672e2049742069732061626f7574207468652073697a65206f662061204765726d616e20736865706865726420627574206c6f6f6b73206d6f7265206c696b652061206c6f6e672d6c656767656420666f782e205468697320686967686c7920656c757369766520616e6420736b696c6c6564206a756d70657220697320636c6173736966696564207769746820776f6c7665732c20636f796f7465732c206a61636b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d69632066616d696c792043616e696461652e", -+ output: "4559abba4e48c16102e8bb2c05e6947f50a786de162f9b0b7e592a9b53d0d4e98d8d6410d540a1a6375b26d80dace4fab52384c731acbf16a5923c0c48d3575d4d0d2c673b666faa731061277701093a6bf7a158a8864292a41c48e3a9b4c0daece0f8d98d0d7e05b37a307bbb66333164ec9e1b24ea0d6c3ffddcec4f68e7443056193a03c810e11344ca06d8ed8a2bfb1e8d48cfa6bc0eb4e2464b748142407c9f431aee769960e15ba8b96890466ef2457599852385c661f752ce20f9da0c09ab6b19df74e76a95967446f8d0fd415e7bee2a12a114c20eb5292ae7a349ae577820d5520a1f3fb62a17ce6a7e68fa7c79111d8860920bc048ef43fe84486ccb87c25f0ae045f0cce1e7989a9aa220a28bdd4827e751a24a6d5c62d790a66393b93111c1a55dd7421a10184974c7c5", -+ }, -+ { -+ nonce: "1733d194b3a2b6063600fe3f", -+ key: "b6a3a89de64abf3aae9cf1a207c768101e80e472925d16ce8f02e761573dac82", -+ input: "", -+ output: "", -+ }, -+ { -+ nonce: "ddfa69041ecc3feeb077cf45", -+ key: "2be077349f80bf45faa1f427e81d90dbdc90a1d8d4212c1dacf2bd870000bfdf", -+ input: "23dbad0780", -+ output: "415a3e498d", -+ }, -+ { -+ nonce: "496b2a516daff98da5a23653", -+ key: "254c12e973a3d14fbbf7457964f0d5ee5d18c42913cf9a3c67a3944c532c2c7c", -+ input: "f518831fab69c054a6", -+ output: "cfe40f63f81391484b", -+ }, -+ { -+ nonce: "9e7a69ca17672f6b209285b7", -+ key: "205082fc0b41a45cd085527d9d1c0a16410b47152a743436faa74ae67ae60bca", -+ input: "805fad1d62951537aeed9859", -+ output: "47bd303f93c3ce04bce44710", -+ }, -+ { -+ nonce: "b33dedcd7f0a77359bdeae06", -+ key: "ef2d6344a720e4a58f2ac10f159ab76314e37d3316bf2fb857bc043127927c67", -+ input: "f4e8a7577affb841cf48392cf5df", -+ output: "f445c0fb7e3d5bfdab47090ddee6", -+ }, -+ { -+ nonce: "b1508a348092cc4ace14608d", -+ key: "a831bd347ef40828f9198b9d8396f54d48435831454aa734a274e10ddcc7d429", -+ input: "1179b71ec4dc34bd812f742b5a0b27", -+ output: "cc7f80f333c647d6e592e4f7ecc834", -+ }, -+ { -+ nonce: "034775c821c58891a6e88cac", -+ key: "ed793ce92b1689ce66836a117f65dcec981dc85b522f5dffbb3e1f172f3f7750", -+ input: "7bd94943d55392d0311c413ac755ce0347872ba3", -+ output: "c43665de15136af232675d9d5dbbeca77f3c542a", -+ }, -+ { -+ nonce: "cb55869aa56e9d6e5e70ad5d", -+ key: "b3d542358ffd7b1ff8ab3810ece814729356d0edbd63e66006d5e5e8a223a9ee", -+ input: "1505f669acc5ad9aaa0e993ba8c24e744d13655e1f", -+ output: "26cad1ccf4cf4c49b267ab7be10bc2ffa3ba66bc86", -+ }, -+ { -+ nonce: "a42c203f86fc63000ea16072", -+ key: "d6b18ae2473d3be8ca711267ffbc77b97644f6a2b4791d31d0910d180c6e1aec", -+ input: "20070523ddb4ebf0d5f20fd95aacf47fb269ebadda6879638a", -+ output: "5ce972624cb2b7e7c28f5b865ba08c887911b4f5e361830a4b", -+ }, -+ { -+ nonce: "ea7186cf2fdf728d8a535a8b", -+ key: "bba26ce4efb56ad06b96e2b02d0cdd549ad81588a9306c421e0f5b0175ae4b25", -+ input: "d10f8050c1186f92e26f351db36490d82ea677498562d8d4f487a0a4058adf", -+ output: "f30c11bc553b2baf6870760d735680897c9fee168f976b2a33ef395fdbd4fc", -+ }, -+ { -+ nonce: "3a98bed189a35a0fe1c726fa", -+ key: "a76d5c79dcaab18c9a3542a0272eea95c45382122f59bcaa10e8910371d941f6", -+ input: "e88dc380b7d45a4a762c34f310199587867516fac4a2634022b96a9f862e17714d17", -+ output: "aac98ba3821399e55a5eab5862f7f1bfc63637d700125878c2b17151f306c9aec80e", -+ }, -+ { -+ nonce: "b8f4f598731d183f2e57f45b", -+ key: "f78c6fa82b1ab48d5631e0e0598aad3dbad1e4b338fbf6759d7094dbf334dbc3", -+ input: "b0fcf0a731e2902787309697db2384e1cda07b60002c95355a4e261fb601f034b2b3", -+ output: "b6c8c40ddda029a70a21c25f724cc90c43f6edc407055683572a9f5e9690a1d571bb", -+ }, -+ { -+ nonce: "18ae8972507ebe7e7691817d", -+ key: "a0076c332ba22e4a462f87a8285e7ba43f5e64be91651c377a23dcd28095c592", -+ input: "cf9ec6fa3f0a67488adb5598a48ed916729a1e416d206f9675dfa9fd6585793f274f363bbca348b3", -+ output: "bb7ed8a199aa329dcd18736ce705804ffae8c3e2ba341ae907f94f4672d57175df25d28e16962fd6", -+ }, -+ { -+ nonce: "de8131fd263e198b99c7eb0b", -+ key: "2e4c1a78e255ab2743af4a8101ab0b0ae02ce69dd2032b47e818eedf935b858b", -+ input: "be9a8211d68642310724eda3dd02f63fcc03a101d9564b0ecee6f4ecececcb0099bb26aabee46b1a2c0416b4ac269e", -+ output: "3152f317cf3626e26d02cff9392619ea02e22115b6d43d6dd2e1177c6bb3cb71c4a90c3d13b63c43e03605ec98d9a1", -+ }, -+ { -+ nonce: "f62fb0273e6110a5d8228b21", -+ key: "3277fc62f46cf0ced55ef4a44f65962f6e952b9ff472b542869cb55b4f78e435", -+ input: "495343a257250f8970f791f493b89d10edba89806b88aaaeb3b5aefd078ba7b765746164bce653f5e6c096dd8499fb76d97d77", -+ output: "62c01f426581551b5b16e8b1a3a23c86bcdd189ab695dbea4bf811a14741e6ebbb0261ef8ae47778a6be7e0ef11697b891412c", -+ }, -+ { -+ nonce: "637ab99d4802f50f56dfb6f2", -+ key: "8f7a652b5d5767fe61d256aa979a1730f1fffcae98b68e9b5637fe1e0c45eab4", -+ input: "e37fbbd3fe37ce5a99d18e5dcb0dafe7adf8b596528708f7d310569ab44c251377f7363a390c653965e0cb8dd217464b3d8f79c1", -+ output: "b07d4c56fb83a49e8d9fc992e1230bb5086fecbd828cdbc7353f61b1a3cec0baf9c5bf67c9da06b49469a999ba3b37916ec125be", -+ }, -+ { -+ nonce: "38ecdfc1d303757d663c3e9a", -+ key: "e7d8148613049bdefab4482a44e7bdcb5edc5dad3ed8449117d6d97445db0b23", -+ input: "9efab614388a7d99102bcc901e3623d31fd9dd9d3c3338d086f69c13e7aa8653f9ce76e722e5a6a8cbbbee067a6cb9c59aa9b4b4c518bbed", -+ output: "829d9fe74b7a4b3aeb04580b41d38a156ffbebba5d49ad55d1b0370f25abcd41221304941ad8e0d5095e15fbd839295bf1e7a509a807c005", -+ }, -+ { -+ nonce: "1c52e2c7b4995479d76c94c7", -+ key: "74e7fc53bf534b9a3441615f1494c3a3727ca0a81123249399ecae435aeb6d21", -+ input: "03b5d7ab4bd8c9a4f47ec122cbeb595bd1a0d58de3bb3dcc66c4e288f29622d6863e846fdfb27a90740feb03a4761c6017250bc0f129cc65d19680ab9d6970", -+ output: "83db55d9eb441a909268311da67d432c732ad6bda0a0dae710d1bce040b91269deb558a68ced4aa5760ca0b9c5efc84e725f297bdbdadbc368bea4e20261c5", -+ }, -+ { -+ nonce: "a1f0411d78773b7ca5ee9169", -+ key: "393e211f141d26562c7cfc15c5ccfe21c58456a9060560266bc0dcdab010c8f2", -+ input: "2f4da518578a2a82c8c855155645838ca431cdf35d9f8562f256746150580ca1c74f79b3e9ae78224573da8b47a4b3cc63fbed8d4e831a6b4d796c124d87c78a66e5", -+ output: "6fc086ded3d1d5566577ccd9971e713c1126ec52d3894f09ab701116c7b5abda959cbb207f4468eb7b6a6b7e1b6d2bc6047f337499d63522f256ee751b91f84f70b6", -+ }, -+ { -+ nonce: "2c029f74b0da21a052228c64", -+ key: "b0e7aca1a10e7a56b913af52080ca3cb746d7ae039ca3b5c07acb285c0afb503", -+ input: "55739a1738b4a4028021b21549e2661b050e3d830ad9a56f57bfcaca3e0f72051b9ca92411840061083e5e45124d8425061ab26c632ac7852118411ac80026da946357c630f27225", -+ output: "8051bf98f8f2617e159ba205a9342ab700973dd045e09321805eed89e419f37f3211c5aa82666b9a097270babc26d3bfe0c990fe245ae982a31f23cfbf6156b5c8cfb77f340e2bf5", -+ }, -+ { -+ nonce: "a86bc1234ecdd19fcb4e22cb", -+ key: "4a4094b698f1b586ff1bfd10544ea81309e521ab64d74374f1b33109f2876e68", -+ input: "7ffd8d5970fdee613eeae531d1c673fd379d64b0b6bfedd010433b080b561038f7f266fa7e15d7d8e10d23f21b9d7724bb200b0f58b9250483e784f4a6555d09c234e8d1c549ebb76a8e", -+ output: "c173617e36ea20ce04c490803b2098bd4f1ff4b31fdca1c51c6475ade83892c5f12731652d5774631d55ae2938617a5e9462bb6083328a23a4fba52de50ca9075586f2efc22aae56e3a8", -+ }, -+ { -+ nonce: "296f5fd61962f7f39e3c039a", -+ key: "c417a0eb1a42e06917239e44118a85293a52c8d0a2c9b0a884cab20a451a01af", -+ input: "7a5766097562361cfaeac5b8a6175e1ceeeda30aec5e354df4302e7700ea48c505da9fdc57874da879480ecfea9c6c8904f330cbac5e27f296b33b667fea483348f031bef761d0b8e318a8132caa7a5943", -+ output: "5e9fbf427c4f0fcf44db3180ea47d923f52bee933a985543622eff70e2b3f5c673be8e05cd7acbcadd8593da454c60d5f19131e61730a73b9c0f87e3921ee5a591a086446b2a0fadd8a4bc7b49a8e83764", -+ }, -+ { -+ nonce: "6ee50ec741ec580e616fd9af", -+ key: "bbf22a177cd285904dc4a28cda48a18ab0880c29397418888147d518ce2c3f63", -+ input: "0777c02a2900052d9b79f38387d2c234108a2ad066cbf7df6ea6acc5a3f86b3d6156abb5b18ad4ecf79e171383a1897e64a95ecdbba6aa3f1c7c12fe31283629ff547cb113a826cb348a7c10507cc645fa2eb97b5f22e44d", -+ output: "368c90db3464ba488340b1960e9f75d2c3b5b392bdd5622ff70e85e6d00b1e6a996ba3978ce64f8f2b5a9a90576c8f32b908233e15d2f443cccc98af87745c93c8056603407a3fb37ce0c1f8ab6384cc37c69c98bfecf337", -+ }, -+ { -+ nonce: "79da06301d054827dc7cc172", -+ key: "e8b7cd6028e9cbceb97a9be13715d63099c1fba0bf387789a90577dd63175c3e", -+ input: "cf2dccbcfd781c030376f9019d841ca701cb54a1791f50f50bee0c2bf178182603a4712b5916eebd5001595c3f48283f1ba097ce2e7bf94f2b7fa957ce776e14a7a570093be2de386ececbd6525e72c5970c3e7d35974b8f0b831fbc", -+ output: "7c92b8c75e6eb8675229660cedcb10334965a7737cde7336512d9eff846c670d1fa8f8a427ea4f43e66be609466711fd241ccff7d3f049bda3a2394e5aa2108abc80e859611dbd3c7ba2d044a3ececa4980dd65e823dd110fea7a548", -+ }, -+ { -+ nonce: "eeb10ffc0ac64c4167bd4441", -+ key: "c6913210b6032b8248b59ad2fe3e8fc86a0536691fa6aa285878dfa01935a2da", -+ input: "e08a8949a1bfd6a8c1186b431b6ad59b106ae5552821db69b66dc03fbc4a2b970dcf9c7da4f5082572bc978f8ee27c554c8884b5a450b36d70453348cd6cac9b80c9900cf98a4088803f564bb1281d24507b2f61ba737c8145c71b50eb0f6dfc", -+ output: "73d043acf9dcd758c7299bd1fd1f4100d61ff77d339e279bfbe6f9233b0d9afa24992a9c1c7a19545d469fdfb369c201322f6fe8c633fcdcffef31032bfb41b9fb55506e301d049fd447d61f974a713debeaed886f486a98efd3d6c3f25fbb30", -+ }, -+ { -+ nonce: "570c03c2e1593b1e1ade7e60", -+ key: "b5c2bad18345a9569b478b621ea556308f8fbf693de0f12dd2489d4b79c3f57d", -+ input: "a0c302120111f00c99cff7d839cdf43207a7e2f73d5dd888daa00d84254db0e621a72493480420c9c61ce1cfc54188ff525bb7a0e6c1cd298f598973a1de9fd2d79a21401588775b0adbe261ba4e4f79a894d1bd5835b5924d09ba32ef03cb4bc0bd6eb4ee4274", -+ output: "bc714bd7d8399beedc238f7ddeb0b99d94ad6bf8bf54548a3e4b90a76aa5673c91db6482591e8ff9126e1412bce56d52a4c2d89f22c29858e24482f177abacef428d0ae1779f0ae0778c44f9f02fe474da93c35c615b5fad29eca697978891f426714441317f2b", -+ }, -+ { -+ nonce: "1fc84df4e7036ecf966796f4", -+ key: "f4127b0d89473f68b48f82c7a0c60f82eb3112c5d71667e493ef36406cb9af26", -+ input: "ebce290c03c7cb65d053918ba2da0256dc700b337b8c124c43d5da4746888ca78387feea1a3a72c5e249d3d93a1907977dd4009699a15be5da2ca89c60e971c8df5d4553b61b710d92d3453dea595a0e45ae1e093f02ea70608b7b32f9c6aadc661a052f9b14c03ea0117a3192", -+ output: "cbb8c4ec827a1123c1141327c594d4a8b0b4a74b0008115bb9ec4275db3a8e5529a4f145551af29c473764cbaa0794b2d1eb1066f32a07fd39f5f3fe51498c46fba5310ae7c3664571d6a851e673ded3badc25e426f9c6038724779aa6d2d8ec3f54865f7df612e25575635ab5", -+ }, -+ { -+ nonce: "1b463e8d60c3057eddafbb3b", -+ key: "c917b9f9f79bf89ac9bbec7d7beae5e755ab4a9bbef6ef90906d9ba11a9bf6b9", -+ input: "275c97de985aa265332065ccce437770b110737a77dea62137a5d6cb62e9cb8b504d34334a58a71aba153d9b86f21377467b2fafaf54829331bf2ce0009acb37842b7a4b5f152aab650a393153f1ed479abc21f7a6fe205b9852ff2f7f3a0e3bfe76ca9770efada4e29e06db0569a99d08648e", -+ output: "b225aa01d5c438d572deaea51ac12c0c694e0f9dc0ed2884a98e5e2943d52bb4692d7d8f12486de12d0559087e8c09e4f2d5b74e350838aa2bd36023032ccbcae56be75c6a17c59583d81a1fd60e305af5053ac89f753c9347f3040e48405232dc8428c49dcb3d9b899145f5b3bc955f34dbbe", -+ }, -+ { -+ nonce: "f5331f87bae3fee4931e8ccb", -+ key: "03491233e587027e8f98d6e95f406219b5c1215fe695c62ac900b246ba98da9f", -+ input: "ceda15cfffd53ccebe31b5886facd863f6166e02ec65f46f54148860a5c2702e34fd204d881af6055952690cd1ffa8ba4d0e297cc165d981b371932adb935398c987baff335108c5e77f2e5dd5e1ca9a017bc376cbdbe3c0f45e079c212e8986b438444e79cd37927c1479f45c9e75b0076cc9f8679011", -+ output: "a3f1c3f885583b999c85cd118e2ababfa5a2de0c8eb28aacc161b1efee89d8de36ddeb584174c0e92011b8d667cb64009049976082072e6262933dbf7b14839805e1face375b7cbb54f9828ba1ed8aa55634ec5d72b6351feff4d77a3a22b34203b02e096f5e5f9ae9ad6a9dd16c57ce6d94dcc8873d18", -+ }, -+ { -+ nonce: "e83c55efea20e1df3a7e049a", -+ key: "c179f4be8b4f555989f097bf1e6f315228e4410104dc26ff578f0ce1598a56a7", -+ input: "799bb2d634406753416b3a2b67513293a0b3496ef5b2d019758dedaaac2edd72502fc4a375b3f0d4237bc16b0e3d47e7ddc315c6aef3a23fcae2eb3a6083bc7ac4fd1b5bf0025cc1cb266b40234b77db762c747d3a7b27956cf3a4cf72320fb60c0d0713fa60b37a6cb5b21a599e79d0f06a5b7201aeb5d2", -+ output: "e84dfb3dbaac364085497aeabd197db852d3140c0c07f5f10e5c144c1fe26a50a9877649e88c6fe04283f4b7590a8d0d042ef577693f76f706e31c4979437590fe0ab03d89afb089d1be50ae173ea5458810372838eceac53bf4bac792735d8149e548efb432e236da92bf3168bbcf36f644c23efb478a4e", -+ }, -+ { -+ nonce: "a02481d9aa80cd78fc5cc53d", -+ key: "416e2802e3383ef16b4735f7fc4bc433978797d795459c4a13040806d8fd9912", -+ input: "b2d060bd173955f44ee01b8bfcf0a6fad017c3517e4e8c8da728379f6d54471c955615e2b1effe4ce3d0139df225223c361be1cac416ade10a749c5da324563696dae8272577e44e8588cd5306bff0bfbdb32af3ac7cbc78be24b51baf4d5e47cf8f1d6b0a63ed9359da45c3e7297b2314028848f5816feab885e2", -+ output: "ffa4aa66dd5d39694ae64696bfa96f771accef68f195456ad815751e25c47ed4f27b436f1b3e3fcaa3e0d04133b53559c100cd633ced3d4321fc56225c85d2443727bce40434455aa4c1f3e6768c0fe58ad88b3a928313d41a7629f1ce874d2c8bcf822ebdaebfd9d95a31bb62daab5385eb8eefe026e8cbf1ff7a", -+ }, -+ { -+ nonce: "0f6b105381fd11dff3b6d169", -+ key: "38b1360794e1cd55c173820fe668c2f7d52b366155b43cbbfcc9d344fdd3567d", -+ input: "4f0171d7309493a349530940feece3c6200693f9cff38924114d53f723d090fffa3c80731b5ca989d3e924d1fa14266632cb9ab879e1a36df22dc9f8d1dadea229db72fded0c42187c38b9fa263c20e5fb5b4aa80eb90e8616e36d9b8c613b371c402343823184ecad3532058a46cf9e7ea5a9ecad043ac3028cbcc3f36d32", -+ output: "88c773ff34b23e691e14018ba1b2bd48a4a6979b377eb0d68336ce6192dcd5177e6b4f1c4bea2df90af56b35fe2a1d6279d253c0194dcbca9bf136f92d69165b216e4c9d1ce6b3fbe40c71e32c3f4088de352732d0e2bad9c16fd0bb9bde3d6c30257ce063432d09f19da79d49aa7641124a6c9e3f09449e911edbae11a053", -+ }, -+ { -+ nonce: "bdff905e73f198a8889a9f26", -+ key: "5fe044529bbeadf9ac549f9e46004623eacd8267962c98ba6b5021c7e3f710ed", -+ input: "8f8d9e18d3212bd20b96d75c06d1a63622fd83d13f79d542e45996135368772ea81511302a0d87e246dd346314cfe019bae8a5c97f567f12d82aca98dfea397c6a47dd0c419f1c609d9c52dcfcbe7eee68b2635954206ed592b7081442ce9ce3187d10ccd41cc856fb924b011f817c676c9419f52a2938c7af5f76755a75eb065411", -+ output: "4e130c5df384b9c3c84aa38a744260735e93783da0337ade99f777e692c5ea276ac4cc65880b4ae9c3b96888760fdddb74bc2e2694bedf1ee6f14619c8015f951ba81b274b466e318d09defe80bdbed57bc213ac4631d2eb14c8e348181d60f6295ceee1e9231ae047830ef4778ff66146621b76974773b5d11c8e17a476450f46ef", -+ }, -+ { -+ nonce: "e8398e304ff1a49a96db11f5", -+ key: "19523b8388e5824b2c652d4bd76e8f7c63e84bfee5503a9d9b0988b868198d9f", -+ input: "30d2379dd3ceae612182576f9acf6de505ab5a9445fe1a86ae75c5c29429e11c50fd9ec657b29b173a3763b1e171b5a7da1803ba5d64fccb2d32cb7788be194dbca00c3c91774c4c4c8ede48c1027d7cc8b387101a4fe5e44a1d9693b2f627626025072806083aadbced91c9711a0171f52ffb8ed5596cf34130022398c8a1da99c7", -+ output: "b1e8da34ad0189038ee24673979b405ef73fdbdd6f376f800031d64005a4ebed51a37f2180571223848decbea6dd22b198ab9560d7edc047c5d69183dc69b5fca346911d25cb2a1a9f830dc6382ad0024e8c3eef3aa2d155abcfe43bff01956a5e20a862fbed5c5e8df8eed0601a120caac634b068314e221f175baa11ae29002bb9", -+ }, -+ { -+ nonce: "5acafea5b4c13a750966a4c5", -+ key: "5948bfabf69b8d826daaf7f7a28c2025adc0a4d78232dd2fc2b8fc2b4bd88983", -+ input: "d9404ccdcc8ef128a1b1ace4f9f1669d274ec82aa914cac34b83ac00b236478fd6167e96ec658850c6c139eb0f6fc0dd7191ba9a39828032008f7f37eb9a8df9d6cdd54240e600efe7fc49a674000c5030d825b2c5c96d0f19b8ecdbf4eeb86d3e569c5e3131abc7d6359dd4255284ccacf150d42e7a899536d51ee6db329654a4581c5ac6e419", -+ output: "c5534b5fb40b4834300e9577a9d87440c5272263d06e6aee84aa92cdf5d1b033145d336f26e5fe55c09a7e75753af93d0786dfc1cb435e86c67bd3ec8e766d0801b99e68691e2c3c3ffec539cf62e68285ea9027daa2716cd6f97e8eb7b9e266357a25eb2d4839a829508a6b7228f2832b3cd998f77597ae530430e6e4ecb53eb9efe456863a04", -+ }, -+ { -+ nonce: "4658aa126c4f608885950dc1", -+ key: "d6cc91149d552f60060c08d4bdfa0202f8f4d3ff174c14bf3c3fbf8875330808", -+ input: "231765f832927461f338aceb0f4cf51fd8469348c69c549c1dec7333d4aa4968c1ed58b65ab3fe3d0562600a2b076d56fd9ef91f589752e0455dd1d2e614cacfc0d757a11a4a2264bd38f23d3cca108632201b4f6c3b06477467726dde0c2f3aee01d66d788247663f1d0e66b044da9393ede27b9905b44115b067914961bdade85a2eca2844e1", -+ output: "1dd35f3f774f66d88cb7c2b23820ee078a093d0d85f86c4f103d869f93e2dbdd8a7cb8f101084fe1d7281a71754ec9aac5eb4fca8c365b24ed80e695caace1a8781a5a225938b50b8be96d0499752fdabd4f50d0b6ce396c6e2ca45308d1f2cc5a2a2361a8ca7a334e6ee62d466d74a1b0bf5b352f4ef6d8f8c589b733748bd3d7cda593243fab", -+ }, -+ { -+ nonce: "f0709d1c67a388a02b4dc24e", -+ key: "75974e4952a8070d4af28aaf5c825bc68067e0c5cebafb17b5711d65efd848f5", -+ input: "e46841f12d98aeb7710b9162d342895a971b0e3a499886bbb6aa74dc744a28d89a54542b628acdc2f693cb7c03f73fc3b74069bc3f2d000a145fb8a806cdc7d6fa971da09a33b92851cc3d1f6f5646d7fa2b1d564876feefeb63b6e66dba1c0b86ca345235bb822e0f93132346840d2a3d6eb1b541178ea51affc7b31f8da02732cc4e5bcb5d8683ae0a91c9", -+ output: "1dcbfd0bb2b905656c52bd7b1bcdad9b4d434ae9ac221a0d3a316115cdd4a463fa9b3444d2612a4e277d0dcd881fa6e80e59e5a54e35e1a14747aed31edf4ac24214f9d9c329ebe2157620b64efaded9976549bc4aa100d5c15be3f85f700f8a21dfe77590dfee2de9a23cc1ed1e44f32ebf68ca289b097bc13b42802dc7c75309c4afc25b5741839f7db3d5", -+ }, -+ { -+ nonce: "8b7b06236d6c275b606ccaae", -+ key: "8844d62973293a89efb4e332d4d5f32a1bc05e094cb605c87d8b4e8862708d79", -+ input: "e98e4a9550bdd29e4106f0cc8669dcc646a69438408e9a72c7cdb9b9d437b5f7a13fcb197629541c55bca1f8972a80cd1c1f591a0e24f977cdeb84763eab2648e42286e6473ea95e3a6a43b07a32b6a6cd80fe007ba0cf7f5ac7e651431f5e72690ec52a7134f9757daf0d8eff6b831a229db4ab8288f6bbf81e16fedebe621fd1737c8792cfd15fb3040f4f6a4cbc1e", -+ output: "5c69cf522c058790a3bc38979e172b60e71f7896d362d754edc1668d4f388b3fc0acdf40786d2f34886e107a142b1e724b9b9b171cb0e38fd78b35f8ac5269d74296c39c9f8628d848f57af9d8525a33f19021db2b9c64ba113171ebb3882075019ec7e77b51ce80b063ed41d48dad481d9536c030002a75d15c1c10ce0ec3ff17bc483f8416055a99b53035f4b6ea60", -+ }, -+ { -+ nonce: "5896072b85daf5bd0d45758a", -+ key: "a3eac94919880462a5cfaa9bdcad7038e182c605f3fff9f44b8e84a3c1ebc10a", -+ input: "ce0f0d900dd0d31749d08631ec59f216a1391f66a73bae81d3b0e2919a461bc9a14d6a01b827e3bcb55bbccf27c1ed574157e6becd5cf47181a73c9d3e865ab48a20551027e560e965876b0e1a256bfa5cb5179bf54bd8ec65e5570e374b853b37bf4b3ef1ec612d288ebc19275fa88da9419e012f957f9b6a7e375b3377db0eb3619c731aebfeb0930772b4020d3a3e90723e72", -+ output: "b06981b57fe184091ef9f8ccf522a5bcdb59bf9a68a3ddb817fdd999a6ecf81053a602141cf1b17017bae592b6b6e64756631a2b29a9e1b4f877c8b2ae30f71bc921e4f34b6f9cd8e587c57a30245f80e95005d0f18f5114400785140e6743da352d921fb4a74632a9c40115ad7706263ac9b41a11609fa0c42fc00f8d60931976162598df63ebad9496dd8943d25a03fa47475c", -+ }, -+ { -+ nonce: "b88a8e097be7d884415830bb", -+ key: "3cf9b5468d77b2c88f27c52c4c90a3d24f5dce06e859440c305ca30402dcea2f", -+ input: "eccfd66bdc691478f354b8423d6a3f20932a1f591d8e6cefa734975fb8ee6881b6dc92c0d1d5ed54fd1999efd7f11ac697a1f130587dd895eb498c9a8fc7d1714c385ec156ecae3bdea2a3462834245e724531d0fedda2b77693a53ed7354b758e875b23cfc83219a091fb2076e7a88cd77f779ed96f8d81ffa3fe5059303ac706086494b9f2982f4f88a0c6fadc3748625004db", -+ output: "925529047d4177b72bf50905ba77e47608815522c1829b24046e439d5451901257903a5409fb910373167e8b7f4fdfa543a477608ddfc11bbd1efc138366961463b9915b302a346b795dd593f6fcf4fa73529b6fe83079552aabbe99474a72806f59688d826675fa7f6649b9f5307e5028853c9821b8c4a1a0fc4bfdc7c8c78b25aeaba2b5821d17b36317381a3bd578917d2504", -+ }, -+ { -+ nonce: "4a6e2a2e8a486d9ab66c96f9", -+ key: "ff3b90583f17bec2b52861e253afb6b6eb8e2f093633cf38fb90df7f374be27a", -+ input: "f0c7139c69413869bca980d7f192b2bc3f57e34ca4f26164e1a54a234e84e1aa285cc02cfbaef3dfba2dbb52a555ec1f6ef0e89d0b2f0bd1846e65b74444b5f003a7308965e67bed558689be2668ca10ca368fac072e0e4535a031af23b3c37c561e185872b86c9bceddb5c1199e43fb5f735384766d33710460b541b52d3f5b6c108c08e76724bcac7ad2d866a8bbeeea92a3d867660d2e", -+ output: "d2c16c7a242b493038203daec65960de384c030eb698ef6a53c36eabb7556cbfa4770eaa8bc0a2b385ad97495eeb1c03ff4e6efcb804aefa81c177dc62700a9eefe6e8dd10cff5d43a2f47463cab5eb1ee260c3826cac9bfa070f1e0435541a89ebd224d13cc43f8fff12f38091c2b3f2102d5c20d8b1c3ae4f129364bbe9f9ce2147dcf0639668ddb90dffe6a50f939f53fa7ba358e913f", -+ }, -+ { -+ nonce: "98013e248c44840860e7319a", -+ key: "bc17e037902e1e9baa9d6715ee234af9fe6da80d4ca8eec3999719dd92fbef6e", -+ input: "7024974ebf3f66e25631c0699bcc057be0af06bc60d81a7131acaa620a998e15f385c4eaf51ff1e0a81ae5c6a7442d28a3cdc8aeb9701055e75d39ecac35f1e0ac9f9affb6f9197c0066bf39338a2286316e9d1bb7464398e411da1507c470d64f88d11d86d09e6958fa856583ace697f4ee4edc82618662cb3c5380cb4ce7f01c770aab3467d6367c409a83e447c36768a92fc78f9cbe5698c11e", -+ output: "ff56a3a6e3867588c753260b320c301ce80de8c406545fdd69025abc21ce7430cba6b4f4a08ad3d95dc09be50e67beeff20d1983a98b9cb544b91165f9a0a5b803a66c4e21bd3a10b463b7c1f565e66064f7019362290c77238d72b0ea1e264c0939d76799843439b9f09e220982eb1dc075d449412f838709428a6b8975db25163c58f40bf320514abf7a685150d37a98bac8b34ccb5245edb551", -+ }, -+ { -+ nonce: "6d864ed2d8259dc5f123f6fc", -+ key: "a0cc325fc5ca6741ee4349c0eca17f50c0df8fad2dfa66624153f0223e147480", -+ input: "8d79329cf647e966fde65a57fc959223c745801c55312046b791671773cca0af4cd48ead1f316eba0da44aa5d18025eced0c9ed97abaabb24570d89b5b00c179dca15dbae89c0b12bb9e67028e3ae4d6065041b76e508706bec36517a135554d8e6ef7cf3b613cbf894bec65d4dc4e8cb5ca8734ad397238e1e5f528fa11181a57dc71cc3d8c29f3aba45f746b1e8c7faace119c9ba23a05fffd9022c6c85260", -+ output: "60aea840869f7be6fcc5584b87f43d7ba91ed2d246a8f0a58e82c5153772a9561bdf08e31a0a974f8a057b04a238feb014403cd5ffe9cf231db292199198271f9793c9202387f0835a1e1dc24f85dd86cb34608923783fd38226244a2dd745071b27d49cbffebea80d9dacad1578c09852406aa15250de58d6d09cf50c3fcfff3313fac92c8dad5cb0a61ccc02c91cecee3f628e30c666698edecf81831e55ec", -+ }, -+ { -+ nonce: "4710b63001f90c812415684d", -+ key: "d07614e58d0098df9ee6df596691b30d4a4a1e6c5e1676fb85f1805135fb5973", -+ input: "85484293a843d2d80b72924b7972dfa97cbe5b8c6bcc096f4d5b38956eb3f13f47b02b0f759ea37014ecdecfb55f2707ef6d7e81fd4973c92b0043eac160aaf90a4f32b83067b708a08b48db7c5900d87e4f2f62b932cf0981de72b4feea50a5eb00e39429c374698cbe5b86cf3e1fc313a6156a1559f73c5bac146ceaaaf3ccf81917c3fdd0b639d57cf19ab5bc98295fff3c779242f8be486ba348bd757ba920ca6579be2156", -+ output: "bb1650260ef2e86d96d39170f355411b6561082dcc763df0e018fdea8f10e9dc48489fb7a075f7f84260aecc10abcfadbc6e1cd26924b25dedb1cc887ada49bb4e3e02006bdd39098ef404c1c320fb3b294ded3e82b3920c8798727badfb0d63853138c29cf1ebf1759423a1457b3d2c252acf0d1cde8165f01c0b2266297e688ff03756d1b06cb79a2cc3ba649d161b8d9ef1f8fb792bd823c4eabb7fb799393f4106ab324d98", -+ }, -+ { -+ nonce: "be0c024290af62adcd539e02", -+ key: "9520adab77c41e60a123c93b1adede1e5523613358485b281467fdd3c3bcf4e0", -+ input: "a2fc6e1b5281a4e0330eecd1ab4c41670570423173255979953142b78733b2910fa5540e8294208df6ae4f18672d5ac65acf851bcd394e1932db13c81b21e6f165e5538aff862e46126c650bbe055e54b31c78f2f0221d2631d66ef6d3f4c5ae25eada043b74d8770e2c29799c0954d8ccbd17766b79e6e94e88f478db3566a20cb890846917591a07738328d5c05f7ed4695a82607660f1239661faa9af0368aeb89726f13c2aaecf0deaf7", -+ output: "d8fe402a641c388522842385de98be60f87d922c318215947d4b7562d4ca1e2dbc7ee86494e65fb0bfddfdebdb2ae6469312f95b32c722b2720d64bb8d7cc3dd82f9055b1d89f05b77984f91f94ba4ac79c5129cd7c91cc751b0defc3f2799518e372d27aa683f1e7bbd4f55414c48fe8a3a37ac1f179a1a329cda775aec0d31d75a5a38addb1de67c06bddbedf4c8d87abc18c9f9dd072d457ea29ad4dfb109ce7e99a4a82fbe330b0afbb5", -+ }, -+ { -+ nonce: "8f1c02a8c4027a6693b6687a", -+ key: "c801e4ec475a80faca2f576d0c781c9ce5457564114cefd7461edc914e692aba", -+ input: "480387bc6d2bbc9e4ced2448d9ec39a4f27abe8cfb46752d773552ad7808a794058962b49e005fef4e403e6a391d1d3f59025eeb5fb8fbbe920f5361862c205d430eac613cd66108f2f2f0bd4d95a8f6ca7bd1f917eaeb388be87d8b7084a2eb98c575034578edf1b3dafff051a59313873a7be78908599e7e1c442d883d3fd3d26787eb7467eed3a3fb2d40046a4460d5d14215565606bcf8b6270af8500e3504d6d27dacf45bace32214472d525fdc", -+ output: "ab81a9c28358dfe12e35a21e96f5f4190afb59214f3cf310c092ab273c63cd73a783d080c7d4db2faccd70d1180b954cd700c0a56b086691e2c2cd735c88e765e2266cd9ebe1830d63df4b34e2611a8abeeca9c8c4fac71135dafb1cb3569540ed1362ddeb744ed62f6fd21de87b836ec2980f165c02506e0c316ae3cf3d18a862954d9781f726ecc1723af4a730ccc6d6de82553450a52499acb58fb2008969401c45b2f20e12b58f308db1d199b4ff", -+ }, -+ { -+ nonce: "7c684e41c269fcc6d312cad3", -+ key: "ca1cb501af5584bc4248903f52b4426064d14dcdf0f383da72b904ff0edd72f9", -+ input: "b274e61059f3215173ae226e30a92ee4b4f8a3da95f2e768e3fac2e54ddac92c200c525f190403a6ef9d13c0661c6a7e52ed14c73b821c9680f1f29711f28a6f3163cf762742ed9474dbea51ff94503a5a404adbbdfbf4c6041e57cb14ea90945dc6cb095a52a1c57c69c5f62ac1a91cd8784b925666335bbfee331820b5f7470bc566f8bbb303366aafe75d77c4df5de2649ed55b2e5e514c3cb9f632b567594a0cf02ec6089a950dbe00554ee4dfb9", -+ output: "a0969730d48ee881792a3927b2f5d279aba9f2ed01e6b31b92d0e1fb8ba7f35a236d838e0ce5f8654957167de864f324c870864b4e7450a6050cd4950aa35e5a1a34a595e88dd6f6396300aff285de369691b6e0e894106dc5b31525e4539c1e56df3ceedbbab1e85da8c0914e816270a4bae3af294b04a3ea6e9ef7e2aab4da5f5370df2706b5e3f000d88179ac756deaa652a1cc85e80ad9622f1bf91a2776262eb7289846d44f7f8192e763cb37aa", -+ }, -+ { -+ nonce: "1d5c31dd98da35230fdaa0e0", -+ key: "d6c71964420f340db8f4f27a42cf3635fbc6682f5f859dac90d4c407b1b11197", -+ input: "ee849039c6cd972dc943d2a4468844d130c0150276f4e0889047e2300c3ecc6792c4527bfe9437dad877eb986e6b1aa9b867d1798c9d314243f0a87ec9ee5b601c2554876c87cbf50df3334a077c4152f8b8fef4a2d301ddbfa90c887ece757c3eb6c4fc1e0212d6b5a8bb038acaec28cba064c9b34f5364cb7f0fc2ac4ef2c7ddde0f5ba17014459eaa78f08a46a01882ebf7c6e409dadda250bb899dc8b3b70e160bbcb4412a9963b174d0fc6bc16383a46ffaacb6e0", -+ output: "3e272ded9c0a5cebe7cf17ac03f69eb20f62996e047501b6cc3c8691ddb2780ea72c21a81888bfea96e4373a412c55ca95648390de740102d661143043baec3976230e024477d134b8504a223c36a215b34164c9e9e1fa99a49fdc56f2f04ea525a6b82997d9bbc95c4b5baeab4dec50061efb7c1a757887acb8b47b142e0a2e61885a2c14c4642d83d718a0546b90699adc545a48129603862a1c89d8e665cde54b3ba487754db6d6f5acf6a4b95693cc569577a2dc48", -+ }, -+ { -+ nonce: "7c4fb4ebddc714af7acd4345", -+ key: "7719e70c860e7999dcd61065e78a96379afb17295ff29e0185d082d243d02861", -+ input: "0992396a6f29b861dd0bc256e1d1b7dce88435733506a6aa20c62e43afa542d1c46e28b2e6d8e2eacb7c08db05e356fe404684b0e3a9849596db82eb788aa09258c28eb19e9838f757425b4edef12deeca56e30cf030272e325d4246d6e083219b2f965124963ca91f066d47bf5a8282a011a78b0155aa70038259a4a59135f241fd2f88c908b9f4eef7b7df0f3a1c16a52c009b522f89dabd52601bbf6e3ce68732e1a6d444469480f06da218786cf6c9666362e7a7f7be12", -+ output: "545c05a84b5a4fffd1dd623c8f2b11443818560bdb0c26dadd3b694d4790d294b99059f4127b7cca122c4000954d745af96094ff4623f60db33e994bb6903263d775f48d7047427b3a498c2ecde65bd37bcb8ee7e240a1e08c884c0079cab518f4e1c38ba5ea547f4da83b7c6036e4259bee91c42e8fae895df07781cc166f1d50e1550a88ee0244bb2950070714dd80a891aa8a9f0580a67a35cb44609b82a5cc7235f16deea2c4f3667f2c2b33e8eeef944e1abdc25e48fa", -+ }, -+ { -+ nonce: "9071cb35869a2e21e43c42bc", -+ key: "dece19faf2e86a57ab5d05585d35b3911a50d269c223637385136c2657454f13", -+ input: "3b9efcbbb607fad5e9f1263dad014cc5c2617d439fcd980408f4f9a93acb1a33d1c3a22f38c037e4603dfbbfb5571bc08c4a1958cbbf510e3e4dd19007fe15fad7808369149a9c4db7ca0496f7a600a6f2454ee1cffd5a68d45c270e4b53ac9b77f33a1ffbb1804244f57d2b05b8036fe2cda9efead3d4eff074ea5c07128e0b354a4a11ffa179163933bc6bd10d200804cc93b64575746e94e975f990bddcc8a4335e99e2459fbe9bc0e004ffcd6cac52f48ef55cc0637a75c1dc", -+ output: "631ba7301e33236da2477506ea98d3b732447389e849b68e1f09bd5fd814f40dc3247a1012fa654f08e3dda0c104ee2dff12ecf5cb018644de50d70dfb6c8cc1f5f552e5f1e50466bbb538ad6b98fd37f33fe615c326efc9cc97899b829b007f91569fa9b28ce0076c53daedf9cc0f838e22cf1125b86a6a2c2eb4a45dadea45ad00fb4f054e7d6b09c13ab1dd5328debfbf4f1b70af2b8a5b1d02df8a87d7661473e0c180ba4c815f14db87c5bdc15f11a29d8e0ce3d747d5dcd4", -+ }, -+ { -+ nonce: "ac41c9cc025ba4dbd67a0dab", -+ key: "5207759b0a0927a6f0957c963f2cfff87eb9be69c1990ba383dcdd0aaf9b3f44", -+ input: "f28a71efd95e963e5e0bc0fcf04d8768ce93cb55dc73c32e6496022e214596314b7f843f5c7b136a371c2776a0bfbdd534dccbe7f55e9d3d3b5e938f2d7e74393e4caf6c38fa4b05c948e31dc6a9126817fa3d7892c478f75ab9f6ab85c0e12091bd06e89c7d3ca8d9dcdd4c21fead3d769a253919c2c72dd068474ea322b7e71cafa31684e05a63e179e6432fb70661792cc626a5060cec9e506b35d9286f15dc53cc220b1826314eec337dd8e7af688e5950b2316c30516620569ea65aab", -+ output: "1bcea54b1bf4e6e17f87e0d16388abe49b988b9c785b31f67f49f2ca4011ecd2ad5283d52ef707dd3b803e73a17663b5bfa9027710e045a0da4237f77a725cf92792b178575456de731b2971718937dd0e9ea12558c3fa06e80bbf769e9799f7470db5b91476d6175f1a6d8e974fd505854c1230b252bb892a318e6d0c24dcc9ecb4861769cd746abab58805bc41c6086a6d22b951fba57b00c5b78f6dcb2831715b9d4d788b11c06086f1d6e6279cd130bc752218d7836abc77d255a9e7a1", -+ }, -+ { -+ nonce: "587c7e98949a83cc602e9530", -+ key: "6f284ae396d9dc4a12871697e8dd820ae54942010b81825ee845a4b4b0ad7995", -+ input: "c1d1ede73bd89b7c3d4ea43b7d49c065a99f789c57452670d1f92f04f2e26f4f5325c825f545016c854f2db2b3448f3dc00afe37c547d0740223515de57fd7a0861b00acfb39931dc9b1681035d69702183e4b9c6559fb8196acbf80b45e8cc5348b638c6d12cea11f6ef3cc370073c5467d0e077d2fb75e6bf89cea9e93e5cf9612862219ca743ef1696783140d833cd2147d8821a33310e3a49360cb26e393b3fee6dba08fcda38d1b7e2310ec1f715e3d8fa0c6b5e291eea07c25afd5c82759a834a89cc5", -+ output: "11a8493cdc495c179f0d29c2b4672997205a9080f596ee3c80d79b55162b1c875ac18eb94bf2a9e05b08024f524a1e9665912394a330c593d23260e6bdf87620c10a48f678693196fb744c49054182fba667c601e7b7ebf0f068e8d69ba004b804fda616a4a0d5350e1a3bd424b8266462be282308219c578569aefc1ccd09ecdf5da283356c9e524e14e69d25b0e19643dab26f54373a7272b43755c3f1ddaee6c5fb9e8e093110c41697e95f73a68c75454e050239197c9fbd8cec76698bd11894ebf6e2b2", -+ }, -+ { -+ nonce: "5a021f8500c8f3e63075ae85", -+ key: "47be0d2d65e405dab2b3f6429ee726708066449e76f91d69a23db2f7fa2134bb", -+ input: "37b2dc4b6a5203d3a753d2aeffcdaed5a7c1741ed04d755dd6325902128f63b6981f93c8cc540f678987f0ddb13aae6965abb975a565f0769528e2bc8c6c19d66b8934f2a39f1234f5a5e16f8f0e47789cd3042ca24d7e1d4ddb9f69d6a96e4fd648673a3a7e988a0730229512382caaded327b6bbbbd00a35df681aca21b186bc7ac3356d50889bbf891839a22bb85db4c00bfa43717b26699c485892eb5e16d1034b08d3afa61f3b5f798af502bba33d7281f2f1942b18fb733ca983244e57963615a43b64184f00a5e220", -+ output: "b68c7a2a1c8d8c8a03fc33495199c432726b9a1500bc5b0f8034ce32c3e3a78c42c1078e087665bd93c72a41df6bfa4e5beb63e3d3226aeeba686128229a584fab0c8c074a65cef417ad06ab1565675a41cf06bb0fb38f51204eccccb75edd724cdd16b1d65a272f939c01508f0385ca55ac68a0e145806317cc12e6848b1124943a6b2d99a8c92083fc5f31ab2e7354db3f8f2d783dbf1cfec9c54f8bfcb93d6f28ef66f18f19b0fab8836458e9b09bee742ba936cb2b747dd9dcf97ca7f6c82bf0af6f1b433592d65143fe", -+ }, -+ { -+ nonce: "7fd9bfae2d4483f51f2fab15", -+ key: "9bcfd1d3e68731e457a77150b4832a416f71273f88c4fd17ed771f2756b04b6c", -+ input: "68c2c5612912b5f994172720130dff092ee85a2c1395111efa64d5a281ca864d3db9600e685854d81c6de7e8747b92fb7c4c2efa829d3d4c0c9fc9d689e2e5c84c9eae8ba4ab536fb6c7523124b9e9f2997f0b36e05fb16163d6952eee066dd22fb7585925ffded0204cc76818bcead0d1f8095ca2cf9cd1ddcd0361b9c9451940e14332dac4e870e8b2af57f8c55996447e2a8c9d548255fe3ed6c08aedaf05bb599743ecb0df8655152bbb162a52e3f21bea51cb8bf29f6df8525eb1aa9f2dd73cd3d99f4cca31f90c05316a146aab2b5b", -+ output: "d0ae327fa3c4d6270a2750b1125145bdeef8ab5d0a11662c25372e56f368c82c6f5fc99115a06a5968f22ffe1e4c3034c231614dd6304e6853090c5940b4d1f7905ef4588356d16d903199186167fec57e3d5ce72c900fe1330a389200ed61eec0bdc3672554f1588ec342961bf4be874139b95df66431178d1d10b178e11fcbd26963ff589d5d5faf301b7774a56bbfa836112a6ea9c3026ebdd051085f9131132c2700674bef6e6c2c5b96aace94eb2ba6c0e0aef0eefa88995e742ca51ac50af83683b801b7c2c5af4880e2b344cc5564", -+ }, -+ { -+ nonce: "b873e9f9a7a68524e6dea72e", -+ key: "11efed96267ff58c3ca8e3b6c634f49e48ea07464d7ee8ac7574d8a058949c3a", -+ input: "fed3d1efa309c8b50cb9da02b95167f3b77c76e0f213490a404f049270a9c105158160357b7922e6be78bc014053360534add61c2052265d9d1985022af6c2327cf2d565e9cef25a13202577948c01edc22337dc4c45defe6adbfb36385b2766e4fa7e9059b23754b1bad52e42fce76c87782918c5911f57a9394a565620d4b2d46716aa6b2ba73e9c4001298c77bfdca6e9f7df8c20807fa71278bd11d6c318ed323584978ad345c9d383b9186db3bd9cec6d128f43ff89998f315dd07fa56e2230c89d803c1c000a1b749107a3159a54398dac37487d9a", -+ output: "6a95fba06be8147a269599bccda0ce8f5c693398a83738512e972808ec2f25bc72402d4bcd1bc808cc7772b6e863b0e49d1d70c58fcf4fcaa442215eeb3a4648ade085177b4e7a0b0e2198f0acf5465c97bd63f93781db3f0b9a0a184c3e06a76c4793a13923f83b2242b62511c2edff00b5304584cbe317c538de23785d2504fae8faabee81c5315298186ce3dcbf63370d1ccd9efec718cbc90b3d2e0b0b6aefb3a9b31e4311f8f518be22fdc2b0f00e79a283701c53f6936dd63734ecb24480d5365d1a81392498faf9a1ddee577007acc5f8c87895be", -+ }, -+ { -+ nonce: "444cbde3315ab7a30f0192fe", -+ key: "8bab05ddd17cac05203711b806475253a1ee0c8ee723eb520b73851cd51439b3", -+ input: "d776bee5625d29a2ebf6fec4df94d2b9ac62e8e7c56704fd38a87ee932b787cbc555621535e76ea30183cb0ee30604f485b541f45feb8c01b9750d37fded5cdffbbc34fb90fdc9c7c7ddf949a1d50b796f1ea5db437238c7fb83c4b22c9e491f75b33d84746f1cd10bfda56851b8514ff0ded0adfd5092a66a85202d06bd967485d06a2c56011110da74bf40b6e59f61b0273164744da02ce2b285d5c3f03aee79eea4d4503e517177692ed3bb035071d77fc1b95c97a4d6cc0d41462ae4a357edf478d457c4805fa586515614697e647e19271091d5734d90", -+ output: "60e9b2dd15da511770162345251edfb15cea929fb79285a42f6c616dfde6befc77f252e653b2d7902a403032fc4ce4934620931a2ec952a8d0f14bf1c0b65cc287b23c2300999ed993446eb416749bf0c9c7dfe60181903e5d78a92d85e7a46b5e1f824c6004d851810b0875ec7b4083e7d861aabdd251b255b3f1fd1ee64619a17d97fde45c5704ab1ef28242d607d9501709a3ac28ee7d91a3aac00cd7f27eb9e7feaf7279962b9d3468bb4367e8e725ecf168a2e1af0b0dc5ca3f5a205b8a7a2aae6534edd224efa2cf1a9cd113b372577decaaf83c1afd", -+ }, -+ { -+ nonce: "50fdabcd995b0dd1850a169e", -+ key: "e9a431828b3cf3891bb1960f9dae3c85334a62f6ee2395ee5378bb28f8c68a68", -+ input: "4f57848ff5398e61bcafd4d4609bcd616ef109c0f5aa826c84f0e5055d475c6a3a90f978a38d0bd773df153179465ab6402b2c03a4bf43de1f7516eb8626d057ae1ab455316dd87f7636b15762a9e46a332645648b707b139e609b377165207bb501b8bccfa05f1bf0084631c648279afdf51c26798899777812de520f6a6f0d3c7f3ef866982f5d57f9c8d81c9a4eabb036651e8055a43c23a7f558b893dd66d8534bf8d179d8aa7d9e8987cfdaaa7b5a9381ba9c79d5c1161b1bdbd30defdd304ee07f19b7ba829a0d5b40a04b42edd6407b68399caac69069", -+ output: "e096cc68956ed16d2dea1154a259e01647913eeea488be0b54bd1816c781a35e161772ae1f7a26b82e864ade297a51cc9be518641b2e5f195b557ec6fc183e4e5c1fc01d84fe6ca75e5b073af8339427569b1b8ee7fcff0ffa5e7e6237987c40deec0abf091c06a3b28469c8f955fc72e4f3727557f78e8606123e0639dff782e954d55e236448f4223ff6301accda9f8fa6cd43a8d6381e5dde61851a5aec0f23aeca7262659bc793ce71fa7992f80e44611ae080b7d36066e5c75c30851306f0af514591d4d5034ecdf0d6c704bfdf85473f86141c9eb59377", -+ }, -+ { -+ nonce: "3f32de67c92a44a0d9b1779d", -+ key: "d4338dcad949438381d5685e0ec3a79938607fdc638b7e69ce2e4c28fa3b3eee", -+ input: "046a61c0f09dcbf3e3af52fab8bbcded365092fad817b66ed8ca6603b649780ed812af0150adbc8b988c43a6ada564a70df677661aff7b9f380d62977d8180d2506c63637c0585dcef6fe3f7a2cf3bbb7b3d0df7769f04bf0f2e3af9439ab7615c304b32055aea0fc060890beb34fa9f90084814b6ed7363b400dfc52ee87925c5b4a14a98e3b50c7f65adc48c89ddd6414626c5e0bdefabab85c4a0e012243e682d4931be413af62fd7123ab7e7774fcae7e423bf1d3a31d036195437e9ea8f38aa40182daa9aacf3c9f3d90cc0050977c6065c9a46bcca6ba745", -+ output: "cd5a6a263e3ee50dda0e34c614b94c3ec1b14b99a2f4095a6b5715fdfc3449fcdf8a09d1ae02d4c52e5e638f1ee87a4a629f99f15a23dd06718792f24285f5a415e40f698752c697ee81f2f9248da1506ce04a7f489f8e2b02e6834671a2da79acc1cdfb78ea01822d09a1c4a87ffa44e56c4f85f97507044cf946ccb6a2e06e2917bac013f608d75ee78fa422a5efc9c569226bf7068d4705fde3a9fad2030256db0acf9a1d12666e0acf9f5346ad62e5af4c01a008d67ab1224b3e98278d073116ff966cdc779fb3aff985ec9411a3eefa042d71dd4ae5b15d5e", -+ }, -+ { -+ nonce: "5a3d6aa35fa04717b40e4405", -+ key: "e61e702d1a5a3d14abb967bbcc8cc8ab8fadba208be40765391b1edb801d529e", -+ input: "af516216f74a6344cbe458cbba820f7e25c0b10aa84b790da2ee6317e059171076d7246c2878be83fc00c200d546c007f849e4c163d52c7b0da31beff4abff481be3266b92e668cf4dd1c84d9d7b3e5191dcd6ddb51d17d337621046e83e9ac035fccfb239648bc3c6fd340fbb50707e5a33b3ef439d292192d0e4bc727690c61450e5a28789e5ea50e746bc66d039493e080fb70e9ae06d89004cb71de8178941c422f1e9862492fc9149a4864ff52b1277b9f5a63c2f16e9adb5263cf65a034a62ebb0f1a385d2681c87a35f1c45670b4edef1c68fe9544fcf411d95", -+ output: "b22ffd8f0e549bd3e0206d7f01ff222f92d39b41cf995a331d5ef0cf5c24bcc3ddb36e64d351b5755400246fe4989b5f912e18daa46cdd33e52dafbd2872f16e94220b56315d72c1dbb1525fd34831d7202970c11711ff36de3fc479407c34fef0aea86e172f9beb0f393194355b9dd59625639f4a6bf72ba571c229f2fb053c1114e82793deb2dfe8232f1a327949689d2fb2820662dcd2a39a2546c7df12b3ff7e87e58c74badf568cddebd3c558f0f7874c834c4b8aa988653f138ec79620f5e3ed737690928a30f981dca9f2920ac7307607063b40f87c204de47c", -+ }, -+ { -+ nonce: "22e02bb9c757121e1ec0d70a", -+ key: "9cbb1dca0495dbaa5ca9b8775eeb0dc5b80fbc2dc24b659e5a92d89466fb9cfe", -+ input: "a3d70bdb509f10bb28a8caab96db61652467cf4d8e608ee365699d6148d4e84d5d93bdabe29aa4f0bc8ee155f0b1fb73293c5293929eaacdd070e770c7cccfb2de120b0c3811abeeddaf77b7214a375ca67d618a5d169bb274a477421d71a651cfb9370bcf7e0d38f913754c11002089cf6cd6a8de1c8a937fb216591d57b37efdf3797f280773950f7eddeb9c3385c8315ff5ff581c64610a86ada7ff6a1657e262df94892dff9fdfb6e958d101f4c26296470c138dc4e1ca4bb565b3ff877a7f78b3d11d64b7c24e27ba6f6b06f6e368f5ac218cd5d11b815ab0987678eb", -+ output: "646314264896a6e25601e536f6e783d465b2ead1e0be4422bc9cc8eacabae4a749ad533eb28091be8397328dcfb34c92006bbda930ab070ed7b806095bb1c8f476350e7b08ffbd4d7d6055c8defaa8deff9d54f5215c2d7db27ce09e08f5d87a859145ea3126e2a01882921c3fddef3985bd451bca44063258390aec8ec725b07d064314fe43a9c83e9287b47616dfefbf539b82da209aa08a6d3176b7e3b4be4a17d44e581280a684e4a64414649bfcea82b541729f8178b580e8b972a89f5b8c4f9b68205e9396d8ae5e81873b61da074080fd44c52d50fb0880ee9c35da", -+ }, -+ { -+ nonce: "27190905ba751c66ad3dc200", -+ key: "9d49002edb63dcaffb2ec6c3197a15b4138bce84796232859d1ee72ee4218731", -+ input: "f48b5ae62f9968baa9ba0754276cd8e9dcfa8a88e4571856d483ee857b1e7bc98b4732e81f1b4421a3bf05ab9020d56c573474b2a2ac4a2daf0a7e0c3a692a097e746d12507ba6c47bec1d91d4c7cfc8993c6700c65a0e5f11b1ccd07a04eac41f59b15b085c1e2a38b7d3be9eb7d08984782753ae23acdafbd01ae0065ab9c6d2a2d157c1fc9c49c2444f2e5f9b0f0bbfb055cc04e29b2658b85d414b448a5b62d32af9a1e115d3d396387d4bb97ba656a9202f868b32353cc05f15ae46cbe983d47b78ba73d2578a94d149e2c64a48d0c1a04fc68baf34c24b641ea0b7a800", -+ output: "b9af1016275eaff9905356292944168c3fe5fdffd9e4494eb33d539b34546680936c664420769204e91ead32c2bb33a8b4868b563174d1a46108b9dfe6d9ac6cc1e975f9662c8473b14950cbc9bc2c08de19d5d0653bb460bea37b4c20a9ab118a9550bfeb1b4892a3ff774e8efe3656adcdf48239f96e844d242525ee9f9559f6a469e920dcb3eaa283a0f31f5dfac3c4fac7befa586ac31bd17f8406f5c4379ba8c3e03a6992a1915afa526d5ed8cc7d5a2605423ece9f4a44f0c41d6dc35a5d2085916ca8cabd85ac257421eb78d73451f69aaedeb4ec57840231436654ce", -+ }, -+ { -+ nonce: "7c996d5d8739629d36de4257", -+ key: "eaa5b2578bd6bdc5c6b0c79960a9ae26f1755cba6bcf04a9de315068990e0f0a", -+ input: "b39101601efa2ecdf41878b0fd920a3005ce709e4ec2970abb76e32c232ea21069f81b246eda75aace7555ce8ae203455d3723e684bd671389300e353eec0d2f499d10654fafda2e7a69bfca7198eb172249167ca8864b5d5f58d28723090ec86e251a1bac0346d52fd81f06e0c05429e0b2b895588290b7d00878a4da3378eb6c7e61487de2b318fedf68fa7ad7c88ee746827c1f60d98c7716f3f9695c5ffd4670f71a0fa78a1fb554ba482c5de83feaed7c65fc71acc9f541342eb8f7622b12bb2cfa222fa2ddd8b3ed210ce442275afa3132c8a0e17dd504ecbc92525c118952be", -+ output: "50eb5b21c179a03b9a822f0075906a3ce4acc32486139f92635c7d834f69071d5a6dc0e15ed06a5cee37147071d59641d140a82ad5815b954e7f28e080c3dbbeaf13943d7b7c66d49d51ba1132eeadd4cb7a7e7d726d08d95f1578d55519f267f753f3e16ff39504a87b2286d8bfba0fe6bc28887b466bf276453a82cdd0abbbbf08db0e1c26c317d50ad9b8dc09cd621bc566d362024e8404739df6468869d2125c58b25d70e392f5e75924c4341be81c263915bb514ad436fb24c2c67450e84f6d1b72d1a02a3310c07a7814d930264fdbbf5ddca7067e18e8a44faa87169b7f2e35", -+ }, -+ { -+ nonce: "07a7bc75f4d1f6897a656f2a", -+ key: "cc429f94483c5d2b73e40bfeaa92ac17ddd9c9bd26dff97408754826a2417b7c", -+ input: "0a42f63b975ad0e12a1e32615813dfd6f79e53ce011e2a2f0534dd054689f8df73a8326fecfd517ff7fe530d78081af66c3a8c7c189eb9d9efed1e5577b5512d42ef1fe273f670ce380c64bc62e217a7e410a8ed89998344e29301e4e053a3a3cf7e71587fd056a6bd976f16e157476a06997dfaaff32172dd84190570621f2221420c0a0ea607ea756e9792c8c0e7157c95b89c9490e20b750ee85e4c27c9b8f409e848ec90afcad33342010bb9808358afbcb3d9b094127c38c243a204e76899677079758e7cbada9a5c18363449eebc07bab516a16372722403a046df85c7dd2ffc804c54d38aab", -+ output: "87a47bcaa1c1eb8e55151011c4f39af4b9e108a55a7124cdcf66d0dee727306e6971f783b038bd6b215f530cdbb53e17975742ec304fdb3792a88b674504396978c6a5e4a9c87a7c3ca430d61165c1a3f6162eeaf38c93e18b6ccb6a595ad428cdc98efef8f84463eed757a72ffd827b71c0579fcc1f4baa11812be2bc5a2a95df8e41d04b33343df09ce628c367d1f88488f7a2787f013c8e76f0b9257cee777ec4adc6df8c5790e41ea02da85142b777a0d4e7c7157a48118046935f8888b5352d1750bf00b92843027a349cf5685e8a2a2efde16dcf5e1c1ed8c779bb38cabfb42ec4dd87d58273", -+ }, -+ { -+ nonce: "f7a40350de8cbd4025fb35fe", -+ key: "d9496e57dfe9840ea327f209e09d7c43dec86ac42b2d6a1a8476ab42b6fb5342", -+ input: "abeff48fa082dfe78cac33636c421991b0d94c3bc9e5bd6d22763601a55201fa47b09ce60cb959ba107020213c28ae31d54923d1e74ab1d9ddc2762b2d23d8c6961d81068230884a39682fa4b30676ffec19319362c075df0b879a0f083a67b23597bf95c4bb997fae4736479cb8a9c00520ba2f6e5962d54c313c576180d17779ff239ad60f1f1373627770d50a1c49718b2b2e536846299e052f8c1a5d3079e91cb1b8eac4661daac32d73b3b99e2051f8f694a61d1e9d3935f802921a4d979b6ade453cf30d73a4a498a6a2c5395c60fcf271d50b4967ac12b0d7bf818c2679d552e9b3b963f9f789", -+ output: "a0d11e732984ad575570ed51031b8ac2d7b4c536f7e85f6fce9ef5d2b946cefe2ee009227d6747c7d133ba69609f4a1e2253d0eb59d1f930611e0c26a7c0cf2d2ce7ccea6e079eadf2eb1acf0463d90fb4b3269faae3febfc88cb9fb0873d8b74894506199394c8e44a96e6b479bd3e045749cce1c3f57243abdb37e67084eb573cd820c6cee424227019592a027e9da8f7b8997bfb292627a986f83c8fb8d156a91a12a8b52659cf9272924631745ed3a2453a4c2d87a167faa9104e799c715ed597bcb66949ab15dae29a86ba147507e8d8af66e96c09c53caa053ad3b79d9ed3c0c6c00169eaec3a3", -+ }, -+ { -+ nonce: "ce48aec66f90f026bfb88afd", -+ key: "502cb8420d9e517f9850b9cb32e5756f1bf6c9e242f94a5a7b7779269c1c8e6a", -+ input: "a77b7a5870335b9145fd2e08ec898ba2f158fda16e8a2661a7a416857b6ba6937b4843ecaa79d3635d28383af80290842de9ca0bb621ee22b7fd6bf379922741e812b1739c33dd6923d0607826fc84d46bbdbd1fe9d1255f56a167779a560a6eed1b9c9579b8f771147df467e67a070d9e9ce8ad92dc0543d1c28216c1dec82614ac5e853ed49b6abac7eb3426ef0c749febce2ca4e589d06ccfc8f9f622ede388282d69ceb2fd5122ba024b7a194da9dffc7acb481eabfcd127e9b854be1da727483452a83d1ca14238a496db89958afd7140dd057773ea9a1eee412875b552d464ba0fab31239c752d7dd3d9", -+ output: "b330c33a511d9809436ab0c4b84253eeda63b095d5e8dc74803de5f070444a0256d21d6c1cf82054a231b43648c3547aa37919b32cfd9893e265b55545be6d7cd11d3f238ef66c3c278fcccb7dd0dc59f57750562cb28da05d86ee30265ff6a3991a466ba7e6208c56fc8862e19ac332e5fb3cbcc84e83a6205dee61a71acd363a3c9de96d54070a69860c152d4ceb9c4b4cc3b878547b6116699885654b11f888dc3c23483a4b24fbe27c52545c06dd80ab7223d4578ab89bff5f9cbf5d55b19611a5251031df5da5060a1f198226c638ab5e8ec5db459e9cd8210f64b2521a2329d79228cc484c5065ef8a1d", -+ }, -+ { -+ nonce: "8b6738eadaea410c7b148133", -+ key: "acc28f26867e2921cff89edf3452b4d4f2c4952ae36cc3cec938fad59037c47d", -+ input: "322d634bc180458123e10d0509870b54e0f0a3a72a2bd9e9cf44324c7a1ca37dd6adf9db1fcc8dadabd881f91d47d93b58382802b42ee936802fac8612ea4dd9eca5f215935ea9ba6233b9c8bddba3385861de669d95c888c8977851cb305db577a4eb2360f362fa459d61ffc8fcaa1502905b073bd8e9567ac7cff8e5fb1002c55641a3af5fc47ac0131fae372f073e19721ffcce9821e0241d7fa67bfc499c8f100e050d39bd4d7cae4557d208629603ec4a007852762ec1905d0e81b873510fd334dedcd9c288eb8415db505913af06bea94d197ab627d58f6a9944f6c56247595fc54ae3f8604aa37c3466f74561131e11dc", -+ output: "edbfb1090987762f75eba2439d746cdbefe8605b8ebad59e075d28b54edfe48813ccae891f6ed655c5ab5211ba896fff0c8e09bd1554aad987dc53f355d0822e9b0f524a99a79c68a9f3b4e30506cd725b07be135e4540078be88dac64fc545c433837b96a924452f6b844291c4c3fb5f8cc94f06d9f19dad7fc945f093020e82ed19f9eb3ddff68b813629991d1a460e5455e1cb41cf23bb3d96fdb6b96581c3bf9ef72814406329bbbba5b835e7724c728cebe88efcd996dea71d0fd5c53e081c21ce8b3764738d693e390fbf8e0137a716760fc9cd2014cd9bf3fd706bc3464d1f15803606976e96b1077cda0a62921ff7c32", -+ }, -+ { -+ nonce: "84c53a88d5e7b88f66de07df", -+ key: "477e74c7c6883d8531a69abf8064f1788080247c3b97ff15408a5231e5869662", -+ input: "e6b8a9012cdfd2041ab2b65b4e4f1442794fdf1c3685e6622ce70f80b9c2252ba6d9e6384d474a7622053d35df946a3b19408b3e1712da00525070279ce381359b542a9ad7c07750e393e0834593777352c1f7dbc84cc1a2b1eba787377d2cb1d08a7d20e1393d44022107acac5d765be37f9075af02e4bbf8e60ceb262aa34e2b870cc7adcf54329a667249cb4958393bff4f4333338cae45cbca419d59e605aa0cecb1241080339198b9b283e4201afc07360b8ae2a57b0b9b97167c315f03fd7a87a00ae73f91ca560a1505f3cdf04576b9aee5ea775f719916f1e1942ad5311c7f87153f8e62855ace3f34afb08d4d7c7f4fd2bf83e42f76", -+ output: "fc2673c80812d101bca7a2e0e105fa449550e695a016596f5c3cde11fb7dc518b94fdb74058e634546a726c37896110e1d1f9cdeccba1c89958041061ded8e8bc2751ec6dad76a305e70c57f9c81a5a65b5116390af4f7bf7053a03ec13f5d60a58cc5ba61f8c46ef6d2d291de490082dcfdf294aeb3a9414d64e4bd6497d4625acfa591627bfd98f0aec7e7def71515c09942db6911d73b96b4bd2d6df03bb729e945d71549d40e4bc401e1f73baf263a74280537692240638619f92645a5ade1eb8151191c7ff8bd715b3c1cd667e69745b806e16d46d9aa680a7367b8fb45a1598631cf3d44c1f5cfcd95bc8dafdb65a2083905a6937fcf21", -+ }, -+ { -+ nonce: "627acd79be19e60a36d2967d", -+ key: "648eec7d142bf1092adf706c0daae0ea14acb12733d8007aca0a3ce6e2389418", -+ input: "0cfd93b195e37dd15dfae83132c24ed5bfce7fe6fad4064b213b2c31a39e39ddad2f977e904c9c5b055ed03db46fcdd845bbb6ff0ab5a8c92e89295b6801f36ae63eba61fba24a3858aeb36f2da226b23b24d7b2c7d2670f23a9a1b60db85c0ecee584bef1b00e42d10ca17432a74bbb220d88356d82c850da4c09dd5baf413caf8f9479e02a330065fb865489c0f59605d56146ec8434182345de2d15e2a1dceeeee2fe94871d41913f6788738947ed9849ca0ae985e3e19a97bee82b96feeddceb196c9b6012264661945981c279f43db9599a4ef01116f592478619690daa64387290484d21e8d2444751194e1f361fb37f04014a3c7e4b409e5c828d8990", -+ output: "0502848571d1472ff10bec06c1299fad23a2cb824d88bf91b5447c5139500bd837a2fddc629e4a964e84907c1e6740263f1fef4f5ed41062982c150d9e77a1047b7d86c0e191945e8db00ca3845a39560857fc9e0e4a394eea4ba80a689cb5714c4bab7124ffdbfa8bbb91c3eb3caa1621f49dba1eea3ebf1d547ee337f9085638a12317b86c11aa1525813445107038942fc519eebdc1b98d313ad822bf0b94a054259aa8cf1be4b3a68f974269729941747f9a23fa5d83453071b431dac62274c24f6a32248b0785ff90aad5840fadc89af0aef7553d9352cfb00d3999ffbe28cd9fde7854e95710f4532b8bf5011e518c93361e58d22a2302182e00e8bccd", -+ }, -+ { -+ nonce: "001e58b792ba1b9a74663564", -+ key: "cd9f2cdc1ade505e6b464685219bb4c1cd70a63667f387280043bf2f74030af9", -+ input: "0d8d864010ce8df1c0179cf0236dce1c100f9c115eaa5294c24a2e1afa27f9d57ebc18f00482be0218d44262bd4db73002ff53c6388f5e333470aced2a42a73b376686c8d02e05ece27cdd8b1e3f675c715981f8b656d68d0e16227b529cf881d2433e4371fbcd933eaa72346e77e688ac80ee95324512c66a4c16338cf38c941b72c21c3d01e005a07c0eb436014fb1ee61806de7e96842ca3217ab8c7607d609dd2f637f9fda8a85cb0549f262c9e4a955c384319a6ad2b696e2593d7d174f5ddb98e2a8d5d12558c18ab67571e9a0202e91ce26d720cbe41a3a6a4f309296ca4d9d9a59a9043dd2e5a707ed7d5034023d5ea06ab14b39b7852e5c984848d5670c6f2f0b189c2a8a4a4bca", -+ output: "d2a5693c9d503a8821751d085a0837579233e65b691366e4a7464481d22800e786939349f721a815f28b4e47c8889f0814fb95d592d1185e45d6dbcac14ffa4f1d6c79194f2f7eb7323439d9607edf80f01e3a968b483eb93c01d9cb9d3625d21d66927e7aeedc1d9bd589560ed2b61cbed5ad0e0310c8ebe140c64c67d4909c010902d5386efa359ab60a9573493d3e5d8761cfd4023eba23de48372032d4673b5f6ad66cd0dfab02a73aa81f269ae88fcabb3ae9cb09f6bf60fd3575a3046bc6843f444e1e9fb9ff9b991620344fb99da68df09496b40f8b9dfc34e830a87f65710940603ebab554d36e8b4c9228bc9c26c07b828f34cdfdd40b161717236ba325e8c20bd018b324345e09", -+ }, -+ { -+ nonce: "cb1f642ce2c770518836a262", -+ key: "1559ed5a18ccc4c57415e5f0c694d875d182701bdba12e5d24fd09079898f6f5", -+ input: "07c50a69e168e388caf6f91471cf436886a3de58ef2c44795d94fba6538add8d414d84f3ef0ac9377fd5bed6aa6805a695f3a711025550bb6f014893c664e09bd05f4d3b850771991fc02f41c7353cd062156243b67fce9c1f0c21eb73087a5de0db0578923eb49bf87a583351e8441c7b121645bcb64ef5960fdca85af863dca7ebb56662e9707d541513bc91bf9b301431423b552e2c148e66ecfd48045ecb3a940dd65694d7fc8bf511e691b9cfd7547fe7bca6465b72ff9f1748723c4eb14f8bc1efb2fbc6726115c597a3881e0d5019335daf2e5ea8796c2a8b893ca798c4ef2639465505c4bd492bf7e934bb35be9b66c9f35730736c65fa4c1a2485378b9d71912cb924634a8e0db2802b75728818dc00fc28effdf1d8a05e4de4608bb6a78bb19c377d5ec77dca1b5ad38fded7", -+ output: "3dff5fde2ca24bf419e13cb7d12368e70449d41f2aa22e4b567f5cbdbcf3257975e44097deb180f2621ec36acf375dad3b7a19234b9856dc6c7842a7f86be00304b41a8c1662a02e8390346cbd0ff6be7bc1ceb821dbd805ab5c93c9c6ea5093249b5dc52081cbbbe1b326e831ef3c6c42fb791790086d1586f7daf031e70a71b54e9134f942e9ce229fc77980eb80c985ee0c5965eaba375d156f9b423b0615f4ca6fd77de28e28f35aba327e4f1b75725730155b7b4d6c5c264bf3d9dc9a16e7ededcc261add8c666278bac5cf0b3275d6d6678060eae30bbf2ce5f63e6a53a450b65aa0adbd1c90cf045f5ddd9700c2a99c80586c5244cf4c08035b6ff630c82cec3a4fcc83860e987898b42fe746939f8b37c814f8dab65de276e9784fb90f0751d3ba0826889e1e7e4fdbf8a90942", -+ }, -+ { -+ nonce: "cc72b199d056100933750548", -+ key: "8e39cfe66660c5c34c19ffc5c4d8d2f608891d6d6520e663cb85a4ccd63db01e", -+ input: "3ddcd3c00014747903c95e49f64258615455a0b26c5070a9532382a9bbd18eeb19c9fe1a902f5c6baf544c5938fc256d310a9332223dc3c54a6eb79a4b4091c3b01c798d2800418863f2865c1cd8add760e445588576d4a6c945e1d6d50dc913674daa4737ac94d84eb0ff57cda95df915989c75adc97c4e3c1c837c798a432ba4803a246bb274b032db77e5c1bb554a5342ef2e5d3ff7f102adb5d4e282ad800ccae83f68c4bfd3b6046786a8cfaa2b63c62d64c938189b1039ae1a81ce5c91530772cca0f4a3470ba68e4e0548a221eb4addf91554e603155a4592dc5c338aa0f75a8cc2822b318fbfba4a8f73fa08512132705dae792eed6b809c251d35cca60c476406d964187b63cd59333771e37367671d0ccb393f5b8bde77bebc133485ec5c66bdd631d98cdbee78a3cf435d2f824fa2f9e91e89af28b2e155df4fb04bbe4ce0b6162dcd8e81ee8d5922ebf9c957b26c343a0396d91f6287a4af9e11b7fbb5a5a5c1fcdb186365a20617d4ff5037b0bfa97b6213a6ebcf0b78b81c65737378787b255cba03d715fed4addc2c70c1fb4d3ab16f2bff287186c26a164dae2fe9dbe3c4a2e1617f01cae79f", -+ output: "ecea5fc18dc4aed23359cacb8f79a457512e0a27d9816f353e315519d2b2faf74d14ae8ae5e227b203823998a47a050c363a807f45f610942fed4518b8091b88dff8b2af8fb6552eb654c85d2b6a918bcf56fb898392941d983b1afd867ef840e12313059ed3e4d217498dd511563a939c3c536fbbf8e019deed29262f0a655fc680b15939475e0cee0ce2e8bab5834f7354b93e2e0958a5bc608fab369b6aee3c9d73a6898e402484eac7300150517bbd137bf55762897696a3dc4be74b0c141755ac8f2f6e59f707b1690c451a774c46bbe195d826a6784f8d807b78f8ebc343ecacf37cb9b1b2fdbff6a1237b5098853d783e77515c419894c2628f8b5117042294ee2ed58a33746f9e79b13fdfaa25a75fc95340a89076e786e0ecad7de437a9a3fb3092146d255005b22895310b1252a3e34572cf74665b97f4adc30dd0f34e3216c7757953a4b618a775bbe68f9e0922d75afc80a1379aaf1745f2263afb6f0b37553d9c984f1ef781ea75b1980c559c77565c83f3e0bd7a3cd7cdb594658beb7e5eb940633dbc6ae2f50383beea676cb6c814b17b1d73dd133f544da88ab371415889ead21803c1ffe3f2", -+ }, -+ { -+ nonce: "6d4adb2a1c0cd0333c19a010", -+ key: "df07d78b19202170815568dba3d1db9c1affb97dee19f11affc0d8b1cb224a3c", -+ input: "93ce72a518ae892e00c271a08ead720cc4a32b676016612b5bf2b45d9ae9a27da52e664dbbdf709d9a69ba0506e2c988bb5a587400bca8ae4773bf1f315a8f383826741bfd36afeae5219796f5ce34b229cac71c066988dbcae2cbcfcdbb49efcf335380519669aaf3058e9df7f364bfd66c84703d3faaf8747442bdd35ac98acdc719011d27beba39f62eab8656060df02fab7039223f2a96caac8649bc34da45f6f224f928d69c18b281a9b3065f376858c9fd10f26658ae21f5166a50fe9a0d20739402eec84f5240ee05e61268f34408089e264e7006a59bb63eeaa629ba72603e65718d48e94e244e7b39d21d85848d5f6f417631f3876f51b76b6c264356d7d7b1b27bbac78316c5167b689eff236078cf9e2e4626a4ae8bedeecbcaf6883e2e6e9304969b4fc7a4280dcdc5196267e9bb980e225fcbf7a9b2f7098f7f5c9edd06f50c8791edaf387ff3e85ff7bee1f61e4660fddd4eaf5ab0320508e3ccaa9823ae5a71faa86bd76e16d862d83ed57bf6a13de046a3095a74a10c4da952b3c9b8fbde36048537f76eef631a83d55d3a13096e48f02b96a5a8da74c287a9164ce03ddf2f868e9ca3119ec41f0233792e64086c903eb9247dbae80e923eae", -+ output: "bcf49d62dcd1cff9dc37d7096df0c39031e64ccaeea3830fa485edb71b7fcf2ec709a4b327ef9c7d4ea2b35f113a8485d4c236e06b3baccee30e79c6c08739fe5fbed59db30479b56dfbe584a5d79b169b200430ed27072137e940a34170606b31f22095f2151b4d9b901f6337f991a23e4c8997a1ebf5105361fdade1c889b8dc9565e3b33e0bd608c39d725becbb60da8a797186fe0986736112da3d09906442364d6e253e5b27fd5ad72e877c120ea7a11d42b19948f0df5ddabf9cf661c5ce14b81adc2a95b6b0009ece48922b6a2b6efffdf961be8f8ec1b51ad7cfc5c1bca371f42cdac2389cbddcdc5373b6507cdf3ffc7bfb7e81487a778fcf380b934f7326b131cb568bbaa14c8f427920aa78cc0b323d6ea65260022113e2febfb93dcfce791ab6a18489e9b38de281169f1cd3b35eee0a57ed30533d7411a7e50641a78d2e80db1f872398e4ae49938b8d5aa930c0c0da2182bd176e3df56ab90af3e46cdb862cfc12070bc3bd62d6b0387e4eee66d90c50972427b34acaf2baff9d8a76002a20f43c22ac93686defc68b98b7b707d78d0e7265aabadde32507a67f425cbd16c22a426d56b9892bac3a73dd2d2c03efdb22ecc6483f8d1ca67fc7d5", -+ }, -+ { -+ nonce: "1552f1ecdd1ae345319d4956", -+ key: "968498f5dfc2bc49c3a34b7bbe38515d6b46cbd6f8828ce9273f7d14f08923c8", -+ input: "f72bec13b0f0b6f2317118f14c2a0d8e963b1bd49ae7584e710dbde75bb1e30c79281847cb822a5f3ae4fa56825e511212f17f0d293cfe80f872e6992d304e9283d08ce65ceeacb003b36a862c91282a22536e0b9c19953512a1bf9e20d3e7a8f1a2dff45dec0b9b04c592e88a7814540cf636a024d10008463d0b3aafbc4c9359889149433ef173124866aa6f53526ef3b3f2c630860ecdd08ffd9fc050e95da512cc87f812f9391085cdec5cc87258b8560806a52336d612da7ab05e0f60566b950904aa27c975a48c7d78455728c87f9b53aa4978374ab9592e12c22d9a760e26eb527133534ac5bbf969596b71cde8b4ef3587fa7ffa7116834348c275ad4dce68ab3397521ddc8e54380129cc81b981f9b32db20dddb0ecaa0f1ff7b06495a42b4a800a207b8e9ca38794e2fa9f40546e0e3aef7b5236d7fdadd72b1158714a5ad8d6264df1e75120088e449b9e911eddac59f1f19a795205ab7532783a93159876133b3fe3a518475a545fbe8dd2ac143f33c35d98e3ee13b63606b1e671917ac3ff9412773a3ac47b8c6627b8ba9dde6820f4f16c2ed9cb7d7086cfbb0cf2d7533eff253d14f634ab2aad3fb4289b9a0bb667a6fdd0acd5949185d53f1dd2b96ff060bb44f872a67259100669e6eaf1a7e2b11dd5fc35792db0c44a1127765934a068bf", -+ output: "bb618ae6b7739a4dedde1dbacf864b0892b93dea3007237d2f6f23be0718bdd29321e6b0fcb6a44dacf0f5c53d91e16165997e2302ae7ebc2dbd02c0fd8e8606a4ad13e409a4e807f331cf4174171c5fff23ca232192906b4eefdf2ffb4c65af78be01b0ba7d15b4341dd5a2edd49b17db2812358c8af0a4a9724e0169f50d1d331936bc2400012a60849876c3ead52cc9fe60173c9992f83f3e41ebd24fe3961835109612994c7620280539d483f91ef9a64c16032a35612a119589efe6357fa35b19531274576e304be75bc7e91d58015792095bb00ce4de251a52b946554366ea7ed9ce9317020ec155ae0071e022af36ad10eda5d671e5090c136e381cecdb8bc179474fabc7dab2d8a134772976cf0791b6cebe2333d34b4b8e2b6b2eab2b5dc7c6a08a583d091df64328cbcde36bc1b81095d82c741a1503c55d833d551a855e098166c5efffb8e4146e32e54abcaa85076ca6660abdfca9e82824217b5d3f23f7ff3455872bc76751480c1a8e3e725365c82fc135cd3713cc0f1ea733754142f8c37716a2a4fa8a6b898215c287565325774c2510df6b49e78cb986853ac5ca532c9a7e2bceb7c0157f60433f29fe29009343d6035d7b5892c77f821b644590615dc505604501dd218dcab789e6f0525387919cf25c7c6d62a8979e39d346decbed2657", -+ }, -+ { -+ nonce: "478ca60b970002bca7147dbf", -+ key: "deedbe3b6c4d8f6e72cd276e60f30f14a0ef91c87f22aa4af2fe3c73f3f1512b", -+ input: "96eb94e1adbcc0646440c8824a2fc0f2c4b17d9cbddbb8ba8d9dbd6482fbf7201c74eb923153e0138b2f6f182f9c3d5656ee40bb7c26a01740b5c7d125261d4e4197614800aa152b402ba581bfbf4288e73c9ef7e7e37491212b921420eaaff880eeb458e3d0aa108b01b53492c97e328e9d10e3220b924351d583c00e76aee9325d6b89b1f162ffa30b386b37b5eaf4dfc25d22987dde4496158818c4d8f19ea300fe140be921d3f1abdaf9ab8946833a57cda5f41f995ff80e98b0f10f7afd736dd33438dfd395547f11563056078ff8f7c202aac262955f0ca5dae2365472de40f069028104ac552ea5a45ff2773335e5d3242f1e62e0e98003333dc51a3c8abbaf368f284536672e55d005b24b7aeba8e4cef23289adc12db2213aa037c797e7e753ae985568199cfe14cf1704fbca443e6036bdd05859e3583897cbefe7a0cf268b75d554b2da6e503ee04b126fbf74eaac0ebca37e84ab9c726973af780fe2bc9869fe67b7d9e4a04062ee535b2c1740d1347224e211b5cd37ee14c3325f40abee930eb6a1634986e756b3a1f86a3d7ee7184d95ea948506d8ab8b23f92ecf3eb0586f7a8b1bc227e08a0e32ca75ca4eeffc5c0a2a623547788bca66f3dc2c48671e462544d52a87d34307a7f111aeacb7da50262deab33d9f29dd6b47c3bb555be598d619cc66be8c4b74b01772725268a43d467f39bc565e5efcd0", -+ output: "590965d18ebdf1a89689662cfae1b8c8a73db8b26941313006b9b9bd6afa6a57149d09a27390b8883069e4fc2dfcf75035def1f8b865e24c21b1a1ed3e9f220d7b48046577b661bc92d9888a912984ad415ea2fc92c9e37da0bef5c7dab11495c612c27b5babe6eee28fd26482272fce69ca7f11bac95251735ad808365ac587830ec04105304f8e440a4da47d30e788718da4282941c9c76f18de4f954b8be750b54cb1145489edf273625a0df9a694a23fe7bfea12579b53c3b2a3de85705568cd7e603f3b8beba9a14cad9979ea283a8a291d3e1105b7f890e2a569804d9b7dd4c7e50bd0dcd11223fd7247af77f04212ece1b98c238d2fa0386a994bc502f83dcdd2e5a0d45b185155e1a395d91726d383c2c198fff1590e983c65ee041638510787c8c59c2e96f31678226a033e027bb40c416b73c3dbef31affc93a659c8ec7ffeca313fd5283a80533b2d63941c8f245d22b160c5fe57c5fa4b759c407b9acd6d9c4f80f244360b9acd11e2b43d4af757e16a6ef9d6756df39ca3a8a235e74351f50b2ebf54df633c8c400fd80b41b07117676d486377095660f2f20f62c034563b4560b473a8f4d6a740306d2a822fd8bd98012a840ba9b1709df9a0d61ecc305f7180fd764e334045d9a8ca23cb8036c05616a8b21fc488429ba4168c59dfa231f0ffa668a3be7b16583df1a55bb9c15d51660ddeca730d66f7a9", -+ }, -+ { -+ nonce: "54df19942a3f5904d66dc071", -+ key: "4077517b5363e841089462edea2ce35fdfc56bb050b3c9ae6f2a0cc04ff4aab3", -+ input: "be3f309c6e7b89e1ec4a855cf161156d09f8a04d5630534ee19e9e071e3f4603f23f0c59a7b7f8a32c4c203ec8c129a268faba09abde7b61135c6c37fd091e2d695f0e242488098ebed30c7d321f4dcef0bdd23fa85a53569868cf2008bf4d2ee7a12a6673298c7e797321b9f4559748223b590e6fcf17aa72251586b01181cefcd32c6a1a20a0fc27143426f6572b1aab0e7301e390cb857f912d78d5153906c698ee140b36cdc72693cc019cb7add747ca3a07b2b82a2332bfa76c962b186ad94209fcf590ed0f6a73b08a771a58eb9649f2f1da4f7c385da83d50c939231f745514d14b0920deedd9c4dc6d2e547f83643d13541870875e52c610372b14b602e7a47f0b3721cfca60ec68e2eee91f40ceba2d0fdb4ebe19cb1d1ab170726c9e600030454ef355f9a40033672be520e528937f38e7a862a5ae50cd94f667cd015a72ee3f91b1a09031bf4c207e0c516b2e7a4baedf373f1ee71843e560741ed3a3094d2b513e2248caf27ce135716f6887d9f1fe5b11e02c12c989d29054ab183a3f55d9b40d78e12ff56edf936ab966c7c3130bea472b71fd69e70165a76afbf720e2c1587a77943b35acfd81b2ab6f39476623edf3663024fb84da8057ed3a361e9533caf9fc58a5e4897e4bf84f58ed063b5c353bdca3792952eec0a1404149ebeb5b17cd6350ab3e27e44e40fbcb00780d001a48d0365d534ff830553409919608881e665f83bb5cf0736d728c41cc4e985c377f89ee1186303d0d76bc634875ab3ebd87059969f24b0464ae11967bcc47f300a34e3b917b1affceea716c5ad9abf1aa3a1106e2f4d006514dc62cfd2a52426968f2f3991c9f9d8fcd", -+ output: "e4032c01bcece73fde73961ed216820dcb44ce20134678c98afb674bb03afec2f4aacbade7f87a32fff57ae9213eaf0509e9d9db1313b06fd1df53561f85896ba627cccd2d0e2ae4f24f5579bf02f6599f5e63412ba084cf53a5bc9a8061b5c029b755329fcd73f629fadd3bcf6cb4c572fea86466cb5159d19eaaf0f44c3471d0323bc7206bb514ed8117a61c6d98d44faff6a83716657531d965ba3efbcf067c452e0d2807db3423958d9a4421886fe132d7c47e82086db9507616b67f0051dffc1a49ecce3ca8e4d5f5af15684cd8837a471430ddd333ea0b6ee603b7d9e702692f857fab060ccf26f2a8e61dfd3b12923acca78b83a6004e4ff09113becf6bdd0bec3a449a195559dfeafd4e2a79ead5ae3c993a15ad9b1a2ce818e18edb010b7fece9aa437d85ba9841d89026d6aac1a3a6ab6dad932a26d7db6f3664b06d51584cf4d22a75c06e2840db7292798306e4d39379af85a6bc8dcaebb5246e07fadd5e336f122de0ecb99ca24a971701a1f43bd69933beef6e52d299b132e7510caf27b99739e32bd272afc36755ea80cc7ed3957d91325584b338d15b19fe554ee70bee903babe21d0cbecd49235c70a3a4f516ce16761d1cfcd70bb4b9c7c73c359f3fdd0753d6c1ac1a1463142f18266b6a9c84675f247d56563646fb2c8c3b6b81944c2ba2b76b685ba5ea40cf539bcf3850a8af3e0a69c0b38164de520a3bea82b91f67d36bbd87877b5be7f06c2d26b2dc747a26a51f51fe293197db0e91e6ac617c71ddc6edfeb7db8f067ac2012268deb7e5f00a640c1bbec5c4c71f10f921071308cadededad5c90e72d744d0bf790b043fd35729570889ebe5", -+ }, -+ { -+ nonce: "90bece179b25feefcad4f9bd", -+ key: "e8512d17c6f5805b38e4c9b9c01961a523232162896538f5a37970de43e66906", -+ input: "0aa4fbce7e1774f0607e7ea01fc0e6d210bb283964ae75e180a9f6ff3d2c4d50914bfc32bca6d243eb33551521d54d66f377fdc1d31974ece79b157905ff7e7a9b064f349727ce37c83c15ae13df635c3e6b4baf994d9aa0bb90b06c6cda51deefda72c97a2993448e654b746b216d2b949bff1af5238558205cfc3162f1d7a020a919db4d4eb44bcf7b269d4df57e24133d1e540694b9148444cee16e64035ef006a6079dff449949c1b342991f2a27f21c8bd74ccf4bc944284a46e9fd9f9bfd4b95f80c05553950fabbf5e5aed6babb8427832266aa4d175114de9127ff6ee848534d6dd5aa6d2dc361319863cdf32cfb1b074faed17d368964393352df01fe8d86af0e994bc9dac315f7d9efa7bef47a16676cdf17a535ae71d399c4c11a3a3ba0491e8d41f419685258a4ec7d1ae588b3ca341719c0827ce5f5a653959a8671844f2d0293c09bc7d35497ed18c160fc7b6d073a311b621a7a37f7ded1df3d73dcba1821278c9e17a191997fa4dab0802e1ee1b468e91e4272c4569a17dc0b2805b980bde798640aa328a3605abea1865083d7446e960c27f69d32882a2a2295efc9c440dc203872373411925f8839715e9441d31dd9cc14bab09a3e03b4a63e14db3039d58725796326ea6327f189beecd63955f1409467c81f4691ecfe9f0ac5234f23dfb84e3199e415ee7b4f67189e8857ff6cb3f64c2ac1b554bfbd679a6ea8491cfd69d96d08ee2744d9103e0b044212560ff707974b1a9043e1f2c3592828fde8ab5e993652c00e2b3fdb19082611b67866ece6c4a2635f87e04d2136d679f632416b03ece4d7e9406f3437163f4fe0c8cc7b87d487f6de3b3022665bcafa847c2b9199e1ba9af7deb0e29b66ad41688d03a8369416dfbee6d03526adb3ebc4b4f8531d73589499a3010b5309e9d9d2f5a9cf347983a92722dbf6c4f0bae8aba57b37d322", -+ output: "a31f9a532f35f20ba604a9ab9989260e5a4ed04e6ecfa1cb9e0e1d16943906acbbb4e761a2bebc86cad0ce8b3f26d98b455e4b0835eb8b43791cea29fe8fa6e5187b60198142059bbce98917aa2957ae2555bee70e6e9e21ff6197a51ac2ca2952c413efec4d9903a2f6883e88aebe7ca8316831f6a8f2cd0e486319b58dc8db862779adff98b7f35c33faa53d56acd7a81e0feffc286b728f3a11afab7cace4c30b1a45780276b1f0ab89242410d07cb1191c7b9da5d09db7c9a729d91ac3ed82f4350f2871a12d125ba672861d1b0af7219c360a0e023a8b7c23fb9d72631c72e032c097118d90e5db0576586d8224165a8376fe8d04de93516848e7c2653cb4f7d24a971ccf4f16c527ea5b4153fad5fd5bf473b15806671854507bf1a6d9e5fe4a6f6ec977197d21d69a041dd955e199031f895adefd850c8b0ae327ba0c18ca1783560e1ff0feb2f659137e34a91e9e9ff04fe3375b7db6e4326986e6265e5fef00297f6ae627c7563846e531762748fe8d0b6baff17acf1e6c5cfefa35a95ef634ff96f83f16342a6c62311fc653d314f8a6de109356ab7801316e69a48834cb6325816b1f66d5c67d6e9c9cbc8e1a0521fd6e4bf77a7d2609f99c9579e143f530677b99d198a97620d087f058edf35eb7271701ecebb8bfde5671641ed21aeee9e7db06b932e0def91be93cf2955159e9666c770cdffa03886eb6e98dfca8f91ff5cef1927c0f82b9226d65c68d011416cbef802c264e34244ead7a6ebbe28a510a37e1276f4f3cf27a3944a08aaa23bd321092761627dae20dc269b6150545c75e995cfee0a9bcedb1ad8b364beb8839fd5c9f7984fa0a08a1a354aebe18f62acf6d6664978fcfda2ce6fc16eaa2cda5b835339001b3b98d3a407a3e18e0ec2da6ee3d1448c1ece2ed67c3f51f01e76ed59f0e61102b103a3c65aea94275e8d1f0d331538efe", -+ }, -+ { -+ nonce: "09bdc9b17d49e6db953bc716", -+ key: "e5d9f90b68e6ed2e95ca1d636de3334244e63fd8891fb199175705ef5f69e91a", -+ input: "e097b1e8dea40f63714e63ab3ad9bdd518ac3e188926d1086a9850a5580affb592f6e421abc617c103479ba39a3924eea1c0bbbb051614c4b5003bbd5fcbb8093864fc1c130748194d6b560e203b889b98b574a98ec3e0e07cb2d9f271ba7794e5419123b4f2ebc7e0d65cd404104868905ff2c38d30c967fe9d77ebdd4b8fa836c3b0ad15e3e70e9a28236d5593e761e694b047f63bc62c7b0d493c3e2528c8af78f56725172ac9416ec2bdc54de92b92a63f9ccb61e686f9249c7cc337d99b2160400bb5535eb8f8eb1e3cafcbceaa821c1088edbacb3b01b5bed977e702de747ad00268ffe72e3d877dd75816db65b5459607cd1b963fe43bf2405ec223ddc0de514d59cde74f7522dc72285caa3eeb7eae527a7723b33d21ce91c91c8d26bf36eeb1dcdfc1e9e475c1565ed9c7e64ef601874a4f277280a5ceec26717e9385aee8b159379e3feed7952b87240c942970d63351259aa7a286ddb4a2620fa67565c92f592902e49422f1eecea2f44d1c0bbbf54a9e5612b86a9549aa3e6639a924c7bbe2d3c1b5669da73c0e2c6f6f6084f54a912ad2635d0141c2f5ac925414dce0da09ab8f86eae2a7b7e48741253189e5fd554d5c04d9807ac6ffd8a4f8229a3e8ab75ca5c778bd7ec5a5c02085faba9792cbc47f9e9311f3444e6544359769e1b3eb4d42ac8923ec94536e1a44497766b5da523f5763749dbc2738dfa8e13c191dfeac56c7614a96bd3ae23e4e6e5ac00be851ac9831108989b491eaade62113c531385ef3e964ce817c8ed0857adca946467682c2f4387fab2f31ce71b58370853171720268459588d5d216faca58d0bebbd7cd83a78445d9b49e83ec2cdb59b5d760880bf60532178d60372752b47d52562b316c7de5c74af9cd588643002d66bc6260595a540d2f82cf2c07fa64e0cdd1f79877b6a25b0608c735a7d35ca10852da441fcfb31061fd7e482a0989866f9eea8b0b39c3d519715c1c2766c3ad99f041143cdb36557ed647403458155dccbb80c3a365f0a85b1135695648ab67ac76b3d219c7b77e49d735c72ac947b1d7eeb279beb9d2602aba7b36ca", -+ output: "7b6e07e6415660affba56047b988f4548b308e7a642c76791f5c3742cc4cb744cde48fc30e50d458084e06c6dd29a52cb4c306a69a493a17c0838d14b107d07b81c983a2dbad09b80f087ba48465a8beaae5b16e8093e17cfb9e84ea3bdb9af00889268a5c01ddf25af434de56f65882322432aa275fac8519e317ef4d89478f29182143f97350983050f5d37c4b518611da6fa2aed7bb73e614231a194fe17c9073e377fc6ea0aa491e15ca54808e0536c8c3f1bf657283f807ebfc89b55049ac8fb86f89f17974fcf0afc1a2c690c0442842d0f4af9ee29dd960e499d1077bfdad4c0c9189a6e83799bb585acdb853c1e99da7ce9c7eeb9bf431f8d364d0ea80b0a95a7807f196c6ee69fe90e6d1f5d23e5cb256e37e65826d7a111f2272884d6319f968580b3164b2697ea6556816cea3ca316651fe2fd68dfa905d080c28622606f7d24da216289fa2c54c6f42dc244ecb047512ace62f0801f2dfad8f0218f45e2b3bbac97c2176c842398b16dfa1fdfc9a68b7b5a1e785d2a0cc592bc491f5a69c81127b758ee02c66b81674d3135c5882d1dc89dadcffa06f4b0644df5c7fd65c72611d79be7ad637edd6fc38b39946aa2a2c6d08ca9d3ff9a8ffe2e7989546489539b1a623fa937c468e59e0978602526b4367de277526895aa222fbaeae2084f418c5745d8ee844da0baa47f592970c14cf710f49539c12104a62baddb3382f5773dd18c83ecb238ae2e749a51584a38e394ebadd175bf5c3cec787907abb1d94af70ae63d3b7d8d5ff254da90b78ec8fe2ea95dfbc6e3e69ecad856c9e54906df8fe39859f2014b74dc3ca0ee2a957001939d37a6c0b489bd3f1658b835a57b24aa282c23e875c9e67e6eb8b32fe44e7d7d8e285d85da0ce1b53990f9fdb5e2e74728e433ed2c1044df9e89cb9bb316c39fc6fc8bcc74a382093926a288170e857d6b7f47858a4c2d05c74263dc9e8199332d0179687f4a4cdfc80ee6737300cefba75905b22d21e897f887b67aa3051877fff11d98bf96ca5091bb225bddd5eae697f3dfb0efcdb788ebf6694b5b39dbb0d4bf9427382a3a58f0b", -+ }, -+ { -+ nonce: "3e507e0cdf0d11f88c6c3183", -+ key: "cdd1a20f05f9e74f1b4c9e2b81c85b11c5bc222925aa603f316dc21363af9620", -+ input: "0a1064714f20d9e47fe53250ecfec759f4137e60afaf65755f4709a483504c3855833b6dcaf7aa0180fd735fa9a73d46697f6c45004adf12452ea4c04a720fd7c20b9783b74b8b3ea0c8b1563d5a85f44af8afd7d91ca6298ca22642a684f66e365edd6f6bdb2dd32dfa13c62dc497fb341b86f65d40655931171416e23e3b2623c0b4a67d448877b6e3d4e0fe284034a10162b2b5e21639047036874f4bcde22b145b5f18aa8ff32dec81e6a5ac68b3c30c24bd8fd3b8e098a1cf202e2ab2a3bb66a9393222b9f7384653cda7707f00bc3c81e9591fd040a07d3629410c2db78781a4c9db3df5f9d648162f1b087974f56a89db07aa21ba827e3864a1618945b2fba06853a13c35da2909f5013feb313bae09870b8eab904024adab0d6ac46c1a1499791b47413139dee59db676949b9e9ab8d3d6abaa954ec2a9fc83953c91b483c3b6bd6700b96484850734e72e3710a1b379c0d0698aeaf68f13a0d317bfd689471e3299288e7a383a58522f0daaff210cc4917fa05f0b8ceefc2afc46148a05a100d30787accfb4da094e61ea6b58f132692aedcabae928e53c2594b01507b8fc2d0a85a1d111d1f4de0b95258281ae01873a72606753b6f878ecd8c4f613fb3477710d260f0bca0d4c06f675ab7113eded395f88755a98a0ad22b4a002cfe9447c4e39eda13738f4eccb9c13367ebc2878257c4647d31b67e5e32b6a77f23e9593658d19c0a40e8a7228767afba1cf23072b013b2d76ee66e42b57bec2797ce3619c695a661004c8129cb5c5d6a2836be22483f3b7e40bf8ac5535bf6cd065c4821a87829948c88163cfe3c0f60cea4e7ff59df4cdbf80064b2d664b39487413039999b5e86f1d467b12682d0cd355e9f7cd980e87d584ddbda89f68632d3b8fd6bc3b80205d7feb97a46842b093f74aa14bb21accda7474247b5e39ac76ef75e9b5b52b6a829a7e2297ab88fb0eb690d54ab1af2d7437149a6202035ce15f1e6c6267458d62677c263d83d3f8119af191b7d766582620e0f08b411c996c25ba6a32c2d73f592e789ed662e94103329bfa5e6573f1116ec04438997f3e4ad91b4123b570743455020d914bde2d8417fb24671e6db261732fb89dda1a36614b095529e4f97374c9bc0e55aa577bfffa663c816ca9fae3472e0a", -+ output: "b00a7caf5359c5bcebe590e6bab9aa03370050c55cbd45a257f4869937e922a15f2d38121b1493d6b5dd4a8a47d7b4e5cb049d396ad84ed421df774b0408b6939f18ebf5cf83f48c540affcc2a885967bf4bd222c42904b8a73c4185bde3f97e874fad25b46714235e60c9ff53ed2975c9c85ebad0752249e4b627ffa41555eb9074f63a5f7d61d207d2ce11b2a9fa23a13a0832eccb91efa2afd8d9acfee94ac78a733fa156bfea5006da1d0127c32aadbb75c015b68c627903e1c85bf3a1a9f99c6cfbdbb5c871f7f9661b78cf5e16d819f53e9930e201d4f58e69bcdce77ec5b9b1d2cf206a71f744342273c26b9abc71303c20df3d51f52222893d803fc8e0e0afcd99ee1c7f95b48680403566f7f9e296d7ccc0ec348b6ad515af58d11fd82c628ea29ee6a5d67aaeabd8823addc01a078b04313af73105d4ce4abef8e6ee8ce649640a19678292d4f1017d121549fd2c19ba6cdc0b613e512bc9551d759c6d38aea7e35c0847a142e273a16bb1495e652f9668b97801ba3f6d9931c0a1efaa4452e15732dca1ca9cb45ed289e0fd08d1cee1cdcc9dfba8d0b2562b0b1a180f4ee69d63573222c8d4789bf0d63d2a201a70c7b27c84e620e33e8a863cf49b784269a51ead3d4ad26f044d5859988d5485a11533ea805f5a8f6313caa6b421071a34f57170fdd8e4663e9a4cdcdcc1ddaa9f6e651fb365cf827667b018ae7d028c7f96295b2b4f9eeb4b361b48af86463a79f50b107ab0935e3cec3f4f203cea801ff95fb870d2c2f0e315dc8a6a547dd3c390a1f5403917315164bd2d40362489b389a54e8dc0ddb83e6a43a26c65923e6f76ee0ee0e3a33b0a9066620a01f0319e20b9f1beb3910ad962a3000e6aacb0ae57f3f6c5e0315be5de93edcf0e45e0e47332f9daf7f33e6e8bf1929910b78b8f88ca12bf5519a3217b7554c8c8350cc314561d580bf67a3878e3979430d070121a5e070a3458742e8549bda972f603222e2b30eb8a49a955805307e6e02f8c60a08188f69340e116422458d4a8841f46a78c833b1a822e3f6c9c97422c918f17c36175ca4b3d1c081ee4b175b4b07bf101c3836eb5b9e3cbd08a89b4a1c50edcb41ea8ea6ceb1532f5b842715d50dc21e2499e08c373d3dedb96bb477c8802ab7aa957e0b5810f38", -+ }, -+ { -+ nonce: "c9da02eb6ca0cba74c76240c", -+ key: "574a41e94695e2d54c2f5e1a464c6e801f8d09481aca51437cd93e05ca95a4a6", -+ input: "00fa3b13b5cfa9b5d65a41cc2d3c420518802c22c4582873f1ad52a22032d2cef7c975078b199787e852fb1f914529f60d1cc854e5d6d547216dce043e0fc94866bb2193343c3a07fde60e668266d1cee3067c6f2ce0f9f63456ad08094b6c7f515f7ca90caa96494e2a6835ba1f3f166012ad1ff6af6b5f8455d5c26e72402966af9066ca70ad027eed23b0eb02c751195064a62283975efeb29bc5993f83360d012a2f5275ac758a9e8fe458fc7cc0673e6b9e338678f0faff60a67fff3784c3054dcbd95d1b00ed4c6156b3831cc42a2ccdeee55541f228b88e6c318e2d797c6fc035ae12868c4a4e3843b5b25a530b1477dec3f5ac27644476b5766e0ee132d833f9a63200eb0980bf72c3666150e567e01e3e1f469cf36beea65946fce714a3f354983e54ca4315b57ea35c5f48bd5eada05f49db1004cbb39888ebab3afad62f6509abad77ca8c4ff28731c7ae545e6876c8f4a80b6cc26928ee05001a9764694b52edd605e182d5a3a5fd192bff58aba90f57e4debe612d02cf6f08af33a78ebf8823bb3eb46d4da25b7dfa15ad436c380633d3db3d0dc4dfec6c2324d105e7090e65342b554854e777b40b5dab8125a58e8b212364ff88459a8466ff5ae661034abc8286a78ad5aa582e2dabbcd7a0b0cedcb9fd5f0bb8c3bef9117f2ca6520a72b94e528c1a4a464398e654995d5f4c77cbabf2b204b96a058cf1b38284b34e41ac37b05a003ed51be9602050f21c6b9326714bc425c1e22833da95a6e77571691d4dcab4ef9056c4c7f85d5b445b902eb375b5164c6bdf629ccfd4127a6c024bb6c4da0b6b08350432e58f8229e04e2e76f704be17d36e0c04fcc7a98f721d4572aa7f66ae8e9664300a189bc3862da47b60c8b33424f6d577cc10f4755f36c2a6decc30ba81bf48f96616ccfcfb74965d6bdcab82728bb224c560d1cfd7a175413ad1c14c734746be3b062b4e7514e9075c688103515e32e3335dbd272a315024d56f4ecd354264da9bc712080657b2b51b06dc7c4c441d9858935a4c3e6b207bde38ea83bba4c6854b2bcf914d758e0a174c0528e0e385c7cff355c38db1c22440369141e91266824c59f1ed23e7d4b99d31b0baa7bed4526e24259dbef5c9ae275e97267b756645f804c274d65ac7ab0f7683435bc2e4f24075cd1b790aa2b53fbf044e8f2092bdf0dbe88a582ff8f8de291e8220", -+ output: "bea32587095caac661c3ac49e65654b282192b2addf5b9a403aea6c8bd0096291a0a66ca4062acf1da91fb5749952096ec63ab652ecf94c29807f0aaac939b6896edcd6f0cd8dd8d208b906ef4d7a8766831fecd6ce98f4ea0c34fa9a5114dbeb23c2cd6d3aa962e39b18cb343c24e65d49fad0a0fb50736f8d2b24b011108932484399f4c4510ac9a5e6bc78ff0b450e67f87b49f253b99d95d6294e15a9934fc8b89a5913c08f75d3516766fb0f60f82e2b2647b4619991c78adbcf548c07c0dda30c629349d84f298313c3e629e03760b1cf860264205a950d6fd86732a6513827f72c0dff5aff96f7203464f60849c1065beb70f282cca1334f6f6c767dfff94f063361f592e85597de5d313eaed17bd533db24818d9ba9aea2afa797721fbd19eea7b8d46bbc4b9dc0164636d2e754f5e9e8c04e2a381096331731c645ea1f613a37bfa9a6fb2c6307e9bacacbeab7f5672163ff9742a8115049bce0269d7d5f6f35787be031dbee1535b0516ec0b46d12f5833cde5f2cc569edcdd20993e9776aacf48ace7bfadf79065f2803fba6b2b27aa622abb7ae023ff2b27b727f509f313f92026392485a5ed4fd53b2e22b2d2dc1538ce158d34921214638be30ae054a0f5f1d4f9c590a2d215ac2a5b23ed33871ab26c8bb6db7fe9d6f51e527c9547248a4e9734c64658b22893f4f6867a35f18e2bbfd7d62142025955cb51af8e40b6fcb91c7e959cea2c92022c87c29dae107a306f41b00e73c7bceef8cb070e8f9e830caeee463170e919cba6eee63092a5a7ee33b74db09cdd022fdafbcd5d524253a29a103ba6f4d668d31d18f867557871c0e0258221c3050d57c18bdae4cc4ff8da0daddb5c08619be127ee76a317b59a9d8e67808603a1bfce6b4e0d070082b283bf9c0e6ef8256208e482f3e2d1a40d30807f60a868e2279dfbc3586d44ee25fdca3505cd39fd469c2cd03bc2f921d22a8346750f346c919e7247301c1c8a4a3ddb8eabc6e80d85cd2459afe1cbb4851ea2c86b8075e0fef3177cb074894410ecf681242fac62b5fa4ed3a10ddaa595427851d376cf69e350207b667f7aa26d003f1ec739a8792532ebd93f3cafb1fea40d227bcadda2fb6da794cea3371240f257f80b1b8a857ea453b46938397c1f4b303a46257750003a60666a11d03bf2afb5c71e059933d617288891733b63784bd9c662234f", -+ }, -+ { -+ nonce: "a4472b3c13c814f614706fa2", -+ key: "183dbd3967cdaac9b58554cb226a532087ac22bb80a59d1c2e6b997d61e46f45", -+ input: "01847d8a97d56e55e12f89adb13c8c0f9dea5555e8dc61171fbb8e181f6cf846a4dd68b2c75335c0896fa215bf7f9eb7e398e4520aaaf33461ecfb61051f43d43569fb75fabd79d319bf39469f951e4da7932a74624c46d8d26a9499c701c00d3dea57a6f65b4c0f33b568d13989340294d17cd005b26d89cf6fa1c88e7b6ef4d074291fa8c117ae05d7c785459ef4561c45af63a811e9aa1c31b69a5bdac2356d955a0f579791247a757a691b3de447a53619878397cd82a74053f06da3574045bc856500ec01fd2afbc64d8dd283ac876a50e9396f78c424ab157f481316fd9c90cd899f5aca46dad32c68f1d64ea7f1c4bdb994ad847072609bd89adc2fa8382a5d573b680533640b8321b6adf27926274660b2cbaf04fbc9a4fb17ce8957c38c7bab1aafd5bf7263171e47d2e1ae5cf0494815642209d303dba561754479c24ea01a573c9083b68acc49907b1748924d3c6a82feb9417ca932578c123f9db35521c0d992565f7396f0c23e436289c1720e4e7c6e285c04a8159f93e06801334e523b18fe188355cc6a155febe64ba053e6b5d1cc87787fd5ae68fa86d8c51868b9f6a9664cf0d56aa6cb8463362bb671e6b8423bcbefe2a1a0acba3f135496736b5cec5e329494af46aba322bf5d1cc108c98298459558773a316e09b0bb960a26f4b0bfbaa493b5f98a0e522b6203c471b10e662abe9b9e60de2a1517843933add02017fadd62608383ad53796159f3d21b2c8ed7295802ca79ea65d550114ca2bcc7f7c3b4c6709fffc3c2de00da06e83d8f0cf04b8c8edd21c0fc11a0b2aa7f6adad255fef25e5c0a9d59546e97446e1fbf6a51a8ea6cad54cabfdd19cd10d7d33ff0549b710557e3931821dd8809ab0a9d3aaa761a01ae0f2e378906672924d6a1b12fb1cca7bed41f31974b9917a05de60c32796f502e7035a2c01cb49bc8e1734b9fa138b81b4dfe19d37f5942dd1b42f03e1e5a6a046ecd457174150e17dd148e4bfea44b72da35ef42a7251244700e59e702033677d42611168fd246e1b18b9a464b6c20fc7fcf6360cd00466ece059a69d7d54a4f5565d08799f85dd3c849a08ba43415077c1c0e5dbdba52bb3167ee99a11db551f0260493be1dde58d2072e8c02251f4f574b6e115cbb6136dc2c3fbce75fdcefe812d9c07a91a89088985a52cb1fb9f6cef80fa30364706414175e42c75e8e37f6e7cd028c99f59caa88c49db5b46e8d6301bc39034013718a9eeef5506415016fb21d70e46a03b4c5ba72f91dd9321ff5e210e5e5f7b0723a3bc4bb02b5a74c1f4a63aa5a993a31f79a768fe8033c9abfeb4deb536af1054be02d8d1c4a6a0fa75f3eb787d57a03b7ae994fb1b54b2c43b230ce32e6245d944b3cea4fa6", -+ output: "785dbea5d1e50af4743ed5fd2209e441fc7c50bc7f6fd9cc7f24654c619e2606178dcbbd81a1f94c1b3176837024098bd31326145be326b32fd9277a55a6fb38780c8dc8b471a3184379d90da4aa87d80b889b1f4d8d0755c1704a526b99ac829b8ad157ca54b2b05ff8b2917e27b0c147ab54add9a89fdcad7b93ba1fe2d5be9de88b68a5324f1b42943e45ee31c4ef783ec9e2337b3f2834b10cf452b313fafdf0c03719140f64060da0a565e185cb8e544e1c185ca230ff2321739a285abe8be4be0ce76678a7b0902a77a645194de49fef8ff64cc464ea25e1f1d72c775e450f08ddd7680d27a4142879787b198583d93b84cd87fd5b4063d92d13d9c9cb580c01fac0174686a18f64e6fa0b3589624cfae04aad74950559bdf92b2b199c60cb04013aa0ef56d1f9ec5b7e968f6a83756ecc9cee7dd8b433f64649f948df5474a64549e71e46fd8bb16568d21f5fb67f5ed555f2b8aec4709383e8cbc45b9fe47c0434178ad4c6d0d42606d6eef0e21d0370898d1d5d646830a88d5f024094fe9c7a2003ca13d20ab7cd748dc11a22f578ddab416f3500eff3d89fc177b46436108e2e2c7973910cb8454a01c9e9b98f966848325444b2ac205b1ed6919fa76aaf63717574761b7f62b10649357df49f85a845a30b6acd57fa202fe58673930ec59399f537e9682b1f5f6f409988789a8e0c1f803478dded14b40d3b6eb3109758efeb6a7fe21f41c4dcc8027258da27ad74010839dbfdf8fe55050511f85c321e653f76e55f22248f46da529a380c6b1a16a19ce73af9715545c2cae098dc42dd61248dbcf7b295f4dc6b8930b41baeef677156c534869be65e723e1aa0336e8be8a3b138f840c9cd63bab6d9d61f239a47d8cf56258544e6ef65edca27069f7a57f087a7cc021fa1294b75c0c0f1093c025e426e4f041ed5187f358402676d5da5fb6ceba76a178f65c8c3046f258531c165b8808bdd221c59ff56e3e06247576e144aac01ea96a07f1be15d7a2b0b3b6c259a9133f8a50b56154ecf9f61022f470027247e6e70e6eaf7ece5e324ec8f95667ffed10337652b119e7cb8d197e306e81ea251340b9fb2c33aa230c0a16e1ca783f9344b3acbf413acd96616e6d477dba90e39326089934bc5ca6620855cdc442e25bf8b8debf335e16e7e25cceb68659cc81b13a507fbd9f30b347126beeb57016bd348fe3df592d4778011664a218227e70d7360d139480500b7f6f84153e61ca4dea105875e19ce3d11a3dfd0ad0074035ff6a9fac0ece91afd8be74c168da20c8baafcc14632eb0e774db758a3d90709cddf0266c27963788c35a842beea8ba2d916234431efde4bb32fd7e1cef51dcf580f4697206bbc3f991f4046360aea6e88ec", -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20/xor.go b/ms_mod/golang.org/x/crypto/chacha20/xor.go -new file mode 100644 -index 00000000000000..c2d04851e0d132 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20/xor.go -@@ -0,0 +1,42 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found src the LICENSE file. -+ -+package chacha20 -+ -+import "runtime" -+ -+// Platforms that have fast unaligned 32-bit little endian accesses. -+const unaligned = runtime.GOARCH == "386" || -+ runtime.GOARCH == "amd64" || -+ runtime.GOARCH == "arm64" || -+ runtime.GOARCH == "ppc64le" || -+ runtime.GOARCH == "s390x" -+ -+// addXor reads a little endian uint32 from src, XORs it with (a + b) and -+// places the result in little endian byte order in dst. -+func addXor(dst, src []byte, a, b uint32) { -+ _, _ = src[3], dst[3] // bounds check elimination hint -+ if unaligned { -+ // The compiler should optimize this code into -+ // 32-bit unaligned little endian loads and stores. -+ // TODO: delete once the compiler does a reliably -+ // good job with the generic code below. -+ // See issue #25111 for more details. -+ v := uint32(src[0]) -+ v |= uint32(src[1]) << 8 -+ v |= uint32(src[2]) << 16 -+ v |= uint32(src[3]) << 24 -+ v ^= a + b -+ dst[0] = byte(v) -+ dst[1] = byte(v >> 8) -+ dst[2] = byte(v >> 16) -+ dst[3] = byte(v >> 24) -+ } else { -+ a += b -+ dst[0] = src[0] ^ byte(a) -+ dst[1] = src[1] ^ byte(a>>8) -+ dst[2] = src[2] ^ byte(a>>16) -+ dst[3] = src[3] ^ byte(a>>24) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go -new file mode 100644 -index 00000000000000..93da7322bc48c2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go -@@ -0,0 +1,98 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its -+// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and -+// draft-irtf-cfrg-xchacha-01. -+package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" -+ -+import ( -+ "crypto/cipher" -+ "errors" -+) -+ -+const ( -+ // KeySize is the size of the key used by this AEAD, in bytes. -+ KeySize = 32 -+ -+ // NonceSize is the size of the nonce used with the standard variant of this -+ // AEAD, in bytes. -+ // -+ // Note that this is too short to be safely generated at random if the same -+ // key is reused more than 2Β³Β² times. -+ NonceSize = 12 -+ -+ // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 -+ // variant of this AEAD, in bytes. -+ NonceSizeX = 24 -+ -+ // Overhead is the size of the Poly1305 authentication tag, and the -+ // difference between a ciphertext length and its plaintext. -+ Overhead = 16 -+) -+ -+type chacha20poly1305 struct { -+ key [KeySize]byte -+} -+ -+// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. -+func New(key []byte) (cipher.AEAD, error) { -+ if len(key) != KeySize { -+ return nil, errors.New("chacha20poly1305: bad key length") -+ } -+ ret := new(chacha20poly1305) -+ copy(ret.key[:], key) -+ return ret, nil -+} -+ -+func (c *chacha20poly1305) NonceSize() int { -+ return NonceSize -+} -+ -+func (c *chacha20poly1305) Overhead() int { -+ return Overhead -+} -+ -+func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if len(nonce) != NonceSize { -+ panic("chacha20poly1305: bad nonce length passed to Seal") -+ } -+ -+ if uint64(len(plaintext)) > (1<<38)-64 { -+ panic("chacha20poly1305: plaintext too large") -+ } -+ -+ return c.seal(dst, nonce, plaintext, additionalData) -+} -+ -+var errOpen = errors.New("chacha20poly1305: message authentication failed") -+ -+func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if len(nonce) != NonceSize { -+ panic("chacha20poly1305: bad nonce length passed to Open") -+ } -+ if len(ciphertext) < 16 { -+ return nil, errOpen -+ } -+ if uint64(len(ciphertext)) > (1<<38)-48 { -+ panic("chacha20poly1305: ciphertext too large") -+ } -+ -+ return c.open(dst, nonce, ciphertext, additionalData) -+} -+ -+// sliceForAppend takes a slice and a requested number of bytes. It returns a -+// slice with the contents of the given slice followed by that many bytes and a -+// second slice that aliases into it and contains only the extra bytes. If the -+// original slice has sufficient capacity then no allocation is performed. -+func sliceForAppend(in []byte, n int) (head, tail []byte) { -+ if total := len(in) + n; cap(in) >= total { -+ head = in[:total] -+ } else { -+ head = make([]byte, total) -+ copy(head, in) -+ } -+ tail = head[len(in):] -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go -new file mode 100644 -index 00000000000000..0c408c57094ccb ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go -@@ -0,0 +1,87 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package chacha20poly1305 -+ -+import ( -+ "encoding/binary" -+ -+ "golang.org/x/crypto/internal/alias" -+ "golang.org/x/sys/cpu" -+) -+ -+//go:noescape -+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool -+ -+//go:noescape -+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) -+ -+var ( -+ useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 -+) -+ -+// setupState writes a ChaCha20 input matrix to state. See -+// https://tools.ietf.org/html/rfc7539#section-2.3. -+func setupState(state *[16]uint32, key *[32]byte, nonce []byte) { -+ state[0] = 0x61707865 -+ state[1] = 0x3320646e -+ state[2] = 0x79622d32 -+ state[3] = 0x6b206574 -+ -+ state[4] = binary.LittleEndian.Uint32(key[0:4]) -+ state[5] = binary.LittleEndian.Uint32(key[4:8]) -+ state[6] = binary.LittleEndian.Uint32(key[8:12]) -+ state[7] = binary.LittleEndian.Uint32(key[12:16]) -+ state[8] = binary.LittleEndian.Uint32(key[16:20]) -+ state[9] = binary.LittleEndian.Uint32(key[20:24]) -+ state[10] = binary.LittleEndian.Uint32(key[24:28]) -+ state[11] = binary.LittleEndian.Uint32(key[28:32]) -+ -+ state[12] = 0 -+ state[13] = binary.LittleEndian.Uint32(nonce[0:4]) -+ state[14] = binary.LittleEndian.Uint32(nonce[4:8]) -+ state[15] = binary.LittleEndian.Uint32(nonce[8:12]) -+} -+ -+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if !cpu.X86.HasSSSE3 { -+ return c.sealGeneric(dst, nonce, plaintext, additionalData) -+ } -+ -+ var state [16]uint32 -+ setupState(&state, &c.key, nonce) -+ -+ ret, out := sliceForAppend(dst, len(plaintext)+16) -+ if alias.InexactOverlap(out, plaintext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData) -+ return ret -+} -+ -+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if !cpu.X86.HasSSSE3 { -+ return c.openGeneric(dst, nonce, ciphertext, additionalData) -+ } -+ -+ var state [16]uint32 -+ setupState(&state, &c.key, nonce) -+ -+ ciphertext = ciphertext[:len(ciphertext)-16] -+ ret, out := sliceForAppend(dst, len(ciphertext)) -+ if alias.InexactOverlap(out, ciphertext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) { -+ for i := range out { -+ out[i] = 0 -+ } -+ return nil, errOpen -+ } -+ -+ return ret, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s -new file mode 100644 -index 00000000000000..867c181a14c074 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s -@@ -0,0 +1,2696 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+// General register allocation -+#define oup DI -+#define inp SI -+#define inl BX -+#define adp CX // free to reuse, after we hash the additional data -+#define keyp R8 // free to reuse, when we copy the key to stack -+#define itr2 R9 // general iterator -+#define itr1 CX // general iterator -+#define acc0 R10 -+#define acc1 R11 -+#define acc2 R12 -+#define t0 R13 -+#define t1 R14 -+#define t2 R15 -+#define t3 R8 -+// Register and stack allocation for the SSE code -+#define rStore (0*16)(BP) -+#define sStore (1*16)(BP) -+#define state1Store (2*16)(BP) -+#define state2Store (3*16)(BP) -+#define tmpStore (4*16)(BP) -+#define ctr0Store (5*16)(BP) -+#define ctr1Store (6*16)(BP) -+#define ctr2Store (7*16)(BP) -+#define ctr3Store (8*16)(BP) -+#define A0 X0 -+#define A1 X1 -+#define A2 X2 -+#define B0 X3 -+#define B1 X4 -+#define B2 X5 -+#define C0 X6 -+#define C1 X7 -+#define C2 X8 -+#define D0 X9 -+#define D1 X10 -+#define D2 X11 -+#define T0 X12 -+#define T1 X13 -+#define T2 X14 -+#define T3 X15 -+#define A3 T0 -+#define B3 T1 -+#define C3 T2 -+#define D3 T3 -+// Register and stack allocation for the AVX2 code -+#define rsStoreAVX2 (0*32)(BP) -+#define state1StoreAVX2 (1*32)(BP) -+#define state2StoreAVX2 (2*32)(BP) -+#define ctr0StoreAVX2 (3*32)(BP) -+#define ctr1StoreAVX2 (4*32)(BP) -+#define ctr2StoreAVX2 (5*32)(BP) -+#define ctr3StoreAVX2 (6*32)(BP) -+#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack -+#define AA0 Y0 -+#define AA1 Y5 -+#define AA2 Y6 -+#define AA3 Y7 -+#define BB0 Y14 -+#define BB1 Y9 -+#define BB2 Y10 -+#define BB3 Y11 -+#define CC0 Y12 -+#define CC1 Y13 -+#define CC2 Y8 -+#define CC3 Y15 -+#define DD0 Y4 -+#define DD1 Y1 -+#define DD2 Y2 -+#define DD3 Y3 -+#define TT0 DD3 -+#define TT1 AA3 -+#define TT2 BB3 -+#define TT3 CC3 -+// ChaCha20 constants -+DATA Β·chacha20Constants<>+0x00(SB)/4, $0x61707865 -+DATA Β·chacha20Constants<>+0x04(SB)/4, $0x3320646e -+DATA Β·chacha20Constants<>+0x08(SB)/4, $0x79622d32 -+DATA Β·chacha20Constants<>+0x0c(SB)/4, $0x6b206574 -+DATA Β·chacha20Constants<>+0x10(SB)/4, $0x61707865 -+DATA Β·chacha20Constants<>+0x14(SB)/4, $0x3320646e -+DATA Β·chacha20Constants<>+0x18(SB)/4, $0x79622d32 -+DATA Β·chacha20Constants<>+0x1c(SB)/4, $0x6b206574 -+// <<< 16 with PSHUFB -+DATA Β·rol16<>+0x00(SB)/8, $0x0504070601000302 -+DATA Β·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -+DATA Β·rol16<>+0x10(SB)/8, $0x0504070601000302 -+DATA Β·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A -+// <<< 8 with PSHUFB -+DATA Β·rol8<>+0x00(SB)/8, $0x0605040702010003 -+DATA Β·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B -+DATA Β·rol8<>+0x10(SB)/8, $0x0605040702010003 -+DATA Β·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B -+ -+DATA Β·avx2InitMask<>+0x00(SB)/8, $0x0 -+DATA Β·avx2InitMask<>+0x08(SB)/8, $0x0 -+DATA Β·avx2InitMask<>+0x10(SB)/8, $0x1 -+DATA Β·avx2InitMask<>+0x18(SB)/8, $0x0 -+ -+DATA Β·avx2IncMask<>+0x00(SB)/8, $0x2 -+DATA Β·avx2IncMask<>+0x08(SB)/8, $0x0 -+DATA Β·avx2IncMask<>+0x10(SB)/8, $0x2 -+DATA Β·avx2IncMask<>+0x18(SB)/8, $0x0 -+// Poly1305 key clamp -+DATA Β·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -+DATA Β·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -+DATA Β·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF -+DATA Β·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF -+ -+DATA Β·sseIncMask<>+0x00(SB)/8, $0x1 -+DATA Β·sseIncMask<>+0x08(SB)/8, $0x0 -+// To load/store the last < 16 bytes in a buffer -+DATA Β·andMask<>+0x00(SB)/8, $0x00000000000000ff -+DATA Β·andMask<>+0x08(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x10(SB)/8, $0x000000000000ffff -+DATA Β·andMask<>+0x18(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x20(SB)/8, $0x0000000000ffffff -+DATA Β·andMask<>+0x28(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x30(SB)/8, $0x00000000ffffffff -+DATA Β·andMask<>+0x38(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x40(SB)/8, $0x000000ffffffffff -+DATA Β·andMask<>+0x48(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x50(SB)/8, $0x0000ffffffffffff -+DATA Β·andMask<>+0x58(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x60(SB)/8, $0x00ffffffffffffff -+DATA Β·andMask<>+0x68(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x70(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0x78(SB)/8, $0x0000000000000000 -+DATA Β·andMask<>+0x80(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0x88(SB)/8, $0x00000000000000ff -+DATA Β·andMask<>+0x90(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0x98(SB)/8, $0x000000000000ffff -+DATA Β·andMask<>+0xa0(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0xa8(SB)/8, $0x0000000000ffffff -+DATA Β·andMask<>+0xb0(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0xb8(SB)/8, $0x00000000ffffffff -+DATA Β·andMask<>+0xc0(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0xc8(SB)/8, $0x000000ffffffffff -+DATA Β·andMask<>+0xd0(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff -+DATA Β·andMask<>+0xe0(SB)/8, $0xffffffffffffffff -+DATA Β·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff -+ -+GLOBL Β·chacha20Constants<>(SB), (NOPTR+RODATA), $32 -+GLOBL Β·rol16<>(SB), (NOPTR+RODATA), $32 -+GLOBL Β·rol8<>(SB), (NOPTR+RODATA), $32 -+GLOBL Β·sseIncMask<>(SB), (NOPTR+RODATA), $16 -+GLOBL Β·avx2IncMask<>(SB), (NOPTR+RODATA), $32 -+GLOBL Β·avx2InitMask<>(SB), (NOPTR+RODATA), $32 -+GLOBL Β·polyClampMask<>(SB), (NOPTR+RODATA), $32 -+GLOBL Β·andMask<>(SB), (NOPTR+RODATA), $240 -+// No PALIGNR in Go ASM yet (but VPALIGNR is present). -+#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3 -+#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4 -+#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5 -+#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13 -+#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6 -+#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7 -+#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8 -+#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14 -+#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9 -+#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10 -+#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11 -+#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15 -+#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3 -+#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4 -+#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5 -+#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13 -+#define shiftC0Right shiftC0Left -+#define shiftC1Right shiftC1Left -+#define shiftC2Right shiftC2Left -+#define shiftC3Right shiftC3Left -+#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9 -+#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10 -+#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11 -+#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15 -+// Some macros -+#define chachaQR(A, B, C, D, T) \ -+ PADDD B, A; PXOR A, D; PSHUFB Β·rol16<>(SB), D \ -+ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \ -+ PADDD B, A; PXOR A, D; PSHUFB Β·rol8<>(SB), D \ -+ PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B -+ -+#define chachaQR_AVX2(A, B, C, D, T) \ -+ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB Β·rol16<>(SB), D, D \ -+ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \ -+ VPADDD B, A, A; VPXOR A, D, D; VPSHUFB Β·rol8<>(SB), D, D \ -+ VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B -+ -+#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2 -+#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2 -+#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX -+#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3 -+#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t3, t2; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2 -+ -+#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2 -+#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3 -+#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3 -+ -+#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage -+#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage -+// ---------------------------------------------------------------------------- -+TEXT polyHashADInternal<>(SB), NOSPLIT, $0 -+ // adp points to beginning of additional data -+ // itr2 holds ad length -+ XORQ acc0, acc0 -+ XORQ acc1, acc1 -+ XORQ acc2, acc2 -+ CMPQ itr2, $13 -+ JNE hashADLoop -+ -+openFastTLSAD: -+ // Special treatment for the TLS case of 13 bytes -+ MOVQ (adp), acc0 -+ MOVQ 5(adp), acc1 -+ SHRQ $24, acc1 -+ MOVQ $1, acc2 -+ polyMul -+ RET -+ -+hashADLoop: -+ // Hash in 16 byte chunks -+ CMPQ itr2, $16 -+ JB hashADTail -+ polyAdd(0(adp)) -+ LEAQ (1*16)(adp), adp -+ SUBQ $16, itr2 -+ polyMul -+ JMP hashADLoop -+ -+hashADTail: -+ CMPQ itr2, $0 -+ JE hashADDone -+ -+ // Hash last < 16 byte tail -+ XORQ t0, t0 -+ XORQ t1, t1 -+ XORQ t2, t2 -+ ADDQ itr2, adp -+ -+hashADTailLoop: -+ SHLQ $8, t0, t1 -+ SHLQ $8, t0 -+ MOVB -1(adp), t2 -+ XORQ t2, t0 -+ DECQ adp -+ DECQ itr2 -+ JNE hashADTailLoop -+ -+hashADTailFinish: -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ -+ // Finished AD -+hashADDone: -+ RET -+ -+// ---------------------------------------------------------------------------- -+// func chacha20Poly1305Open(dst, key, src, ad []byte) bool -+TEXT Β·chacha20Poly1305Open(SB), 0, $288-97 -+ // For aligned stack access -+ MOVQ SP, BP -+ ADDQ $32, BP -+ ANDQ $-32, BP -+ MOVQ dst+0(FP), oup -+ MOVQ key+24(FP), keyp -+ MOVQ src+48(FP), inp -+ MOVQ src_len+56(FP), inl -+ MOVQ ad+72(FP), adp -+ -+ // Check for AVX2 support -+ CMPB Β·useAVX2(SB), $1 -+ JE chacha20Poly1305Open_AVX2 -+ -+ // Special optimization, for very short buffers -+ CMPQ inl, $128 -+ JBE openSSE128 // About 16% faster -+ -+ // For long buffers, prepare the poly key first -+ MOVOU Β·chacha20Constants<>(SB), A0 -+ MOVOU (1*16)(keyp), B0 -+ MOVOU (2*16)(keyp), C0 -+ MOVOU (3*16)(keyp), D0 -+ MOVO D0, T1 -+ -+ // Store state on stack for future use -+ MOVO B0, state1Store -+ MOVO C0, state2Store -+ MOVO D0, ctr3Store -+ MOVQ $10, itr2 -+ -+openSSEPreparePolyKey: -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ DECQ itr2 -+ JNE openSSEPreparePolyKey -+ -+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL state1Store, B0 -+ -+ // Clamp and store the key -+ PAND Β·polyClampMask<>(SB), A0 -+ MOVO A0, rStore; MOVO B0, sStore -+ -+ // Hash AAD -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+openSSEMainLoop: -+ CMPQ inl, $256 -+ JB openSSEMainLoopDone -+ -+ // Load state, increment counter blocks -+ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ -+ // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16 -+ MOVQ $4, itr1 -+ MOVQ inp, itr2 -+ -+openSSEInternalLoop: -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyAdd(0(itr2)) -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ polyMulStage1 -+ polyMulStage2 -+ LEAQ (2*8)(itr2), itr2 -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ polyMulStage3 -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyMulReduceStage -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ DECQ itr1 -+ JGE openSSEInternalLoop -+ -+ polyAdd(0(itr2)) -+ polyMul -+ LEAQ (2*8)(itr2), itr2 -+ -+ CMPQ itr1, $-6 -+ JG openSSEInternalLoop -+ -+ // Add in the state -+ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ -+ // Load - xor - store -+ MOVO D3, tmpStore -+ MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup) -+ MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup) -+ MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup) -+ MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup) -+ MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup) -+ MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup) -+ MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup) -+ MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup) -+ MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup) -+ MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup) -+ MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup) -+ MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup) -+ MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup) -+ MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup) -+ MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup) -+ MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup) -+ LEAQ 256(inp), inp -+ LEAQ 256(oup), oup -+ SUBQ $256, inl -+ JMP openSSEMainLoop -+ -+openSSEMainLoopDone: -+ // Handle the various tail sizes efficiently -+ TESTQ inl, inl -+ JE openSSEFinalize -+ CMPQ inl, $64 -+ JBE openSSETail64 -+ CMPQ inl, $128 -+ JBE openSSETail128 -+ CMPQ inl, $192 -+ JBE openSSETail192 -+ JMP openSSETail256 -+ -+openSSEFinalize: -+ // Hash in the PT, AAD lengths -+ ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2 -+ polyMul -+ -+ // Final reduce -+ MOVQ acc0, t0 -+ MOVQ acc1, t1 -+ MOVQ acc2, t2 -+ SUBQ $-5, acc0 -+ SBBQ $-1, acc1 -+ SBBQ $3, acc2 -+ CMOVQCS t0, acc0 -+ CMOVQCS t1, acc1 -+ CMOVQCS t2, acc2 -+ -+ // Add in the "s" part of the key -+ ADDQ 0+sStore, acc0 -+ ADCQ 8+sStore, acc1 -+ -+ // Finally, constant time compare to the tag at the end of the message -+ XORQ AX, AX -+ MOVQ $1, DX -+ XORQ (0*8)(inp), acc0 -+ XORQ (1*8)(inp), acc1 -+ ORQ acc1, acc0 -+ CMOVQEQ DX, AX -+ -+ // Return true iff tags are equal -+ MOVB AX, ret+96(FP) -+ RET -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 129 bytes -+openSSE128: -+ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks -+ MOVOU Β·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 -+ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 -+ MOVQ $10, itr2 -+ -+openSSE128InnerCipherLoop: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftB1Left; shiftB2Left -+ shiftC0Left; shiftC1Left; shiftC2Left -+ shiftD0Left; shiftD1Left; shiftD2Left -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftB1Right; shiftB2Right -+ shiftC0Right; shiftC1Right; shiftC2Right -+ shiftD0Right; shiftD1Right; shiftD2Right -+ DECQ itr2 -+ JNE openSSE128InnerCipherLoop -+ -+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 -+ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 -+ PADDL T2, C1; PADDL T2, C2 -+ PADDL T3, D1; PADDL Β·sseIncMask<>(SB), T3; PADDL T3, D2 -+ -+ // Clamp and store the key -+ PAND Β·polyClampMask<>(SB), A0 -+ MOVOU A0, rStore; MOVOU B0, sStore -+ -+ // Hash -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+openSSE128Open: -+ CMPQ inl, $16 -+ JB openSSETail16 -+ SUBQ $16, inl -+ -+ // Load for hashing -+ polyAdd(0(inp)) -+ -+ // Load for decryption -+ MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ polyMul -+ -+ // Shift the stream "left" -+ MOVO B1, A1 -+ MOVO C1, B1 -+ MOVO D1, C1 -+ MOVO A2, D1 -+ MOVO B2, A2 -+ MOVO C2, B2 -+ MOVO D2, C2 -+ JMP openSSE128Open -+ -+openSSETail16: -+ TESTQ inl, inl -+ JE openSSEFinalize -+ -+ // We can safely load the CT from the end, because it is padded with the MAC -+ MOVQ inl, itr2 -+ SHLQ $4, itr2 -+ LEAQ Β·andMask<>(SB), t0 -+ MOVOU (inp), T0 -+ ADDQ inl, inp -+ PAND -16(t0)(itr2*1), T0 -+ MOVO T0, 0+tmpStore -+ MOVQ T0, t0 -+ MOVQ 8+tmpStore, t1 -+ PXOR A1, T0 -+ -+ // We can only store one byte at a time, since plaintext can be shorter than 16 bytes -+openSSETail16Store: -+ MOVQ T0, t3 -+ MOVB t3, (oup) -+ PSRLDQ $1, T0 -+ INCQ oup -+ DECQ inl -+ JNE openSSETail16Store -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ JMP openSSEFinalize -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 64 bytes of ciphertext -+openSSETail64: -+ // Need to decrypt up to 64 bytes - prepare single block -+ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr0Store -+ XORQ itr2, itr2 -+ MOVQ inl, itr1 -+ CMPQ itr1, $16 -+ JB openSSETail64LoopB -+ -+openSSETail64LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ SUBQ $16, itr1 -+ -+openSSETail64LoopB: -+ ADDQ $16, itr2 -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ chachaQR(A0, B0, C0, D0, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ -+ CMPQ itr1, $16 -+ JAE openSSETail64LoopA -+ -+ CMPQ itr2, $160 -+ JNE openSSETail64LoopB -+ -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0 -+ -+openSSETail64DecLoop: -+ CMPQ inl, $16 -+ JB openSSETail64DecLoopDone -+ SUBQ $16, inl -+ MOVOU (inp), T0 -+ PXOR T0, A0 -+ MOVOU A0, (oup) -+ LEAQ 16(inp), inp -+ LEAQ 16(oup), oup -+ MOVO B0, A0 -+ MOVO C0, B0 -+ MOVO D0, C0 -+ JMP openSSETail64DecLoop -+ -+openSSETail64DecLoopDone: -+ MOVO A0, A1 -+ JMP openSSETail16 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of ciphertext -+openSSETail128: -+ // Need to decrypt up to 128 bytes - prepare two blocks -+ MOVO Β·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr0Store -+ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr1Store -+ XORQ itr2, itr2 -+ MOVQ inl, itr1 -+ ANDQ $-16, itr1 -+ -+openSSETail128LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ -+openSSETail128LoopB: -+ ADDQ $16, itr2 -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ -+ CMPQ itr2, itr1 -+ JB openSSETail128LoopA -+ -+ CMPQ itr2, $160 -+ JNE openSSETail128LoopB -+ -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1 -+ PADDL state1Store, B0; PADDL state1Store, B1 -+ PADDL state2Store, C0; PADDL state2Store, C1 -+ PADDL ctr1Store, D0; PADDL ctr0Store, D1 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 -+ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) -+ -+ SUBQ $64, inl -+ LEAQ 64(inp), inp -+ LEAQ 64(oup), oup -+ JMP openSSETail64DecLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 192 bytes of ciphertext -+openSSETail192: -+ // Need to decrypt up to 192 bytes - prepare three blocks -+ MOVO Β·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL Β·sseIncMask<>(SB), D2; MOVO D2, ctr0Store -+ MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr1Store -+ MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr2Store -+ -+ MOVQ inl, itr1 -+ MOVQ $160, itr2 -+ CMPQ itr1, $160 -+ CMOVQGT itr2, itr1 -+ ANDQ $-16, itr1 -+ XORQ itr2, itr2 -+ -+openSSLTail192LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ -+openSSLTail192LoopB: -+ ADDQ $16, itr2 -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ shiftB2Left; shiftC2Left; shiftD2Left -+ -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ shiftB2Right; shiftC2Right; shiftD2Right -+ -+ CMPQ itr2, itr1 -+ JB openSSLTail192LoopA -+ -+ CMPQ itr2, $160 -+ JNE openSSLTail192LoopB -+ -+ CMPQ inl, $176 -+ JB openSSLTail192Store -+ -+ polyAdd(160(inp)) -+ polyMul -+ -+ CMPQ inl, $192 -+ JB openSSLTail192Store -+ -+ polyAdd(176(inp)) -+ polyMul -+ -+openSSLTail192Store: -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 -+ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 -+ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 -+ PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2 -+ MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup) -+ -+ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 -+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ -+ SUBQ $128, inl -+ LEAQ 128(inp), inp -+ LEAQ 128(oup), oup -+ JMP openSSETail64DecLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 256 bytes of ciphertext -+openSSETail256: -+ // Need to decrypt up to 256 bytes - prepare four blocks -+ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ XORQ itr2, itr2 -+ -+openSSETail256Loop: -+ // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication -+ polyAdd(0(inp)(itr2*1)) -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ polyMulStage1 -+ polyMulStage2 -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyMulStage3 -+ polyMulReduceStage -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ ADDQ $2*8, itr2 -+ CMPQ itr2, $160 -+ JB openSSETail256Loop -+ MOVQ inl, itr1 -+ ANDQ $-16, itr1 -+ -+openSSETail256HashLoop: -+ polyAdd(0(inp)(itr2*1)) -+ polyMul -+ ADDQ $2*8, itr2 -+ CMPQ itr2, itr1 -+ JB openSSETail256HashLoop -+ -+ // Add in the state -+ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ MOVO D3, tmpStore -+ -+ // Load - xor - store -+ MOVOU (0*16)(inp), D3; PXOR D3, A0 -+ MOVOU (1*16)(inp), D3; PXOR D3, B0 -+ MOVOU (2*16)(inp), D3; PXOR D3, C0 -+ MOVOU (3*16)(inp), D3; PXOR D3, D0 -+ MOVOU A0, (0*16)(oup) -+ MOVOU B0, (1*16)(oup) -+ MOVOU C0, (2*16)(oup) -+ MOVOU D0, (3*16)(oup) -+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 -+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 -+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 -+ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) -+ LEAQ 192(inp), inp -+ LEAQ 192(oup), oup -+ SUBQ $192, inl -+ MOVO A3, A0 -+ MOVO B3, B0 -+ MOVO C3, C0 -+ MOVO tmpStore, D0 -+ -+ JMP openSSETail64DecLoop -+ -+// ---------------------------------------------------------------------------- -+// ------------------------- AVX2 Code ---------------------------------------- -+chacha20Poly1305Open_AVX2: -+ VZEROUPPER -+ VMOVDQU Β·chacha20Constants<>(SB), AA0 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 -+ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 -+ VPADDD Β·avx2InitMask<>(SB), DD0, DD0 -+ -+ // Special optimization, for very short buffers -+ CMPQ inl, $192 -+ JBE openAVX2192 -+ CMPQ inl, $320 -+ JBE openAVX2320 -+ -+ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream -+ VMOVDQA BB0, state1StoreAVX2 -+ VMOVDQA CC0, state2StoreAVX2 -+ VMOVDQA DD0, ctr3StoreAVX2 -+ MOVQ $10, itr2 -+ -+openAVX2PreparePolyKey: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 -+ DECQ itr2 -+ JNE openAVX2PreparePolyKey -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0 -+ VPADDD state1StoreAVX2, BB0, BB0 -+ VPADDD state2StoreAVX2, CC0, CC0 -+ VPADDD ctr3StoreAVX2, DD0, DD0 -+ -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ -+ // Clamp and store poly key -+ VPAND Β·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for the first 64 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ -+ // Hash AD + first 64 bytes -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ XORQ itr1, itr1 -+ -+openAVX2InitialHash64: -+ polyAdd(0(inp)(itr1*1)) -+ polyMulAVX2 -+ ADDQ $16, itr1 -+ CMPQ itr1, $64 -+ JNE openAVX2InitialHash64 -+ -+ // Decrypt the first 64 bytes -+ VPXOR (0*32)(inp), AA0, AA0 -+ VPXOR (1*32)(inp), BB0, BB0 -+ VMOVDQU AA0, (0*32)(oup) -+ VMOVDQU BB0, (1*32)(oup) -+ LEAQ (2*32)(inp), inp -+ LEAQ (2*32)(oup), oup -+ SUBQ $64, inl -+ -+openAVX2MainLoop: -+ CMPQ inl, $512 -+ JB openAVX2MainLoopDone -+ -+ // Load state, increment counter blocks, store the incremented counters -+ VMOVDQU Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ XORQ itr1, itr1 -+ -+openAVX2InternalLoop: -+ // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications -+ // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext -+ polyAdd(0*8(inp)(itr1*1)) -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage1_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ polyMulStage2_AVX2 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyMulStage3_AVX2 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ polyAdd(2*8(inp)(itr1*1)) -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage1_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage2_AVX2 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage3_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ polyMulReduceStage -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(4*8(inp)(itr1*1)) -+ LEAQ (6*8)(itr1), itr1 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage1_AVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ polyMulStage2_AVX2 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage3_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ CMPQ itr1, $480 -+ JNE openAVX2InternalLoop -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ -+ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here -+ polyAdd(480(inp)) -+ polyMulAVX2 -+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 -+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 -+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ -+ // and here -+ polyAdd(496(inp)) -+ polyMulAVX2 -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) -+ LEAQ (32*16)(inp), inp -+ LEAQ (32*16)(oup), oup -+ SUBQ $(32*16), inl -+ JMP openAVX2MainLoop -+ -+openAVX2MainLoopDone: -+ // Handle the various tail sizes efficiently -+ TESTQ inl, inl -+ JE openSSEFinalize -+ CMPQ inl, $128 -+ JBE openAVX2Tail128 -+ CMPQ inl, $256 -+ JBE openAVX2Tail256 -+ CMPQ inl, $384 -+ JBE openAVX2Tail384 -+ JMP openAVX2Tail512 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 193 bytes -+openAVX2192: -+ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks -+ VMOVDQA AA0, AA1 -+ VMOVDQA BB0, BB1 -+ VMOVDQA CC0, CC1 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2 -+ VMOVDQA BB0, BB2 -+ VMOVDQA CC0, CC2 -+ VMOVDQA DD0, DD2 -+ VMOVDQA DD1, TT3 -+ MOVQ $10, itr2 -+ -+openAVX2192InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ DECQ itr2 -+ JNE openAVX2192InnerCipherLoop -+ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 -+ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 -+ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 -+ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ -+ // Clamp and store poly key -+ VPAND Β·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 192 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ -+openAVX2ShortOpen: -+ // Hash -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+openAVX2ShortOpenLoop: -+ CMPQ inl, $32 -+ JB openAVX2ShortTail32 -+ SUBQ $32, inl -+ -+ // Load for hashing -+ polyAdd(0*8(inp)) -+ polyMulAVX2 -+ polyAdd(2*8(inp)) -+ polyMulAVX2 -+ -+ // Load for decryption -+ VPXOR (inp), AA0, AA0 -+ VMOVDQU AA0, (oup) -+ LEAQ (1*32)(inp), inp -+ LEAQ (1*32)(oup), oup -+ -+ // Shift stream left -+ VMOVDQA BB0, AA0 -+ VMOVDQA CC0, BB0 -+ VMOVDQA DD0, CC0 -+ VMOVDQA AA1, DD0 -+ VMOVDQA BB1, AA1 -+ VMOVDQA CC1, BB1 -+ VMOVDQA DD1, CC1 -+ VMOVDQA AA2, DD1 -+ VMOVDQA BB2, AA2 -+ JMP openAVX2ShortOpenLoop -+ -+openAVX2ShortTail32: -+ CMPQ inl, $16 -+ VMOVDQA A0, A1 -+ JB openAVX2ShortDone -+ -+ SUBQ $16, inl -+ -+ // Load for hashing -+ polyAdd(0*8(inp)) -+ polyMulAVX2 -+ -+ // Load for decryption -+ VPXOR (inp), A0, T0 -+ VMOVDQU T0, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ VPERM2I128 $0x11, AA0, AA0, AA0 -+ VMOVDQA A0, A1 -+ -+openAVX2ShortDone: -+ VZEROUPPER -+ JMP openSSETail16 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 321 bytes -+openAVX2320: -+ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks -+ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD Β·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 -+ MOVQ $10, itr2 -+ -+openAVX2320InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ DECQ itr2 -+ JNE openAVX2320InnerCipherLoop -+ -+ VMOVDQA Β·chacha20Constants<>(SB), TT0 -+ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 -+ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 -+ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 -+ VMOVDQA Β·avx2IncMask<>(SB), TT0 -+ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD2, DD2 -+ -+ // Clamp and store poly key -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPAND Β·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 320 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ VPERM2I128 $0x02, AA2, BB2, CC1 -+ VPERM2I128 $0x02, CC2, DD2, DD1 -+ VPERM2I128 $0x13, AA2, BB2, AA2 -+ VPERM2I128 $0x13, CC2, DD2, BB2 -+ JMP openAVX2ShortOpen -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of ciphertext -+openAVX2Tail128: -+ // Need to decrypt up to 128 bytes - prepare two blocks -+ VMOVDQA Β·chacha20Constants<>(SB), AA1 -+ VMOVDQA state1StoreAVX2, BB1 -+ VMOVDQA state2StoreAVX2, CC1 -+ VMOVDQA ctr3StoreAVX2, DD1 -+ VPADDD Β·avx2IncMask<>(SB), DD1, DD1 -+ VMOVDQA DD1, DD0 -+ -+ XORQ itr2, itr2 -+ MOVQ inl, itr1 -+ ANDQ $-16, itr1 -+ TESTQ itr1, itr1 -+ JE openAVX2Tail128LoopB -+ -+openAVX2Tail128LoopA: -+ // Perform ChaCha rounds, while hashing the remaining input -+ polyAdd(0(inp)(itr2*1)) -+ polyMulAVX2 -+ -+openAVX2Tail128LoopB: -+ ADDQ $16, itr2 -+ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD1, DD1, DD1 -+ CMPQ itr2, itr1 -+ JB openAVX2Tail128LoopA -+ CMPQ itr2, $160 -+ JNE openAVX2Tail128LoopB -+ -+ VPADDD Β·chacha20Constants<>(SB), AA1, AA1 -+ VPADDD state1StoreAVX2, BB1, BB1 -+ VPADDD state2StoreAVX2, CC1, CC1 -+ VPADDD DD0, DD1, DD1 -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ -+openAVX2TailLoop: -+ CMPQ inl, $32 -+ JB openAVX2Tail -+ SUBQ $32, inl -+ -+ // Load for decryption -+ VPXOR (inp), AA0, AA0 -+ VMOVDQU AA0, (oup) -+ LEAQ (1*32)(inp), inp -+ LEAQ (1*32)(oup), oup -+ VMOVDQA BB0, AA0 -+ VMOVDQA CC0, BB0 -+ VMOVDQA DD0, CC0 -+ JMP openAVX2TailLoop -+ -+openAVX2Tail: -+ CMPQ inl, $16 -+ VMOVDQA A0, A1 -+ JB openAVX2TailDone -+ SUBQ $16, inl -+ -+ // Load for decryption -+ VPXOR (inp), A0, T0 -+ VMOVDQU T0, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ VPERM2I128 $0x11, AA0, AA0, AA0 -+ VMOVDQA A0, A1 -+ -+openAVX2TailDone: -+ VZEROUPPER -+ JMP openSSETail16 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 256 bytes of ciphertext -+openAVX2Tail256: -+ // Need to decrypt up to 256 bytes - prepare four blocks -+ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA DD0, TT1 -+ VMOVDQA DD1, TT2 -+ -+ // Compute the number of iterations that will hash data -+ MOVQ inl, tmpStoreAVX2 -+ MOVQ inl, itr1 -+ SUBQ $128, itr1 -+ SHRQ $4, itr1 -+ MOVQ $10, itr2 -+ CMPQ itr1, $10 -+ CMOVQGT itr2, itr1 -+ MOVQ inp, inl -+ XORQ itr2, itr2 -+ -+openAVX2Tail256LoopA: -+ polyAdd(0(inl)) -+ polyMulAVX2 -+ LEAQ 16(inl), inl -+ -+ // Perform ChaCha rounds, while hashing the remaining input -+openAVX2Tail256LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ INCQ itr2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ CMPQ itr2, itr1 -+ JB openAVX2Tail256LoopA -+ -+ CMPQ itr2, $10 -+ JNE openAVX2Tail256LoopB -+ -+ MOVQ inl, itr2 -+ SUBQ inp, inl -+ MOVQ inl, itr1 -+ MOVQ tmpStoreAVX2, inl -+ -+ // Hash the remainder of data (if any) -+openAVX2Tail256Hash: -+ ADDQ $16, itr1 -+ CMPQ itr1, inl -+ JGT openAVX2Tail256HashEnd -+ polyAdd (0(itr2)) -+ polyMulAVX2 -+ LEAQ 16(itr2), itr2 -+ JMP openAVX2Tail256Hash -+ -+// Store 128 bytes safely, then go to store loop -+openAVX2Tail256HashEnd: -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 -+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2 -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ -+ VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2 -+ VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup) -+ LEAQ (4*32)(inp), inp -+ LEAQ (4*32)(oup), oup -+ SUBQ $4*32, inl -+ -+ JMP openAVX2TailLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 384 bytes of ciphertext -+openAVX2Tail384: -+ // Need to decrypt up to 384 bytes - prepare six blocks -+ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VPADDD Β·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA DD0, ctr0StoreAVX2 -+ VMOVDQA DD1, ctr1StoreAVX2 -+ VMOVDQA DD2, ctr2StoreAVX2 -+ -+ // Compute the number of iterations that will hash two blocks of data -+ MOVQ inl, tmpStoreAVX2 -+ MOVQ inl, itr1 -+ SUBQ $256, itr1 -+ SHRQ $4, itr1 -+ ADDQ $6, itr1 -+ MOVQ $10, itr2 -+ CMPQ itr1, $10 -+ CMOVQGT itr2, itr1 -+ MOVQ inp, inl -+ XORQ itr2, itr2 -+ -+ // Perform ChaCha rounds, while hashing the remaining input -+openAVX2Tail384LoopB: -+ polyAdd(0(inl)) -+ polyMulAVX2 -+ LEAQ 16(inl), inl -+ -+openAVX2Tail384LoopA: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ polyAdd(0(inl)) -+ polyMulAVX2 -+ LEAQ 16(inl), inl -+ INCQ itr2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ -+ CMPQ itr2, itr1 -+ JB openAVX2Tail384LoopB -+ -+ CMPQ itr2, $10 -+ JNE openAVX2Tail384LoopA -+ -+ MOVQ inl, itr2 -+ SUBQ inp, inl -+ MOVQ inl, itr1 -+ MOVQ tmpStoreAVX2, inl -+ -+openAVX2Tail384Hash: -+ ADDQ $16, itr1 -+ CMPQ itr1, inl -+ JGT openAVX2Tail384HashEnd -+ polyAdd(0(itr2)) -+ polyMulAVX2 -+ LEAQ 16(itr2), itr2 -+ JMP openAVX2Tail384Hash -+ -+// Store 256 bytes safely, then go to store loop -+openAVX2Tail384HashEnd: -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2 -+ VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3 -+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3 -+ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ LEAQ (8*32)(inp), inp -+ LEAQ (8*32)(oup), oup -+ SUBQ $8*32, inl -+ JMP openAVX2TailLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 512 bytes of ciphertext -+openAVX2Tail512: -+ VMOVDQU Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ XORQ itr1, itr1 -+ MOVQ inp, itr2 -+ -+openAVX2Tail512LoopB: -+ polyAdd(0(itr2)) -+ polyMulAVX2 -+ LEAQ (2*8)(itr2), itr2 -+ -+openAVX2Tail512LoopA: -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyAdd(0*8(itr2)) -+ polyMulAVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(2*8(itr2)) -+ polyMulAVX2 -+ LEAQ (4*8)(itr2), itr2 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ INCQ itr1 -+ CMPQ itr1, $4 -+ JLT openAVX2Tail512LoopB -+ -+ CMPQ itr1, $10 -+ JNE openAVX2Tail512LoopA -+ -+ MOVQ inl, itr1 -+ SUBQ $384, itr1 -+ ANDQ $-16, itr1 -+ -+openAVX2Tail512HashLoop: -+ TESTQ itr1, itr1 -+ JE openAVX2Tail512HashEnd -+ polyAdd(0(itr2)) -+ polyMulAVX2 -+ LEAQ 16(itr2), itr2 -+ SUBQ $16, itr1 -+ JMP openAVX2Tail512HashLoop -+ -+openAVX2Tail512HashEnd: -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 -+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 -+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ -+ LEAQ (12*32)(inp), inp -+ LEAQ (12*32)(oup), oup -+ SUBQ $12*32, inl -+ -+ JMP openAVX2TailLoop -+ -+// ---------------------------------------------------------------------------- -+// ---------------------------------------------------------------------------- -+// func chacha20Poly1305Seal(dst, key, src, ad []byte) -+TEXT Β·chacha20Poly1305Seal(SB), 0, $288-96 -+ // For aligned stack access -+ MOVQ SP, BP -+ ADDQ $32, BP -+ ANDQ $-32, BP -+ MOVQ dst+0(FP), oup -+ MOVQ key+24(FP), keyp -+ MOVQ src+48(FP), inp -+ MOVQ src_len+56(FP), inl -+ MOVQ ad+72(FP), adp -+ -+ CMPB Β·useAVX2(SB), $1 -+ JE chacha20Poly1305Seal_AVX2 -+ -+ // Special optimization, for very short buffers -+ CMPQ inl, $128 -+ JBE sealSSE128 // About 15% faster -+ -+ // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration -+ MOVOU Β·chacha20Constants<>(SB), A0 -+ MOVOU (1*16)(keyp), B0 -+ MOVOU (2*16)(keyp), C0 -+ MOVOU (3*16)(keyp), D0 -+ -+ // Store state on stack for future use -+ MOVO B0, state1Store -+ MOVO C0, state2Store -+ -+ // Load state, increment counter blocks -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ MOVQ $10, itr2 -+ -+sealSSEIntroLoop: -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ DECQ itr2 -+ JNE sealSSEIntroLoop -+ -+ // Add in the state -+ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ -+ // Clamp and store the key -+ PAND Β·polyClampMask<>(SB), A0 -+ MOVO A0, rStore -+ MOVO B0, sStore -+ -+ // Hash AAD -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 -+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 -+ MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) -+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 -+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 -+ MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup) -+ -+ MOVQ $128, itr1 -+ SUBQ $128, inl -+ LEAQ 128(inp), inp -+ -+ MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1 -+ -+ CMPQ inl, $64 -+ JBE sealSSE128SealHash -+ -+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 -+ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 -+ MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup) -+ -+ ADDQ $64, itr1 -+ SUBQ $64, inl -+ LEAQ 64(inp), inp -+ -+ MOVQ $2, itr1 -+ MOVQ $8, itr2 -+ -+ CMPQ inl, $64 -+ JBE sealSSETail64 -+ CMPQ inl, $128 -+ JBE sealSSETail128 -+ CMPQ inl, $192 -+ JBE sealSSETail192 -+ -+sealSSEMainLoop: -+ // Load state, increment counter blocks -+ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 -+ MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL Β·sseIncMask<>(SB), D3 -+ -+ // Store counters -+ MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store -+ -+sealSSEInnerLoop: -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyAdd(0(oup)) -+ shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left -+ shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left -+ shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left -+ polyMulStage1 -+ polyMulStage2 -+ LEAQ (2*8)(oup), oup -+ MOVO C3, tmpStore -+ chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) -+ MOVO tmpStore, C3 -+ MOVO C1, tmpStore -+ polyMulStage3 -+ chachaQR(A3, B3, C3, D3, C1) -+ MOVO tmpStore, C1 -+ polyMulReduceStage -+ shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right -+ shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right -+ shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right -+ DECQ itr2 -+ JGE sealSSEInnerLoop -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ (2*8)(oup), oup -+ DECQ itr1 -+ JG sealSSEInnerLoop -+ -+ // Add in the state -+ PADDD Β·chacha20Constants<>(SB), A0; PADDD Β·chacha20Constants<>(SB), A1; PADDD Β·chacha20Constants<>(SB), A2; PADDD Β·chacha20Constants<>(SB), A3 -+ PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 -+ PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 -+ PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 -+ MOVO D3, tmpStore -+ -+ // Load - xor - store -+ MOVOU (0*16)(inp), D3; PXOR D3, A0 -+ MOVOU (1*16)(inp), D3; PXOR D3, B0 -+ MOVOU (2*16)(inp), D3; PXOR D3, C0 -+ MOVOU (3*16)(inp), D3; PXOR D3, D0 -+ MOVOU A0, (0*16)(oup) -+ MOVOU B0, (1*16)(oup) -+ MOVOU C0, (2*16)(oup) -+ MOVOU D0, (3*16)(oup) -+ MOVO tmpStore, D3 -+ -+ MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 -+ PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 -+ PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 -+ MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) -+ ADDQ $192, inp -+ MOVQ $192, itr1 -+ SUBQ $192, inl -+ MOVO A3, A1 -+ MOVO B3, B1 -+ MOVO C3, C1 -+ MOVO D3, D1 -+ CMPQ inl, $64 -+ JBE sealSSE128SealHash -+ MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 -+ PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 -+ MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup) -+ LEAQ 64(inp), inp -+ SUBQ $64, inl -+ MOVQ $6, itr1 -+ MOVQ $4, itr2 -+ CMPQ inl, $192 -+ JG sealSSEMainLoop -+ -+ MOVQ inl, itr1 -+ TESTQ inl, inl -+ JE sealSSE128SealHash -+ MOVQ $6, itr1 -+ CMPQ inl, $64 -+ JBE sealSSETail64 -+ CMPQ inl, $128 -+ JBE sealSSETail128 -+ JMP sealSSETail192 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 64 bytes of plaintext -+sealSSETail64: -+ // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes -+ MOVO Β·chacha20Constants<>(SB), A1 -+ MOVO state1Store, B1 -+ MOVO state2Store, C1 -+ MOVO ctr3Store, D1 -+ PADDL Β·sseIncMask<>(SB), D1 -+ MOVO D1, ctr0Store -+ -+sealSSETail64LoopA: -+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealSSETail64LoopB: -+ chachaQR(A1, B1, C1, D1, T1) -+ shiftB1Left; shiftC1Left; shiftD1Left -+ chachaQR(A1, B1, C1, D1, T1) -+ shiftB1Right; shiftC1Right; shiftD1Right -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+ DECQ itr1 -+ JG sealSSETail64LoopA -+ -+ DECQ itr2 -+ JGE sealSSETail64LoopB -+ PADDL Β·chacha20Constants<>(SB), A1 -+ PADDL state1Store, B1 -+ PADDL state2Store, C1 -+ PADDL ctr0Store, D1 -+ -+ JMP sealSSE128Seal -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of plaintext -+sealSSETail128: -+ // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes -+ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr0Store -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr1Store -+ -+sealSSETail128LoopA: -+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealSSETail128LoopB: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ -+ DECQ itr1 -+ JG sealSSETail128LoopA -+ -+ DECQ itr2 -+ JGE sealSSETail128LoopB -+ -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1 -+ PADDL state1Store, B0; PADDL state1Store, B1 -+ PADDL state2Store, C0; PADDL state2Store, C1 -+ PADDL ctr0Store, D0; PADDL ctr1Store, D1 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 -+ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) -+ -+ MOVQ $64, itr1 -+ LEAQ 64(inp), inp -+ SUBQ $64, inl -+ -+ JMP sealSSE128SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 192 bytes of plaintext -+sealSSETail192: -+ // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes -+ MOVO Β·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL Β·sseIncMask<>(SB), D0; MOVO D0, ctr0Store -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1; MOVO D1, ctr1Store -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2; MOVO D2, ctr2Store -+ -+sealSSETail192LoopA: -+ // Perform ChaCha rounds, while hashing the previously encrypted ciphertext -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealSSETail192LoopB: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftC0Left; shiftD0Left -+ shiftB1Left; shiftC1Left; shiftD1Left -+ shiftB2Left; shiftC2Left; shiftD2Left -+ -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftC0Right; shiftD0Right -+ shiftB1Right; shiftC1Right; shiftD1Right -+ shiftB2Right; shiftC2Right; shiftD2Right -+ -+ DECQ itr1 -+ JG sealSSETail192LoopA -+ -+ DECQ itr2 -+ JGE sealSSETail192LoopB -+ -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 -+ PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 -+ PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 -+ PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2 -+ -+ MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 -+ PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 -+ MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) -+ MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 -+ PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 -+ MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) -+ -+ MOVO A2, A1 -+ MOVO B2, B1 -+ MOVO C2, C1 -+ MOVO D2, D1 -+ MOVQ $128, itr1 -+ LEAQ 128(inp), inp -+ SUBQ $128, inl -+ -+ JMP sealSSE128SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special seal optimization for buffers smaller than 129 bytes -+sealSSE128: -+ // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks -+ MOVOU Β·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 -+ MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL Β·sseIncMask<>(SB), D1 -+ MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL Β·sseIncMask<>(SB), D2 -+ MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 -+ MOVQ $10, itr2 -+ -+sealSSE128InnerCipherLoop: -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Left; shiftB1Left; shiftB2Left -+ shiftC0Left; shiftC1Left; shiftC2Left -+ shiftD0Left; shiftD1Left; shiftD2Left -+ chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) -+ shiftB0Right; shiftB1Right; shiftB2Right -+ shiftC0Right; shiftC1Right; shiftC2Right -+ shiftD0Right; shiftD1Right; shiftD2Right -+ DECQ itr2 -+ JNE sealSSE128InnerCipherLoop -+ -+ // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded -+ PADDL Β·chacha20Constants<>(SB), A0; PADDL Β·chacha20Constants<>(SB), A1; PADDL Β·chacha20Constants<>(SB), A2 -+ PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 -+ PADDL T2, C1; PADDL T2, C2 -+ PADDL T3, D1; PADDL Β·sseIncMask<>(SB), T3; PADDL T3, D2 -+ PAND Β·polyClampMask<>(SB), A0 -+ MOVOU A0, rStore -+ MOVOU B0, sStore -+ -+ // Hash -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ XORQ itr1, itr1 -+ -+sealSSE128SealHash: -+ // itr1 holds the number of bytes encrypted but not yet hashed -+ CMPQ itr1, $16 -+ JB sealSSE128Seal -+ polyAdd(0(oup)) -+ polyMul -+ -+ SUBQ $16, itr1 -+ ADDQ $16, oup -+ -+ JMP sealSSE128SealHash -+ -+sealSSE128Seal: -+ CMPQ inl, $16 -+ JB sealSSETail -+ SUBQ $16, inl -+ -+ // Load for decryption -+ MOVOU (inp), T0 -+ PXOR T0, A1 -+ MOVOU A1, (oup) -+ LEAQ (1*16)(inp), inp -+ LEAQ (1*16)(oup), oup -+ -+ // Extract for hashing -+ MOVQ A1, t0 -+ PSRLDQ $8, A1 -+ MOVQ A1, t1 -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ -+ // Shift the stream "left" -+ MOVO B1, A1 -+ MOVO C1, B1 -+ MOVO D1, C1 -+ MOVO A2, D1 -+ MOVO B2, A2 -+ MOVO C2, B2 -+ MOVO D2, C2 -+ JMP sealSSE128Seal -+ -+sealSSETail: -+ TESTQ inl, inl -+ JE sealSSEFinalize -+ -+ // We can only load the PT one byte at a time to avoid read after end of buffer -+ MOVQ inl, itr2 -+ SHLQ $4, itr2 -+ LEAQ Β·andMask<>(SB), t0 -+ MOVQ inl, itr1 -+ LEAQ -1(inp)(inl*1), inp -+ XORQ t2, t2 -+ XORQ t3, t3 -+ XORQ AX, AX -+ -+sealSSETailLoadLoop: -+ SHLQ $8, t2, t3 -+ SHLQ $8, t2 -+ MOVB (inp), AX -+ XORQ AX, t2 -+ LEAQ -1(inp), inp -+ DECQ itr1 -+ JNE sealSSETailLoadLoop -+ MOVQ t2, 0+tmpStore -+ MOVQ t3, 8+tmpStore -+ PXOR 0+tmpStore, A1 -+ MOVOU A1, (oup) -+ MOVOU -16(t0)(itr2*1), T0 -+ PAND T0, A1 -+ MOVQ A1, t0 -+ PSRLDQ $8, A1 -+ MOVQ A1, t1 -+ ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 -+ polyMul -+ -+ ADDQ inl, oup -+ -+sealSSEFinalize: -+ // Hash in the buffer lengths -+ ADDQ ad_len+80(FP), acc0 -+ ADCQ src_len+56(FP), acc1 -+ ADCQ $1, acc2 -+ polyMul -+ -+ // Final reduce -+ MOVQ acc0, t0 -+ MOVQ acc1, t1 -+ MOVQ acc2, t2 -+ SUBQ $-5, acc0 -+ SBBQ $-1, acc1 -+ SBBQ $3, acc2 -+ CMOVQCS t0, acc0 -+ CMOVQCS t1, acc1 -+ CMOVQCS t2, acc2 -+ -+ // Add in the "s" part of the key -+ ADDQ 0+sStore, acc0 -+ ADCQ 8+sStore, acc1 -+ -+ // Finally store the tag at the end of the message -+ MOVQ acc0, (0*8)(oup) -+ MOVQ acc1, (1*8)(oup) -+ RET -+ -+// ---------------------------------------------------------------------------- -+// ------------------------- AVX2 Code ---------------------------------------- -+chacha20Poly1305Seal_AVX2: -+ VZEROUPPER -+ VMOVDQU Β·chacha20Constants<>(SB), AA0 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 -+ BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 -+ BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 -+ VPADDD Β·avx2InitMask<>(SB), DD0, DD0 -+ -+ // Special optimizations, for very short buffers -+ CMPQ inl, $192 -+ JBE seal192AVX2 // 33% faster -+ CMPQ inl, $320 -+ JBE seal320AVX2 // 17% faster -+ -+ // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream -+ VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2 -+ VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2 -+ VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2 -+ VPADDD Β·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2 -+ VMOVDQA DD3, ctr3StoreAVX2 -+ MOVQ $10, itr2 -+ -+sealAVX2IntroLoop: -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 -+ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 -+ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 -+ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 -+ -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 -+ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 -+ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 -+ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 -+ DECQ itr2 -+ JNE sealAVX2IntroLoop -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ -+ VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127 -+ VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key -+ VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95 -+ -+ // Clamp and store poly key -+ VPAND Β·polyClampMask<>(SB), DD0, DD0 -+ VMOVDQA DD0, rsStoreAVX2 -+ -+ // Hash AD -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ -+ // Can store at least 320 bytes -+ VPXOR (0*32)(inp), AA0, AA0 -+ VPXOR (1*32)(inp), CC0, CC0 -+ VMOVDQU AA0, (0*32)(oup) -+ VMOVDQU CC0, (1*32)(oup) -+ -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup) -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup) -+ -+ MOVQ $320, itr1 -+ SUBQ $320, inl -+ LEAQ 320(inp), inp -+ -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0 -+ CMPQ inl, $128 -+ JBE sealAVX2SealHash -+ -+ VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup) -+ SUBQ $128, inl -+ LEAQ 128(inp), inp -+ -+ MOVQ $8, itr1 -+ MOVQ $2, itr2 -+ -+ CMPQ inl, $128 -+ JBE sealAVX2Tail128 -+ CMPQ inl, $256 -+ JBE sealAVX2Tail256 -+ CMPQ inl, $384 -+ JBE sealAVX2Tail384 -+ CMPQ inl, $512 -+ JBE sealAVX2Tail512 -+ -+ // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop -+ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 -+ VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 -+ VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 -+ VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 -+ -+ VMOVDQA CC3, tmpStoreAVX2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) -+ VMOVDQA tmpStoreAVX2, CC3 -+ VMOVDQA CC1, tmpStoreAVX2 -+ chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) -+ VMOVDQA tmpStoreAVX2, CC1 -+ -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 -+ VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 -+ VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 -+ VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ -+ SUBQ $16, oup // Adjust the pointer -+ MOVQ $9, itr1 -+ JMP sealAVX2InternalLoopStart -+ -+sealAVX2MainLoop: -+ // Load state, increment counter blocks, store the incremented counters -+ VMOVDQU Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ MOVQ $10, itr1 -+ -+sealAVX2InternalLoop: -+ polyAdd(0*8(oup)) -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage1_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ polyMulStage2_AVX2 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyMulStage3_AVX2 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ -+sealAVX2InternalLoopStart: -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ polyAdd(2*8(oup)) -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage1_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage2_AVX2 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ polyMulStage3_AVX2 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ polyMulReduceStage -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(4*8(oup)) -+ LEAQ (6*8)(oup), oup -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulStage1_AVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ polyMulStage2_AVX2 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ polyMulStage3_AVX2 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyMulReduceStage -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ DECQ itr1 -+ JNE sealAVX2InternalLoop -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ -+ // We only hashed 480 of the 512 bytes available - hash the remaining 32 here -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ LEAQ (4*8)(oup), oup -+ VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 -+ VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 -+ VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ -+ // and here -+ polyAdd(-2*8(oup)) -+ polyMulAVX2 -+ VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) -+ LEAQ (32*16)(inp), inp -+ SUBQ $(32*16), inl -+ CMPQ inl, $512 -+ JG sealAVX2MainLoop -+ -+ // Tail can only hash 480 bytes -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ polyAdd(2*8(oup)) -+ polyMulAVX2 -+ LEAQ 32(oup), oup -+ -+ MOVQ $10, itr1 -+ MOVQ $0, itr2 -+ CMPQ inl, $128 -+ JBE sealAVX2Tail128 -+ CMPQ inl, $256 -+ JBE sealAVX2Tail256 -+ CMPQ inl, $384 -+ JBE sealAVX2Tail384 -+ JMP sealAVX2Tail512 -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 193 bytes -+seal192AVX2: -+ // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks -+ VMOVDQA AA0, AA1 -+ VMOVDQA BB0, BB1 -+ VMOVDQA CC0, CC1 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2 -+ VMOVDQA BB0, BB2 -+ VMOVDQA CC0, CC2 -+ VMOVDQA DD0, DD2 -+ VMOVDQA DD1, TT3 -+ MOVQ $10, itr2 -+ -+sealAVX2192InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ DECQ itr2 -+ JNE sealAVX2192InnerCipherLoop -+ VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 -+ VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 -+ VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 -+ VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ -+ // Clamp and store poly key -+ VPAND Β·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 192 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ -+sealAVX2ShortSeal: -+ // Hash aad -+ MOVQ ad_len+80(FP), itr2 -+ CALL polyHashADInternal<>(SB) -+ XORQ itr1, itr1 -+ -+sealAVX2SealHash: -+ // itr1 holds the number of bytes encrypted but not yet hashed -+ CMPQ itr1, $16 -+ JB sealAVX2ShortSealLoop -+ polyAdd(0(oup)) -+ polyMul -+ SUBQ $16, itr1 -+ ADDQ $16, oup -+ JMP sealAVX2SealHash -+ -+sealAVX2ShortSealLoop: -+ CMPQ inl, $32 -+ JB sealAVX2ShortTail32 -+ SUBQ $32, inl -+ -+ // Load for encryption -+ VPXOR (inp), AA0, AA0 -+ VMOVDQU AA0, (oup) -+ LEAQ (1*32)(inp), inp -+ -+ // Now can hash -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ polyAdd(2*8(oup)) -+ polyMulAVX2 -+ LEAQ (1*32)(oup), oup -+ -+ // Shift stream left -+ VMOVDQA BB0, AA0 -+ VMOVDQA CC0, BB0 -+ VMOVDQA DD0, CC0 -+ VMOVDQA AA1, DD0 -+ VMOVDQA BB1, AA1 -+ VMOVDQA CC1, BB1 -+ VMOVDQA DD1, CC1 -+ VMOVDQA AA2, DD1 -+ VMOVDQA BB2, AA2 -+ JMP sealAVX2ShortSealLoop -+ -+sealAVX2ShortTail32: -+ CMPQ inl, $16 -+ VMOVDQA A0, A1 -+ JB sealAVX2ShortDone -+ -+ SUBQ $16, inl -+ -+ // Load for encryption -+ VPXOR (inp), A0, T0 -+ VMOVDQU T0, (oup) -+ LEAQ (1*16)(inp), inp -+ -+ // Hash -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ LEAQ (1*16)(oup), oup -+ VPERM2I128 $0x11, AA0, AA0, AA0 -+ VMOVDQA A0, A1 -+ -+sealAVX2ShortDone: -+ VZEROUPPER -+ JMP sealSSETail -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for buffers smaller than 321 bytes -+seal320AVX2: -+ // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks -+ VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD Β·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 -+ MOVQ $10, itr2 -+ -+sealAVX2320InnerCipherLoop: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ DECQ itr2 -+ JNE sealAVX2320InnerCipherLoop -+ -+ VMOVDQA Β·chacha20Constants<>(SB), TT0 -+ VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 -+ VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 -+ VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 -+ VMOVDQA Β·avx2IncMask<>(SB), TT0 -+ VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 -+ VPADDD TT3, DD2, DD2 -+ -+ // Clamp and store poly key -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPAND Β·polyClampMask<>(SB), TT0, TT0 -+ VMOVDQA TT0, rsStoreAVX2 -+ -+ // Stream for up to 320 bytes -+ VPERM2I128 $0x13, AA0, BB0, AA0 -+ VPERM2I128 $0x13, CC0, DD0, BB0 -+ VPERM2I128 $0x02, AA1, BB1, CC0 -+ VPERM2I128 $0x02, CC1, DD1, DD0 -+ VPERM2I128 $0x13, AA1, BB1, AA1 -+ VPERM2I128 $0x13, CC1, DD1, BB1 -+ VPERM2I128 $0x02, AA2, BB2, CC1 -+ VPERM2I128 $0x02, CC2, DD2, DD1 -+ VPERM2I128 $0x13, AA2, BB2, AA2 -+ VPERM2I128 $0x13, CC2, DD2, BB2 -+ JMP sealAVX2ShortSeal -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 128 bytes of ciphertext -+sealAVX2Tail128: -+ // Need to decrypt up to 128 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA Β·chacha20Constants<>(SB), AA0 -+ VMOVDQA state1StoreAVX2, BB0 -+ VMOVDQA state2StoreAVX2, CC0 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 -+ VMOVDQA DD0, DD1 -+ -+sealAVX2Tail128LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail128LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ polyAdd(0(oup)) -+ polyMul -+ VPALIGNR $4, BB0, BB0, BB0 -+ VPALIGNR $8, CC0, CC0, CC0 -+ VPALIGNR $12, DD0, DD0, DD0 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) -+ polyAdd(16(oup)) -+ polyMul -+ LEAQ 32(oup), oup -+ VPALIGNR $12, BB0, BB0, BB0 -+ VPALIGNR $8, CC0, CC0, CC0 -+ VPALIGNR $4, DD0, DD0, DD0 -+ DECQ itr1 -+ JG sealAVX2Tail128LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail128LoopB -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA1 -+ VPADDD state1StoreAVX2, BB0, BB1 -+ VPADDD state2StoreAVX2, CC0, CC1 -+ VPADDD DD1, DD0, DD1 -+ -+ VPERM2I128 $0x02, AA1, BB1, AA0 -+ VPERM2I128 $0x02, CC1, DD1, BB0 -+ VPERM2I128 $0x13, AA1, BB1, CC0 -+ VPERM2I128 $0x13, CC1, DD1, DD0 -+ JMP sealAVX2ShortSealLoop -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 256 bytes of ciphertext -+sealAVX2Tail256: -+ // Need to decrypt up to 256 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA Β·chacha20Constants<>(SB), AA1 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD1 -+ VMOVDQA DD0, TT1 -+ VMOVDQA DD1, TT2 -+ -+sealAVX2Tail256LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail256LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ polyAdd(0(oup)) -+ polyMul -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) -+ polyAdd(16(oup)) -+ polyMul -+ LEAQ 32(oup), oup -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 -+ DECQ itr1 -+ JG sealAVX2Tail256LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail256LoopB -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 -+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPERM2I128 $0x02, CC0, DD0, TT1 -+ VPERM2I128 $0x13, AA0, BB0, TT2 -+ VPERM2I128 $0x13, CC0, DD0, TT3 -+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) -+ MOVQ $128, itr1 -+ LEAQ 128(inp), inp -+ SUBQ $128, inl -+ VPERM2I128 $0x02, AA1, BB1, AA0 -+ VPERM2I128 $0x02, CC1, DD1, BB0 -+ VPERM2I128 $0x13, AA1, BB1, CC0 -+ VPERM2I128 $0x13, CC1, DD1, DD0 -+ -+ JMP sealAVX2SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 384 bytes of ciphertext -+sealAVX2Tail384: -+ // Need to decrypt up to 384 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2 -+ VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3 -+ -+sealAVX2Tail384LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail384LoopB: -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ polyAdd(0(oup)) -+ polyMul -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 -+ chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) -+ polyAdd(16(oup)) -+ polyMul -+ LEAQ 32(oup), oup -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 -+ DECQ itr1 -+ JG sealAVX2Tail384LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail384LoopB -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 -+ VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2 -+ VPERM2I128 $0x02, AA0, BB0, TT0 -+ VPERM2I128 $0x02, CC0, DD0, TT1 -+ VPERM2I128 $0x13, AA0, BB0, TT2 -+ VPERM2I128 $0x13, CC0, DD0, TT3 -+ VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) -+ VPERM2I128 $0x02, AA1, BB1, TT0 -+ VPERM2I128 $0x02, CC1, DD1, TT1 -+ VPERM2I128 $0x13, AA1, BB1, TT2 -+ VPERM2I128 $0x13, CC1, DD1, TT3 -+ VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 -+ VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) -+ MOVQ $256, itr1 -+ LEAQ 256(inp), inp -+ SUBQ $256, inl -+ VPERM2I128 $0x02, AA2, BB2, AA0 -+ VPERM2I128 $0x02, CC2, DD2, BB0 -+ VPERM2I128 $0x13, AA2, BB2, CC0 -+ VPERM2I128 $0x13, CC2, DD2, DD0 -+ -+ JMP sealAVX2SealHash -+ -+// ---------------------------------------------------------------------------- -+// Special optimization for the last 512 bytes of ciphertext -+sealAVX2Tail512: -+ // Need to decrypt up to 512 bytes - prepare two blocks -+ // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed -+ // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed -+ VMOVDQA Β·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 -+ VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 -+ VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 -+ VMOVDQA ctr3StoreAVX2, DD0 -+ VPADDD Β·avx2IncMask<>(SB), DD0, DD0; VPADDD Β·avx2IncMask<>(SB), DD0, DD1; VPADDD Β·avx2IncMask<>(SB), DD1, DD2; VPADDD Β·avx2IncMask<>(SB), DD2, DD3 -+ VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 -+ -+sealAVX2Tail512LoopA: -+ polyAdd(0(oup)) -+ polyMul -+ LEAQ 16(oup), oup -+ -+sealAVX2Tail512LoopB: -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ polyAdd(0*8(oup)) -+ polyMulAVX2 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol16<>(SB), DD0, DD0; VPSHUFB Β·rol16<>(SB), DD1, DD1; VPSHUFB Β·rol16<>(SB), DD2, DD2; VPSHUFB Β·rol16<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ polyAdd(2*8(oup)) -+ polyMulAVX2 -+ LEAQ (4*8)(oup), oup -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 -+ VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 -+ VPSHUFB Β·rol8<>(SB), DD0, DD0; VPSHUFB Β·rol8<>(SB), DD1, DD1; VPSHUFB Β·rol8<>(SB), DD2, DD2; VPSHUFB Β·rol8<>(SB), DD3, DD3 -+ VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 -+ VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 -+ VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 -+ VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 -+ VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 -+ VMOVDQA tmpStoreAVX2, CC3 -+ VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 -+ VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 -+ VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 -+ -+ DECQ itr1 -+ JG sealAVX2Tail512LoopA -+ DECQ itr2 -+ JGE sealAVX2Tail512LoopB -+ -+ VPADDD Β·chacha20Constants<>(SB), AA0, AA0; VPADDD Β·chacha20Constants<>(SB), AA1, AA1; VPADDD Β·chacha20Constants<>(SB), AA2, AA2; VPADDD Β·chacha20Constants<>(SB), AA3, AA3 -+ VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 -+ VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 -+ VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 -+ VMOVDQA CC3, tmpStoreAVX2 -+ VPERM2I128 $0x02, AA0, BB0, CC3 -+ VPXOR (0*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (0*32)(oup) -+ VPERM2I128 $0x02, CC0, DD0, CC3 -+ VPXOR (1*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (1*32)(oup) -+ VPERM2I128 $0x13, AA0, BB0, CC3 -+ VPXOR (2*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (2*32)(oup) -+ VPERM2I128 $0x13, CC0, DD0, CC3 -+ VPXOR (3*32)(inp), CC3, CC3 -+ VMOVDQU CC3, (3*32)(oup) -+ -+ VPERM2I128 $0x02, AA1, BB1, AA0 -+ VPERM2I128 $0x02, CC1, DD1, BB0 -+ VPERM2I128 $0x13, AA1, BB1, CC0 -+ VPERM2I128 $0x13, CC1, DD1, DD0 -+ VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) -+ -+ VPERM2I128 $0x02, AA2, BB2, AA0 -+ VPERM2I128 $0x02, CC2, DD2, BB0 -+ VPERM2I128 $0x13, AA2, BB2, CC0 -+ VPERM2I128 $0x13, CC2, DD2, DD0 -+ VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 -+ VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) -+ -+ MOVQ $384, itr1 -+ LEAQ 384(inp), inp -+ SUBQ $384, inl -+ VPERM2I128 $0x02, AA3, BB3, AA0 -+ VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0 -+ VPERM2I128 $0x13, AA3, BB3, CC0 -+ VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 -+ -+ JMP sealAVX2SealHash -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go -new file mode 100644 -index 00000000000000..6313898f0a75d9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go -@@ -0,0 +1,81 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20poly1305 -+ -+import ( -+ "encoding/binary" -+ -+ "golang.org/x/crypto/chacha20" -+ "golang.org/x/crypto/internal/alias" -+ "golang.org/x/crypto/internal/poly1305" -+) -+ -+func writeWithPadding(p *poly1305.MAC, b []byte) { -+ p.Write(b) -+ if rem := len(b) % 16; rem != 0 { -+ var buf [16]byte -+ padLen := 16 - rem -+ p.Write(buf[:padLen]) -+ } -+} -+ -+func writeUint64(p *poly1305.MAC, n int) { -+ var buf [8]byte -+ binary.LittleEndian.PutUint64(buf[:], uint64(n)) -+ p.Write(buf[:]) -+} -+ -+func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { -+ ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) -+ ciphertext, tag := out[:len(plaintext)], out[len(plaintext):] -+ if alias.InexactOverlap(out, plaintext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ -+ var polyKey [32]byte -+ s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.SetCounter(1) // set the counter to 1, skipping 32 bytes -+ s.XORKeyStream(ciphertext, plaintext) -+ -+ p := poly1305.New(&polyKey) -+ writeWithPadding(p, additionalData) -+ writeWithPadding(p, ciphertext) -+ writeUint64(p, len(additionalData)) -+ writeUint64(p, len(plaintext)) -+ p.Sum(tag[:0]) -+ -+ return ret -+} -+ -+func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ tag := ciphertext[len(ciphertext)-16:] -+ ciphertext = ciphertext[:len(ciphertext)-16] -+ -+ var polyKey [32]byte -+ s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce) -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.SetCounter(1) // set the counter to 1, skipping 32 bytes -+ -+ p := poly1305.New(&polyKey) -+ writeWithPadding(p, additionalData) -+ writeWithPadding(p, ciphertext) -+ writeUint64(p, len(additionalData)) -+ writeUint64(p, len(ciphertext)) -+ -+ ret, out := sliceForAppend(dst, len(ciphertext)) -+ if alias.InexactOverlap(out, ciphertext) { -+ panic("chacha20poly1305: invalid buffer overlap") -+ } -+ if !p.Verify(tag) { -+ for i := range out { -+ out[i] = 0 -+ } -+ return nil, errOpen -+ } -+ -+ s.XORKeyStream(out, ciphertext) -+ return ret, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go -new file mode 100644 -index 00000000000000..f832b33d45f208 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go -@@ -0,0 +1,16 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || !gc || purego -+// +build !amd64 !gc purego -+ -+package chacha20poly1305 -+ -+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ return c.sealGeneric(dst, nonce, plaintext, additionalData) -+} -+ -+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ return c.openGeneric(dst, nonce, ciphertext, additionalData) -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go -new file mode 100644 -index 00000000000000..82a4a36102d6d6 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go -@@ -0,0 +1,268 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20poly1305 -+ -+import ( -+ "bytes" -+ "crypto/cipher" -+ cryptorand "crypto/rand" -+ "encoding/hex" -+ "fmt" -+ mathrand "math/rand" -+ "strconv" -+ "testing" -+) -+ -+func TestVectors(t *testing.T) { -+ for i, test := range chacha20Poly1305Tests { -+ key, _ := hex.DecodeString(test.key) -+ nonce, _ := hex.DecodeString(test.nonce) -+ ad, _ := hex.DecodeString(test.aad) -+ plaintext, _ := hex.DecodeString(test.plaintext) -+ -+ var ( -+ aead cipher.AEAD -+ err error -+ ) -+ switch len(nonce) { -+ case NonceSize: -+ aead, err = New(key) -+ case NonceSizeX: -+ aead, err = NewX(key) -+ default: -+ t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce)) -+ } -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ ct := aead.Seal(nil, nonce, plaintext, ad) -+ if ctHex := hex.EncodeToString(ct); ctHex != test.out { -+ t.Errorf("#%d: got %s, want %s", i, ctHex, test.out) -+ continue -+ } -+ -+ plaintext2, err := aead.Open(nil, nonce, ct, ad) -+ if err != nil { -+ t.Errorf("#%d: Open failed", i) -+ continue -+ } -+ -+ if !bytes.Equal(plaintext, plaintext2) { -+ t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) -+ continue -+ } -+ -+ if len(ad) > 0 { -+ alterAdIdx := mathrand.Intn(len(ad)) -+ ad[alterAdIdx] ^= 0x80 -+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil { -+ t.Errorf("#%d: Open was successful after altering additional data", i) -+ } -+ ad[alterAdIdx] ^= 0x80 -+ } -+ -+ alterNonceIdx := mathrand.Intn(aead.NonceSize()) -+ nonce[alterNonceIdx] ^= 0x80 -+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil { -+ t.Errorf("#%d: Open was successful after altering nonce", i) -+ } -+ nonce[alterNonceIdx] ^= 0x80 -+ -+ alterCtIdx := mathrand.Intn(len(ct)) -+ ct[alterCtIdx] ^= 0x80 -+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil { -+ t.Errorf("#%d: Open was successful after altering ciphertext", i) -+ } -+ ct[alterCtIdx] ^= 0x80 -+ } -+} -+ -+func TestRandom(t *testing.T) { -+ // Some random tests to verify Open(Seal) == Plaintext -+ f := func(t *testing.T, nonceSize int) { -+ for i := 0; i < 256; i++ { -+ var nonce = make([]byte, nonceSize) -+ var key [32]byte -+ -+ al := mathrand.Intn(128) -+ pl := mathrand.Intn(16384) -+ ad := make([]byte, al) -+ plaintext := make([]byte, pl) -+ cryptorand.Read(key[:]) -+ cryptorand.Read(nonce[:]) -+ cryptorand.Read(ad) -+ cryptorand.Read(plaintext) -+ -+ var ( -+ aead cipher.AEAD -+ err error -+ ) -+ switch len(nonce) { -+ case NonceSize: -+ aead, err = New(key[:]) -+ case NonceSizeX: -+ aead, err = NewX(key[:]) -+ default: -+ t.Fatalf("#%d: wrong nonce length: %d", i, len(nonce)) -+ } -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ ct := aead.Seal(nil, nonce[:], plaintext, ad) -+ -+ plaintext2, err := aead.Open(nil, nonce[:], ct, ad) -+ if err != nil { -+ t.Errorf("Random #%d: Open failed", i) -+ continue -+ } -+ -+ if !bytes.Equal(plaintext, plaintext2) { -+ t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) -+ continue -+ } -+ -+ if len(ad) > 0 { -+ alterAdIdx := mathrand.Intn(len(ad)) -+ ad[alterAdIdx] ^= 0x80 -+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { -+ t.Errorf("Random #%d: Open was successful after altering additional data", i) -+ } -+ ad[alterAdIdx] ^= 0x80 -+ } -+ -+ alterNonceIdx := mathrand.Intn(aead.NonceSize()) -+ nonce[alterNonceIdx] ^= 0x80 -+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { -+ t.Errorf("Random #%d: Open was successful after altering nonce", i) -+ } -+ nonce[alterNonceIdx] ^= 0x80 -+ -+ alterCtIdx := mathrand.Intn(len(ct)) -+ ct[alterCtIdx] ^= 0x80 -+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { -+ t.Errorf("Random #%d: Open was successful after altering ciphertext", i) -+ } -+ ct[alterCtIdx] ^= 0x80 -+ } -+ } -+ t.Run("Standard", func(t *testing.T) { f(t, NonceSize) }) -+ t.Run("X", func(t *testing.T) { f(t, NonceSizeX) }) -+} -+ -+func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte, nonceSize int) { -+ b.ReportAllocs() -+ b.SetBytes(int64(len(buf))) -+ -+ var key [32]byte -+ var nonce = make([]byte, nonceSize) -+ var ad [13]byte -+ var out []byte -+ -+ var aead cipher.AEAD -+ switch len(nonce) { -+ case NonceSize: -+ aead, _ = New(key[:]) -+ case NonceSizeX: -+ aead, _ = NewX(key[:]) -+ } -+ -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ out = aead.Seal(out[:0], nonce[:], buf[:], ad[:]) -+ } -+} -+ -+func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte, nonceSize int) { -+ b.ReportAllocs() -+ b.SetBytes(int64(len(buf))) -+ -+ var key [32]byte -+ var nonce = make([]byte, nonceSize) -+ var ad [13]byte -+ var ct []byte -+ var out []byte -+ -+ var aead cipher.AEAD -+ switch len(nonce) { -+ case NonceSize: -+ aead, _ = New(key[:]) -+ case NonceSizeX: -+ aead, _ = NewX(key[:]) -+ } -+ ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:]) -+ -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:]) -+ } -+} -+ -+func BenchmarkChacha20Poly1305(b *testing.B) { -+ for _, length := range []int{64, 1350, 8 * 1024} { -+ b.Run("Open-"+strconv.Itoa(length), func(b *testing.B) { -+ benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSize) -+ }) -+ b.Run("Seal-"+strconv.Itoa(length), func(b *testing.B) { -+ benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSize) -+ }) -+ -+ b.Run("Open-"+strconv.Itoa(length)+"-X", func(b *testing.B) { -+ benchamarkChaCha20Poly1305Open(b, make([]byte, length), NonceSizeX) -+ }) -+ b.Run("Seal-"+strconv.Itoa(length)+"-X", func(b *testing.B) { -+ benchamarkChaCha20Poly1305Seal(b, make([]byte, length), NonceSizeX) -+ }) -+ } -+} -+ -+func ExampleNewX() { -+ // key should be randomly generated or derived from a function like Argon2. -+ key := make([]byte, KeySize) -+ if _, err := cryptorand.Read(key); err != nil { -+ panic(err) -+ } -+ -+ aead, err := NewX(key) -+ if err != nil { -+ panic(err) -+ } -+ -+ // Encryption. -+ var encryptedMsg []byte -+ { -+ msg := []byte("Gophers, gophers, gophers everywhere!") -+ -+ // Select a random nonce, and leave capacity for the ciphertext. -+ nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead()) -+ if _, err := cryptorand.Read(nonce); err != nil { -+ panic(err) -+ } -+ -+ // Encrypt the message and append the ciphertext to the nonce. -+ encryptedMsg = aead.Seal(nonce, nonce, msg, nil) -+ } -+ -+ // Decryption. -+ { -+ if len(encryptedMsg) < aead.NonceSize() { -+ panic("ciphertext too short") -+ } -+ -+ // Split nonce and ciphertext. -+ nonce, ciphertext := encryptedMsg[:aead.NonceSize()], encryptedMsg[aead.NonceSize():] -+ -+ // Decrypt the message and check it wasn't tampered with. -+ plaintext, err := aead.Open(nil, nonce, ciphertext, nil) -+ if err != nil { -+ panic(err) -+ } -+ -+ fmt.Printf("%s\n", plaintext) -+ } -+ -+ // Output: Gophers, gophers, gophers everywhere! -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go -new file mode 100644 -index 00000000000000..76823d13e6cbce ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go -@@ -0,0 +1,727 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20poly1305 -+ -+var chacha20Poly1305Tests = []struct { -+ plaintext, aad, key, nonce, out string -+}{ -+ { -+ "", -+ "", -+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", -+ "070000004041424344454647", -+ "a0784d7a4716f3feb4f64e7f4b39bf04", -+ }, -+ { -+ // https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-01#appendix-A.3.1 -+ "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", -+ "50515253c0c1c2c3c4c5c6c7", -+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", -+ "404142434445464748494a4b4c4d4e4f5051525354555657", -+ "bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52ec0875924c1c7987947deafd8780acf49", -+ }, -+ { -+ "1400000cebccee3bf561b292340fec60", -+ "00000000000000001603030010", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163", -+ }, -+ { -+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa", -+ }, -+ { -+ "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87", -+ "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1", -+ "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f", -+ "4349e2131d44dc711148dfe3", -+ "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb", -+ }, -+ { -+ "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad", -+ "85deea3dc4", -+ "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7", -+ "b34710f65aed442e4a40866b", -+ "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0", -+ }, -+ { -+ "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5", -+ "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5", -+ "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e", -+ "2bbca0910cc47ca0b8517391", -+ "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f", -+ }, -+ { -+ "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337", -+ "74ba3372d308910b5c9c3885f41252d57556", -+ "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3", -+ "b928935c4c966c60fd6583c0", -+ "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d", -+ }, -+ { -+ "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b", -+ "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4", -+ "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093", -+ "8998e043d2961afa51ea262a", -+ "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7", -+ }, -+ { -+ "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e", -+ "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7", -+ "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975", -+ "aeb6159fa88bb1ffd51d036d", -+ "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e", -+ }, -+ { -+ "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296", -+ "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14", -+ "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c", -+ "4c46854e9e101090b1436f90", -+ "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb", -+ }, -+ { -+ "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9", -+ "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521", -+ "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87", -+ "eaa4d916d261676d632455be", -+ "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd", -+ }, -+ { -+ "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90", -+ "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a", -+ "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089", -+ "2403fe689e239c2ed261b381", -+ "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91", -+ }, -+ { -+ "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae", -+ "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974", -+ "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be", -+ "231b5780fedfb06d724450b3", -+ "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7", -+ }, -+ { -+ "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91", -+ "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3", -+ "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97", -+ "1e46a7486c5a03fd6758d938", -+ "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf", -+ }, -+ { -+ "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf", -+ "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae", -+ "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369", -+ "e14de73c4b17581a7e0d0649", -+ "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d", -+ }, -+ { -+ "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5", -+ "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81", -+ "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6", -+ "bb2d033de71d570ddf824e85", -+ "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2", -+ }, -+ { -+ "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65", -+ "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497", -+ "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d", -+ "350287a6bed5709dfba3d35c", -+ "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95", -+ }, -+ { -+ "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5", -+ "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68", -+ "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c", -+ "c0494bb7249f864f69beab46", -+ "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081", -+ }, -+ { -+ "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c", -+ "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5", -+ "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7", -+ "674a516f8f59f9067e0485e3", -+ "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc", -+ }, -+ { -+ "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c", -+ "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85", -+ "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b", -+ "8726dc5cae9497936658f603", -+ "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465", -+ }, -+ { -+ "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c", -+ "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94", -+ "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea", -+ "b633c1a0e1ddf4727b149b3d", -+ "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527", -+ }, -+ { -+ "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c", -+ "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655", -+ "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9", -+ "9f1d08be539f1244f0f69ad2", -+ "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a", -+ }, -+ { -+ "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271", -+ "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442", -+ "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1", -+ "952f492fe00b26028c560fc6", -+ "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053", -+ }, -+ { -+ "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34", -+ "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f", -+ "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769", -+ "7d3981073f90c6648c5e9c74", -+ "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7", -+ }, -+ { -+ "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf", -+ "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062", -+ "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc", -+ "5f6267f6b3b21423267310e6", -+ "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5", -+ }, -+ { -+ "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607", -+ "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd", -+ "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f", -+ "240cb25aaae4d085bbb747a5", -+ "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500", -+ }, -+ { -+ "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e", -+ "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597", -+ "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31", -+ "d9ce7d249af9496e99c93b36", -+ "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb", -+ }, -+ { -+ "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1", -+ "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555", -+ "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd", -+ "7df9824e774c5f86d83cb5d8", -+ "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f", -+ }, -+ { -+ "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092", -+ "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5", -+ "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a", -+ "588d9bc1d98210d9700ef488", -+ "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3", -+ }, -+ { -+ "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831", -+ "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f", -+ "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34", -+ "34a04df283c45655a52bdd84", -+ "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784", -+ }, -+ { -+ "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154", -+ "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9", -+ "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6", -+ "bb21211f342379370f2642d3", -+ "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8", -+ }, -+ { -+ "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459", -+ "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a", -+ "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb", -+ "47cc9eea11f9f3f9aafa23bd", -+ "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964", -+ }, -+ { -+ "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768", -+ "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33", -+ "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b", -+ "e88c14ef96c7768f5dba9de9", -+ "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc", -+ }, -+ { -+ "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64", -+ "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d", -+ "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81", -+ "36c79f9f14d431cc8c077439", -+ "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d", -+ }, -+ { -+ "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30", -+ "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083", -+ "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55", -+ "7812a320691ca8442767a51a", -+ "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb", -+ }, -+ { -+ "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e", -+ "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837", -+ "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c", -+ "e4709d225a552e90fb357413", -+ "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75", -+ }, -+ { -+ "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718", -+ "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9", -+ "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257", -+ "8bf183347ec1ca4bceff3374", -+ "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c", -+ }, -+ { -+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b", -+ "0942e506c433afcda3847f2dad", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d", -+ }, -+ { -+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", -+ "d3d934f75ea0f210a8f6059401", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925", -+ }, -+ { -+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", -+ "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91", -+ }, -+ { -+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b", -+ "bc", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170", -+ }, -+ { -+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0", -+ "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d", -+ }, -+ { -+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525", -+ "", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5", -+ }, -+ { -+ "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a", -+ "026866d46aa940309fdcabf92a324fbc", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00", -+ }, -+ { -+ "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9", -+ "56", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b", -+ }, -+ { -+ "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2", -+ "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6", -+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", -+ "129039b5572e8a7a8131f76a", -+ "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54", -+ }, -+ -+ // XChaCha20-Poly1305 vectors -+ { -+ "000000000000000000000000000000", -+ "", -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000", -+ "789e9689e5208d7fd9e1f3c5b5341fb2f7033812ac9ebd3745e2c99c7bbfeb", -+ }, -+ { -+ "02dc819b71875e49f5e1e5a768141cfd3f14307ae61a34d81decd9a3367c00c7", -+ "", -+ "b7bbfe61b8041658ddc95d5cbdc01bbe7626d24f3a043b70ddee87541234cff7", -+ "e293239d4c0a07840c5f83cb515be7fd59c333933027e99c", -+ "7a51f271bd2e547943c7be3316c05519a5d16803712289aa2369950b1504dd8267222e47b13280077ecada7b8795d535", -+ }, -+ { -+ "7afc5f3f24155002e17dc176a8f1f3a097ff5a991b02ff4640f70b90db0c15c328b696d6998ea7988edfe3b960e47824e4ae002fbe589be57896a9b7bf5578599c6ba0153c7c", -+ "d499bb9758debe59a93783c61974b7", -+ "4ea8fab44a07f7ffc0329b2c2f8f994efdb6d505aec32113ae324def5d929ba1", -+ "404d5086271c58bf27b0352a205d21ce4367d7b6a7628961", -+ "26d2b46ad58b6988e2dcf1d09ba8ab6f532dc7e0847cdbc0ed00284225c02bbdb278ee8381ebd127a06926107d1b731cfb1521b267168926492e8f77219ad922257a5be2c5e52e6183ca4dfd0ad3912d7bd1ec968065", -+ }, -+ { -+ "", -+ "", -+ "48d8bd02c2e9947eae58327114d35e055407b5519c8019535efcb4fc875b5e2b", -+ "cc0a587a475caba06f8dbc09afec1462af081fe1908c2cba", -+ "fc3322d0a9d6fac3eb4a9e09b00b361e", -+ }, -+ { -+ "e0862731e5", -+ "", -+ "6579e7ee96151131a1fcd06fe0d52802c0021f214960ecceec14b2b8591f62cd", -+ "e2230748649bc22e2b71e46a7814ecabe3a7005e949bd491", -+ "e991efb85d8b1cfa3f92cb72b8d3c882e88f4529d9", -+ }, -+ { -+ "00c7dd8f440af1530b44", -+ "", -+ "ffb733657c849d50ab4ab40c4ae18f8ee2f0acf7c907afefdc04dff3537fdff3", -+ "02c6fd8032a8d89edbedcd1db024c09d29f08b1e74325085", -+ "13dbcdb8c60c3ed28449a57688edfaea89e309ab4faa6d51e532", -+ }, -+ { -+ "7422f311ea476cf819cb8b3c77369f", -+ "", -+ "ef0d05d028d6abdd5e99d1761d2028de75ee6eb376ff0dc8036e9a8e10743876", -+ "f772745200b0f92e38f1d8dae79bf8138e84b301f0be74df", -+ "d5f992f9834df1be86b580ac59c7eae063a68072829c51bc8a26970dd3d310", -+ }, -+ { -+ "ba09ca69450e6c7bece31a7a3f216e3b9ed0e536", -+ "", -+ "8d93e31abfe22a63faf45cbea91877050718f13fef6e2664a1892d7f23007ccf", -+ "260b7b3554a7e6ff8aae7dd6234077ca539689a20c1610a8", -+ "c99e9a768eb2ec8569bdff8a37295069552faebcafb1a76e98bc7c5b6b778b3d1b6291f0", -+ }, -+ { -+ "424ec5f98a0fdc5a7388532d11ab0edb26733505627b7f2d1f", -+ "", -+ "b68d5e6c46cdbb0060445522bdc5c562ae803b6aaaf1e103c146e93527a59299", -+ "80bb5dc1dd44a35ec4f91307f1a95b4ca31183a1a596fb7c", -+ "29d4eed0fff0050d4bb40de3b055d836206e7cbd62de1a63904f0cf731129ba3f9c2b9d46251a6de89", -+ }, -+ { -+ "e7e4515cc0a6ef0491af983eaac4f862d6e726758a3c657f4ec444841e42", -+ "", -+ "e31a1d3af650e8e2848bd78432d89ecd1fdece9842dc2792e7bda080f537b17b", -+ "f3f09905e9a871e757348834f483ed71be9c0f437c8d74b0", -+ "f5c69528963e17db725a28885d30a45194f12848b8b7644c7bded47a2ee83e6d4ef34006305cfdf82effdced461d", -+ }, -+ { -+ "0f5ca45a54875d1d19e952e53caeaa19389342f776dab11723535503338d6f77202a37", -+ "", -+ "1031bc920d4fcb4434553b1bf2d25ab375200643bf523ff037bf8914297e8dca", -+ "4cc77e2ef5445e07b5f44de2dc5bf62d35b8c6f69502d2bf", -+ "7aa8669e1bfe8b0688899cdddbb8cee31265928c66a69a5090478da7397573b1cc0f64121e7d8bff8db0ddd3c17460d7f29a12", -+ }, -+ { -+ "c45578c04c194994e89025c7ffb015e5f138be3cd1a93640af167706aee2ad25ad38696df41ad805", -+ "", -+ "ac8648b7c94328419c668ce1c57c71893adf73abbb98892a4fc8da17400e3a5e", -+ "4ad637facf97af5fc03207ae56219da9972858b7430b3611", -+ "49e093fcd074fb67a755669119b8bd430d98d9232ca988882deeb3508bde7c00160c35cea89092db864dcb6d440aefa5aacb8aa7b9c04cf0", -+ }, -+ { -+ "b877bfa192ea7e4c7569b9ee973f89924d45f9d8ed03c7098ad0cad6e7880906befedcaf6417bb43efabca7a2f", -+ "", -+ "125e331d5da423ecabc8adf693cdbc2fc3d3589740d40a3894f914db86c02492", -+ "913f8b2f08006e6260de41ec3ee01d938a3e68fb12dc44c4", -+ "1be334253423c90fc8ea885ee5cd3a54268c035ba8a2119e5bd4f7822cd7bf9cb4cec568d5b6d6292606d32979e044df3504e6eb8c0b2fc7e2a0e17d62", -+ }, -+ { -+ "d946484a1df5f85ff72c92ff9e192660cde5074bd0ddd5de900c35eb10ed991113b1b19884631bc8ceb386bcd83908061ce9", -+ "", -+ "b7e83276373dcf8929b6a6ea80314c9de871f5f241c9144189ee4caf62726332", -+ "f59f9d6e3e6c00720dc20dc21586e8330431ebf42cf9180e", -+ "a38a662b18c2d15e1b7b14443cc23267a10bee23556b084b6254226389c414069b694159a4d0b5abbe34de381a0e2c88b947b4cfaaebf50c7a1ad6c656e386280ad7", -+ }, -+ { -+ "d266927ca40b2261d5a4722f3b4da0dd5bec74e103fab431702309fd0d0f1a259c767b956aa7348ca923d64c04f0a2e898b0670988b15e", -+ "", -+ "a60e09cd0bea16f26e54b62b2908687aa89722c298e69a3a22cf6cf1c46b7f8a", -+ "92da9d67854c53597fc099b68d955be32df2f0d9efe93614", -+ "9dd6d05832f6b4d7f555a5a83930d6aed5423461d85f363efb6c474b6c4c8261b680dea393e24c2a3c8d1cc9db6df517423085833aa21f9ab5b42445b914f2313bcd205d179430", -+ }, -+ { -+ "f7e11b4d372ed7cb0c0e157f2f9488d8efea0f9bbe089a345f51bdc77e30d1392813c5d22ca7e2c7dfc2e2d0da67efb2a559058d4de7a11bd2a2915e", -+ "", -+ "194b1190fa31d483c222ec475d2d6117710dd1ac19a6f1a1e8e894885b7fa631", -+ "6b07ea26bb1f2d92e04207b447f2fd1dd2086b442a7b6852", -+ "25ae14585790d71d39a6e88632228a70b1f6a041839dc89a74701c06bfa7c4de3288b7772cb2919818d95777ab58fe5480d6e49958f5d2481431014a8f88dab8f7e08d2a9aebbe691430011d", -+ }, -+ { -+ "", -+ "1e2b11e3", -+ "70cd96817da85ede0efdf03a358103a84561b25453dee73735e5fb0161b0d493", -+ "5ddeba49f7266d11827a43931d1c300dd47a3c33f9f8bf9b", -+ "592fc4c19f3cddec517b2a00f9df9665", -+ }, -+ { -+ "81b3cb7eb3", -+ "efcfd0cf", -+ "a977412f889281a6d75c24186f1bfaa00dcc5132f0929f20ef15bbf9e63c4c91", -+ "3f26ca997fb9166d9c615babe3e543ca43ab7cab20634ac5", -+ "8e4ade3e254cf52e93eace5c46667f150832725594", -+ }, -+ { -+ "556f97f2ebdb4e949923", -+ "f7cee2e0", -+ "787b3e86546a51028501c801dadf8d5b996fd6f6f2363d5d0f900c44f6a2f4c2", -+ "7fa6af59a779657d1cada847439ea5b92a1337cfbebbc3b1", -+ "608ec22dae5f48b89d6f0d2a940d5a7661e0a8e68aaee4ad2d96", -+ }, -+ { -+ "c06847a36ad031595b60edd44dc245", -+ "d4175e1f", -+ "16de31e534dd5af32801b1acd0ec541d1f8d82bcbc3af25ec815f3575b7aca73", -+ "29f6656972838f56c1684f6a278f9e4e207b51d68706fc25", -+ "836082cc51303e500fceade0b1a18f1d97d64ff41cc81754c07d6231b9fd1b", -+ }, -+ { -+ "0d03c22ced7b29c6741e72166cd61792028dfc80", -+ "e505dad0", -+ "ac2b426e5c5c8e00666180a3410e8a2f6e52247a43aecea9622163e8433c93b2", -+ "c1123430468228625967bbc0fbd0f963e674372259ff2deb", -+ "bf09979bf4fed2eec6c97f6e1bcfac35eeffc6d54a55cc1d83d8767ae74db2d7cdfbc371", -+ }, -+ { -+ "05bf00e1707cffe7ccbd06a9f846d0fd471a700ed43b4facb8", -+ "d863bebe", -+ "66c121f0f84b95ba1e6d29e7d81900bc96a642421b9b6105ae5eb5f2e7b07577", -+ "8ed6ae211a661e967995b71f7316ba88f44322bb62b4187b", -+ "b2c5c85d087e0305e9058fba52b661fb3d7f21cb4d4915ae048bc9e5d66a2f921dd4a1c1b030f442c9", -+ }, -+ { -+ "5f2b91a9be8bfaa21451ddc6c5cf28d1cc00b046b76270b95cda3c280c83", -+ "a8750275", -+ "39592eb276877fca9dd11e2181c0b23127328407e3cc11e315e5d748f43529cc", -+ "1084bebd756f193d9eea608b3a0193a5028f8ced19684821", -+ "eaee1f49ac8468154c601a5dd8b84d597602e5a73534b5fad5664f97d0f017dd114752be969679cf610340c6a312", -+ }, -+ { -+ "01e8e269b5376943f3b2d245483a76461dc8b7634868b559165f5dbb20839029fae9bb", -+ "a1e96da0", -+ "b8386123b87e50d9d046242cf1bf141fce7f65aff0fba76861a2bc72582d6ff0", -+ "0fbe2a13a89bea031de96d78f9f11358ba7b6a5e724b4392", -+ "705ec3f910ec85c6005baa99641de6ca43332ff52b5466df6af4ffbe4ef2a376a8f871d1eae503b5896601fee005cdc1f4c1c6", -+ }, -+ { -+ "706daba66e2edb1f828f3c0051e3cc214b12210bde0587bba02580f741a4c83e84d4e9fe961120cd", -+ "87663c5a", -+ "d519d82ba8a3f0c3af9efe36682b62e285167be101a526c1d73000f169c2a486", -+ "ad651aac536978e2bc1a54816345ac5e9a9b43b3d9cc0bfc", -+ "07051b5e72da9c4811beb07ff9f95aece67eae18420eb3f0e8bb8a5e26d4b483fa40eb063a2354842d0c8a41d981cc2b77c530b496db01c8", -+ }, -+ { -+ "1f6b24f2f0d9eb460d726bed953d66fcc4ecc29da6ed2fd711358eac3b2609d74ba3e21885156cde3cbe6d9b6f", -+ "f5efbc4e", -+ "86068a00544f749ad4ad15bb8e427ae78577ae22f4ca9778efff828ba10f6b20", -+ "c8420412c9626dcd34ece14593730f6aa2d01ec51cacd59f", -+ "a99f6c88eac35bb34439e34b292fe9db8192446dcdc81e2192060ec36d98b47de2bee12bf0f67cb24fb0949c07733a6781cd9455cdc61123f506886b04", -+ }, -+ { -+ "d69389d83362be8c0ddb738659a6cc4bd65d88cb5b525232f4d59a7d4751a7203c254923ecb6873e803220aab19664789a63", -+ "bc35fb1c", -+ "835855b326a98682b3075b4d7f1b89059c3cdfc547d4296c80ce7a77ba6434e3", -+ "c27cb75fc319ba431cbaeb120341d0c4745d883eb47e92bc", -+ "db6dc3f9a0f4f1a6df2495a88910550c2c6205478bfc1e81282e34b5b36d984c72c0509c522c987c61d2e640ced69402a6d33aa10d3d0b81e680b3c19bc142e81923", -+ }, -+ { -+ "a66a7f089115ed9e2d5bb5d33d7282a7afe401269b00f2a233a59c04b794a42901d862140b61d18d7c7f0ad5da040613e557f8abc74219", -+ "2c060aaf", -+ "99758aa7714fd707931f71803eefe04a06955041308a0b2a1104313b270ccf34", -+ "63f690d8926408c7a34fe8ddd505a8dc58769dc74e8d5da6", -+ "92b21ee85afcd8996ac28f3aed1047ad814d6e4ffbca3159af16f26eded83e4abda9e4275eb3ff0ad90dffe09f2d443b628f824f680b46527ce0128e8de1920f7c44350ebe7913", -+ }, -+ { -+ "f955183b1f762d4536d3f6885ea7f5ac27414caf46c2e24a2fd3bd56b91c53d840fb657224565e0a6f686f8ba320e04a401057399d9a3d995ab17c13", -+ "c372ddc5", -+ "a188be3795b2ca2e69b6aa263244f0963c492d694cf6c9b705a1d7045f3f2a26", -+ "51bb484ea094ee140474681e1c838e4442fd148de2cc345a", -+ "48759a5ddfdd829d11de8e0c538ce4a9c475faab6912039b568ad92d737d172fc1eb0c00c3793de6dddbfacfdbbc7f44aeba33684e18005aa982b6fc6c556e63bb90ff7a1dde8153a63eabe0", -+ }, -+ { -+ "", -+ "e013cd0bfafd486d", -+ "af3d3ba094d38299ecb91c17bfe3d085da5bd42e11acf8acb5bc26a4be9a7583", -+ "7dd63c14173831f109761b1c1abe18f6ba937d825957011b", -+ "8bc685a7d9d501952295cd25d8c92517", -+ }, -+ { -+ "284b64597e", -+ "31d013e53aa3ea79", -+ "93c77409d7f805f97fe683b2dd6ee06152a5e918b3eed5b731acccffdcb2cc04", -+ "3d331e90c4597cf0c30d1b7cfbd07bcb6ab927eda056873c", -+ "3538a449d6c18d148a8c6cb76f1bc288657ac7036a", -+ }, -+ { -+ "9fe67f5c78180ede8274", -+ "188608d230d75860", -+ "b7cca89a82640aea6f80b458c9e633d88594fb498959d39787be87030892d48f", -+ "ef891d50e8c08958f814590fdb7a9f16c61cc2aae1682109", -+ "bbb40c30f3d1391a5b38df480cbbf964b71e763e8140751f4e28", -+ }, -+ { -+ "3a2826b6f7e3d542e4ded8f23c9aa4", -+ "260033e789c4676a", -+ "7fe2731214f2b4b42f93217d43f1776498413725e4f6cfe62b756e5a52df10ea", -+ "888728219ebf761547f5e2218532714403020e5a8b7a49d0", -+ "fe0328f883fcd88930ae017c0f54ed90f883041efc020e959125af370c1d47", -+ }, -+ { -+ "91858bf7b969005d7164acbd5678052b651c53e0", -+ "f3cc53ecafcbadb3", -+ "d69c04e9726b22d51f97bc9da0f0fda86736e6b78e8ef9f6f0000f79890d6d43", -+ "6de3c45161b434e05445cf6bf69eef7bddf595fc6d8836bd", -+ "a8869dd578c0835e120c843bb7dedc7a1e9eae24ffd742be6bf5b74088a8a2c550976fcb", -+ }, -+ { -+ "b3b1a4d6b2a2b9c5a1ca6c1efaec34dcfa1acbe7074d5e10cc", -+ "d0f72bd16cda3bae", -+ "2b317857b089c9305c49b83019f6e158bc4ecc3339b39ade02ee10c37c268da0", -+ "cb5fa6d1e14a0b4bdf350cd10c8a7bd638102911ec74be09", -+ "e6372f77c14343650074e07a2b7223c37b29242224b722b24d63b5956f27aa64ce7ce4e39cd14a2787", -+ }, -+ { -+ "057d3e9f865be7dff774938cab6d080e50cf9a1593f53c0063201e0bb7ae", -+ "fd3881e505c8b12d", -+ "36e42b1ef1ee8d068f09b5fad3ee43d98d34aa3e3f994f2055aee139da71de9d", -+ "24124da36473d01bdca30297c9eef4fe61955525a453da17", -+ "a8b28139524c98c1f8776f442eac4c22766fe6aac83224641c58bf021fc9cb709ec4706f49c2d0c1828acf2bfe8d", -+ }, -+ { -+ "bd8f13e928c34d67a6c70c3c7efdf2982ecc31d8cee68f9cbddc75912cd828ac93d28b", -+ "193206c8fcc5b19b", -+ "6e47c40c9d7b757c2efca4d73890e4c73f3c859aab4fdc64b564b8480dd84e72", -+ "ca31340ae20d30fe488be355cb36652c5db7c9d6265a3e95", -+ "a121efc5e1843deade4b8adbfef1808de4eda222f176630ad34fb476fca19e0299e4a13668e53cf13882035ba4f04f47c8b4e3", -+ }, -+ { -+ "23067a196e977d10039c14ff358061c918d2148d31961bb3e12c27c5122383cb25c4d1d79c775720", -+ "62338d02fff78a00", -+ "2c5c79c92d91fb40ef7d0a77e8033f7b265e3bab998b8116d17b2e62bb4f8a09", -+ "024736adb1d5c01006dffd8158b57936d158d5b42054336d", -+ "46d0905473a995d38c7cdbb8ef3da96ecc82a22c5b3c6c9d1c4a61ae7a17db53cb88c5f7eccf2da1d0c417c300f989b4273470e36f03542f", -+ }, -+ { -+ "252e966c680329eb687bff813b78fea3bfd3505333f106c6f9f45ba69896723c41bb763793d9b266e897d05557", -+ "1e93e0cfe6523380", -+ "9ec6fd1baa13ee16aec3fac16718a2baccf18a403cec467c25b7448e9b321110", -+ "e7120b1018ab363a36e61102eedbcbe9847a6cbacaa9c328", -+ "2934f034587d4144bb11182679cd2cd1c99c8088d18e233379e9bc9c41107a1f57a2723ecc7b9ba4e6ee198adf0fd766738e828827dc73136fc5b996e9", -+ }, -+ { -+ "6744aefcb318f12bc6eeb59d4d62f7eb95f347cea14bd5158415f07f84e4e3baa3de07512d9b76095ac1312cfcb1bb77f499", -+ "608d2a33ce5d0b04", -+ "0f665cbdaaa40f4f5a00c53d951b0a98aac2342be259a52670f650a783be7aab", -+ "378bdb57e957b8c2e1500c9513052a3b02ff5b7edbd4a3a7", -+ "341c60fcb374b394f1b01a4a80aedef49ab0b67ec963675e6eec43ef106f7003be87dbf4a8976709583dccc55abc7f979c4721837e8664a69804ea31736aa2af615a", -+ }, -+ { -+ "bcf1004f988220b7ce063ef2ec4e276ffd074f0a90aa807de1532679d2a1505568eaa4192d9a6ea52cc500322343ce9f8e68cc2c606d83", -+ "e64bd00126c8792c", -+ "58e65150d6a15dcefbc14a171998987ad0d709fb06a17d68d6a778759681c308", -+ "106d2bd120b06e4eb10bc674fe55c77a3742225268319303", -+ "a28052a6686a1e9435fee8702f7da563a7b3d7b5d3e9e27f11abf73db309cd1f39a34756258c1c5c7f2fb12cf15eb20175c2a08fc93dd19c5e482ef3fbef3d8404a3cfd54a7baf", -+ }, -+ { -+ "acd08d4938a224b4cb2d723bf75420f3ea27b698fadd815bb7db9548a05651398644354334e69f8e4e5503bf1a6f92b38e860044a7edca6874038ce1", -+ "28a137808d0225b8", -+ "a031203b963a395b08be55844d81af39d19b23b7cc24b21afa31edc1eea6edd6", -+ "e8b31c52b6690f10f4ae62ba9d50ba39fb5edcfb78400e35", -+ "35cf39ba31da95ac9b661cdbd5e9c9655d13b8ff065c4ec10c810833a47a87d8057dd1948a7801bfe6904b49fed0aabfb3cd755a1a262d372786908ddcf64cae9f71cb9ed199c3ddacc50116", -+ }, -+ { -+ "", -+ "cda7ee2857e09e9054ef6806", -+ "d91dffb18132d8dd3d144a2f10ba28bc5df36cb60369f3b19893ec91db3cf904", -+ "ee56f19c62b0438da6a0d9e01844313902be44f84a6a4ce7", -+ "ccd48b61a5683c195d4424009eb1d147", -+ }, -+ { -+ "350f4c7ac2", -+ "7c104b539c1d2ae022434cd6", -+ "cbb61e369117f9250f68fa707240c554359262a4d66c757f80e3aeb6920894fb", -+ "fbb14c9943444eac5413c6f5c8095451eddece02c9461043", -+ "b5c6a35865ed8e5216ff6c77339ee1ab570de50e51", -+ }, -+ { -+ "4f0d61d3ea03a44a8df0", -+ "51c20a8ae9e9794da931fe23", -+ "ba6ced943aa62f9261d7513b822e02054e099acafb5360f0d850064da48b5a4f", -+ "04c68cb50cdbb0ec03f8381cf59b886e64c40548bf8e3f82", -+ "ea45a73957e2a853655623f2a3bb58791f7ea36dd2957ed66ffa", -+ }, -+ { -+ "4fbdd4d4293a8f34fdbc8f3ad44cf6", -+ "8212f315e3759c3253c588bb", -+ "5354791bc2370415811818e913e310dd12e6a0cf5dcab2b6424816eecccf4b65", -+ "7ee6353c2fbc73c9ebc652270bc86e4008e09583e623e679", -+ "50a354811a918e1801fb567621a8924baf8dd79da6d36702855d3753f1319c", -+ }, -+ { -+ "5a6f68b5a9a9920ca9c6edf5be7c0af150a063c4", -+ "9a524aa62938fb7a1e50ed06", -+ "fd91605a6ad85d8ba7a71b08dce1032aa9992bf4f28d407a53ddda04c043cada", -+ "46791d99d6de33e79025bf9e97c198e7cf409614c6284b4d", -+ "648033c1eb615467e90b7d3ac24202d8b849549141f9bab03e9e910c29b8eab3d4fb3f2c", -+ }, -+ { -+ "d9318c2c0d9ed89e35d242a6b1d496e7e0c5bbdf77eba14c56", -+ "a16053c35fbe8dc93c14a81f", -+ "f21406aec83134ebf7bc48c6d0f45acb5f341fbc7d3b5a9bff3ea1333c916af7", -+ "de6b977be450d5efa7777e006802ddbb10814a22da1c3cd9", -+ "8d3dad487d5161663da830b71c3e24ec5cdb74d858cbb73b084ed0902198532aad3a18416966bff223", -+ }, -+ { -+ "68d0ee08d38cb4bcc9268fee3030666e70e41fcabf6fe06536eeec43eec5", -+ "11e09447d40b22dc98070eec", -+ "da5ee1ec02eab13220fcb94f16efec848a8dd57c0f4d67955423f5d17fde5aa3", -+ "8f13e61d773a250810f75d46bf163a3f9205be5751f6049a", -+ "92a103b03764c1ad1f88500d22eeae5c0fe1044c872987c0b97affc5e8c3d783f8cc28a11dc91990ea22dd1bad74", -+ }, -+ { -+ "a1d960bda08efcf19e136dc1e8b05b6b381c820eda5f9a8047e1a2dd1803a1e4d11a7f", -+ "aa73d8d4aaa0cfd9d80a9ae8", -+ "08028833d617c28ba75b48f177cb5da87189189abb68dcb8974eca9230c25945", -+ "f7b6f34a910fd11588f567de8555932291f7df05f6e2b193", -+ "99cfc4cca193998bae153b744e6c94a82a2867780aa0f43acddb7c433fcb297311313ec2199f00d7ca7da0646b40113c60e935", -+ }, -+ { -+ "3b4ae39a745b6247ce5baf675ec36c5065b1bf76c8379eab4b769961d43a753896d068938017777e", -+ "128c017a985052f8cdbc6b28", -+ "4683d5caff613187a9b16af897253848e9c54fc0ec319de62452a86961d3cbb2", -+ "5612a13c2da003b91188921cbac3fa093eba99d8cbbb51ff", -+ "91a98b93b2174257175f7c882b45cc252e0db8667612bd270c1c12fe28b6bf209760bf8f370318f92ae3f88a5d4773b05714132cc28dddb8", -+ }, -+ { -+ "22ccf680d2995ef6563de281cff76882a036a59ad73f250e710b3040590d69bccde8a8411abe8b0d3cb728ca82", -+ "13a97d0a167a61aa21e531ec", -+ "9e140762eed274948b66de25e6e8f36ab65dc730b0cb096ef15aaba900a5588c", -+ "d0e9594cfd42ab72553bf34062a263f588bb8f1fc86a19f5", -+ "f194fc866dfba30e42c4508b7d90b3fa3f8983831ede713334563e36aa861f2f885b40be1dbe20ba2d10958a12823588d4bbbefb81a87d87315204f5e3", -+ }, -+ { -+ "a65f5d10c482b3381af296e631eb605eba6a11ccec6ceab021460d0bd35feb676ec6dbba5d4ad6c9f4d683ea541035bc80fa", -+ "f15ae71ffed50a8fcc4996b0", -+ "f535d60e8b75ac7e526041eed86eb4d65ae7e315eff15dba6c0133acc2a6a4bf", -+ "01ba61691ebb3c66d2f94c1b1c597ecd7b5ff7d2a30be405", -+ "d79e7c3893df5a5879c2f0a3f7ca619f08e4540f3ac7db35790b4211b9d47ae735adadf35fd47252a4763e3fd2b2cd8157f6ea7986108a53437962670a97d68ee281", -+ }, -+ { -+ "8c014655b97f6da76b0b168b565fd62de874c164fd7e227346a0ec22c908bed1e2a0b429620e6f3a68dd518f13a2c0250608a1cb08a7c3", -+ "10a7eff999029c5040c1b3bd", -+ "bf11af23e88c350a443493f6fa0eb34f234f4daa2676e26f0701bce5642d13f4", -+ "f14c97392afd2e32e2c625910ca029f9b6e81676c79cc42f", -+ "78d5226f372d5d60681dbfc749d12df74249f196b0cbf14fa65a3a59dc65ae458455ec39baa1df3397afe752bb06f6f13bf03c99abda7a95c1d0b73fd92d5f888a5f6f889a9aea", -+ }, -+ { -+ "66234d7a5b71eef134d60eccf7d5096ee879a33983d6f7a575e3a5e3a4022edccffe7865dde20b5b0a37252e31cb9a3650c63e35b057a1bc200a5b5b", -+ "ccc2406f997bcae737ddd0f5", -+ "d009eeb5b9b029577b14d200b7687b655eedb7d74add488f092681787999d66d", -+ "99319712626b400f9458dbb7a9abc9f5810f25b47fc90b39", -+ "543a2bbf52fd999027ae7c297353f3ce986f810bc2382583d0a81fda5939e4c87b6e8d262790cd614d6f753d8035b32adf43acc7f6d4c2c44289538928564b6587c2fcb99de1d8e34ffff323", -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go -new file mode 100644 -index 00000000000000..1cebfe946f4440 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go -@@ -0,0 +1,86 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package chacha20poly1305 -+ -+import ( -+ "crypto/cipher" -+ "errors" -+ -+ "golang.org/x/crypto/chacha20" -+) -+ -+type xchacha20poly1305 struct { -+ key [KeySize]byte -+} -+ -+// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. -+// -+// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce, -+// suitable to be generated randomly without risk of collisions. It should be -+// preferred when nonce uniqueness cannot be trivially ensured, or whenever -+// nonces are randomly generated. -+func NewX(key []byte) (cipher.AEAD, error) { -+ if len(key) != KeySize { -+ return nil, errors.New("chacha20poly1305: bad key length") -+ } -+ ret := new(xchacha20poly1305) -+ copy(ret.key[:], key) -+ return ret, nil -+} -+ -+func (*xchacha20poly1305) NonceSize() int { -+ return NonceSizeX -+} -+ -+func (*xchacha20poly1305) Overhead() int { -+ return Overhead -+} -+ -+func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if len(nonce) != NonceSizeX { -+ panic("chacha20poly1305: bad nonce length passed to Seal") -+ } -+ -+ // XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no -+ // size limit. However, since we reuse the ChaCha20-Poly1305 implementation, -+ // the second half of the counter is not available. This is unlikely to be -+ // an issue because the cipher.AEAD API requires the entire message to be in -+ // memory, and the counter overflows at 256 GB. -+ if uint64(len(plaintext)) > (1<<38)-64 { -+ panic("chacha20poly1305: plaintext too large") -+ } -+ -+ c := new(chacha20poly1305) -+ hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) -+ copy(c.key[:], hKey) -+ -+ // The first 4 bytes of the final nonce are unused counter space. -+ cNonce := make([]byte, NonceSize) -+ copy(cNonce[4:12], nonce[16:24]) -+ -+ return c.seal(dst, cNonce[:], plaintext, additionalData) -+} -+ -+func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if len(nonce) != NonceSizeX { -+ panic("chacha20poly1305: bad nonce length passed to Open") -+ } -+ if len(ciphertext) < 16 { -+ return nil, errOpen -+ } -+ if uint64(len(ciphertext)) > (1<<38)-48 { -+ panic("chacha20poly1305: ciphertext too large") -+ } -+ -+ c := new(chacha20poly1305) -+ hKey, _ := chacha20.HChaCha20(x.key[:], nonce[0:16]) -+ copy(c.key[:], hKey) -+ -+ // The first 4 bytes of the final nonce are unused counter space. -+ cNonce := make([]byte, NonceSize) -+ copy(cNonce[4:12], nonce[16:24]) -+ -+ return c.open(dst, cNonce[:], ciphertext, additionalData) -+} -diff --git a/ms_mod/golang.org/x/crypto/codereview.cfg b/ms_mod/golang.org/x/crypto/codereview.cfg -new file mode 100644 -index 00000000000000..3f8b14b64e83f9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/codereview.cfg -@@ -0,0 +1 @@ -+issuerepo: golang/go -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/asn1.go b/ms_mod/golang.org/x/crypto/cryptobyte/asn1.go -new file mode 100644 -index 00000000000000..6fc2838a3fb853 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/asn1.go -@@ -0,0 +1,824 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package cryptobyte -+ -+import ( -+ encoding_asn1 "encoding/asn1" -+ "fmt" -+ "math/big" -+ "reflect" -+ "time" -+ -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// This file contains ASN.1-related methods for String and Builder. -+ -+// Builder -+ -+// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER. -+func (b *Builder) AddASN1Int64(v int64) { -+ b.addASN1Signed(asn1.INTEGER, v) -+} -+ -+// AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the -+// given tag. -+func (b *Builder) AddASN1Int64WithTag(v int64, tag asn1.Tag) { -+ b.addASN1Signed(tag, v) -+} -+ -+// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. -+func (b *Builder) AddASN1Enum(v int64) { -+ b.addASN1Signed(asn1.ENUM, v) -+} -+ -+func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) { -+ b.AddASN1(tag, func(c *Builder) { -+ length := 1 -+ for i := v; i >= 0x80 || i < -0x80; i >>= 8 { -+ length++ -+ } -+ -+ for ; length > 0; length-- { -+ i := v >> uint((length-1)*8) & 0xff -+ c.AddUint8(uint8(i)) -+ } -+ }) -+} -+ -+// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER. -+func (b *Builder) AddASN1Uint64(v uint64) { -+ b.AddASN1(asn1.INTEGER, func(c *Builder) { -+ length := 1 -+ for i := v; i >= 0x80; i >>= 8 { -+ length++ -+ } -+ -+ for ; length > 0; length-- { -+ i := v >> uint((length-1)*8) & 0xff -+ c.AddUint8(uint8(i)) -+ } -+ }) -+} -+ -+// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER. -+func (b *Builder) AddASN1BigInt(n *big.Int) { -+ if b.err != nil { -+ return -+ } -+ -+ b.AddASN1(asn1.INTEGER, func(c *Builder) { -+ if n.Sign() < 0 { -+ // A negative number has to be converted to two's-complement form. So we -+ // invert and subtract 1. If the most-significant-bit isn't set then -+ // we'll need to pad the beginning with 0xff in order to keep the number -+ // negative. -+ nMinus1 := new(big.Int).Neg(n) -+ nMinus1.Sub(nMinus1, bigOne) -+ bytes := nMinus1.Bytes() -+ for i := range bytes { -+ bytes[i] ^= 0xff -+ } -+ if len(bytes) == 0 || bytes[0]&0x80 == 0 { -+ c.add(0xff) -+ } -+ c.add(bytes...) -+ } else if n.Sign() == 0 { -+ c.add(0) -+ } else { -+ bytes := n.Bytes() -+ if bytes[0]&0x80 != 0 { -+ c.add(0) -+ } -+ c.add(bytes...) -+ } -+ }) -+} -+ -+// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING. -+func (b *Builder) AddASN1OctetString(bytes []byte) { -+ b.AddASN1(asn1.OCTET_STRING, func(c *Builder) { -+ c.AddBytes(bytes) -+ }) -+} -+ -+const generalizedTimeFormatStr = "20060102150405Z0700" -+ -+// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME. -+func (b *Builder) AddASN1GeneralizedTime(t time.Time) { -+ if t.Year() < 0 || t.Year() > 9999 { -+ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t) -+ return -+ } -+ b.AddASN1(asn1.GeneralizedTime, func(c *Builder) { -+ c.AddBytes([]byte(t.Format(generalizedTimeFormatStr))) -+ }) -+} -+ -+// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. -+func (b *Builder) AddASN1UTCTime(t time.Time) { -+ b.AddASN1(asn1.UTCTime, func(c *Builder) { -+ // As utilized by the X.509 profile, UTCTime can only -+ // represent the years 1950 through 2049. -+ if t.Year() < 1950 || t.Year() >= 2050 { -+ b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) -+ return -+ } -+ c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) -+ }) -+} -+ -+// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not -+// support BIT STRINGs that are not a whole number of bytes. -+func (b *Builder) AddASN1BitString(data []byte) { -+ b.AddASN1(asn1.BIT_STRING, func(b *Builder) { -+ b.AddUint8(0) -+ b.AddBytes(data) -+ }) -+} -+ -+func (b *Builder) addBase128Int(n int64) { -+ var length int -+ if n == 0 { -+ length = 1 -+ } else { -+ for i := n; i > 0; i >>= 7 { -+ length++ -+ } -+ } -+ -+ for i := length - 1; i >= 0; i-- { -+ o := byte(n >> uint(i*7)) -+ o &= 0x7f -+ if i != 0 { -+ o |= 0x80 -+ } -+ -+ b.add(o) -+ } -+} -+ -+func isValidOID(oid encoding_asn1.ObjectIdentifier) bool { -+ if len(oid) < 2 { -+ return false -+ } -+ -+ if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) { -+ return false -+ } -+ -+ for _, v := range oid { -+ if v < 0 { -+ return false -+ } -+ } -+ -+ return true -+} -+ -+func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) { -+ b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) { -+ if !isValidOID(oid) { -+ b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid) -+ return -+ } -+ -+ b.addBase128Int(int64(oid[0])*40 + int64(oid[1])) -+ for _, v := range oid[2:] { -+ b.addBase128Int(int64(v)) -+ } -+ }) -+} -+ -+func (b *Builder) AddASN1Boolean(v bool) { -+ b.AddASN1(asn1.BOOLEAN, func(b *Builder) { -+ if v { -+ b.AddUint8(0xff) -+ } else { -+ b.AddUint8(0) -+ } -+ }) -+} -+ -+func (b *Builder) AddASN1NULL() { -+ b.add(uint8(asn1.NULL), 0) -+} -+ -+// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if -+// successful or records an error if one occurred. -+func (b *Builder) MarshalASN1(v interface{}) { -+ // NOTE(martinkr): This is somewhat of a hack to allow propagation of -+ // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a -+ // value embedded into a struct, its tag information is lost. -+ if b.err != nil { -+ return -+ } -+ bytes, err := encoding_asn1.Marshal(v) -+ if err != nil { -+ b.err = err -+ return -+ } -+ b.AddBytes(bytes) -+} -+ -+// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. -+// Tags greater than 30 are not supported and result in an error (i.e. -+// low-tag-number form only). The child builder passed to the -+// BuilderContinuation can be used to build the content of the ASN.1 object. -+func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { -+ if b.err != nil { -+ return -+ } -+ // Identifiers with the low five bits set indicate high-tag-number format -+ // (two or more octets), which we don't support. -+ if tag&0x1f == 0x1f { -+ b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) -+ return -+ } -+ b.AddUint8(uint8(tag)) -+ b.addLengthPrefixed(1, true, f) -+} -+ -+// String -+ -+// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean -+// representation into out and advances. It reports whether the read -+// was successful. -+func (s *String) ReadASN1Boolean(out *bool) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { -+ return false -+ } -+ -+ switch bytes[0] { -+ case 0: -+ *out = false -+ case 0xff: -+ *out = true -+ default: -+ return false -+ } -+ -+ return true -+} -+ -+// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does -+// not point to an integer, to a big.Int, or to a []byte it panics. Only -+// positive and zero values can be decoded into []byte, and they are returned as -+// big-endian binary values that share memory with s. Positive values will have -+// no leading zeroes, and zero will be returned as a single zero byte. -+// ReadASN1Integer reports whether the read was successful. -+func (s *String) ReadASN1Integer(out interface{}) bool { -+ switch out := out.(type) { -+ case *int, *int8, *int16, *int32, *int64: -+ var i int64 -+ if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { -+ return false -+ } -+ reflect.ValueOf(out).Elem().SetInt(i) -+ return true -+ case *uint, *uint8, *uint16, *uint32, *uint64: -+ var u uint64 -+ if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { -+ return false -+ } -+ reflect.ValueOf(out).Elem().SetUint(u) -+ return true -+ case *big.Int: -+ return s.readASN1BigInt(out) -+ case *[]byte: -+ return s.readASN1Bytes(out) -+ default: -+ panic("out does not point to an integer type") -+ } -+} -+ -+func checkASN1Integer(bytes []byte) bool { -+ if len(bytes) == 0 { -+ // An INTEGER is encoded with at least one octet. -+ return false -+ } -+ if len(bytes) == 1 { -+ return true -+ } -+ if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 { -+ // Value is not minimally encoded. -+ return false -+ } -+ return true -+} -+ -+var bigOne = big.NewInt(1) -+ -+func (s *String) readASN1BigInt(out *big.Int) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { -+ return false -+ } -+ if bytes[0]&0x80 == 0x80 { -+ // Negative number. -+ neg := make([]byte, len(bytes)) -+ for i, b := range bytes { -+ neg[i] = ^b -+ } -+ out.SetBytes(neg) -+ out.Add(out, bigOne) -+ out.Neg(out) -+ } else { -+ out.SetBytes(bytes) -+ } -+ return true -+} -+ -+func (s *String) readASN1Bytes(out *[]byte) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { -+ return false -+ } -+ if bytes[0]&0x80 == 0x80 { -+ return false -+ } -+ for len(bytes) > 1 && bytes[0] == 0 { -+ bytes = bytes[1:] -+ } -+ *out = bytes -+ return true -+} -+ -+func (s *String) readASN1Int64(out *int64) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { -+ return false -+ } -+ return true -+} -+ -+func asn1Signed(out *int64, n []byte) bool { -+ length := len(n) -+ if length > 8 { -+ return false -+ } -+ for i := 0; i < length; i++ { -+ *out <<= 8 -+ *out |= int64(n[i]) -+ } -+ // Shift up and down in order to sign extend the result. -+ *out <<= 64 - uint8(length)*8 -+ *out >>= 64 - uint8(length)*8 -+ return true -+} -+ -+func (s *String) readASN1Uint64(out *uint64) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) { -+ return false -+ } -+ return true -+} -+ -+func asn1Unsigned(out *uint64, n []byte) bool { -+ length := len(n) -+ if length > 9 || length == 9 && n[0] != 0 { -+ // Too large for uint64. -+ return false -+ } -+ if n[0]&0x80 != 0 { -+ // Negative number. -+ return false -+ } -+ for i := 0; i < length; i++ { -+ *out <<= 8 -+ *out |= uint64(n[i]) -+ } -+ return true -+} -+ -+// ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out -+// and advances. It reports whether the read was successful and resulted in a -+// value that can be represented in an int64. -+func (s *String) ReadASN1Int64WithTag(out *int64, tag asn1.Tag) bool { -+ var bytes String -+ return s.ReadASN1(&bytes, tag) && checkASN1Integer(bytes) && asn1Signed(out, bytes) -+} -+ -+// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports -+// whether the read was successful. -+func (s *String) ReadASN1Enum(out *int) bool { -+ var bytes String -+ var i int64 -+ if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) { -+ return false -+ } -+ if int64(int(i)) != i { -+ return false -+ } -+ *out = int(i) -+ return true -+} -+ -+func (s *String) readBase128Int(out *int) bool { -+ ret := 0 -+ for i := 0; len(*s) > 0; i++ { -+ if i == 5 { -+ return false -+ } -+ // Avoid overflowing int on a 32-bit platform. -+ // We don't want different behavior based on the architecture. -+ if ret >= 1<<(31-7) { -+ return false -+ } -+ ret <<= 7 -+ b := s.read(1)[0] -+ -+ // ITU-T X.690, section 8.19.2: -+ // The subidentifier shall be encoded in the fewest possible octets, -+ // that is, the leading octet of the subidentifier shall not have the value 0x80. -+ if i == 0 && b == 0x80 { -+ return false -+ } -+ -+ ret |= int(b & 0x7f) -+ if b&0x80 == 0 { -+ *out = ret -+ return true -+ } -+ } -+ return false // truncated -+} -+ -+// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and -+// advances. It reports whether the read was successful. -+func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { -+ return false -+ } -+ -+ // In the worst case, we get two elements from the first byte (which is -+ // encoded differently) and then every varint is a single byte long. -+ components := make([]int, len(bytes)+1) -+ -+ // The first varint is 40*value1 + value2: -+ // According to this packing, value1 can take the values 0, 1 and 2 only. -+ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, -+ // then there are no restrictions on value2. -+ var v int -+ if !bytes.readBase128Int(&v) { -+ return false -+ } -+ if v < 80 { -+ components[0] = v / 40 -+ components[1] = v % 40 -+ } else { -+ components[0] = 2 -+ components[1] = v - 80 -+ } -+ -+ i := 2 -+ for ; len(bytes) > 0; i++ { -+ if !bytes.readBase128Int(&v) { -+ return false -+ } -+ components[i] = v -+ } -+ *out = components[:i] -+ return true -+} -+ -+// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and -+// advances. It reports whether the read was successful. -+func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { -+ return false -+ } -+ t := string(bytes) -+ res, err := time.Parse(generalizedTimeFormatStr, t) -+ if err != nil { -+ return false -+ } -+ if serialized := res.Format(generalizedTimeFormatStr); serialized != t { -+ return false -+ } -+ *out = res -+ return true -+} -+ -+const defaultUTCTimeFormatStr = "060102150405Z0700" -+ -+// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. -+// It reports whether the read was successful. -+func (s *String) ReadASN1UTCTime(out *time.Time) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.UTCTime) { -+ return false -+ } -+ t := string(bytes) -+ -+ formatStr := defaultUTCTimeFormatStr -+ var err error -+ res, err := time.Parse(formatStr, t) -+ if err != nil { -+ // Fallback to minute precision if we can't parse second -+ // precision. If we are following X.509 or X.690 we shouldn't -+ // support this, but we do. -+ formatStr = "0601021504Z0700" -+ res, err = time.Parse(formatStr, t) -+ } -+ if err != nil { -+ return false -+ } -+ -+ if serialized := res.Format(formatStr); serialized != t { -+ return false -+ } -+ -+ if res.Year() >= 2050 { -+ // UTCTime interprets the low order digits 50-99 as 1950-99. -+ // This only applies to its use in the X.509 profile. -+ // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 -+ res = res.AddDate(-100, 0, 0) -+ } -+ *out = res -+ return true -+} -+ -+// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. -+// It reports whether the read was successful. -+func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { -+ var bytes String -+ if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || -+ len(bytes)*8/8 != len(bytes) { -+ return false -+ } -+ -+ paddingBits := bytes[0] -+ bytes = bytes[1:] -+ if paddingBits > 7 || -+ len(bytes) == 0 && paddingBits != 0 || -+ len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) { -+ return false -+ } -+ -+ lenBytes := String((*s)[2 : 2+lenLen]) -+ if !lenBytes.readUnsigned(&len32, int(lenLen)) { -+ return false -+ } -+ -+ // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length -+ // with the minimum number of octets. -+ if len32 < 128 { -+ // Length should have used short-form encoding. -+ return false -+ } -+ if len32>>((lenLen-1)*8) == 0 { -+ // Leading octet is 0. Length should have been at least one byte shorter. -+ return false -+ } -+ -+ headerLen = 2 + uint32(lenLen) -+ if headerLen+len32 < len32 { -+ // Overflow. -+ return false -+ } -+ length = headerLen + len32 -+ } -+ -+ if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { -+ return false -+ } -+ if skipHeader && !out.Skip(int(headerLen)) { -+ panic("cryptobyte: internal error") -+ } -+ -+ return true -+} -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go -new file mode 100644 -index 00000000000000..cda8e3edfd5ea4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/asn1/asn1.go -@@ -0,0 +1,46 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package asn1 contains supporting types for parsing and building ASN.1 -+// messages with the cryptobyte package. -+package asn1 // import "golang.org/x/crypto/cryptobyte/asn1" -+ -+// Tag represents an ASN.1 identifier octet, consisting of a tag number -+// (indicating a type) and class (such as context-specific or constructed). -+// -+// Methods in the cryptobyte package only support the low-tag-number form, i.e. -+// a single identifier octet with bits 7-8 encoding the class and bits 1-6 -+// encoding the tag number. -+type Tag uint8 -+ -+const ( -+ classConstructed = 0x20 -+ classContextSpecific = 0x80 -+) -+ -+// Constructed returns t with the constructed class bit set. -+func (t Tag) Constructed() Tag { return t | classConstructed } -+ -+// ContextSpecific returns t with the context-specific class bit set. -+func (t Tag) ContextSpecific() Tag { return t | classContextSpecific } -+ -+// The following is a list of standard tag and class combinations. -+const ( -+ BOOLEAN = Tag(1) -+ INTEGER = Tag(2) -+ BIT_STRING = Tag(3) -+ OCTET_STRING = Tag(4) -+ NULL = Tag(5) -+ OBJECT_IDENTIFIER = Tag(6) -+ ENUM = Tag(10) -+ UTF8String = Tag(12) -+ SEQUENCE = Tag(16 | classConstructed) -+ SET = Tag(17 | classConstructed) -+ PrintableString = Tag(19) -+ T61String = Tag(20) -+ IA5String = Tag(22) -+ UTCTime = Tag(23) -+ GeneralizedTime = Tag(24) -+ GeneralString = Tag(27) -+) -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go b/ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go -new file mode 100644 -index 00000000000000..e3f53a932ee847 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/asn1_test.go -@@ -0,0 +1,435 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package cryptobyte -+ -+import ( -+ "bytes" -+ encoding_asn1 "encoding/asn1" -+ "math/big" -+ "reflect" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+type readASN1Test struct { -+ name string -+ in []byte -+ tag asn1.Tag -+ ok bool -+ out interface{} -+} -+ -+var readASN1TestData = []readASN1Test{ -+ {"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}}, -+ {"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil}, -+ {"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil}, -+ {"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil}, -+ {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil}, -+ {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil}, -+ {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil}, -+ {"2**31 - 1 length", []byte{0x30, 0x84, 0x7f, 0xff, 0xff, 0xff}, 0x30, false, nil}, -+ {"2**32 - 1 length", []byte{0x30, 0x84, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, -+ {"2**63 - 1 length", []byte{0x30, 0x88, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, -+ {"2**64 - 1 length", []byte{0x30, 0x88, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0x30, false, nil}, -+} -+ -+func TestReadASN1(t *testing.T) { -+ for _, test := range readASN1TestData { -+ t.Run(test.name, func(t *testing.T) { -+ var in, out String = test.in, nil -+ ok := in.ReadASN1(&out, test.tag) -+ if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) { -+ t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) -+ } -+ }) -+ } -+} -+ -+func TestReadASN1Optional(t *testing.T) { -+ var empty String -+ var present bool -+ ok := empty.ReadOptionalASN1(nil, &present, 0xa0) -+ if !ok || present { -+ t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present) -+ } -+ -+ var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil -+ ok = in.ReadOptionalASN1(&out, &present, 0xa0) -+ if !ok || present { -+ t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present) -+ } -+ ok = in.ReadOptionalASN1(&out, &present, 0xa1) -+ wantBytes := []byte{4, 1, 1} -+ if !ok || !present || !bytes.Equal(out, wantBytes) { -+ t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes) -+ } -+} -+ -+var optionalOctetStringTestData = []struct { -+ readASN1Test -+ present bool -+}{ -+ {readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false}, -+ {readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true}, -+ {readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false}, -+ {readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true}, -+} -+ -+func TestReadASN1OptionalOctetString(t *testing.T) { -+ for _, test := range optionalOctetStringTestData { -+ t.Run(test.name, func(t *testing.T) { -+ in := String(test.in) -+ var out []byte -+ var present bool -+ ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag) -+ if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) { -+ t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out) -+ } -+ }) -+ } -+} -+ -+const defaultInt = -1 -+ -+var optionalIntTestData = []readASN1Test{ -+ {"empty", []byte{}, 0xa0, true, defaultInt}, -+ {"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0}, -+ {"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt}, -+ {"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42}, -+} -+ -+func TestReadASN1OptionalInteger(t *testing.T) { -+ for _, test := range optionalIntTestData { -+ t.Run(test.name, func(t *testing.T) { -+ in := String(test.in) -+ var out int -+ ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt) -+ if ok != test.ok || ok && out != test.out.(int) { -+ t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) -+ } -+ }) -+ } -+} -+ -+func TestReadASN1IntegerSigned(t *testing.T) { -+ testData64 := []struct { -+ in []byte -+ out int64 -+ }{ -+ {[]byte{2, 3, 128, 0, 0}, -0x800000}, -+ {[]byte{2, 2, 255, 0}, -256}, -+ {[]byte{2, 2, 255, 127}, -129}, -+ {[]byte{2, 1, 128}, -128}, -+ {[]byte{2, 1, 255}, -1}, -+ {[]byte{2, 1, 0}, 0}, -+ {[]byte{2, 1, 1}, 1}, -+ {[]byte{2, 1, 2}, 2}, -+ {[]byte{2, 1, 127}, 127}, -+ {[]byte{2, 2, 0, 128}, 128}, -+ {[]byte{2, 2, 1, 0}, 256}, -+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000}, -+ } -+ for i, test := range testData64 { -+ in := String(test.in) -+ var out int64 -+ ok := in.ReadASN1Integer(&out) -+ if !ok || out != test.out { -+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out) -+ } -+ } -+ -+ // Repeat the same cases, reading into a big.Int. -+ t.Run("big.Int", func(t *testing.T) { -+ for i, test := range testData64 { -+ in := String(test.in) -+ var out big.Int -+ ok := in.ReadASN1Integer(&out) -+ if !ok || out.Int64() != test.out { -+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out) -+ } -+ } -+ }) -+ -+ // Repeat the same cases, reading into a []byte. -+ t.Run("bytes", func(t *testing.T) { -+ for i, test := range testData64 { -+ in := String(test.in) -+ var out []byte -+ ok := in.ReadASN1Integer(&out) -+ if test.out < 0 { -+ if ok { -+ t.Errorf("#%d: in.ReadASN1Integer(%d) = %v, want false", i, test.out, ok) -+ } -+ continue -+ } -+ if !ok { -+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true", i, ok) -+ continue -+ } -+ n := new(big.Int).SetBytes(out).Int64() -+ if n != test.out { -+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %x, want %d", i, ok, out, test.out) -+ } -+ if out[0] == 0 && len(out) > 1 { -+ t.Errorf("#%d: in.ReadASN1Integer() = %v; out = %x, has leading zeroes", i, ok, out) -+ } -+ } -+ }) -+ -+ // Repeat with the implicit-tagging functions -+ t.Run("WithTag", func(t *testing.T) { -+ for i, test := range testData64 { -+ tag := asn1.Tag((i * 3) % 32).ContextSpecific() -+ -+ testData := make([]byte, len(test.in)) -+ copy(testData, test.in) -+ -+ // Alter the tag of the test case. -+ testData[0] = uint8(tag) -+ -+ in := String(testData) -+ var out int64 -+ ok := in.ReadASN1Int64WithTag(&out, tag) -+ if !ok || out != test.out { -+ t.Errorf("#%d: in.ReadASN1Int64WithTag() = %v, want true; out = %d, want %d", i, ok, out, test.out) -+ } -+ -+ var b Builder -+ b.AddASN1Int64WithTag(test.out, tag) -+ result, err := b.Bytes() -+ -+ if err != nil { -+ t.Errorf("#%d: AddASN1Int64WithTag failed: %s", i, err) -+ continue -+ } -+ -+ if !bytes.Equal(result, testData) { -+ t.Errorf("#%d: AddASN1Int64WithTag: got %x, want %x", i, result, testData) -+ } -+ } -+ }) -+} -+ -+func TestReadASN1IntegerUnsigned(t *testing.T) { -+ testData := []struct { -+ in []byte -+ out uint64 -+ }{ -+ {[]byte{2, 1, 0}, 0}, -+ {[]byte{2, 1, 1}, 1}, -+ {[]byte{2, 1, 2}, 2}, -+ {[]byte{2, 1, 127}, 127}, -+ {[]byte{2, 2, 0, 128}, 128}, -+ {[]byte{2, 2, 1, 0}, 256}, -+ {[]byte{2, 4, 0, 128, 0, 0}, 0x800000}, -+ {[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff}, -+ {[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000}, -+ {[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff}, -+ } -+ for i, test := range testData { -+ in := String(test.in) -+ var out uint64 -+ ok := in.ReadASN1Integer(&out) -+ if !ok || out != test.out { -+ t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out) -+ } -+ } -+} -+ -+func TestReadASN1IntegerInvalid(t *testing.T) { -+ testData := []String{ -+ []byte{3, 1, 0}, // invalid tag -+ // truncated -+ []byte{2, 1}, -+ []byte{2, 2, 0}, -+ // not minimally encoded -+ []byte{2, 2, 0, 1}, -+ []byte{2, 2, 0xff, 0xff}, -+ } -+ -+ for i, test := range testData { -+ var out int64 -+ if test.ReadASN1Integer(&out) { -+ t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out) -+ } -+ } -+} -+ -+func TestASN1ObjectIdentifier(t *testing.T) { -+ testData := []struct { -+ in []byte -+ ok bool -+ out []int -+ }{ -+ {[]byte{}, false, []int{}}, -+ {[]byte{6, 0}, false, []int{}}, -+ {[]byte{5, 1, 85}, false, []int{2, 5}}, -+ {[]byte{6, 1, 85}, true, []int{2, 5}}, -+ {[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}}, -+ {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, -+ {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}}, -+ {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, -+ {[]byte{6, 7, 85, 0x02, 0x85, 0xc7, 0xcc, 0xfb, 0x01}, true, []int{2, 5, 2, 1492336001}}, -+ {[]byte{6, 7, 0x55, 0x02, 0x87, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 2147483647}}, // 2**31-1 -+ {[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**31 -+ {[]byte{6, 3, 85, 0x80, 0x02}, false, []int{}}, // leading 0x80 octet -+ } -+ -+ for i, test := range testData { -+ in := String(test.in) -+ var out encoding_asn1.ObjectIdentifier -+ ok := in.ReadASN1ObjectIdentifier(&out) -+ if ok != test.ok || ok && !out.Equal(test.out) { -+ t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) -+ continue -+ } -+ -+ var b Builder -+ b.AddASN1ObjectIdentifier(out) -+ result, err := b.Bytes() -+ if builderOk := err == nil; test.ok != builderOk { -+ t.Errorf("#%d: error from Builder.Bytes: %s", i, err) -+ continue -+ } -+ if test.ok && !bytes.Equal(result, test.in) { -+ t.Errorf("#%d: reserialisation didn't match, got %x, want %x", i, result, test.in) -+ continue -+ } -+ } -+} -+ -+func TestReadASN1GeneralizedTime(t *testing.T) { -+ testData := []struct { -+ in string -+ ok bool -+ out time.Time -+ }{ -+ {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"20100102030405", false, time.Time{}}, -+ {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}, -+ {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))}, -+ /* These are invalid times. However, the time package normalises times -+ * and they were accepted in some versions. See #11134. */ -+ {"00000100000000Z", false, time.Time{}}, -+ {"20101302030405Z", false, time.Time{}}, -+ {"20100002030405Z", false, time.Time{}}, -+ {"20100100030405Z", false, time.Time{}}, -+ {"20100132030405Z", false, time.Time{}}, -+ {"20100231030405Z", false, time.Time{}}, -+ {"20100102240405Z", false, time.Time{}}, -+ {"20100102036005Z", false, time.Time{}}, -+ {"20100102030460Z", false, time.Time{}}, -+ {"-20100102030410Z", false, time.Time{}}, -+ {"2010-0102030410Z", false, time.Time{}}, -+ {"2010-0002030410Z", false, time.Time{}}, -+ {"201001-02030410Z", false, time.Time{}}, -+ {"20100102-030410Z", false, time.Time{}}, -+ {"2010010203-0410Z", false, time.Time{}}, -+ {"201001020304-10Z", false, time.Time{}}, -+ } -+ for i, test := range testData { -+ in := String(append([]byte{byte(asn1.GeneralizedTime), byte(len(test.in))}, test.in...)) -+ var out time.Time -+ ok := in.ReadASN1GeneralizedTime(&out) -+ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) { -+ t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out) -+ } -+ } -+} -+ -+func TestReadASN1UTCTime(t *testing.T) { -+ testData := []struct { -+ in string -+ ok bool -+ out time.Time -+ }{ -+ {"000102030405Z", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"500102030405Z", true, time.Date(1950, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"490102030405Z", true, time.Date(2049, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"990102030405Z", true, time.Date(1999, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"250102030405Z", true, time.Date(2025, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"750102030405Z", true, time.Date(1975, 01, 02, 03, 04, 05, 0, time.UTC)}, -+ {"000102030405+0905", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.FixedZone("", 9*60*60+5*60))}, -+ {"000102030405-0905", true, time.Date(2000, 01, 02, 03, 04, 05, 0, time.FixedZone("", -9*60*60-5*60))}, -+ {"0001020304Z", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.UTC)}, -+ {"5001020304Z", true, time.Date(1950, 01, 02, 03, 04, 00, 0, time.UTC)}, -+ {"0001020304+0905", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.FixedZone("", 9*60*60+5*60))}, -+ {"0001020304-0905", true, time.Date(2000, 01, 02, 03, 04, 0, 0, time.FixedZone("", -9*60*60-5*60))}, -+ {"000102030405Z0700", false, time.Time{}}, -+ {"000102030405", false, time.Time{}}, -+ } -+ for i, test := range testData { -+ in := String(append([]byte{byte(asn1.UTCTime), byte(len(test.in))}, test.in...)) -+ var out time.Time -+ ok := in.ReadASN1UTCTime(&out) -+ if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) { -+ t.Errorf("#%d: in.ReadASN1UTCTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out) -+ } -+ } -+} -+ -+func TestReadASN1BitString(t *testing.T) { -+ testData := []struct { -+ in []byte -+ ok bool -+ out encoding_asn1.BitString -+ }{ -+ {[]byte{}, false, encoding_asn1.BitString{}}, -+ {[]byte{0x00}, true, encoding_asn1.BitString{}}, -+ {[]byte{0x07, 0x00}, true, encoding_asn1.BitString{Bytes: []byte{0}, BitLength: 1}}, -+ {[]byte{0x07, 0x01}, false, encoding_asn1.BitString{}}, -+ {[]byte{0x07, 0x40}, false, encoding_asn1.BitString{}}, -+ {[]byte{0x08, 0x00}, false, encoding_asn1.BitString{}}, -+ {[]byte{0xff}, false, encoding_asn1.BitString{}}, -+ {[]byte{0xfe, 0x00}, false, encoding_asn1.BitString{}}, -+ } -+ for i, test := range testData { -+ in := String(append([]byte{3, byte(len(test.in))}, test.in...)) -+ var out encoding_asn1.BitString -+ ok := in.ReadASN1BitString(&out) -+ if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) { -+ t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) -+ } -+ } -+} -+ -+func TestAddASN1BigInt(t *testing.T) { -+ x := big.NewInt(-1) -+ var b Builder -+ b.AddASN1BigInt(x) -+ got, err := b.Bytes() -+ if err != nil { -+ t.Fatalf("unexpected error adding -1: %v", err) -+ } -+ s := String(got) -+ var y big.Int -+ ok := s.ReadASN1Integer(&y) -+ if !ok || x.Cmp(&y) != 0 { -+ t.Errorf("unexpected bytes %v, want %v", &y, x) -+ } -+} -+ -+func TestReadASN1Boolean(t *testing.T) { -+ testData := []struct { -+ in []byte -+ ok bool -+ out bool -+ }{ -+ {[]byte{}, false, false}, -+ {[]byte{0x01, 0x01, 0x00}, true, false}, -+ {[]byte{0x01, 0x01, 0xff}, true, true}, -+ {[]byte{0x01, 0x01, 0x01}, false, false}, -+ } -+ for i, test := range testData { -+ in := String(test.in) -+ var out bool -+ ok := in.ReadASN1Boolean(&out) -+ if ok != test.ok || ok && (out != test.out) { -+ t.Errorf("#%d: in.ReadASN1Boolean() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/builder.go b/ms_mod/golang.org/x/crypto/cryptobyte/builder.go -new file mode 100644 -index 00000000000000..c05ac7d16da71e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/builder.go -@@ -0,0 +1,345 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package cryptobyte -+ -+import ( -+ "errors" -+ "fmt" -+) -+ -+// A Builder builds byte strings from fixed-length and length-prefixed values. -+// Builders either allocate space as needed, or are β€˜fixed’, which means that -+// they write into a given buffer and produce an error if it's exhausted. -+// -+// The zero value is a usable Builder that allocates space as needed. -+// -+// Simple values are marshaled and appended to a Builder using methods on the -+// Builder. Length-prefixed values are marshaled by providing a -+// BuilderContinuation, which is a function that writes the inner contents of -+// the value to a given Builder. See the documentation for BuilderContinuation -+// for details. -+type Builder struct { -+ err error -+ result []byte -+ fixedSize bool -+ child *Builder -+ offset int -+ pendingLenLen int -+ pendingIsASN1 bool -+ inContinuation *bool -+} -+ -+// NewBuilder creates a Builder that appends its output to the given buffer. -+// Like append(), the slice will be reallocated if its capacity is exceeded. -+// Use Bytes to get the final buffer. -+func NewBuilder(buffer []byte) *Builder { -+ return &Builder{ -+ result: buffer, -+ } -+} -+ -+// NewFixedBuilder creates a Builder that appends its output into the given -+// buffer. This builder does not reallocate the output buffer. Writes that -+// would exceed the buffer's capacity are treated as an error. -+func NewFixedBuilder(buffer []byte) *Builder { -+ return &Builder{ -+ result: buffer, -+ fixedSize: true, -+ } -+} -+ -+// SetError sets the value to be returned as the error from Bytes. Writes -+// performed after calling SetError are ignored. -+func (b *Builder) SetError(err error) { -+ b.err = err -+} -+ -+// Bytes returns the bytes written by the builder or an error if one has -+// occurred during building. -+func (b *Builder) Bytes() ([]byte, error) { -+ if b.err != nil { -+ return nil, b.err -+ } -+ return b.result[b.offset:], nil -+} -+ -+// BytesOrPanic returns the bytes written by the builder or panics if an error -+// has occurred during building. -+func (b *Builder) BytesOrPanic() []byte { -+ if b.err != nil { -+ panic(b.err) -+ } -+ return b.result[b.offset:] -+} -+ -+// AddUint8 appends an 8-bit value to the byte string. -+func (b *Builder) AddUint8(v uint8) { -+ b.add(byte(v)) -+} -+ -+// AddUint16 appends a big-endian, 16-bit value to the byte string. -+func (b *Builder) AddUint16(v uint16) { -+ b.add(byte(v>>8), byte(v)) -+} -+ -+// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest -+// byte of the 32-bit input value is silently truncated. -+func (b *Builder) AddUint24(v uint32) { -+ b.add(byte(v>>16), byte(v>>8), byte(v)) -+} -+ -+// AddUint32 appends a big-endian, 32-bit value to the byte string. -+func (b *Builder) AddUint32(v uint32) { -+ b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) -+} -+ -+// AddUint64 appends a big-endian, 64-bit value to the byte string. -+func (b *Builder) AddUint64(v uint64) { -+ b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) -+} -+ -+// AddBytes appends a sequence of bytes to the byte string. -+func (b *Builder) AddBytes(v []byte) { -+ b.add(v...) -+} -+ -+// BuilderContinuation is a continuation-passing interface for building -+// length-prefixed byte sequences. Builder methods for length-prefixed -+// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation -+// supplied to them. The child builder passed to the continuation can be used -+// to build the content of the length-prefixed sequence. For example: -+// -+// parent := cryptobyte.NewBuilder() -+// parent.AddUint8LengthPrefixed(func (child *Builder) { -+// child.AddUint8(42) -+// child.AddUint8LengthPrefixed(func (grandchild *Builder) { -+// grandchild.AddUint8(5) -+// }) -+// }) -+// -+// It is an error to write more bytes to the child than allowed by the reserved -+// length prefix. After the continuation returns, the child must be considered -+// invalid, i.e. users must not store any copies or references of the child -+// that outlive the continuation. -+// -+// If the continuation panics with a value of type BuildError then the inner -+// error will be returned as the error from Bytes. If the child panics -+// otherwise then Bytes will repanic with the same value. -+type BuilderContinuation func(child *Builder) -+ -+// BuildError wraps an error. If a BuilderContinuation panics with this value, -+// the panic will be recovered and the inner error will be returned from -+// Builder.Bytes. -+type BuildError struct { -+ Err error -+} -+ -+// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence. -+func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) { -+ b.addLengthPrefixed(1, false, f) -+} -+ -+// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence. -+func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) { -+ b.addLengthPrefixed(2, false, f) -+} -+ -+// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence. -+func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) { -+ b.addLengthPrefixed(3, false, f) -+} -+ -+// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence. -+func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) { -+ b.addLengthPrefixed(4, false, f) -+} -+ -+func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) { -+ if !*b.inContinuation { -+ *b.inContinuation = true -+ -+ defer func() { -+ *b.inContinuation = false -+ -+ r := recover() -+ if r == nil { -+ return -+ } -+ -+ if buildError, ok := r.(BuildError); ok { -+ b.err = buildError.Err -+ } else { -+ panic(r) -+ } -+ }() -+ } -+ -+ f(arg) -+} -+ -+func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) { -+ // Subsequent writes can be ignored if the builder has encountered an error. -+ if b.err != nil { -+ return -+ } -+ -+ offset := len(b.result) -+ b.add(make([]byte, lenLen)...) -+ -+ if b.inContinuation == nil { -+ b.inContinuation = new(bool) -+ } -+ -+ b.child = &Builder{ -+ result: b.result, -+ fixedSize: b.fixedSize, -+ offset: offset, -+ pendingLenLen: lenLen, -+ pendingIsASN1: isASN1, -+ inContinuation: b.inContinuation, -+ } -+ -+ b.callContinuation(f, b.child) -+ b.flushChild() -+ if b.child != nil { -+ panic("cryptobyte: internal error") -+ } -+} -+ -+func (b *Builder) flushChild() { -+ if b.child == nil { -+ return -+ } -+ b.child.flushChild() -+ child := b.child -+ b.child = nil -+ -+ if child.err != nil { -+ b.err = child.err -+ return -+ } -+ -+ length := len(child.result) - child.pendingLenLen - child.offset -+ -+ if length < 0 { -+ panic("cryptobyte: internal error") // result unexpectedly shrunk -+ } -+ -+ if child.pendingIsASN1 { -+ // For ASN.1, we reserved a single byte for the length. If that turned out -+ // to be incorrect, we have to move the contents along in order to make -+ // space. -+ if child.pendingLenLen != 1 { -+ panic("cryptobyte: internal error") -+ } -+ var lenLen, lenByte uint8 -+ if int64(length) > 0xfffffffe { -+ b.err = errors.New("pending ASN.1 child too long") -+ return -+ } else if length > 0xffffff { -+ lenLen = 5 -+ lenByte = 0x80 | 4 -+ } else if length > 0xffff { -+ lenLen = 4 -+ lenByte = 0x80 | 3 -+ } else if length > 0xff { -+ lenLen = 3 -+ lenByte = 0x80 | 2 -+ } else if length > 0x7f { -+ lenLen = 2 -+ lenByte = 0x80 | 1 -+ } else { -+ lenLen = 1 -+ lenByte = uint8(length) -+ length = 0 -+ } -+ -+ // Insert the initial length byte, make space for successive length bytes, -+ // and adjust the offset. -+ child.result[child.offset] = lenByte -+ extraBytes := int(lenLen - 1) -+ if extraBytes != 0 { -+ child.add(make([]byte, extraBytes)...) -+ childStart := child.offset + child.pendingLenLen -+ copy(child.result[childStart+extraBytes:], child.result[childStart:]) -+ } -+ child.offset++ -+ child.pendingLenLen = extraBytes -+ } -+ -+ l := length -+ for i := child.pendingLenLen - 1; i >= 0; i-- { -+ child.result[child.offset+i] = uint8(l) -+ l >>= 8 -+ } -+ if l != 0 { -+ b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen) -+ return -+ } -+ -+ if b.fixedSize && &b.result[0] != &child.result[0] { -+ panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer") -+ } -+ -+ b.result = child.result -+} -+ -+func (b *Builder) add(bytes ...byte) { -+ if b.err != nil { -+ return -+ } -+ if b.child != nil { -+ panic("cryptobyte: attempted write while child is pending") -+ } -+ if len(b.result)+len(bytes) < len(bytes) { -+ b.err = errors.New("cryptobyte: length overflow") -+ } -+ if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) { -+ b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer") -+ return -+ } -+ b.result = append(b.result, bytes...) -+} -+ -+// Unwrite rolls back non-negative n bytes written directly to the Builder. -+// An attempt by a child builder passed to a continuation to unwrite bytes -+// from its parent will panic. -+func (b *Builder) Unwrite(n int) { -+ if b.err != nil { -+ return -+ } -+ if b.child != nil { -+ panic("cryptobyte: attempted unwrite while child is pending") -+ } -+ length := len(b.result) - b.pendingLenLen - b.offset -+ if length < 0 { -+ panic("cryptobyte: internal error") -+ } -+ if n < 0 { -+ panic("cryptobyte: attempted to unwrite negative number of bytes") -+ } -+ if n > length { -+ panic("cryptobyte: attempted to unwrite more than was written") -+ } -+ b.result = b.result[:len(b.result)-n] -+} -+ -+// A MarshalingValue marshals itself into a Builder. -+type MarshalingValue interface { -+ // Marshal is called by Builder.AddValue. It receives a pointer to a builder -+ // to marshal itself into. It may return an error that occurred during -+ // marshaling, such as unset or invalid values. -+ Marshal(b *Builder) error -+} -+ -+// AddValue calls Marshal on v, passing a pointer to the builder to append to. -+// If Marshal returns an error, it is set on the Builder so that subsequent -+// appends don't have an effect. -+func (b *Builder) AddValue(v MarshalingValue) { -+ err := v.Marshal(b) -+ if err != nil { -+ b.err = err -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go b/ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go -new file mode 100644 -index 00000000000000..dc90e81fa93e4c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/cryptobyte_test.go -@@ -0,0 +1,536 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package cryptobyte -+ -+import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "testing" -+) -+ -+func builderBytesEq(b *Builder, want ...byte) error { -+ got := b.BytesOrPanic() -+ if !bytes.Equal(got, want) { -+ return fmt.Errorf("Bytes() = %v, want %v", got, want) -+ } -+ return nil -+} -+ -+func TestContinuationError(t *testing.T) { -+ const errorStr = "TestContinuationError" -+ var b Builder -+ b.AddUint8LengthPrefixed(func(b *Builder) { -+ b.AddUint8(1) -+ panic(BuildError{Err: errors.New(errorStr)}) -+ }) -+ -+ ret, err := b.Bytes() -+ if ret != nil { -+ t.Error("expected nil result") -+ } -+ if err == nil { -+ t.Fatal("unexpected nil error") -+ } -+ if s := err.Error(); s != errorStr { -+ t.Errorf("expected error %q, got %v", errorStr, s) -+ } -+} -+ -+func TestContinuationNonError(t *testing.T) { -+ defer func() { -+ recover() -+ }() -+ -+ var b Builder -+ b.AddUint8LengthPrefixed(func(b *Builder) { -+ b.AddUint8(1) -+ panic(1) -+ }) -+ -+ t.Error("Builder did not panic") -+} -+ -+func TestGeneratedPanic(t *testing.T) { -+ defer func() { -+ recover() -+ }() -+ -+ var b Builder -+ b.AddUint8LengthPrefixed(func(b *Builder) { -+ var p *byte -+ *p = 0 -+ }) -+ -+ t.Error("Builder did not panic") -+} -+ -+func TestBytes(t *testing.T) { -+ var b Builder -+ v := []byte("foobarbaz") -+ b.AddBytes(v[0:3]) -+ b.AddBytes(v[3:4]) -+ b.AddBytes(v[4:9]) -+ if err := builderBytesEq(&b, v...); err != nil { -+ t.Error(err) -+ } -+ s := String(b.BytesOrPanic()) -+ for _, w := range []string{"foo", "bar", "baz"} { -+ var got []byte -+ if !s.ReadBytes(&got, 3) { -+ t.Errorf("ReadBytes() = false, want true (w = %v)", w) -+ } -+ want := []byte(w) -+ if !bytes.Equal(got, want) { -+ t.Errorf("ReadBytes(): got = %v, want %v", got, want) -+ } -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUint8(t *testing.T) { -+ var b Builder -+ b.AddUint8(42) -+ if err := builderBytesEq(&b, 42); err != nil { -+ t.Error(err) -+ } -+ -+ var s String = b.BytesOrPanic() -+ var v uint8 -+ if !s.ReadUint8(&v) { -+ t.Error("ReadUint8() = false, want true") -+ } -+ if v != 42 { -+ t.Errorf("v = %d, want 42", v) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUint16(t *testing.T) { -+ var b Builder -+ b.AddUint16(65534) -+ if err := builderBytesEq(&b, 255, 254); err != nil { -+ t.Error(err) -+ } -+ var s String = b.BytesOrPanic() -+ var v uint16 -+ if !s.ReadUint16(&v) { -+ t.Error("ReadUint16() == false, want true") -+ } -+ if v != 65534 { -+ t.Errorf("v = %d, want 65534", v) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUint24(t *testing.T) { -+ var b Builder -+ b.AddUint24(0xfffefd) -+ if err := builderBytesEq(&b, 255, 254, 253); err != nil { -+ t.Error(err) -+ } -+ -+ var s String = b.BytesOrPanic() -+ var v uint32 -+ if !s.ReadUint24(&v) { -+ t.Error("ReadUint24() = false, want true") -+ } -+ if v != 0xfffefd { -+ t.Errorf("v = %d, want fffefd", v) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUint24Truncation(t *testing.T) { -+ var b Builder -+ b.AddUint24(0x10111213) -+ if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestUint32(t *testing.T) { -+ var b Builder -+ b.AddUint32(0xfffefdfc) -+ if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil { -+ t.Error(err) -+ } -+ -+ var s String = b.BytesOrPanic() -+ var v uint32 -+ if !s.ReadUint32(&v) { -+ t.Error("ReadUint32() = false, want true") -+ } -+ if v != 0xfffefdfc { -+ t.Errorf("v = %x, want fffefdfc", v) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUint64(t *testing.T) { -+ var b Builder -+ b.AddUint64(0xf2fefefcff3cfdfc) -+ if err := builderBytesEq(&b, 242, 254, 254, 252, 255, 60, 253, 252); err != nil { -+ t.Error(err) -+ } -+ -+ var s String = b.BytesOrPanic() -+ var v uint64 -+ if !s.ReadUint64(&v) { -+ t.Error("ReadUint64() = false, want true") -+ } -+ if v != 0xf2fefefcff3cfdfc { -+ t.Errorf("v = %x, want f2fefefcff3cfdfc", v) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUMultiple(t *testing.T) { -+ var b Builder -+ b.AddUint8(23) -+ b.AddUint32(0xfffefdfc) -+ b.AddUint16(42) -+ if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil { -+ t.Error(err) -+ } -+ -+ var s String = b.BytesOrPanic() -+ var ( -+ x uint8 -+ y uint32 -+ z uint16 -+ ) -+ if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) { -+ t.Error("ReadUint8() = false, want true") -+ } -+ if x != 23 || y != 0xfffefdfc || z != 42 { -+ t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+} -+ -+func TestUint8LengthPrefixedSimple(t *testing.T) { -+ var b Builder -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ c.AddUint8(23) -+ c.AddUint8(42) -+ }) -+ if err := builderBytesEq(&b, 2, 23, 42); err != nil { -+ t.Error(err) -+ } -+ -+ var base, child String = b.BytesOrPanic(), nil -+ var x, y uint8 -+ if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || -+ !child.ReadUint8(&y) { -+ t.Error("parsing failed") -+ } -+ if x != 23 || y != 42 { -+ t.Errorf("want x, y == 23, 42; got %d, %d", x, y) -+ } -+ if len(base) != 0 { -+ t.Errorf("len(base) = %d, want 0", len(base)) -+ } -+ if len(child) != 0 { -+ t.Errorf("len(child) = %d, want 0", len(child)) -+ } -+} -+ -+func TestUint8LengthPrefixedMulti(t *testing.T) { -+ var b Builder -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ c.AddUint8(23) -+ c.AddUint8(42) -+ }) -+ b.AddUint8(5) -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ c.AddUint8(123) -+ c.AddUint8(234) -+ }) -+ if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil { -+ t.Error(err) -+ } -+ -+ var s, child String = b.BytesOrPanic(), nil -+ var u, v, w, x, y uint8 -+ if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) || -+ !s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) { -+ t.Error("parsing failed") -+ } -+ if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 { -+ t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234", -+ u, v, w, x, y) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+ if len(child) != 0 { -+ t.Errorf("len(child) = %d, want 0", len(child)) -+ } -+} -+ -+func TestUint8LengthPrefixedNested(t *testing.T) { -+ var b Builder -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ c.AddUint8(5) -+ c.AddUint8LengthPrefixed(func(d *Builder) { -+ d.AddUint8(23) -+ d.AddUint8(42) -+ }) -+ c.AddUint8(123) -+ }) -+ if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil { -+ t.Error(err) -+ } -+ -+ var base, child1, child2 String = b.BytesOrPanic(), nil, nil -+ var u, v, w, x uint8 -+ if !base.ReadUint8LengthPrefixed(&child1) { -+ t.Error("parsing base failed") -+ } -+ if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) { -+ t.Error("parsing child1 failed") -+ } -+ if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) { -+ t.Error("parsing child2 failed") -+ } -+ if u != 5 || v != 23 || w != 42 || x != 123 { -+ t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123", -+ u, v, w, x) -+ } -+ if len(base) != 0 { -+ t.Errorf("len(base) = %d, want 0", len(base)) -+ } -+ if len(child1) != 0 { -+ t.Errorf("len(child1) = %d, want 0", len(child1)) -+ } -+ if len(base) != 0 { -+ t.Errorf("len(child2) = %d, want 0", len(child2)) -+ } -+} -+ -+func TestPreallocatedBuffer(t *testing.T) { -+ var buf [5]byte -+ b := NewBuilder(buf[0:0]) -+ b.AddUint8(1) -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ c.AddUint8(3) -+ c.AddUint8(4) -+ }) -+ b.AddUint16(1286) // Outgrow buf by one byte. -+ want := []byte{1, 2, 3, 4, 0} -+ if !bytes.Equal(buf[:], want) { -+ t.Errorf("buf = %v want %v", buf, want) -+ } -+ if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestWriteWithPendingChild(t *testing.T) { -+ var b Builder -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ c.AddUint8LengthPrefixed(func(d *Builder) { -+ func() { -+ defer func() { -+ if recover() == nil { -+ t.Errorf("recover() = nil, want error; c.AddUint8() did not panic") -+ } -+ }() -+ c.AddUint8(2) // panics -+ }() -+ -+ defer func() { -+ if recover() == nil { -+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic") -+ } -+ }() -+ b.AddUint8(2) // panics -+ }) -+ -+ defer func() { -+ if recover() == nil { -+ t.Errorf("recover() = nil, want error; b.AddUint8() did not panic") -+ } -+ }() -+ b.AddUint8(2) // panics -+ }) -+} -+ -+func TestSetError(t *testing.T) { -+ const errorStr = "TestSetError" -+ var b Builder -+ b.SetError(errors.New(errorStr)) -+ -+ ret, err := b.Bytes() -+ if ret != nil { -+ t.Error("expected nil result") -+ } -+ if err == nil { -+ t.Fatal("unexpected nil error") -+ } -+ if s := err.Error(); s != errorStr { -+ t.Errorf("expected error %q, got %v", errorStr, s) -+ } -+} -+ -+func TestUnwrite(t *testing.T) { -+ var b Builder -+ b.AddBytes([]byte{1, 2, 3, 4, 5}) -+ b.Unwrite(2) -+ if err := builderBytesEq(&b, 1, 2, 3); err != nil { -+ t.Error(err) -+ } -+ -+ func() { -+ defer func() { -+ if recover() == nil { -+ t.Errorf("recover() = nil, want error; b.Unwrite() did not panic") -+ } -+ }() -+ b.Unwrite(4) // panics -+ }() -+ -+ b = Builder{} -+ b.AddBytes([]byte{1, 2, 3, 4, 5}) -+ b.AddUint8LengthPrefixed(func(b *Builder) { -+ b.AddBytes([]byte{1, 2, 3, 4, 5}) -+ -+ defer func() { -+ if recover() == nil { -+ t.Errorf("recover() = nil, want error; b.Unwrite() did not panic") -+ } -+ }() -+ b.Unwrite(6) // panics -+ }) -+ -+ b = Builder{} -+ b.AddBytes([]byte{1, 2, 3, 4, 5}) -+ b.AddUint8LengthPrefixed(func(c *Builder) { -+ defer func() { -+ if recover() == nil { -+ t.Errorf("recover() = nil, want error; b.Unwrite() did not panic") -+ } -+ }() -+ b.Unwrite(2) // panics (attempted unwrite while child is pending) -+ }) -+} -+ -+func TestFixedBuilderLengthPrefixed(t *testing.T) { -+ bufCap := 10 -+ inner := bytes.Repeat([]byte{0xff}, bufCap-2) -+ buf := make([]byte, 0, bufCap) -+ b := NewFixedBuilder(buf) -+ b.AddUint16LengthPrefixed(func(b *Builder) { -+ b.AddBytes(inner) -+ }) -+ if got := b.BytesOrPanic(); len(got) != bufCap { -+ t.Errorf("Expected output length to be %d, got %d", bufCap, len(got)) -+ } -+} -+ -+func TestFixedBuilderPanicReallocate(t *testing.T) { -+ defer func() { -+ recover() -+ }() -+ -+ b := NewFixedBuilder(make([]byte, 0, 10)) -+ b1 := NewFixedBuilder(make([]byte, 0, 10)) -+ b.AddUint16LengthPrefixed(func(b *Builder) { -+ *b = *b1 -+ }) -+ -+ t.Error("Builder did not panic") -+} -+ -+// ASN.1 -+ -+func TestASN1Int64(t *testing.T) { -+ tests := []struct { -+ in int64 -+ want []byte -+ }{ -+ {-0x800000, []byte{2, 3, 128, 0, 0}}, -+ {-256, []byte{2, 2, 255, 0}}, -+ {-129, []byte{2, 2, 255, 127}}, -+ {-128, []byte{2, 1, 128}}, -+ {-1, []byte{2, 1, 255}}, -+ {0, []byte{2, 1, 0}}, -+ {1, []byte{2, 1, 1}}, -+ {2, []byte{2, 1, 2}}, -+ {127, []byte{2, 1, 127}}, -+ {128, []byte{2, 2, 0, 128}}, -+ {256, []byte{2, 2, 1, 0}}, -+ {0x800000, []byte{2, 4, 0, 128, 0, 0}}, -+ } -+ for i, tt := range tests { -+ var b Builder -+ b.AddASN1Int64(tt.in) -+ if err := builderBytesEq(&b, tt.want...); err != nil { -+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in) -+ } -+ -+ var n int64 -+ s := String(b.BytesOrPanic()) -+ ok := s.ReadASN1Integer(&n) -+ if !ok || n != tt.in { -+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)", -+ ok, n, tt.in, i) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+ } -+} -+ -+func TestASN1Uint64(t *testing.T) { -+ tests := []struct { -+ in uint64 -+ want []byte -+ }{ -+ {0, []byte{2, 1, 0}}, -+ {1, []byte{2, 1, 1}}, -+ {2, []byte{2, 1, 2}}, -+ {127, []byte{2, 1, 127}}, -+ {128, []byte{2, 2, 0, 128}}, -+ {256, []byte{2, 2, 1, 0}}, -+ {0x800000, []byte{2, 4, 0, 128, 0, 0}}, -+ {0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}}, -+ {0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}}, -+ {0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}}, -+ } -+ for i, tt := range tests { -+ var b Builder -+ b.AddASN1Uint64(tt.in) -+ if err := builderBytesEq(&b, tt.want...); err != nil { -+ t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in) -+ } -+ -+ var n uint64 -+ s := String(b.BytesOrPanic()) -+ ok := s.ReadASN1Integer(&n) -+ if !ok || n != tt.in { -+ t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)", -+ ok, n, tt.in, i) -+ } -+ if len(s) != 0 { -+ t.Errorf("len(s) = %d, want 0", len(s)) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/example_test.go b/ms_mod/golang.org/x/crypto/cryptobyte/example_test.go -new file mode 100644 -index 00000000000000..86c098adf6141e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/example_test.go -@@ -0,0 +1,154 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package cryptobyte_test -+ -+import ( -+ "errors" -+ "fmt" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+func ExampleString_lengthPrefixed() { -+ // This is an example of parsing length-prefixed data (as found in, for -+ // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed -+ // strings. -+ -+ input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'}) -+ var result []string -+ -+ var values cryptobyte.String -+ if !input.ReadUint16LengthPrefixed(&values) || -+ !input.Empty() { -+ panic("bad format") -+ } -+ -+ for !values.Empty() { -+ var value cryptobyte.String -+ if !values.ReadUint8LengthPrefixed(&value) { -+ panic("bad format") -+ } -+ -+ result = append(result, string(value)) -+ } -+ -+ // Output: []string{"hello", "world"} -+ fmt.Printf("%#v\n", result) -+} -+ -+func ExampleString_aSN1() { -+ // This is an example of parsing ASN.1 data that looks like: -+ // Foo ::= SEQUENCE { -+ // version [6] INTEGER DEFAULT 0 -+ // data OCTET STRING -+ // } -+ -+ input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'}) -+ -+ var ( -+ version int64 -+ data, inner, versionBytes cryptobyte.String -+ haveVersion bool -+ ) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadOptionalASN1(&versionBytes, &haveVersion, asn1.Tag(6).Constructed().ContextSpecific()) || -+ (haveVersion && !versionBytes.ReadASN1Integer(&version)) || -+ (haveVersion && !versionBytes.Empty()) || -+ !inner.ReadASN1(&data, asn1.OCTET_STRING) || -+ !inner.Empty() { -+ panic("bad format") -+ } -+ -+ // Output: haveVersion: true, version: 2, data: hello -+ fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data)) -+} -+ -+func ExampleBuilder_aSN1() { -+ // This is an example of building ASN.1 data that looks like: -+ // Foo ::= SEQUENCE { -+ // version [6] INTEGER DEFAULT 0 -+ // data OCTET STRING -+ // } -+ -+ version := int64(2) -+ data := []byte("hello") -+ const defaultVersion = 0 -+ -+ var b cryptobyte.Builder -+ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ if version != defaultVersion { -+ b.AddASN1(asn1.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) { -+ b.AddASN1Int64(version) -+ }) -+ } -+ b.AddASN1OctetString(data) -+ }) -+ -+ result, err := b.Bytes() -+ if err != nil { -+ panic(err) -+ } -+ -+ // Output: 300ca603020102040568656c6c6f -+ fmt.Printf("%x\n", result) -+} -+ -+func ExampleBuilder_lengthPrefixed() { -+ // This is an example of building length-prefixed data (as found in, -+ // for example, TLS). Imagine a 16-bit prefixed series of 8-bit -+ // prefixed strings. -+ input := []string{"hello", "world"} -+ -+ var b cryptobyte.Builder -+ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { -+ for _, value := range input { -+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddBytes([]byte(value)) -+ }) -+ } -+ }) -+ -+ result, err := b.Bytes() -+ if err != nil { -+ panic(err) -+ } -+ -+ // Output: 000c0568656c6c6f05776f726c64 -+ fmt.Printf("%x\n", result) -+} -+ -+func ExampleBuilder_lengthPrefixOverflow() { -+ // Writing more data that can be expressed by the length prefix results -+ // in an error from Bytes(). -+ -+ tooLarge := make([]byte, 256) -+ -+ var b cryptobyte.Builder -+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddBytes(tooLarge) -+ }) -+ -+ result, err := b.Bytes() -+ fmt.Printf("len=%d err=%s\n", len(result), err) -+ -+ // Output: len=0 err=cryptobyte: pending child length 256 exceeds 1-byte length prefix -+} -+ -+func ExampleBuilderContinuation_errorHandling() { -+ var b cryptobyte.Builder -+ // Continuations that panic with a BuildError will cause Bytes to -+ // return the inner error. -+ b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddUint32(0) -+ panic(cryptobyte.BuildError{Err: errors.New("example error")}) -+ }) -+ -+ result, err := b.Bytes() -+ fmt.Printf("len=%d err=%s\n", len(result), err) -+ -+ // Output: len=0 err=example error -+} -diff --git a/ms_mod/golang.org/x/crypto/cryptobyte/string.go b/ms_mod/golang.org/x/crypto/cryptobyte/string.go -new file mode 100644 -index 00000000000000..0531a3d6f1aa9e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/cryptobyte/string.go -@@ -0,0 +1,172 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package cryptobyte contains types that help with parsing and constructing -+// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage -+// contains useful ASN.1 constants.) -+// -+// The String type is for parsing. It wraps a []byte slice and provides helper -+// functions for consuming structures, value by value. -+// -+// The Builder type is for constructing messages. It providers helper functions -+// for appending values and also for appending length-prefixed submessages – -+// without having to worry about calculating the length prefix ahead of time. -+// -+// See the documentation and examples for the Builder and String types to get -+// started. -+package cryptobyte // import "golang.org/x/crypto/cryptobyte" -+ -+// String represents a string of bytes. It provides methods for parsing -+// fixed-length and length-prefixed values from it. -+type String []byte -+ -+// read advances a String by n bytes and returns them. If less than n bytes -+// remain, it returns nil. -+func (s *String) read(n int) []byte { -+ if len(*s) < n || n < 0 { -+ return nil -+ } -+ v := (*s)[:n] -+ *s = (*s)[n:] -+ return v -+} -+ -+// Skip advances the String by n byte and reports whether it was successful. -+func (s *String) Skip(n int) bool { -+ return s.read(n) != nil -+} -+ -+// ReadUint8 decodes an 8-bit value into out and advances over it. -+// It reports whether the read was successful. -+func (s *String) ReadUint8(out *uint8) bool { -+ v := s.read(1) -+ if v == nil { -+ return false -+ } -+ *out = uint8(v[0]) -+ return true -+} -+ -+// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. -+// It reports whether the read was successful. -+func (s *String) ReadUint16(out *uint16) bool { -+ v := s.read(2) -+ if v == nil { -+ return false -+ } -+ *out = uint16(v[0])<<8 | uint16(v[1]) -+ return true -+} -+ -+// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. -+// It reports whether the read was successful. -+func (s *String) ReadUint24(out *uint32) bool { -+ v := s.read(3) -+ if v == nil { -+ return false -+ } -+ *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2]) -+ return true -+} -+ -+// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. -+// It reports whether the read was successful. -+func (s *String) ReadUint32(out *uint32) bool { -+ v := s.read(4) -+ if v == nil { -+ return false -+ } -+ *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) -+ return true -+} -+ -+// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it. -+// It reports whether the read was successful. -+func (s *String) ReadUint64(out *uint64) bool { -+ v := s.read(8) -+ if v == nil { -+ return false -+ } -+ *out = uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7]) -+ return true -+} -+ -+func (s *String) readUnsigned(out *uint32, length int) bool { -+ v := s.read(length) -+ if v == nil { -+ return false -+ } -+ var result uint32 -+ for i := 0; i < length; i++ { -+ result <<= 8 -+ result |= uint32(v[i]) -+ } -+ *out = result -+ return true -+} -+ -+func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { -+ lenBytes := s.read(lenLen) -+ if lenBytes == nil { -+ return false -+ } -+ var length uint32 -+ for _, b := range lenBytes { -+ length = length << 8 -+ length = length | uint32(b) -+ } -+ v := s.read(int(length)) -+ if v == nil { -+ return false -+ } -+ *outChild = v -+ return true -+} -+ -+// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value -+// into out and advances over it. It reports whether the read was successful. -+func (s *String) ReadUint8LengthPrefixed(out *String) bool { -+ return s.readLengthPrefixed(1, out) -+} -+ -+// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit -+// length-prefixed value into out and advances over it. It reports whether the -+// read was successful. -+func (s *String) ReadUint16LengthPrefixed(out *String) bool { -+ return s.readLengthPrefixed(2, out) -+} -+ -+// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit -+// length-prefixed value into out and advances over it. It reports whether -+// the read was successful. -+func (s *String) ReadUint24LengthPrefixed(out *String) bool { -+ return s.readLengthPrefixed(3, out) -+} -+ -+// ReadBytes reads n bytes into out and advances over them. It reports -+// whether the read was successful. -+func (s *String) ReadBytes(out *[]byte, n int) bool { -+ v := s.read(n) -+ if v == nil { -+ return false -+ } -+ *out = v -+ return true -+} -+ -+// CopyBytes copies len(out) bytes into out and advances over them. It reports -+// whether the copy operation was successful -+func (s *String) CopyBytes(out []byte) bool { -+ n := len(out) -+ v := s.read(n) -+ if v == nil { -+ return false -+ } -+ return copy(out, v) == n -+} -+ -+// Empty reports whether the string does not contain any bytes. -+func (s String) Empty() bool { -+ return len(s) == 0 -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519.go -new file mode 100644 -index 00000000000000..00f963ea20a35e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519.go -@@ -0,0 +1,59 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package curve25519 provides an implementation of the X25519 function, which -+// performs scalar multiplication on the elliptic curve known as Curve25519. -+// See RFC 7748. -+// -+// Starting in Go 1.20, this package is a wrapper for the X25519 implementation -+// in the crypto/ecdh package. -+package curve25519 // import "golang.org/x/crypto/curve25519" -+ -+// ScalarMult sets dst to the product scalar * point. -+// -+// Deprecated: when provided a low-order point, ScalarMult will set dst to all -+// zeroes, irrespective of the scalar. Instead, use the X25519 function, which -+// will return an error. -+func ScalarMult(dst, scalar, point *[32]byte) { -+ scalarMult(dst, scalar, point) -+} -+ -+// ScalarBaseMult sets dst to the product scalar * base where base is the -+// standard generator. -+// -+// It is recommended to use the X25519 function with Basepoint instead, as -+// copying into fixed size arrays can lead to unexpected bugs. -+func ScalarBaseMult(dst, scalar *[32]byte) { -+ scalarBaseMult(dst, scalar) -+} -+ -+const ( -+ // ScalarSize is the size of the scalar input to X25519. -+ ScalarSize = 32 -+ // PointSize is the size of the point input to X25519. -+ PointSize = 32 -+) -+ -+// Basepoint is the canonical Curve25519 generator. -+var Basepoint []byte -+ -+var basePoint = [32]byte{9} -+ -+func init() { Basepoint = basePoint[:] } -+ -+// X25519 returns the result of the scalar multiplication (scalar * point), -+// according to RFC 7748, Section 5. scalar, point and the return value are -+// slices of 32 bytes. -+// -+// scalar can be generated at random, for example with crypto/rand. point should -+// be either Basepoint or the output of another X25519 call. -+// -+// If point is Basepoint (but not if it's a different slice with the same -+// contents) a precomputed implementation might be used for performance. -+func X25519(scalar, point []byte) ([]byte, error) { -+ // Outline the body of function, to let the allocation be inlined in the -+ // caller, and possibly avoid escaping to the heap. -+ var dst [32]byte -+ return x25519(&dst, scalar, point) -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go -new file mode 100644 -index 00000000000000..ba647e8d77d985 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519_compat.go -@@ -0,0 +1,105 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !go1.20 -+ -+package curve25519 -+ -+import ( -+ "crypto/subtle" -+ "errors" -+ "strconv" -+ -+ "golang.org/x/crypto/curve25519/internal/field" -+) -+ -+func scalarMult(dst, scalar, point *[32]byte) { -+ var e [32]byte -+ -+ copy(e[:], scalar[:]) -+ e[0] &= 248 -+ e[31] &= 127 -+ e[31] |= 64 -+ -+ var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element -+ x1.SetBytes(point[:]) -+ x2.One() -+ x3.Set(&x1) -+ z3.One() -+ -+ swap := 0 -+ for pos := 254; pos >= 0; pos-- { -+ b := e[pos/8] >> uint(pos&7) -+ b &= 1 -+ swap ^= int(b) -+ x2.Swap(&x3, swap) -+ z2.Swap(&z3, swap) -+ swap = int(b) -+ -+ tmp0.Subtract(&x3, &z3) -+ tmp1.Subtract(&x2, &z2) -+ x2.Add(&x2, &z2) -+ z2.Add(&x3, &z3) -+ z3.Multiply(&tmp0, &x2) -+ z2.Multiply(&z2, &tmp1) -+ tmp0.Square(&tmp1) -+ tmp1.Square(&x2) -+ x3.Add(&z3, &z2) -+ z2.Subtract(&z3, &z2) -+ x2.Multiply(&tmp1, &tmp0) -+ tmp1.Subtract(&tmp1, &tmp0) -+ z2.Square(&z2) -+ -+ z3.Mult32(&tmp1, 121666) -+ x3.Square(&x3) -+ tmp0.Add(&tmp0, &z3) -+ z3.Multiply(&x1, &z2) -+ z2.Multiply(&tmp1, &tmp0) -+ } -+ -+ x2.Swap(&x3, swap) -+ z2.Swap(&z3, swap) -+ -+ z2.Invert(&z2) -+ x2.Multiply(&x2, &z2) -+ copy(dst[:], x2.Bytes()) -+} -+ -+func scalarBaseMult(dst, scalar *[32]byte) { -+ checkBasepoint() -+ scalarMult(dst, scalar, &basePoint) -+} -+ -+func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { -+ var in [32]byte -+ if l := len(scalar); l != 32 { -+ return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32") -+ } -+ if l := len(point); l != 32 { -+ return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32") -+ } -+ copy(in[:], scalar) -+ if &point[0] == &Basepoint[0] { -+ scalarBaseMult(dst, &in) -+ } else { -+ var base, zero [32]byte -+ copy(base[:], point) -+ scalarMult(dst, &in, &base) -+ if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 { -+ return nil, errors.New("bad input point: low order point") -+ } -+ } -+ return dst[:], nil -+} -+ -+func checkBasepoint() { -+ if subtle.ConstantTimeCompare(Basepoint, []byte{ -+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ }) != 1 { -+ panic("curve25519: global Basepoint value was modified") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go -new file mode 100644 -index 00000000000000..627df497270f9c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519_go120.go -@@ -0,0 +1,46 @@ -+// Copyright 2022 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.20 -+ -+package curve25519 -+ -+import "crypto/ecdh" -+ -+func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { -+ curve := ecdh.X25519() -+ pub, err := curve.NewPublicKey(point) -+ if err != nil { -+ return nil, err -+ } -+ priv, err := curve.NewPrivateKey(scalar) -+ if err != nil { -+ return nil, err -+ } -+ out, err := priv.ECDH(pub) -+ if err != nil { -+ return nil, err -+ } -+ copy(dst[:], out) -+ return dst[:], nil -+} -+ -+func scalarMult(dst, scalar, point *[32]byte) { -+ if _, err := x25519(dst, scalar[:], point[:]); err != nil { -+ // The only error condition for x25519 when the inputs are 32 bytes long -+ // is if the output would have been the all-zero value. -+ for i := range dst { -+ dst[i] = 0 -+ } -+ } -+} -+ -+func scalarBaseMult(dst, scalar *[32]byte) { -+ curve := ecdh.X25519() -+ priv, err := curve.NewPrivateKey(scalar[:]) -+ if err != nil { -+ panic("curve25519: internal error: scalarBaseMult was not 32 bytes") -+ } -+ copy(dst[:], priv.PublicKey().Bytes()) -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go b/ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go -new file mode 100644 -index 00000000000000..e2b338b5ecf23d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/curve25519_test.go -@@ -0,0 +1,142 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package curve25519_test -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/hex" -+ "testing" -+ -+ "golang.org/x/crypto/curve25519" -+) -+ -+const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" -+ -+func TestX25519Basepoint(t *testing.T) { -+ x := make([]byte, 32) -+ x[0] = 1 -+ -+ for i := 0; i < 200; i++ { -+ var err error -+ x, err = curve25519.X25519(x, curve25519.Basepoint) -+ if err != nil { -+ t.Fatal(err) -+ } -+ } -+ -+ result := hex.EncodeToString(x) -+ if result != expectedHex { -+ t.Errorf("incorrect result: got %s, want %s", result, expectedHex) -+ } -+} -+ -+func TestLowOrderPoints(t *testing.T) { -+ scalar := make([]byte, curve25519.ScalarSize) -+ if _, err := rand.Read(scalar); err != nil { -+ t.Fatal(err) -+ } -+ for i, p := range lowOrderPoints { -+ out, err := curve25519.X25519(scalar, p) -+ if err == nil { -+ t.Errorf("%d: expected error, got nil", i) -+ } -+ if out != nil { -+ t.Errorf("%d: expected nil output, got %x", i, out) -+ } -+ } -+} -+ -+func TestTestVectors(t *testing.T) { -+ t.Run("Legacy", func(t *testing.T) { testTestVectors(t, curve25519.ScalarMult) }) -+ t.Run("X25519", func(t *testing.T) { -+ testTestVectors(t, func(dst, scalar, point *[32]byte) { -+ out, err := curve25519.X25519(scalar[:], point[:]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ copy(dst[:], out) -+ }) -+ }) -+} -+ -+func testTestVectors(t *testing.T, scalarMult func(dst, scalar, point *[32]byte)) { -+ for _, tv := range testVectors { -+ var got [32]byte -+ scalarMult(&got, &tv.In, &tv.Base) -+ if !bytes.Equal(got[:], tv.Expect[:]) { -+ t.Logf(" in = %x", tv.In) -+ t.Logf(" base = %x", tv.Base) -+ t.Logf(" got = %x", got) -+ t.Logf("expect = %x", tv.Expect) -+ t.Fail() -+ } -+ } -+} -+ -+// TestHighBitIgnored tests the following requirement in RFC 7748: -+// -+// When receiving such an array, implementations of X25519 (but not X448) MUST -+// mask the most significant bit in the final byte. -+// -+// Regression test for issue #30095. -+func TestHighBitIgnored(t *testing.T) { -+ var s, u [32]byte -+ rand.Read(s[:]) -+ rand.Read(u[:]) -+ -+ var hi0, hi1 [32]byte -+ -+ u[31] &= 0x7f -+ curve25519.ScalarMult(&hi0, &s, &u) -+ -+ u[31] |= 0x80 -+ curve25519.ScalarMult(&hi1, &s, &u) -+ -+ if !bytes.Equal(hi0[:], hi1[:]) { -+ t.Errorf("high bit of group point should not affect result") -+ } -+} -+ -+var benchmarkSink byte -+ -+func BenchmarkX25519Basepoint(b *testing.B) { -+ scalar := make([]byte, curve25519.ScalarSize) -+ if _, err := rand.Read(scalar); err != nil { -+ b.Fatal(err) -+ } -+ -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ out, err := curve25519.X25519(scalar, curve25519.Basepoint) -+ if err != nil { -+ b.Fatal(err) -+ } -+ benchmarkSink ^= out[0] -+ } -+} -+ -+func BenchmarkX25519(b *testing.B) { -+ scalar := make([]byte, curve25519.ScalarSize) -+ if _, err := rand.Read(scalar); err != nil { -+ b.Fatal(err) -+ } -+ point, err := curve25519.X25519(scalar, curve25519.Basepoint) -+ if err != nil { -+ b.Fatal(err) -+ } -+ if _, err := rand.Read(scalar); err != nil { -+ b.Fatal(err) -+ } -+ -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ out, err := curve25519.X25519(scalar, point) -+ if err != nil { -+ b.Fatal(err) -+ } -+ benchmarkSink ^= out[0] -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/README b/ms_mod/golang.org/x/crypto/curve25519/internal/field/README -new file mode 100644 -index 00000000000000..e25bca7dc806b3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/README -@@ -0,0 +1,7 @@ -+This package is kept in sync with crypto/ed25519/internal/edwards25519/field in -+the standard library. -+ -+If there are any changes in the standard library that need to be synced to this -+package, run sync.sh. It will not overwrite any local changes made since the -+previous sync, so it's ok to land changes in this package first, and then sync -+to the standard library later. -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go -new file mode 100644 -index 00000000000000..1f3652987e84f8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/fe_amd64_asm.go -@@ -0,0 +1,298 @@ -+// Copyright (c) 2021 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package main -+ -+import ( -+ "fmt" -+ -+ . "github.com/mmcloughlin/avo/build" -+ . "github.com/mmcloughlin/avo/gotypes" -+ . "github.com/mmcloughlin/avo/operand" -+ . "github.com/mmcloughlin/avo/reg" -+ -+ // Ensure "go mod tidy" doesn't remove the golang.org/x/crypto module -+ // dependency, which is necessary to access the field.Element type. -+ _ "golang.org/x/crypto/curve25519" -+) -+ -+//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field -+ -+func main() { -+ Package("golang.org/x/crypto/curve25519/internal/field") -+ ConstraintExpr("amd64,gc,!purego") -+ feMul() -+ feSquare() -+ Generate() -+} -+ -+type namedComponent struct { -+ Component -+ name string -+} -+ -+func (c namedComponent) String() string { return c.name } -+ -+type uint128 struct { -+ name string -+ hi, lo GPVirtual -+} -+ -+func (c uint128) String() string { return c.name } -+ -+func feSquare() { -+ TEXT("feSquare", NOSPLIT, "func(out, a *Element)") -+ Doc("feSquare sets out = a * a. It works like feSquareGeneric.") -+ Pragma("noescape") -+ -+ a := Dereference(Param("a")) -+ l0 := namedComponent{a.Field("l0"), "l0"} -+ l1 := namedComponent{a.Field("l1"), "l1"} -+ l2 := namedComponent{a.Field("l2"), "l2"} -+ l3 := namedComponent{a.Field("l3"), "l3"} -+ l4 := namedComponent{a.Field("l4"), "l4"} -+ -+ // r0 = l0Γ—l0 + 19Γ—2Γ—(l1Γ—l4 + l2Γ—l3) -+ r0 := uint128{"r0", GP64(), GP64()} -+ mul64(r0, 1, l0, l0) -+ addMul64(r0, 38, l1, l4) -+ addMul64(r0, 38, l2, l3) -+ -+ // r1 = 2Γ—l0Γ—l1 + 19Γ—2Γ—l2Γ—l4 + 19Γ—l3Γ—l3 -+ r1 := uint128{"r1", GP64(), GP64()} -+ mul64(r1, 2, l0, l1) -+ addMul64(r1, 38, l2, l4) -+ addMul64(r1, 19, l3, l3) -+ -+ // r2 = = 2Γ—l0Γ—l2 + l1Γ—l1 + 19Γ—2Γ—l3Γ—l4 -+ r2 := uint128{"r2", GP64(), GP64()} -+ mul64(r2, 2, l0, l2) -+ addMul64(r2, 1, l1, l1) -+ addMul64(r2, 38, l3, l4) -+ -+ // r3 = = 2Γ—l0Γ—l3 + 2Γ—l1Γ—l2 + 19Γ—l4Γ—l4 -+ r3 := uint128{"r3", GP64(), GP64()} -+ mul64(r3, 2, l0, l3) -+ addMul64(r3, 2, l1, l2) -+ addMul64(r3, 19, l4, l4) -+ -+ // r4 = = 2Γ—l0Γ—l4 + 2Γ—l1Γ—l3 + l2Γ—l2 -+ r4 := uint128{"r4", GP64(), GP64()} -+ mul64(r4, 2, l0, l4) -+ addMul64(r4, 2, l1, l3) -+ addMul64(r4, 1, l2, l2) -+ -+ Comment("First reduction chain") -+ maskLow51Bits := GP64() -+ MOVQ(Imm((1<<51)-1), maskLow51Bits) -+ c0, r0lo := shiftRightBy51(&r0) -+ c1, r1lo := shiftRightBy51(&r1) -+ c2, r2lo := shiftRightBy51(&r2) -+ c3, r3lo := shiftRightBy51(&r3) -+ c4, r4lo := shiftRightBy51(&r4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Second reduction chain (carryPropagate)") -+ // c0 = r0 >> 51 -+ MOVQ(r0lo, c0) -+ SHRQ(Imm(51), c0) -+ // c1 = r1 >> 51 -+ MOVQ(r1lo, c1) -+ SHRQ(Imm(51), c1) -+ // c2 = r2 >> 51 -+ MOVQ(r2lo, c2) -+ SHRQ(Imm(51), c2) -+ // c3 = r3 >> 51 -+ MOVQ(r3lo, c3) -+ SHRQ(Imm(51), c3) -+ // c4 = r4 >> 51 -+ MOVQ(r4lo, c4) -+ SHRQ(Imm(51), c4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Store output") -+ out := Dereference(Param("out")) -+ Store(r0lo, out.Field("l0")) -+ Store(r1lo, out.Field("l1")) -+ Store(r2lo, out.Field("l2")) -+ Store(r3lo, out.Field("l3")) -+ Store(r4lo, out.Field("l4")) -+ -+ RET() -+} -+ -+func feMul() { -+ TEXT("feMul", NOSPLIT, "func(out, a, b *Element)") -+ Doc("feMul sets out = a * b. It works like feMulGeneric.") -+ Pragma("noescape") -+ -+ a := Dereference(Param("a")) -+ a0 := namedComponent{a.Field("l0"), "a0"} -+ a1 := namedComponent{a.Field("l1"), "a1"} -+ a2 := namedComponent{a.Field("l2"), "a2"} -+ a3 := namedComponent{a.Field("l3"), "a3"} -+ a4 := namedComponent{a.Field("l4"), "a4"} -+ -+ b := Dereference(Param("b")) -+ b0 := namedComponent{b.Field("l0"), "b0"} -+ b1 := namedComponent{b.Field("l1"), "b1"} -+ b2 := namedComponent{b.Field("l2"), "b2"} -+ b3 := namedComponent{b.Field("l3"), "b3"} -+ b4 := namedComponent{b.Field("l4"), "b4"} -+ -+ // r0 = a0Γ—b0 + 19Γ—(a1Γ—b4 + a2Γ—b3 + a3Γ—b2 + a4Γ—b1) -+ r0 := uint128{"r0", GP64(), GP64()} -+ mul64(r0, 1, a0, b0) -+ addMul64(r0, 19, a1, b4) -+ addMul64(r0, 19, a2, b3) -+ addMul64(r0, 19, a3, b2) -+ addMul64(r0, 19, a4, b1) -+ -+ // r1 = a0Γ—b1 + a1Γ—b0 + 19Γ—(a2Γ—b4 + a3Γ—b3 + a4Γ—b2) -+ r1 := uint128{"r1", GP64(), GP64()} -+ mul64(r1, 1, a0, b1) -+ addMul64(r1, 1, a1, b0) -+ addMul64(r1, 19, a2, b4) -+ addMul64(r1, 19, a3, b3) -+ addMul64(r1, 19, a4, b2) -+ -+ // r2 = a0Γ—b2 + a1Γ—b1 + a2Γ—b0 + 19Γ—(a3Γ—b4 + a4Γ—b3) -+ r2 := uint128{"r2", GP64(), GP64()} -+ mul64(r2, 1, a0, b2) -+ addMul64(r2, 1, a1, b1) -+ addMul64(r2, 1, a2, b0) -+ addMul64(r2, 19, a3, b4) -+ addMul64(r2, 19, a4, b3) -+ -+ // r3 = a0Γ—b3 + a1Γ—b2 + a2Γ—b1 + a3Γ—b0 + 19Γ—a4Γ—b4 -+ r3 := uint128{"r3", GP64(), GP64()} -+ mul64(r3, 1, a0, b3) -+ addMul64(r3, 1, a1, b2) -+ addMul64(r3, 1, a2, b1) -+ addMul64(r3, 1, a3, b0) -+ addMul64(r3, 19, a4, b4) -+ -+ // r4 = a0Γ—b4 + a1Γ—b3 + a2Γ—b2 + a3Γ—b1 + a4Γ—b0 -+ r4 := uint128{"r4", GP64(), GP64()} -+ mul64(r4, 1, a0, b4) -+ addMul64(r4, 1, a1, b3) -+ addMul64(r4, 1, a2, b2) -+ addMul64(r4, 1, a3, b1) -+ addMul64(r4, 1, a4, b0) -+ -+ Comment("First reduction chain") -+ maskLow51Bits := GP64() -+ MOVQ(Imm((1<<51)-1), maskLow51Bits) -+ c0, r0lo := shiftRightBy51(&r0) -+ c1, r1lo := shiftRightBy51(&r1) -+ c2, r2lo := shiftRightBy51(&r2) -+ c3, r3lo := shiftRightBy51(&r3) -+ c4, r4lo := shiftRightBy51(&r4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Second reduction chain (carryPropagate)") -+ // c0 = r0 >> 51 -+ MOVQ(r0lo, c0) -+ SHRQ(Imm(51), c0) -+ // c1 = r1 >> 51 -+ MOVQ(r1lo, c1) -+ SHRQ(Imm(51), c1) -+ // c2 = r2 >> 51 -+ MOVQ(r2lo, c2) -+ SHRQ(Imm(51), c2) -+ // c3 = r3 >> 51 -+ MOVQ(r3lo, c3) -+ SHRQ(Imm(51), c3) -+ // c4 = r4 >> 51 -+ MOVQ(r4lo, c4) -+ SHRQ(Imm(51), c4) -+ maskAndAdd(r0lo, maskLow51Bits, c4, 19) -+ maskAndAdd(r1lo, maskLow51Bits, c0, 1) -+ maskAndAdd(r2lo, maskLow51Bits, c1, 1) -+ maskAndAdd(r3lo, maskLow51Bits, c2, 1) -+ maskAndAdd(r4lo, maskLow51Bits, c3, 1) -+ -+ Comment("Store output") -+ out := Dereference(Param("out")) -+ Store(r0lo, out.Field("l0")) -+ Store(r1lo, out.Field("l1")) -+ Store(r2lo, out.Field("l2")) -+ Store(r3lo, out.Field("l3")) -+ Store(r4lo, out.Field("l4")) -+ -+ RET() -+} -+ -+// mul64 sets r to i * aX * bX. -+func mul64(r uint128, i int, aX, bX namedComponent) { -+ switch i { -+ case 1: -+ Comment(fmt.Sprintf("%s = %sΓ—%s", r, aX, bX)) -+ Load(aX, RAX) -+ case 2: -+ Comment(fmt.Sprintf("%s = 2Γ—%sΓ—%s", r, aX, bX)) -+ Load(aX, RAX) -+ SHLQ(Imm(1), RAX) -+ default: -+ panic("unsupported i value") -+ } -+ MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX -+ MOVQ(RAX, r.lo) -+ MOVQ(RDX, r.hi) -+} -+ -+// addMul64 sets r to r + i * aX * bX. -+func addMul64(r uint128, i uint64, aX, bX namedComponent) { -+ switch i { -+ case 1: -+ Comment(fmt.Sprintf("%s += %sΓ—%s", r, aX, bX)) -+ Load(aX, RAX) -+ default: -+ Comment(fmt.Sprintf("%s += %dΓ—%sΓ—%s", r, i, aX, bX)) -+ IMUL3Q(Imm(i), Load(aX, GP64()), RAX) -+ } -+ MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX -+ ADDQ(RAX, r.lo) -+ ADCQ(RDX, r.hi) -+} -+ -+// shiftRightBy51 returns r >> 51 and r.lo. -+// -+// After this function is called, the uint128 may not be used anymore. -+func shiftRightBy51(r *uint128) (out, lo GPVirtual) { -+ out = r.hi -+ lo = r.lo -+ SHLQ(Imm(64-51), r.lo, r.hi) -+ r.lo, r.hi = nil, nil // make sure the uint128 is unusable -+ return -+} -+ -+// maskAndAdd sets r = r&mask + c*i. -+func maskAndAdd(r, mask, c GPVirtual, i uint64) { -+ ANDQ(mask, r) -+ if i != 1 { -+ IMUL3Q(Imm(i), c, c) -+ } -+ ADDQ(c, r) -+} -+ -+func mustAddr(c Component) Op { -+ b, err := c.Resolve() -+ if err != nil { -+ panic(err) -+ } -+ return b.Addr -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod -new file mode 100644 -index 00000000000000..5b3dba315e7f90 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.mod -@@ -0,0 +1,10 @@ -+module asm -+ -+go 1.16 -+ -+require ( -+ github.com/mmcloughlin/avo v0.4.0 -+ golang.org/x/crypto v0.0.0 -+) -+ -+replace golang.org/x/crypto v0.0.0 => ../../../.. -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum -new file mode 100644 -index 00000000000000..4c9bbf675bc033 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/_asm/go.sum -@@ -0,0 +1,34 @@ -+github.com/mmcloughlin/avo v0.4.0 h1:jeHDRktVD+578ULxWpQHkilor6pkdLF7u7EiTzDbfcU= -+github.com/mmcloughlin/avo v0.4.0/go.mod h1:RW9BfYA3TgO9uCdNrKU2h6J8cPD8ZLznvfgHAeszb1s= -+github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= -+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -+golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 h1:giLT+HuUP/gXYrG2Plg9WTjj4qhfgaW424ZIFog3rlk= -+golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -+golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -+golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go -new file mode 100644 -index 00000000000000..ca841ad99e3ab7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe.go -@@ -0,0 +1,416 @@ -+// Copyright (c) 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package field implements fast arithmetic modulo 2^255-19. -+package field -+ -+import ( -+ "crypto/subtle" -+ "encoding/binary" -+ "math/bits" -+) -+ -+// Element represents an element of the field GF(2^255-19). Note that this -+// is not a cryptographically secure group, and should only be used to interact -+// with edwards25519.Point coordinates. -+// -+// This type works similarly to math/big.Int, and all arguments and receivers -+// are allowed to alias. -+// -+// The zero value is a valid zero element. -+type Element struct { -+ // An element t represents the integer -+ // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 -+ // -+ // Between operations, all limbs are expected to be lower than 2^52. -+ l0 uint64 -+ l1 uint64 -+ l2 uint64 -+ l3 uint64 -+ l4 uint64 -+} -+ -+const maskLow51Bits uint64 = (1 << 51) - 1 -+ -+var feZero = &Element{0, 0, 0, 0, 0} -+ -+// Zero sets v = 0, and returns v. -+func (v *Element) Zero() *Element { -+ *v = *feZero -+ return v -+} -+ -+var feOne = &Element{1, 0, 0, 0, 0} -+ -+// One sets v = 1, and returns v. -+func (v *Element) One() *Element { -+ *v = *feOne -+ return v -+} -+ -+// reduce reduces v modulo 2^255 - 19 and returns it. -+func (v *Element) reduce() *Element { -+ v.carryPropagate() -+ -+ // After the light reduction we now have a field element representation -+ // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. -+ -+ // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, -+ // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. -+ c := (v.l0 + 19) >> 51 -+ c = (v.l1 + c) >> 51 -+ c = (v.l2 + c) >> 51 -+ c = (v.l3 + c) >> 51 -+ c = (v.l4 + c) >> 51 -+ -+ // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's -+ // effectively applying the reduction identity to the carry. -+ v.l0 += 19 * c -+ -+ v.l1 += v.l0 >> 51 -+ v.l0 = v.l0 & maskLow51Bits -+ v.l2 += v.l1 >> 51 -+ v.l1 = v.l1 & maskLow51Bits -+ v.l3 += v.l2 >> 51 -+ v.l2 = v.l2 & maskLow51Bits -+ v.l4 += v.l3 >> 51 -+ v.l3 = v.l3 & maskLow51Bits -+ // no additional carry -+ v.l4 = v.l4 & maskLow51Bits -+ -+ return v -+} -+ -+// Add sets v = a + b, and returns v. -+func (v *Element) Add(a, b *Element) *Element { -+ v.l0 = a.l0 + b.l0 -+ v.l1 = a.l1 + b.l1 -+ v.l2 = a.l2 + b.l2 -+ v.l3 = a.l3 + b.l3 -+ v.l4 = a.l4 + b.l4 -+ // Using the generic implementation here is actually faster than the -+ // assembly. Probably because the body of this function is so simple that -+ // the compiler can figure out better optimizations by inlining the carry -+ // propagation. TODO -+ return v.carryPropagateGeneric() -+} -+ -+// Subtract sets v = a - b, and returns v. -+func (v *Element) Subtract(a, b *Element) *Element { -+ // We first add 2 * p, to guarantee the subtraction won't underflow, and -+ // then subtract b (which can be up to 2^255 + 2^13 * 19). -+ v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 -+ v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 -+ v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 -+ v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 -+ v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 -+ return v.carryPropagate() -+} -+ -+// Negate sets v = -a, and returns v. -+func (v *Element) Negate(a *Element) *Element { -+ return v.Subtract(feZero, a) -+} -+ -+// Invert sets v = 1/z mod p, and returns v. -+// -+// If z == 0, Invert returns v = 0. -+func (v *Element) Invert(z *Element) *Element { -+ // Inversion is implemented as exponentiation with exponent p βˆ’ 2. It uses the -+ // same sequence of 255 squarings and 11 multiplications as [Curve25519]. -+ var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element -+ -+ z2.Square(z) // 2 -+ t.Square(&z2) // 4 -+ t.Square(&t) // 8 -+ z9.Multiply(&t, z) // 9 -+ z11.Multiply(&z9, &z2) // 11 -+ t.Square(&z11) // 22 -+ z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 -+ -+ t.Square(&z2_5_0) // 2^6 - 2^1 -+ for i := 0; i < 4; i++ { -+ t.Square(&t) // 2^10 - 2^5 -+ } -+ z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 -+ -+ t.Square(&z2_10_0) // 2^11 - 2^1 -+ for i := 0; i < 9; i++ { -+ t.Square(&t) // 2^20 - 2^10 -+ } -+ z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 -+ -+ t.Square(&z2_20_0) // 2^21 - 2^1 -+ for i := 0; i < 19; i++ { -+ t.Square(&t) // 2^40 - 2^20 -+ } -+ t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 -+ -+ t.Square(&t) // 2^41 - 2^1 -+ for i := 0; i < 9; i++ { -+ t.Square(&t) // 2^50 - 2^10 -+ } -+ z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 -+ -+ t.Square(&z2_50_0) // 2^51 - 2^1 -+ for i := 0; i < 49; i++ { -+ t.Square(&t) // 2^100 - 2^50 -+ } -+ z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 -+ -+ t.Square(&z2_100_0) // 2^101 - 2^1 -+ for i := 0; i < 99; i++ { -+ t.Square(&t) // 2^200 - 2^100 -+ } -+ t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 -+ -+ t.Square(&t) // 2^201 - 2^1 -+ for i := 0; i < 49; i++ { -+ t.Square(&t) // 2^250 - 2^50 -+ } -+ t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 -+ -+ t.Square(&t) // 2^251 - 2^1 -+ t.Square(&t) // 2^252 - 2^2 -+ t.Square(&t) // 2^253 - 2^3 -+ t.Square(&t) // 2^254 - 2^4 -+ t.Square(&t) // 2^255 - 2^5 -+ -+ return v.Multiply(&t, &z11) // 2^255 - 21 -+} -+ -+// Set sets v = a, and returns v. -+func (v *Element) Set(a *Element) *Element { -+ *v = *a -+ return v -+} -+ -+// SetBytes sets v to x, which must be a 32-byte little-endian encoding. -+// -+// Consistent with RFC 7748, the most significant bit (the high bit of the -+// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) -+// are accepted. Note that this is laxer than specified by RFC 8032. -+func (v *Element) SetBytes(x []byte) *Element { -+ if len(x) != 32 { -+ panic("edwards25519: invalid field element input size") -+ } -+ -+ // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). -+ v.l0 = binary.LittleEndian.Uint64(x[0:8]) -+ v.l0 &= maskLow51Bits -+ // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). -+ v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 -+ v.l1 &= maskLow51Bits -+ // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). -+ v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 -+ v.l2 &= maskLow51Bits -+ // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). -+ v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 -+ v.l3 &= maskLow51Bits -+ // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). -+ // Note: not bytes 25:33, shift 4, to avoid overread. -+ v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 -+ v.l4 &= maskLow51Bits -+ -+ return v -+} -+ -+// Bytes returns the canonical 32-byte little-endian encoding of v. -+func (v *Element) Bytes() []byte { -+ // This function is outlined to make the allocations inline in the caller -+ // rather than happen on the heap. -+ var out [32]byte -+ return v.bytes(&out) -+} -+ -+func (v *Element) bytes(out *[32]byte) []byte { -+ t := *v -+ t.reduce() -+ -+ var buf [8]byte -+ for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { -+ bitsOffset := i * 51 -+ binary.LittleEndian.PutUint64(buf[:], l<= len(out) { -+ break -+ } -+ out[off] |= bb -+ } -+ } -+ -+ return out[:] -+} -+ -+// Equal returns 1 if v and u are equal, and 0 otherwise. -+func (v *Element) Equal(u *Element) int { -+ sa, sv := u.Bytes(), v.Bytes() -+ return subtle.ConstantTimeCompare(sa, sv) -+} -+ -+// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. -+func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } -+ -+// Select sets v to a if cond == 1, and to b if cond == 0. -+func (v *Element) Select(a, b *Element, cond int) *Element { -+ m := mask64Bits(cond) -+ v.l0 = (m & a.l0) | (^m & b.l0) -+ v.l1 = (m & a.l1) | (^m & b.l1) -+ v.l2 = (m & a.l2) | (^m & b.l2) -+ v.l3 = (m & a.l3) | (^m & b.l3) -+ v.l4 = (m & a.l4) | (^m & b.l4) -+ return v -+} -+ -+// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. -+func (v *Element) Swap(u *Element, cond int) { -+ m := mask64Bits(cond) -+ t := m & (v.l0 ^ u.l0) -+ v.l0 ^= t -+ u.l0 ^= t -+ t = m & (v.l1 ^ u.l1) -+ v.l1 ^= t -+ u.l1 ^= t -+ t = m & (v.l2 ^ u.l2) -+ v.l2 ^= t -+ u.l2 ^= t -+ t = m & (v.l3 ^ u.l3) -+ v.l3 ^= t -+ u.l3 ^= t -+ t = m & (v.l4 ^ u.l4) -+ v.l4 ^= t -+ u.l4 ^= t -+} -+ -+// IsNegative returns 1 if v is negative, and 0 otherwise. -+func (v *Element) IsNegative() int { -+ return int(v.Bytes()[0] & 1) -+} -+ -+// Absolute sets v to |u|, and returns v. -+func (v *Element) Absolute(u *Element) *Element { -+ return v.Select(new(Element).Negate(u), u, u.IsNegative()) -+} -+ -+// Multiply sets v = x * y, and returns v. -+func (v *Element) Multiply(x, y *Element) *Element { -+ feMul(v, x, y) -+ return v -+} -+ -+// Square sets v = x * x, and returns v. -+func (v *Element) Square(x *Element) *Element { -+ feSquare(v, x) -+ return v -+} -+ -+// Mult32 sets v = x * y, and returns v. -+func (v *Element) Mult32(x *Element, y uint32) *Element { -+ x0lo, x0hi := mul51(x.l0, y) -+ x1lo, x1hi := mul51(x.l1, y) -+ x2lo, x2hi := mul51(x.l2, y) -+ x3lo, x3hi := mul51(x.l3, y) -+ x4lo, x4hi := mul51(x.l4, y) -+ v.l0 = x0lo + 19*x4hi // carried over per the reduction identity -+ v.l1 = x1lo + x0hi -+ v.l2 = x2lo + x1hi -+ v.l3 = x3lo + x2hi -+ v.l4 = x4lo + x3hi -+ // The hi portions are going to be only 32 bits, plus any previous excess, -+ // so we can skip the carry propagation. -+ return v -+} -+ -+// mul51 returns lo + hi * 2⁡¹ = a * b. -+func mul51(a uint64, b uint32) (lo uint64, hi uint64) { -+ mh, ml := bits.Mul64(a, uint64(b)) -+ lo = ml & maskLow51Bits -+ hi = (mh << 13) | (ml >> 51) -+ return -+} -+ -+// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. -+func (v *Element) Pow22523(x *Element) *Element { -+ var t0, t1, t2 Element -+ -+ t0.Square(x) // x^2 -+ t1.Square(&t0) // x^4 -+ t1.Square(&t1) // x^8 -+ t1.Multiply(x, &t1) // x^9 -+ t0.Multiply(&t0, &t1) // x^11 -+ t0.Square(&t0) // x^22 -+ t0.Multiply(&t1, &t0) // x^31 -+ t1.Square(&t0) // x^62 -+ for i := 1; i < 5; i++ { // x^992 -+ t1.Square(&t1) -+ } -+ t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 -+ t1.Square(&t0) // 2^11 - 2 -+ for i := 1; i < 10; i++ { // 2^20 - 2^10 -+ t1.Square(&t1) -+ } -+ t1.Multiply(&t1, &t0) // 2^20 - 1 -+ t2.Square(&t1) // 2^21 - 2 -+ for i := 1; i < 20; i++ { // 2^40 - 2^20 -+ t2.Square(&t2) -+ } -+ t1.Multiply(&t2, &t1) // 2^40 - 1 -+ t1.Square(&t1) // 2^41 - 2 -+ for i := 1; i < 10; i++ { // 2^50 - 2^10 -+ t1.Square(&t1) -+ } -+ t0.Multiply(&t1, &t0) // 2^50 - 1 -+ t1.Square(&t0) // 2^51 - 2 -+ for i := 1; i < 50; i++ { // 2^100 - 2^50 -+ t1.Square(&t1) -+ } -+ t1.Multiply(&t1, &t0) // 2^100 - 1 -+ t2.Square(&t1) // 2^101 - 2 -+ for i := 1; i < 100; i++ { // 2^200 - 2^100 -+ t2.Square(&t2) -+ } -+ t1.Multiply(&t2, &t1) // 2^200 - 1 -+ t1.Square(&t1) // 2^201 - 2 -+ for i := 1; i < 50; i++ { // 2^250 - 2^50 -+ t1.Square(&t1) -+ } -+ t0.Multiply(&t1, &t0) // 2^250 - 1 -+ t0.Square(&t0) // 2^251 - 2 -+ t0.Square(&t0) // 2^252 - 4 -+ return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) -+} -+ -+// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. -+var sqrtM1 = &Element{1718705420411056, 234908883556509, -+ 2233514472574048, 2117202627021982, 765476049583133} -+ -+// SqrtRatio sets r to the non-negative square root of the ratio of u and v. -+// -+// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio -+// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, -+// and returns r and 0. -+func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { -+ var a, b Element -+ -+ // r = (u * v3) * (u * v7)^((p-5)/8) -+ v2 := a.Square(v) -+ uv3 := b.Multiply(u, b.Multiply(v2, v)) -+ uv7 := a.Multiply(uv3, a.Square(v2)) -+ r.Multiply(uv3, r.Pow22523(uv7)) -+ -+ check := a.Multiply(v, a.Square(r)) // check = v * r^2 -+ -+ uNeg := b.Negate(u) -+ correctSignSqrt := check.Equal(u) -+ flippedSignSqrt := check.Equal(uNeg) -+ flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) -+ -+ rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r -+ // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) -+ r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) -+ -+ r.Absolute(r) // Choose the nonnegative square root. -+ return r, correctSignSqrt | flippedSignSqrt -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go -new file mode 100644 -index 00000000000000..64e57c4f359d5d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_alias_test.go -@@ -0,0 +1,126 @@ -+// Copyright (c) 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package field -+ -+import ( -+ "testing" -+ "testing/quick" -+) -+ -+func checkAliasingOneArg(f func(v, x *Element) *Element) func(v, x Element) bool { -+ return func(v, x Element) bool { -+ x1, v1 := x, x -+ -+ // Calculate a reference f(x) without aliasing. -+ if out := f(&v, &x); out != &v && isInBounds(out) { -+ return false -+ } -+ -+ // Test aliasing the argument and the receiver. -+ if out := f(&v1, &v1); out != &v1 || v1 != v { -+ return false -+ } -+ -+ // Ensure the arguments was not modified. -+ return x == x1 -+ } -+} -+ -+func checkAliasingTwoArgs(f func(v, x, y *Element) *Element) func(v, x, y Element) bool { -+ return func(v, x, y Element) bool { -+ x1, y1, v1 := x, y, Element{} -+ -+ // Calculate a reference f(x, y) without aliasing. -+ if out := f(&v, &x, &y); out != &v && isInBounds(out) { -+ return false -+ } -+ -+ // Test aliasing the first argument and the receiver. -+ v1 = x -+ if out := f(&v1, &v1, &y); out != &v1 || v1 != v { -+ return false -+ } -+ // Test aliasing the second argument and the receiver. -+ v1 = y -+ if out := f(&v1, &x, &v1); out != &v1 || v1 != v { -+ return false -+ } -+ -+ // Calculate a reference f(x, x) without aliasing. -+ if out := f(&v, &x, &x); out != &v { -+ return false -+ } -+ -+ // Test aliasing the first argument and the receiver. -+ v1 = x -+ if out := f(&v1, &v1, &x); out != &v1 || v1 != v { -+ return false -+ } -+ // Test aliasing the second argument and the receiver. -+ v1 = x -+ if out := f(&v1, &x, &v1); out != &v1 || v1 != v { -+ return false -+ } -+ // Test aliasing both arguments and the receiver. -+ v1 = x -+ if out := f(&v1, &v1, &v1); out != &v1 || v1 != v { -+ return false -+ } -+ -+ // Ensure the arguments were not modified. -+ return x == x1 && y == y1 -+ } -+} -+ -+// TestAliasing checks that receivers and arguments can alias each other without -+// leading to incorrect results. That is, it ensures that it's safe to write -+// -+// v.Invert(v) -+// -+// or -+// -+// v.Add(v, v) -+// -+// without any of the inputs getting clobbered by the output being written. -+func TestAliasing(t *testing.T) { -+ type target struct { -+ name string -+ oneArgF func(v, x *Element) *Element -+ twoArgsF func(v, x, y *Element) *Element -+ } -+ for _, tt := range []target{ -+ {name: "Absolute", oneArgF: (*Element).Absolute}, -+ {name: "Invert", oneArgF: (*Element).Invert}, -+ {name: "Negate", oneArgF: (*Element).Negate}, -+ {name: "Set", oneArgF: (*Element).Set}, -+ {name: "Square", oneArgF: (*Element).Square}, -+ {name: "Multiply", twoArgsF: (*Element).Multiply}, -+ {name: "Add", twoArgsF: (*Element).Add}, -+ {name: "Subtract", twoArgsF: (*Element).Subtract}, -+ { -+ name: "Select0", -+ twoArgsF: func(v, x, y *Element) *Element { -+ return (*Element).Select(v, x, y, 0) -+ }, -+ }, -+ { -+ name: "Select1", -+ twoArgsF: func(v, x, y *Element) *Element { -+ return (*Element).Select(v, x, y, 1) -+ }, -+ }, -+ } { -+ var err error -+ switch { -+ case tt.oneArgF != nil: -+ err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8}) -+ case tt.twoArgsF != nil: -+ err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8}) -+ } -+ if err != nil { -+ t.Errorf("%v: %v", tt.name, err) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go -new file mode 100644 -index 00000000000000..edcf163c4ed433 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go -@@ -0,0 +1,16 @@ -+// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+package field -+ -+// feMul sets out = a * b. It works like feMulGeneric. -+// -+//go:noescape -+func feMul(out *Element, a *Element, b *Element) -+ -+// feSquare sets out = a * a. It works like feSquareGeneric. -+// -+//go:noescape -+func feSquare(out *Element, a *Element) -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s -new file mode 100644 -index 00000000000000..293f013c94a66c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s -@@ -0,0 +1,379 @@ -+// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. -+ -+//go:build amd64 && gc && !purego -+// +build amd64,gc,!purego -+ -+#include "textflag.h" -+ -+// func feMul(out *Element, a *Element, b *Element) -+TEXT Β·feMul(SB), NOSPLIT, $0-24 -+ MOVQ a+8(FP), CX -+ MOVQ b+16(FP), BX -+ -+ // r0 = a0Γ—b0 -+ MOVQ (CX), AX -+ MULQ (BX) -+ MOVQ AX, DI -+ MOVQ DX, SI -+ -+ // r0 += 19Γ—a1Γ—b4 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r0 += 19Γ—a2Γ—b3 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r0 += 19Γ—a3Γ—b2 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 16(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r0 += 19Γ—a4Γ—b1 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 8(BX) -+ ADDQ AX, DI -+ ADCQ DX, SI -+ -+ // r1 = a0Γ—b1 -+ MOVQ (CX), AX -+ MULQ 8(BX) -+ MOVQ AX, R9 -+ MOVQ DX, R8 -+ -+ // r1 += a1Γ—b0 -+ MOVQ 8(CX), AX -+ MULQ (BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r1 += 19Γ—a2Γ—b4 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r1 += 19Γ—a3Γ—b3 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r1 += 19Γ—a4Γ—b2 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 16(BX) -+ ADDQ AX, R9 -+ ADCQ DX, R8 -+ -+ // r2 = a0Γ—b2 -+ MOVQ (CX), AX -+ MULQ 16(BX) -+ MOVQ AX, R11 -+ MOVQ DX, R10 -+ -+ // r2 += a1Γ—b1 -+ MOVQ 8(CX), AX -+ MULQ 8(BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r2 += a2Γ—b0 -+ MOVQ 16(CX), AX -+ MULQ (BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r2 += 19Γ—a3Γ—b4 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r2 += 19Γ—a4Γ—b3 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(BX) -+ ADDQ AX, R11 -+ ADCQ DX, R10 -+ -+ // r3 = a0Γ—b3 -+ MOVQ (CX), AX -+ MULQ 24(BX) -+ MOVQ AX, R13 -+ MOVQ DX, R12 -+ -+ // r3 += a1Γ—b2 -+ MOVQ 8(CX), AX -+ MULQ 16(BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r3 += a2Γ—b1 -+ MOVQ 16(CX), AX -+ MULQ 8(BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r3 += a3Γ—b0 -+ MOVQ 24(CX), AX -+ MULQ (BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r3 += 19Γ—a4Γ—b4 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(BX) -+ ADDQ AX, R13 -+ ADCQ DX, R12 -+ -+ // r4 = a0Γ—b4 -+ MOVQ (CX), AX -+ MULQ 32(BX) -+ MOVQ AX, R15 -+ MOVQ DX, R14 -+ -+ // r4 += a1Γ—b3 -+ MOVQ 8(CX), AX -+ MULQ 24(BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // r4 += a2Γ—b2 -+ MOVQ 16(CX), AX -+ MULQ 16(BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // r4 += a3Γ—b1 -+ MOVQ 24(CX), AX -+ MULQ 8(BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // r4 += a4Γ—b0 -+ MOVQ 32(CX), AX -+ MULQ (BX) -+ ADDQ AX, R15 -+ ADCQ DX, R14 -+ -+ // First reduction chain -+ MOVQ $0x0007ffffffffffff, AX -+ SHLQ $0x0d, DI, SI -+ SHLQ $0x0d, R9, R8 -+ SHLQ $0x0d, R11, R10 -+ SHLQ $0x0d, R13, R12 -+ SHLQ $0x0d, R15, R14 -+ ANDQ AX, DI -+ IMUL3Q $0x13, R14, R14 -+ ADDQ R14, DI -+ ANDQ AX, R9 -+ ADDQ SI, R9 -+ ANDQ AX, R11 -+ ADDQ R8, R11 -+ ANDQ AX, R13 -+ ADDQ R10, R13 -+ ANDQ AX, R15 -+ ADDQ R12, R15 -+ -+ // Second reduction chain (carryPropagate) -+ MOVQ DI, SI -+ SHRQ $0x33, SI -+ MOVQ R9, R8 -+ SHRQ $0x33, R8 -+ MOVQ R11, R10 -+ SHRQ $0x33, R10 -+ MOVQ R13, R12 -+ SHRQ $0x33, R12 -+ MOVQ R15, R14 -+ SHRQ $0x33, R14 -+ ANDQ AX, DI -+ IMUL3Q $0x13, R14, R14 -+ ADDQ R14, DI -+ ANDQ AX, R9 -+ ADDQ SI, R9 -+ ANDQ AX, R11 -+ ADDQ R8, R11 -+ ANDQ AX, R13 -+ ADDQ R10, R13 -+ ANDQ AX, R15 -+ ADDQ R12, R15 -+ -+ // Store output -+ MOVQ out+0(FP), AX -+ MOVQ DI, (AX) -+ MOVQ R9, 8(AX) -+ MOVQ R11, 16(AX) -+ MOVQ R13, 24(AX) -+ MOVQ R15, 32(AX) -+ RET -+ -+// func feSquare(out *Element, a *Element) -+TEXT Β·feSquare(SB), NOSPLIT, $0-16 -+ MOVQ a+8(FP), CX -+ -+ // r0 = l0Γ—l0 -+ MOVQ (CX), AX -+ MULQ (CX) -+ MOVQ AX, SI -+ MOVQ DX, BX -+ -+ // r0 += 38Γ—l1Γ—l4 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, SI -+ ADCQ DX, BX -+ -+ // r0 += 38Γ—l2Γ—l3 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 24(CX) -+ ADDQ AX, SI -+ ADCQ DX, BX -+ -+ // r1 = 2Γ—l0Γ—l1 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 8(CX) -+ MOVQ AX, R8 -+ MOVQ DX, DI -+ -+ // r1 += 38Γ—l2Γ—l4 -+ MOVQ 16(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, R8 -+ ADCQ DX, DI -+ -+ // r1 += 19Γ—l3Γ—l3 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 24(CX) -+ ADDQ AX, R8 -+ ADCQ DX, DI -+ -+ // r2 = 2Γ—l0Γ—l2 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 16(CX) -+ MOVQ AX, R10 -+ MOVQ DX, R9 -+ -+ // r2 += l1Γ—l1 -+ MOVQ 8(CX), AX -+ MULQ 8(CX) -+ ADDQ AX, R10 -+ ADCQ DX, R9 -+ -+ // r2 += 38Γ—l3Γ—l4 -+ MOVQ 24(CX), AX -+ IMUL3Q $0x26, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, R10 -+ ADCQ DX, R9 -+ -+ // r3 = 2Γ—l0Γ—l3 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 24(CX) -+ MOVQ AX, R12 -+ MOVQ DX, R11 -+ -+ // r3 += 2Γ—l1Γ—l2 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x02, AX, AX -+ MULQ 16(CX) -+ ADDQ AX, R12 -+ ADCQ DX, R11 -+ -+ // r3 += 19Γ—l4Γ—l4 -+ MOVQ 32(CX), AX -+ IMUL3Q $0x13, AX, AX -+ MULQ 32(CX) -+ ADDQ AX, R12 -+ ADCQ DX, R11 -+ -+ // r4 = 2Γ—l0Γ—l4 -+ MOVQ (CX), AX -+ SHLQ $0x01, AX -+ MULQ 32(CX) -+ MOVQ AX, R14 -+ MOVQ DX, R13 -+ -+ // r4 += 2Γ—l1Γ—l3 -+ MOVQ 8(CX), AX -+ IMUL3Q $0x02, AX, AX -+ MULQ 24(CX) -+ ADDQ AX, R14 -+ ADCQ DX, R13 -+ -+ // r4 += l2Γ—l2 -+ MOVQ 16(CX), AX -+ MULQ 16(CX) -+ ADDQ AX, R14 -+ ADCQ DX, R13 -+ -+ // First reduction chain -+ MOVQ $0x0007ffffffffffff, AX -+ SHLQ $0x0d, SI, BX -+ SHLQ $0x0d, R8, DI -+ SHLQ $0x0d, R10, R9 -+ SHLQ $0x0d, R12, R11 -+ SHLQ $0x0d, R14, R13 -+ ANDQ AX, SI -+ IMUL3Q $0x13, R13, R13 -+ ADDQ R13, SI -+ ANDQ AX, R8 -+ ADDQ BX, R8 -+ ANDQ AX, R10 -+ ADDQ DI, R10 -+ ANDQ AX, R12 -+ ADDQ R9, R12 -+ ANDQ AX, R14 -+ ADDQ R11, R14 -+ -+ // Second reduction chain (carryPropagate) -+ MOVQ SI, BX -+ SHRQ $0x33, BX -+ MOVQ R8, DI -+ SHRQ $0x33, DI -+ MOVQ R10, R9 -+ SHRQ $0x33, R9 -+ MOVQ R12, R11 -+ SHRQ $0x33, R11 -+ MOVQ R14, R13 -+ SHRQ $0x33, R13 -+ ANDQ AX, SI -+ IMUL3Q $0x13, R13, R13 -+ ADDQ R13, SI -+ ANDQ AX, R8 -+ ADDQ BX, R8 -+ ANDQ AX, R10 -+ ADDQ DI, R10 -+ ANDQ AX, R12 -+ ADDQ R9, R12 -+ ANDQ AX, R14 -+ ADDQ R11, R14 -+ -+ // Store output -+ MOVQ out+0(FP), AX -+ MOVQ SI, (AX) -+ MOVQ R8, 8(AX) -+ MOVQ R10, 16(AX) -+ MOVQ R12, 24(AX) -+ MOVQ R14, 32(AX) -+ RET -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go -new file mode 100644 -index 00000000000000..ddb6c9b8f7f245 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go -@@ -0,0 +1,12 @@ -+// Copyright (c) 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || !gc || purego -+// +build !amd64 !gc purego -+ -+package field -+ -+func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } -+ -+func feSquare(v, x *Element) { feSquareGeneric(v, x) } -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go -new file mode 100644 -index 00000000000000..af459ef51549e7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go -@@ -0,0 +1,16 @@ -+// Copyright (c) 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build arm64 && gc && !purego -+// +build arm64,gc,!purego -+ -+package field -+ -+//go:noescape -+func carryPropagate(v *Element) -+ -+func (v *Element) carryPropagate() *Element { -+ carryPropagate(v) -+ return v -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s -new file mode 100644 -index 00000000000000..5c91e458923e32 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s -@@ -0,0 +1,43 @@ -+// Copyright (c) 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build arm64 && gc && !purego -+// +build arm64,gc,!purego -+ -+#include "textflag.h" -+ -+// carryPropagate works exactly like carryPropagateGeneric and uses the -+// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but -+// avoids loading R0-R4 twice and uses LDP and STP. -+// -+// See https://golang.org/issues/43145 for the main compiler issue. -+// -+// func carryPropagate(v *Element) -+TEXT Β·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 -+ MOVD v+0(FP), R20 -+ -+ LDP 0(R20), (R0, R1) -+ LDP 16(R20), (R2, R3) -+ MOVD 32(R20), R4 -+ -+ AND $0x7ffffffffffff, R0, R10 -+ AND $0x7ffffffffffff, R1, R11 -+ AND $0x7ffffffffffff, R2, R12 -+ AND $0x7ffffffffffff, R3, R13 -+ AND $0x7ffffffffffff, R4, R14 -+ -+ ADD R0>>51, R11, R11 -+ ADD R1>>51, R12, R12 -+ ADD R2>>51, R13, R13 -+ ADD R3>>51, R14, R14 -+ // R4>>51 * 19 + R10 -> R10 -+ LSR $51, R4, R21 -+ MOVD $19, R22 -+ MADD R22, R10, R21, R10 -+ -+ STP (R10, R11), 0(R20) -+ STP (R12, R13), 16(R20) -+ MOVD R14, 32(R20) -+ -+ RET -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go -new file mode 100644 -index 00000000000000..234a5b2e5d18ab ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go -@@ -0,0 +1,12 @@ -+// Copyright (c) 2021 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !arm64 || !gc || purego -+// +build !arm64 !gc purego -+ -+package field -+ -+func (v *Element) carryPropagate() *Element { -+ return v.carryPropagateGeneric() -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go -new file mode 100644 -index 00000000000000..77dc06cf9861cb ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_bench_test.go -@@ -0,0 +1,36 @@ -+// Copyright (c) 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package field -+ -+import "testing" -+ -+func BenchmarkAdd(b *testing.B) { -+ var x, y Element -+ x.One() -+ y.Add(feOne, feOne) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ x.Add(&x, &y) -+ } -+} -+ -+func BenchmarkMultiply(b *testing.B) { -+ var x, y Element -+ x.One() -+ y.Add(feOne, feOne) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ x.Multiply(&x, &y) -+ } -+} -+ -+func BenchmarkMult32(b *testing.B) { -+ var x Element -+ x.One() -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ x.Mult32(&x, 0xaa42aa42) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go -new file mode 100644 -index 00000000000000..2671217da597cc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_generic.go -@@ -0,0 +1,264 @@ -+// Copyright (c) 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package field -+ -+import "math/bits" -+ -+// uint128 holds a 128-bit number as two 64-bit limbs, for use with the -+// bits.Mul64 and bits.Add64 intrinsics. -+type uint128 struct { -+ lo, hi uint64 -+} -+ -+// mul64 returns a * b. -+func mul64(a, b uint64) uint128 { -+ hi, lo := bits.Mul64(a, b) -+ return uint128{lo, hi} -+} -+ -+// addMul64 returns v + a * b. -+func addMul64(v uint128, a, b uint64) uint128 { -+ hi, lo := bits.Mul64(a, b) -+ lo, c := bits.Add64(lo, v.lo, 0) -+ hi, _ = bits.Add64(hi, v.hi, c) -+ return uint128{lo, hi} -+} -+ -+// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. -+func shiftRightBy51(a uint128) uint64 { -+ return (a.hi << (64 - 51)) | (a.lo >> 51) -+} -+ -+func feMulGeneric(v, a, b *Element) { -+ a0 := a.l0 -+ a1 := a.l1 -+ a2 := a.l2 -+ a3 := a.l3 -+ a4 := a.l4 -+ -+ b0 := b.l0 -+ b1 := b.l1 -+ b2 := b.l2 -+ b3 := b.l3 -+ b4 := b.l4 -+ -+ // Limb multiplication works like pen-and-paper columnar multiplication, but -+ // with 51-bit limbs instead of digits. -+ // -+ // a4 a3 a2 a1 a0 x -+ // b4 b3 b2 b1 b0 = -+ // ------------------------ -+ // a4b0 a3b0 a2b0 a1b0 a0b0 + -+ // a4b1 a3b1 a2b1 a1b1 a0b1 + -+ // a4b2 a3b2 a2b2 a1b2 a0b2 + -+ // a4b3 a3b3 a2b3 a1b3 a0b3 + -+ // a4b4 a3b4 a2b4 a1b4 a0b4 = -+ // ---------------------------------------------- -+ // r8 r7 r6 r5 r4 r3 r2 r1 r0 -+ // -+ // We can then use the reduction identity (a * 2²⁡⁡ + b = a * 19 + b) to -+ // reduce the limbs that would overflow 255 bits. r5 * 2²⁡⁡ becomes 19 * r5, -+ // r6 * 2³⁰⁢ becomes 19 * r6 * 2⁡¹, etc. -+ // -+ // Reduction can be carried out simultaneously to multiplication. For -+ // example, we do not compute r5: whenever the result of a multiplication -+ // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. -+ // -+ // a4b0 a3b0 a2b0 a1b0 a0b0 + -+ // a3b1 a2b1 a1b1 a0b1 19Γ—a4b1 + -+ // a2b2 a1b2 a0b2 19Γ—a4b2 19Γ—a3b2 + -+ // a1b3 a0b3 19Γ—a4b3 19Γ—a3b3 19Γ—a2b3 + -+ // a0b4 19Γ—a4b4 19Γ—a3b4 19Γ—a2b4 19Γ—a1b4 = -+ // -------------------------------------- -+ // r4 r3 r2 r1 r0 -+ // -+ // Finally we add up the columns into wide, overlapping limbs. -+ -+ a1_19 := a1 * 19 -+ a2_19 := a2 * 19 -+ a3_19 := a3 * 19 -+ a4_19 := a4 * 19 -+ -+ // r0 = a0Γ—b0 + 19Γ—(a1Γ—b4 + a2Γ—b3 + a3Γ—b2 + a4Γ—b1) -+ r0 := mul64(a0, b0) -+ r0 = addMul64(r0, a1_19, b4) -+ r0 = addMul64(r0, a2_19, b3) -+ r0 = addMul64(r0, a3_19, b2) -+ r0 = addMul64(r0, a4_19, b1) -+ -+ // r1 = a0Γ—b1 + a1Γ—b0 + 19Γ—(a2Γ—b4 + a3Γ—b3 + a4Γ—b2) -+ r1 := mul64(a0, b1) -+ r1 = addMul64(r1, a1, b0) -+ r1 = addMul64(r1, a2_19, b4) -+ r1 = addMul64(r1, a3_19, b3) -+ r1 = addMul64(r1, a4_19, b2) -+ -+ // r2 = a0Γ—b2 + a1Γ—b1 + a2Γ—b0 + 19Γ—(a3Γ—b4 + a4Γ—b3) -+ r2 := mul64(a0, b2) -+ r2 = addMul64(r2, a1, b1) -+ r2 = addMul64(r2, a2, b0) -+ r2 = addMul64(r2, a3_19, b4) -+ r2 = addMul64(r2, a4_19, b3) -+ -+ // r3 = a0Γ—b3 + a1Γ—b2 + a2Γ—b1 + a3Γ—b0 + 19Γ—a4Γ—b4 -+ r3 := mul64(a0, b3) -+ r3 = addMul64(r3, a1, b2) -+ r3 = addMul64(r3, a2, b1) -+ r3 = addMul64(r3, a3, b0) -+ r3 = addMul64(r3, a4_19, b4) -+ -+ // r4 = a0Γ—b4 + a1Γ—b3 + a2Γ—b2 + a3Γ—b1 + a4Γ—b0 -+ r4 := mul64(a0, b4) -+ r4 = addMul64(r4, a1, b3) -+ r4 = addMul64(r4, a2, b2) -+ r4 = addMul64(r4, a3, b1) -+ r4 = addMul64(r4, a4, b0) -+ -+ // After the multiplication, we need to reduce (carry) the five coefficients -+ // to obtain a result with limbs that are at most slightly larger than 2⁡¹, -+ // to respect the Element invariant. -+ // -+ // Overall, the reduction works the same as carryPropagate, except with -+ // wider inputs: we take the carry for each coefficient by shifting it right -+ // by 51, and add it to the limb above it. The top carry is multiplied by 19 -+ // according to the reduction identity and added to the lowest limb. -+ // -+ // The largest coefficient (r0) will be at most 111 bits, which guarantees -+ // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. -+ // -+ // r0 = a0Γ—b0 + 19Γ—(a1Γ—b4 + a2Γ—b3 + a3Γ—b2 + a4Γ—b1) -+ // r0 < 2⁡²×2⁡² + 19Γ—(2⁡²×2⁡² + 2⁡²×2⁡² + 2⁡²×2⁡² + 2⁡²×2⁡²) -+ // r0 < (1 + 19 Γ— 4) Γ— 2⁡² Γ— 2⁡² -+ // r0 < 2⁷ Γ— 2⁡² Γ— 2⁡² -+ // r0 < 2ΒΉΒΉΒΉ -+ // -+ // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most -+ // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and -+ // allows us to easily apply the reduction identity. -+ // -+ // r4 = a0Γ—b4 + a1Γ—b3 + a2Γ—b2 + a3Γ—b1 + a4Γ—b0 -+ // r4 < 5 Γ— 2⁡² Γ— 2⁡² -+ // r4 < 2¹⁰⁷ -+ // -+ -+ c0 := shiftRightBy51(r0) -+ c1 := shiftRightBy51(r1) -+ c2 := shiftRightBy51(r2) -+ c3 := shiftRightBy51(r3) -+ c4 := shiftRightBy51(r4) -+ -+ rr0 := r0.lo&maskLow51Bits + c4*19 -+ rr1 := r1.lo&maskLow51Bits + c0 -+ rr2 := r2.lo&maskLow51Bits + c1 -+ rr3 := r3.lo&maskLow51Bits + c2 -+ rr4 := r4.lo&maskLow51Bits + c3 -+ -+ // Now all coefficients fit into 64-bit registers but are still too large to -+ // be passed around as a Element. We therefore do one last carry chain, -+ // where the carries will be small enough to fit in the wiggle room above 2⁡¹. -+ *v = Element{rr0, rr1, rr2, rr3, rr4} -+ v.carryPropagate() -+} -+ -+func feSquareGeneric(v, a *Element) { -+ l0 := a.l0 -+ l1 := a.l1 -+ l2 := a.l2 -+ l3 := a.l3 -+ l4 := a.l4 -+ -+ // Squaring works precisely like multiplication above, but thanks to its -+ // symmetry we get to group a few terms together. -+ // -+ // l4 l3 l2 l1 l0 x -+ // l4 l3 l2 l1 l0 = -+ // ------------------------ -+ // l4l0 l3l0 l2l0 l1l0 l0l0 + -+ // l4l1 l3l1 l2l1 l1l1 l0l1 + -+ // l4l2 l3l2 l2l2 l1l2 l0l2 + -+ // l4l3 l3l3 l2l3 l1l3 l0l3 + -+ // l4l4 l3l4 l2l4 l1l4 l0l4 = -+ // ---------------------------------------------- -+ // r8 r7 r6 r5 r4 r3 r2 r1 r0 -+ // -+ // l4l0 l3l0 l2l0 l1l0 l0l0 + -+ // l3l1 l2l1 l1l1 l0l1 19Γ—l4l1 + -+ // l2l2 l1l2 l0l2 19Γ—l4l2 19Γ—l3l2 + -+ // l1l3 l0l3 19Γ—l4l3 19Γ—l3l3 19Γ—l2l3 + -+ // l0l4 19Γ—l4l4 19Γ—l3l4 19Γ—l2l4 19Γ—l1l4 = -+ // -------------------------------------- -+ // r4 r3 r2 r1 r0 -+ // -+ // With precomputed 2Γ—, 19Γ—, and 2Γ—19Γ— terms, we can compute each limb with -+ // only three Mul64 and four Add64, instead of five and eight. -+ -+ l0_2 := l0 * 2 -+ l1_2 := l1 * 2 -+ -+ l1_38 := l1 * 38 -+ l2_38 := l2 * 38 -+ l3_38 := l3 * 38 -+ -+ l3_19 := l3 * 19 -+ l4_19 := l4 * 19 -+ -+ // r0 = l0Γ—l0 + 19Γ—(l1Γ—l4 + l2Γ—l3 + l3Γ—l2 + l4Γ—l1) = l0Γ—l0 + 19Γ—2Γ—(l1Γ—l4 + l2Γ—l3) -+ r0 := mul64(l0, l0) -+ r0 = addMul64(r0, l1_38, l4) -+ r0 = addMul64(r0, l2_38, l3) -+ -+ // r1 = l0Γ—l1 + l1Γ—l0 + 19Γ—(l2Γ—l4 + l3Γ—l3 + l4Γ—l2) = 2Γ—l0Γ—l1 + 19Γ—2Γ—l2Γ—l4 + 19Γ—l3Γ—l3 -+ r1 := mul64(l0_2, l1) -+ r1 = addMul64(r1, l2_38, l4) -+ r1 = addMul64(r1, l3_19, l3) -+ -+ // r2 = l0Γ—l2 + l1Γ—l1 + l2Γ—l0 + 19Γ—(l3Γ—l4 + l4Γ—l3) = 2Γ—l0Γ—l2 + l1Γ—l1 + 19Γ—2Γ—l3Γ—l4 -+ r2 := mul64(l0_2, l2) -+ r2 = addMul64(r2, l1, l1) -+ r2 = addMul64(r2, l3_38, l4) -+ -+ // r3 = l0Γ—l3 + l1Γ—l2 + l2Γ—l1 + l3Γ—l0 + 19Γ—l4Γ—l4 = 2Γ—l0Γ—l3 + 2Γ—l1Γ—l2 + 19Γ—l4Γ—l4 -+ r3 := mul64(l0_2, l3) -+ r3 = addMul64(r3, l1_2, l2) -+ r3 = addMul64(r3, l4_19, l4) -+ -+ // r4 = l0Γ—l4 + l1Γ—l3 + l2Γ—l2 + l3Γ—l1 + l4Γ—l0 = 2Γ—l0Γ—l4 + 2Γ—l1Γ—l3 + l2Γ—l2 -+ r4 := mul64(l0_2, l4) -+ r4 = addMul64(r4, l1_2, l3) -+ r4 = addMul64(r4, l2, l2) -+ -+ c0 := shiftRightBy51(r0) -+ c1 := shiftRightBy51(r1) -+ c2 := shiftRightBy51(r2) -+ c3 := shiftRightBy51(r3) -+ c4 := shiftRightBy51(r4) -+ -+ rr0 := r0.lo&maskLow51Bits + c4*19 -+ rr1 := r1.lo&maskLow51Bits + c0 -+ rr2 := r2.lo&maskLow51Bits + c1 -+ rr3 := r3.lo&maskLow51Bits + c2 -+ rr4 := r4.lo&maskLow51Bits + c3 -+ -+ *v = Element{rr0, rr1, rr2, rr3, rr4} -+ v.carryPropagate() -+} -+ -+// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction -+// identity (a * 2²⁡⁡ + b = a * 19 + b) to the l4 carry. TODO inline -+func (v *Element) carryPropagateGeneric() *Element { -+ c0 := v.l0 >> 51 -+ c1 := v.l1 >> 51 -+ c2 := v.l2 >> 51 -+ c3 := v.l3 >> 51 -+ c4 := v.l4 >> 51 -+ -+ v.l0 = v.l0&maskLow51Bits + c4*19 -+ v.l1 = v.l1&maskLow51Bits + c0 -+ v.l2 = v.l2&maskLow51Bits + c1 -+ v.l3 = v.l3&maskLow51Bits + c2 -+ v.l4 = v.l4&maskLow51Bits + c3 -+ -+ return v -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go -new file mode 100644 -index 00000000000000..b484459ff251f2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/fe_test.go -@@ -0,0 +1,558 @@ -+// Copyright (c) 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package field -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/hex" -+ "io" -+ "math/big" -+ "math/bits" -+ mathrand "math/rand" -+ "reflect" -+ "testing" -+ "testing/quick" -+) -+ -+func (v Element) String() string { -+ return hex.EncodeToString(v.Bytes()) -+} -+ -+// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks) -+// times. The default value of -quickchecks is 100. -+var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10} -+ -+func generateFieldElement(rand *mathrand.Rand) Element { -+ const maskLow52Bits = (1 << 52) - 1 -+ return Element{ -+ rand.Uint64() & maskLow52Bits, -+ rand.Uint64() & maskLow52Bits, -+ rand.Uint64() & maskLow52Bits, -+ rand.Uint64() & maskLow52Bits, -+ rand.Uint64() & maskLow52Bits, -+ } -+} -+ -+// weirdLimbs can be combined to generate a range of edge-case field elements. -+// 0 and -1 are intentionally more weighted, as they combine well. -+var ( -+ weirdLimbs51 = []uint64{ -+ 0, 0, 0, 0, -+ 1, -+ 19 - 1, -+ 19, -+ 0x2aaaaaaaaaaaa, -+ 0x5555555555555, -+ (1 << 51) - 20, -+ (1 << 51) - 19, -+ (1 << 51) - 1, (1 << 51) - 1, -+ (1 << 51) - 1, (1 << 51) - 1, -+ } -+ weirdLimbs52 = []uint64{ -+ 0, 0, 0, 0, 0, 0, -+ 1, -+ 19 - 1, -+ 19, -+ 0x2aaaaaaaaaaaa, -+ 0x5555555555555, -+ (1 << 51) - 20, -+ (1 << 51) - 19, -+ (1 << 51) - 1, (1 << 51) - 1, -+ (1 << 51) - 1, (1 << 51) - 1, -+ (1 << 51) - 1, (1 << 51) - 1, -+ 1 << 51, -+ (1 << 51) + 1, -+ (1 << 52) - 19, -+ (1 << 52) - 1, -+ } -+) -+ -+func generateWeirdFieldElement(rand *mathrand.Rand) Element { -+ return Element{ -+ weirdLimbs52[rand.Intn(len(weirdLimbs52))], -+ weirdLimbs51[rand.Intn(len(weirdLimbs51))], -+ weirdLimbs51[rand.Intn(len(weirdLimbs51))], -+ weirdLimbs51[rand.Intn(len(weirdLimbs51))], -+ weirdLimbs51[rand.Intn(len(weirdLimbs51))], -+ } -+} -+ -+func (Element) Generate(rand *mathrand.Rand, size int) reflect.Value { -+ if rand.Intn(2) == 0 { -+ return reflect.ValueOf(generateWeirdFieldElement(rand)) -+ } -+ return reflect.ValueOf(generateFieldElement(rand)) -+} -+ -+// isInBounds returns whether the element is within the expected bit size bounds -+// after a light reduction. -+func isInBounds(x *Element) bool { -+ return bits.Len64(x.l0) <= 52 && -+ bits.Len64(x.l1) <= 52 && -+ bits.Len64(x.l2) <= 52 && -+ bits.Len64(x.l3) <= 52 && -+ bits.Len64(x.l4) <= 52 -+} -+ -+func TestMultiplyDistributesOverAdd(t *testing.T) { -+ multiplyDistributesOverAdd := func(x, y, z Element) bool { -+ // Compute t1 = (x+y)*z -+ t1 := new(Element) -+ t1.Add(&x, &y) -+ t1.Multiply(t1, &z) -+ -+ // Compute t2 = x*z + y*z -+ t2 := new(Element) -+ t3 := new(Element) -+ t2.Multiply(&x, &z) -+ t3.Multiply(&y, &z) -+ t2.Add(t2, t3) -+ -+ return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) -+ } -+ -+ if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestMul64to128(t *testing.T) { -+ a := uint64(5) -+ b := uint64(5) -+ r := mul64(a, b) -+ if r.lo != 0x19 || r.hi != 0 { -+ t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) -+ } -+ -+ a = uint64(18014398509481983) // 2^54 - 1 -+ b = uint64(18014398509481983) // 2^54 - 1 -+ r = mul64(a, b) -+ if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff { -+ t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) -+ } -+ -+ a = uint64(1125899906842661) -+ b = uint64(2097155) -+ r = mul64(a, b) -+ r = addMul64(r, a, b) -+ r = addMul64(r, a, b) -+ r = addMul64(r, a, b) -+ r = addMul64(r, a, b) -+ if r.lo != 16888498990613035 || r.hi != 640 { -+ t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi) -+ } -+} -+ -+func TestSetBytesRoundTrip(t *testing.T) { -+ f1 := func(in [32]byte, fe Element) bool { -+ fe.SetBytes(in[:]) -+ -+ // Mask the most significant bit as it's ignored by SetBytes. (Now -+ // instead of earlier so we check the masking in SetBytes is working.) -+ in[len(in)-1] &= (1 << 7) - 1 -+ -+ return bytes.Equal(in[:], fe.Bytes()) && isInBounds(&fe) -+ } -+ if err := quick.Check(f1, nil); err != nil { -+ t.Errorf("failed bytes->FE->bytes round-trip: %v", err) -+ } -+ -+ f2 := func(fe, r Element) bool { -+ r.SetBytes(fe.Bytes()) -+ -+ // Intentionally not using Equal not to go through Bytes again. -+ // Calling reduce because both Generate and SetBytes can produce -+ // non-canonical representations. -+ fe.reduce() -+ r.reduce() -+ return fe == r -+ } -+ if err := quick.Check(f2, nil); err != nil { -+ t.Errorf("failed FE->bytes->FE round-trip: %v", err) -+ } -+ -+ // Check some fixed vectors from dalek -+ type feRTTest struct { -+ fe Element -+ b []byte -+ } -+ var tests = []feRTTest{ -+ { -+ fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}, -+ b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31}, -+ }, -+ { -+ fe: Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}, -+ b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122}, -+ }, -+ } -+ -+ for _, tt := range tests { -+ b := tt.fe.Bytes() -+ if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 { -+ t.Errorf("Failed fixed roundtrip: %v", tt) -+ } -+ } -+} -+ -+func swapEndianness(buf []byte) []byte { -+ for i := 0; i < len(buf)/2; i++ { -+ buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i] -+ } -+ return buf -+} -+ -+func TestBytesBigEquivalence(t *testing.T) { -+ f1 := func(in [32]byte, fe, fe1 Element) bool { -+ fe.SetBytes(in[:]) -+ -+ in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit -+ b := new(big.Int).SetBytes(swapEndianness(in[:])) -+ fe1.fromBig(b) -+ -+ if fe != fe1 { -+ return false -+ } -+ -+ buf := make([]byte, 32) // pad with zeroes -+ copy(buf, swapEndianness(fe1.toBig().Bytes())) -+ -+ return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1) -+ } -+ if err := quick.Check(f1, nil); err != nil { -+ t.Error(err) -+ } -+} -+ -+// fromBig sets v = n, and returns v. The bit length of n must not exceed 256. -+func (v *Element) fromBig(n *big.Int) *Element { -+ if n.BitLen() > 32*8 { -+ panic("edwards25519: invalid field element input size") -+ } -+ -+ buf := make([]byte, 0, 32) -+ for _, word := range n.Bits() { -+ for i := 0; i < bits.UintSize; i += 8 { -+ if len(buf) >= cap(buf) { -+ break -+ } -+ buf = append(buf, byte(word)) -+ word >>= 8 -+ } -+ } -+ -+ return v.SetBytes(buf[:32]) -+} -+ -+func (v *Element) fromDecimal(s string) *Element { -+ n, ok := new(big.Int).SetString(s, 10) -+ if !ok { -+ panic("not a valid decimal: " + s) -+ } -+ return v.fromBig(n) -+} -+ -+// toBig returns v as a big.Int. -+func (v *Element) toBig() *big.Int { -+ buf := v.Bytes() -+ -+ words := make([]big.Word, 32*8/bits.UintSize) -+ for n := range words { -+ for i := 0; i < bits.UintSize; i += 8 { -+ if len(buf) == 0 { -+ break -+ } -+ words[n] |= big.Word(buf[0]) << big.Word(i) -+ buf = buf[1:] -+ } -+ } -+ -+ return new(big.Int).SetBits(words) -+} -+ -+func TestDecimalConstants(t *testing.T) { -+ sqrtM1String := "19681161376707505956807079304988542015446066515923890162744021073123829784752" -+ if exp := new(Element).fromDecimal(sqrtM1String); sqrtM1.Equal(exp) != 1 { -+ t.Errorf("sqrtM1 is %v, expected %v", sqrtM1, exp) -+ } -+ // d is in the parent package, and we don't want to expose d or fromDecimal. -+ // dString := "37095705934669439343138083508754565189542113879843219016388785533085940283555" -+ // if exp := new(Element).fromDecimal(dString); d.Equal(exp) != 1 { -+ // t.Errorf("d is %v, expected %v", d, exp) -+ // } -+} -+ -+func TestSetBytesRoundTripEdgeCases(t *testing.T) { -+ // TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1, -+ // and between 2^255 and 2^256-1. Test both the documented SetBytes -+ // behavior, and that Bytes reduces them. -+} -+ -+// Tests self-consistency between Multiply and Square. -+func TestConsistency(t *testing.T) { -+ var x Element -+ var x2, x2sq Element -+ -+ x = Element{1, 1, 1, 1, 1} -+ x2.Multiply(&x, &x) -+ x2sq.Square(&x) -+ -+ if x2 != x2sq { -+ t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) -+ } -+ -+ var bytes [32]byte -+ -+ _, err := io.ReadFull(rand.Reader, bytes[:]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ x.SetBytes(bytes[:]) -+ -+ x2.Multiply(&x, &x) -+ x2sq.Square(&x) -+ -+ if x2 != x2sq { -+ t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) -+ } -+} -+ -+func TestEqual(t *testing.T) { -+ x := Element{1, 1, 1, 1, 1} -+ y := Element{5, 4, 3, 2, 1} -+ -+ eq := x.Equal(&x) -+ if eq != 1 { -+ t.Errorf("wrong about equality") -+ } -+ -+ eq = x.Equal(&y) -+ if eq != 0 { -+ t.Errorf("wrong about inequality") -+ } -+} -+ -+func TestInvert(t *testing.T) { -+ x := Element{1, 1, 1, 1, 1} -+ one := Element{1, 0, 0, 0, 0} -+ var xinv, r Element -+ -+ xinv.Invert(&x) -+ r.Multiply(&x, &xinv) -+ r.reduce() -+ -+ if one != r { -+ t.Errorf("inversion identity failed, got: %x", r) -+ } -+ -+ var bytes [32]byte -+ -+ _, err := io.ReadFull(rand.Reader, bytes[:]) -+ if err != nil { -+ t.Fatal(err) -+ } -+ x.SetBytes(bytes[:]) -+ -+ xinv.Invert(&x) -+ r.Multiply(&x, &xinv) -+ r.reduce() -+ -+ if one != r { -+ t.Errorf("random inversion identity failed, got: %x for field element %x", r, x) -+ } -+ -+ zero := Element{} -+ x.Set(&zero) -+ if xx := xinv.Invert(&x); xx != &xinv { -+ t.Errorf("inverting zero did not return the receiver") -+ } else if xinv.Equal(&zero) != 1 { -+ t.Errorf("inverting zero did not return zero") -+ } -+} -+ -+func TestSelectSwap(t *testing.T) { -+ a := Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676} -+ b := Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972} -+ -+ var c, d Element -+ -+ c.Select(&a, &b, 1) -+ d.Select(&a, &b, 0) -+ -+ if c.Equal(&a) != 1 || d.Equal(&b) != 1 { -+ t.Errorf("Select failed") -+ } -+ -+ c.Swap(&d, 0) -+ -+ if c.Equal(&a) != 1 || d.Equal(&b) != 1 { -+ t.Errorf("Swap failed") -+ } -+ -+ c.Swap(&d, 1) -+ -+ if c.Equal(&b) != 1 || d.Equal(&a) != 1 { -+ t.Errorf("Swap failed") -+ } -+} -+ -+func TestMult32(t *testing.T) { -+ mult32EquivalentToMul := func(x Element, y uint32) bool { -+ t1 := new(Element) -+ for i := 0; i < 100; i++ { -+ t1.Mult32(&x, y) -+ } -+ -+ ty := new(Element) -+ ty.l0 = uint64(y) -+ -+ t2 := new(Element) -+ for i := 0; i < 100; i++ { -+ t2.Multiply(&x, ty) -+ } -+ -+ return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) -+ } -+ -+ if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestSqrtRatio(t *testing.T) { -+ // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4. -+ type test struct { -+ u, v string -+ wasSquare int -+ r string -+ } -+ var tests = []test{ -+ // If u is 0, the function is defined to return (0, TRUE), even if v -+ // is zero. Note that where used in this package, the denominator v -+ // is never zero. -+ { -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ 1, "0000000000000000000000000000000000000000000000000000000000000000", -+ }, -+ // 0/1 == 0Β² -+ { -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ "0100000000000000000000000000000000000000000000000000000000000000", -+ 1, "0000000000000000000000000000000000000000000000000000000000000000", -+ }, -+ // If u is non-zero and v is zero, defined to return (0, FALSE). -+ { -+ "0100000000000000000000000000000000000000000000000000000000000000", -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ 0, "0000000000000000000000000000000000000000000000000000000000000000", -+ }, -+ // 2/1 is not square in this field. -+ { -+ "0200000000000000000000000000000000000000000000000000000000000000", -+ "0100000000000000000000000000000000000000000000000000000000000000", -+ 0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54", -+ }, -+ // 4/1 == 2Β² -+ { -+ "0400000000000000000000000000000000000000000000000000000000000000", -+ "0100000000000000000000000000000000000000000000000000000000000000", -+ 1, "0200000000000000000000000000000000000000000000000000000000000000", -+ }, -+ // 1/4 == (2⁻¹)Β² == (2^(p-2))Β² per Euler's theorem -+ { -+ "0100000000000000000000000000000000000000000000000000000000000000", -+ "0400000000000000000000000000000000000000000000000000000000000000", -+ 1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f", -+ }, -+ } -+ -+ for i, tt := range tests { -+ u := new(Element).SetBytes(decodeHex(tt.u)) -+ v := new(Element).SetBytes(decodeHex(tt.v)) -+ want := new(Element).SetBytes(decodeHex(tt.r)) -+ got, wasSquare := new(Element).SqrtRatio(u, v) -+ if got.Equal(want) == 0 || wasSquare != tt.wasSquare { -+ t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare) -+ } -+ } -+} -+ -+func TestCarryPropagate(t *testing.T) { -+ asmLikeGeneric := func(a [5]uint64) bool { -+ t1 := &Element{a[0], a[1], a[2], a[3], a[4]} -+ t2 := &Element{a[0], a[1], a[2], a[3], a[4]} -+ -+ t1.carryPropagate() -+ t2.carryPropagateGeneric() -+ -+ if *t1 != *t2 { -+ t.Logf("got: %#v,\nexpected: %#v", t1, t2) -+ } -+ -+ return *t1 == *t2 && isInBounds(t2) -+ } -+ -+ if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { -+ t.Error(err) -+ } -+ -+ if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) { -+ t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}") -+ } -+} -+ -+func TestFeSquare(t *testing.T) { -+ asmLikeGeneric := func(a Element) bool { -+ t1 := a -+ t2 := a -+ -+ feSquareGeneric(&t1, &t1) -+ feSquare(&t2, &t2) -+ -+ if t1 != t2 { -+ t.Logf("got: %#v,\nexpected: %#v", t1, t2) -+ } -+ -+ return t1 == t2 && isInBounds(&t2) -+ } -+ -+ if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestFeMul(t *testing.T) { -+ asmLikeGeneric := func(a, b Element) bool { -+ a1 := a -+ a2 := a -+ b1 := b -+ b2 := b -+ -+ feMulGeneric(&a1, &a1, &b1) -+ feMul(&a2, &a2, &b2) -+ -+ if a1 != a2 || b1 != b2 { -+ t.Logf("got: %#v,\nexpected: %#v", a1, a2) -+ t.Logf("got: %#v,\nexpected: %#v", b1, b2) -+ } -+ -+ return a1 == a2 && isInBounds(&a2) && -+ b1 == b2 && isInBounds(&b2) -+ } -+ -+ if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { -+ t.Error(err) -+ } -+} -+ -+func decodeHex(s string) []byte { -+ b, err := hex.DecodeString(s) -+ if err != nil { -+ panic(err) -+ } -+ return b -+} -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint -new file mode 100644 -index 00000000000000..e3685f95cab22f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint -@@ -0,0 +1 @@ -+b0c49ae9f59d233526f8934262c5bbbe14d4358d -diff --git a/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh -new file mode 100644 -index 00000000000000..1ba22a8b4c9a28 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/internal/field/sync.sh -@@ -0,0 +1,19 @@ -+#! /bin/bash -+set -euo pipefail -+ -+cd "$(git rev-parse --show-toplevel)" -+ -+STD_PATH=src/crypto/ed25519/internal/edwards25519/field -+LOCAL_PATH=curve25519/internal/field -+LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint) -+ -+git fetch https://go.googlesource.com/go master -+ -+if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then -+ echo "No changes." -+else -+ NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint) -+ echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..." -+ git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \ -+ git apply -3 --directory=$LOCAL_PATH -+fi -diff --git a/ms_mod/golang.org/x/crypto/curve25519/vectors_test.go b/ms_mod/golang.org/x/crypto/curve25519/vectors_test.go -new file mode 100644 -index 00000000000000..f4c0a1414f0cea ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/curve25519/vectors_test.go -@@ -0,0 +1,105 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package curve25519_test -+ -+// lowOrderPoints from libsodium. -+// https://github.com/jedisct1/libsodium/blob/65621a1059a37d/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L11-L70 -+var lowOrderPoints = [][]byte{ -+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ {0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00}, -+ {0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57}, -+ {0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, -+ {0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, -+ {0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, -+} -+ -+// testVectors generated with BoringSSL. -+var testVectors = []struct { -+ In [32]byte -+ Base [32]byte -+ Expect [32]byte -+}{ -+ { -+ In: [32]byte{0x66, 0x8f, 0xb9, 0xf7, 0x6a, 0xd9, 0x71, 0xc8, 0x1a, 0xc9, 0x0, 0x7, 0x1a, 0x15, 0x60, 0xbc, 0xe2, 0xca, 0x0, 0xca, 0xc7, 0xe6, 0x7a, 0xf9, 0x93, 0x48, 0x91, 0x37, 0x61, 0x43, 0x40, 0x14}, -+ Base: [32]byte{0xdb, 0x5f, 0x32, 0xb7, 0xf8, 0x41, 0xe7, 0xa1, 0xa0, 0x9, 0x68, 0xef, 0xfd, 0xed, 0x12, 0x73, 0x5f, 0xc4, 0x7a, 0x3e, 0xb1, 0x3b, 0x57, 0x9a, 0xac, 0xad, 0xea, 0xe8, 0x9, 0x39, 0xa7, 0xdd}, -+ Expect: [32]byte{0x9, 0xd, 0x85, 0xe5, 0x99, 0xea, 0x8e, 0x2b, 0xee, 0xb6, 0x13, 0x4, 0xd3, 0x7b, 0xe1, 0xe, 0xc5, 0xc9, 0x5, 0xf9, 0x92, 0x7d, 0x32, 0xf4, 0x2a, 0x9a, 0xa, 0xfb, 0x3e, 0xb, 0x40, 0x74}, -+ }, -+ { -+ In: [32]byte{0x63, 0x66, 0x95, 0xe3, 0x4f, 0x75, 0xb9, 0xa2, 0x79, 0xc8, 0x70, 0x6f, 0xad, 0x12, 0x89, 0xf2, 0xc0, 0xb1, 0xe2, 0x2e, 0x16, 0xf8, 0xb8, 0x86, 0x17, 0x29, 0xc1, 0xa, 0x58, 0x29, 0x58, 0xaf}, -+ Base: [32]byte{0x9, 0xd, 0x7, 0x1, 0xf8, 0xfd, 0xe2, 0x8f, 0x70, 0x4, 0x3b, 0x83, 0xf2, 0x34, 0x62, 0x25, 0x41, 0x9b, 0x18, 0xa7, 0xf2, 0x7e, 0x9e, 0x3d, 0x2b, 0xfd, 0x4, 0xe1, 0xf, 0x3d, 0x21, 0x3e}, -+ Expect: [32]byte{0xbf, 0x26, 0xec, 0x7e, 0xc4, 0x13, 0x6, 0x17, 0x33, 0xd4, 0x40, 0x70, 0xea, 0x67, 0xca, 0xb0, 0x2a, 0x85, 0xdc, 0x1b, 0xe8, 0xcf, 0xe1, 0xff, 0x73, 0xd5, 0x41, 0xcc, 0x8, 0x32, 0x55, 0x6}, -+ }, -+ { -+ In: [32]byte{0x73, 0x41, 0x81, 0xcd, 0x1a, 0x94, 0x6, 0x52, 0x2a, 0x56, 0xfe, 0x25, 0xe4, 0x3e, 0xcb, 0xf0, 0x29, 0x5d, 0xb5, 0xdd, 0xd0, 0x60, 0x9b, 0x3c, 0x2b, 0x4e, 0x79, 0xc0, 0x6f, 0x8b, 0xd4, 0x6d}, -+ Base: [32]byte{0xf8, 0xa8, 0x42, 0x1c, 0x7d, 0x21, 0xa9, 0x2d, 0xb3, 0xed, 0xe9, 0x79, 0xe1, 0xfa, 0x6a, 0xcb, 0x6, 0x2b, 0x56, 0xb1, 0x88, 0x5c, 0x71, 0xc5, 0x11, 0x53, 0xcc, 0xb8, 0x80, 0xac, 0x73, 0x15}, -+ Expect: [32]byte{0x11, 0x76, 0xd0, 0x16, 0x81, 0xf2, 0xcf, 0x92, 0x9d, 0xa2, 0xc7, 0xa3, 0xdf, 0x66, 0xb5, 0xd7, 0x72, 0x9f, 0xd4, 0x22, 0x22, 0x6f, 0xd6, 0x37, 0x42, 0x16, 0xbf, 0x7e, 0x2, 0xfd, 0xf, 0x62}, -+ }, -+ { -+ In: [32]byte{0x1f, 0x70, 0x39, 0x1f, 0x6b, 0xa8, 0x58, 0x12, 0x94, 0x13, 0xbd, 0x80, 0x1b, 0x12, 0xac, 0xbf, 0x66, 0x23, 0x62, 0x82, 0x5c, 0xa2, 0x50, 0x9c, 0x81, 0x87, 0x59, 0xa, 0x2b, 0xe, 0x61, 0x72}, -+ Base: [32]byte{0xd3, 0xea, 0xd0, 0x7a, 0x0, 0x8, 0xf4, 0x45, 0x2, 0xd5, 0x80, 0x8b, 0xff, 0xc8, 0x97, 0x9f, 0x25, 0xa8, 0x59, 0xd5, 0xad, 0xf4, 0x31, 0x2e, 0xa4, 0x87, 0x48, 0x9c, 0x30, 0xe0, 0x1b, 0x3b}, -+ Expect: [32]byte{0xf8, 0x48, 0x2f, 0x2e, 0x9e, 0x58, 0xbb, 0x6, 0x7e, 0x86, 0xb2, 0x87, 0x24, 0xb3, 0xc0, 0xa3, 0xbb, 0xb5, 0x7, 0x3e, 0x4c, 0x6a, 0xcd, 0x93, 0xdf, 0x54, 0x5e, 0xff, 0xdb, 0xba, 0x50, 0x5f}, -+ }, -+ { -+ In: [32]byte{0x3a, 0x7a, 0xe6, 0xcf, 0x8b, 0x88, 0x9d, 0x2b, 0x7a, 0x60, 0xa4, 0x70, 0xad, 0x6a, 0xd9, 0x99, 0x20, 0x6b, 0xf5, 0x7d, 0x90, 0x30, 0xdd, 0xf7, 0xf8, 0x68, 0xc, 0x8b, 0x1a, 0x64, 0x5d, 0xaa}, -+ Base: [32]byte{0x4d, 0x25, 0x4c, 0x80, 0x83, 0xd8, 0x7f, 0x1a, 0x9b, 0x3e, 0xa7, 0x31, 0xef, 0xcf, 0xf8, 0xa6, 0xf2, 0x31, 0x2d, 0x6f, 0xed, 0x68, 0xe, 0xf8, 0x29, 0x18, 0x51, 0x61, 0xc8, 0xfc, 0x50, 0x60}, -+ Expect: [32]byte{0x47, 0xb3, 0x56, 0xd5, 0x81, 0x8d, 0xe8, 0xef, 0xac, 0x77, 0x4b, 0x71, 0x4c, 0x42, 0xc4, 0x4b, 0xe6, 0x85, 0x23, 0xdd, 0x57, 0xdb, 0xd7, 0x39, 0x62, 0xd5, 0xa5, 0x26, 0x31, 0x87, 0x62, 0x37}, -+ }, -+ { -+ In: [32]byte{0x20, 0x31, 0x61, 0xc3, 0x15, 0x9a, 0x87, 0x6a, 0x2b, 0xea, 0xec, 0x29, 0xd2, 0x42, 0x7f, 0xb0, 0xc7, 0xc3, 0xd, 0x38, 0x2c, 0xd0, 0x13, 0xd2, 0x7c, 0xc3, 0xd3, 0x93, 0xdb, 0xd, 0xaf, 0x6f}, -+ Base: [32]byte{0x6a, 0xb9, 0x5d, 0x1a, 0xbe, 0x68, 0xc0, 0x9b, 0x0, 0x5c, 0x3d, 0xb9, 0x4, 0x2c, 0xc9, 0x1a, 0xc8, 0x49, 0xf7, 0xe9, 0x4a, 0x2a, 0x4a, 0x9b, 0x89, 0x36, 0x78, 0x97, 0xb, 0x7b, 0x95, 0xbf}, -+ Expect: [32]byte{0x11, 0xed, 0xae, 0xdc, 0x95, 0xff, 0x78, 0xf5, 0x63, 0xa1, 0xc8, 0xf1, 0x55, 0x91, 0xc0, 0x71, 0xde, 0xa0, 0x92, 0xb4, 0xd7, 0xec, 0xaa, 0xc8, 0xe0, 0x38, 0x7b, 0x5a, 0x16, 0xc, 0x4e, 0x5d}, -+ }, -+ { -+ In: [32]byte{0x13, 0xd6, 0x54, 0x91, 0xfe, 0x75, 0xf2, 0x3, 0xa0, 0x8, 0xb4, 0x41, 0x5a, 0xbc, 0x60, 0xd5, 0x32, 0xe6, 0x95, 0xdb, 0xd2, 0xf1, 0xe8, 0x3, 0xac, 0xcb, 0x34, 0xb2, 0xb7, 0x2c, 0x3d, 0x70}, -+ Base: [32]byte{0x2e, 0x78, 0x4e, 0x4, 0xca, 0x0, 0x73, 0x33, 0x62, 0x56, 0xa8, 0x39, 0x25, 0x5e, 0xd2, 0xf7, 0xd4, 0x79, 0x6a, 0x64, 0xcd, 0xc3, 0x7f, 0x1e, 0xb0, 0xe5, 0xc4, 0xc8, 0xd1, 0xd1, 0xe0, 0xf5}, -+ Expect: [32]byte{0x56, 0x3e, 0x8c, 0x9a, 0xda, 0xa7, 0xd7, 0x31, 0x1, 0xb0, 0xf2, 0xea, 0xd3, 0xca, 0xe1, 0xea, 0x5d, 0x8f, 0xcd, 0x5c, 0xd3, 0x60, 0x80, 0xbb, 0x8e, 0x6e, 0xc0, 0x3d, 0x61, 0x45, 0x9, 0x17}, -+ }, -+ { -+ In: [32]byte{0x68, 0x6f, 0x7d, 0xa9, 0x3b, 0xf2, 0x68, 0xe5, 0x88, 0x6, 0x98, 0x31, 0xf0, 0x47, 0x16, 0x3f, 0x33, 0x58, 0x99, 0x89, 0xd0, 0x82, 0x6e, 0x98, 0x8, 0xfb, 0x67, 0x8e, 0xd5, 0x7e, 0x67, 0x49}, -+ Base: [32]byte{0x8b, 0x54, 0x9b, 0x2d, 0xf6, 0x42, 0xd3, 0xb2, 0x5f, 0xe8, 0x38, 0xf, 0x8c, 0xc4, 0x37, 0x5f, 0x99, 0xb7, 0xbb, 0x4d, 0x27, 0x5f, 0x77, 0x9f, 0x3b, 0x7c, 0x81, 0xb8, 0xa2, 0xbb, 0xc1, 0x29}, -+ Expect: [32]byte{0x1, 0x47, 0x69, 0x65, 0x42, 0x6b, 0x61, 0x71, 0x74, 0x9a, 0x8a, 0xdd, 0x92, 0x35, 0x2, 0x5c, 0xe5, 0xf5, 0x57, 0xfe, 0x40, 0x9, 0xf7, 0x39, 0x30, 0x44, 0xeb, 0xbb, 0x8a, 0xe9, 0x52, 0x79}, -+ }, -+ { -+ In: [32]byte{0x82, 0xd6, 0x1c, 0xce, 0xdc, 0x80, 0x6a, 0x60, 0x60, 0xa3, 0x34, 0x9a, 0x5e, 0x87, 0xcb, 0xc7, 0xac, 0x11, 0x5e, 0x4f, 0x87, 0x77, 0x62, 0x50, 0xae, 0x25, 0x60, 0x98, 0xa7, 0xc4, 0x49, 0x59}, -+ Base: [32]byte{0x8b, 0x6b, 0x9d, 0x8, 0xf6, 0x1f, 0xc9, 0x1f, 0xe8, 0xb3, 0x29, 0x53, 0xc4, 0x23, 0x40, 0xf0, 0x7, 0xb5, 0x71, 0xdc, 0xb0, 0xa5, 0x6d, 0x10, 0x72, 0x4e, 0xce, 0xf9, 0x95, 0xc, 0xfb, 0x25}, -+ Expect: [32]byte{0x9c, 0x49, 0x94, 0x1f, 0x9c, 0x4f, 0x18, 0x71, 0xfa, 0x40, 0x91, 0xfe, 0xd7, 0x16, 0xd3, 0x49, 0x99, 0xc9, 0x52, 0x34, 0xed, 0xf2, 0xfd, 0xfb, 0xa6, 0xd1, 0x4a, 0x5a, 0xfe, 0x9e, 0x5, 0x58}, -+ }, -+ { -+ In: [32]byte{0x7d, 0xc7, 0x64, 0x4, 0x83, 0x13, 0x97, 0xd5, 0x88, 0x4f, 0xdf, 0x6f, 0x97, 0xe1, 0x74, 0x4c, 0x9e, 0xb1, 0x18, 0xa3, 0x1a, 0x7b, 0x23, 0xf8, 0xd7, 0x9f, 0x48, 0xce, 0x9c, 0xad, 0x15, 0x4b}, -+ Base: [32]byte{0x1a, 0xcd, 0x29, 0x27, 0x84, 0xf4, 0x79, 0x19, 0xd4, 0x55, 0xf8, 0x87, 0x44, 0x83, 0x58, 0x61, 0xb, 0xb9, 0x45, 0x96, 0x70, 0xeb, 0x99, 0xde, 0xe4, 0x60, 0x5, 0xf6, 0x89, 0xca, 0x5f, 0xb6}, -+ Expect: [32]byte{0x0, 0xf4, 0x3c, 0x2, 0x2e, 0x94, 0xea, 0x38, 0x19, 0xb0, 0x36, 0xae, 0x2b, 0x36, 0xb2, 0xa7, 0x61, 0x36, 0xaf, 0x62, 0x8a, 0x75, 0x1f, 0xe5, 0xd0, 0x1e, 0x3, 0xd, 0x44, 0x25, 0x88, 0x59}, -+ }, -+ { -+ In: [32]byte{0xfb, 0xc4, 0x51, 0x1d, 0x23, 0xa6, 0x82, 0xae, 0x4e, 0xfd, 0x8, 0xc8, 0x17, 0x9c, 0x1c, 0x6, 0x7f, 0x9c, 0x8b, 0xe7, 0x9b, 0xbc, 0x4e, 0xff, 0x5c, 0xe2, 0x96, 0xc6, 0xbc, 0x1f, 0xf4, 0x45}, -+ Base: [32]byte{0x55, 0xca, 0xff, 0x21, 0x81, 0xf2, 0x13, 0x6b, 0xe, 0xd0, 0xe1, 0xe2, 0x99, 0x44, 0x48, 0xe1, 0x6c, 0xc9, 0x70, 0x64, 0x6a, 0x98, 0x3d, 0x14, 0xd, 0xc4, 0xea, 0xb3, 0xd9, 0x4c, 0x28, 0x4e}, -+ Expect: [32]byte{0xae, 0x39, 0xd8, 0x16, 0x53, 0x23, 0x45, 0x79, 0x4d, 0x26, 0x91, 0xe0, 0x80, 0x1c, 0xaa, 0x52, 0x5f, 0xc3, 0x63, 0x4d, 0x40, 0x2c, 0xe9, 0x58, 0xb, 0x33, 0x38, 0xb4, 0x6f, 0x8b, 0xb9, 0x72}, -+ }, -+ { -+ In: [32]byte{0x4e, 0x6, 0xc, 0xe1, 0xc, 0xeb, 0xf0, 0x95, 0x9, 0x87, 0x16, 0xc8, 0x66, 0x19, 0xeb, 0x9f, 0x7d, 0xf6, 0x65, 0x24, 0x69, 0x8b, 0xa7, 0x98, 0x8c, 0x3b, 0x90, 0x95, 0xd9, 0xf5, 0x1, 0x34}, -+ Base: [32]byte{0x57, 0x73, 0x3f, 0x2d, 0x86, 0x96, 0x90, 0xd0, 0xd2, 0xed, 0xae, 0xc9, 0x52, 0x3d, 0xaa, 0x2d, 0xa9, 0x54, 0x45, 0xf4, 0x4f, 0x57, 0x83, 0xc1, 0xfa, 0xec, 0x6c, 0x3a, 0x98, 0x28, 0x18, 0xf3}, -+ Expect: [32]byte{0xa6, 0x1e, 0x74, 0x55, 0x2c, 0xce, 0x75, 0xf5, 0xe9, 0x72, 0xe4, 0x24, 0xf2, 0xcc, 0xb0, 0x9c, 0x83, 0xbc, 0x1b, 0x67, 0x1, 0x47, 0x48, 0xf0, 0x2c, 0x37, 0x1a, 0x20, 0x9e, 0xf2, 0xfb, 0x2c}, -+ }, -+ { -+ In: [32]byte{0x5c, 0x49, 0x2c, 0xba, 0x2c, 0xc8, 0x92, 0x48, 0x8a, 0x9c, 0xeb, 0x91, 0x86, 0xc2, 0xaa, 0xc2, 0x2f, 0x1, 0x5b, 0xf3, 0xef, 0x8d, 0x3e, 0xcc, 0x9c, 0x41, 0x76, 0x97, 0x62, 0x61, 0xaa, 0xb1}, -+ Base: [32]byte{0x67, 0x97, 0xc2, 0xe7, 0xdc, 0x92, 0xcc, 0xbe, 0x7c, 0x5, 0x6b, 0xec, 0x35, 0xa, 0xb6, 0xd3, 0xbd, 0x2a, 0x2c, 0x6b, 0xc5, 0xa8, 0x7, 0xbb, 0xca, 0xe1, 0xf6, 0xc2, 0xaf, 0x80, 0x36, 0x44}, -+ Expect: [32]byte{0xfc, 0xf3, 0x7, 0xdf, 0xbc, 0x19, 0x2, 0xb, 0x28, 0xa6, 0x61, 0x8c, 0x6c, 0x62, 0x2f, 0x31, 0x7e, 0x45, 0x96, 0x7d, 0xac, 0xf4, 0xae, 0x4a, 0xa, 0x69, 0x9a, 0x10, 0x76, 0x9f, 0xde, 0x14}, -+ }, -+ { -+ In: [32]byte{0xea, 0x33, 0x34, 0x92, 0x96, 0x5, 0x5a, 0x4e, 0x8b, 0x19, 0x2e, 0x3c, 0x23, 0xc5, 0xf4, 0xc8, 0x44, 0x28, 0x2a, 0x3b, 0xfc, 0x19, 0xec, 0xc9, 0xdc, 0x64, 0x6a, 0x42, 0xc3, 0x8d, 0xc2, 0x48}, -+ Base: [32]byte{0x2c, 0x75, 0xd8, 0x51, 0x42, 0xec, 0xad, 0x3e, 0x69, 0x44, 0x70, 0x4, 0x54, 0xc, 0x1c, 0x23, 0x54, 0x8f, 0xc8, 0xf4, 0x86, 0x25, 0x1b, 0x8a, 0x19, 0x46, 0x3f, 0x3d, 0xf6, 0xf8, 0xac, 0x61}, -+ Expect: [32]byte{0x5d, 0xca, 0xb6, 0x89, 0x73, 0xf9, 0x5b, 0xd3, 0xae, 0x4b, 0x34, 0xfa, 0xb9, 0x49, 0xfb, 0x7f, 0xb1, 0x5a, 0xf1, 0xd8, 0xca, 0xe2, 0x8c, 0xd6, 0x99, 0xf9, 0xc1, 0xaa, 0x33, 0x37, 0x34, 0x2f}, -+ }, -+ { -+ In: [32]byte{0x4f, 0x29, 0x79, 0xb1, 0xec, 0x86, 0x19, 0xe4, 0x5c, 0xa, 0xb, 0x2b, 0x52, 0x9, 0x34, 0x54, 0x1a, 0xb9, 0x44, 0x7, 0xb6, 0x4d, 0x19, 0xa, 0x76, 0xf3, 0x23, 0x14, 0xef, 0xe1, 0x84, 0xe7}, -+ Base: [32]byte{0xf7, 0xca, 0xe1, 0x8d, 0x8d, 0x36, 0xa7, 0xf5, 0x61, 0x17, 0xb8, 0xb7, 0xe, 0x25, 0x52, 0x27, 0x7f, 0xfc, 0x99, 0xdf, 0x87, 0x56, 0xb5, 0xe1, 0x38, 0xbf, 0x63, 0x68, 0xbc, 0x87, 0xf7, 0x4c}, -+ Expect: [32]byte{0xe4, 0xe6, 0x34, 0xeb, 0xb4, 0xfb, 0x66, 0x4f, 0xe8, 0xb2, 0xcf, 0xa1, 0x61, 0x5f, 0x0, 0xe6, 0x46, 0x6f, 0xff, 0x73, 0x2c, 0xe1, 0xf8, 0xa0, 0xc8, 0xd2, 0x72, 0x74, 0x31, 0xd1, 0x6f, 0x14}, -+ }, -+ { -+ In: [32]byte{0xf5, 0xd8, 0xa9, 0x27, 0x90, 0x1d, 0x4f, 0xa4, 0x24, 0x90, 0x86, 0xb7, 0xff, 0xec, 0x24, 0xf5, 0x29, 0x7d, 0x80, 0x11, 0x8e, 0x4a, 0xc9, 0xd3, 0xfc, 0x9a, 0x82, 0x37, 0x95, 0x1e, 0x3b, 0x7f}, -+ Base: [32]byte{0x3c, 0x23, 0x5e, 0xdc, 0x2, 0xf9, 0x11, 0x56, 0x41, 0xdb, 0xf5, 0x16, 0xd5, 0xde, 0x8a, 0x73, 0x5d, 0x6e, 0x53, 0xe2, 0x2a, 0xa2, 0xac, 0x14, 0x36, 0x56, 0x4, 0x5f, 0xf2, 0xe9, 0x52, 0x49}, -+ Expect: [32]byte{0xab, 0x95, 0x15, 0xab, 0x14, 0xaf, 0x9d, 0x27, 0xe, 0x1d, 0xae, 0xc, 0x56, 0x80, 0xcb, 0xc8, 0x88, 0xb, 0xd8, 0xa8, 0xe7, 0xeb, 0x67, 0xb4, 0xda, 0x42, 0xa6, 0x61, 0x96, 0x1e, 0xfc, 0xb}, -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/ed25519/ed25519.go b/ms_mod/golang.org/x/crypto/ed25519/ed25519.go -new file mode 100644 -index 00000000000000..a7828345fcc431 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ed25519/ed25519.go -@@ -0,0 +1,71 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package ed25519 implements the Ed25519 signature algorithm. See -+// https://ed25519.cr.yp.to/. -+// -+// These functions are also compatible with the β€œEd25519” function defined in -+// RFC 8032. However, unlike RFC 8032's formulation, this package's private key -+// representation includes a public key suffix to make multiple signing -+// operations with the same key more efficient. This package refers to the RFC -+// 8032 private key as the β€œseed”. -+// -+// Beginning with Go 1.13, the functionality of this package was moved to the -+// standard library as crypto/ed25519. This package only acts as a compatibility -+// wrapper. -+package ed25519 -+ -+import ( -+ "crypto/ed25519" -+ "io" -+) -+ -+const ( -+ // PublicKeySize is the size, in bytes, of public keys as used in this package. -+ PublicKeySize = 32 -+ // PrivateKeySize is the size, in bytes, of private keys as used in this package. -+ PrivateKeySize = 64 -+ // SignatureSize is the size, in bytes, of signatures generated and verified by this package. -+ SignatureSize = 64 -+ // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. -+ SeedSize = 32 -+) -+ -+// PublicKey is the type of Ed25519 public keys. -+// -+// This type is an alias for crypto/ed25519's PublicKey type. -+// See the crypto/ed25519 package for the methods on this type. -+type PublicKey = ed25519.PublicKey -+ -+// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -+// -+// This type is an alias for crypto/ed25519's PrivateKey type. -+// See the crypto/ed25519 package for the methods on this type. -+type PrivateKey = ed25519.PrivateKey -+ -+// GenerateKey generates a public/private key pair using entropy from rand. -+// If rand is nil, crypto/rand.Reader will be used. -+func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { -+ return ed25519.GenerateKey(rand) -+} -+ -+// NewKeyFromSeed calculates a private key from a seed. It will panic if -+// len(seed) is not SeedSize. This function is provided for interoperability -+// with RFC 8032. RFC 8032's private keys correspond to seeds in this -+// package. -+func NewKeyFromSeed(seed []byte) PrivateKey { -+ return ed25519.NewKeyFromSeed(seed) -+} -+ -+// Sign signs the message with privateKey and returns a signature. It will -+// panic if len(privateKey) is not PrivateKeySize. -+func Sign(privateKey PrivateKey, message []byte) []byte { -+ return ed25519.Sign(privateKey, message) -+} -+ -+// Verify reports whether sig is a valid signature of message by publicKey. It -+// will panic if len(publicKey) is not PublicKeySize. -+func Verify(publicKey PublicKey, message, sig []byte) bool { -+ return ed25519.Verify(publicKey, message, sig) -+} -diff --git a/ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go b/ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go -new file mode 100644 -index 00000000000000..ab433ba02bfb7e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ed25519/ed25519_test.go -@@ -0,0 +1,22 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ed25519_test -+ -+import ( -+ ed25519std "crypto/ed25519" -+ "testing" -+ -+ "golang.org/x/crypto/ed25519" -+) -+ -+func TestTypeAlias(t *testing.T) { -+ public, private, _ := ed25519std.GenerateKey(nil) -+ -+ message := []byte("test message") -+ sig := ed25519.Sign(private, message) -+ if !ed25519.Verify(public, message, sig) { -+ t.Errorf("valid signature rejected") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/go.mod b/ms_mod/golang.org/x/crypto/go.mod -new file mode 100644 -index 00000000000000..294c7e46f65928 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/go.mod -@@ -0,0 +1,11 @@ -+module golang.org/x/crypto -+ -+go 1.17 -+ -+require ( -+ golang.org/x/net v0.10.0 // tagx:ignore -+ golang.org/x/sys v0.11.0 -+ golang.org/x/term v0.11.0 -+) -+ -+require golang.org/x/text v0.12.0 // indirect -diff --git a/ms_mod/golang.org/x/crypto/go.sum b/ms_mod/golang.org/x/crypto/go.sum -new file mode 100644 -index 00000000000000..fb0fa61dbcf4f0 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/go.sum -@@ -0,0 +1,41 @@ -+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -+golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -+golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -diff --git a/ms_mod/golang.org/x/crypto/hkdf/example_test.go b/ms_mod/golang.org/x/crypto/hkdf/example_test.go -new file mode 100644 -index 00000000000000..e89c260e9b26e8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/hkdf/example_test.go -@@ -0,0 +1,56 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package hkdf_test -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "crypto/sha256" -+ "fmt" -+ "io" -+ -+ "golang.org/x/crypto/hkdf" -+) -+ -+// Usage example that expands one master secret into three other -+// cryptographically secure keys. -+func Example_usage() { -+ // Underlying hash function for HMAC. -+ hash := sha256.New -+ -+ // Cryptographically secure master secret. -+ secret := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this. -+ -+ // Non-secret salt, optional (can be nil). -+ // Recommended: hash-length random value. -+ salt := make([]byte, hash().Size()) -+ if _, err := rand.Read(salt); err != nil { -+ panic(err) -+ } -+ -+ // Non-secret context info, optional (can be nil). -+ info := []byte("hkdf example") -+ -+ // Generate three 128-bit derived keys. -+ hkdf := hkdf.New(hash, secret, salt, info) -+ -+ var keys [][]byte -+ for i := 0; i < 3; i++ { -+ key := make([]byte, 16) -+ if _, err := io.ReadFull(hkdf, key); err != nil { -+ panic(err) -+ } -+ keys = append(keys, key) -+ } -+ -+ for i := range keys { -+ fmt.Printf("Key #%d: %v\n", i+1, !bytes.Equal(keys[i], make([]byte, 16))) -+ } -+ -+ // Output: -+ // Key #1: true -+ // Key #2: true -+ // Key #3: true -+} -diff --git a/ms_mod/golang.org/x/crypto/hkdf/hkdf.go b/ms_mod/golang.org/x/crypto/hkdf/hkdf.go -new file mode 100644 -index 00000000000000..8700f761b3b6de ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/hkdf/hkdf.go -@@ -0,0 +1,95 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation -+// Function (HKDF) as defined in RFC 5869. -+// -+// HKDF is a cryptographic key derivation function (KDF) with the goal of -+// expanding limited input keying material into one or more cryptographically -+// strong secret keys. -+package hkdf // import "golang.org/x/crypto/hkdf" -+ -+import ( -+ "crypto/hmac" -+ "errors" -+ "fmt" -+ "hash" -+ "io" -+) -+ -+// Extract generates a pseudorandom key for use with Expand from an input secret -+// and an optional independent salt. -+// -+// Only use this function if you need to reuse the extracted key with multiple -+// Expand invocations and different context values. Most common scenarios, -+// including the generation of multiple keys, should use New instead. -+func Extract(hash func() hash.Hash, secret, salt []byte) []byte { -+ if salt == nil { -+ salt = make([]byte, hash().Size()) -+ } -+ extractor := hmac.New(hash, salt) -+ extractor.Write(secret) -+ return extractor.Sum(nil) -+} -+ -+type hkdf struct { -+ expander hash.Hash -+ size int -+ -+ info []byte -+ counter byte -+ -+ prev []byte -+ buf []byte -+} -+ -+func (f *hkdf) Read(p []byte) (int, error) { -+ // Check whether enough data can be generated -+ need := len(p) -+ remains := len(f.buf) + int(255-f.counter+1)*f.size -+ if remains < need { -+ return 0, errors.New("hkdf: entropy limit reached") -+ } -+ // Read any leftover from the buffer -+ n := copy(p, f.buf) -+ p = p[n:] -+ -+ // Fill the rest of the buffer -+ for len(p) > 0 { -+ f.expander.Reset() -+ f.expander.Write(f.prev) -+ f.expander.Write(f.info) -+ f.expander.Write([]byte{f.counter}) -+ f.prev = f.expander.Sum(f.prev[:0]) -+ f.counter++ -+ -+ // Copy the new batch into p -+ f.buf = f.prev -+ n = copy(p, f.buf) -+ p = p[n:] -+ } -+ // Save leftovers for next run -+ f.buf = f.buf[n:] -+ -+ return need, nil -+} -+ -+// Expand returns a Reader, from which keys can be read, using the given -+// pseudorandom key and optional context info, skipping the extraction step. -+// -+// The pseudorandomKey should have been generated by Extract, or be a uniformly -+// random or pseudorandom cryptographically strong key. See RFC 5869, Section -+// 3.3. Most common scenarios will want to use New instead. -+func Expand(hash func() hash.Hash, pseudorandomKey, info []byte) io.Reader { -+ expander := hmac.New(hash, pseudorandomKey) -+ return &hkdf{expander, expander.Size(), info, 1, nil, nil} -+} -+ -+// New returns a Reader, from which keys can be read, using the given hash, -+// secret, salt and context info. Salt and info can be nil. -+func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader { -+ fmt.Println("This is a not-so-subtle modification to x/crypto that you got automatically!") -+ prk := Extract(hash, secret, salt) -+ return Expand(hash, prk, info) -+} -diff --git a/ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go b/ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go -new file mode 100644 -index 00000000000000..ea575772ef2f9e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/hkdf/hkdf_test.go -@@ -0,0 +1,449 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+package hkdf -+ -+import ( -+ "bytes" -+ "crypto/md5" -+ "crypto/sha1" -+ "crypto/sha256" -+ "crypto/sha512" -+ "hash" -+ "io" -+ "testing" -+) -+ -+type hkdfTest struct { -+ hash func() hash.Hash -+ master []byte -+ salt []byte -+ prk []byte -+ info []byte -+ out []byte -+} -+ -+var hkdfTests = []hkdfTest{ -+ // Tests from RFC 5869 -+ { -+ sha256.New, -+ []byte{ -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ }, -+ []byte{ -+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, -+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, -+ }, -+ []byte{ -+ 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, -+ 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, -+ 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, -+ 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, -+ }, -+ []byte{ -+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, -+ 0xf8, 0xf9, -+ }, -+ []byte{ -+ 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, -+ 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, -+ 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, -+ 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, -+ 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, -+ 0x58, 0x65, -+ }, -+ }, -+ { -+ sha256.New, -+ []byte{ -+ 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, -+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, -+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, -+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, -+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, -+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, -+ }, -+ []byte{ -+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, -+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, -+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, -+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, -+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, -+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, -+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, -+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, -+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, -+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, -+ }, -+ []byte{ -+ 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, -+ 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, -+ 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, -+ 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44, -+ }, -+ []byte{ -+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, -+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, -+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, -+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, -+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, -+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, -+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, -+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, -+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, -+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -+ }, -+ []byte{ -+ 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, -+ 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, -+ 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, -+ 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, -+ 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, -+ 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, -+ 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, -+ 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, -+ 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, -+ 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, -+ 0x1d, 0x87, -+ }, -+ }, -+ { -+ sha256.New, -+ []byte{ -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ }, -+ []byte{}, -+ []byte{ -+ 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, -+ 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, -+ 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, -+ 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04, -+ }, -+ []byte{}, -+ []byte{ -+ 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, -+ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, -+ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, -+ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, -+ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, -+ 0x96, 0xc8, -+ }, -+ }, -+ { -+ sha256.New, -+ []byte{ -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ }, -+ nil, -+ []byte{ -+ 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, -+ 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, -+ 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, -+ 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04, -+ }, -+ nil, -+ []byte{ -+ 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, -+ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, -+ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, -+ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, -+ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, -+ 0x96, 0xc8, -+ }, -+ }, -+ { -+ sha1.New, -+ []byte{ -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, -+ }, -+ []byte{ -+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, -+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, -+ }, -+ []byte{ -+ 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, -+ 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, -+ 0xaa, 0x2b, 0xa2, 0x43, -+ }, -+ []byte{ -+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, -+ 0xf8, 0xf9, -+ }, -+ []byte{ -+ 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, -+ 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, -+ 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, -+ 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, -+ 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, -+ 0xf8, 0x96, -+ }, -+ }, -+ { -+ sha1.New, -+ []byte{ -+ 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, -+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, -+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, -+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, -+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, -+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, -+ }, -+ []byte{ -+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, -+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, -+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, -+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, -+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, -+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, -+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, -+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, -+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, -+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, -+ }, -+ []byte{ -+ 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, -+ 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, -+ 0x22, 0x4c, 0xfa, 0xf6, -+ }, -+ []byte{ -+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, -+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, -+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, -+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, -+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, -+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, -+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, -+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, -+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, -+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -+ }, -+ []byte{ -+ 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, -+ 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, -+ 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, -+ 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, -+ 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, -+ 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, -+ 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, -+ 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, -+ 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, -+ 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, -+ 0xd3, 0xb4, -+ }, -+ }, -+ { -+ sha1.New, -+ []byte{ -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ }, -+ []byte{}, -+ []byte{ -+ 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, -+ 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, -+ 0xa0, 0xd3, 0x2d, 0x01, -+ }, -+ []byte{}, -+ []byte{ -+ 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, -+ 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, -+ 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, -+ 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, -+ 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, -+ 0x49, 0x18, -+ }, -+ }, -+ { -+ sha1.New, -+ []byte{ -+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, -+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, -+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, -+ }, -+ nil, -+ []byte{ -+ 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, -+ 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, -+ 0x73, 0x13, 0x85, 0xdd, -+ }, -+ nil, -+ []byte{ -+ 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, -+ 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, -+ 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, -+ 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, -+ 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, -+ 0xfc, 0x48, -+ }, -+ }, -+} -+ -+func TestHKDF(t *testing.T) { -+ for i, tt := range hkdfTests { -+ prk := Extract(tt.hash, tt.master, tt.salt) -+ if !bytes.Equal(prk, tt.prk) { -+ t.Errorf("test %d: incorrect PRK: have %v, need %v.", i, prk, tt.prk) -+ } -+ -+ hkdf := New(tt.hash, tt.master, tt.salt, tt.info) -+ out := make([]byte, len(tt.out)) -+ -+ n, err := io.ReadFull(hkdf, out) -+ if n != len(tt.out) || err != nil { -+ t.Errorf("test %d: not enough output bytes: %d.", i, n) -+ } -+ -+ if !bytes.Equal(out, tt.out) { -+ t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) -+ } -+ -+ hkdf = Expand(tt.hash, prk, tt.info) -+ -+ n, err = io.ReadFull(hkdf, out) -+ if n != len(tt.out) || err != nil { -+ t.Errorf("test %d: not enough output bytes from Expand: %d.", i, n) -+ } -+ -+ if !bytes.Equal(out, tt.out) { -+ t.Errorf("test %d: incorrect output from Expand: have %v, need %v.", i, out, tt.out) -+ } -+ } -+} -+ -+func TestHKDFMultiRead(t *testing.T) { -+ for i, tt := range hkdfTests { -+ hkdf := New(tt.hash, tt.master, tt.salt, tt.info) -+ out := make([]byte, len(tt.out)) -+ -+ for b := 0; b < len(tt.out); b++ { -+ n, err := io.ReadFull(hkdf, out[b:b+1]) -+ if n != 1 || err != nil { -+ t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out)) -+ } -+ } -+ -+ if !bytes.Equal(out, tt.out) { -+ t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) -+ } -+ } -+} -+ -+func TestHKDFLimit(t *testing.T) { -+ hash := sha1.New -+ master := []byte{0x00, 0x01, 0x02, 0x03} -+ info := []byte{} -+ -+ hkdf := New(hash, master, nil, info) -+ limit := hash().Size() * 255 -+ out := make([]byte, limit) -+ -+ // The maximum output bytes should be extractable -+ n, err := io.ReadFull(hkdf, out) -+ if n != limit || err != nil { -+ t.Errorf("not enough output bytes: %d, %v.", n, err) -+ } -+ -+ // Reading one more should fail -+ n, err = io.ReadFull(hkdf, make([]byte, 1)) -+ if n > 0 || err == nil { -+ t.Errorf("key expansion overflowed: n = %d, err = %v", n, err) -+ } -+} -+ -+func Benchmark16ByteMD5Single(b *testing.B) { -+ benchmarkHKDFSingle(md5.New, 16, b) -+} -+ -+func Benchmark20ByteSHA1Single(b *testing.B) { -+ benchmarkHKDFSingle(sha1.New, 20, b) -+} -+ -+func Benchmark32ByteSHA256Single(b *testing.B) { -+ benchmarkHKDFSingle(sha256.New, 32, b) -+} -+ -+func Benchmark64ByteSHA512Single(b *testing.B) { -+ benchmarkHKDFSingle(sha512.New, 64, b) -+} -+ -+func Benchmark8ByteMD5Stream(b *testing.B) { -+ benchmarkHKDFStream(md5.New, 8, b) -+} -+ -+func Benchmark16ByteMD5Stream(b *testing.B) { -+ benchmarkHKDFStream(md5.New, 16, b) -+} -+ -+func Benchmark8ByteSHA1Stream(b *testing.B) { -+ benchmarkHKDFStream(sha1.New, 8, b) -+} -+ -+func Benchmark20ByteSHA1Stream(b *testing.B) { -+ benchmarkHKDFStream(sha1.New, 20, b) -+} -+ -+func Benchmark8ByteSHA256Stream(b *testing.B) { -+ benchmarkHKDFStream(sha256.New, 8, b) -+} -+ -+func Benchmark32ByteSHA256Stream(b *testing.B) { -+ benchmarkHKDFStream(sha256.New, 32, b) -+} -+ -+func Benchmark8ByteSHA512Stream(b *testing.B) { -+ benchmarkHKDFStream(sha512.New, 8, b) -+} -+ -+func Benchmark64ByteSHA512Stream(b *testing.B) { -+ benchmarkHKDFStream(sha512.New, 64, b) -+} -+ -+func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) { -+ master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} -+ salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} -+ info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} -+ out := make([]byte, block) -+ -+ b.SetBytes(int64(block)) -+ b.ResetTimer() -+ -+ for i := 0; i < b.N; i++ { -+ hkdf := New(hasher, master, salt, info) -+ io.ReadFull(hkdf, out) -+ } -+} -+ -+func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) { -+ master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} -+ salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} -+ info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} -+ out := make([]byte, block) -+ -+ b.SetBytes(int64(block)) -+ b.ResetTimer() -+ -+ hkdf := New(hasher, master, salt, info) -+ for i := 0; i < b.N; i++ { -+ _, err := io.ReadFull(hkdf, out) -+ if err != nil { -+ hkdf = New(hasher, master, salt, info) -+ i-- -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/alias/alias.go b/ms_mod/golang.org/x/crypto/internal/alias/alias.go -new file mode 100644 -index 00000000000000..69c17f822b9a13 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/alias/alias.go -@@ -0,0 +1,32 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !purego -+// +build !purego -+ -+// Package alias implements memory aliasing tests. -+package alias -+ -+import "unsafe" -+ -+// AnyOverlap reports whether x and y share memory at any (not necessarily -+// corresponding) index. The memory beyond the slice length is ignored. -+func AnyOverlap(x, y []byte) bool { -+ return len(x) > 0 && len(y) > 0 && -+ uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && -+ uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) -+} -+ -+// InexactOverlap reports whether x and y share memory at any non-corresponding -+// index. The memory beyond the slice length is ignored. Note that x and y can -+// have different lengths and still not have any inexact overlap. -+// -+// InexactOverlap can be used to implement the requirements of the crypto/cipher -+// AEAD, Block, BlockMode and Stream interfaces. -+func InexactOverlap(x, y []byte) bool { -+ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { -+ return false -+ } -+ return AnyOverlap(x, y) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go b/ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go -new file mode 100644 -index 00000000000000..4775b0a4384370 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/alias/alias_purego.go -@@ -0,0 +1,35 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build purego -+// +build purego -+ -+// Package alias implements memory aliasing tests. -+package alias -+ -+// This is the Google App Engine standard variant based on reflect -+// because the unsafe package and cgo are disallowed. -+ -+import "reflect" -+ -+// AnyOverlap reports whether x and y share memory at any (not necessarily -+// corresponding) index. The memory beyond the slice length is ignored. -+func AnyOverlap(x, y []byte) bool { -+ return len(x) > 0 && len(y) > 0 && -+ reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && -+ reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() -+} -+ -+// InexactOverlap reports whether x and y share memory at any non-corresponding -+// index. The memory beyond the slice length is ignored. Note that x and y can -+// have different lengths and still not have any inexact overlap. -+// -+// InexactOverlap can be used to implement the requirements of the crypto/cipher -+// AEAD, Block, BlockMode and Stream interfaces. -+func InexactOverlap(x, y []byte) bool { -+ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { -+ return false -+ } -+ return AnyOverlap(x, y) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/alias/alias_test.go b/ms_mod/golang.org/x/crypto/internal/alias/alias_test.go -new file mode 100644 -index 00000000000000..a68fb33667bf63 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/alias/alias_test.go -@@ -0,0 +1,46 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package alias -+ -+import "testing" -+ -+var a, b [100]byte -+ -+var aliasingTests = []struct { -+ x, y []byte -+ anyOverlap, inexactOverlap bool -+}{ -+ {a[:], b[:], false, false}, -+ {a[:], b[:0], false, false}, -+ {a[:], b[:50], false, false}, -+ {a[40:50], a[50:60], false, false}, -+ {a[40:50], a[60:70], false, false}, -+ {a[:51], a[50:], true, true}, -+ {a[:], a[:], true, false}, -+ {a[:50], a[:60], true, false}, -+ {a[:], nil, false, false}, -+ {nil, nil, false, false}, -+ {a[:], a[:0], false, false}, -+ {a[:10], a[:10:20], true, false}, -+ {a[:10], a[5:10:20], true, true}, -+} -+ -+func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { -+ any := AnyOverlap(x, y) -+ if any != anyOverlap { -+ t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) -+ } -+ inexact := InexactOverlap(x, y) -+ if inexact != inexactOverlap { -+ t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) -+ } -+} -+ -+func TestAliasing(t *testing.T) { -+ for i, tt := range aliasingTests { -+ testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) -+ testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go b/ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go -new file mode 100644 -index 00000000000000..59e844db05980a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/backend/boring_linux.go -@@ -0,0 +1,95 @@ -+// Generated code. DO NOT EDIT. -+ -+// This file implements a proxy that links into a specific crypto backend. -+ -+//go:build goexperiment.boringcrypto && linux && cgo && (amd64 || arm64) && !android && !msan -+ -+// The following functions defined in the API are not implemented by the backend and panic instead: -+// -+// NewSHA3_224 -+// NewSHA3_256 -+// NewSHA3_384 -+// NewSHA3_512 -+// SHA3_224 -+// SHA3_256 -+// SHA3_384 -+// SHA3_512 -+// SupportsHash -+ -+package backend -+ -+import ( -+ "crypto" -+ _ "unsafe" -+ "io" -+ "hash" -+ "crypto/cipher" -+) -+ -+const Enabled = true -+//go:linkname NewSHA1 crypto/internal/backend.NewSHA1 -+func NewSHA1() hash.Hash -+//go:linkname NewSHA224 crypto/internal/backend.NewSHA224 -+func NewSHA224() hash.Hash -+//go:linkname NewSHA256 crypto/internal/backend.NewSHA256 -+func NewSHA256() hash.Hash -+//go:linkname NewSHA384 crypto/internal/backend.NewSHA384 -+func NewSHA384() hash.Hash -+//go:linkname NewSHA512 crypto/internal/backend.NewSHA512 -+func NewSHA512() hash.Hash -+// Not implemented by this backend. -+func NewSHA3_224() hash.Hash { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func NewSHA3_256() hash.Hash { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func NewSHA3_384() hash.Hash { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func NewSHA3_512() hash.Hash { -+ panic("not implemented by this backend") -+} -+//go:linkname SHA1 crypto/internal/backend.SHA1 -+func SHA1(p []byte) (sum [20]byte) -+//go:linkname SHA224 crypto/internal/backend.SHA224 -+func SHA224(p []byte) (sum [28]byte) -+//go:linkname SHA256 crypto/internal/backend.SHA256 -+func SHA256(p []byte) (sum [32]byte) -+//go:linkname SHA384 crypto/internal/backend.SHA384 -+func SHA384(p []byte) (sum [48]byte) -+//go:linkname SHA512 crypto/internal/backend.SHA512 -+func SHA512(p []byte) (sum [64]byte) -+// Not implemented by this backend. -+func SHA3_224(p []byte) (sum [28]byte) { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func SHA3_256(p []byte) (sum [32]byte) { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func SHA3_384(p []byte) (sum [48]byte) { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func SHA3_512(p []byte) (sum [64]byte) { -+ panic("not implemented by this backend") -+} -+// Not implemented by this backend. -+func SupportsHash(h crypto.Hash) bool { -+ panic("not implemented by this backend") -+} -+//go:linkname NewHMAC crypto/internal/backend.NewHMAC -+func NewHMAC(h func() hash.Hash, key []byte) hash.Hash -+//go:linkname NewAESCipher crypto/internal/backend.NewAESCipher -+func NewAESCipher(key []byte) (cipher.Block, error) -+//go:linkname NewGCMTLS crypto/internal/backend.NewGCMTLS -+func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) -+//go:linkname ExpandHKDF crypto/internal/backend.ExpandHKDF -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) -+//go:linkname ExtractHKDF crypto/internal/backend.ExtractHKDF -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) -diff --git a/ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go b/ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go -new file mode 100644 -index 00000000000000..a6571800fedb34 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/backend/cng_windows.go -@@ -0,0 +1,77 @@ -+// Generated code. DO NOT EDIT. -+ -+// This file implements a proxy that links into a specific crypto backend. -+ -+//go:build goexperiment.cngcrypto && windows -+ -+// The following functions defined in the API are not implemented by the backend and panic instead: -+// -+// NewSHA3_224 -+// SHA3_224 -+ -+package backend -+ -+import ( -+ "crypto" -+ _ "unsafe" -+ "io" -+ "hash" -+ "crypto/cipher" -+) -+ -+const Enabled = true -+//go:linkname NewSHA1 crypto/internal/backend.NewSHA1 -+func NewSHA1() hash.Hash -+//go:linkname NewSHA224 crypto/internal/backend.NewSHA224 -+func NewSHA224() hash.Hash -+//go:linkname NewSHA256 crypto/internal/backend.NewSHA256 -+func NewSHA256() hash.Hash -+//go:linkname NewSHA384 crypto/internal/backend.NewSHA384 -+func NewSHA384() hash.Hash -+//go:linkname NewSHA512 crypto/internal/backend.NewSHA512 -+func NewSHA512() hash.Hash -+// Not implemented by this backend. -+func NewSHA3_224() hash.Hash { -+ panic("not implemented by this backend") -+} -+//go:linkname NewSHA3_256 crypto/internal/backend.NewSHA3_256 -+func NewSHA3_256() hash.Hash -+//go:linkname NewSHA3_384 crypto/internal/backend.NewSHA3_384 -+func NewSHA3_384() hash.Hash -+//go:linkname NewSHA3_512 crypto/internal/backend.NewSHA3_512 -+func NewSHA3_512() hash.Hash -+//go:linkname SHA1 crypto/internal/backend.SHA1 -+func SHA1(p []byte) (sum [20]byte) -+//go:linkname SHA224 crypto/internal/backend.SHA224 -+func SHA224(p []byte) (sum [28]byte) -+//go:linkname SHA256 crypto/internal/backend.SHA256 -+func SHA256(p []byte) (sum [32]byte) -+//go:linkname SHA384 crypto/internal/backend.SHA384 -+func SHA384(p []byte) (sum [48]byte) -+//go:linkname SHA512 crypto/internal/backend.SHA512 -+func SHA512(p []byte) (sum [64]byte) -+// Not implemented by this backend. -+func SHA3_224(p []byte) (sum [28]byte) { -+ panic("not implemented by this backend") -+} -+//go:linkname SHA3_256 crypto/internal/backend.SHA3_256 -+//go:noescape -+func SHA3_256(p []byte) (sum [32]byte) -+//go:linkname SHA3_384 crypto/internal/backend.SHA3_384 -+//go:noescape -+func SHA3_384(p []byte) (sum [48]byte) -+//go:linkname SHA3_512 crypto/internal/backend.SHA3_512 -+//go:noescape -+func SHA3_512(p []byte) (sum [64]byte) -+//go:linkname SupportsHash crypto/internal/backend.SupportsHash -+func SupportsHash(h crypto.Hash) bool -+//go:linkname NewHMAC crypto/internal/backend.NewHMAC -+func NewHMAC(h func() hash.Hash, key []byte) hash.Hash -+//go:linkname NewAESCipher crypto/internal/backend.NewAESCipher -+func NewAESCipher(key []byte) (cipher.Block, error) -+//go:linkname NewGCMTLS crypto/internal/backend.NewGCMTLS -+func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) -+//go:linkname ExpandHKDF crypto/internal/backend.ExpandHKDF -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) -+//go:linkname ExtractHKDF crypto/internal/backend.ExtractHKDF -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) -diff --git a/ms_mod/golang.org/x/crypto/internal/backend/nobackend.go b/ms_mod/golang.org/x/crypto/internal/backend/nobackend.go -new file mode 100644 -index 00000000000000..9089be8591e208 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/backend/nobackend.go -@@ -0,0 +1,49 @@ -+// Generated code. DO NOT EDIT. -+ -+//go:build !(goexperiment.boringcrypto && linux && cgo && (amd64 || arm64) && !android && !msan) && !(goexperiment.cngcrypto && windows) && !(goexperiment.opensslcrypto && linux && cgo) -+ -+package backend -+ -+import ( -+ "crypto" -+ "crypto/cipher" -+ "hash" -+ "io" -+) -+ -+const Enabled = false -+ -+func NewSHA1() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA224() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA256() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA384() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA512() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA3_224() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA3_256() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA3_384() hash.Hash { panic("cryptobackend: not available") } -+func NewSHA3_512() hash.Hash { panic("cryptobackend: not available") } -+ -+func SHA1(p []byte) (sum [20]byte) { panic("cryptobackend: not available") } -+func SHA224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } -+func SHA256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } -+func SHA384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } -+func SHA512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } -+func SHA3_224(p []byte) (sum [28]byte) { panic("cryptobackend: not available") } -+func SHA3_256(p []byte) (sum [32]byte) { panic("cryptobackend: not available") } -+func SHA3_384(p []byte) (sum [48]byte) { panic("cryptobackend: not available") } -+func SHA3_512(p []byte) (sum [64]byte) { panic("cryptobackend: not available") } -+ -+func SupportsHash(h crypto.Hash) bool { panic("cryptobackend: not available") } -+ -+func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("cryptobackend: not available") } -+ -+func NewAESCipher(key []byte) (cipher.Block, error) { panic("cryptobackend: not available") } -+func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { panic("cryptobackend: not available") } -+ -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) { -+ panic("cryptobackend: not available") -+} -+ -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) { -+ panic("cryptobackend: not available") -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go b/ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go -new file mode 100644 -index 00000000000000..01d442dcac4910 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/backend/openssl_linux.go -@@ -0,0 +1,69 @@ -+// Generated code. DO NOT EDIT. -+ -+// This file implements a proxy that links into a specific crypto backend. -+ -+//go:build goexperiment.opensslcrypto && linux && cgo -+ -+package backend -+ -+import ( -+ "crypto" -+ _ "unsafe" -+ "io" -+ "hash" -+ "crypto/cipher" -+) -+ -+const Enabled = true -+//go:linkname NewSHA1 crypto/internal/backend.NewSHA1 -+func NewSHA1() hash.Hash -+//go:linkname NewSHA224 crypto/internal/backend.NewSHA224 -+func NewSHA224() hash.Hash -+//go:linkname NewSHA256 crypto/internal/backend.NewSHA256 -+func NewSHA256() hash.Hash -+//go:linkname NewSHA384 crypto/internal/backend.NewSHA384 -+func NewSHA384() hash.Hash -+//go:linkname NewSHA512 crypto/internal/backend.NewSHA512 -+func NewSHA512() hash.Hash -+//go:linkname NewSHA3_224 crypto/internal/backend.NewSHA3_224 -+func NewSHA3_224() hash.Hash -+//go:linkname NewSHA3_256 crypto/internal/backend.NewSHA3_256 -+func NewSHA3_256() hash.Hash -+//go:linkname NewSHA3_384 crypto/internal/backend.NewSHA3_384 -+func NewSHA3_384() hash.Hash -+//go:linkname NewSHA3_512 crypto/internal/backend.NewSHA3_512 -+func NewSHA3_512() hash.Hash -+//go:linkname SHA1 crypto/internal/backend.SHA1 -+func SHA1(p []byte) (sum [20]byte) -+//go:linkname SHA224 crypto/internal/backend.SHA224 -+func SHA224(p []byte) (sum [28]byte) -+//go:linkname SHA256 crypto/internal/backend.SHA256 -+func SHA256(p []byte) (sum [32]byte) -+//go:linkname SHA384 crypto/internal/backend.SHA384 -+func SHA384(p []byte) (sum [48]byte) -+//go:linkname SHA512 crypto/internal/backend.SHA512 -+func SHA512(p []byte) (sum [64]byte) -+//go:linkname SHA3_224 crypto/internal/backend.SHA3_224 -+//go:noescape -+func SHA3_224(p []byte) (sum [28]byte) -+//go:linkname SHA3_256 crypto/internal/backend.SHA3_256 -+//go:noescape -+func SHA3_256(p []byte) (sum [32]byte) -+//go:linkname SHA3_384 crypto/internal/backend.SHA3_384 -+//go:noescape -+func SHA3_384(p []byte) (sum [48]byte) -+//go:linkname SHA3_512 crypto/internal/backend.SHA3_512 -+//go:noescape -+func SHA3_512(p []byte) (sum [64]byte) -+//go:linkname SupportsHash crypto/internal/backend.SupportsHash -+func SupportsHash(h crypto.Hash) bool -+//go:linkname NewHMAC crypto/internal/backend.NewHMAC -+func NewHMAC(h func() hash.Hash, key []byte) hash.Hash -+//go:linkname NewAESCipher crypto/internal/backend.NewAESCipher -+func NewAESCipher(key []byte) (cipher.Block, error) -+//go:linkname NewGCMTLS crypto/internal/backend.NewGCMTLS -+func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) -+//go:linkname ExpandHKDF crypto/internal/backend.ExpandHKDF -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) -+//go:linkname ExtractHKDF crypto/internal/backend.ExtractHKDF -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go -new file mode 100644 -index 00000000000000..45b5c966b2be38 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_compat.go -@@ -0,0 +1,40 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !go1.13 -+// +build !go1.13 -+ -+package poly1305 -+ -+// Generic fallbacks for the math/bits intrinsics, copied from -+// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had -+// variable time fallbacks until Go 1.13. -+ -+func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) { -+ sum = x + y + carry -+ carryOut = ((x & y) | ((x | y) &^ sum)) >> 63 -+ return -+} -+ -+func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) { -+ diff = x - y - borrow -+ borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63 -+ return -+} -+ -+func bitsMul64(x, y uint64) (hi, lo uint64) { -+ const mask32 = 1<<32 - 1 -+ x0 := x & mask32 -+ x1 := x >> 32 -+ y0 := y & mask32 -+ y1 := y >> 32 -+ w0 := x0 * y0 -+ t := x1*y0 + w0>>32 -+ w1 := t & mask32 -+ w2 := t >> 32 -+ w1 += x0 * y1 -+ hi = x1*y1 + w2 + w1>>32 -+ lo = x * y -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go -new file mode 100644 -index 00000000000000..ed52b3418ab537 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/bits_go1.13.go -@@ -0,0 +1,22 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.13 -+// +build go1.13 -+ -+package poly1305 -+ -+import "math/bits" -+ -+func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) { -+ return bits.Add64(x, y, carry) -+} -+ -+func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) { -+ return bits.Sub64(x, y, borrow) -+} -+ -+func bitsMul64(x, y uint64) (hi, lo uint64) { -+ return bits.Mul64(x, y) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go -new file mode 100644 -index 00000000000000..f184b67d98db29 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/mac_noasm.go -@@ -0,0 +1,10 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego -+// +build !amd64,!ppc64le,!s390x !gc purego -+ -+package poly1305 -+ -+type mac struct{ macGeneric } -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go -new file mode 100644 -index 00000000000000..4aaea810a26823 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305.go -@@ -0,0 +1,99 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package poly1305 implements Poly1305 one-time message authentication code as -+// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. -+// -+// Poly1305 is a fast, one-time authentication function. It is infeasible for an -+// attacker to generate an authenticator for a message without the key. However, a -+// key must only be used for a single message. Authenticating two different -+// messages with the same key allows an attacker to forge authenticators for other -+// messages with the same key. -+// -+// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was -+// used with a fixed key in order to generate one-time keys from an nonce. -+// However, in this package AES isn't used and the one-time key is specified -+// directly. -+package poly1305 -+ -+import "crypto/subtle" -+ -+// TagSize is the size, in bytes, of a poly1305 authenticator. -+const TagSize = 16 -+ -+// Sum generates an authenticator for msg using a one-time key and puts the -+// 16-byte result into out. Authenticating two different messages with the same -+// key allows an attacker to forge messages at will. -+func Sum(out *[16]byte, m []byte, key *[32]byte) { -+ h := New(key) -+ h.Write(m) -+ h.Sum(out[:0]) -+} -+ -+// Verify returns true if mac is a valid authenticator for m with the given key. -+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { -+ var tmp [16]byte -+ Sum(&tmp, m, key) -+ return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 -+} -+ -+// New returns a new MAC computing an authentication -+// tag of all data written to it with the given key. -+// This allows writing the message progressively instead -+// of passing it as a single slice. Common users should use -+// the Sum function instead. -+// -+// The key must be unique for each message, as authenticating -+// two different messages with the same key allows an attacker -+// to forge messages at will. -+func New(key *[32]byte) *MAC { -+ m := &MAC{} -+ initialize(key, &m.macState) -+ return m -+} -+ -+// MAC is an io.Writer computing an authentication tag -+// of the data written to it. -+// -+// MAC cannot be used like common hash.Hash implementations, -+// because using a poly1305 key twice breaks its security. -+// Therefore writing data to a running MAC after calling -+// Sum or Verify causes it to panic. -+type MAC struct { -+ mac // platform-dependent implementation -+ -+ finalized bool -+} -+ -+// Size returns the number of bytes Sum will return. -+func (h *MAC) Size() int { return TagSize } -+ -+// Write adds more data to the running message authentication code. -+// It never returns an error. -+// -+// It must not be called after the first call of Sum or Verify. -+func (h *MAC) Write(p []byte) (n int, err error) { -+ if h.finalized { -+ panic("poly1305: write to MAC after Sum or Verify") -+ } -+ return h.mac.Write(p) -+} -+ -+// Sum computes the authenticator of all data written to the -+// message authentication code. -+func (h *MAC) Sum(b []byte) []byte { -+ var mac [TagSize]byte -+ h.mac.Sum(&mac) -+ h.finalized = true -+ return append(b, mac[:]...) -+} -+ -+// Verify returns whether the authenticator of all data written to -+// the message authentication code matches the expected value. -+func (h *MAC) Verify(expected []byte) bool { -+ var mac [TagSize]byte -+ h.mac.Sum(&mac) -+ h.finalized = true -+ return subtle.ConstantTimeCompare(expected, mac[:]) == 1 -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go -new file mode 100644 -index 00000000000000..e7ec6d19dd2e3d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/poly1305_test.go -@@ -0,0 +1,276 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package poly1305 -+ -+import ( -+ "crypto/rand" -+ "encoding/binary" -+ "encoding/hex" -+ "flag" -+ "testing" -+ "unsafe" -+) -+ -+var stressFlag = flag.Bool("stress", false, "run slow stress tests") -+ -+type test struct { -+ in string -+ key string -+ tag string -+ state string -+} -+ -+func (t *test) Input() []byte { -+ in, err := hex.DecodeString(t.in) -+ if err != nil { -+ panic(err) -+ } -+ return in -+} -+ -+func (t *test) Key() [32]byte { -+ buf, err := hex.DecodeString(t.key) -+ if err != nil { -+ panic(err) -+ } -+ var key [32]byte -+ copy(key[:], buf[:32]) -+ return key -+} -+ -+func (t *test) Tag() [16]byte { -+ buf, err := hex.DecodeString(t.tag) -+ if err != nil { -+ panic(err) -+ } -+ var tag [16]byte -+ copy(tag[:], buf[:16]) -+ return tag -+} -+ -+func (t *test) InitialState() [3]uint64 { -+ // state is hex encoded in big-endian byte order -+ if t.state == "" { -+ return [3]uint64{0, 0, 0} -+ } -+ buf, err := hex.DecodeString(t.state) -+ if err != nil { -+ panic(err) -+ } -+ if len(buf) != 3*8 { -+ panic("incorrect state length") -+ } -+ return [3]uint64{ -+ binary.BigEndian.Uint64(buf[16:24]), -+ binary.BigEndian.Uint64(buf[8:16]), -+ binary.BigEndian.Uint64(buf[0:8]), -+ } -+} -+ -+func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) { -+ var tag [16]byte -+ for i, v := range testData { -+ // cannot set initial state before calling sum, so skip those tests -+ if v.InitialState() != [3]uint64{0, 0, 0} { -+ continue -+ } -+ -+ in := v.Input() -+ if unaligned { -+ in = unalignBytes(in) -+ } -+ key := v.Key() -+ sumImpl(&tag, in, &key) -+ if tag != v.Tag() { -+ t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:]) -+ } -+ if !Verify(&tag, in, &key) { -+ t.Errorf("%d: tag didn't verify", i) -+ } -+ // If the key is zero, the tag will always be zero, independent of the input. -+ if len(in) > 0 && key != [32]byte{} { -+ in[0] ^= 0xff -+ if Verify(&tag, in, &key) { -+ t.Errorf("%d: tag verified after altering the input", i) -+ } -+ in[0] ^= 0xff -+ } -+ // If the input is empty, the tag only depends on the second half of the key. -+ if len(in) > 0 { -+ key[0] ^= 0xff -+ if Verify(&tag, in, &key) { -+ t.Errorf("%d: tag verified after altering the key", i) -+ } -+ key[0] ^= 0xff -+ } -+ tag[0] ^= 0xff -+ if Verify(&tag, in, &key) { -+ t.Errorf("%d: tag verified after altering the tag", i) -+ } -+ tag[0] ^= 0xff -+ } -+} -+ -+func TestBurnin(t *testing.T) { -+ // This test can be used to sanity-check significant changes. It can -+ // take about many minutes to run, even on fast machines. It's disabled -+ // by default. -+ if !*stressFlag { -+ t.Skip("skipping without -stress") -+ } -+ -+ var key [32]byte -+ var input [25]byte -+ var output [16]byte -+ -+ for i := range key { -+ key[i] = 1 -+ } -+ for i := range input { -+ input[i] = 2 -+ } -+ -+ for i := uint64(0); i < 1e10; i++ { -+ Sum(&output, input[:], &key) -+ copy(key[0:], output[:]) -+ copy(key[16:], output[:]) -+ copy(input[:], output[:]) -+ copy(input[16:], output[:]) -+ } -+ -+ const expected = "5e3b866aea0b636d240c83c428f84bfa" -+ if got := hex.EncodeToString(output[:]); got != expected { -+ t.Errorf("expected %s, got %s", expected, got) -+ } -+} -+ -+func TestSum(t *testing.T) { testSum(t, false, Sum) } -+func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) } -+func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) } -+func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) } -+ -+func TestWriteGeneric(t *testing.T) { testWriteGeneric(t, false) } -+func TestWriteGenericUnaligned(t *testing.T) { testWriteGeneric(t, true) } -+func TestWrite(t *testing.T) { testWrite(t, false) } -+func TestWriteUnaligned(t *testing.T) { testWrite(t, true) } -+ -+func testWriteGeneric(t *testing.T, unaligned bool) { -+ for i, v := range testData { -+ key := v.Key() -+ input := v.Input() -+ var out [16]byte -+ -+ if unaligned { -+ input = unalignBytes(input) -+ } -+ h := newMACGeneric(&key) -+ if s := v.InitialState(); s != [3]uint64{0, 0, 0} { -+ h.macState.h = s -+ } -+ n, err := h.Write(input[:len(input)/3]) -+ if err != nil || n != len(input[:len(input)/3]) { -+ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) -+ } -+ n, err = h.Write(input[len(input)/3:]) -+ if err != nil || n != len(input[len(input)/3:]) { -+ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) -+ } -+ h.Sum(&out) -+ if tag := v.Tag(); out != tag { -+ t.Errorf("%d: expected %x, got %x", i, tag[:], out[:]) -+ } -+ } -+} -+ -+func testWrite(t *testing.T, unaligned bool) { -+ for i, v := range testData { -+ key := v.Key() -+ input := v.Input() -+ var out [16]byte -+ -+ if unaligned { -+ input = unalignBytes(input) -+ } -+ h := New(&key) -+ if s := v.InitialState(); s != [3]uint64{0, 0, 0} { -+ h.macState.h = s -+ } -+ n, err := h.Write(input[:len(input)/3]) -+ if err != nil || n != len(input[:len(input)/3]) { -+ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) -+ } -+ n, err = h.Write(input[len(input)/3:]) -+ if err != nil || n != len(input[len(input)/3:]) { -+ t.Errorf("#%d: unexpected Write results: n = %d, err = %v", i, n, err) -+ } -+ h.Sum(out[:0]) -+ tag := v.Tag() -+ if out != tag { -+ t.Errorf("%d: expected %x, got %x", i, tag[:], out[:]) -+ } -+ if !h.Verify(tag[:]) { -+ t.Errorf("%d: Verify failed", i) -+ } -+ tag[0] ^= 0xff -+ if h.Verify(tag[:]) { -+ t.Errorf("%d: Verify succeeded after modifying the tag", i) -+ } -+ } -+} -+ -+func benchmarkSum(b *testing.B, size int, unaligned bool) { -+ var out [16]byte -+ var key [32]byte -+ in := make([]byte, size) -+ if unaligned { -+ in = unalignBytes(in) -+ } -+ rand.Read(in) -+ b.SetBytes(int64(len(in))) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ Sum(&out, in, &key) -+ } -+} -+ -+func benchmarkWrite(b *testing.B, size int, unaligned bool) { -+ var key [32]byte -+ h := New(&key) -+ in := make([]byte, size) -+ if unaligned { -+ in = unalignBytes(in) -+ } -+ rand.Read(in) -+ b.SetBytes(int64(len(in))) -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ h.Write(in) -+ } -+} -+ -+func Benchmark64(b *testing.B) { benchmarkSum(b, 64, false) } -+func Benchmark1K(b *testing.B) { benchmarkSum(b, 1024, false) } -+func Benchmark2M(b *testing.B) { benchmarkSum(b, 2*1024*1024, false) } -+func Benchmark64Unaligned(b *testing.B) { benchmarkSum(b, 64, true) } -+func Benchmark1KUnaligned(b *testing.B) { benchmarkSum(b, 1024, true) } -+func Benchmark2MUnaligned(b *testing.B) { benchmarkSum(b, 2*1024*1024, true) } -+ -+func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64, false) } -+func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024, false) } -+func BenchmarkWrite2M(b *testing.B) { benchmarkWrite(b, 2*1024*1024, false) } -+func BenchmarkWrite64Unaligned(b *testing.B) { benchmarkWrite(b, 64, true) } -+func BenchmarkWrite1KUnaligned(b *testing.B) { benchmarkWrite(b, 1024, true) } -+func BenchmarkWrite2MUnaligned(b *testing.B) { benchmarkWrite(b, 2*1024*1024, true) } -+ -+func unalignBytes(in []byte) []byte { -+ out := make([]byte, len(in)+1) -+ if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { -+ out = out[1:] -+ } else { -+ out = out[:len(in)] -+ } -+ copy(out, in) -+ return out -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go -new file mode 100644 -index 00000000000000..6d522333f29e86 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.go -@@ -0,0 +1,48 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package poly1305 -+ -+//go:noescape -+func update(state *macState, msg []byte) -+ -+// mac is a wrapper for macGeneric that redirects calls that would have gone to -+// updateGeneric to update. -+// -+// Its Write and Sum methods are otherwise identical to the macGeneric ones, but -+// using function pointers would carry a major performance cost. -+type mac struct{ macGeneric } -+ -+func (h *mac) Write(p []byte) (int, error) { -+ nn := len(p) -+ if h.offset > 0 { -+ n := copy(h.buffer[h.offset:], p) -+ if h.offset+n < TagSize { -+ h.offset += n -+ return nn, nil -+ } -+ p = p[n:] -+ h.offset = 0 -+ update(&h.macState, h.buffer[:]) -+ } -+ if n := len(p) - (len(p) % TagSize); n > 0 { -+ update(&h.macState, p[:n]) -+ p = p[n:] -+ } -+ if len(p) > 0 { -+ h.offset += copy(h.buffer[h.offset:], p) -+ } -+ return nn, nil -+} -+ -+func (h *mac) Sum(out *[16]byte) { -+ state := h.macState -+ if h.offset > 0 { -+ update(&state, h.buffer[:h.offset]) -+ } -+ finalize(out, &state.h, &state.s) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s -new file mode 100644 -index 00000000000000..1d74f0f88189b1 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_amd64.s -@@ -0,0 +1,109 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+ -+#define POLY1305_ADD(msg, h0, h1, h2) \ -+ ADDQ 0(msg), h0; \ -+ ADCQ 8(msg), h1; \ -+ ADCQ $1, h2; \ -+ LEAQ 16(msg), msg -+ -+#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ -+ MOVQ r0, AX; \ -+ MULQ h0; \ -+ MOVQ AX, t0; \ -+ MOVQ DX, t1; \ -+ MOVQ r0, AX; \ -+ MULQ h1; \ -+ ADDQ AX, t1; \ -+ ADCQ $0, DX; \ -+ MOVQ r0, t2; \ -+ IMULQ h2, t2; \ -+ ADDQ DX, t2; \ -+ \ -+ MOVQ r1, AX; \ -+ MULQ h0; \ -+ ADDQ AX, t1; \ -+ ADCQ $0, DX; \ -+ MOVQ DX, h0; \ -+ MOVQ r1, t3; \ -+ IMULQ h2, t3; \ -+ MOVQ r1, AX; \ -+ MULQ h1; \ -+ ADDQ AX, t2; \ -+ ADCQ DX, t3; \ -+ ADDQ h0, t2; \ -+ ADCQ $0, t3; \ -+ \ -+ MOVQ t0, h0; \ -+ MOVQ t1, h1; \ -+ MOVQ t2, h2; \ -+ ANDQ $3, h2; \ -+ MOVQ t2, t0; \ -+ ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ -+ ADDQ t0, h0; \ -+ ADCQ t3, h1; \ -+ ADCQ $0, h2; \ -+ SHRQ $2, t3, t2; \ -+ SHRQ $2, t3; \ -+ ADDQ t2, h0; \ -+ ADCQ t3, h1; \ -+ ADCQ $0, h2 -+ -+// func update(state *[7]uint64, msg []byte) -+TEXT Β·update(SB), $0-32 -+ MOVQ state+0(FP), DI -+ MOVQ msg_base+8(FP), SI -+ MOVQ msg_len+16(FP), R15 -+ -+ MOVQ 0(DI), R8 // h0 -+ MOVQ 8(DI), R9 // h1 -+ MOVQ 16(DI), R10 // h2 -+ MOVQ 24(DI), R11 // r0 -+ MOVQ 32(DI), R12 // r1 -+ -+ CMPQ R15, $16 -+ JB bytes_between_0_and_15 -+ -+loop: -+ POLY1305_ADD(SI, R8, R9, R10) -+ -+multiply: -+ POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) -+ SUBQ $16, R15 -+ CMPQ R15, $16 -+ JAE loop -+ -+bytes_between_0_and_15: -+ TESTQ R15, R15 -+ JZ done -+ MOVQ $1, BX -+ XORQ CX, CX -+ XORQ R13, R13 -+ ADDQ R15, SI -+ -+flush_buffer: -+ SHLQ $8, BX, CX -+ SHLQ $8, BX -+ MOVB -1(SI), R13 -+ XORQ R13, BX -+ DECQ SI -+ DECQ R15 -+ JNZ flush_buffer -+ -+ ADDQ BX, R8 -+ ADCQ CX, R9 -+ ADCQ $0, R10 -+ MOVQ $16, R15 -+ JMP multiply -+ -+done: -+ MOVQ R8, 0(DI) -+ MOVQ R9, 8(DI) -+ MOVQ R10, 16(DI) -+ RET -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go -new file mode 100644 -index 00000000000000..e041da5ea3e7d0 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_generic.go -@@ -0,0 +1,309 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This file provides the generic implementation of Sum and MAC. Other files -+// might provide optimized assembly implementations of some of this code. -+ -+package poly1305 -+ -+import "encoding/binary" -+ -+// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag -+// for a 64 bytes message is approximately -+// -+// s + m[0:16] * r⁴ + m[16:32] * rΒ³ + m[32:48] * rΒ² + m[48:64] * r mod 2¹³⁰ - 5 -+// -+// for some secret r and s. It can be computed sequentially like -+// -+// for len(msg) > 0: -+// h += read(msg, 16) -+// h *= r -+// h %= 2¹³⁰ - 5 -+// return h + s -+// -+// All the complexity is about doing performant constant-time math on numbers -+// larger than any available numeric type. -+ -+func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { -+ h := newMACGeneric(key) -+ h.Write(msg) -+ h.Sum(out) -+} -+ -+func newMACGeneric(key *[32]byte) macGeneric { -+ m := macGeneric{} -+ initialize(key, &m.macState) -+ return m -+} -+ -+// macState holds numbers in saturated 64-bit little-endian limbs. That is, -+// the value of [x0, x1, x2] is x[0] + x[1] * 2⁢⁴ + x[2] * 2¹²⁸. -+type macState struct { -+ // h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but -+ // can grow larger during and after rounds. It must, however, remain below -+ // 2 * (2¹³⁰ - 5). -+ h [3]uint64 -+ // r and s are the private key components. -+ r [2]uint64 -+ s [2]uint64 -+} -+ -+type macGeneric struct { -+ macState -+ -+ buffer [TagSize]byte -+ offset int -+} -+ -+// Write splits the incoming message into TagSize chunks, and passes them to -+// update. It buffers incomplete chunks. -+func (h *macGeneric) Write(p []byte) (int, error) { -+ nn := len(p) -+ if h.offset > 0 { -+ n := copy(h.buffer[h.offset:], p) -+ if h.offset+n < TagSize { -+ h.offset += n -+ return nn, nil -+ } -+ p = p[n:] -+ h.offset = 0 -+ updateGeneric(&h.macState, h.buffer[:]) -+ } -+ if n := len(p) - (len(p) % TagSize); n > 0 { -+ updateGeneric(&h.macState, p[:n]) -+ p = p[n:] -+ } -+ if len(p) > 0 { -+ h.offset += copy(h.buffer[h.offset:], p) -+ } -+ return nn, nil -+} -+ -+// Sum flushes the last incomplete chunk from the buffer, if any, and generates -+// the MAC output. It does not modify its state, in order to allow for multiple -+// calls to Sum, even if no Write is allowed after Sum. -+func (h *macGeneric) Sum(out *[TagSize]byte) { -+ state := h.macState -+ if h.offset > 0 { -+ updateGeneric(&state, h.buffer[:h.offset]) -+ } -+ finalize(out, &state.h, &state.s) -+} -+ -+// [rMask0, rMask1] is the specified Poly1305 clamping mask in little-endian. It -+// clears some bits of the secret coefficient to make it possible to implement -+// multiplication more efficiently. -+const ( -+ rMask0 = 0x0FFFFFFC0FFFFFFF -+ rMask1 = 0x0FFFFFFC0FFFFFFC -+) -+ -+// initialize loads the 256-bit key into the two 128-bit secret values r and s. -+func initialize(key *[32]byte, m *macState) { -+ m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 -+ m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 -+ m.s[0] = binary.LittleEndian.Uint64(key[16:24]) -+ m.s[1] = binary.LittleEndian.Uint64(key[24:32]) -+} -+ -+// uint128 holds a 128-bit number as two 64-bit limbs, for use with the -+// bits.Mul64 and bits.Add64 intrinsics. -+type uint128 struct { -+ lo, hi uint64 -+} -+ -+func mul64(a, b uint64) uint128 { -+ hi, lo := bitsMul64(a, b) -+ return uint128{lo, hi} -+} -+ -+func add128(a, b uint128) uint128 { -+ lo, c := bitsAdd64(a.lo, b.lo, 0) -+ hi, c := bitsAdd64(a.hi, b.hi, c) -+ if c != 0 { -+ panic("poly1305: unexpected overflow") -+ } -+ return uint128{lo, hi} -+} -+ -+func shiftRightBy2(a uint128) uint128 { -+ a.lo = a.lo>>2 | (a.hi&3)<<62 -+ a.hi = a.hi >> 2 -+ return a -+} -+ -+// updateGeneric absorbs msg into the state.h accumulator. For each chunk m of -+// 128 bits of message, it computes -+// -+// hβ‚Š = (h + m) * r mod 2¹³⁰ - 5 -+// -+// If the msg length is not a multiple of TagSize, it assumes the last -+// incomplete chunk is the final one. -+func updateGeneric(state *macState, msg []byte) { -+ h0, h1, h2 := state.h[0], state.h[1], state.h[2] -+ r0, r1 := state.r[0], state.r[1] -+ -+ for len(msg) > 0 { -+ var c uint64 -+ -+ // For the first step, h + m, we use a chain of bits.Add64 intrinsics. -+ // The resulting value of h might exceed 2¹³⁰ - 5, but will be partially -+ // reduced at the end of the multiplication below. -+ // -+ // The spec requires us to set a bit just above the message size, not to -+ // hide leading zeroes. For full chunks, that's 1 << 128, so we can just -+ // add 1 to the most significant (2¹²⁸) limb, h2. -+ if len(msg) >= TagSize { -+ h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0) -+ h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c) -+ h2 += c + 1 -+ -+ msg = msg[TagSize:] -+ } else { -+ var buf [TagSize]byte -+ copy(buf[:], msg) -+ buf[len(msg)] = 1 -+ -+ h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0) -+ h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c) -+ h2 += c -+ -+ msg = nil -+ } -+ -+ // Multiplication of big number limbs is similar to elementary school -+ // columnar multiplication. Instead of digits, there are 64-bit limbs. -+ // -+ // We are multiplying a 3 limbs number, h, by a 2 limbs number, r. -+ // -+ // h2 h1 h0 x -+ // r1 r0 = -+ // ---------------- -+ // h2r0 h1r0 h0r0 <-- individual 128-bit products -+ // + h2r1 h1r1 h0r1 -+ // ------------------------ -+ // m3 m2 m1 m0 <-- result in 128-bit overlapping limbs -+ // ------------------------ -+ // m3.hi m2.hi m1.hi m0.hi <-- carry propagation -+ // + m3.lo m2.lo m1.lo m0.lo -+ // ------------------------------- -+ // t4 t3 t2 t1 t0 <-- final result in 64-bit limbs -+ // -+ // The main difference from pen-and-paper multiplication is that we do -+ // carry propagation in a separate step, as if we wrote two digit sums -+ // at first (the 128-bit limbs), and then carried the tens all at once. -+ -+ h0r0 := mul64(h0, r0) -+ h1r0 := mul64(h1, r0) -+ h2r0 := mul64(h2, r0) -+ h0r1 := mul64(h0, r1) -+ h1r1 := mul64(h1, r1) -+ h2r1 := mul64(h2, r1) -+ -+ // Since h2 is known to be at most 7 (5 + 1 + 1), and r0 and r1 have their -+ // top 4 bits cleared by rMask{0,1}, we know that their product is not going -+ // to overflow 64 bits, so we can ignore the high part of the products. -+ // -+ // This also means that the product doesn't have a fifth limb (t4). -+ if h2r0.hi != 0 { -+ panic("poly1305: unexpected overflow") -+ } -+ if h2r1.hi != 0 { -+ panic("poly1305: unexpected overflow") -+ } -+ -+ m0 := h0r0 -+ m1 := add128(h1r0, h0r1) // These two additions don't overflow thanks again -+ m2 := add128(h2r0, h1r1) // to the 4 masked bits at the top of r0 and r1. -+ m3 := h2r1 -+ -+ t0 := m0.lo -+ t1, c := bitsAdd64(m1.lo, m0.hi, 0) -+ t2, c := bitsAdd64(m2.lo, m1.hi, c) -+ t3, _ := bitsAdd64(m3.lo, m2.hi, c) -+ -+ // Now we have the result as 4 64-bit limbs, and we need to reduce it -+ // modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do -+ // a cheap partial reduction according to the reduction identity -+ // -+ // c * 2¹³⁰ + n = c * 5 + n mod 2¹³⁰ - 5 -+ // -+ // because 2¹³⁰ = 5 mod 2¹³⁰ - 5. Partial reduction since the result is -+ // likely to be larger than 2¹³⁰ - 5, but still small enough to fit the -+ // assumptions we make about h in the rest of the code. -+ // -+ // See also https://speakerdeck.com/gtank/engineering-prime-numbers?slide=23 -+ -+ // We split the final result at the 2¹³⁰ mark into h and cc, the carry. -+ // Note that the carry bits are effectively shifted left by 2, in other -+ // words, cc = c * 4 for the c in the reduction identity. -+ h0, h1, h2 = t0, t1, t2&maskLow2Bits -+ cc := uint128{t2 & maskNotLow2Bits, t3} -+ -+ // To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c. -+ -+ h0, c = bitsAdd64(h0, cc.lo, 0) -+ h1, c = bitsAdd64(h1, cc.hi, c) -+ h2 += c -+ -+ cc = shiftRightBy2(cc) -+ -+ h0, c = bitsAdd64(h0, cc.lo, 0) -+ h1, c = bitsAdd64(h1, cc.hi, c) -+ h2 += c -+ -+ // h2 is at most 3 + 1 + 1 = 5, making the whole of h at most -+ // -+ // 5 * 2¹²⁸ + (2¹²⁸ - 1) = 6 * 2¹²⁸ - 1 -+ } -+ -+ state.h[0], state.h[1], state.h[2] = h0, h1, h2 -+} -+ -+const ( -+ maskLow2Bits uint64 = 0x0000000000000003 -+ maskNotLow2Bits uint64 = ^maskLow2Bits -+) -+ -+// select64 returns x if v == 1 and y if v == 0, in constant time. -+func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y } -+ -+// [p0, p1, p2] is 2¹³⁰ - 5 in little endian order. -+const ( -+ p0 = 0xFFFFFFFFFFFFFFFB -+ p1 = 0xFFFFFFFFFFFFFFFF -+ p2 = 0x0000000000000003 -+) -+ -+// finalize completes the modular reduction of h and computes -+// -+// out = h + s mod 2¹²⁸ -+func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) { -+ h0, h1, h2 := h[0], h[1], h[2] -+ -+ // After the partial reduction in updateGeneric, h might be more than -+ // 2¹³⁰ - 5, but will be less than 2 * (2¹³⁰ - 5). To complete the reduction -+ // in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the -+ // result if the subtraction underflows, and t otherwise. -+ -+ hMinusP0, b := bitsSub64(h0, p0, 0) -+ hMinusP1, b := bitsSub64(h1, p1, b) -+ _, b = bitsSub64(h2, p2, b) -+ -+ // h = h if h < p else h - p -+ h0 = select64(b, h0, hMinusP0) -+ h1 = select64(b, h1, hMinusP1) -+ -+ // Finally, we compute the last Poly1305 step -+ // -+ // tag = h + s mod 2¹²⁸ -+ // -+ // by just doing a wide addition with the 128 low bits of h and discarding -+ // the overflow. -+ h0, c := bitsAdd64(h0, s[0], 0) -+ h1, _ = bitsAdd64(h1, s[1], c) -+ -+ binary.LittleEndian.PutUint64(out[0:8], h0) -+ binary.LittleEndian.PutUint64(out[8:16], h1) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go -new file mode 100644 -index 00000000000000..4a069941a6ef9b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go -@@ -0,0 +1,48 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package poly1305 -+ -+//go:noescape -+func update(state *macState, msg []byte) -+ -+// mac is a wrapper for macGeneric that redirects calls that would have gone to -+// updateGeneric to update. -+// -+// Its Write and Sum methods are otherwise identical to the macGeneric ones, but -+// using function pointers would carry a major performance cost. -+type mac struct{ macGeneric } -+ -+func (h *mac) Write(p []byte) (int, error) { -+ nn := len(p) -+ if h.offset > 0 { -+ n := copy(h.buffer[h.offset:], p) -+ if h.offset+n < TagSize { -+ h.offset += n -+ return nn, nil -+ } -+ p = p[n:] -+ h.offset = 0 -+ update(&h.macState, h.buffer[:]) -+ } -+ if n := len(p) - (len(p) % TagSize); n > 0 { -+ update(&h.macState, p[:n]) -+ p = p[n:] -+ } -+ if len(p) > 0 { -+ h.offset += copy(h.buffer[h.offset:], p) -+ } -+ return nn, nil -+} -+ -+func (h *mac) Sum(out *[16]byte) { -+ state := h.macState -+ if h.offset > 0 { -+ update(&state, h.buffer[:h.offset]) -+ } -+ finalize(out, &state.h, &state.s) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s -new file mode 100644 -index 00000000000000..58422aad230570 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s -@@ -0,0 +1,182 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+ -+// This was ported from the amd64 implementation. -+ -+#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \ -+ MOVD (msg), t0; \ -+ MOVD 8(msg), t1; \ -+ MOVD $1, t2; \ -+ ADDC t0, h0, h0; \ -+ ADDE t1, h1, h1; \ -+ ADDE t2, h2; \ -+ ADD $16, msg -+ -+#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ -+ MULLD r0, h0, t0; \ -+ MULLD r0, h1, t4; \ -+ MULHDU r0, h0, t1; \ -+ MULHDU r0, h1, t5; \ -+ ADDC t4, t1, t1; \ -+ MULLD r0, h2, t2; \ -+ ADDZE t5; \ -+ MULHDU r1, h0, t4; \ -+ MULLD r1, h0, h0; \ -+ ADD t5, t2, t2; \ -+ ADDC h0, t1, t1; \ -+ MULLD h2, r1, t3; \ -+ ADDZE t4, h0; \ -+ MULHDU r1, h1, t5; \ -+ MULLD r1, h1, t4; \ -+ ADDC t4, t2, t2; \ -+ ADDE t5, t3, t3; \ -+ ADDC h0, t2, t2; \ -+ MOVD $-4, t4; \ -+ MOVD t0, h0; \ -+ MOVD t1, h1; \ -+ ADDZE t3; \ -+ ANDCC $3, t2, h2; \ -+ AND t2, t4, t0; \ -+ ADDC t0, h0, h0; \ -+ ADDE t3, h1, h1; \ -+ SLD $62, t3, t4; \ -+ SRD $2, t2; \ -+ ADDZE h2; \ -+ OR t4, t2, t2; \ -+ SRD $2, t3; \ -+ ADDC t2, h0, h0; \ -+ ADDE t3, h1, h1; \ -+ ADDZE h2 -+ -+DATA Β·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -+DATA Β·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -+GLOBL Β·poly1305Mask<>(SB), RODATA, $16 -+ -+// func update(state *[7]uint64, msg []byte) -+TEXT Β·update(SB), $0-32 -+ MOVD state+0(FP), R3 -+ MOVD msg_base+8(FP), R4 -+ MOVD msg_len+16(FP), R5 -+ -+ MOVD 0(R3), R8 // h0 -+ MOVD 8(R3), R9 // h1 -+ MOVD 16(R3), R10 // h2 -+ MOVD 24(R3), R11 // r0 -+ MOVD 32(R3), R12 // r1 -+ -+ CMP R5, $16 -+ BLT bytes_between_0_and_15 -+ -+loop: -+ POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) -+ -+multiply: -+ POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) -+ ADD $-16, R5 -+ CMP R5, $16 -+ BGE loop -+ -+bytes_between_0_and_15: -+ CMP R5, $0 -+ BEQ done -+ MOVD $0, R16 // h0 -+ MOVD $0, R17 // h1 -+ -+flush_buffer: -+ CMP R5, $8 -+ BLE just1 -+ -+ MOVD $8, R21 -+ SUB R21, R5, R21 -+ -+ // Greater than 8 -- load the rightmost remaining bytes in msg -+ // and put into R17 (h1) -+ MOVD (R4)(R21), R17 -+ MOVD $16, R22 -+ -+ // Find the offset to those bytes -+ SUB R5, R22, R22 -+ SLD $3, R22 -+ -+ // Shift to get only the bytes in msg -+ SRD R22, R17, R17 -+ -+ // Put 1 at high end -+ MOVD $1, R23 -+ SLD $3, R21 -+ SLD R21, R23, R23 -+ OR R23, R17, R17 -+ -+ // Remainder is 8 -+ MOVD $8, R5 -+ -+just1: -+ CMP R5, $8 -+ BLT less8 -+ -+ // Exactly 8 -+ MOVD (R4), R16 -+ -+ CMP R17, $0 -+ -+ // Check if we've already set R17; if not -+ // set 1 to indicate end of msg. -+ BNE carry -+ MOVD $1, R17 -+ BR carry -+ -+less8: -+ MOVD $0, R16 // h0 -+ MOVD $0, R22 // shift count -+ CMP R5, $4 -+ BLT less4 -+ MOVWZ (R4), R16 -+ ADD $4, R4 -+ ADD $-4, R5 -+ MOVD $32, R22 -+ -+less4: -+ CMP R5, $2 -+ BLT less2 -+ MOVHZ (R4), R21 -+ SLD R22, R21, R21 -+ OR R16, R21, R16 -+ ADD $16, R22 -+ ADD $-2, R5 -+ ADD $2, R4 -+ -+less2: -+ CMP R5, $0 -+ BEQ insert1 -+ MOVBZ (R4), R21 -+ SLD R22, R21, R21 -+ OR R16, R21, R16 -+ ADD $8, R22 -+ -+insert1: -+ // Insert 1 at end of msg -+ MOVD $1, R21 -+ SLD R22, R21, R21 -+ OR R16, R21, R16 -+ -+carry: -+ // Add new values to h0, h1, h2 -+ ADDC R16, R8 -+ ADDE R17, R9 -+ ADDZE R10, R10 -+ MOVD $16, R5 -+ ADD R5, R4 -+ BR multiply -+ -+done: -+ // Save h0, h1, h2 in state -+ MOVD R8, 0(R3) -+ MOVD R9, 8(R3) -+ MOVD R10, 16(R3) -+ RET -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go -new file mode 100644 -index 00000000000000..ec95966889691d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.go -@@ -0,0 +1,77 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package poly1305 -+ -+import ( -+ "golang.org/x/sys/cpu" -+) -+ -+// updateVX is an assembly implementation of Poly1305 that uses vector -+// instructions. It must only be called if the vector facility (vx) is -+// available. -+// -+//go:noescape -+func updateVX(state *macState, msg []byte) -+ -+// mac is a replacement for macGeneric that uses a larger buffer and redirects -+// calls that would have gone to updateGeneric to updateVX if the vector -+// facility is installed. -+// -+// A larger buffer is required for good performance because the vector -+// implementation has a higher fixed cost per call than the generic -+// implementation. -+type mac struct { -+ macState -+ -+ buffer [16 * TagSize]byte // size must be a multiple of block size (16) -+ offset int -+} -+ -+func (h *mac) Write(p []byte) (int, error) { -+ nn := len(p) -+ if h.offset > 0 { -+ n := copy(h.buffer[h.offset:], p) -+ if h.offset+n < len(h.buffer) { -+ h.offset += n -+ return nn, nil -+ } -+ p = p[n:] -+ h.offset = 0 -+ if cpu.S390X.HasVX { -+ updateVX(&h.macState, h.buffer[:]) -+ } else { -+ updateGeneric(&h.macState, h.buffer[:]) -+ } -+ } -+ -+ tail := len(p) % len(h.buffer) // number of bytes to copy into buffer -+ body := len(p) - tail // number of bytes to process now -+ if body > 0 { -+ if cpu.S390X.HasVX { -+ updateVX(&h.macState, p[:body]) -+ } else { -+ updateGeneric(&h.macState, p[:body]) -+ } -+ } -+ h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0 -+ return nn, nil -+} -+ -+func (h *mac) Sum(out *[TagSize]byte) { -+ state := h.macState -+ remainder := h.buffer[:h.offset] -+ -+ // Use the generic implementation if we have 2 or fewer blocks left -+ // to sum. The vector implementation has a higher startup time. -+ if cpu.S390X.HasVX && len(remainder) > 2*TagSize { -+ updateVX(&state, remainder) -+ } else if len(remainder) > 0 { -+ updateGeneric(&state, remainder) -+ } -+ finalize(out, &state.h, &state.s) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s -new file mode 100644 -index 00000000000000..aa9e0494c909d8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/sum_s390x.s -@@ -0,0 +1,504 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+ -+// This implementation of Poly1305 uses the vector facility (vx) -+// to process up to 2 blocks (32 bytes) per iteration using an -+// algorithm based on the one described in: -+// -+// NEON crypto, Daniel J. Bernstein & Peter Schwabe -+// https://cryptojedi.org/papers/neoncrypto-20120320.pdf -+// -+// This algorithm uses 5 26-bit limbs to represent a 130-bit -+// value. These limbs are, for the most part, zero extended and -+// placed into 64-bit vector register elements. Each vector -+// register is 128-bits wide and so holds 2 of these elements. -+// Using 26-bit limbs allows us plenty of headroom to accommodate -+// accumulations before and after multiplication without -+// overflowing either 32-bits (before multiplication) or 64-bits -+// (after multiplication). -+// -+// In order to parallelise the operations required to calculate -+// the sum we use two separate accumulators and then sum those -+// in an extra final step. For compatibility with the generic -+// implementation we perform this summation at the end of every -+// updateVX call. -+// -+// To use two accumulators we must multiply the message blocks -+// by rΒ² rather than r. Only the final message block should be -+// multiplied by r. -+// -+// Example: -+// -+// We want to calculate the sum (h) for a 64 byte message (m): -+// -+// h = m[0:16]r⁴ + m[16:32]rΒ³ + m[32:48]rΒ² + m[48:64]r -+// -+// To do this we split the calculation into the even indices -+// and odd indices of the message. These form our SIMD 'lanes': -+// -+// h = m[ 0:16]r⁴ + m[32:48]rΒ² + <- lane 0 -+// m[16:32]rΒ³ + m[48:64]r <- lane 1 -+// -+// To calculate this iteratively we refactor so that both lanes -+// are written in terms of rΒ² and r: -+// -+// h = (m[ 0:16]rΒ² + m[32:48])rΒ² + <- lane 0 -+// (m[16:32]rΒ² + m[48:64])r <- lane 1 -+// ^ ^ -+// | coefficients for second iteration -+// coefficients for first iteration -+// -+// So in this case we would have two iterations. In the first -+// both lanes are multiplied by rΒ². In the second only the -+// first lane is multiplied by rΒ² and the second lane is -+// instead multiplied by r. This gives use the odd and even -+// powers of r that we need from the original equation. -+// -+// Notation: -+// -+// h - accumulator -+// r - key -+// m - message -+// -+// [a, b] - SIMD register holding two 64-bit values -+// [a, b, c, d] - SIMD register holding four 32-bit values -+// xα΅’[n] - limb n of variable x with bit width i -+// -+// Limbs are expressed in little endian order, so for 26-bit -+// limbs x₂₆[4] will be the most significant limb and x₂₆[0] -+// will be the least significant limb. -+ -+// masking constants -+#define MOD24 V0 // [0x0000000000ffffff, 0x0000000000ffffff] - mask low 24-bits -+#define MOD26 V1 // [0x0000000003ffffff, 0x0000000003ffffff] - mask low 26-bits -+ -+// expansion constants (see EXPAND macro) -+#define EX0 V2 -+#define EX1 V3 -+#define EX2 V4 -+ -+// key (rΒ², r or 1 depending on context) -+#define R_0 V5 -+#define R_1 V6 -+#define R_2 V7 -+#define R_3 V8 -+#define R_4 V9 -+ -+// precalculated coefficients (5rΒ², 5r or 0 depending on context) -+#define R5_1 V10 -+#define R5_2 V11 -+#define R5_3 V12 -+#define R5_4 V13 -+ -+// message block (m) -+#define M_0 V14 -+#define M_1 V15 -+#define M_2 V16 -+#define M_3 V17 -+#define M_4 V18 -+ -+// accumulator (h) -+#define H_0 V19 -+#define H_1 V20 -+#define H_2 V21 -+#define H_3 V22 -+#define H_4 V23 -+ -+// temporary registers (for short-lived values) -+#define T_0 V24 -+#define T_1 V25 -+#define T_2 V26 -+#define T_3 V27 -+#define T_4 V28 -+ -+GLOBL Β·constants<>(SB), RODATA, $0x30 -+// EX0 -+DATA Β·constants<>+0x00(SB)/8, $0x0006050403020100 -+DATA Β·constants<>+0x08(SB)/8, $0x1016151413121110 -+// EX1 -+DATA Β·constants<>+0x10(SB)/8, $0x060c0b0a09080706 -+DATA Β·constants<>+0x18(SB)/8, $0x161c1b1a19181716 -+// EX2 -+DATA Β·constants<>+0x20(SB)/8, $0x0d0d0d0d0d0f0e0d -+DATA Β·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d -+ -+// MULTIPLY multiplies each lane of f and g, partially reduced -+// modulo 2¹³⁰ - 5. The result, h, consists of partial products -+// in each lane that need to be reduced further to produce the -+// final result. -+// -+// h₁₃₀ = (f₁₃₀g₁₃₀) % 2¹³⁰ + (5f₁₃₀g₁₃₀) / 2¹³⁰ -+// -+// Note that the multiplication by 5 of the high bits is -+// achieved by precalculating the multiplication of four of the -+// g coefficients by 5. These are g51-g54. -+#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ -+ VMLOF f0, g0, h0 \ -+ VMLOF f0, g3, h3 \ -+ VMLOF f0, g1, h1 \ -+ VMLOF f0, g4, h4 \ -+ VMLOF f0, g2, h2 \ -+ VMLOF f1, g54, T_0 \ -+ VMLOF f1, g2, T_3 \ -+ VMLOF f1, g0, T_1 \ -+ VMLOF f1, g3, T_4 \ -+ VMLOF f1, g1, T_2 \ -+ VMALOF f2, g53, h0, h0 \ -+ VMALOF f2, g1, h3, h3 \ -+ VMALOF f2, g54, h1, h1 \ -+ VMALOF f2, g2, h4, h4 \ -+ VMALOF f2, g0, h2, h2 \ -+ VMALOF f3, g52, T_0, T_0 \ -+ VMALOF f3, g0, T_3, T_3 \ -+ VMALOF f3, g53, T_1, T_1 \ -+ VMALOF f3, g1, T_4, T_4 \ -+ VMALOF f3, g54, T_2, T_2 \ -+ VMALOF f4, g51, h0, h0 \ -+ VMALOF f4, g54, h3, h3 \ -+ VMALOF f4, g52, h1, h1 \ -+ VMALOF f4, g0, h4, h4 \ -+ VMALOF f4, g53, h2, h2 \ -+ VAG T_0, h0, h0 \ -+ VAG T_3, h3, h3 \ -+ VAG T_1, h1, h1 \ -+ VAG T_4, h4, h4 \ -+ VAG T_2, h2, h2 -+ -+// REDUCE performs the following carry operations in four -+// stages, as specified in Bernstein & Schwabe: -+// -+// 1: h₂₆[0]->h₂₆[1] h₂₆[3]->h₂₆[4] -+// 2: h₂₆[1]->h₂₆[2] h₂₆[4]->h₂₆[0] -+// 3: h₂₆[0]->h₂₆[1] h₂₆[2]->h₂₆[3] -+// 4: h₂₆[3]->h₂₆[4] -+// -+// The result is that all of the limbs are limited to 26-bits -+// except for h₂₆[1] and h₂₆[4] which are limited to 27-bits. -+// -+// Note that although each limb is aligned at 26-bit intervals -+// they may contain values that exceed 2²⁢ - 1, hence the need -+// to carry the excess bits in each limb. -+#define REDUCE(h0, h1, h2, h3, h4) \ -+ VESRLG $26, h0, T_0 \ -+ VESRLG $26, h3, T_1 \ -+ VN MOD26, h0, h0 \ -+ VN MOD26, h3, h3 \ -+ VAG T_0, h1, h1 \ -+ VAG T_1, h4, h4 \ -+ VESRLG $26, h1, T_2 \ -+ VESRLG $26, h4, T_3 \ -+ VN MOD26, h1, h1 \ -+ VN MOD26, h4, h4 \ -+ VESLG $2, T_3, T_4 \ -+ VAG T_3, T_4, T_4 \ -+ VAG T_2, h2, h2 \ -+ VAG T_4, h0, h0 \ -+ VESRLG $26, h2, T_0 \ -+ VESRLG $26, h0, T_1 \ -+ VN MOD26, h2, h2 \ -+ VN MOD26, h0, h0 \ -+ VAG T_0, h3, h3 \ -+ VAG T_1, h1, h1 \ -+ VESRLG $26, h3, T_2 \ -+ VN MOD26, h3, h3 \ -+ VAG T_2, h4, h4 -+ -+// EXPAND splits the 128-bit little-endian values in0 and in1 -+// into 26-bit big-endian limbs and places the results into -+// the first and second lane of d₂₆[0:4] respectively. -+// -+// The EX0, EX1 and EX2 constants are arrays of byte indices -+// for permutation. The permutation both reverses the bytes -+// in the input and ensures the bytes are copied into the -+// destination limb ready to be shifted into their final -+// position. -+#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ -+ VPERM in0, in1, EX0, d0 \ -+ VPERM in0, in1, EX1, d2 \ -+ VPERM in0, in1, EX2, d4 \ -+ VESRLG $26, d0, d1 \ -+ VESRLG $30, d2, d3 \ -+ VESRLG $4, d2, d2 \ -+ VN MOD26, d0, d0 \ // [in0₂₆[0], in1₂₆[0]] -+ VN MOD26, d3, d3 \ // [in0₂₆[3], in1₂₆[3]] -+ VN MOD26, d1, d1 \ // [in0₂₆[1], in1₂₆[1]] -+ VN MOD24, d4, d4 \ // [in0₂₆[4], in1₂₆[4]] -+ VN MOD26, d2, d2 // [in0₂₆[2], in1₂₆[2]] -+ -+// func updateVX(state *macState, msg []byte) -+TEXT Β·updateVX(SB), NOSPLIT, $0 -+ MOVD state+0(FP), R1 -+ LMG msg+8(FP), R2, R3 // R2=msg_base, R3=msg_len -+ -+ // load EX0, EX1 and EX2 -+ MOVD $Β·constants<>(SB), R5 -+ VLM (R5), EX0, EX2 -+ -+ // generate masks -+ VGMG $(64-24), $63, MOD24 // [0x00ffffff, 0x00ffffff] -+ VGMG $(64-26), $63, MOD26 // [0x03ffffff, 0x03ffffff] -+ -+ // load h (accumulator) and r (key) from state -+ VZERO T_1 // [0, 0] -+ VL 0(R1), T_0 // [h₆₄[0], h₆₄[1]] -+ VLEG $0, 16(R1), T_1 // [h₆₄[2], 0] -+ VL 24(R1), T_2 // [r₆₄[0], r₆₄[1]] -+ VPDI $0, T_0, T_2, T_3 // [h₆₄[0], r₆₄[0]] -+ VPDI $5, T_0, T_2, T_4 // [h₆₄[1], r₆₄[1]] -+ -+ // unpack h and r into 26-bit limbs -+ // note: h₆₄[2] may have the low 3 bits set, so h₂₆[4] is a 27-bit value -+ VN MOD26, T_3, H_0 // [h₂₆[0], r₂₆[0]] -+ VZERO H_1 // [0, 0] -+ VZERO H_3 // [0, 0] -+ VGMG $(64-12-14), $(63-12), T_0 // [0x03fff000, 0x03fff000] - 26-bit mask with low 12 bits masked out -+ VESLG $24, T_1, T_1 // [h₆₄[2]<<24, 0] -+ VERIMG $-26&63, T_3, MOD26, H_1 // [h₂₆[1], r₂₆[1]] -+ VESRLG $+52&63, T_3, H_2 // [h₂₆[2], r₂₆[2]] - low 12 bits only -+ VERIMG $-14&63, T_4, MOD26, H_3 // [h₂₆[1], r₂₆[1]] -+ VESRLG $40, T_4, H_4 // [h₂₆[4], r₂₆[4]] - low 24 bits only -+ VERIMG $+12&63, T_4, T_0, H_2 // [h₂₆[2], r₂₆[2]] - complete -+ VO T_1, H_4, H_4 // [h₂₆[4], r₂₆[4]] - complete -+ -+ // replicate r across all 4 vector elements -+ VREPF $3, H_0, R_0 // [r₂₆[0], r₂₆[0], r₂₆[0], r₂₆[0]] -+ VREPF $3, H_1, R_1 // [r₂₆[1], r₂₆[1], r₂₆[1], r₂₆[1]] -+ VREPF $3, H_2, R_2 // [r₂₆[2], r₂₆[2], r₂₆[2], r₂₆[2]] -+ VREPF $3, H_3, R_3 // [r₂₆[3], r₂₆[3], r₂₆[3], r₂₆[3]] -+ VREPF $3, H_4, R_4 // [r₂₆[4], r₂₆[4], r₂₆[4], r₂₆[4]] -+ -+ // zero out lane 1 of h -+ VLEIG $1, $0, H_0 // [h₂₆[0], 0] -+ VLEIG $1, $0, H_1 // [h₂₆[1], 0] -+ VLEIG $1, $0, H_2 // [h₂₆[2], 0] -+ VLEIG $1, $0, H_3 // [h₂₆[3], 0] -+ VLEIG $1, $0, H_4 // [h₂₆[4], 0] -+ -+ // calculate 5r (ignore least significant limb) -+ VREPIF $5, T_0 -+ VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r₂₆[1], 5r₂₆[1], 5r₂₆[1]] -+ VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r₂₆[2], 5r₂₆[2], 5r₂₆[2]] -+ VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r₂₆[3], 5r₂₆[3], 5r₂₆[3]] -+ VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r₂₆[4], 5r₂₆[4], 5r₂₆[4]] -+ -+ // skip rΒ² calculation if we are only calculating one block -+ CMPBLE R3, $16, skip -+ -+ // calculate rΒ² -+ MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, M_0, M_1, M_2, M_3, M_4) -+ REDUCE(M_0, M_1, M_2, M_3, M_4) -+ VGBM $0x0f0f, T_0 -+ VERIMG $0, M_0, T_0, R_0 // [r₂₆[0], r²₂₆[0], r₂₆[0], r²₂₆[0]] -+ VERIMG $0, M_1, T_0, R_1 // [r₂₆[1], r²₂₆[1], r₂₆[1], r²₂₆[1]] -+ VERIMG $0, M_2, T_0, R_2 // [r₂₆[2], r²₂₆[2], r₂₆[2], r²₂₆[2]] -+ VERIMG $0, M_3, T_0, R_3 // [r₂₆[3], r²₂₆[3], r₂₆[3], r²₂₆[3]] -+ VERIMG $0, M_4, T_0, R_4 // [r₂₆[4], r²₂₆[4], r₂₆[4], r²₂₆[4]] -+ -+ // calculate 5rΒ² (ignore least significant limb) -+ VREPIF $5, T_0 -+ VMLF T_0, R_1, R5_1 // [5r₂₆[1], 5r²₂₆[1], 5r₂₆[1], 5r²₂₆[1]] -+ VMLF T_0, R_2, R5_2 // [5r₂₆[2], 5r²₂₆[2], 5r₂₆[2], 5r²₂₆[2]] -+ VMLF T_0, R_3, R5_3 // [5r₂₆[3], 5r²₂₆[3], 5r₂₆[3], 5r²₂₆[3]] -+ VMLF T_0, R_4, R5_4 // [5r₂₆[4], 5r²₂₆[4], 5r₂₆[4], 5r²₂₆[4]] -+ -+loop: -+ CMPBLE R3, $32, b2 // 2 or fewer blocks remaining, need to change key coefficients -+ -+ // load next 2 blocks from message -+ VLM (R2), T_0, T_1 -+ -+ // update message slice -+ SUB $32, R3 -+ MOVD $32(R2), R2 -+ -+ // unpack message blocks into 26-bit big-endian limbs -+ EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) -+ -+ // add 2¹²⁸ to each message block value -+ VLEIB $4, $1, M_4 -+ VLEIB $12, $1, M_4 -+ -+multiply: -+ // accumulate the incoming message -+ VAG H_0, M_0, M_0 -+ VAG H_3, M_3, M_3 -+ VAG H_1, M_1, M_1 -+ VAG H_4, M_4, M_4 -+ VAG H_2, M_2, M_2 -+ -+ // multiply the accumulator by the key coefficient -+ MULTIPLY(M_0, M_1, M_2, M_3, M_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4) -+ -+ // carry and partially reduce the partial products -+ REDUCE(H_0, H_1, H_2, H_3, H_4) -+ -+ CMPBNE R3, $0, loop -+ -+finish: -+ // sum lane 0 and lane 1 and put the result in lane 1 -+ VZERO T_0 -+ VSUMQG H_0, T_0, H_0 -+ VSUMQG H_3, T_0, H_3 -+ VSUMQG H_1, T_0, H_1 -+ VSUMQG H_4, T_0, H_4 -+ VSUMQG H_2, T_0, H_2 -+ -+ // reduce again after summation -+ // TODO(mundaym): there might be a more efficient way to do this -+ // now that we only have 1 active lane. For example, we could -+ // simultaneously pack the values as we reduce them. -+ REDUCE(H_0, H_1, H_2, H_3, H_4) -+ -+ // carry h[1] through to h[4] so that only h[4] can exceed 2²⁢ - 1 -+ // TODO(mundaym): in testing this final carry was unnecessary. -+ // Needs a proof before it can be removed though. -+ VESRLG $26, H_1, T_1 -+ VN MOD26, H_1, H_1 -+ VAQ T_1, H_2, H_2 -+ VESRLG $26, H_2, T_2 -+ VN MOD26, H_2, H_2 -+ VAQ T_2, H_3, H_3 -+ VESRLG $26, H_3, T_3 -+ VN MOD26, H_3, H_3 -+ VAQ T_3, H_4, H_4 -+ -+ // h is now < 2(2¹³⁰ - 5) -+ // Pack each lane in h₂₆[0:4] into hβ‚β‚‚β‚ˆ[0:1]. -+ VESLG $26, H_1, H_1 -+ VESLG $26, H_3, H_3 -+ VO H_0, H_1, H_0 -+ VO H_2, H_3, H_2 -+ VESLG $4, H_2, H_2 -+ VLEIB $7, $48, H_1 -+ VSLB H_1, H_2, H_2 -+ VO H_0, H_2, H_0 -+ VLEIB $7, $104, H_1 -+ VSLB H_1, H_4, H_3 -+ VO H_3, H_0, H_0 -+ VLEIB $7, $24, H_1 -+ VSRLB H_1, H_4, H_1 -+ -+ // update state -+ VSTEG $1, H_0, 0(R1) -+ VSTEG $0, H_0, 8(R1) -+ VSTEG $1, H_1, 16(R1) -+ RET -+ -+b2: // 2 or fewer blocks remaining -+ CMPBLE R3, $16, b1 -+ -+ // Load the 2 remaining blocks (17-32 bytes remaining). -+ MOVD $-17(R3), R0 // index of final byte to load modulo 16 -+ VL (R2), T_0 // load full 16 byte block -+ VLL R0, 16(R2), T_1 // load final (possibly partial) block and pad with zeros to 16 bytes -+ -+ // The Poly1305 algorithm requires that a 1 bit be appended to -+ // each message block. If the final block is less than 16 bytes -+ // long then it is easiest to insert the 1 before the message -+ // block is split into 26-bit limbs. If, on the other hand, the -+ // final message block is 16 bytes long then we append the 1 bit -+ // after expansion as normal. -+ MOVBZ $1, R0 -+ MOVD $-16(R3), R3 // index of byte in last block to insert 1 at (could be 16) -+ CMPBEQ R3, $16, 2(PC) // skip the insertion if the final block is 16 bytes long -+ VLVGB R3, R0, T_1 // insert 1 into the byte at index R3 -+ -+ // Split both blocks into 26-bit limbs in the appropriate lanes. -+ EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) -+ -+ // Append a 1 byte to the end of the second to last block. -+ VLEIB $4, $1, M_4 -+ -+ // Append a 1 byte to the end of the last block only if it is a -+ // full 16 byte block. -+ CMPBNE R3, $16, 2(PC) -+ VLEIB $12, $1, M_4 -+ -+ // Finally, set up the coefficients for the final multiplication. -+ // We have previously saved r and 5r in the 32-bit even indexes -+ // of the R_[0-4] and R5_[1-4] coefficient registers. -+ // -+ // We want lane 0 to be multiplied by rΒ² so that can be kept the -+ // same. We want lane 1 to be multiplied by r so we need to move -+ // the saved r value into the 32-bit odd index in lane 1 by -+ // rotating the 64-bit lane by 32. -+ VGBM $0x00ff, T_0 // [0, 0xffffffffffffffff] - mask lane 1 only -+ VERIMG $32, R_0, T_0, R_0 // [_, r²₂₆[0], _, r₂₆[0]] -+ VERIMG $32, R_1, T_0, R_1 // [_, r²₂₆[1], _, r₂₆[1]] -+ VERIMG $32, R_2, T_0, R_2 // [_, r²₂₆[2], _, r₂₆[2]] -+ VERIMG $32, R_3, T_0, R_3 // [_, r²₂₆[3], _, r₂₆[3]] -+ VERIMG $32, R_4, T_0, R_4 // [_, r²₂₆[4], _, r₂₆[4]] -+ VERIMG $32, R5_1, T_0, R5_1 // [_, 5r²₂₆[1], _, 5r₂₆[1]] -+ VERIMG $32, R5_2, T_0, R5_2 // [_, 5r²₂₆[2], _, 5r₂₆[2]] -+ VERIMG $32, R5_3, T_0, R5_3 // [_, 5r²₂₆[3], _, 5r₂₆[3]] -+ VERIMG $32, R5_4, T_0, R5_4 // [_, 5r²₂₆[4], _, 5r₂₆[4]] -+ -+ MOVD $0, R3 -+ BR multiply -+ -+skip: -+ CMPBEQ R3, $0, finish -+ -+b1: // 1 block remaining -+ -+ // Load the final block (1-16 bytes). This will be placed into -+ // lane 0. -+ MOVD $-1(R3), R0 -+ VLL R0, (R2), T_0 // pad to 16 bytes with zeros -+ -+ // The Poly1305 algorithm requires that a 1 bit be appended to -+ // each message block. If the final block is less than 16 bytes -+ // long then it is easiest to insert the 1 before the message -+ // block is split into 26-bit limbs. If, on the other hand, the -+ // final message block is 16 bytes long then we append the 1 bit -+ // after expansion as normal. -+ MOVBZ $1, R0 -+ CMPBEQ R3, $16, 2(PC) -+ VLVGB R3, R0, T_0 -+ -+ // Set the message block in lane 1 to the value 0 so that it -+ // can be accumulated without affecting the final result. -+ VZERO T_1 -+ -+ // Split the final message block into 26-bit limbs in lane 0. -+ // Lane 1 will be contain 0. -+ EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4) -+ -+ // Append a 1 byte to the end of the last block only if it is a -+ // full 16 byte block. -+ CMPBNE R3, $16, 2(PC) -+ VLEIB $4, $1, M_4 -+ -+ // We have previously saved r and 5r in the 32-bit even indexes -+ // of the R_[0-4] and R5_[1-4] coefficient registers. -+ // -+ // We want lane 0 to be multiplied by r so we need to move the -+ // saved r value into the 32-bit odd index in lane 0. We want -+ // lane 1 to be set to the value 1. This makes multiplication -+ // a no-op. We do this by setting lane 1 in every register to 0 -+ // and then just setting the 32-bit index 3 in R_0 to 1. -+ VZERO T_0 -+ MOVD $0, R0 -+ MOVD $0x10111213, R12 -+ VLVGP R12, R0, T_1 // [_, 0x10111213, _, 0x00000000] -+ VPERM T_0, R_0, T_1, R_0 // [_, r₂₆[0], _, 0] -+ VPERM T_0, R_1, T_1, R_1 // [_, r₂₆[1], _, 0] -+ VPERM T_0, R_2, T_1, R_2 // [_, r₂₆[2], _, 0] -+ VPERM T_0, R_3, T_1, R_3 // [_, r₂₆[3], _, 0] -+ VPERM T_0, R_4, T_1, R_4 // [_, r₂₆[4], _, 0] -+ VPERM T_0, R5_1, T_1, R5_1 // [_, 5r₂₆[1], _, 0] -+ VPERM T_0, R5_2, T_1, R5_2 // [_, 5r₂₆[2], _, 0] -+ VPERM T_0, R5_3, T_1, R5_3 // [_, 5r₂₆[3], _, 0] -+ VPERM T_0, R5_4, T_1, R5_4 // [_, 5r₂₆[4], _, 0] -+ -+ // Set the value of lane 1 to be 1. -+ VLEIF $3, $1, R_0 // [_, r₂₆[0], _, 1] -+ -+ MOVD $0, R3 -+ BR multiply -diff --git a/ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go b/ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go -new file mode 100644 -index 00000000000000..4788950f19c710 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/poly1305/vectors_test.go -@@ -0,0 +1,3000 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package poly1305 -+ -+var testData = [...]test{ -+ // edge cases -+ { -+ // see https://go-review.googlesource.com/#/c/30101/ -+ key: "3b3a29e93b213a5c5c3b3b053a3a8c0d00000000000000000000000000000000", -+ tag: "6dc18b8c344cd79927118bbe84b7f314", -+ in: "81d8b2e46a25213b58fee4213a2a28e921c12a9632516d3b73272727becf2129", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "04000000000000000000000000000000", // (2¹³⁰-1) % (2¹³⁰-5) -+ in: "ffffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "faffffffffffffffffffffffffffffff", // (2¹³⁰-6) % (2¹³⁰-5) -+ in: "faffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", // (2¹³⁰-5) % (2¹³⁰-5) -+ in: "fbffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "f9ffffffffffffffffffffffffffffff", // (2*(2¹³⁰-6)) % (2¹³⁰-5) -+ in: "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", // (2*(2¹³⁰-5)) % (2¹³⁰-5) -+ in: "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "f8ffffffffffffffffffffffffffffff", // (3*(2¹³⁰-6)) % (2¹³⁰-5) -+ in: "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", // (3*(2¹³⁰-5)) % (2¹³⁰-5) -+ in: "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "f7ffffffffffffffffffffffffffffff", // (4*(2¹³⁰-6)) % (2¹³⁰-5) -+ in: "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", // (4*(2¹³⁰-5)) % (2¹³⁰-5) -+ in: "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "f3ffffffffffffffffffffffffffffff", // (8*(2¹³⁰-6)) % (2¹³⁰-5) -+ in: "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", // (8*(2¹³⁰-5)) % (2¹³⁰-5) -+ in: "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "ebffffffffffffffffffffffffffffff", // (16*(2¹³⁰-6)) % (2¹³⁰-5) -+ in: "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "faffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ { -+ key: "0100000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", // (16*(2¹³⁰-5)) % (2¹³⁰-5) -+ in: "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "fbffffffffffffffffffffffffffffff" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000" + -+ "00000000000000000000000000000000", -+ }, -+ // original smoke tests -+ { -+ key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", -+ tag: "a6f745008f81c916a20dcc74eef2b2f0", -+ in: "48656c6c6f20776f726c6421", -+ }, -+ { -+ key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", -+ tag: "49ec78090e481ec6c26b33b91ccc0307", -+ in: "0000000000000000000000000000000000000000000000000000000000000000", -+ }, -+ { -+ key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035", -+ tag: "da84bcab02676c38cdb015604274c2aa", -+ in: "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000", -+ }, -+ { -+ key: "0000000000000000000000000000000000000000000000000000000000000000", -+ tag: "00000000000000000000000000000000", -+ in: "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000000000" + -+ "000000000000000000000000000000000000000000000000000000", -+ }, -+ // randomly generated -+ { -+ key: "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649", -+ tag: "9566c74d10037c4d7bbb0407d1e2c649", -+ in: "", -+ }, -+ { -+ key: "81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f6999", -+ tag: "eaa270caaa12faa39b797374a4b8a420", -+ in: "eb", -+ }, -+ { -+ key: "9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f15f", -+ tag: "dbea66e1da48a8f822887c6162c2acf1", -+ in: "b90b", -+ }, -+ { -+ key: "adb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621632525", -+ tag: "6ac09aaa88c32ee95a7198376f16abdb", -+ in: "3fec73", -+ }, -+ { -+ key: "8dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d20bf505987592", -+ tag: "b1443487f97fe340b04a74719ed4de68", -+ in: "1e668a5b", -+ }, -+ { -+ key: "df2c7fc4844592d2572bcd0668d2d6c52f5054e2d0836bf84c7174cb7476364c", -+ tag: "7463be0f9d99a5348039e4afcbf4019c", -+ in: "c3dbd968b0", -+ }, -+ { -+ key: "f7172ed85794bb358b0c3b525da1786f9fff094279db1944ebd7a19d0f7bbacb", -+ tag: "2edaee3bcf303fd05609e131716f8157", -+ in: "e0255aa5b7d4", -+ }, -+ { -+ key: "4bec40f84c892b9bffd43629b0223beea5f4f74391f445d15afd4294040374f6", -+ tag: "965f18767420c1d94a4ef657e8d15e1e", -+ in: "924b98cbf8713f", -+ }, -+ { -+ key: "8d962d7c8d019192c24224e2cafccae3a61fb586b14323a6bc8f9e7df1d92933", -+ tag: "2bf4a33287dd6d87e1ed4282f7342b6a", -+ in: "3ff993933bea6f5b", -+ }, -+ { -+ key: "3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c7215a3", -+ tag: "c5e987b60373a48893c5af30acf2471f", -+ in: "b539eb1e5849c6077d", -+ }, -+ { -+ key: "bb5722f5717a289a266f97647981998ebea89c0b4b373970115e82ed6f4125c8", -+ tag: "19f0f640b309d168ea1b480e6a4faee5", -+ in: "fa7311e4d7defa922daa", -+ }, -+ { -+ key: "e7786667f7e936cd4f24abf7df866baa56038367ad6145de1ee8f4a8b0993ebd", -+ tag: "de75e5565d97834b9fa84ad568d31359", -+ in: "f8883a0ad8be9c3978b048", -+ }, -+ { -+ key: "83e56a156a8de563afa467d49dec6a40e9a1d007f033c2823061bdd0eaa59f8e", -+ tag: "de184a5a9b826aa203c5c017986d6690", -+ in: "4da6430105220d0b29688b73", -+ }, -+ { -+ key: "4b8ea0f3ca9936e8461f10d77c96ea80a7a665f606f6a63b7f3dfd2567c18979", -+ tag: "7478f18d9684905aa5d1a34ee67e4c84", -+ in: "e4d60f26686d9bf2fb26c901ff", -+ }, -+ { -+ key: "354cde1607ee294b39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be89904341", -+ tag: "3b2008a9c52b5308f5538b789ab5506f", -+ in: "79d3af4491a369012db92d184fc3", -+ }, -+ { -+ key: "9d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7649c6c93478009", -+ tag: "71c8e76a67a505b7370b562ba15ba032", -+ in: "79d1830356f2a54c3deab2a4b4475d", -+ }, -+ { -+ key: "63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924ae", -+ tag: "1dc895f74f866bdb3edf6c4430829c1c", -+ in: "f78ae151c00755925836b7075885650c", -+ }, -+ { -+ key: "30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752b3b827", -+ tag: "afca2b3ba7b0e1a928001966883e9b16", -+ in: "1d03e944b3c9db366b75045f8efd69d22ae5411947cb553d7694267aef4e" + -+ "bcea406b32d6108bd68584f57e37caac6e33feaa3263a399437024ba9c9b" + -+ "14678a274f01a910ae295f6efbfe5f5abf44ccde263b5606633e2bf0006f" + -+ "28295d7d39069f01a239c4365854c3af7f6b41d631f92b9a8d12f4125732" + -+ "5fff332f7576b0620556304a3e3eae14c28d0cea39d2901a52720da85ca1" + -+ "e4b38eaf3f", -+ }, -+ { -+ key: "44c6c6ef8362f2f54fc00e09d6fc25640854c15dfcacaa8a2cecce5a3aba53ab", -+ tag: "6f2a09aa76c9b76774e31ec02dcf7991", -+ in: "705b18db94b4d338a5143e63408d8724b0cf3fae17a3f79be1072fb63c35" + -+ "d6042c4160f38ee9e2a9f3fb4ffb0019b454d522b5ffa17604193fb89667" + -+ "10a7960732ca52cf53c3f520c889b79bf504cfb57c7601232d589baccea9" + -+ "d6e263e25c27741d3f6c62cbbb15d9afbcbf7f7da41ab0408e3969c2e2cd" + -+ "cf233438bf1774ace7709a4f091e9a83fdeae0ec55eb233a9b5394cb3c78" + -+ "56b546d313c8a3b4c1c0e05447f4ba370eb36dbcfdec90b302dcdc3b9ef5" + -+ "22e2a6f1ed0afec1f8e20faabedf6b162e717d3a748a58677a0c56348f89" + -+ "21a266b11d0f334c62fe52ba53af19779cb2948b6570ffa0b773963c130a" + -+ "d797ddea", -+ }, -+ { -+ key: "fe4e3ad29b5125210f0ef1c314090f07c79a6f571c246f3e9ac0b7413ef110bd", -+ tag: "27381e3fc2a356103fb796f107d826e7", -+ in: "58b00ce73bff706f7ff4b6f44090a32711f3208e4e4b89cb5165ce64002c" + -+ "bd9c2887aa113df2468928d5a23b9ca740f80c9382d9c6034ad2960c7965" + -+ "03e1ce221725f50caf1fbfe831b10b7bf5b15c47a53dbf8e7dcafc9e1386" + -+ "47a4b44ed4bce964ed47f74aa594468ced323cb76f0d3fac476c9fb03fc9" + -+ "228fbae88fd580663a0454b68312207f0a3b584c62316492b49753b5d502" + -+ "7ce15a4f0a58250d8fb50e77f2bf4f0152e5d49435807f9d4b97be6fb779" + -+ "70466a5626fe33408cf9e88e2c797408a32d29416baf206a329cfffd4a75" + -+ "e498320982c85aad70384859c05a4b13a1d5b2f5bfef5a6ed92da482caa9" + -+ "568e5b6fe9d8a9ddd9eb09277b92cef9046efa18500944cbe800a0b1527e" + -+ "a6", -+ }, -+ { -+ key: "4729a861d2f6497a3235c37f4192779ec1d96b3b1c5424fce0b727b03072e641", -+ tag: "0173965669fb9de88d38a827a0271271", -+ in: "5a761f03abaa40abc9448fddeb2191d945c04767af847afd0edb5d8857b7" + -+ "99acb18e4affabe3037ffe7fa68aa8af5e39cc416e734d373c5ebebc9cdc" + -+ "c595bcce3c7bd3d8df93fab7e125ddebafe65a31bd5d41e2d2ce9c2b1789" + -+ "2f0fea1931a290220777a93143dfdcbfa68406e877073ff08834e197a403" + -+ "4aa48afa3f85b8a62708caebbac880b5b89b93da53810164402104e648b6" + -+ "226a1b78021851f5d9ac0f313a89ddfc454c5f8f72ac89b38b19f53784c1" + -+ "9e9beac03c875a27db029de37ae37a42318813487685929359ca8c5eb94e" + -+ "152dc1af42ea3d1676c1bdd19ab8e2925c6daee4de5ef9f9dcf08dfcbd02" + -+ "b80809398585928a0f7de50be1a6dc1d5768e8537988fddce562e9b948c9" + -+ "18bba3e933e5c400cde5e60c5ead6fc7ae77ba1d259b188a4b21c86fbc23" + -+ "d728b45347eada650af24c56d0800a8691332088a805bd55c446e25eb075" + -+ "90bafcccbec6177536401d9a2b7f512b54bfc9d00532adf5aaa7c3a96bc5" + -+ "9b489f77d9042c5bce26b163defde5ee6a0fbb3e9346cef81f0ae9515ef3" + -+ "0fa47a364e75aea9e111d596e685a591121966e031650d510354aa845580" + -+ "ff560760fd36514ca197c875f1d02d9216eba7627e2398322eb5cf43d72b" + -+ "d2e5b887d4630fb8d4747ead6eb82acd1c5b078143ee26a586ad23139d50" + -+ "41723470bf24a865837c", -+ }, -+ { -+ key: "9123461c41f5ff99aa99ce24eb4d788576e3336e65491622558fdf297b9fa007", -+ tag: "1eb0cdad9237905250d30a24fe172a34", -+ in: "864bafd7cd4ca1b2fb5766ab431a032b72b9a7e937ed648d0801f29055d3" + -+ "090d2463718254f9442483c7b98b938045da519843854b0ed3f7ba951a49" + -+ "3f321f0966603022c1dfc579b99ed9d20d573ad53171c8fef7f1f4e4613b" + -+ "b365b2ebb44f0ffb6907136385cdc838f0bdd4c812f042577410aca008c2" + -+ "afbc4c79c62572e20f8ed94ee62b4de7aa1cc84c887e1f7c31e927dfe52a" + -+ "5f8f46627eb5d3a4fe16fafce23623e196c9dfff7fbaff4ffe94f4589733" + -+ "e563e19d3045aad3e226488ac02cca4291aed169dce5039d6ab00e40f67a" + -+ "ab29332de1448b35507c7c8a09c4db07105dc31003620405da3b2169f5a9" + -+ "10c9d0096e5e3ef1b570680746acd0cc7760331b663138d6d342b051b5df" + -+ "410637cf7aee9b0c8c10a8f9980630f34ce001c0ab7ac65e502d39b216cb" + -+ "c50e73a32eaf936401e2506bd8b82c30d346bc4b2fa319f245a8657ec122" + -+ "eaf4ad5425c249ee160e17b95541c2aee5df820ac85de3f8e784870fd87a" + -+ "36cc0d163833df636613a9cc947437b6592835b9f6f4f8c0e70dbeebae7b" + -+ "14cdb9bc41033aa5baf40d45e24d72eac4a28e3ca030c9937ab8409a7cbf" + -+ "05ae21f97425254543d94d115900b90ae703b97d9856d2441d14ba49a677" + -+ "de8b18cb454b99ddd9daa7ccbb7500dae4e2e5df8cf3859ebddada6745fb" + -+ "a6a04c5c37c7ca35036f11732ce8bc27b48868611fc73c82a491bfabd7a1" + -+ "9df50fdc78a55dbbc2fd37f9296566557fab885b039f30e706f0cd5961e1" + -+ "9b642221db44a69497b8ad99408fe1e037c68bf7c5e5de1d2c68192348ec" + -+ "1189fb2e36973cef09ff14be23922801f6eaee41409158b45f2dec82d17c" + -+ "aaba160cd6", -+ }, -+ { -+ key: "40ff73495fe4a05ce1202ca7287ed3235b95e69f571fa5e656aaa51fae1ebdd7", -+ tag: "2e619d8ea81b77484e4fddeb29844e4b", -+ in: "aa6269c2ec7f4057b33593bc84888c970fd528d4a99a1eab9d2420134537" + -+ "cd6d02282e0981e140232a4a87383a21d1845c408ad757043813032a0bd5" + -+ "a30dcca6e3aa2df04715d879279a96879a4f3690ac2025a60c7db15e0501" + -+ "ebc34b734355fe4a059bd3899d920e95f1c46d432f9b08e64d7f9b38965d" + -+ "5a77a7ac183c3833e1a3425ead69d4f975012fd1a49ed832f69e6e9c63b4" + -+ "53ec049c9e7a5cf944232d10353f64434abae060f6506ad3fdb1f4415b0a" + -+ "f9ce8c208bc20ee526741539fa3203c77ecba410fd6718f227e0b430f9bc" + -+ "b049a3d38540dc222969120ce80f2007cd42a708a721aa29987b45d4e428" + -+ "811984ecad349cc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b65" + -+ "2b69ccb092e55a20f1b9f97d046296124621928739a86671cc180152b953" + -+ "e3bf9d19f825c3dd54ae1688e49efb5efe65dcdad34bc860010e7c8c997c" + -+ "d5f9e320ca7d39d4ba801a175b1c76f057832f3f36d7d893e216e4c7bbdb" + -+ "548d0ba48449330027368b34f9c69776b4591532da1c5be68ef4eebe8cb8" + -+ "fa7dc5483fb70c2c896334cb1f9cb5dfe044fa086197ff5dfd02f2ba3884" + -+ "c53dd718c8560da743a8e9d4aeae20ccef002d82ca352592b8d8f2a8df3b" + -+ "0c35f15b9b370dca80d4ca8e9a133eb52094f2dd5c08731f52315d828846" + -+ "e37df68fd10658b480f2ac84233633957e688e924ffe3713b52c76fd8a56" + -+ "da8bb07daa8eb4eb8f7334f99256e2766a4109150eed424f0f743543cdea" + -+ "66e5baaa03edc918e8305bb19fc0c6b4ddb4aa3886cb5090940fc6d4cabe" + -+ "2153809e4ed60a0e2af07f1b2a6bb5a6017a578a27cbdc20a1759f76b088" + -+ "9a83ce25ce3ca91a4eb5c2f8580819da04d02c41770c01746de44f3db6e3" + -+ "402e7873db7635516e87b33e4b412ba3df68544920f5ea27ec097710954f" + -+ "42158bdba66d4814c064b4112538676095467c89ba98e6a543758d7093a4" + -+ "94df", -+ }, -+ { -+ key: "5cc36d09c7a6472a41f29c380a987b1ecdcf84765f4e5d3ceefc1c02181f570f", -+ tag: "0d57b8cbea8090df0541354673dcb4e0", -+ in: "44fcd629f08dc1ef53c9ae0d8869fe67fdc7a2c67b425f13c5be8d9f630c" + -+ "1d063c02fd75cf64c1aec9d2e2ef6e6431d5f5ad0489078dc61f46494dcc" + -+ "f403dad7f094170d2c3e29c198b0f341e284c4be8fa60c1a478d6bd55dd2" + -+ "c04dad86d2053d5d25b014e3d8b64322cdcb5004faa46cfa2d6ad2ff933b" + -+ "c3bd9a5a74660af3d048a9a43634c0250427d9a6219197a3f3633f841753" + -+ "ba7c27f3619f387b6b1a6cb9c1dc227674aa020724d137da2cb87b1615d5" + -+ "12974fa4747dd1e17d02c9462a44fec150ca3a8f99cc1e4953365e429956" + -+ "5e108535b1f62e1d4ba18e17a52164418bfd1a933f7fb3a126c860830a87" + -+ "293d9271da736e4398c1e37fb75c4bf02786e1faf4b610cd1377fbb9ae18" + -+ "0655a0abefbad700c09473469f1eca5a66d53fa3dc7cd3e7c3b0411d7e14" + -+ "5f96eb9654ab94913dda503a50f9e773842f4d2a5faa60869bf365830511" + -+ "f2ededd03e0a73000edb60c9a29a5f5e194cf3b5667a694690384599d116" + -+ "f8d2fd93b2aed55b7d44b5b054f3f38e788e4fdf36e591568c41d1052cad" + -+ "0fcb68ca4c4bf5090d57df9db6f0d91dd8b11b804f331adb7efb087a5604" + -+ "e9e22b4d54db40bcbc6e272ff5eaddfc1471459e59f0554c58251342134a" + -+ "8daaef1498069ba581ef1da2510be92843487a4eb8111c79a6f0195fc38a" + -+ "d6aee93c1df2b5897eaa38ad8f47ab2fe0e3aa3e6accbfd4c16d46843318" + -+ "5fc61c861b96ca65e34d31f24d6f56ee85092314a4d7656205c15322f1c9" + -+ "7613c079eae292ba966e10d1e700164e518b243f424c46f9ea63db1c2c34" + -+ "b512c403c128ee19030a6226517b805a072512a5e4cd274b7fd1fa23f830" + -+ "058208ff1a063b41039c74036b5b3da8b1a0b93135a710352da0f6c31203" + -+ "a09d1f2329651bb3ab3984ab591f2247e71cd44835e7a1a1b66d8595f7ae" + -+ "f9bf39d1417d2d31ea3599d405ff4b5999a86f52f3259b452909b57937d8" + -+ "5364d6c23deb4f14e0d9fcee9184df5994fdc11f045c025c8d561adb0e7d" + -+ "fd4748fd4b20f84e53322471a410cdb3fd88e48b2e7eb7ae5dae994cb5ea" + -+ "e3eaf21cf9005db560d6d22e4d9b97d7e9e488751afcd72aa176c0fcde93" + -+ "16f676fd527d9c42105b851639f09ea70533d26fc60cbeb4b76ed554fc99" + -+ "177620b28ca6f56a716f8cb384", -+ }, -+ { -+ key: "811c3e356e7c793acf114c624dc86ace38e67bff2a60e5b2a6c20723c1b9f003", -+ tag: "c6e59044cefc43ee681c3eed872d02b3", -+ in: "e115b304c023792448794546a2474f04294d7a616215e5dd6c40a65bb6ed" + -+ "b508c3680b14c176c327fdfb1ee21962c0006b7deb4e5de87db21989d13c" + -+ "3ab0462d5d2a52ef4ca0d366ae06a314f50e3a21d9247f814037798cc5e1" + -+ "0a63de027477decdeb8a8e0c279299272490106ddf8683126f60d35772c6" + -+ "dfc744b0adbfd5dcf118c4f2b06cfaf077881d733a5e643b7c46976647d1" + -+ "c1d3f8f6237c6218fa86fb47080b1f7966137667bd6661660c43b75b6339" + -+ "0b514bbe491aa46b524bde1c5b7456255fb214c3f74907b7ce1cba94210b" + -+ "78b5e68f049fcb002b96a5d38d59df6e977d587abb42d0972d5f3ffc898b" + -+ "3cbec26f104255761aee1b8a232d703585dd276ee1f43c8cd7e92a993eb1" + -+ "5107d02f59ba75f8dd1442ee37786ddb902deb88dd0ebdbf229fb25a9dca" + -+ "86d0ce46a278a45f5517bff2c049cc959a227dcdd3aca677e96ce84390e9" + -+ "b9a28e0988777331847a59f1225b027a66c1421422683dd6081af95e16f2" + -+ "48ab03da494112449ce7bdace6c988292f95699bb5e4d9c8d250aa28a6df" + -+ "44c0c265156deb27e9476a0a4af44f34bdf631b4af1146afe34ea988fc95" + -+ "3e71fc21ce60b3962313000fe46d757109281f6e55bc950200d0834ceb5c" + -+ "41553afd12576f3fbb9a8e05883ccc51c9a1269b6d8e9d27123dce5d0bd6" + -+ "db649c6fea06b4e4e9dea8d2d17709dc50ae8aa38231fd409e9580e255fe" + -+ "2bf59e6e1b6e310610ea4881206262be76120d6c97db969e003947f08bad" + -+ "8fa731f149397c47d2c964e84f090e77e19046277e18cd8917c48a776c9d" + -+ "e627b6656203b522c60e97cc61914621c564243913ae643f1c9c9e0ad00a" + -+ "14f66eaa45844229ecc35abb2637317ae5d5e338c68691bea8fa1fd469b7" + -+ "b54d0fccd730c1284ec7e6fccdec800b8fa67e6e55ac574f1e53a65ab976" + -+ "4c218a404184793cc9892308e296b334c85f7097edc16927c2451c4cd7e5" + -+ "3f239aa4f4c83241bde178f692898b1ece2dbcb19a97e64c4710326528f2" + -+ "4b099d0b674bd614fad307d9b9440adab32117f0f15b1450277b00eb366e" + -+ "0260fca84c1d27e50a1116d2ce16c8f5eb212c77c1a84425744ea3195edb" + -+ "b54c970b77e090b644942d43fe8c4546a158bad7620217a40e34b9bb84d1" + -+ "89eff32b20ef3f015714dbb1f150015d6eeb84cbccbd3fffa63bde89", -+ }, -+ { -+ key: "f33691f5db2dea41e1e608af3ff39f3a6988dba204ce1b09214475ae0ea864b8", -+ tag: "6e50e70411201378c8d67857d7b631d2", -+ in: "439bc9ea10db4d2b08c7fcf2e8bd89fa9844f8061d462e28f174489e7514" + -+ "0f84e842040141cc59ce38f9551850cfbdfac2d75337d155090d70d0d930" + -+ "04340bdfe60062f17c53f3c9005b9995a0feb49f6bef8eaff80f4feb7ef3" + -+ "f2181733a4b43b6ac43a5130a73a9b3c2cbc93bd296cd5f48c9df022b6c8" + -+ "2bb752bc21e3d8379be31328aa32edc11efc8a4b4b3f370ee8c870cd281d" + -+ "614e6bc2c0a5ca303bc48696a3bd574ee34738de4c4c29910f8feb7557bf" + -+ "ffcfe7428b4703144bd6d7fe5b3f5de748918553df5453b3c6001696f3de" + -+ "0137e454aadf30cedfb6be36b0b908a38409f1a2dc202fc285610765e4c8" + -+ "6414692bf4bde20ed899e97727b7ea1d95d7c621717c560f1d260ab3624e" + -+ "d6168d77c483dd5ce0d234049017795f2e5a7569d7ad323c50a5b1170337" + -+ "4174a9977026c20cd52c10b72f14e0569a684a3dcf2ccbc148fd3db506e2" + -+ "8d24f6c55544cb3980a36e86747adc89ebad78d1630618d113fa445f8625" + -+ "b583cd7be33913c30c419d047cf3baf40fd05219a1fcec717b87a65fa022" + -+ "1a3aa8143062d77588168019454240ae3d37640996f2967810459bc658df" + -+ "e556de4d07263dc3d9158ec242008226d1c6aea7f0846e12ce2d316e80da" + -+ "522343264ec9451ec23aaaa367d640faad4af3d44d6d86544ade34c93518" + -+ "2843f6b4d1c934996778affa9ee962e7dfef5e70d933d4309f0f343e9606" + -+ "1b91b11ac380a9675e17a96099fe411bedc28a298cd78d5496e28fbbd4f5" + -+ "b0a27735d1144348e22be5b75724d8f125e99c4cb4e9c3a1f0b4e9da5146" + -+ "e6afaa33d02fda74bf58a8badee2b634b989c01755afa6ab20ee494c6ae4" + -+ "c2c6f17af6b53b61d2947d83a18eb3b8a1612aad5d3ea7e8e35f325c9168" + -+ "ac490f22cb713ddb61fbd96011c5849ac8e2fcd42db820349bdf9157dcc0" + -+ "0d9f9ed9c099b10c7194d48b623b0df43759734b2a2e5f8a35e7192bf9a0" + -+ "03dcb9d16a54bd84d922f85b6021b28aacc5264fe9e83deb48f18f864cbd" + -+ "367eb163d39c45b0eb907311a2a4b09fb26109088df782ce031b02f3caff" + -+ "d2dbe25b1cbde9f35ba7c47292a4fd49e7def7a28824f3dfda259a86c3de" + -+ "59257c255c712686ee47d128a55c7b9e8c546035eab7e2da420f32ed5c94" + -+ "bc12a34dc68eb99257a7ea03b69d6c760b0681fa24e4ca97b7c377182ab5" + -+ "fee30a278b08c44c988a8f925af2997883111c750d176b432735868208f4" + -+ "0de7137331b544f2d28040a3581d195e82811c945c3f9fde68fc21b36a44" + -+ "e1cfa2d8eb625f3102461539b3f13c660936a5ddb29a0ae791fbf52c2f69" + -+ "7bd334653f3605b362d91cd78569b41dbd09b2a5892440b5097fa08d0b4b" + -+ "291fc5b934585dd8d5adc80d573fdd194b2eae26dfc49f5e51c1f1607d7e" + -+ "87740702f244bf39ca1d52423e0ae84891dfdf4f43ef984c7a5f293a2007" + -+ "a1e00e39c757f064518953f55621f955986f63", -+ }, -+ { -+ key: "d115b6ac998a65b48b3dae5977abaf985258d3d1cfe1616cec3d6a77f7a75785", -+ tag: "b431c9318ec2769fc8ee8f5fc3c079c3", -+ in: "7e7eb43839a6d7616b8a7b1fb7144817904342a9bd34167051162941a6b1" + -+ "b85db5e587f76e4a53211755d5ab29c11822d7711a97b3f1ff5b21f2485d" + -+ "9c86241fb56cdd6796245d3112df11ad9a7344db44d09934c4efb280ed65" + -+ "80cfcafb5c97a32993cbbf4917183e0b7bb38f2ce2479c28e1d39f673962" + -+ "17a7010448dfd39a4e7f406c8bd2d804f993bb410fffa4eb57518a531ecf" + -+ "259a8af068230acb826d9ffc20ee0fc43885221a321e3928971bb28615f0" + -+ "d9f099f5b68a80503a910fdba0bc643c60b64837900be38770b6b30c362c" + -+ "4580722b5dbb1b9c8cd02a18fd7b5661d2c4d28aa941c50af6655c826690" + -+ "37312fbf9f1cf4adb0b9400532755011b40e8252bd0e3c7a22efb0ef9122" + -+ "1e04b4aa8316d4a4ffeaa11909d38cc264650e7ca416835ded0953f39e29" + -+ "b01d3a33bba454760fb0a96d9fe50b3e42c95271e57840380d1fd39a375b" + -+ "3e5513a31a4b80a2dad8731d4fd1ced5ff61e1fbe8ff3ff90a277e6b5631" + -+ "f99f046c4c3c66158554f61af2ede73aede97e94b1d1f129aaadf9b53548" + -+ "553cc2304103e245b77701f134d94d2a3658f2b41108c5a519c2c8f450db" + -+ "027824f1c0ab94010589a4139ff521938b4f0c7bf0986585f535b6e292e5" + -+ "b3ded23bf81cec17c8420fe67a449e508864e4cbb7eaf335975668f013e9" + -+ "da70b33bd52a72094a8f03762ea7440ce9fcd10e251837cfc9ccc1a8cc47" + -+ "0c67379f6a32f16cf70ea8c19d1a67779a9b2d2b379665e0e908a88b26e7" + -+ "8c9f94f17acefa6d5feb70a7095e0297c53e091cf98df132a23a5ce5aa72" + -+ "59f1154b92e079f0b6f95d2a38aa5d62a2fd97c12ee7b085e57cc4652863" + -+ "8defacc1e70c3aceab82a9fa04e6aa70f5fbfd19de075bee4e3aac4a87d0" + -+ "ad0226a463a554816f1ebac08f30f4c3a93fa85d79b92f0da06348b4f008" + -+ "880fac2df0f768d8f9d082f5a747afb0f62eb29c89d926de9fc491921474" + -+ "1d8647c67d57ac55f94751389ee466bbd44dbe186f2f38abbc61a0425613" + -+ "e9b6a64e6bcb45a2e2bb783b9103483643d5610a7e2dcdb10b5d78423285" + -+ "506b42a99b00a4fb7b619b4526bb4ec78299dd01ad894fde2f053e18c55b" + -+ "6047f86333f2690c2cb8e87d9834ab8a5e339aa346e4d9952ed62dc083e3" + -+ "b11a823a67f23fec099a033f127ebe8626a89fa1a5a6b3520aa0d215a8e7" + -+ "dea3af37907686c16521739a95d6c532cc259c497bf397fceaea49cd46b9" + -+ "ad5c1b39a36fdd2f0d2225fef1b6ca2bb73fe604646c10ba4c572ab13a26" + -+ "559ededc98f5a34c874cc25621e65ba4852529b5a4e9c1b2bf8e1a8f8ff0" + -+ "5a31095b84696c6381eb9ad37ac0db184fe5fccf3554e514946a33cabe6f" + -+ "4d617b549d28ad1cc4642dac96e0215ee1596481600d3619e8f45e2c9ae1" + -+ "da834d44aca216bba0efef6254503ca90339f2d7ca508b2722d50c08def8" + -+ "a736590fa44855cd9eb9979c743783aa26e633696739f2ae25ff7b72ceb2" + -+ "4dff4455b85bbd675c8cb71ad18386dc58c371bdf37b4b3875b98a9423ff" + -+ "3becfc0d0ba2aacab3ee7683cb3b345095fefcaca5751ca793da63c89428", -+ }, -+ { -+ key: "f3717306b9729be998cdb2c9d856306c5ae3d89da2cdcef12f86f6110c98d873", -+ tag: "907dba0f4849c7cf4570b5128b5f31d5", -+ in: "079572187d4559f24d8e48dc366441acf226a4db79e214ec3ee288acc349" + -+ "887e2e377419bcafa377d0151497b52e4d9cf2a02b0fc91ad9516482bdf6" + -+ "eccd1497954b53241bfb0bc5c04cc45045c6251f23a510060fee32721872" + -+ "bbc95cd8d400dff00bcac2ecce6229c7d73d8f85ed5a87afdccf6dedd299" + -+ "2d5c7b5b8090c47c737ded036ff0e9aedf02a2242fd9820be618b9601e73" + -+ "d3ba5d8f1ae9805cfd2306251704bc74e3546997f109f1dfae20c03ff31f" + -+ "17564769aa49f01233c9c4b79f90fa3d1433d18cdc497914046ad77d2792" + -+ "2588a7d0e61d4258d7d80cdab8503e3111ddca22cf7f39c1f80f1e16a68d" + -+ "9e21db8b53dd316dfa4233cb453a39a90101c60efc08514a3057db007e96" + -+ "507745bd4a0764ed8717a250bffb5fd1ea58474bdfb5b869681939693926" + -+ "40d832a3387ed4ac9cdab0d2af8fcb51b86e4d927097f1e79b5af96574ec" + -+ "d59d0dd150a0208978c41de28ad6cadf72a49279cffd6dc281c640f2e294" + -+ "4cde49a13ed390da1dd92e3011ce0f4a0863375a9db3f67fca1e3b8288a0" + -+ "78611161d7cb668ecdb932e1ff3733982c8c460eeeff2bca46c96e8a02cf" + -+ "b55d770940de556373a4dd676e3a0dd66f1280c8cb77a85136b3f003fab4" + -+ "887dad548de7bfe6488ae55e7a71da4097db03900d4b94e776a939530328" + -+ "83492da900b2a6c3e73d7a6f12ee30c9dd06cc34e5a3893976eb1de5864d" + -+ "32e792ac02e68d052d9d0cfc7cfb40b77728422f6c26cf68987c6b40fcfe" + -+ "9d660abc657360eb129de11bd70af5eb8fe350af2c27a6ece2cdf81b94c8" + -+ "0e68e8c51106497cfa5171236efe2d71d76b5dff3352af9b407dc5aab60f" + -+ "46b5683646f5b28732b7c750d351a08a507243d8e437cc4bef13a3edaa20" + -+ "5fc4e9968b4e563fa0dc965ba20b8e48bc188a321b16d3213bed69647512" + -+ "7a20afc1a3680ef261df6d37b017dee05cfc3a42e4130216e5540cf715c4" + -+ "e638d7d615c50bef576eeb19b3b15b2c2b454dfcef2b18161a143ddf52fc" + -+ "8e88fa71cbe34c92cd4b5a0adc81e5c33e11d2721bc1b95a9e693ac3cabc" + -+ "490889a8a42bf7e22375b679e8598c8faef22a006ed2da8ab1c08aaed2f5" + -+ "6d6f26649036335c0881bfec1e3a5346335c3b3707ee92173f1a7a3305c2" + -+ "933f78e995da8f1df64daf12b81ce23c8813c27fd4551103dc33561c2e80" + -+ "45b6b6770fa03498fd359a104884699d628020173edbcc4398b977e456e4" + -+ "885964840466176a490e7c513ba5d66090277c1ab1632a995a54f555a452" + -+ "1170a000507865b6650730aa6d6050a55959102836fff3d37e4773340e59" + -+ "2e56951ff9652519de4421d9c5b63edbeb30a3852a1ea110a9a29721aee3" + -+ "23d5a306de1624cecc87badc47aa87f489635d2fb60bff62ba67f5257999" + -+ "6af0a1f1a6fbcd8704e119196fcc289a6db6a4170a2cae31a1d30744b702" + -+ "2536d1526d41659c2dcc8b39c26aecfc0f8a707136d81b2827a158fd7386" + -+ "a537514471c213a8c859016748e0264cf3fbde10f40c620840ec4df99432" + -+ "e2b9e1e368e33f126ec40c572e841c2618d49d4eb098b9533b1f4ae00b46" + -+ "8d15de8c8ab6d0b650e599576f2bd90a124c9c6a0f911fd1bd8253bac272" + -+ "942cbdf8864f3747ff7f09d8a5a9d8599be7ee1744e5f1faf3e526cd2a06" + -+ "b157527272af9d38565957c9ce663c295766c0e0e464971c6282b70d4c0c" + -+ "1fb3b69856b34c089ad2b2c745f5a033cee1429c5b855581ee285278893c" + -+ "43a5968d9c28384b7abe8d072ba69089c938685cb1eab461f05314ad6d06" + -+ "eaa58512f8738bde35b7b15ef359dd2e8753cb1ed6", -+ }, -+ { -+ key: "9772c1a4b74cbf53586e5df04369b35f1fdca390565872251bc6844bc81bda88", -+ tag: "68eb7fc459ecc3be819485001ab438dc", -+ in: "e115cc2f33e367cb85c01a914b3a512404ad6a98b5b0c3a211d4bffd5802" + -+ "ee43b3fb07451c74524ec8b4eddbb41ca33dd6e49791875d716a44bec97b" + -+ "7c2d4546616939ffa3b1ab9b8ba1d1a637e7c985cc922606caa0453085e3" + -+ "5f2fe0bd2de129d1d1856ade975a3281a62965927d8bb695e54514e69558" + -+ "89361a2a00a1b24e62bda78d0b71a0d40147016fcdaf1a702331dda8e678" + -+ "d8f476dcc91698da1688c610ec0cb1d9b8fbcd45dfde6d1503ba60a01337" + -+ "ae5b2f5c854a82c3087779babd2e522dd92f4718cd9f8c649ac226745ca2" + -+ "fa1696442764758f67cd926369578ae87612790dc56ed9cda935281a490e" + -+ "5c984950ec7a4e930520d273a69da4ed3a330e532508e26f942961fed0e3" + -+ "efeed52a7b96250d723155aa39a8ae85131c255c32bf406b647de1a37fba" + -+ "dc61e302bb5b70adec4505ee66b3a1d1b7bfe9c58b11e53ad556d56e5807" + -+ "017bb30b71be94e8f86aaf1496e8b8d6db75ec0afbe1cd336c23963c745d" + -+ "7b4ba1787ceb30728f1762b46f6eaad5064c8029d29b86266b87f93142a2" + -+ "74f519f3281d8c1cb43c23eb184ae41f3f625cf624b05a48d73cd7783fdf" + -+ "14954a03ec1a930e9a954424eff030e3f15357de4c19983f484619a0e9e2" + -+ "b67221cf965e9aa8d8926595c793adfe0181050df8b845ce648a66df532f" + -+ "78b10c83ecc86374a4f8abf8edcc303654bafd3dcc7de9c77a0a9d1d98fb" + -+ "121534b47d16f75b55fdc2a5e2e6799f8a2f8000d4292282e56863ae422a" + -+ "5779900ad6881b78946e750d7777f33f2f013a75c19615632c0e40b98338" + -+ "1e9b8d35a26abe30242c45662eebb157e6d7a8a5519de60268ac289b8295" + -+ "5d4feb47b9eef6da65031c6f52c2c4f5baa36fce3618b6a331f1e8bdd621" + -+ "48954fcf0846afeeb0a6cadb495c909a7fe671b021d5b0b4669961052187" + -+ "d01b67d44218471bfb04c1a3d82bf7b776208013fc8adabaefb11719f7a7" + -+ "e6cb0b92d4cc39b403ceb56bd806cbdcc9ee75362ab4aaeb760e170fdc6a" + -+ "23c038d45f465d8ec8519af8b0aad2eb5fae2972c603ed35ff8e46644803" + -+ "fc042ff8044540280766e35d8aaddcaa81e7c0c7eba28674f710492924c6" + -+ "1743da4d241e12b0c519910d4e31de332c2672ea77c9a3d5c60cd78a35d7" + -+ "924fda105b6f0a7cc11523157982418405be0bacf554b6398aeb9a1a3b12" + -+ "fe411c09e9bfb66416a47dd51cbd29abf8fbbd264dd57ba21a388c7e19e8" + -+ "12e66768b2584ad8471bef36245881fc04a22d9900a246668592ca35cfc3" + -+ "a8faf77da494df65f7d5c3daa129b7c98cef57e0826dee394eb927b3d6b3" + -+ "a3c42fa2576dcc6efd1259b6819da9544c82728276b324a36121a519aee5" + -+ "ae850738a44349cdec1220a6a933808aee44ba48ce46ec8fb7d897bd9e6b" + -+ "c4c325a27d1b457eb6be5c1806cd301c5d874d2e863fb0a01cbd3e1f5b0f" + -+ "8e0c771fca0c0b14042a7b0f3ae6264294a82212119b73821dcfbbfd85bb" + -+ "625b6f75e4dc0ee0292ab4f17daf1d507e6c97364260480d406bd43b7d8e" + -+ "8c2f26672a916321b482d5fa7166e282bfeed9b3598c8f8c19d2f8c8b98d" + -+ "f24c2500c8ad41cd6ed3f2835737916d846f1a6406cda1125ed7740fe301" + -+ "d1144559b7c95fa407599ae40a795226513153f86c9b8abe7d8aa6963c99" + -+ "5646ec586cbf20a03a698cc0681b7bd333402d00fa8e15cb32300b5a24ea" + -+ "316c5e1df67de78891846cb9183a4b112c3bcc17bcaa5fecd6c1dbbf6ef8" + -+ "272d9269e7f0ba9f17050a6aa5f11cb28874360396ab647941f2c9a85cb0" + -+ "6a969919b16997b0827af8f909c614545f1ad638ebb23109f6bab6b49b22" + -+ "b2285cabbb998b3e1bf42771b4d4e52330b224e5a1d63169ec85fe1c7dd2" + -+ "46dbafa6138448420f463d547a41c2b26026d4621b854bc7786ab3a0a93a" + -+ "e5390dd840f2454028b7c3bb87680f04f084089bbc8786ee42cf06904d01" + -+ "7e405144d2fae141599e2babe71abfbe7644fb25ec8a8a44a8928ff77a59" + -+ "a3e235de6bd7c7b803cf3cf60435e473e3315f02d7292b1c3f5a19c93646" + -+ "3cc4ccd6b24961083756f86ffa107322c5c7dd8d2e4ca0466f6725e8a35b" + -+ "574f0439f34ca52a393b2f017d2503ba2018fb4a0991fddc1949832d370a" + -+ "27c42e", -+ }, -+ { -+ key: "d18a328b63a1d0f34e987682fe6ca3d48b4834b4312a17e99b3d88827b8d2238", -+ tag: "938b43b80cb3935e39b21dd8ba133cf8", -+ in: "bc2b0baf92580ee6c5efe640f2a029a791a3c77bec459be74cbc30931508" + -+ "d9f312c3a0944212831cbe4fc92e8f107f2f750c91bcc09f7624fa9a09b4" + -+ "9b7712cf5d619ea9da100fc23068ae2f4e353047e3956b215884bdb12235" + -+ "3f06b8ee98f36c3212493d61ae9ce151cd0453f3075b18a12d7d73da3de7" + -+ "dc2d98376cfb420069ca8148c511ca6bbae57572394a3c615a6fefb30c5f" + -+ "d727f964b4065ac9ee252bdd2bcae3e70162fe0e8069974e073f0a093d45" + -+ "be52d7de16a8f5f65c548aa6525822ffb00dc642530fedf355f7188ef017" + -+ "56384760c80afb61ad903d10119a7d615ec4fbdc79c490160bdeaf200915" + -+ "e405f2a921a2380c0ab9d2ac1e4fdc8ec4b907368c004458598efac13dc7" + -+ "2751e7faded538e3dc8b16590cac9b7ec294da0ad53e22cb9c05d8ef494f" + -+ "a04f6ab7c843c867fbe3cf1b4eb146d65339b0b03392259f12627a8e98e8" + -+ "0f4896c30b8ecd210acb2365539a872541921dcd8e1e54caf4936dfc7e1f" + -+ "68f3bbce61d325b447a8cce7f0fcad28494f2e47dae46b136594b5dfca7a" + -+ "bdafd6856f91496c05b21079aa55aa8c41628220a2cf0cdd755893375b7b" + -+ "b13d914c9a1d1db4a18f8fa36c55e52d0342352052032fb62d32fcd51cb1" + -+ "ac46f44b06e682db5d96d583cda03b966c650c03ae53542e8da1066b6884" + -+ "4a7e2280c664415e413f270b1fdcfbb40b9daa6131d071ee7eb1553dc5b1" + -+ "a50677971223dc316d2d326d57cbd529c88698facdca425e2d5c6b10d7ae" + -+ "cae28b8890aa44ede9b9193dbe8d1d8aa1fa580ca384b57eadcbefc96dd8" + -+ "bfccbe3b855a96f1fd4913035f817b75954ef1827c7718aab24d353e41cb" + -+ "a73748e14e0c2750d5b6a9752125708cc7ee7a498c7fbadf4186e7f8fa93" + -+ "bfdf281a49400f877621651b8ba87edda5231e80b758564e75139b61b1a9" + -+ "9fb9ec694f928ab1f47c6c4287bd4182d1b2be053380616e98da06f3ef57" + -+ "b570ade17c51da1d602b6ebc5a638ebde30d99bf4f91d0e01557c7dcd8f7" + -+ "9e5120143c935fc699eb5616ccd3cac56b5f8a53ed9e6c47ba896bfefe71" + -+ "2004ad908c12cf6d954b83bec8fb0e641cc261ff8f542b86e62d90e227f2" + -+ "a5bd59c9d390c0dd857f6da2b7624787a0bb31908bae84896890b283da61" + -+ "d8ec4f56eea38b22b438d6374b42243f9c1d94288874e53ab90c554cc1f1" + -+ "d736acde67aff55007fd4b3becc4d0f3ddd96f10dc75255cb0327aa47076" + -+ "2b3a3a656e33c87b02a682658b6cd2a75d9c0462803c9bbffa51441501a0" + -+ "3a2fbb2344aa13d27ffb9e98704ea6720b6a9992e53449688cd74d0648fa" + -+ "e8e776b0ea6bf048b2ec05341e5948cab0af015328b284ae7bd89a5f763c" + -+ "eaf5ca3e647a9f5bff7197e4d357e4359fa5fe30709545453149be510e3b" + -+ "ff86beeba5110c79c0215fbe9ac9339a8ac7d41f7488588ab14ac657aaf7" + -+ "d5c03a353932bbb2b261f0e83f3526c5e8e0c2348a10ab4eed6ecdcf9014" + -+ "7550abcb0a722f257e01d38bad47cdd5a64eef43ef4e741bf50da275720a" + -+ "0aee47adfc5cd2534b911dc269197c3c396820b303f6941e3fd85b5ed21d" + -+ "6d8136745c3eeb9f36b1f226434e334dc94be8a5606079cb7643136aacd2" + -+ "da9c38b2eb7e2b898bd8632003767bf0c87d00a3c2fcee48bbbcdd949af3" + -+ "3455128216709df25879b0ce894ac4f121dfca6b8c7865002b828696641d" + -+ "14ffc59924fbda50866fded0afaea545c8008c564a3a0b023f519a9980ea" + -+ "d541d91d1c07a739fd02286ea5660e473f80494236a68e84ea31aad71348" + -+ "e45055ded69c39941e31d51df257a4d0b0d8f025dbedee093f2b91795bc1" + -+ "533dc472020769a157a187abd6d8d52e1693e2ef56b2212759d0c0120e54" + -+ "c425d0084fdb3925e296dd6cdd8e677043a90674904057d88ebdea5998aa" + -+ "03562a790adecc4399352df43e5179cf8c584d95ef8e4b37295946b1d37f" + -+ "faf4b3b7b98869184e42ea8b304fe1059f180ff83d14a0861ca7c0682c34" + -+ "b48a70df8653bd8d9a26f9489e1271fa44e41b392e648d0e619ecdad2c53" + -+ "952094802eeb70ade4ffe096e3049867de93a824217e31364b18204e9681" + -+ "dd8e84ae2678aad155b238f59dd9bf9ce07e97183a690b2a46a8f3624843" + -+ "5b2f713e7d8dcda4dea1e3c4cf9692dda082322c51f7bb1f63d92aa987ec" + -+ "cf1355a043e21a7b8d60a2b97f18487f6fff4c77df92dbfdc9837540c518" + -+ "9fd9585731bc6e726a34ca21154b0499522c9d1016953dd0fa2eb6a92b6d" + -+ "14d6e3da5c12fabe92bd639e253983fc91041091791643", -+ }, -+ { -+ key: "46e8eb27acfdc8f4be622d8741c7bc414464c149e21da97ab4afbf3e07b98b0e", -+ tag: "56b5f49be824c7a19b19faabf0787a87", -+ in: "ced52b76c057872a60107194b432cf04b7be05e65209045d2952ea0284d8" + -+ "3e2ed5a15cfdc58071204573c18ab03765b4d5e63a601419e039c42075b2" + -+ "7ebb2827de9c6233d6632e6d3db9140bdb4a9291d53f33734c2dc8e24df9" + -+ "0764dc10e0d321d20fdf659bfa2a81bc9e04fd0f83448143276647c08bfa" + -+ "dcfe3bc23898eda655c9353693ed7b022f43eefa23c21db7660c5029ca64" + -+ "a6085d93029ea6c43197356f56b7624d4819f5008d053357d981ffbe7f40" + -+ "96d6c55d8417002d36189b04bbb2c637339d90f4910a400833a8d422d88d" + -+ "c816c1636e8d9f7f926c244a28d9e0a956cec11e81d0fd81d4b2b5d4904a" + -+ "d1a5f55b5ec078dcb5c2bc1112bbfd5efc8c2577fe6d9872a985ee129e5b" + -+ "953e9cebf28cf23c6f9c6a5e09cb09ab586c6a50e4389cd3110777591d7f" + -+ "0608a3fd95b99f6ba03984fb0e13c6bbbde3668c59f2f2b69d7caadffa94" + -+ "6f67e725d56280e59e66dca025a18d4616e81abd9801835bd94485bb2025" + -+ "dee81fba440005b181ee81dc1d7796cbec92e4ec1c9016c8e8073cf281ce" + -+ "f749993f09a618a4671d58b476feffa454600f82955c591882715148a826" + -+ "586f68bb50059914dce1c1c85e5e3951647c9964ec9316005209a58baeb5" + -+ "2c6d01e6b4c275c0050a7e2bdc52133e433b050a700b556d4314e5c041d1" + -+ "93ee47f47adc971aed1b63259dd5cd4f95854a71a947eae3d3d12d0d7b52" + -+ "c6cd2fef2d2e892607a9681d73ac3236fad21ee30a4f857010bc95c00d5f" + -+ "6f0c6b3fe50cd6452be6eec4f5f01542dc2cb5e2db1f52224f11348fe2a0" + -+ "5d1e5885f1317f2d06ce2813dc4c723008e836a2ee95d0aac66855fe4c3b" + -+ "1b2e02ba0700be759b1ef1c2a3123ee4ccf9200d8d4de5e0d503f04c2053" + -+ "66393d1e91b648392ca28389d976aa618b4796acbfe8aa356ecdce1f7786" + -+ "bf09af226bb9402317b6fa319bbb9248d8ce00b1f49f066c69d4df93266b" + -+ "938342cd7fd4b07c320c2409ef72d8a57c21d0c6d6d493f7ca94d01b9852" + -+ "e4fca6a9291e9060154bc38af6c86932645f53914709fc90e11db56ec471" + -+ "6d600ee6452041248ea8244f79534f793bfc1f2020855d817cb4ca3c48ea" + -+ "7f6441ce9af9bda61936c226d810086c04a35e8654fdc30d4b35701adccc" + -+ "016d5895b2121ba4066e44d694f6371d97911786edb73dc3020ba186a01f" + -+ "ee3dd6036c0e205a8d05979bad228fd12c0fd2fded6c7f1e4c11354d266e" + -+ "d9c2f706269c43cd90504997d93a17b39b10dab0ff083ab3bd06540ce612" + -+ "d08f46ce75a16ef330525737410a0d98fb3d484968f9c12edcaf50103fdc" + -+ "c14128ea4ad6c30b56247eab28197fe617e5f88afa5cbe003c63d423647a" + -+ "d3042626fafd2084a0582ff1b1efdb5baa162662048019546234e2f6b6a1" + -+ "d8bb971114aae41df7795b4f3598f2af9e8921a9aadc7fab6c780aaa32a3" + -+ "84865a4ccb02351dbc55ec92a3152d1e66ec9d478be5dca17b4a131b4a0d" + -+ "3d4420fc6123fef80fd56ca266407d58a7880d6b7e5ce2b6bdc9a3721071" + -+ "7feec573d83c83a2e3f7d4023f2f68e785cde728fdbf5054060e4c89faa6" + -+ "1c9dd10524a08811d15c627b3b4ada549a3fa1d8dd77c005daaf2addeb10" + -+ "0abf694da8dd692f113965cd6366a5a7b0c17e1f2a320243e2c90b01418e" + -+ "22426d0401a2c8fd02cb3129a14fdfa6cbcaa1f1c2f17706e9ac374a3458" + -+ "777761e986ee4c358d26f8e420d33230d198fd86704e77298dd4c40c5205" + -+ "7566ac0cd92993b21937c3a3b4a8b89110a97cf38c781ad758bdc28f3565" + -+ "60cf3acbedfa8e05b396d226ef619746e8e4fa84c8e00a7f0e6d652808c8" + -+ "9c9b123d9bd802624cfa949eb68af85ca459b9aa85b81dbc0b630856cb9d" + -+ "7e18cdc96b3c069a006dd5b716e218a5ed1f580be3e3ccf0083017607902" + -+ "a7967a02d0a439e7c54b3b7ca4cc9d94a7754efba0bb5e192e8d1a6e7c79" + -+ "4aa59e410869b21009d9443204213f7bceb880ccf1f61edb6a67c395a361" + -+ "ff14144262b4d90c0e715dbefce92339ff704cc4065d56118624a7e429e4" + -+ "cadf0b9d2e7ffc4eb31c6078474a5265beba0774209c79bf81a930b302bd" + -+ "0f142534a6ae402da6d355a010d8c82dc379ea16d49b9d859a7de4db6e62" + -+ "40f6976ae0f47bc583b327df7ec88f5bd68f713b5d53796e72e28c29e843" + -+ "6c64cd411d335623ff4f5d167f3c7b8cba411e82f03714662425c8e1bc1e" + -+ "fbf435d28df541a914a55317de0ded8c744a1c3a6e047590244b207bcdcb" + -+ "f4bd1f9f81210deddd629192c58e6fd73e83812f084ef52f21c67bea98ee" + -+ "17554437d9642e2e", -+ }, -+ { -+ key: "b41210e5ef845bd5a8128455c4e67b533e3e2b19dffc1fb754caa528c234d6a0", -+ tag: "72c9534aec8c1d883eef899f04e1c65e", -+ in: "7eeca180bb20d99635e36b9208221b2b8ef073fbf5a57f5190e19cb86c49" + -+ "89b0e8150d22ec3aaf56f6ed9cb6720284d13a4b0a34cd3d7f7fc7089326" + -+ "6d1893fa4185269fb806677ff490aec8f889896fca50d6c80d295875b1d5" + -+ "4a779b6d49305360b31011b48537157d0f323ff4e865d46fba6bd23a06c1" + -+ "46878cf9404360d325432312ff08ce495edca63a3c93c44d79c050e3f1de" + -+ "4b6ca5fedbbd43dbdef9ceb26d440a59c7e0be3a8e461c4f15b6b1e1dc36" + -+ "a71fc723ad593fb903e83d0804ce497fc49bfc6b6a602b9dc6e9891010b1" + -+ "4ca066cb1c68044c1ad837c638076dd3708078509cba49fdc54922cdf5d7" + -+ "715fb43e9b5a5942cb8950eade143577bc9dcedde58d51deddc70075e452" + -+ "bbceab1e95b5d003eb96bea69687faa6d50d9c605769cb4287b5d9924dd6" + -+ "8881c699abaa6f93e41dac7639cdbbbd0259099a3ed096f482a1fa322b15" + -+ "ffc379812c74e09e95f1bd3706347eac421fe56895e738a47fcd3e118773" + -+ "c3a7e7e264cc7ff5a53a80e436df058265dab9756fdf6913786a47e98bbc" + -+ "411052d58ffec9ee948e28cbaadaae471c5d828eaf3b3c87d3bfd495477b" + -+ "403da54f1418a15ace0d4d0df68f6a8f2b0457b127d5eae1f45ae055afa1" + -+ "8f058d5dd7eea559de3ae9378ca53f7d6dc9a9465ea1f945295f16ee0404" + -+ "7fc9dd3deda8ee32631d7af70c20edc1e12c5f8abd2e78f43dbd4cd6407f" + -+ "038efab144a24ea8a090a7ba3e6499345a60106220c2959a388e1a73d070" + -+ "1d854bfaaa86165a5aee934b615ac7f45da7c43a1e8f74613917ed10dcd2" + -+ "27e4b070414412e77851db5bc053e5f502bb4e2b2645bca074c18643e814" + -+ "4caeccb58be49ea9a552913c0616382c899635eea79a166988c206b9aaa0" + -+ "977c7ced89c4c7aaeaa8fb89b38030c44530a97187fda592b088198b63a5" + -+ "2dfad59a0a4c1aadf812bdf1881924e8b51b8fd4dbca8e73b2986b3ab484" + -+ "171e9d0cbb08be40ae60de8818bd7f400191b42c7b3200c27643f06720a7" + -+ "e0a17441f34131629388ac43955b78c31ea6602a70dd665f872e7669e865" + -+ "f6f40e634e8772d747608cd3a570e1726eb1ddca64f08582b022bb026eda" + -+ "6a913dc83f174ce3c18b9fc0503d3ac74e2fe45691d6dfb4af8c86d752a1" + -+ "6d6664fab4de08afe8858392fcc35cb9ea82fc42c42d48c0c0556267ea0d" + -+ "cc19b10f05e0318c4488ffe704b5036908f5cb938eebd3163503acaa874f" + -+ "592d945448fbeb93a877a26a72306a36e181745ba300afdc30cb7986919f" + -+ "3dbdc5c47ef1fa052a9e4aeeda3955f61ce2f30a0593a81dbaffebac5a49" + -+ "e5a8d1308352701d1ca9e620a67a89abdf5f0f8b1a0acfde5819981d4b77" + -+ "58799c0fe41030b86754837712af821c315301aa8dd50d1387b9fb92ee63" + -+ "10777e08229edd54e5e86b086ac281bd321082ef46ce298a6211aaa3aa4f" + -+ "6e55b5a4641220ec94cca73087760da1b1ac3e0da3f438214e691aa184b0" + -+ "535950b715a64d11485940dcaa3f72e0aa521002b1443f5e7880e2a85b83" + -+ "40d32db0fc4c4702e10f0fa24a35da9307850e945f608ad34d6cfdf6f2b9" + -+ "ff4f6b8e9eb5a883546578e2ff3cc5787322e4384640f42dc5bd05f432d9" + -+ "610dcf7c06cdf34762dd2a5e805e24aee8cebb3b4db9e4d1471da995bba9" + -+ "a72cf59ea8a040671b1d8ce24a3dce4fc86d2df85c8ab5e1eb2b0567c186" + -+ "4fb464f48c3ca72c7df2749542ed4d4be51b63769012ce3d06356856b2a4" + -+ "24995a2429a156ad93bc79c705e7b163149ce53a42c34a19680dfe4fd0f7" + -+ "fce38c30dffe9da9bc941d131f435c1398f8284a230e9d6e3992710074c3" + -+ "881d03aa309a9edd0fde7a39c33f6455dfcc5ae3fa20ea0e0d6549a43536" + -+ "b4cd8a2991a135b7d7a4265fb840318813091274414108f13fe191db7774" + -+ "6a5f4270f6d51a29ff523954f84cb76131d4abee79161dcbd97dc1ef24cf" + -+ "db1fade057dddee00a1e0de0db1afaeed1b535f7bb402afa3b297551fd14" + -+ "8c8f3e05f1351d3a8ee2948daaf14e7fc448c4670c906ae076eac5a7c656" + -+ "fd5f9cd937b91e26c9e5adb43c138f8d65e447b0022a524e059f879c6e27" + -+ "4ff7e671f75717233aae70853d5bd7bbb41b43c47bb08d6dc2f54f9ec606" + -+ "9487d1267add72403d01552a3d138abab9ca8a0d2dc32439759aa5695f70" + -+ "1a17d28dfb85850fdb55fddadcdde4d220e4b05821e5736d346e7dc9c945" + -+ "72743366488b1de8975184771361894b6520e3407c5c2e38473430969e35" + -+ "b106024da8618665d58c9d084824a28991a33658d6ec702139e01b65b7d0" + -+ "cc537a644caeee880657803d95f5f67816948d5ab362922f8ffbd531473e" + -+ "b0ff8fde2afc37a4abfa28dbed0be1b3d4ed48a1d02358e8403905d33b12" + -+ "3066e7a9fe2491ee9eb24fc9de7dbd322c8ddbc5ebcd0d92cd102ebac96b" + -+ "90e2fd784fd6d4b699304df23b17d963080a013794322690456be525c071" + -+ "b78fcd2d1148026e44ff14c4d0f942cd44d2b3263f4a93b79ec7a618b4b0" + -+ "d77ae7a1f6e6c7c7e2f498b825bf1954df348bae45ae1d7c87b6787f1212" + -+ "60c9a724429a4a2491ef989f65acfdc72fa717486dcf1984905218e11cc3" + -+ "970a09d71061e6df751f100abfbf", -+ }, -+ { -+ key: "d9b0dc303188756312c12d08488c29f43a72e78714560fe476703c1d9d3e20c1", -+ tag: "6b9782f2a09b59653aa448348a49291b", -+ in: "dbde1820035997dc8a8ff3015b4e0674e7ce7bf0c2d994b7977f2d91b49b" + -+ "f200995040daeb1218a0f4307b6b8211913992b070d321bdb947b4ba5017" + -+ "a0885e7e5502710a75cbbcb56d49e1bdc2bc2afa5a0e83851162dec41340" + -+ "bafc41c5e11fcbf4ea2ac45bc57def4742281bbf734777f83c9ae1ea3d5e" + -+ "d42380230570f59c40d5dd9a2d89b75fa3c92664f12a274d965ed8de79a8" + -+ "b37f3763939ad21d1703ad794f617c8b32b20cc4dd7c1b7f969a65e1bafa" + -+ "f6c43f30c9eba256f10201910e2cc31a9b13a46ad29257024ef8f2ee29b2" + -+ "ee63cc5b6230ab9f87cd5cb534f4b0bb08a790466e0d57b849fffa1ed21b" + -+ "fb0b27804e3ff9df7bebf14e100cf91691a493e53870abfad6321f6711c5" + -+ "0fbcf1f0b2c1e5231d6c0a08e710525176355f6f82bedc1f787f0d3cb41f" + -+ "a11e91ebf9f4cbae46035a371232d63ef0d8bda0355af8cd0a2f7d1327d8" + -+ "0ab769ea0f1da0f76ec99cc737b5ce84675fa8a9ac0c98342bb82b5848bf" + -+ "656d35327ea01a1b09d84ab974c307511af68a30cd6978b529a8f58c68a5" + -+ "9d476062ace8897ec0d1a90d5d167e29ebaa6f46d93d697760c8771417ce" + -+ "94c0f3698985a98702833d1b68641b811840ca3d935386dbd4600fbc81c8" + -+ "728c4fd0e4588be739a048f03bd4ac651ceecd7e2fb120fe7190011f957f" + -+ "cbbfdc025f1ca0b356208db8cad87fcd53c5d3a30a7c2a48140ccd4cdb49" + -+ "f3961cef742caedd1e848bf3cacafb0da030416bf3177877aa0bc5f9d1cc" + -+ "41fafcb829d5e3ace9394028683d712552579e024084a6b855830ad9f567" + -+ "ff58f05d3ec263eddd6f56adec378f167e8dabbeaf7d0a9e65c71660314d" + -+ "6c8d54beeca2711113fbc32a2ff8c0daa8373278d10085d2a0660ad53f4e" + -+ "1ade74a483be180180acf9e9ad3ea5bdd9162ccd69599163a451c6837d5e" + -+ "a5e115bd9a560f395128ea002ee739009a44fa46078b18959933fb6e866f" + -+ "eb4612a56ce93b1affcb95fccaa18d71a148582ba1412a5daa07404fcb39" + -+ "c3cb4a2519cc506c1172c6c326016ae2e5410f6a438569f35a50d45cbf3c" + -+ "c46188651aa22c257858f60649cee8c05c75953ce49358dfe5980445fce9" + -+ "614ccd16d333ad236e29d204691ca0bf46f29da954bcaae52e41016556d2" + -+ "f4cae1d37565bcbe84de1b49f344d0200478a38187da29c155cc98184d9d" + -+ "33dca088d70054e0fce321f7a90c48a14963d0ace2b4e7a24b21c14a5e67" + -+ "1994fe1f7d22d1135d4df9268dd18d323fde3603288735626a5449582d35" + -+ "30e2c2225414e05a8c7b987c873a82e272a5d83e59b90f3d7264631d6ad0" + -+ "4a0cf3b5e96596a66ed5bfbc24ab6e4870aeec0acbad2cc5affaee06de32" + -+ "dca06f175bf763cf8e7fdf95941a177e934f0078be7dbaa4c9b6f5c16b4a" + -+ "5607bab5d56144a6ba3c7d9a084b8d1f4b24b6f9754ed207b230d3a2cc26" + -+ "259ccc725e1f8a44c4df8143e13edb5ebf073e2c9d2da5f1562df4feece2" + -+ "f6480987f093f642eb7afa3aa92dce2a8b60bb925cd2d11cf6c2ae7d2153" + -+ "1a9c8f068d71d0e682023932fe64e956a49347aed22b21084c4a84480491" + -+ "244ac6b337b6d12d5551ad5684766c68bacca62bdcafab6603c81bdbd8e6" + -+ "80d9d8b3825eaea4df023142e840f98ee251466a0422d810a54726a9f03a" + -+ "7e0afeb0043e60e2ba4908f951d2e87fcbc372096f2a9f4f2a95ad5faede" + -+ "3796b11ecf4401c3ee3d268bd8c46476c61e0ffc5c43c0f3c58c79e20f75" + -+ "520c102aa3c260972a870fc50f8841fa0553a9e30bf37ad282fb51b34adc" + -+ "7a933ca1691a8a706605ce0b906fdccbe954f8e5f2f63c42599a483c4be7" + -+ "3a041ef90ad930fe60e7e6d44bab29eebde5abb111e433447825c8a46ef7" + -+ "070d1f65862b30418efd93bfea9c2b601a994354a2ff1fc11c383e7bc555" + -+ "9e7546b8bf8d44358b1ce8cb63978dd194260e00a88a8fd17df06373aa80" + -+ "04a89172a6051bd5b8cea41bdaf3f23fc0612197f5573f3f72bce39c9f89" + -+ "faf3fb48d8ca918586d4feaea7e0f2a0d7a6afca096a081af462ea5318cc" + -+ "898a9cc09e8258a837559570cbd5eb901e8c0e04ee88ba31c81a76b000b8" + -+ "0e544feba576b3eb5272b53e46e96a0b35b9c759caadcec61444f8ec47c3" + -+ "45a1d2304e2708eeddfbfa75a98eab3493889047d690e84431d445407fdd" + -+ "99560c0bdd287e0944116f8ac62ab992ed3f1e2b415aea784b03c6904795" + -+ "f4326ff60bc839615f2894570dc9c27cf928ef192047528a1a19ec990978" + -+ "3b0d1a13dd4baf4a19e49bf798975abe2ad167dd574b32b3d0c22aa4d9b5" + -+ "2761e8f56cf2100fe5a39fceae3d865f3724d4f299d07ff899fed6baf7fc" + -+ "eb7189357bf56cf94a6493e61301b43e3ed158cb9c7a0e615fd9888c2db0" + -+ "7f7689762f62ef6b3ad4125e06b07a422f5040c3aa8b8f205d68356c9225" + -+ "56fc4c976165fed9599daeb297498ecf744bf6c7dc5e30604c461ad99402" + -+ "2eea0fb6fe33f82a97b5c272fd24162a94b761ec7e52173e7bb42e88b343" + -+ "64f5fa2c141ed04a86b8d00fd9c25bf77a8dc3e63f5543331405be6bf421" + -+ "6a891089b316aa4f887cb4aff0dfb4e80c2ccd65ddd9daa74b17b4411c0f" + -+ "c849dc748d9b138279dcd9ebfc6e6759a53f5c28a41bb82107d71cc161fa" + -+ "81291a8290", -+ }, -+ { -+ key: "fb70ae7ec12264ff9f51124da188e5b11dbf53cae2671363f6054b575b1ddcc1", -+ tag: "d9ab81fab28b3be96fa3331714e78c9a", -+ in: "c62edf20b1d53962b42386eb570b10378f9764421ecbd7c4802853332747" + -+ "19ff4c89c06005050fa9ba6579a844060eb7ece6c43bab520e683e0f36ba" + -+ "49cba259edc6ae35d41e0d7812a7d5edbe4d90cd5e0504d16f4c3f70d01f" + -+ "5a0313de55934b661ce1ec317968c2c4de60f45c66cded8c10565a1ca6d2" + -+ "3a84bf182df2fcb05956ed4d46b49fc0fe3bd23961d9466fde070341ce41" + -+ "bc6e148449360a31634fe10e91082d82def90d9da2c250ea72c58add2058" + -+ "d046b4392b78bc3af5b3936ed568733e8ad5672dabbfa3130a6a535ec73b" + -+ "da8e7223535f49f96cd35d56ed4792c5cb7076720d5461d96a2692b2ada5" + -+ "2be08fb7bad15d15a0108143790024f0f15f5adc275e783aa56b70844061" + -+ "e30952a040e4cb9650f2a010417812790105d8f58bd25d99b0db3cb16229" + -+ "3f6322e86cd5b0bb1505a7b998fb0f81d1e1915faca3c2c8ddea39115507" + -+ "80339430a7955521839deff5b301f3fad54edd5ebd2ac4ec9b1795cb4dc0" + -+ "e2eb62ebca8e886c3f1e507d10a0228c3027b472a7104b815f5ec8dae55e" + -+ "0783ff7ae9a3e6b99e381ad788206b135520cb870ba0cdbe876feea843b8" + -+ "5a82adc95a6d71c555f798da92b82daf0abfcdbc82ec30b1f12d78490b06" + -+ "7315735017a94ac150b44dfaace151896f873923310ffcd41e91bac04de6" + -+ "d70ea71565948c907ab21c4a23703fbbd2a8de6d3095f3d8f901538968e3" + -+ "60e7bfddb9d22036b1c23f4f5f1b2ee22623426a2d5de68c1e1a38e38e08" + -+ "e2b5670aac1edff69e9c73c2ca56cb69c709009ef1d541aff1fdb2b40c92" + -+ "9b87f162f394b76cdbba1f5605993e4dd9c312321d59b0aa5c6e33be1b10" + -+ "bfd00b92d4c02db064d0e4a98f2913c89051b0f0ead163deb5087b6466d9" + -+ "84f57553b0fa53850eaa142e072fd91802eb9f0d2eb7318dd620555e6ce1" + -+ "86706b866d41cf6ba81f100342faa14d801dc6f3d522db38fab17a879fcb" + -+ "b6acfe922163505bd23a6842f6ef6397ae5fb6e6016421998bd43b0142b0" + -+ "3ca3b16d6ccb7a47891c75c687d791a930b26aaa2e3412e7aa16e2cf1501" + -+ "7bf6df6d2e1c289af0d7ce03954a60c1dfcee5e4b3da51eb43ddd14faf59" + -+ "082005d0c8b104561f66c002ff426be60be769282fc5685cfd1968df1941" + -+ "73667e48e9ad681d35757f1199f1d93377bbad093c8cc3efa2bcb6ecb703" + -+ "694422772d15aaa58cab9e9ab277ed510f684114cc4a44ccadb3eb1c9a76" + -+ "d8619a9b7743106df6fb6f927ac49b22ae5bb9a9a4d231e340a2cd0e3282" + -+ "53f6d75df694826f60e4b3e758398793eaf73ef5d4b56cd1471e16400f40" + -+ "4a947e9737f4f874fe09a29ad799f4525156e3abbf0585c3c3c0a3744c86" + -+ "5d56db3d2ecba6bcbb1adcc8bf5f3b2a2d46d3eba18cda55201598a8112f" + -+ "d8f14e205f0e615f081b8ff6c5aa6669da776bfc7c34d5af4d0b26d0d819" + -+ "f6aacc53cf3c6653138b9a962acee9d6ea01d280c35bb1f05d1509238ccf" + -+ "004c5013167f804d1780d9f4ef9d45742fccac346b0472bde24ff5db9ae0" + -+ "16455a3c02256358fcd8e6a9aae94f8a37a1a3da58a889bbe3d295e16544" + -+ "2e580f59bdd31c92ffcab40c49c1cdbb4db1dd4882b66edc10fcb1704203" + -+ "c518c1d8d4c268588ce13fc38e0210aeb47d11d2603d4b3de5c6ff5e969b" + -+ "9d5904abb282b699bd04a6e9f1cb323679e30400d725aab128a032745dc0" + -+ "be05a46b02b34b93bff02523cd8498c021fc35a488f164a70ef1ceb873d9" + -+ "14a681d3a3a34cc76bfd5a547e2630d7741a284511bae5897d9f7a197fc2" + -+ "456af5c6cd7e1a93d3388c7a990b5feacd7749cf39fdecdc20adfdd540c6" + -+ "9d330195db7cc0d4555ea5f5356a3647e2265399f153c34ed1e217c5dafd" + -+ "c2c5dd3d566c332c7ddacb0d76ecd3a0ad505a4165443aa81b0f43cabfb4" + -+ "62942fe74a77c22b8f68a8b1a6d712d1e9b86e6a750005a3796ba1545396" + -+ "13170906d228dabf572ab969c762f8b296054f23d5d4a37bff64bf9cc46f" + -+ "43b491b41101256018376d487fe8097f1653a7a9e99e1ef2492600598fb0" + -+ "bbb7df8270be8b9106126d6f491f8b342a96ab95df6133e883d3db4c6a99" + -+ "402aeb58d371263a32dcf76d33c8904395b9cf0016fdfc15608eb43e20b0" + -+ "99cbe7455f7a76f69bba058ef96f83ae752587485657f89c7f26fde7fbeb" + -+ "a82ede581ee92821dc13b8202930aa58bd4f1c86f68926baca0d06fee642" + -+ "ea8c652d226af91a9638a0244f1a03c7ce56969b87cd5c1f86110d192e0b" + -+ "98dd979d74acca6c1956b1127d9a1f456053d17974081ed8ced0faa4293a" + -+ "319e5b25ba285c1151214f52c283e39c35af51c4572c8e395b7856697bfe" + -+ "dfc4145ab4ed0bdbe43ba509c06a196ae6bf30d7582550cb546c63b51833" + -+ "cb0dfff7196d83f6a1c6d6d712cce2ec1989fd9ff5a0a22ac5022b49d566" + -+ "58f196703e4809e7624fe7cfa6c13b378f5aac7e66e657ed7eaa942d1a00" + -+ "544a947199f24d736b8976ec2cfb563433c49ba131bd08b63636854219d4" + -+ "c45100c98e3092773ef492dd9210bfd8f54cfe2cddafcf5c05468d90e620" + -+ "0c2ef99d17fa6992cc45eff3072b7cfd51cabb07ea3019582c245b3ff758" + -+ "0302e88edc2c13fc43646ba34de37338568baa66ecff3accfebad88d143a" + -+ "fd1c3b09ae39c501e3f116af33b0b720d6c2baf5acd7f31220788b2f9017" + -+ "3ed7a51f400054e174d3b692273fcab263eb87bc38b1f486e707d399fe8d" + -+ "5a3f0a7ed4f5e443d477d1ab30bc0b312b7d85754cb886e9", -+ }, -+ { -+ key: "f7e7affceb80a0127d9ce2f27693f447be80efc695d2e3ee9ca37c3f1b4120f4", -+ tag: "41c32ced08a16bb35ac8c23868f58ac9", -+ in: "5a3607fb98eaea52e4d642e98aa35719bfce5b7d7902950995f4a87c3dc6" + -+ "ad6238aadc71b7884318c2b93cd24139eed13d68773f901307a90189e272" + -+ "6471e4bf9e786b2e4cf144764f33c3ac3e66521f845f6f0688f09eaa227f" + -+ "e71033b0f74295f6ddb91fe741323f2b54f420cb9b774d4291b06219f1fb" + -+ "4410b55900425c5e6fcabec76a5c2424d637a1641db6f0f6cad564a36a91" + -+ "0f49894bfd598e91f38ceea65e8253c1284f210cf7b50a96e664e562f3cc" + -+ "01c4fc490fa6d4679fd63fbb3ed8995a8a05166b573e92d22ef4370c6aac" + -+ "74ae94c94177e5f71143c6f340efceefda679ae76f6ed7f26eaa4848a8de" + -+ "8c40894316efbb06400f9695b18ba279e8947c032a84a40ca647d9ace457" + -+ "6dd0082494d6bd7be4e7928e749c78110af8774a5d43e9c9479964e2fddc" + -+ "ee51146460eac734311225d08c60706e40f298a7cb97f369ef599be097ac" + -+ "3bf1c275497bbd68968a235fdf8a61bc7cfeef0fe451bb04e662ca39f34e" + -+ "a8e3acdd0befe9762f9eeb275c0cdd43c80fc91131d1e0e790020975ab65" + -+ "afbea81f303ebd86760821efb4cad7cc01fd6d6fd194ac5ffe7703d890d0" + -+ "169e21b444cdbaf691fc741a5d99bd47357c37785755fa72582ca4754a03" + -+ "b4def86ded39aa6d9eb3f38801077e6d17e3cee3fb57ae83f30c79c3cf29" + -+ "0e2739c6b7323612cec3a561ebeadb4faa642f150323aaa9d270658c907c" + -+ "4c1610a5e1834730c08be3379cf1abc50c30e2bf01ce903927c27d85e135" + -+ "3db9e216dda8860c45925e2bb791abe5c8281ee6d16607bdca87f60662dc" + -+ "bd6e20224e7f009a86db66fadd8e37e0a59559328385090c6953cd20bb61" + -+ "f28a734fb056714f5159977f18e5c5f11de75f7a00ba807e47a29e4da32d" + -+ "5c67ec76ce4d7b669b5e6ee17e1df7c673dd8a7c87fce665cda8adb9547d" + -+ "1dccbdbe7be44846b4b121b0bfa65e4ed530789510d79bc4477e50178060" + -+ "f2668ac8956f39ef422ecb0e4cf90b8ce508552eedeeefa6c7d1bccc077e" + -+ "8088bd7e0e6aaf0bda9f11c412c270ee2ad6912f9808f9344a4bb137bdac" + -+ "b5b9372b00b0de026a8f5d1fb13972e1290b5005689f7636c43aee2fd443" + -+ "93d390371ae573f0e064b2d7df552b9adf04bf173d71c621795b9fb503dc" + -+ "5e918536c6ad25ce4a76f70e6b752b6d44be321187269a19bcf33ec899ca" + -+ "40e88b4eb23217095a85057bf95d8a54812cae4a7d32e0c2966a21376110" + -+ "74c6c8c3dd45a553c43c675d23308709f91be0b235d0222aa5e1e1ce08f9" + -+ "c6b45ceb5b47bcd7d7b2d4380bcdbd6eced452d93e6d8cbe18123277889c" + -+ "7f86b15fb991364a501fbf5d8244f2e3332ea0ab49e833c6f765017a4006" + -+ "cc7cd1a0365945a8d8873cb21832b210c83e451c01ac949de2fb0f7a420e" + -+ "405bf64eb251c6f022181595d68174b91e503187d3b3f49b60c23e44ea40" + -+ "ca20311305b413047bb22e89672758b74d6bd1a06decf09e9556421087a4" + -+ "0c1d2c44c5fb13d4d9625581ac4ccef1a1b5eeb5689aac5c0291aebda276" + -+ "50daf9d4396a64d02c6d58bcbd609d9a0017880ae0cbaf02ad0f1fc8d1b3" + -+ "ec987ffe13102d77352690c9b761bf13ea0b3a8ebad4a0823817fcaab4d0" + -+ "9b0bf03486620761dc77a6ba007ba07153b17425c4026597473e78863cbf" + -+ "430c0e5e9b04a83ad11506b61b8d9be3aeb06b5114e0d53d4724863eba12" + -+ "4f3b974bdb0d02743520409910621cd730c97ca984fe2921c38055f83ee8" + -+ "c4611db92e52d8ea51d89203e89df7586c574df15f3a96ed5a10bf04cb27" + -+ "f9656b5b11cf35fd21360b029ab26e9a741c6b3e6357aa1a41de2cac6e85" + -+ "f9a49e3441e60a60e74f434e1b8cd4454b11962e5507ebf904e9d6c52a7d" + -+ "9722300517c434758fbd6191f4550108b143eb16c0b60094fdc29327492c" + -+ "18a3f36737e506fda2ae48cd48691533f525acfffb619d356bf8347a8bbb" + -+ "4babdc2ac866e497f192e65a694d620687cfb4f631fbd6ae5d20ac2e3a12" + -+ "4d85f9391a240b616d829ac2adceedf8f3451ee77e4835639b13c622ef8c" + -+ "48a181fc7598eacb419fa438d4046aa971942c86b36eb8e16eab67105783" + -+ "d27fc56f5b66f35451b2a407d4648a87ae70807e45bccf14983b3abcb198" + -+ "d661d562dfcb00ffc569ca967171746e4e36f839946bc7d2ea9a0eda85b5" + -+ "a5594f6a9c1b179f7230eaa7797a6aaf8628d67fd538050cf47aa654778c" + -+ "11dbdc149458c1ec2233c7ca5cb172356424eb79479b6a3eed1deb9f3278" + -+ "5282a1034ba165032b0d30733912e7cd775cdb7e0f2616b05d521dc407a2" + -+ "ae7dfcf46fbae30547b56f14dbb0ead11b3666666c45d345cd5dbfa200ae" + -+ "24d5d0b747cdc29dfe7d9029a3e8c94d205c0b78b56d5e18613b3169bd44" + -+ "1b3c31513528fe102f9bac588c400f29c515d59bbcb0725a62c2e5bfb32b" + -+ "5cf291d737e67f923080f52d8a79f2324e45a3bd051bd51bac2816c501af" + -+ "873b27f253ef9b92ba4d7a422e2fb26a35c1e99eca605acc10d2a60369d0" + -+ "1f52bca5850299a522b3aa126f470675fa2ec84793a31e9ac0d11beab08e" + -+ "2c66d989a1e1b89db8d11439ad0d0e79617eafe0160e88384f936c15eb15" + -+ "ece4ff00e1ba80b0f9fb7a7d6138bdf0bf48d5d2ad494deae0ccf448c4bd" + -+ "60f0788d3f2b76de8ad1456f7572bd0ffd27bc2836d704d95e9c0df34571" + -+ "9dab267dd805577fafda03b834dd225ad9714d2bd182b4103faa5975180f" + -+ "90d5d6cac1825a19b9d4c87cc825512ae9dbeb33d2759c990905050f960c" + -+ "db3eb364c15b593524c882902b2a1d7fe40ea3f54fb0202fd8821463c7e3" + -+ "4b02a1209ba0048a9805f0468a13e03d18009318ecd92042959be263a51a" + -+ "407f1e660632c4247419659a4e073a8e9cd4a226763a7daea464d5427270" + -+ "7efd053cb4efc0504602c4f63e7d247b55db2ce1c07138f585d16cec97a3" + -+ "0731d5aec2166cb4de41695feb76280cbae1af8a2e67c2d5a3ac5487ffe8" + -+ "640f308ace6137e83576b79d586b663122221c20aba7a6bf60f73958f436" + -+ "59f087f850ba6e2d7fd862249c5fa6b20e3e43d4f2aa10d4c9cebfcbdf02" + -+ "6b8d103e4f89b93dd8af172f421001c8b162bd6d0b847a58ac108b6d6cc4" + -+ "9c7a9ba069deee", -+ }, -+ { -+ key: "e3d21f9674f72ae65661aebe726a8a6496dd3cc4b3319f797e75ccbc98125caa", -+ tag: "3c95668130de728d24f7bca0c91588bc", -+ in: "baaea2b4b4cbe9dbc4fa193c376271f40a9e216836dc35ac8012476e9abd" + -+ "43dac6b9ce67dc6815904e6c84a5730cea0f9b4c6900a04ae2f7344fd846" + -+ "58a99513ffb268c6899dfe98d605c11e7dc77de77b0d30986f3051754503" + -+ "7c26be7b719aa9ca1140cfdf4c586b7fe726a8bc403249396a11cfee0a6a" + -+ "f6c5e72259785cfd13c2897384fe527100170001ea19106aed38f7d5d9a7" + -+ "ad43f0b41451e19989192a46b4f9734a774b6304cb74feb7d83822044a24" + -+ "2e51d55c0b8318e0439493bd1a57cc13f6079166cabc46877d003dcd39b2" + -+ "c0b90f6b32fc77acf04a6c125e11b35d91e2b18401cd53df4aff804e3c67" + -+ "a8bb3894b27c6e9b0070b53a85aafab0c0a253f9cfd4d3cd3be52428385b" + -+ "24a3f9f71660ca2c38474d14a0309e2f400e2c21af6e379099283ff241d7" + -+ "51da5a96a8dcbfdc43b913b29cc8cf8020eebb4a67f5bed31f2e383f8656" + -+ "8c815ff172382b425e95902e80f5fc219eccb51b656d37b56660f749e5b1" + -+ "4976a23648680a472d02ba71476e0afb29a0e084984f4eac3befbf8dd802" + -+ "2b7dca4dadd18bbe58e49c49ce48a06a71557a9a620c51e2623f818e4d62" + -+ "c2564c7ba04595cc109685869b183faeff2ac7a65049fc57cb10fb01951e" + -+ "a525332782d691f9759ec2ecd68bebb9c7aece5d522a08ce7830be520db4" + -+ "c9d60a2e490eaa0c91e37b256a97f84b39fe3c77953748c3b86fd84e9547" + -+ "a298c049cb28b8c85d59548b8dce635d59487c9de615802d16a8adc4c0e7" + -+ "80f35b9f10588a431b39b499dca929ab9d225f26e5721820627fe62427fe" + -+ "06d5773a50878b6effe840dc55bd3ea0c35168f6b6a972d57e8f88c5993d" + -+ "1ae33e0b7e9459c123753b518c184de7aaf429df078c9a18a29af77c727b" + -+ "796f5c1a501fa8105ee873c4e78c907142eb19690638a182fddb413adb06" + -+ "d66db19c7f6f46dac582bd72a6347b4427a576eb769d233febaf7be8f768" + -+ "337273c12253924f15653f9f3602b783703a81454a1dd7a8772a9ab1eeb8" + -+ "51be33e0c6c0708f3cc2012cabe8e2f0c38e35372abe27bc148fc4e1054d" + -+ "9d151f80aec0232a3a92dd77928a3678ebd7d09ba7b4e1d83227257292c0" + -+ "b8bc4a76de36bff6c9deb383029afaf4f37d5b935dc080a18665545e4acc" + -+ "195da0b9545d8902408886204b64f8548b32d012e0cdc520c17d9fb3be97" + -+ "800c2e2b945cb09a75a0a49e5d4d81c4194d91e839333b2b9b9e34d588e4" + -+ "e20cc1e911ca0a1429fa70ff063f0090fd842f89dfc5cc44affcce4e1e1b" + -+ "8b11c612f66b074c03ac2a055fd8f51ac9ed4f2e624589ff5730721d077a" + -+ "fb4c19e43abf8cf3ffa698362be8be51e92c2c91a4a56be64d9ac6d3fbaf" + -+ "5536a24c7fd0adaf74ca84c508e5e8c8bf7d4254e0c44158bd26acdf3f64" + -+ "e78438b3aaff89ac9986cef1e3a88d5bf2016340367a1cacd01ec167ec6d" + -+ "185d93a2a220d718b43ce1d429d2cb598605660b030e51e8d75fdbdd5b8f" + -+ "8677675e196a40a88285b18b24c5d2d594bab3d457e6f9e503e38cd470a6" + -+ "9ff8037c9a0a0f110a434335d954fa856a3721e0edcfb14287c3dd9639ba" + -+ "4db32b7da0670dd0a872e468e3819741d0d4ecf0a4f7a011bbae1493c01e" + -+ "642757491189f8664be3ec6437c4f3c76abfb0276e44a4d28871d3487c2c" + -+ "ce2f230452cb06184bb8620919659a7ba0a3d5c12ec25678b03403715ee4" + -+ "acb6a53d281036d8f3a085143cf5ecc3a0c6c92129caa7ac1f645c7bb95e" + -+ "4f63da38dc319e2ccff4a9006f9b9b1a38c4c39f6dc686bb82d43fb9fce4" + -+ "0c767d3ff22f52c5f9900130c65bb6a9cc7408a777d49b70946665f4a733" + -+ "5099376b276a43dc9a6382bb2d40425f6481b1846148434c672b84dd7a20" + -+ "33deb5140d43ba39e04ffe83659b6deb48629e1abf51e68748deffb756a3" + -+ "ed9e0807506b248a024cd509f539f4161366547c62c72933584e851599b6" + -+ "82ec16f1d79e9c6a01cff6f51ba7f46b67cdca09f3ab8496322b990a6116" + -+ "8d7574854a1cb1cb8f30a303dbd13a095df56dbb940dd16ce79879cd2d73" + -+ "80a419842fa1b34da668286de4c1ff5917b7aaa64713c349dc8f855d04ae" + -+ "de9a3a4d0739dfc36510b1e7bb1695418164285c44631b4b1a7c5798ecb2" + -+ "d976c1a3679a827bf0e8c662567e402bcc1354222036ad5959a6f0b8508c" + -+ "6a8c7d4a63e7dde154d778fc80a011592771d55801c7e1297b00b77f80d6" + -+ "314ebd1f5b3057398d1943599897cfabb65e7568d8fbdfcbecfd4b8a83ca" + -+ "0a7bed08ab9a656424831e0d7718c15727af7c83b2ef5eb5684aa044eca2" + -+ "ba896811246766248b20a325094a4b4159f9cde1ee349be6dc3c9a190453" + -+ "0349212a9537f65ae333c288753cd2bef6c5beb2f4164168d965a2c0fb9c" + -+ "c8c73d9e776e23d53ddcfb83bb7dfe2a1b8c781280f449d6f310faf8b53e" + -+ "89e6a611d6d3f42f2aaed5259730d149b3e7dabdc9f865bc1555374738c8" + -+ "456abe112e9628fb31efc2ecdc972da05987aafce728ccaed246cfcdf518" + -+ "3fe5dae528bbfb99d33194167e0f84d462d3d0da83e92227cf57922c7956" + -+ "4fe44648d87c69ad708e797972c44c4a5183fd5d1150a1182e3d39c3cd16" + -+ "3920f1d7ed83992bc4116d9351ae1c6c4827d1374242e374310409f32d5f" + -+ "0f38c78b6489c568b791c70394d29ea2516dcb10e51bdad862ce3339d5e6" + -+ "14fe14f150961809c36e0a2c8eb872e9f7a1c0956fbc9194cb63ff9993e5" + -+ "d0dcf62c0f49e81dbe99f3656c4dea57b766ae9a11254f9970618f1b33c8" + -+ "f339f440de240170f7a21f03ff2da42102b323ce2b9b7d0de5aae324d1ba" + -+ "c87b1e4c5279a566bf659778f8b03882aded57377a0f1b063af2897060e4" + -+ "23be7cefd4aa9a28479c16773944d254fc21d3e1acdf508b7972372b5991" + -+ "3b8b088e93471a7d54c6ae4c52ba465ef07f19f269677fc2f64d3fb3d7f1" + -+ "9069d6c7001d4b002ed6683c59bd5651a450503b68a4a00820b8c17e3263" + -+ "18f32c21dfbcb2a02a104edaeff67ec09533aaf3d1a7fb41aa5d506ccdbb" + -+ "e6e35fa0a263c0aad3acc91182addf8c5bdfbd0626702694b8d652a63c65" + -+ "8d6b2b7c75d015630de508195e1fca9573b61bc549ca017c4bd888194d44" + -+ "3e031f36170215a301f922736a819f3ffda69117170d1933300366c5f2ae" + -+ "1052446ef7c3b82c5868be158a881597132f51c91c80c24ebf621393dc45" + -+ "05fe057364a76ae67494a8a5f67acb551cfe89f447df272ed9c1509fc330" + -+ "2c3e16541452d4d68438f26858724012ad3b72c094b9f166c6bedb8336a3" + -+ "41e032988f39cf53535789b320b5424d07b6bf5f8792e3aceb0e868765b8" + -+ "611d7905089949e0c273e2410c72a146cd63981f420405bd883e5390e985" + -+ "8214a8db714e8400a21d0636d7e5d9671a3582ab9ff032170b8dd6b9d5a2" + -+ "144d065228fa54aea9a22654df67f3f62c5fc59d68914d8b219829b536cd" + -+ "2ae937ecccdb6031d94cb3", -+ }, -+ { -+ key: "84373472e362a356bd5c9b50f55c588d067b939009944f02564f136c62dac36b", -+ tag: "12dd5297cfcec53deae1dd5f9325d894", -+ in: "860d9b2954c3daf18fd67eb8bd9e6e3de2e4988ad9b04b1987219204dee2" + -+ "388db1c59a935de27bce29e7cd3ebdf038785efb35eabd4c3785a62b1d9c" + -+ "3ffa25e2273cfe5eb10b4ec6152cd8f21dea415421b452efc7cc4ea6bf1a" + -+ "b85fa6614e7f6d650125424865386ff8ab53247a63ff023b2d0753a9e5bd" + -+ "458d6ab0156fd3cf2d5002f902f927a847e8c4a8426b0a5191f5e237d590" + -+ "2659ce9be9024750d1d618a6b8dd57efb6c2bbac2930858f1132639391aa" + -+ "9e8a620a2a7d64bb7e943c77753401b5b619d95ef857df25a52b4eb97372" + -+ "a05416706b2644e2687bf1d42c0cf06e5eef8a1fc7e178440bfebb85c44a" + -+ "4837f69e43a1789728a999c5e04291576e757510f22bca11583a4e93688b" + -+ "442f2b2dab8d5ea9441ff09b8287862ca538ad979297cc75510a3d9ef36a" + -+ "662b4b7c373f184202befa5bf3f315642e6210763d033b7e2c59731cb356" + -+ "045e9470bf2f83cd62f11b3e904b0c0b1be99bcb805150ba7ef12b8df3ca" + -+ "bfc5055640687d710ab88e0fa8034b26112ebfd044a4b290b1c6f6d18c31" + -+ "ba9880b1cf2d81b5d02f00d6d351da5dbf47b6a5cb7b53eaf6de52c8a68d" + -+ "053602ccffa37ccb44a7683ab4f8a58c4bbc9e140e4e6f3cc10a5c07ebd6" + -+ "070818db983f9f415168606011efab6b8d7b4e61e8eadd8bfd8d028b89bf" + -+ "b0a16996252d7b4ee4f9ab50fc9d6e482ecf99beeabc38d70efbb9a0d4b7" + -+ "9a1c5d2835adf8e25111352eabd24d562644efc97637f695e4792f2049c6" + -+ "00f4d889ceb951cfe289adf159865d013046985d7fe2598014bf2dbbc528" + -+ "b4166fc2180e724ded8e7ea1c8d66338ec50d955d5594a0a7b4655338b70" + -+ "e8978485a722df814fdc6fd2436dbc060121fcb575672b2a5e454c1209bc" + -+ "2bb21a99d39dcb3c697306dbc2104d60fd8051c43ea2fce268987d0ec249" + -+ "a5c02f91d3b0dfee181b3cf8ef1ba9665daf7ea1f1d3b216e378943b78b6" + -+ "bb41e5dba095748bc776f8df6383033a1f5504955da3f42153b1c7ea83e2" + -+ "f90b990ea0c5bd3906b5c4060b19f447ec7762916b8766e5a23bc4d39cdf" + -+ "8e27752df8129b60ccee1731e47383b589d4fcad865eed4041a186df206e" + -+ "9fb69ab6ea092e36f186a6fea8d77bd7f3ab0fa0e29404d617317c75c832" + -+ "854427848237cfc18486c95f7213b9d53f324da036e8d298133b5003984a" + -+ "b9d71836f9f1b059db90005a9067c261bd85aaeed4d623df2220eb52b73d" + -+ "d683abcdee5cebd411996f853752f638bd28df6d78bec2ed3e00d7beea06" + -+ "2b81c19682ffb2f6abe3a3623a2e0570650c1384f1818d76fbefe3a7ef3f" + -+ "46138160ef897f9934e00e066e215230e719c23905dc60d7fa4d666fa52f" + -+ "e7737db15126d3262c3a4c385cdb23ff3b56c131e43b241f4a6062a1a248" + -+ "de9f13eb82c11f7b6a22c28904a1eb6513cdb11179067b13c7b5f83a58c1" + -+ "4f2753f19fdb356f124f52923249d6e4a2c8dadc8bb0fc91e360155a14c5" + -+ "c194334b9f0a566d51fad98592b59c1cc4b40eeddb34e64f337f83874884" + -+ "0583f853398c343dabc29b9444be1e316309fb8d81304d654b3d4bc4cff3" + -+ "55fc31278fe22e649324ef10acd247c0b72397edf96a1c16bbbef0640296" + -+ "4d219575fd23c36efc1fb8f8a34b510ba9bdfb3b478e236777ef7c6c47f5" + -+ "5a2bd0383d8eed3759456ffcffb15e61985b08c022658a5ffc875821bdf8" + -+ "83f69f096dcc72a96888c3af76db57a54be701759670bf05cc9015f5bf1a" + -+ "745cf755a25b1403a870875701427f820c4b29eccc260f30113629ba03e2" + -+ "785014bdcbf34d0c67aa6aca20d2dece811788686d5a45820d2980bf7d69" + -+ "d5c820a09bad7bd95166f63dcfbe8652565c285e60e2704955d69b3037d8" + -+ "7f5e6567d95b8891276d5cf7c59047d10a02ae4a28794405e2524ec2d595" + -+ "1b36ad1b9d5265fa098a033b88aa66cd9eaf01eea49c7dc4cc51c486f624" + -+ "507a2be23f152f43709b2cfecee44945ca506950e90e70164b77e12e1c13" + -+ "0b4d1021c2afa20038f190096276cd22e89b6e7dd10fd58fa033c9d42536" + -+ "98de3f4908203be8dbf259112f840c76726d982b4a837cae7139e27182b6" + -+ "1b4dfbcc50e42d5ab8532edfbd30f668879824e9ebc34b63ff1526cda81a" + -+ "e38352a774d79f73219500e57f0159a32326195d8895d965071834876a45" + -+ "c1a3c0bc4b1638535f7d40011cd5b23343fc27fa318c1aa3f9d8c43351c6" + -+ "6148dc2175e0e620813266da3000954dfa22048f305244629d512e852376" + -+ "6248a897a3ec3e2983aaa8a0f025f18feea57a5153a59b02604ebfcc7a9f" + -+ "b03e62443df88ead9dee955e23bcf6528c278a353f254c9484a67a7b263d" + -+ "a301923a4efb6866aeaaafd428e6da48781365bc49e90cd16b2388220d08" + -+ "bb9f79d14012b5a8299a651917b6a829488753b6ca449a14e8dd8c5fd5ef" + -+ "657d627b8e7773475b802655dc033694f24376e3b01e519d1aa8365d0e55" + -+ "92d0a4adbf555639b6d75d7ee59a7d12c6c11317b7927f11bbe75ed90508" + -+ "b0698420e231206704d22dd1f1740edbdcaf19a47d66ace4eecbcefb77b0" + -+ "85cfcfaced4d2d6048ce76434eb79990f0898adb4af2c377b581ebab3f3a" + -+ "150f40dcae002d4caa60050591c0de4ba83bfd59a08670beaa4641aa9829" + -+ "bdbb720d6eb8b2f3e864a98676a67271a82cffdca2b3590a0b5f97efa5d4" + -+ "ba062b4798707159782bedc75e5363d5f5d55ec2bef70db22955adf401fa" + -+ "c3b7af937816eb25d54d9f2a92e5a2a04bd8b8d7568204fd289f5ed2e033" + -+ "a76209d288e11e8a4dbb06b9029e90cb186446746853f02d738e06bba538" + -+ "894e03e2658ab3d7f9ac861d2cffdf12396004d1cd15f18812d3803ab9e0" + -+ "6f41c9b374d6a0678bb82ce06d9e3b9dbc8d2e90b8f64d0d040f3fa8a3fa" + -+ "8be71d2b3183cceae1bcbfa2353689d842f7d7052e5699dcc70ab2b58761" + -+ "7041e5aa1e2f41911d525505f061d3ca45152f5a7a1fab50c674e4597a52" + -+ "b46aafb4ba57413879cad1308321843abb7c39696fc2f2e225878bb1191e" + -+ "e151cc76f1a1b8d491c1672fecbf710db82dcd32554361967fc839c8e5d4" + -+ "e488856e1b9382eb3fc3bdc3b6886a3cd79761b02bafa080a745ef6afa26" + -+ "822f1d10d5e8eefb842837d82c9986e78fc3390caa142b7643de8f613e5a" + -+ "890a57f5883409549537f8139534f4ca1b60f33e42be25433f1d82add530" + -+ "6a4cfce258c0d4f1f3c9148ffb5c4b626d51f78ac20bff0393b7fdb4b9cd" + -+ "70fee7f69892c8a9ee089c6c5c7bee0a1b825e5b9517f2c82d6c149735fe" + -+ "45a8839812c2deb2a355b6230697053092eca450b7b0d3242b2689efe364" + -+ "09e820d91fa4932034d96495d9dd3baa4b385da815a7cb69438ff648b326" + -+ "e7efe8d688e88570ba59df7c439faf72c95317a10c984c5ec0043407e9fc" + -+ "9b46487810eac19d2bb40e0a654935f76e7d8861480c5f48419eb33084d4" + -+ "0e1070e5ad542c94f58b49e67dd05b6637a2c67d41451b7e00ba30eff221" + -+ "755d6d427ec634a2b95980d274a89579feccf1c7df3787a9435e588f2496" + -+ "06a93b7ac41c8aaa84b91c95cad9463d4881de7353d95b13bbde4c9da90b" + -+ "f1fe96257309a416407c64368b5564f022c4a493f2a39df1696f45801e42" + -+ "a5", -+ }, -+ { -+ key: "2d0035a30d19b9cbc7a27561f3ab474c01115c4499b4adec660ea06ebaa1a14c", -+ tag: "a2c77b55cb0c076d8ea83cfe0e64f293", -+ in: "4e667580ba4f38f64e5cb5566bffb486dcae10cd17acb3754251e837767f" + -+ "16429bba2b832f29ba538f97f3556548d163be25e69f88fff0743150623b" + -+ "e0a1d82af9384ca335927a0e9cacc3dadbdf1e24fa5c81f2602d109e1400" + -+ "33929e409b9a0fa4f2653944edcb8b3ef963ba7f8806196c73bff0ded670" + -+ "c6def5d240c5f3daa121f8d5bec9b2a0b0f1d62d54b013dc742d6bd46325" + -+ "460f692b76d4991f0796820ddebf150c7d33829795784dd2759b334d2706" + -+ "70a7264941be5d99d460d078a9eedc3660cb3176ad302f9365f0bd698e46" + -+ "9f3e63511abc81109995dba17be1abe8bcd28407c7fc8d02c14794bb033e" + -+ "178a94f6dc73719d5bc235f980a16eccb4121ca83b13c4e165931ae4f192" + -+ "4292f8cfdf1c3ed40feb71e13d919b48fa296dddb4d23114a3d86ec10f16" + -+ "f314de4cef813ed24b49f4c7bc44cb8424df1f70e8d77366161c7cdd709e" + -+ "97610aca3a24fb2202ffe15eaaa25d711cb5179212a2c6497a13e5d7c365" + -+ "7bc502b3d2ebde2e57b714dd9bc21e73795f3d35d620613918c4c9aa0e89" + -+ "031481c97a5a4c15ec6abe42d40498c33d71c823bf1d5bb5fee457e2fff0" + -+ "bf777c80c6e3336ab3ce793440e74b336a8f7034f6ea2e4ff5ea4ea7c350" + -+ "65cf2ccd2da1d6df29bde10f4cc0202b5e4cf7ed097da49b970a6db41e5e" + -+ "98f3845b42f46663b1d1ff01da71389a8737ba8f51eac1ef357ba5ac9a80" + -+ "dd2c7f9476111dcd651fc33f4c86dc8658656f3f02a8878bc38ff0d0a1af" + -+ "2e31fb92eaef08c50195490818661feaf90e8b6f5daa1ebedb2cdbc8d5dc" + -+ "16db3505f9611ac46bc37931e02c1fd6aad6e4b7e187d5e6f990fddc9563" + -+ "2b33f55bf68b0db3890b11113ecc839a4fa4de25160e574289aabe4d8fb7" + -+ "9cecf9d2fa75ac8d0195beefbdfe0815f8d7d9751c1280a29b547149ec7c" + -+ "2295f5afa53cfb516158086bf203357eec2a5db71143f996c81555a47f92" + -+ "209719a71570a5553f1ff9b4b41827dd74657b463f36623565f0c9f4d2ee" + -+ "8735d6af56ceb3b3d0ec516b22f0ddafbc24647481f61ab169e2616c91c0" + -+ "e1f6a35436598ed801670e1dba76226cbd0544959ebe70f836c8a7df575c" + -+ "b907d780ed5aa0d6e4e8e0d2f457efe89a777374aa49d4961db96dbb787f" + -+ "021d99231001360d532a70ee1fb94bd6f26524dd4b7556c6d40e08723d7f" + -+ "9905aca66c4743f2bf8b34493bdabcfca617809a867bfe0a4f94c756a6a3" + -+ "dcd04ffc0a3ac671a0afefe0d5d447efcec48c6368998760db6a572676d4" + -+ "29b6d3d6e0c815650447748c4b27541c5447acfb8f7261b6378f3fc0fdd7" + -+ "375eb9d458648c7fe9cd96344f11aca912cc5098e9ee39e0b6794cc1dc2d" + -+ "f1b10f927102705efa20e667b63a91f935c17764650b287f5289d5790766" + -+ "555f31985c5aad94c652ba41fa9c0195d15405f1fcce9e23054a42c8a252" + -+ "da83bf6268782ba44edec5d8f94a20b1830cd1c5894cc6b9b52ad0b12a5e" + -+ "cf3195a32a0b02483ae3b954ac6f3af1e0f334221279d03a72138f3a2cb2" + -+ "1e706427c4d604674dab88d429f28a67be7a996126e077a1dcf8989d90d0" + -+ "8b08f4abb9a546b3c64ecaa287bf3468c59add86365b885f52afe13ed8d2" + -+ "69ea61832a7ecbb96ff3336f58a1eeaa6dde3611f3ff7c2cc8c9b745b0e8" + -+ "b5919914245a49ac192cd77d10deb9a249623f696065a532c20eef9e9b0f" + -+ "e706579566a9eeb14d4e8251a7750e29eaa60f034c1a7a1d51aa03a45fff" + -+ "89acf41080deec5506128b06f003fa46bc4021a82fad6a8052a49744ed69" + -+ "45bd9331b5ae80d873cd042bff079b2b9d8af8065a22c449c32a56dbbe7a" + -+ "80d0f3e30b9167532506915883dce0aa9cb749e4368c595c5bd33b57e36d" + -+ "98cc9bf91cbfa47331d69b5cbe9c92bc66c0fc9ca8717bfc108e1f710333" + -+ "14dba02a28b9aa05890cb01ae9175806c3c4215bd446f6cc96ec5d08982b" + -+ "4f83cd1646160e1d306b3cdec02d251f0901b03e8c3c35464eaa5082586b" + -+ "b55482db97599d513ed8d7a82e32fae302684b7ede058474c1fac7893444" + -+ "16fec93fb982accd162dd956ba2f31a894e9366eca00e6e997fbbf9a2980" + -+ "8b83a139f6432147a717381bb8baa2205715f735c1e0db273cdda6897c9f" + -+ "39bf0d7eb7caf93f657ef4d3fecea28baf69cf36d3cf347081df3114455e" + -+ "b4fe3e49ad3c3f14435e0b39b6c0d16db0fbcfd7ba8da8760d5952c03667" + -+ "251e7a4c3008cfb0904225e55c23b884bb09d26631650460c4240bd5a165" + -+ "b531ee76ba5749b3bc60adad35de519321c1672b47bc35fb59f7792a3495" + -+ "11b2bb3504ba4a28717823a27a1f99ce6970290b26efcf1e7a0399b10eb1" + -+ "0c1299c09b80f4520d00e7908d004d5b6a72a411759cfa9523f6b2912234" + -+ "481b1d8fe4c2365961c0528bd593d42bebb398b5836ae6ca013fe440adbb" + -+ "0090e8ea274f4d8bcae483e3663051a328f7c12870b40e4973a9797a2336" + -+ "3d3c53e1b0d1a9159bfb26158f44734b3c34b571be641bba2db937d4ae1e" + -+ "edc807b95b1c2a7d44804885536316ad38aedf0d83b1519661f2bb5283cb" + -+ "9c50dd61c3753433e988189f26962d1f4befd444257d0b6d5b819d5fd572" + -+ "22c9fdff032e07a4d8686d451e71de4748965309c0a2d7c422ab7cf3d96a" + -+ "8c0a1b0afb229debd1c9421cb828b9f2be96bb9d6b5be7ef8134bd9ccf81" + -+ "51620937d720d83dbdddbfaba8ecd2eab6f1974090efde0ca963e9fdd691" + -+ "ed0cc5e074c5780779222552fa46ddcd951763a32aa3a044ff4a73cbab41" + -+ "dabb3c2c03fcda68303477f0dc26f35bdb5c9bde721fba1a2db732a89629" + -+ "a8de3cfebc3918df1a9d5053d09da5b7316e3285bf62156ca28cb64d343e" + -+ "72445fd66757bf4ab374fe7932a65f3d7fb6e42cb12e5b67ddf8530383a4" + -+ "6c1ee7ec8883e454a467df1aa7e468a6e7035515f473901efca5d46ff358" + -+ "70e0cc2575bbd7f8866c8e73cb157903a1694ff3051424f28de826984dcd" + -+ "065dc3658df144ae3a6d37b88c367e3cf7c58169dfdedda4a2821ce22188" + -+ "40472ff72f0dd1a6b0100555ff188b80f835259a634405e3dad61fc299f9" + -+ "307e27503b2cb7714bf3b636cc64b61d2e374119c8ef8adb21f1516c7fe2" + -+ "38c807818065bf312003c12e02525d69d9629a99e4ac66ad2e792f302cd2" + -+ "a6f5f702dd28040738a084a7052f2c3ed0924c33b7a5d357b7c9a29cebd8" + -+ "621a4bfb7bb34676ff210d59f7f9d4eafb7c5c490c9ea48402af5bb072c4" + -+ "731bdebcbed4e8e08a67931b6d7342d4ef7bc4a75ca1dfbd32ed6027d8fc" + -+ "b71e3f55565c02e06daa8c579b69774889181291c470576a99e11f2c5acf" + -+ "77e091ef65ed243d4287176f7f6ac7aba6908c9ff1fa43b894a499b642ad" + -+ "c01b2fa1c4b58801411941bb448f1f7a04794d2cfe5db1be61f7b86d6eca" + -+ "c547ee51d4c9050f9e9f318dae958c150acc21c878f0c7df6065294eb1d9" + -+ "a278c920838a0db752b080a32e67ac312fa76b589a385f31847196076ed8" + -+ "1021fcc375bfcc8e1361878e2693860eb21ff0595e4eaaf7897f2b79367f" + -+ "7c4f711279bf0c93a97dcb1cd8d87e444ad5f4cb5c1de44e37868c6743f1" + -+ "cd72cec376726f26c8bd4836f9a9f9c68042f95ca6f9d7cde493e531c553" + -+ "8bf7ace6dd768db69ac7b41ce93e8ca27ff20a83ff2148ec5b89e05d8b8f" + -+ "5d78d0fe16b96f6eb8d3b20126a186085c6825df81aa16b3dbf57eabc360" + -+ "71299ccdda60e250c652408d9cd1da94d73c728440ae08fddb901aec0fac" + -+ "1050a778b10f94f84883bee158bc53b1c001807c43a3151fbf581b18dda2" + -+ "527430872834e5c380575c54b7aa50f817cf3249fb943d46933cad32092e" + -+ "bfc575bd31cc744b7405580a5f2eabe27a02eec31e0d7306750adbbb9f08" + -+ "c78cb2d4c738b2274c7310cbf8dd0e59138b6a91b8253ae9512fe3d7367e" + -+ "a965ac44d54a7ed664e5e5c3c6c2d942eac388cd32beffb38f", -+ }, -+ { -+ key: "2f29d71d73f7af98f96b34e939e1a21e2789ec6271b878bbebd14d7942d30080", -+ tag: "ec02f4953a9a63ab6f2bfc3501e4fab8", -+ in: "0e0950987f3508239063e26a13727fefcdfd2cea6a903615c64bf12d9ed3" + -+ "887f9b2cf7ccaa196ccc7756b09471475b9daefd4261e69abd23b9faf9c5" + -+ "1fd5d5788bb39d3c068fa6807d30f6201d3f6dfd31715d08b1733440cde1" + -+ "049608d23c4e45c5ed61f863350232f85827e7c292dc5f1eced1cbc912e3" + -+ "f5c420bd945911d3881ede5153d3b2cc85371fff98d2caf97cad6ef59001" + -+ "4017f9690cab08989851c2647e77e81401714a93ed9f938b79f8f54e3133" + -+ "fc2cdef259df2ba0d48f37bf9e43792e3a777214cf4aab6dde6deeb543a8" + -+ "813b71b5974136c1220d6218a252881f0f5677ff5b6aba127f19a5f3c5aa" + -+ "c988543d7839a90a3f947c4e4d5c6ae1ab48dbd40456d1aa65339a4c15eb" + -+ "520e8ff9f965ac4c37735937cf09942e7958f8a6cddee41707423f715903" + -+ "ffe0d15af8c3140d3a736d23be7485fceb9f07c6509f2c506eda4ec9d30c" + -+ "cc133708f48d8828e332808c84a745d337296d871b9794de1c5d06534aaf" + -+ "65587526a84e2521f8b332645e0e72564bb308ecf99b7bc69608474389d1" + -+ "686ffab8c49b7f04dadc28d2ecdd0f508dad2135843304e378b3bc7a4f25" + -+ "7fa4316be956e0a021edb8045f39fa9f002087f067199bd6001acaadd261" + -+ "4bf6aefd3f098f92a959685f24bb2206c347359d9c6adc6847117bb434ac" + -+ "6c40ec618f6ae8b75a5e2e4d44c332b7b06c8b4d521493b9b0bde8894209" + -+ "717a24b320214297b62dec741cea018ea681c9b56702068528b3726953e8" + -+ "c5e4ccd5029e4183e772d9834a56a88d45bf87603dfda40e03f7e894766a" + -+ "7623ab4dcc0dfc3086d17566945069173935916f772e2a5f8e1547348f28" + -+ "782400fc069ac0e2b94242e9e0f1ba2d0e76898f9b986540e61ea64d7f69" + -+ "1006b86ce61565da75eb16a8b4c5865ca4eebdde2190e354734bda94fe7e" + -+ "12ff47dcb5d5e6ad93cfadcc491cb350b09ffe391a157e14b65e3a211b5d" + -+ "4e447c3ff95571dbab33a83126d68dfddf9383b4359d4103ca64af1e6963" + -+ "d09e17eb944aa71e76711dca33168586bfc44ebe9fdc55497d83f238c66d" + -+ "bcb16063bc85635f0f1a6280563bca49ef971db96a41b6ac5e0642643262" + -+ "61eb4662f3d6ad4cac826db895de22c9b8aa35e6464a7f44e1ae7238e355" + -+ "068d68754ffcca76c50b7ce7ef9bfebac9eeab32c87d059cc7ef2adb5d57" + -+ "c7419adb394eef48441952253e8391e555730e29789d6293c3696f441449" + -+ "0aebe2bbe541e191a6652ffbec1192f0f9395b7ea370aefc1f1cc8438035" + -+ "d7681f12f1e11d6e334da188b10c302fc0f4bcf1de448090510a8f1d5683" + -+ "0c943a3c388b33a038c26741a4cf3487313f755fe7a28e25e44b5383c5f4" + -+ "cd6ef34d7dd73462226281899dc3f2e69809a0150f694673f31addc89888" + -+ "072a7d4ecd63d6b90540f9522ec05829a7f17d48728345ad808fb0203883" + -+ "3cbd018d612992a88df944b8e34a70920b3f26cda2e8bb16c3aa38b12b33" + -+ "b395c9ba5e809f60ff05f087112151af1b5987403cff8bb2dce79093f431" + -+ "2c744f911a6f3091e4f9ef9375c4dce4c241d2f6024a1797321851ca316c" + -+ "4e460fc060e7839deaff8ab5e8bf682c0f21ab6952eb793cffe690db911f" + -+ "50b11f56ea352942c43bfff51d4360882754faeb7cf28b6b32bf7fc9ca71" + -+ "fbfe1d72be05b8bac9ba513d731e2c9d13d6f2f10eb926edaaf0e3996656" + -+ "da8718a8e103c59326529e91ebac6ed52657c9690ccbf81028cd9fb189ec" + -+ "4de94fc0771e53302c8d9082835a68780cccd772660a110a1b40c57bef3a" + -+ "c1d69428aea549ed17663a96895a66a3bb5ff6ff61dc64908df49b760caf" + -+ "a5aff05e2766a418dbaa1e7d189a9edd55a04fee8c9d6e506d299abc36a9" + -+ "d67be035fea5d220f41d081af67615fe627c4dd04bd8659c7fa4f57f35d0" + -+ "db40d9684aa178d7483ed5d86f04eaea412e0ea05a4698377dbff4fc3a39" + -+ "1f6ce0cb833d3118d6c69319b511cce65fdc74928e270da0c537f8201eff" + -+ "77416155d4a39c7ad38c22cdbf7d2b7ff7d85383c178a835ec604c3f9ee3" + -+ "7399f7dd826e34f1a35ab75da44ba56f86097ddc0f3658ef5bd65a24f4de" + -+ "4255d0b03411a9d7f0ddc29e33cb865da23393471aa94e6c9e72e789206d" + -+ "3ba118aecd39727068f528f01b25fae2280d70033e4ee46b41b864bb922e" + -+ "001d8bf46d6fbaa5a594e926f45eb3a4d2f074506d7834b606f43c89699a" + -+ "6db00b374658d9333700894d440a712a1f25f5538f9e7c8ee57ae7e612df" + -+ "13292c8ba9dbede4fb77cc6c8944aaef59ea6ad3b36db398f4bb0f82d40b" + -+ "44879835f224d6e05992b1b8a68dd58c3dbda2fd73786492ee48c7a25f87" + -+ "264b766930fe9427487504fad17f8d230934f044e49ba219f26ead728856" + -+ "cb30eecc33a3946d3b1b781061f2458c7c46f6d96f3e06f369f97be91835" + -+ "f23b38347d1e381ad5be4419275772c2abd549522a0203c1ee9c96faefe1" + -+ "df413c4b7b2624417890e0716854b7092b3b3b368cb674035d3e6bab2357" + -+ "e7c262b606f7141b6dad2f6145ebc1deb7597814719784f3c17848a90ffb" + -+ "cb0289e2f3cc7da12442b837c4e47f468bca3eb4e944a31c48562c2f144e" + -+ "9e920ab5e4cf90a14ccadbae29af13db38cda911e3c8f6f525e6722809b5" + -+ "31a4de1926ab12f643d25af87eb8610df59eded6ec278242247dc69a4213" + -+ "13f7c2b26ae7a917c1bdaf66c56876e9104d40b59e6ca1431ddb77fc89f3" + -+ "14b46a154cf127688564a4f9e120d7b5816cd24a6e095dc8ab8b43bc3639" + -+ "329719f0e0f723e2f5136d82638e2249e648ebca67cf0306741e9e8d45cb" + -+ "903bca85485c4007397c88a1ce07266f4f611b96b7e0ace3074247a7dfb1" + -+ "cdbbdd66e25e172fd2bda74abde7f3b4cb5cc7ee7859f053b2f04f9de03b" + -+ "a8e96264117f502087c3ddbee8d850bf3618b4de90f7b3e562dfa57e4426" + -+ "5357236e35e71d1669226d63bca50b1b944ac07a1f794e73e80985689b25" + -+ "f18fc709367d63b8639d71865cee667536040be827145c08cf3e57a66678" + -+ "4c81115706a146eccadc7aa1a9f074b47e95bcba7db8108a13279077bef2" + -+ "64699fb87e5abf5b05ff3879d7c7c5169c7cae817c13f0859d4e9c05db0f" + -+ "74c045ecc30a51e515feea627da387ff780719395b5b9ad93179b16fad10" + -+ "5856049169dcebd43a7f39c549762405f807378e854b1654a1179d895ef0" + -+ "85aafc72c7fe1e0e1cd3abf8e20935e331145bbcece4f17ad24ebb6c64ea" + -+ "73bd98a7494c134859206c9422f7c4a057db0ae0770c4bcb08c1a6b9ca4b" + -+ "7dd8c1cdb3e4977c7ce6c1e79b9d6ad98e27d2759b53cee73ec037a8b686" + -+ "f1ff78eb8421f41c74ce9c62a90d38b75159ec925f232e0db71362f31e29" + -+ "4336f5580a34b26c5a01ee3454cba227c7f400f6889a319d7121dcea27b9" + -+ "584f33ac796d48a9a24cc5b6799ee12f10725fbc10d7cf83e4b87d9c444b" + -+ "f43e2f5ee49d8f3b531ebb58fed4234cb8bcab1b8b18bf50956506baae8b" + -+ "c1b7492250f3adf64294310387f1d4bcac12652895d4f2dce26f380733ce" + -+ "0b5820e9fcd8512a1585a49940a32fc8875ac3c9542a4270602e5e97e720" + -+ "90ed71b51badb775340429fdbe45b887fb9ee61cf9e091c06092cf0a2129" + -+ "b26572574c46910cb458bca7c63eddd29d89753d57e568323e380065794d" + -+ "3fa1ffb874543f5b0ddc702b087e91e22604d9600d37fa0dd90d7acb2458" + -+ "4cd408a4e66bb781dde5f39efda6a8fc26be0d08ffdf851e422ab1500c28" + -+ "bf6b4c85bdfa94e8aef5cda22870c39ad49c3c6acdbb3b0d58cd05424c65" + -+ "20740b5c2bce4336545eda12716317df58e6fb764fcb3004f5248c5ccd84" + -+ "f63abdc0dd2a64e447c0de4da4a1082a729d8ebe14810d396933085cde18" + -+ "318278481fdb9a748b637cacb491f5234bfe16b53a35da6677336baeedb7" + -+ "4a28c19a412e7812dace251446d40ec07afd63854c3dffbd5c0f6a9a3cac" + -+ "ee3bab07fba94800fd1fa0fe44f5f2ecb2b4a188cd02b8a2df0728347c50" + -+ "7d0cc58fcd5d54dffdbda11dd1bcc59758396ed8db77498fbe13238d3d8a" + -+ "0040194dfe66811542ddaa658094a9580d4e4b4e29", -+ }, -+ { -+ key: "1285f117bd90b70ef078ae62f37d2218419e894b7d334759ddb2d88833b287b5", -+ tag: "429b2b39195a10357043c9601590a277", -+ in: "00ef065a1adb4ce7108b497813ccc748933fa8442689a7cb8dc7c1ffdbf6" + -+ "c09adfe05ca2cc5ec3acb7493f3497ee8f9cd9bb8a4b332c18e33f78114a" + -+ "c8f9a72ddb9f13494e934ad711818909831013ba195b53f5e9e5b4689399" + -+ "6d0b669f3860958a32b85a21009d47fddbc8697b7c9b92dc75d5060eb4fb" + -+ "40aed7a1dbe69dbbeb6296f5467ea2426cd17d323671fa408855bc53e5c2" + -+ "d111203ae38cecac7719c0bd7f21f6bd6a1588187b3b513983627b80ac0b" + -+ "300b7fa038af1cc8512403ac2cea6e406595202ec3e74014d94cf8780ed0" + -+ "33c570e887ca7fb35ee4768202aa52427d02c24e63f7f2cede95ca9909e9" + -+ "dfa86246a27db757750667c198c9aff4ce348f7ac51864b36ef5695df713" + -+ "d17b8f561a972d0136bd9ee9aa16079c2ab5d29ac9ab472255ade05dc49c" + -+ "b966e0c1c04258ef9ec59ded01f402d9fdcd9a2020a2038a8c78892ca218" + -+ "30136069485527069132959dab2b81c73ca590fde2a7ecff761d95a54d63" + -+ "a2664aa5a6deec163e46b5225bc98976a4f363063b0f42e29f792d138af8" + -+ "eae68d3854b5c1985d5cd1c9f49f529b0b4d2c936887b5b92cdebacef992" + -+ "c35e0b7bbd52114aff8c6b261852e28e451b02099814f809b0289cba0586" + -+ "04a363e3f969aad3d982f645ec4c549f943fb360fb8fa0d5a597bf89842f" + -+ "8ced6014a5b2590ef71524a7ad50fe0ef0e2f81b6e26b99f9ebbc8036549" + -+ "f7eacbf6ab884710c6406ff59788e03ede35c30d4781ad5af171e0623e8f" + -+ "cf5344d71165f0475e256e9159040f702b359a2963116ed135dd6c1d111d" + -+ "2a1e33e15c178ca4f02c5fb15593c50cf9a8a492f01e04778dbb81d26c99" + -+ "0c58cf50a9bcf4fe38fbfc0fc0685d8bd422a773c7bce649f7a86c59118e" + -+ "f5f857b2c72508cd1ef05e1a0c0b7ab4687fdd57437092eb49bf41a9ae8b" + -+ "bd98272ea2f8ee2515ff267fa6ae892c266a7effe61ed54984924aefc461" + -+ "6cf483dec024ad666bc797beaa429a742d1b8806f67d451b6d3a85b4d474" + -+ "003cfe9e9dd906df47da5559c41f15afabecc3e6af279cca0f2a200eb2e8" + -+ "31437e034d457fc880f60f5ae635690bce82bf6d1ad6b4f5344ec042bf25" + -+ "7d010273c861e3ac516e9ee2bab3a255f570baa32298467bf704bf6d9076" + -+ "a4c0b08a528a05cd1fcbdf51f3885fbaba7891a144fc058919903b269b4a" + -+ "29f43926eda32c38853b814a7d528156c223748d674d8f7f5448350f011b" + -+ "bfab1511001b8014e20fee37ccd4a0456f638c197c86dc116b34f955c0b7" + -+ "dee10bac5ea0c2fec8a780ac05098b51b902ca6afff4db3c6fb4f761df79" + -+ "b2039dc5f16d9402442a6fcf6c4297769e6c36824d908beba8e584ea0b3a" + -+ "91b9017baeefac651d0307bd89f517789236c0693c65a5a20f244d39684c" + -+ "eb810cd2ffd3c78fe9285d2eb9f55d133b86113efb8dffcbc6d258e84c38" + -+ "2dd8f4d7d63b65672516d9bfcc3310a79ce244b60d380128d529487f99b7" + -+ "d532d5f5c28fad8b9a071fd2fab8fd98f6d7ed9dadbd2fc4396476eba6e2" + -+ "1a1b1cc594a31fbd3418d98e4aa736cab285a2786fbbd4650e49f9b080ed" + -+ "3fda34941c28d25545395e1408fc3e60730d0696061f821a4d24123cadf2" + -+ "3af3d37ba7ce1ba3cde1368d468f136df82c02f9be9210022192aa02117a" + -+ "ef5ff70bcfeffd47bc37b920826a4d3db001f956939abc0df520f3ec1613" + -+ "ba1c4b3385cad97e42bfd15a3150711fe86ba4562f17780cee1cdf198615" + -+ "ca06270db84986f33e1d53d552b0da82397c496a23c7a78ca7641a908e71" + -+ "89249cc657c0431f1e09ae0213f28a27e6267e9d17b5bba0ea4f3c21f266" + -+ "fe538e215ec62f85517ae6bd87799ac5ce68453f09cbbc50d6e2a168f0cf" + -+ "7166ad50cb65b6c76406c326573c00e04a3186251c6181933828c58f4198" + -+ "f8208c4484805639b0d428fd05b57e4356239638f458a84000c7a7a8de62" + -+ "ec25b54d1e39d2579ec9c512fec475f243576f35efc02a1cd6b0478e2dc8" + -+ "be5f17aa4e3849cd42e76fbffe6e7d6f912d6edf80f718f94a7e48e1fc10" + -+ "6cac29627d9d4b82f05a30cd7c739f7f3ef7ea368d22612f189da450e274" + -+ "de7b61c6361521e684d639be5af4cb11fefa5fce6f8a5065c90873e504c1" + -+ "2c940571ea7bd7e9221129b83039d2edb069e8b5bb68567d8fcae34c6ee0" + -+ "cb94474d8b056cc3c7403873f2fe6db3b567a44e702e4f4813b2a264231b" + -+ "0a998207b41916715ef94e5eec281589d0a711f8e74be32bc60f43d693de" + -+ "77f21d5f7eef892abe87725f3d2b01d9ddb6dee15f40735a8fb67766dbcd" + -+ "020a93b8eef4361dc3a891d521551f65dbe6e3f68c60819b0a540b0991c6" + -+ "4449d207cf5b1c198c17ad6caf3adc628d09fa0baae7a696d84e1879577c" + -+ "ffe9b3f62669d4ea5ebab6364f08c66d170ee4a94d61fb77d60b33dd6b60" + -+ "650f034c5c9879243d5c16f853dd7a89885a9047a341b076912d47872b3b" + -+ "3de49edf7451b435698ac4e182d16c339be83e18531a34aebad36c5c7c93" + -+ "aaf121cf99ff92d3844d40740fe001eeca9ee71300d826bc3cfc87a29d39" + -+ "ea108a3cf259657ec4b967fbb534e7513ef3a96bffb35abc5ce0e890696e" + -+ "54fab515af3d2c0be6e003747504e486c0ec6e30fa4ca79d6596ae0425f3" + -+ "396e40fd37432e52c74f812250dad603b3502f97ada48a26e39fd4d44584" + -+ "6591bfa5ffb3770d95d3dbd49e9c3a38c6305796b8f7d79bd0845170925d" + -+ "575774445299bdf9d3f8ad3dc2dc5cfd3ef0293b84d6e11370851af05ebf" + -+ "b3510a22edd930797dcb76b759a9b5a77ed8dd5130e79ff5ac44b01901bb" + -+ "79603cecf674202bc5d84076ff41b3c806454ce80cb9e5fa9db77294d20e" + -+ "6d3008ae3017aba712862ecd4b32daafef1b8cc8b19ee8f8bc3835e2372b" + -+ "5cec66222ad5ea9df753c033508ec43c8b5995e88c36c13ea3465c8bc462" + -+ "ae0a659d9767db34499e9d01fb1588410257d6f588b3fdb766a66bce28b5" + -+ "e0880f8cf988a2e5eb5bf80cd7d83192b7392fbb2e3a07d51aea2b6bfac0" + -+ "d74d304f56d5af3598a0712cb09c04c5dc14194eca8e1b9b29f88344c0ea" + -+ "55638c0f8ebb70b6242b797fe2525fa1bde76293dbc0a66ab4715e6f9b11" + -+ "f7ecd8f35a20ee4ff3552caf01bb307e257ec0576023d624d6094d43d25a" + -+ "aadfce939a6808f8baacb2109c3de50a1cfada9e384cdba3e97d2c9025a3" + -+ "2377bb195fce68c5569d2d1267e1bc68fcd925ddb4acf567fb29ea80517a" + -+ "7e4056fb014cdee597333ac2408157ff60cfa1afdc363a11fd4883308cab" + -+ "d9a8fe56c2b41c95eaef854f20bf5941ed23156d86de3bd413465a3bc74d" + -+ "5acffcd15722879849c261c1bbe987f89a1f00b3069453841b7da667d566" + -+ "e41fd894d94de44c23fed08d9bdffb723aa8449bf236261240d865efd7b1" + -+ "74a4460e5004ff77f4196d1d421227dff7c78f1726df7b5eebddb4bb5f57" + -+ "5ade25296dda2e71ab87ea2b44ef2ce8742a7ad5c1e7a40e097eb336561e" + -+ "865515f7ee0efbe01d5a928f208f7c9f2f58974d1c11af0e737c673dc446" + -+ "1795da9757010cefc6e7f2784658717938735ed8cbcbd7981a1bb8f31cab" + -+ "b901c87a3218dd1195c59f64d0bc3ce8b72580fe38e6dbf1181e0090e5c6" + -+ "d162df9f31cc52fa6a8ac61897e9b4b3cb0ca2bfb38a38d9b78e46d775d5" + -+ "7645d2d6da16bda8edd8675e2ba121f7f85400cf7cacb9ffcdfae583fb93" + -+ "753d07985a00afc3a4e26c9939a5116d9b61196502f5d774ab4c7fb6cfa6" + -+ "01bcfddcfabfcd28055e858d7d3c19feb6bd7c02565add3a3af61bfba8b6" + -+ "f4b52c072a8613e878368318383143059a98a85ba521f781a8983c2486ba" + -+ "b83f5b91fce02acee0be8d0dda7489975f0506c8f363b5adc48ba971adeb" + -+ "4e1c830b5f264ed42da36d2b5ce2fdab1e63333b1061ec5a44ec1b6e99da" + -+ "0f25e7f7250e788fe3f1b8e64467d3d709aeb7360720f854afe38e190cc0" + -+ "925c6cbd77fbfccc07d8beeb0ce68e47442fadaf13b53c30a03ce317cf79" + -+ "dc9155ddf96814583695f15c970fd0b6cea0b04b1825eb26e65ea9351bf2" + -+ "f7a841ddaa8c9f8e885b7c30b9985bac23d3ce777b", -+ }, -+ { -+ key: "491ebd0dddefc9f0117176772f9bab61b92a1f1de13796176091c56d1e53dfbe", -+ tag: "fbd3f884a3dc2a8be06ce03883282e1e", -+ in: "953b9a40789b206fb507ec2c5e9c88ca1baf25ad24c11a62f664db1da8bf" + -+ "dbe9b54f8e93b0bfb4adb12f8873096b8960fd91eb92a8ddb53232ac9141" + -+ "57caced33424cff943a8db129049af7e7b733afbec6637d8ee4f39d063e2" + -+ "be241cca6a339e48d72372efabceac57220692c40856532d95529adfae87" + -+ "a71c72f30244126d01a875375ad8836ef8db929bc81027935042a05c346f" + -+ "bc94dcc057db015e55c56064d2b11154596b813ee64b73bcac05d2688bf6" + -+ "f1fbb0cf3f8307b3df44c3e2dd1d226a4d0e9dc5f7482bada9611970f887" + -+ "f656dcb19ce1f8c5c86f4cbd1e4f49b18f170ecfd184028e769e79d7424f" + -+ "d01cb315897c21111f53f4d41c3b71402eea695272cb5b4e5f33abb9df50" + -+ "cbdaa55ed629d3ed7d93b43e550295502db1f2ed884afc320518e88be4c6" + -+ "b62a13f8d3636ba091d07dbc6c20c7e7fda016c05b2fadcfc9ea32f4ee2c" + -+ "4893de78ad8a1771aacf6efdbd8fb1f6ee9b0572ced3edc6313185b5d398" + -+ "88ce77950aa4c5201a256e3ae3e74f05b70faada14124b35b105a70e7769" + -+ "7184576b69708eaabd36e0ba885fc6bafd5738a67307a1181792333cddfd" + -+ "a4ef19c88497c82fccff05a8f9f732fc7505f0467a14e135288ee018aef3" + -+ "d0412f6b0760573d8ee4ab455d2789b4d22a42eebdf60616fe403627cfca" + -+ "fea672bd0a49e8e7b80e7b7b8feebce3381f2fc16819a8996a99ea230c3a" + -+ "84b510cf2e0d914610d646a2f45a14268ec1d6fca03d0aea5c9ae1c8d519" + -+ "b0e8b0f6fb8ad176b5d6aa620b253cc492b5e5645353fbd9b6c02bea48f0" + -+ "286e2c669782b5ffefa4d8f3f1037151026d9cca78e7808dfbe61df29e82" + -+ "951d7154f3c97606cd1e99300012578ea6a776dcef0811338b56606b51a6" + -+ "9893fe68f762af6c9c26066b1d503e64877d8cd988b443af66a36af8bdfa" + -+ "41b4dfb3721d1d81895884755b9c52527030afdfaecd66d4638fab1d1786" + -+ "3d5517ef7ee7d081b5555d24991810f1edde30930fd392f817cfe632b4ca" + -+ "6fb0460c36bde4a5620b9c369bf51c7d870c43998b8171a553d2f643fe8a" + -+ "58aabfce8cf7363ea978ff4d53f58284db822ca95b80306ec02a64d26a29" + -+ "c98520f1924c70d161682c54d08a2c48f54bb72980a8cf5babd0aaf0fd72" + -+ "7d5b1b9d9b731dc49bad228fe83f7347750e277a4fbd526983c206e075d6" + -+ "a03d68957b3e925a71bc1ea7304c77660d112a5d19fd21a785d4a8d7f2eb" + -+ "dc4183376d8125341eb28b2df5be0b4e04bbf95c47d2fe2aed939619cb97" + -+ "79548b752f57b723cf8295dfce69c9b7486b75a4e900f91926636f3fc78f" + -+ "7b7720a5151abdf5868fecf1e1a1d830cd6a4c5e3cd739da4432cf1fe2af" + -+ "a1090d6a1eeb32e7236ecfddb9d07b97220ab8e23edcc93d91abc11b0c30" + -+ "460d2027869d1c2487070cf60b85ad0b8bc5df566f6fdb0e58fd044da530" + -+ "6d277e564ca6cbfa820ca73fb6201b240a5a94c4ecd11d466cdc44046a66" + -+ "32478221bfa69b3a2cebd16baa302a573c90895d7f4cab453b11e3a4d8bb" + -+ "b5a9bf264781ce5b9796e3c47d0fa57f46b923889af4d073270a360dae8d" + -+ "51d85ea916f14787c6500d2d906ccaaa92d20d93edd09139f79bfeb5fcd9" + -+ "8c1cdbcbe9f2587e9c9094e3c4a32ab9ba56f400b929e80c0551f953896b" + -+ "e8eda6ecf22e6d4a541957dec21d6a9cf388ff0ba58169ab934902892a58" + -+ "86e1126b16118e965a271495ffa339c49466209ed3875b568a4290b7b949" + -+ "69d0465744a3c2a75c599c3a04ab1a3fd09125fe8f45724b2f48c7822b9f" + -+ "ef95af4b758ae66a8b6646df7a0a1aabe2a24c052fd6d30561cae0389263" + -+ "e3388c4c1effe431a04356c334aac64f36593544885c4b7295b57dc39638" + -+ "b665b22dcbf7dd6da867615de38c6a575cc66391135d47f8e1f0c73c6129" + -+ "17ada4099723933a758d83311b384364263cad5fe14bdd7c825d9601c400" + -+ "3537a5aca7f9da4710c132ce8b0f1464cee625633ef57f507739a0ab1cd2" + -+ "21ae634d4d0b3ff07e9ecb1baaef0a82a97279d46543a0464855cd62c07d" + -+ "5e890265612906a9eac88bec07b1dea5f67054c31ae40f8c673296cc5df7" + -+ "f0dd8cc9e643b44fd90dc2d1e870ad8acdbe165237642fd04c00965837cf" + -+ "bd2344ae830887a5719a3c16dc8ec08bd9131d055bfb959b64ff4cb638a1" + -+ "002a4fe02e369871cc4e3ffda17dd85343e679fab43e11970e60198b424b" + -+ "676ab17fb0dee10cc9c2e92b32b68d5b05b7a559176f822850c0557ed98b" + -+ "7454916e32af549a0027db95f02b88cfc5e7e05f28f53757dd97cc0f0594" + -+ "212f8801e58043cb17b040413c226dfce2104a172d218caa4353890de17d" + -+ "be1f53af6ceda24b8781801516cc51de9ca459e469b3c322be13d8c9541f" + -+ "755c518ca41a0ed42e44b9f87faa2a968b0292216e9f3d3e8987282103e5" + -+ "016fe9f7681496e1e8d663eb2d8bc30b41d735465527f19e336a98d2dc54" + -+ "d7c020bfab30fe6c62cbae7d09f84af69bc2c51a1839ffba15015d381ba0" + -+ "a44a3758771c4f18d13827f518f30bb74f4bff29a87d4b9e949f1063f63f" + -+ "662721cfd64ffe1dab3761852387f78fa83fb48ae2c75fc567475b673da6" + -+ "fa8f53770b6e5a3c9fad951ec099c6bc1e72d1c489e1ae620e7f12ddc29f" + -+ "ed65f29c65cef75014b999d739e2e6e015f928a30f2fee3f2e59bf65b54d" + -+ "89948bf2bfde98b076e5460643952befd02fc1b0f472a8b75195c53ea296" + -+ "6403b9028db529cd04b97231bac3068855fa211f4d976a88bc27a0088f04" + -+ "576e2487ac0467992066ef7667ca8429faee92db38003728e5c219c751f6" + -+ "6f011b5d679fdd957f4575a0cfb6b54693a9624f2c7e66c578f5f0367005" + -+ "c66addd1e3ab7ea1ac404e357cbdab9438b9b4f80b3a6761b864b006f1df" + -+ "689ae4c0434b06b686d5353d3e421b57381ea24fdcf6199195ccdb3d5cf4" + -+ "623a6bb1f9eba9b22fa15395f65f8093b5f90455061c1cbf8128b44a31e3" + -+ "910862a59e187aa7f4d22e0317ae6c177cef24eebc44171f70c25efac73b" + -+ "38ada0cba0b74f72d1c171277a734819c1111ebe46d5db20a6ff20e2c1a9" + -+ "a57edae95a3c1f80ddf2b12c86d3df0078a7bf68695b16ccf92053c727a4" + -+ "80586b8d87d0d1772e456fde0c20a7927f351a641bff5f22f9ee2217b6a2" + -+ "d0983c8102d7d5356dea60a19e105ce366b9d000987c8c33396569f97c56" + -+ "2d0fc0bc5859779aa10efd1f8df0909c307a9110083cc6d9748456c9bddf" + -+ "16dccee52b7974867cec718bb0b76b3353379a621257094277a30148ac38" + -+ "e5cf67ed7cc9c1bae12dbdeb99d7d880ce98e17f0dc93c5330d1824a3c9e" + -+ "ffd86f89e15b59a4bee5a48d4f674766896e187abaa39917b83f8d2f3265" + -+ "bbe7aac44c9f8d92f775fe6493e85ab44e6e28f79f28eff156c21e1abdae" + -+ "d10a291b88c4020b1ae8be001080870847a852d073e82bfc751028ac62d5" + -+ "6aeac1b18f2cff1c0c7d336bf08f8cd5099d9d3b28f9e16077e9caabab49" + -+ "f2d234616a7522a6bde1a3b3c608df4cc74a6c633d4c8068138abda8d26b" + -+ "4ca70f95d152888fb32bdee5dfad8ff4a5b002a0a327c873656db8d6fdd8" + -+ "ed882e47ce8e47c729e1292db9122ce2e9fa275f9bb986eb7e0a1dccb7cf" + -+ "abd0449c92fd35e2aedc4aa89caf53bcd28170cae85e93f93988e723a896" + -+ "10cefb4edb6fa545835fba3107e21dceb272c5a32da26fa77df070f41d7c" + -+ "ad1d68b836199ff0f1221e36b9b976b5e69bed54b5bfec67fe9cbb383484" + -+ "696265204797634594bc335150daea92dbc1004f613b4c27bf5c699debf9" + -+ "4365041b5a894701da68a93bcb61f4e546c553fe61f14ab0322b45915da6" + -+ "ecacaa093b0071f2516ca8c3fef2f1e3c403993d734403c47bfe5f4379e9" + -+ "cb5b613fde3c0d880cecef4101aad8b8b1c60a92ac5185f6c243fdf1711b" + -+ "0b56f0fd8e5ed6cc0f99da888e4f156455a0f0eb365b8964347eedd15d80" + -+ "2f297977af667ed1376dfcc610f5152421b97afaaf16f9db57a435328595" + -+ "b9aa00b5ed9ff106c66970fafef379f4d2f98f2c5984ea05aad64651fbf7" + -+ "7968c8cbc4e959859b85302a88a3c2faed37765f3f6ced59d8feb6c72e71" + -+ "f9d4497d98bccf95fcb650f29131e1df1bf06a5443f8af844aa1a7b5a68e" + -+ "bb250c7de3a65ae9b1086cf83f832050e55030d0f67c6a54ea2a1dbe18e2" + -+ "8a96c9e0dea2966997bfc5c5afd4244e3c8477c4f5e8bee8fc8ca9a5cde4" + -+ "d9c5a2c7f3d2e811b1de7ce4279229319e432674c609b4c8b70dc6172e9e" + -+ "653fe1969bbc2cb3685e64fd81d96d33", -+ }, -+ { -+ key: "b41db44465a0f0d70093f0303bbd7776017bca8461c92116595ae89f1da1e95f", -+ tag: "d8a111a09db22b841fa28367ce35438b", -+ in: "b074b0984fb83749586881e8ec2c5ce9e086cfb2aad17b42b2429d4cf43a" + -+ "0400fd15352d182e6c51e9338da892f886f460d40bd178d81c52e9ab9c1c" + -+ "bdd812594e6fe7a9bb7fb729c11328d3288604097600a0c151fa3d9e4268" + -+ "de75866558e9f47d8dd331994bf69f826fd4a6cb475ae5e18365f59a477a" + -+ "dde7fbcf7e40b4e3dee020a115830b86f0faae561751e9b596c07491c42d" + -+ "e02fc979e69071113953729d7b99f1867116d058a90f1b8c0f9ba12c6322" + -+ "4ebd1b563a87734f5d6e2d4e6715d5f0213e33316500cc4b23784f78a9bf" + -+ "13fdf99bfe149cf47aeaaeb9df1cee140c3c1264fe89bcde8acda6bde16c" + -+ "e3d770ba51950b67ad2c5232ae0cff048ddfda8540cf18e673582dc96987" + -+ "4b127f655e7d4e08859f2c6b95403cd5b4e2c21f72bb872e49e592306286" + -+ "48ba1b16fc9637709636b198f9a297aec364d4c3bc869dcad32b1830e434" + -+ "b556b429136f0012a0a0b6fb3797bc8668014b010ea51674ef8865348dcc" + -+ "197672047fcf72e6b6910a0e32a4f110d85e28db0e338d9cfdec715a8800" + -+ "b4f007a7951d09e41620815848c89f8768344c50bd522c46f64ac6c98e53" + -+ "92176651961c7a70b62f3d1819bfda674e2ecd3167415edc4b97419e8ae4" + -+ "9974b56cd8d52e1d05b82610b59606a750b34844ca33bfc9b21fb970738d" + -+ "b66f48928df79cf67730a30b0b612f8c15c22892120548ab460a6b9bb3ac" + -+ "e30554c86c9681c797821a1b1ce91d0e87fe90ad4097c974cfbdfd5c4c24" + -+ "a5f808f388e1b1473e858f48a387614501c8c39d6973ded69b1764663cd5" + -+ "166be02b596a49e392d637e3d8afc91323f7450318b79d5488c040e346cf" + -+ "0cee512044514b570aa66bb98d639a9ee23a7cebe28474592623d082873b" + -+ "73efb3eaa4721fc4761e15a390497cb13cce181107e8b1a0186b9e47a5a4" + -+ "b67a5be3cd88a43d341ef63f10af6970aaf56035db938655020809033a92" + -+ "8d4fe6d2f5424fbde2fe82adfd991d388edf293cb4e3eb68d876f225a5f1" + -+ "58208bcb1aaefcbc28d6763d267406aa8d6ecb413d18cff7a318ba031ba6" + -+ "0ac4560748c248de64eec56dd4540124b38581604f502d94a2004f9eb1d6" + -+ "edb009e16af6c6d3ccbea79b10743da98aee7ace407a90c6cfdde694f36b" + -+ "e0271e722618a457be68619b980754795f4ac95ebf4f1820b85ca8e3fbff" + -+ "a2430f8e01ab422d7140751f7741f2c921400dac404b04e049736738a87b" + -+ "6f49bd54b1b447b922c473831a65f224ab84fc96e4551a0333bc6187e15c" + -+ "c0f0ad628068bcd7c043bd1e3036ec01e7fdc3d157476149917baafaced0" + -+ "15d09fafb92181a0ec65b00c9c13631e65de184377416e04d3d93b847e0e" + -+ "286c1d88245d4d550d30d4fbfcb416ff26a39a94275631c2deafc7cb6780" + -+ "f149e4d0e9c4515b708fcd62be5252485407a6ceeb9247de34e0266ef384" + -+ "976f6d31284c97468b3b03e951d87a5a00836ea303a266147a79ff3431b4" + -+ "b382e86c74d92661e0f65e266b7d569c03994b667a8137f3080eda2ff542" + -+ "0f0b52b427558dc26932a22a615c9e6b1834a251c6b68fdfc0bbe0e8781e" + -+ "36adf669f2d78bd23509ef7e086634e526258e8d11a1e0be0a678ac09c7b" + -+ "b4e3c5758504011e701dc85997fe2a3e40c7af83f032bdbe7adc10ef1e4a" + -+ "666946c2bf31dd8e3a383211c9684d5302f89dafcf77976d5a02c14e2462" + -+ "09d2d99918e82402cb0eacaa12032ad8316315af1b3d3bd5058f7c935d35" + -+ "ef0d4e71373958fd5e4140a9a586d89c53e4144c00148a4706a524896eb0" + -+ "5b1479a0de5d3f57be46b3f5fa4e49bffe027c81a33e37abc01a4cafe08b" + -+ "8e21fa86b42be52d75d6407e6cdf399de7aedb9b61a6917b2677b211c979" + -+ "33536664c637a57ce2234e3319fe8b4a77d7285ae6347464dfd0aab3e6f1" + -+ "178e0029686770d3b0dd541490b097f001e95f27efe8eb16e4747937d643" + -+ "cdefd49e586ecad541270cedc3064bdb7c79f086bf1fa8c666304d977a15" + -+ "54ae268881e17d8bc3fe51fa9969f7e560e3d3e050424febec0998b35f2a" + -+ "7378b2c3e384cbfc80c4987734d76c78224cb81cc5376f88f0ceda28aa50" + -+ "44e956537c3ee209071d84a66173384e0aa466d989759fb1f2f17fe627a0" + -+ "ffeaae7c5a3884b237f5151278a07117c2e833f1815c7e0e0b1611f25058" + -+ "ca338d21deb1a571faf1d0486667cb7c58e2814c3722d24fb77ce1b7e018" + -+ "2ae5746442b5ad00208b17c0a68bab4df8a8f36edead4fbe79b4c9220dd6" + -+ "acea6d23c7caaf6ce7cabeeca677a1c764d610ea6c7e994d6a9c88f57fda" + -+ "ef160b251e7595578ea2cc1441d480c14b8b6945e76a001891b1f214979b" + -+ "c52ec15e9480d706a40cb6e3b259ee99a9e84e63a738f1b52cf71c8ecb04" + -+ "fc833c2c680bfed587aa1541e5ffe8bbd7b21302bbf745011e559f94f952" + -+ "8b7fad8a37f6d855306a5be22725859cc950bcc334179d49564af3b9c78c" + -+ "e1de59a9cb45086a33856ba7195c17cef573950155bea73ed16645768bf0" + -+ "a5cefce78ba3ff98a54a8e8afc5dfcb0d422bd811ba9b7770a663b081dbb" + -+ "40aefffbeabca955a9638830f0c5d70663cbf5b26067cd061c4a3f5cf8fa" + -+ "4b6678d82d9a2aa33f8538b7499a3466f6b0ae2a1daf280ab91a6c220684" + -+ "12705245f353b4b83db50bedd3bf99d42bde6363fd6212cb745467acb007" + -+ "b678128f6580629a06171f7f3af272f8900b801af3bf47439167871e7b0c" + -+ "33f198333992a6c52c32be46071738cfbf245937d48f816ebb88ff0e726a" + -+ "dc41de4c771ff0bd320a4c0b1fcccd9fd6c42ec9c5185943c70e9a4b7c26" + -+ "a980afe104bb1f99576671a254704c7d4233eaf9915e1d56c103ba9f6e8a" + -+ "46aff466933bf58c9842796ae9cd21f7ac6aa96ef42ca54e390203bac354" + -+ "b7c1de7d1887c48255201335f819020e2782a2ee8af92ceb206b651ae92b" + -+ "3f4fdefed05e08974aee0a353d104b1be9a5e75c7f958f1981271b0a6928" + -+ "05a7a2f28a0448d86102b4fadf9ab4ec2f98e31e64fcfdf2b524780b3342" + -+ "7a2a3100c2032fc93199f3ea7a9e8063fe73282dcb1fafaa9496c7da868f" + -+ "dcf33bbb761df0bfc6fef30fadd2b6efef4fd3216a8aee48a2ef28102491" + -+ "cf7278b567c272d1064a277eb193b3f6f01df641ddb729f72454943cbd3b" + -+ "671ec077f9e3548f5f57d063c653ebee4f228a78f8a128d26f7f4b44160a" + -+ "07e942bab87b2d043c77ecdf10c1a419e0a1c4162a99c21d4abae0558b8f" + -+ "4dc0b7f1ca3892a6babf71f2f70aaca26bb813ac884ee5d71abd273ff1c4" + -+ "add230a771b678afbb12a1ca7fbcb2c0f5589c9ce67fe8f78a8db87825b3" + -+ "09ca34f48ac35aa7ac69c2fb2423807650fcf47ee5529e9d79dd2628718e" + -+ "230ffe5b83f9d5bdfd9c5d211282e71cbcacf972995bf1b13d21419f7fa2" + -+ "8829ed1dcc459da35883b9269a474f7fceff01d44ab78caf1ef7d8117f50" + -+ "cc83eb624062b149a6ed06ddd1cd1feafccdee7122353e7b3eb82978ca69" + -+ "247fde52d2d6cfe7324f04af5259e1b5c2460889da4541b431ba342a1c25" + -+ "3a1b1b65fce7120829e5466e7ad2fe4e0f773c7c13954a9c92d906c91aa1" + -+ "de211f40916596bfa8245344e257e5907a2c49ebcc864cfbe28663e700d8" + -+ "472c50355313d5cf088e9e8a19cdd85bcfc483520498c6386050e53a3ff8" + -+ "1e2b77b55b116a853d71f60d621265166cd7e95ff5cb4466226d7cef68ff" + -+ "d0a35b61e76a43cdcfa8da7fff9558e2f89b981ec6be632b126303ca1fe8" + -+ "53d5c628d967d39317b60ac904d6a882beb0746f6925a86693aff4deaac2" + -+ "e5b64b611de86767d55a6e11221605508b1c5cc828251539b1b6f65c2c04" + -+ "8e65be5422c1b11194eb687d906c559068c0a810713b23b30d8b17f10df7" + -+ "0962c5e7e782aff7bb95adfe4cba9d90b0ebc975fa56822025100b5cb8b3" + -+ "8bdc8928c1a2a8034dd66e2a763696d7ce6cef4dd586b83f7d01749d37fc" + -+ "4fe8d7abd324d4ff1efdbdbfeb0a2fbb8b266fc2bce8e5e5b95d0089e7c5" + -+ "d7de4db837d1822ac8db8198889d6bfe778d0b19e842f12b5afd740aaecd" + -+ "e36e2cefc2cf0b082aa0c4f75684d024b8d828d8f2911fe1aae270251f62" + -+ "4f49584e40bb193577c9d8e04eb16c094653cdf9a15fe9210f724c7a7c73" + -+ "74cfd1a74abb5ceae88ea54f7e7569f8eb674529cbec965ed05bb62f1968" + -+ "8fdaa97297268bfeefd06eb21f700cc56f9bf7f6cecbbbe7278ada8399fb" + -+ "960371a2d5cdb852b11c9fa17650e614c5297bf46cb7889d52bcf49d2560" + -+ "720852822b75bb16524d88273cb366b84b88282da91875562e5a1fe73973" + -+ "afe90e5cdd3f5381612d3ba7bfa058d023a9326e403ec474d8938313fb32" + -+ "bdb5bf899b900c3818c43c8a0af6a061bd26e847ed75983402ee8a9cf4ef" + -+ "85bba5545a0d329ba81495157eda0286f1917de512fe448251697dea406d" + -+ "a510adcb05", -+ }, -+ { -+ key: "b78d5b3019688e6ef5980c17d28d7f543ca5b8f9f360f805ee459717ca0d85a1", -+ tag: "f01babc4901e957d0c2032a7279321e1", -+ in: "ba7d35b2ef8af1118bce1e78018c9314b0c8c320591e103d23f715acb05e" + -+ "dc98fbc618de06627661df5842dbba9f604c2d20d664e5db06e949b11d49" + -+ "665088dbafdb0d39d20beaca7d723f8dcdc57e9c5583d303b6cdfdbecf95" + -+ "7d8daf2f1c72b2a6fa27e3d18841f4841abafd334c110cd2b74efb6191db" + -+ "ab9b8fc8427ee17664082f31db98d30bf15dda967e20730a9ef525abe9f3" + -+ "f620e559ed22bf74d347c9869f0311f33da7f1a3dc858b3a8aa73a35989d" + -+ "b055a4a2c269c95e352259c57de8b94d8de48984ecde426d3ef60ec1c7b4" + -+ "41cc950f7764f55bd0cf52d069b9ad446d1f765f35d02ec104ffcc00bf1e" + -+ "dc1b951ef953acd19984ff1b41041bea0e9f5326a7c9ed97e6aab42174ee" + -+ "971ea1dbe2fd1c1f67f977ab215962b0195417170f6b7748fd57262424d6" + -+ "cf7c235b34425f4047191232722932213b3eb73904cadd6a2e9c7571d7c6" + -+ "6c2f705b5039ff75e5e71c5aa738bf4177653e6eb0b49303a4bc0e641e91" + -+ "2691f217296a3325431d578d615afddf47784e4618a2ca40ccecb05d621d" + -+ "a52f272b8cf84f7fd8177c83af1580d25a764cc06436d67171cb5d1e3b39" + -+ "367b46d9a59d849d87ab6bfcf3fb9bac2b1ebfcd1cef4459e74b0e1b7080" + -+ "dabd2dea79f75581a55de63c4b23ff67d986ad060102933fc6cce8d614c9" + -+ "c86dc84068828dd9e21ffc5665c809d83b09432fd315dfce5d7a4ebd8143" + -+ "181953e3f8716e47b0b30cc1f753e31a7d509f2dbd4177b6da310cf3cd02" + -+ "5db270adf98e96259a5ae1b81f5be4d5c76f502a612ca73c76b91e0ca695" + -+ "aa921f9489948619482c2956205ae71fffc3aba4476ff754e4878e36c763" + -+ "2c935c076857c5b90cd63ea4764efbcee53e2ddc9bdce54b1cbbcf0e7544" + -+ "d023e7c2b79419ad92221a1f76abe31a8236e370d38e2493cc9ca2aaa811" + -+ "30fc713d11f500fd071d6eba6861e8b0859b372e62fe60b627a96c377f66" + -+ "236aedf307e1d148a61bdad072b93d7d2a73367c595b1e048f7023e72729" + -+ "1ec508326f5424a5bbf4e010d0240b71fa9137e6642ab40c5e4fff79877d" + -+ "b3253c663a221b49b3e77ea307c7b9f3f72a0f3a54d0112c45c64a0c0034" + -+ "baf2b55ae36ea6f811bbb480cee663136474dacac174c73b1e8be817916c" + -+ "fd4eb1876582bb3a36cfbabad91776aa676305ddf568a86e3a5eb687fa81" + -+ "67771fca7b5ca00e974b3cc3e322b4bd9bcee2a87d0ae7976da5e04fa18c" + -+ "219fa988d4f6fce62f194b05c26ed3ae1b066cd9751a2d916d53426a454d" + -+ "58f9c3b2fb49374e5791b412fdee1b6029144f1ca787f56fece4f64f4fac" + -+ "bfe4cfd8ba7c807a83cf44008fe5126a283ab2631a87acd8e2a3bd10979c" + -+ "4b07a84a49b0687a45a4798ded0b5e9b2acce30e714d78395bfa8f33ca91" + -+ "e68b2138bd67d8a694cd87c88dcefcd101a3b408d7a9095cc6a4b38898ec" + -+ "c8b375f5a67deaaf73eb7e99b10314ca6bba824658bee85dd731d9a1475f" + -+ "976b7c0aed4b67b088f0db5ca5091273217f724969dff6cf184181377c45" + -+ "5722beb23fd9d097a82ea2d8d527ba6284acc20cb30f2e52af28800c61fd" + -+ "1faf9f4f619550e0162a1a63758e202533889b27420fe7d0eac9a47a6e11" + -+ "1d80054412340e0426cdddbb3c7b9b823b8db3ef58230fad7a3ac21a7805" + -+ "d30878d4ea78dda95c951b7a5dc552e9434c35e03e1dd88652d3714f8fbe" + -+ "a39936cc0717c2e0335371f2a751204f5d9386baaec853f019325edfd1b0" + -+ "719d1fdac3fbd774a64bf957fc54039501f66df94b5b9b82c2076c597065" + -+ "dfcfe58b2e215a3734066aeb685ef97759c704b5f32dd672ba59b74806cf" + -+ "ad5daeeb98d16f7332ff0ca713d541c84e4aef0750bab7477ea707e2e497" + -+ "e12882dbc0765106070ec6a722d08fe5c84a677817b28fa3a41a6117f2f5" + -+ "465c2a2f0eb2b8be4f36e676b4115008bade3573c86cfb1370c03b6b0dc4" + -+ "bbbb0ada4dedac10a593655068a26febc2bf10d869cac84e046c9c846ce7" + -+ "927431f606f07b92abdfd81260199ae05ed01dfa07088c56a6a8de9c6d51" + -+ "d61d6a6d3f9904c216ea8329467a006a3d2495a768a39ef99a21827d2def" + -+ "909bb743fed7209f7fe59ff1c1e710095b05f166c6173deef5c6ec4105c5" + -+ "fc3b87c8269c786bebd999af4acbf12d20453b125f338aee87e9509ee405" + -+ "9c9e568e336304d7be9ffe81d1700555b0800242d9b7450d7256f2b17f6e" + -+ "d46a39f67bb2980572ce73169e352070dbafd4c7fa5a6be78cf9b72981c0" + -+ "a01f1e1e30ee3736c59828b791d2373799854497a28a44bbe0e074925723" + -+ "4986696fbb06ef9ea83fbd49c45a583ce12ff10258ba06127c67b0f66dd1" + -+ "09f1366d8036853973d8884f93de54fb2a12949eefc020717eff47898cef" + -+ "306b5de068411f1e113ffdfe2556e0faedc3e27d95a45b8afc15ba0eeeff" + -+ "eb86da7b4324e20af80c62bf0ceb4aee1515f5912f71c6bf2febf20123e3" + -+ "dd3a82dc1e58a108f1039942dcdacdeb1f0ad0b2ef34488d98d6a52311ae" + -+ "acbd03c12f6e775e375d5979c7c295bb049f2cfd3580e3da3841ddd8e6af" + -+ "4de5e6512ca79cebcab9280554524881da37984d340e8f0163fe10a02ed0" + -+ "88682560bc6d3c4dbcf1a542ffb3dcc2ed16a2eb96896e8269697ffeb50b" + -+ "73f2cc354092e782a0072fc12e1eaff117c2cc8a5a1ad8b47802ac9e23fb" + -+ "91a0cef9e4027595e0885464e61563093ee2b1dc5f22dfd04af7de6a70d5" + -+ "977d3751a4b3cc0c71a71c59c0534cb1f8c0eeddcf1c0e1b3e5ad0d083b6" + -+ "6e8b998ddf9ae9d3b365c851d42e995b9afdf8d66b2ac40bf514ce32e456" + -+ "0880afd38c42c08926067eb243c4b1184e667ba756c14ace5f525eb48df7" + -+ "ebb429d0a23d159664f8021d27dc7167081de331c7114c9c6456e1ffdb42" + -+ "2172a81c06d8deca995e158c48df27261a83f83e0127f5e056a139be9b76" + -+ "e25dadf534d3d1ed6ebc0b5d77d51e5b90ff86f30d4023066115bc11b33c" + -+ "c827b1103098826d0bf8777176b2da6f1e5b580e407ccf7e614fdf4f5b53" + -+ "3ef6d30b20c1bee61eab90e983b1a97173a62720ffd27abb8976a948d532" + -+ "d06596c23b0ef31c79831bead8f8e99ad209af3658cac0cb3c3f9c88379b" + -+ "9bc871d8e84171d53400902da1243f664afeaff60bd96ba2639a7644676c" + -+ "a79f43130af12ba2c877d67f7ec030a4217a72f5368af7c9f24e643db6ac" + -+ "97a04adaf57dbc53762d8dfa1afd49667c4041adcb5ec303e191b786273b" + -+ "bb065cd9f16a3a4a399c6a7aab9c1a6604998264e8b3dbd13d8f2228b13b" + -+ "2c2b9fec5055d8e9f2df1d9a25e4bfe2029776389877bbef7e2c7621f06b" + -+ "c0b7fc0786e2b2d042483ccd4a59d2872a6c5ac73e217123e5c8401580a8" + -+ "d967e0895aaa28f4d25ce68c90b4394d8113bc423e9fae46ac47bc2ac191" + -+ "fb97b80b5a85feb2bb54f84c493235c1408662fe253c6786fcf6fdb8be87" + -+ "dc66a72cc847f94dfb5214af5905b7039a7363a1b23a07853daa26862783" + -+ "ba08a80846fbb93ce98700a4f9961115128dd67bd7d19e0c588fdf6196c1" + -+ "1cb0154002ae862f11421f5dc3a57b6c0870b452272be556a1d14eab1af0" + -+ "a91ff5b89de6bbeed6e03bc64f5efddf9e54da71c594bc5ef78e0192cfde" + -+ "da36e4ad1a6b0b51110c1b24d20dea1f19e18cb1184d80189f842d4f07ac" + -+ "834744dd009aa3771b1e5502fe4b65a403a4bb319e1880ff6ba852e90a8f" + -+ "4fcb52cf374c88408428cdb1255291b04ed58c992310955198d61fa1fd9d" + -+ "762d48f2f65a287773efc67d549981c291b427889d3e3dfc0cc6cd68415c" + -+ "dbed81b516786dacf431472a7dfc99688d15bb6c1b85b1a2015a106e5de8" + -+ "cb9eec4c80b17d00fdcf4a9c64de4643a95dade8fa9f1bc5c839037d86c1" + -+ "3800a244188e3b18561a74912ed72f99f2365f0126732d037dd54a3ab77f" + -+ "9a9f6a1c1469ea92eb707482066bd4990dec4d7614ccb4ea6dd4deb8bee2" + -+ "2c4dc0b9b4d4cc70a500d2c8a5ac3ef88a38439b7dc254a6d920cfd317a8" + -+ "4d7747148c65b6730709e43369d4c995b03c58b9df444f77f216944e70f6" + -+ "6446554d8d513b8f7f28ef0a2d7ad5ca2f6110304196953247a7ac184f68" + -+ "61fba896c2d5a59007ec2b2c8e263957e54cdc1f3b4a145228823fdf0960" + -+ "c33a28f59b03ee4be21001d2f56fd49ed14db33b2c4eec2c3f41b250a624" + -+ "99a9b6602c1e838526a54cdcd058af1c252d56009d4c7769deace53bdb66" + -+ "543f5a081cdde775e61efa70956fe2a7a6019a164c6e413ded314bc928b4" + -+ "aebccb946ffdf3eb33e187bf421febe26112b3262a526de65678cd1fa03b" + -+ "83513705108fe0bb87aa99aceb28af3641c46a2c4427cc1063de01aedaea" + -+ "fba68155d4de494a27ff6b7fcc8f5c5c3f7d3a115c397a1a295bc55aec8f" + -+ "7f150cbce2a8aa4706d54ec863877bb966ad441c57e612a1b5d438b98d9e" + -+ "fcdfe6d4f66e885f96407e038015cf974ae5a3540692b054d2ddfde59b28" + -+ "ede7e2f581eeb56c5b88e2779aea60c1d8ca6107b0cdda1ac93e6c7520da" + -+ "edc66afeed12f980e20e1e1c327d15ade4bb90de30b011a9cb33855ca3ca" + -+ "e2", -+ }, -+ { -+ key: "2b0b0fd3347e73c2fa3a9234e2787e690a11aec97a1c6d555ff7b4047b36f372", -+ tag: "81b1a6633f849ab0aa7baafa58a5d9b8", -+ in: "427f3a7a5f1142ffa68e83df5f917e07b2bc454f3adce068a8ae9e0908e1" + -+ "3e0099aaa9074697593c6d8c2528fedddeca05e3888be1a0a201c389a72d" + -+ "20cb661017544d95a431e70e7c6580d8fb46ea4495bc59db6ae2cd69510a" + -+ "02426c50de1b6110120f759960605aca718d4d0a497e003e1ea2b8ae9a53" + -+ "df3c1eb4f704eb32f8f05eb08cecba0fd4a94f0daa3b0984c30a38f94b7a" + -+ "10cde723182d30588bc40f1f9d38a3bab4800fdd5148e34e396144763696" + -+ "c9b3e9b8adfdb337123d54237c7413f98bb2056152b256e37a27bb947c67" + -+ "240fa3ce8da62ab367db540bcdd9eb873d6c71c75a08fe99b5c11ec8e6af" + -+ "f926d2adfcf073479de394d4aac5fdc6241824d944b8773db604c59afc01" + -+ "495ee755905e5616f256c8a64321d743a1c9368d46418826d99b762e2f6b" + -+ "f998d37a995969cdc1de85f0ce3987c6550459f5e5bfd9173bfcb9e0112a" + -+ "d91f092de446beba14fb3b8ce3fb2f9c941815b2cb5a3b406e2d887b7912" + -+ "bba07c8dc7caab9836827da93ca71fa5ada810da1e5e9b09738524564d8c" + -+ "923746d19c78dc9107b9f20f653e05d7f2eb6bd90cf5eb30fdd7b587eb46" + -+ "74a1064c70ef0af2e75373044d32b78d96eb1db3112342d38dca0e47b96e" + -+ "9307fcdd711b1c66355186369a28481cb47ef6bf6651c2ff7ee4665247cb" + -+ "12b573933d3b626d1c6264c88bd77873c2e73e73ee649216bf0b6d6615ab" + -+ "245c43569d0b8096596f25ceca8667661de1cd60dd575697370ebd63f7e9" + -+ "5333e8a2cdb829b75ea83d72cd246d50358f7c094c8a515805fda03165d5" + -+ "21391617c9f9a2ea562b419632df611a67912d2b369e5e505dbd5c719253" + -+ "16d66cd608cc4a9583a8eaa4661b7279870345fac3031631c1a220551527" + -+ "5be7d8d89b71960e687aace3a0e8f206e475053d6fbf97717b154c75406f" + -+ "2caa97d1ab66048f1c99281c188a2f37b8bfc736c25840a9130ef2031c05" + -+ "6acd9dc10592eddf94f5bac85319b10ae46cc136a0738aa803837287ed7e" + -+ "dafe08d1fcf31d5e63763e39a5e1f4d7d0edab368d44e63fdb33c28905ff" + -+ "d6be406a024c017081b4f2d70860776e9d2556cd008fa5017b58733da13c" + -+ "634938407a118827a80baa28d4e605db59430f65862b90cd8356baa287b8" + -+ "4e6d9199fd80abb9fa697e2c2c4c760128e4ec0438388cf407e2a2fe0f57" + -+ "908187ed8efd4c5cb83cc91dbe6a11444eede85099149ca82921bc28bdd6" + -+ "b9999594a41d97307f8854b1bf77b697e8cdd4daead2aa49fbc571aa44c0" + -+ "bc84a57cb5fd85f06847ad897ceaf449eec45bddd4e4eb1e1e119d15d5e7" + -+ "90957e686acbdda1bbe47ea935ebc4b8c2e3cf9b7157cc6dc03bcb19508d" + -+ "a9e19cb76d166da55559ec7e0995d9b50c6c45932d5b46eee400c56d9dee" + -+ "618977dcf6f76e3e86bc5207493afbc2aae9f569ec9277f33d9f61c03d59" + -+ "dd6d8250ee8cb3e54e5e941afb74f0735c41d52ef967610c9f55b2b52868" + -+ "4b549a99ae3392a7237bb52ff5f8d97327e2837268e767bed0bea51f76bf" + -+ "88bf0286bf22b881f93f1d54fab5cd4e3c148c96c39e7aeef375de249df0" + -+ "4d89d1bd97a7afb2be0cbfd3380cb861d31e4ad1ea8627721e4518b9db3c" + -+ "cda20273ec23549c4adc3c027e3ac9558de2010a0263c1225a77dac8be60" + -+ "d498b913f91391d8b2656ffddb06e748cb454dc2b7226745f11030a6b9ae" + -+ "09ac8ac428d9c6500801fb540650c94610ab70465b1210c6db2064dc84dd" + -+ "7f52573f8f40c281470e85176c85ec6de3c718663d30ad6b3dfc1a3a9606" + -+ "1936744357ca62fb8bb066aa1fcac6d7a2adf0a635cd546bef39fbd3ee0a" + -+ "8802ab0466ec9b049b5892a9befa4377cd199a887c34569b6f90852139a7" + -+ "86babc0049ee2b527aa96b988237a52eae8b4b49d2ee15ee5294118cee62" + -+ "3c3e11cecb836b21af88555f10be2eff8379beb615b7b3d6c01d545cacf6" + -+ "61be8ebbf7a3c58ac5e0e7b17997659a2bf15f2b2e3d680d142fd29d23a7" + -+ "aea9890f3ff7c337fce49ecedaf38573edfae07810ba9806723e576d687e" + -+ "a11700b8ccb96a6559259c367cef4e3999a05a373ab00a5672ce8b3d1dec" + -+ "a414187f383e449d10021b73c1f7e39ce01516b7af96193f9993036049fc" + -+ "72ac059ef36b2bcfbe13acf140d41592880fb8294ebffb98eb428ce9e65e" + -+ "1094521bcf8ecd71b84c7064539a7a1aac1ad2a8a22558fb3febe8a44b87" + -+ "72fc00c735773d4ce2868a0b478ee574b4f2e2ceb189221d36780b66212c" + -+ "dd8fd3627cf2faaa23a3d0b3cd7779b4d2b7f5b01eb8f1d78f5b6549c32a" + -+ "cc27945b5209f2dc82979324aebb5a80ab8a3b02129d358a7a98003e701c" + -+ "788a64de89726da470010eda8fdcf3da58b020fadc8970fafb08a29bef20" + -+ "2bd0707e994015258b08958fc2af4c86c3a570443fe6e1d786d7617b0c66" + -+ "29a6d9a97740c487622b5b8186c529d7f8af04d9f0a9f883043f08103ca4" + -+ "d70057ee76639f3b1046d86928d54cd79fb5bb7b46defdf15d2f8578568f" + -+ "1d7b73e475e798ec6812586700e038ed4791b23ac9439d679a1a4bc04cea" + -+ "e328330c24b065c9cdcdcedfbaf58e5299779e6f48783d29ec3b1643bc8f" + -+ "1095c724dea75770583b15797fc666f787510d91e65a8e2090cc1ed2013f" + -+ "e63ab17bc7640ee817487f4eac8326e9c4698cb4df05d01bae8c0d00fc00" + -+ "08919484d5e386c8f60b8ac097c93c025d74faa56e8cb688d1f0c554fc95" + -+ "aae30873e09aae39b2b53b1fd330b8546e82d9e09bbb80132d794c46263f" + -+ "4fd7b45fda61f86576dec52c49f2373e4dca31f276d033e155bbcdda82af" + -+ "8f823948498f4949bf23a08f4c8ca5fcc8598b89c7691a13e5aba3299ee0" + -+ "0b479b031463a11b97a9d0ed3189d60a6b6c2390fa5c27ce27e28384e4fb" + -+ "04291b476f01689292ace4db14abcb22a1a37556675c3497ac08098dfd94" + -+ "d682401cabec239377dff592c91aca7eb86634e9d5a2848161dc9f8c0c3a" + -+ "f7b6a728371fac9be057107b32634478476a34cbc8b95f83e5b7c08d28f6" + -+ "fb793e557513ca4c5342b124ad7808c7de9ecd2ac22d35d6d3c9ce2f8418" + -+ "7f16103879ed1f4827d1537f7a92b5bbd7cd12d1ecc13b91b2257ad073b7" + -+ "a9b1ea8f56b781bea1bddf19b3d7b5973f1065fb72105bb4aeecca5b7513" + -+ "ffd44d62bf41751e58490f171eb9e9eb6d57ffebedd4f77dd32f4016b769" + -+ "fed08dd96929e8efb39774d3c694b0d30c58610541dcfab3c1cd34970195" + -+ "7bf50204acd498da7e83947815e40f42338204392563a7b9039c8583a4dc" + -+ "faba5eaf2d0c27ada3b357b4fccd1595b9de09c607ebf20c537eb5b214b8" + -+ "e358cd97992fa5487bc1572c8459c583116a71e87c45c0ba2ca801931a47" + -+ "a18ef0785ebbe420790a30278d2d0d42a0225d211900618438d1a0b2d5be" + -+ "d14f8b4be850dc8cb08d775a011683a69ee1970bb114d8d5017de492f672" + -+ "09062d9ba3616e256d24078536f30489e4dacd6429ed37aab9b73c53fdd8" + -+ "a8a7aff1b914b9d82d75a46d0ccf85f48d3ce9a8d3f959b596ae9994ac3e" + -+ "3b4af137d0c8e07ece1b21fd8aa05522ba98f85a7ab24ed8c1e265fadf4e" + -+ "9a18c5ab5684d8ba8d3382ad53b415c73ebfaba35abeebaf973b6f18e0d8" + -+ "7f019420eb34e09bbb12afc5b149f1e9e9b6ae36ebde429d437ada1a2d52" + -+ "b998f7c75ef731132aafc3bb106a2ad3ae11223a355804d4869ebaa47166" + -+ "2df261d95d48ac6eb17c1781e81c0027ccf8f05c39e1eda7793cb16622be" + -+ "ce7a1ad5d2f72f8bf4bdb2f4f4dcadac3db3bf727f0d447adddad4500360" + -+ "09ee011bf4155e5e46c74b00d72e8e6a88de9a81a5a4685651b90e874dfe" + -+ "eba41698c98370fd9e99619ce59ebb8342417d03fc724f9c910ae36ac5e5" + -+ "b46c424141073199aaac34232a8e17ebbfdd80eb75e82290de92968f3893" + -+ "0ab53dc83ac433833576e86fbabfb9d7cd792c7e062811f4cb017710f841" + -+ "1e0fb65ea4b3cd68b0af132cb08330aa13579196ec632091476f268b44ba" + -+ "8f2e64b482427dfc535d40d3f58b4dee99053b35a3fed1cb245c711fa16f" + -+ "c141974c8db04f4c525205dad6ca23ccaebde585cd3bc91f5874452ed473" + -+ "08de95cb6164102744f90b3007e511e091653c97d364fe0cbd7f4cd3249c" + -+ "1f5c452becd722ccc8c6b4e371e2631337dff78efd903a8fc195a90ca5a2" + -+ "aa4513bc63cd43794ff06c5337329055c43d4fb547e63d6e4d14fbe37b52" + -+ "1411caf2f1b0df51a68f677db59aa227c725cf494ccb7f8cacc5a06ac5bd" + -+ "f135a2603175a5fd5e5af615fd2e7cea61934e6d938b9e672290aaccd99a" + -+ "7e26dc55efe928e56ae6354168264e61668a61f842a581cd0c4b39e0e429" + -+ "04631c01320857b4d7e260a39c7fbed0593875b495a76aa782b51fee4f88" + -+ "84ca8ddb8dda560b695323cdde78f82dd85757cadea12ef7cf205138c7ba" + -+ "db6a7361a8d7868c7aefa7aaf15f212f5f5ab090fd40113e5e3ad1ab04f9" + -+ "b7f68a12ad0c6db642d4efb3d9f54070cc80d05842272991bcdae54cd484" + -+ "9a017d2879fd2f6d6ebce27469dda28ad5c345c7f3c9738038667cc9a5bf" + -+ "97f8f3bc", -+ }, -+ { -+ key: "aa3a83a6843cec16ab9a02db3725654cb177e55ec9c0c4abd03ada0fbafca99a", -+ tag: "719dbe5a028d634398ce98e6702a164b", -+ in: "643883153c215352a4ff2bb2d6c857bafa6444f910653cacd2bbdb50ffdb" + -+ "cae23cc297a66e3afefbd85ab885e8ccf8d8f4930e403662fb4db5121aca" + -+ "82dfcc3069bd5f90be4f5bfd3c10f8038272021f155e5de0a381d1716abe" + -+ "0b64b6d0f73c30baf6ddfe0e6a700483cad0fa14f637afb2f72361e84915" + -+ "78ba117e1c03f01fd61aa8f31da6464f3d0c529524d12dc53b68f4d4b326" + -+ "db7fc45c63f75244002b8f9a185556f8aab85948647818f1486d32c73614" + -+ "b8c4763e2645bdb457721ff3901327588da01622a37ccbbd0374fec6fd1b" + -+ "cce62157e64c4cde22c3a5f14c54cd6db63db0bd77e14579989f1dd46461" + -+ "4c8691ef26406984b3f794bb7b612e8b160374be11586ec91e3dbb3d2ccc" + -+ "dbfd9c4b52f0069df27f04853e7cc8b2e382323345b82ce19473c30296cc" + -+ "453f479af9a09ec759597337221e37e395b5ef958d91767eeb2df37069a4" + -+ "f3a530399961b6bf01a88ce9dfcc21c573e899b7951723d76d3993666b7e" + -+ "24dc2570afe738cbe215272ccedb9d752e1a2da00d76adb4bc0bd05b52c3" + -+ "fa08445671c7c99981a1b535582e9b3228ce61662a1d90a9c79afbdcfcd4" + -+ "74def2b7880cac6533ba0a73fa0ba595e81fd9a72ec26965acc0f4159ba5" + -+ "08cd42553c23540bc582e6e9ac996a95a63309f3fa012eac14128818a377" + -+ "4d39936338827bbaafad7316e500a89ed0df7af81be99e2f6aae6bb62568" + -+ "1dfa7e100ebca5c8d70f67be3c1e534f25446738d990ee821c195c98d19c" + -+ "fd901e7722b4e388da90b95ac0b5b5dc5d052ad6b54f6ea34a824bcf0cd8" + -+ "7f1fc9a07e8f5b8aa0793e3c9c1022109a7c7ae97ee2a2867fd0cf0f8971" + -+ "34b3d150d3b24fcf8323de929b73cca01244df02510393f0b3905caa0268" + -+ "7fe35f64391e7d4b30be1cc98319716528ca4f35bb75d7e55cf7749968c5" + -+ "37136eddb149a9f91c456fde51937c0f35e7e524647311077e6fbe7f3c12" + -+ "37b9584fcf3b0f78744c7b2d3b452823aca06d144e4463eb5b01014201cc" + -+ "bfed1adf3414427072135d48e705b1b36ab602cae69428e7c19d39cbb4e0" + -+ "ca26a871d607ed4daa158b5c58a0a9f4aa935c18a66bdeff42f3dc44166b" + -+ "a299d71a2141877f23213b11c52d068b5afadc1fad76387cf1e76571e334" + -+ "0b066ade8da02fe3b0bdc575b1d9ec5d5f5a5f78599f14b62db0bef7ccc6" + -+ "1711482dfa4787957d42a58fdc2f99525c32962b06492229399980601bd2" + -+ "ee252306b1464914424de9aa414a0a6e5dadf8ffbf789e6d18a761035d3e" + -+ "f2ff0753becbd2dd19fc1c28f9acebec86f934f20b608a9ef735ac91f6b7" + -+ "83d9327cce7f4870d39bbbfb0100838dee83e6baf2b40cfc98415dd174ed" + -+ "72e393ad0459e8035dce7eb18eb3af2f39d2712846b9e1852cd61d06dfc3" + -+ "5e34fb761b67e2a711ceb4a82557371ed32ca8db2e4cd7fea0b6bd026177" + -+ "4057b9abc45dae6869cab1097459473a389a80a4523e5de696554f8b0bec" + -+ "0ca605e6acfaa00386fb5a48e0f5893860a29f35e680be979cf3bf81ee7e" + -+ "ed88262dc80af042b8cfe6359cf8b475560bb704728034e2bd67e590bd76" + -+ "1632e516e3292b564c7265d7a6dc15c75ba6f6a447b1c98c25315ac7de59" + -+ "9edc4993e4dc7d1dbfcea7e50ebd0b226e096500216c42de3abe352e5b09" + -+ "a3c9754aa35d00883906599c90a80284d172a90abbeaf7e156fe2166ada1" + -+ "794420fe55b1a166d752d0eb7f04e822d021c615e84777101e7c9f9dd12e" + -+ "565b7d093fe978f85e6142c1ca26798b45f4b8d23ecff6be836e810e314f" + -+ "ebd2ea66f2ac95bad84b39b7a6bac41448f237b45e9ec579235ba2bf5fa1" + -+ "f00286379ec107c743f06ae0d11b57a2f5b32e3bc5f1697aae812d7ca303" + -+ "b196a8a43259257f7697bae67adc7f121be561b2d0725982532ffc06cb22" + -+ "839d9066dce0e4d683d9348899089f6732de62751ca77f1c439e43054468" + -+ "2c531b9c61977bc221b66030f7571dfb3ddfb91d9838529dbc99612f650a" + -+ "d72bb78de061192068941a81d6ac341101aeb745b61bd7a87a35a2714d50" + -+ "c3eb2c3ea148fb9ebed948307f8b491aec277ac01903ba36e6ad54f89fe4" + -+ "280a17f8e7ae639e75aec16d56576f03c2a1efe4af995eb825ccaa6efe0f" + -+ "d6d878299a351591d791c286cac5cb049834580d47a9bb7720d0603e3141" + -+ "ad7c1ec2dd23d3002e15d73c1828a7f08062848b1b6fcf816bd954743547" + -+ "6f0d6f882125bd03095eb1b1a846d535730e258fc279f7095de7c2d3fcca" + -+ "a4640a2e2d5ce0974c1e073c60bb78171c1c88ae62c7213a95d36ea9ab17" + -+ "59093813b85d17ff106e69100bd739ede9656388bf47cc52730766a8a186" + -+ "9dcc623e09e43cfba1f83ae1d9f16789064ec73504c29686760ea02c6634" + -+ "a929ca10c6d334b1751494c6d143671ce8e1e7dcc9bcda25af895a193032" + -+ "ce27c1016ccc4d85507fd2265ebf280d3419f54f66ba2a161c068491578f" + -+ "be056f02f97be745db443e25ed2647c5348f278f4ad8bf5b2a2c2d56e795" + -+ "532e25585984a3a94f435ef2742a0413abed7230ff2e9724187c91f73a7a" + -+ "726ebf36bc8d0d959418dd586452664990889358c56720c1001c004ff768" + -+ "54b9850890ce1b31735fd9f4a3640622ef0b25c659e8a937daa0df7a21f1" + -+ "77be13dfdb8f729da1f48e39a05f592d8c98da416b022fd8edab8e6132eb" + -+ "a80c00501f5cc1e0243b6b096c8dbe7f8c6ffa2f8bcc7f309fb80b489b92" + -+ "c4878fabad42d91876e10ee64ccd415124461cdc7d86c7bb6bcd9133f3c0" + -+ "dfa8f629ddb43ab914c0ac5ecddf4398052229876fd838b9ae72523946cb" + -+ "bba0906a6b3ef26672c78cb24cbf691a5ec869d9fc912009d840772b7da0" + -+ "c7f47856037c7608705cd533918c207a744f75fdfac618a6981778e09332" + -+ "5c7d22170da85bdc61044b4c397919d601a30746cefefa798c58f02cb827" + -+ "0d130c813cbeb67b77fe67da37a1b04bf3f1e9ee95b104939220fb8a0394" + -+ "86ab8954b2a1468016f546406d1946d531966eadce8af3e02a1f59043ff6" + -+ "e1efc237dbf4dfd482c876531d131c9b120af8b8fd9662cef1a47a32da40" + -+ "da96c57dc4efad707a4e86d0b84262d850b451bda48e630c482ef7ede5bd" + -+ "c55147f69e2ff8d49262d9fe66368d1e38ecdb5c1d4e4042effff0670e69" + -+ "04e47d7d3047a971d65372126ff5d0426d82b12b253bb4b55005e7a22de5" + -+ "6fa54f1dfcce30b1e4b4f12b1e3c0de27cea30ce79b08c8c1aceb1ffa285" + -+ "c317d203a9f2e01d542874fc8035b7670f3648eec79561d6ff2fc20d114f" + -+ "ba4fbed462f1cd975ee78763c41663849b44cb2827ee875e500b445193e1" + -+ "4556bcccfaba833bb4ea331d24a6a3bd8ec09906c7b75598b44ce1820a49" + -+ "fca4a0c1501e6c67515d4fa7f88f6aa3cd7fbc6802131a7b14b219e154db" + -+ "9ed241133e10ace40e4d963f904dd9f3bdaaade99f19de1ddfe8af2b3cc4" + -+ "0a48374dd8eb559782bea5410f8f9a1cd128523c0157b6baad9ea331c273" + -+ "311492fa65c032d0d3b513d23b13b86201840d51759021e4133f873f2781" + -+ "8f54f34ba73b4f33107d49c8de1533856ec37bb440f3c67d42148765610c" + -+ "3296bce932c839fd866bec3762a38406ac2b39d0d93730d0c88cb8f765dc" + -+ "d8ee71263fc96068b538da06fc49e25dbeaa10a5111a9af8e8f8d78e6ed1" + -+ "3752ad021d9f2c6b5ff18a859fee9651d23a7237bd5a5c29029db3882c47" + -+ "0470de59fd19fb3bfbd25d116f2f13ef5c534bf3a84284ae03e3cf9cf01d" + -+ "9e984af9a2e63de54e030857b1a071267cc33d22843b28b64b66e4e02803" + -+ "c6ab5635291aefa69cfeb3958c09d0b37176842b902da26caae3f0d305e7" + -+ "c6ab550414e862e1d13d9bb9dc6122cb90ddb1a7bc6d31c55f146659baa9" + -+ "6cca4ea283e5e1639967889543ecb6849e355b6c0227572097221dd46c1d" + -+ "f8600b230e9644ba611ba45cd83fa4ac7df647b3be57387b6db12682018a" + -+ "de9be50a8ea7d5f7c743bf0c6382964bb385b3c207c0cdd63279c16130b3" + -+ "73ba974125291673344b35c8ef9a33be5a8a394e28dc1448f54d46af675a" + -+ "edc88ce85a11ad7e50058df4f3f2364abd243683d58a2b13fcb0dc0eed21" + -+ "380b666eb87f4be75e7f2842bae916c15af3e9658c55408537b2301faa6e" + -+ "42af4d94e3eda6a41d6d302be281e2a9299e9d0fb1f20cf4ca978e66bdd7" + -+ "4c8bea0f15c84d6513cdea787dacbd4bb529ed03528284cb12f6ecd841d3" + -+ "c58c3a57c6bc19b65d6d10692f4e1ad63b091137c8acacc6bc1496953f81" + -+ "2972bf6362cf883bb75a2d10614029596bf9f35e92addbb50315b30161b7" + -+ "de8867a1393d9583887a292cadceb54078c9c846ec30882e6ff987494060" + -+ "721d3c761940b91a126e8d1e0118617bdae01a7f9c1aa96bdd6c78ca06f2" + -+ "6c8d85664a8705334f4997c724ef98fe265985593d5a9c30798714e6de1e" + -+ "bd04b648be47a6b5d986a3103e738a5cd114b19b7ba99d2e2eec6181bf3d" + -+ "ff0fec8c54ae6118be8702c3e775d493a6fafb509712a43ee66c3f4b75b0" + -+ "194c88937cffa5fa17b284d2556f2b0eebf876e05f92c065515198bd5e83" + -+ "00d0db432cb256a4a0f9963a05694ffce3ecbd182209e0b7bb50120f6be4" + -+ "eeb9d268b17790ee14a2c887dc5753e0086630b3123734053aa37595aa8f" + -+ "31968ddae4991af4ab970c1e3cfa1146a2efd9dc42abd6af14777b8a0455" + -+ "3865691cbac4b4417b3fa13c154d581b498f3b8cb77adf0e42dc2f2fb521" + -+ "732447de97271e542c6cf8cad3ba0148cc3ba1f2983ead836a25a2c022d0" + -+ "43ba18fcd009d518d07b53344a5bc4d626b3b38405a114471f75dc70e015" + -+ "d11e8f6f57d087fa72909785573008b1", -+ }, -+ { -+ key: "1793bfda9c8666f0839b4b983776735a927bdaa3da99b13c9f3d1cc57d4d6b03", -+ tag: "bc89cfec34ab2f4f2d5308b8c1a5e70a", -+ in: "a09f661aa125471417d88912f0a4a14115df9a3a19c1de184878291acb0e" + -+ "89ee1f9d8213f62df442f8969a9a5a7c402fea09bdbe236fb832544e1f93" + -+ "9cdd4873802b2bb8fc35ba06b7ff96da6dc7efddfeeda84116bc525a7fc5" + -+ "2d84d2e63cbac00b122dc64f2d15b36595259d81a1d2a09f204c54072751" + -+ "dd812259df1104bb2d2ee58baee917c5d0aa2649c8a1503114501e6ed6fe" + -+ "239847d3d88dccd63d5f842426b600079c6bf06e80a2813b2208181163b8" + -+ "61dca07fa4d88254e84dac1c78c38397a016b5ad55a6b58878f99036db56" + -+ "89871ab3c321f6ed5895f218f8fd976c348b3f1269fcdf4d38c9492b4721" + -+ "6c45f499f5705830b33114d721f9731acf6c69fca681b74c2d82c92e145b" + -+ "7bab77110821d3a12cc818d7595a5c60c4b5e5219376c38a4dd52d435d41" + -+ "562802ff65ba2bba5c331c333d5adf194d29b2cd9ebb55927bb4ec17681a" + -+ "3f5574ad34fb4e964f2c756f6dbbb7a6876a21579a515263444de7a30a33" + -+ "15005458bc137ccfdff18a3892fc9f58f1de10d4de20bbcf860f5f036d8e" + -+ "8a188f18e5cf7ea3cd260710e7491befcb131d49a28dfb1ef688fd021a1e" + -+ "e4420d32fbfb03b47f5e85c37d91e49a1b0db85d966eb5434c4197433eb4" + -+ "9d56f2ff999c9a72230447032dc949202468261b48b6ac212e3f651d6c63" + -+ "03a06c90bb2d3a755ed91ba73bcdc28e1c5b0936e51e0a9f69c3ebabd3db" + -+ "add7abab6d8f6a44daeb3126429a01815f57444fb7022a4a510f8b564ae2" + -+ "dd9779b3a273fef15859a33e233724846c30d89fb78a595b6ff6c834812c" + -+ "00a991e405806aafd0c26a788895ad00a5e43c5426197aa8247207077548" + -+ "ee67db4cd6f878431a2e36e952d84b5fb89d681f553198e2c066310ea6ac" + -+ "3a31f5b1792620616f6c41d486fb844eeacc7fd36971abf416e8d6d50985" + -+ "c83cc92ea46ac37da8f0026aba30c945d8bb15080d2d95e4081bad626199" + -+ "3f95f57ed3252822a7caa035ae22a36c35e280cbbc82d729346cacdb1794" + -+ "ae9a9bb2793fd1d5c47121b135c2836063367339c5151b4e35278e97f62a" + -+ "fdd2f231d4b47812d083a829ebb9c374ff2ae8479cc4b76d55f9cef3ec6c" + -+ "4894f53e8caaeb0d8cd072960cedaf758e48e3640590d4f728626e0a08ee" + -+ "ebf719c96bf8ed4d0c283be09c0ae67b609e22d3b9aa6b03642854909de0" + -+ "5ed52b39673867bf586a632ab8072de15c637cc212cba8387515c9c9c433" + -+ "abd7ba6b02abd09da06a34694ad34f88515b65c0c9c247fdf9819fb05a1a" + -+ "ea4728c1182f8a08a64b7581cd0fb2131265edcb3d4874b009aede0e87ed" + -+ "463a2e4392aefd55e008eb7ba931788262f56e53193122a3555d4c08133b" + -+ "66020154b15643fa7f4f5e9f17621d350ede3dc70be02c59e40fea74dbbd" + -+ "7919d1a8d4e22ef07c916fa65e7d4b89fb11a7c24ddc4ca5f43344c753b6" + -+ "1331c3fa4558738ba7832b5b2a275bc9b7989b6e6888865793329806cd3b" + -+ "f0ba57c941d4428623e062f4ac05e7cd79ad5446f8838f2b247b66bddadf" + -+ "540845a1bb304a04b7edbbff579c8d37e2f6718f8690abd5231822c7e565" + -+ "69365ce532449a41ae963ec23a2a75e88307dc6b59cbb3fab913e43ed74d" + -+ "841ca9f6e4ef96dfd9f04e29e89361aece439c0b2e1943b30410a63d495c" + -+ "522ac3ec1b04ec4cb345f7f86969957ad750e5bd7dbf1d6a22eed02f70b8" + -+ "1cb5b2b020c0694d7f63044f9de0c3de1ede52009c858992d01ebb92ff19" + -+ "a9e0fbea18942fbafb77746c8e9e687dd58ccc569e767528bde43b62c7c1" + -+ "270a5721f1212de2b29a7aae2d6ba6cd173d7fbc78aec4356ce2e8ba9164" + -+ "d97dec061dd0c3a0e3c520a7611ac99739049dd5825537c70b7ef660046c" + -+ "1785546cd99aa400da848eb7c3c91247415c8e245d0f14c30d482c5849ae" + -+ "aaeab2568288229b08267818dae8f76fc674c684c99eb5faf88a0783813d" + -+ "f7298e0b50cb233f78471e5ca9cc3b04927c26a3871cf253798cc49aa717" + -+ "d8f18a1ddcbdc26497d188f15f86ec494dcf8f942c3e07e572385c6fa0ef" + -+ "40c0b625f1737543074a747a369482a0b342a08b3eccac9f9209be31aefe" + -+ "5a7794974f71ac0bc9a58026397ea3dd4f5e40511d58d2a3b45925c194ef" + -+ "13987037d736dd48b509d003a86471d5f161e0e5dd168b4f1ce32f703b89" + -+ "15004d8dfc708a5bb02b2e6fb67424b2cbcb31ddaa0114c4016b0917382d" + -+ "aad11815ff5b6e37d5af48daa5ef67cee3439283712bc51b5adf2356cb2a" + -+ "5181b8941fd78945c7c9d61497683e44fee456ad345e12b4258f15945d45" + -+ "b6ca4369ee792d849112d583fdb39cd4d333ee057355f0abc8d1eea4640c" + -+ "128cc1617982db0394233dbd416102eec1874081247d2982bbf9fed1b1b3" + -+ "8f4da923d68c8975c698f189a4d7840fd7aca9dceb7d91c076f85e1c546f" + -+ "4d5de4f60c91348455aaea30cac134c844dad93d583c139dd52b3be6346c" + -+ "4d2e6864125c5a2d0aed8f67930e1ebf8700ca88aacc914ea76ff17148f0" + -+ "777738cc126e75a2c81110faf02fefc47c91edbab7814599000ce55fe20e" + -+ "f313566e9b62457acf2f22e1141e220bd9d4747417d03e703d4e39282803" + -+ "386327fc65dd597f723ee28185c78d9195fc70a75706c36287ab9c6e00e8" + -+ "5cecbbd6043c6af8d30df6cdd8777be0686853b7c8a55a5b1e03e4431d39" + -+ "1725ff99875a85cae6926998723b36d13ad458220712209bfc5e8d2ca5d4" + -+ "4ea044d5ba846b4035e7ac7e9885f55d3f85c0c1b3d09fe929a74450f5d2" + -+ "9c9672e42d3f59be4ca9d864a4322cc454c2578493bd498a51bbe960e657" + -+ "3e5dd02c4a3a386d4f29e4578a39e9184024cd28d0e86ecac893b8e271bf" + -+ "ce3f944d130817378c74d471bd20a4086f2429ed66c5c99969fd8da358ff" + -+ "5c3be72bf356ae49a385aa0a631b588ddb63628fd162673e915cfc4de56e" + -+ "ae6ff7101df3b33125c9bab95928f6e61c60039b6cc07a66f9c733251447" + -+ "ef9c1ffefa2158a8ddf89dc08686a4cf9b86ea09914e79842d72a3236afc" + -+ "98a3afa0a1cac5590ab6a923e35a2ab8db6410a9d33cb84d1c48a054377e" + -+ "549774b25f50fbb343ecd5db095155cce9fb0c77d09752f62d4bbf16a770" + -+ "30452a75f6bdf73f7807d8f3a6bae16ad06b22175fee60549c22548de9c1" + -+ "3df35ef4e7bf7b66491a62b93c2c3fb0c5edc51f60f5704b56af30f1079d" + -+ "7c385b99f958ef8209e030e381d1ee8d67d3cb84f32e030e8ea2c1d0c77f" + -+ "d6b242a9f48707557c8682a08e1127f51221a55c733ab1edd00a9c2912cb" + -+ "36dde85f73b524e1a4f4da6414c5e4c18d9537722b2becc8a91bcc63f2b0" + -+ "9f32409c53c2beee0de6726dabcd6bf33118a5c23fb9c5c1810476efe658" + -+ "4bb6109c516b45e16b2f79f96755680374d82b91f2c519639a1815fd485b" + -+ "a3c00b46fbefeafcf25554ec5a6a5ae2da07c85b8a0f9fcde50263d9ed85" + -+ "038b2f7aadb9de765655bd201235218bfc74bcad6a9ddf4506167a649afa" + -+ "df400b85752d68a92b7a97f26b334dd77fce824862046b286a7c8e0adc36" + -+ "f713a252a673d4d995b268badf4bec8b8eefe85c25b823b6728582d35c4a" + -+ "60041114dab72b0623b99e2758f6a1e97365279bfba0eb1fc8952ca4f2c6" + -+ "fbffd9f5fd7dcad1125b18a796981b5ead0b6431141315898ace96f0d38f" + -+ "865698df8822ca7b65644b6b1f0a0f0d2e5850d4c93ec48ca3eba1b919e2" + -+ "4413a46d595ffa427715e499db3b7b9ab53c64abec7302bc737a5bd124bc" + -+ "da756abbca132f7f67e6989e09bfb23b497da31bf156bb9c69ae54588df1" + -+ "7420e8fe989f0472c8893b2bfe57cdae265a8cc7aeb39624167a567a6fbe" + -+ "bb1aa30c3dcfd14f2808a070994085e6e1fa79021e77c399f90ab1f995a7" + -+ "baff672cb693bd39b798b4c890b7d0a57978d6b9bcdc5bf3f4d205f8f24b" + -+ "2b43d3ae300a96971c9182be297618b9adceebedba1ab0f324b01d23d7e6" + -+ "35f009db3dbbc643c2d787567594bc639bfd78c4f3e6d948caf06f013423" + -+ "eb3c764666b58f886d5d28137c053c2a28535efcea400147e92ac6753574" + -+ "3b47f9cb48852abed1d057647d5b1c6f334eab1a813401fccd3dae332738" + -+ "776bb223e359f3c459b5c573ba64fa945bdd66c5ac0fcbd53b67032a7b80" + -+ "25f551e8d1fd2a4291bdb7941cbabe3a09765dc263e2bbb6db7077cc8fe6" + -+ "790d4bed5e36bd976d1e37dfdba36aafcdaa10c5f3ed51ba973379bcb8fd" + -+ "203d8b7282abbd271ecf947e54486e8653b7712c9df996a8ad035f41f29c" + -+ "ab81509f922c67dacb03f25f8f120cb1365ab3c1c286849c2722448ba9bc" + -+ "ff42a6b8a7a52f2c79b2bfcbdd22ef8a5651c18879a9575dac35f57d8107" + -+ "d6bece37b15d7dfff480c01f4461ef11f22228792accda4f7936d29d4c56" + -+ "cbba103b6d3e6db86e39e5f1bb9e9fd955df65b8a6e44a148620f02b5b90" + -+ "b2be9e5bb526d0ec75b1e723e94da933a356d7ca42d0ce8349699f730b8e" + -+ "59bac24a6b633759c88041d29399ce60a2ca2261c7eec1acb9a56e0e65bd" + -+ "e37653ce2cf7eb83a4d019c755bdc5d685b6394ecddb9006823182dd8138" + -+ "a1bf79a32d07a8e5e8ab221995c714e571b40bb255b79e328ab883542c16" + -+ "4899fffa16eb3296f310e302512352a864fd809beaab4169113027c6ccca" + -+ "99a92c6ce35c30f9449a3add70f10db1ed08078e8e6cbaafef630aab7e9f" + -+ "c8adb09c18e33fe1af3620d1e4d069ac11325e23cc18e5519a1ed249caf8" + -+ "ddba871c701f1287cc160019766988f63e089bd9bf1af7e6f5b9002e3b6c" + -+ "264d69a8bac16914ab55c418d3a8e974677cdcbea36c912e90386a839a37" + -+ "77b878e680c07c7cc99f42a7dd71924babf7fb0627d1f2cc60d9d390d1e1" + -+ "50d47386be6eefec9ddbb83b28fa7e2fd28cc3867cbe42d13b00545af8a0" + -+ "48cc07016ec79808b180e0b258c564739185da754f2e", -+ }, -+ { -+ key: "0d41cb4ac25217feb20e86fc2490e8d2ea2e8225c051252a9395cc4f56e1ae5a", -+ tag: "42df9f9a59d6dc05c98fd9e9577f7176", -+ in: "01caba7a19cdb09dc0ec6c522c61c628eacf17ef15485aa5710fed723875" + -+ "2e4e8e93dd4bbc414e4c5620bab596876dfbea33987e568ddabf7814b318" + -+ "8210a5f8d70041351e4d8410840642a29cc8d901c25fa67cc8f9664ea5e1" + -+ "9e433eaff7c722d0258ae112b7aca47120aa8af4420d4412a10732551db2" + -+ "cd3e0af6e5855d5eea61035af15a4d0d898d04033809e995706eba750a7c" + -+ "ac07aaa0dc71477d3020f778d0347f1a8e37c18540deb9ae967e734c0264" + -+ "df0e1f52b0b5334805579ea744c8784c3ae0c3ff8217cd3f53cb747f6996" + -+ "f3d2147699799e649061b205f97f7992e147fb20f21ff862c6c512e95534" + -+ "f03075e8e52f162e0d70d7a259e3618474427f400f44f75198edebae6e40" + -+ "a2173257d114e1bb5a13cf419c821eb124d90e89a938d91f4d2e70dfd1ab" + -+ "60446f1b602614930a329e98a0c30f107d342281db25b8f8259933e14d20" + -+ "8bbd991e42969e8b0600272f9bd408483cddfc4cb8dfe7bc19be1989c7fa" + -+ "129d38e1078d094b82e0a845040ddd69f220dc4aa2b236c44101d7da7779" + -+ "9827a7b037561b51e50fa033a045571c7267af93b96192df3bf6180c9a30" + -+ "7e8c8f2b1d6b9391767369625015da02730ad6070df4595eb8099bd8e484" + -+ "59214310cb62c3a91a4fa8ac3b3d7b2017d4254fb465f0a248e1bf45819b" + -+ "4f0360f37c9a79d405e2bb72e5c25a1b4df192cfd524d61e1e8b274f2fe0" + -+ "634c73f0653c7c9e9062c9d081f22a8b0327897eed7c6e870f2815bbac8f" + -+ "585c1bd868759a98dcb5c3db2f6c53244b9cc494a56f28a9ba673167cea8" + -+ "b799f37049ee7b0772972b3a6603f0b80eddb58ef03f916106814d72f000" + -+ "250b3573c97c5c105910d79b2f85ad9d56002a76a1f43d9d1c244ef56d3e" + -+ "032a9bab95fe3bd5dd830ad7d7e341f28b58c0440658f7fc2ca98f157708" + -+ "1c647e91432cb0739d9acdbf973ceb9b0047634d695279e8837b04dc5357" + -+ "f013fde3c55c9c53bf1d817ec59a1b18ed0ac0081ed9bbb3bcd1a5d3634f" + -+ "50f7506f79dc6a4ebfa640bf65682fe9aeca68088e276937669250064de1" + -+ "c19ad6d5c697f862114d0f81d2cc52be831ed20d3aab1e41fe6f476b5392" + -+ "af4799392464c51394c2d1a8325ee2e84f1635d295ee663490e538eb338c" + -+ "7126a8e731ad5c0becf144c7a9cae5c6493350b589385de29e1a0ad6716c" + -+ "346ec4f0a31ca5ea35c59ab6b099f65d7f0b3d00925a1da1b5777c029aea" + -+ "9679e895d7100645dc83f81d82a6174beab2357f7888ea640900cf3ee67a" + -+ "e0724a123919d78e70e05288f67e5e69ffa6f345be8a96e58bbe260184b5" + -+ "ec5c0c1354cfd516ebdb8d420029137d41b029641959cc07fa7b4e16b39d" + -+ "17f36b2367057410a42e0550e9ec1dcd2df4604d52d4f9dd1140d57af08d" + -+ "50e1527dad793b6d649324de799754f755818bf10e6d1ab614958dbb24ac" + -+ "8e2c01270a90ec3df4379c3f509b5ef721b0fd4f91a1bdb8127ae4dc74d0" + -+ "75f6cd8bb28319d6f8e8d8ff64fb4a42d646e9365156c6bc72cc46e9cd1c" + -+ "f9e735549e3df9a8e6b5fe541948b126190117db71fd1d61ad84be0f725f" + -+ "20b99eb141b240326d399976c4f2ce5823d94649a9580e1e8820bf49184d" + -+ "fc34378a60bea89b12aca69cb996c17847b7fb517cf2d51f16d78e3875ce" + -+ "aa33be15f6a154004f0e1134c6652c815c705efc34bcf35bd7743d28f0a2" + -+ "77d82dea4709dab41fbfb4e0cbc118c17aa00808872f0edc6437c357cd31" + -+ "74a02aee61890464e03e9458853189431bf5df6a0ad5d69951e24be7f266" + -+ "5bb3c904aa03f799fe7edc7bc6779d621cab7e520b5994f81505d0f01e55" + -+ "96e14b4c1efdf3e8aadee866c5337c1e50066b3acc039c84567b29b7d957" + -+ "683cadfb04fb35402acaba631e46ca83dbdd8adf28e377ec147e4d555a21" + -+ "e6d779d7c5a3078ab72702234d36ca65f68bd01221c9411f68f32e16ef04" + -+ "99a20c2d945fa31b79d9965853d38ada9d48eead9084d868c6bad974b0f4" + -+ "0956aa0fcbce6dac905858e46c4b62c0ee576b8db7d484a524e951f4c179" + -+ "decfc7d6f619e86dee808f246dd71c7e0b51d28bc958110d122fa2717148" + -+ "77823242711632f6e1c7c15248655ced8e451a107707cec8c84929beece4" + -+ "efe5503d3c1763d0ab7f139f043e26027d5e52a00d5414dd98a324a8fc2a" + -+ "06a1345cbde747f41099c3377b86bbdc5a17c8f6e5b773a761f78573832e" + -+ "4359b143810361dedc79142fffc49ddc0b32f225d50d360ceec3920fb0ba" + -+ "0693b644ee07fbd1ce829e223a02794b197614061c4bfa46112d105c2b7b" + -+ "4efea448501d146dece44f6640d674d5749db498b32969de6e165e705a18" + -+ "2aa1f3d8e16892b0120337640d52c9bee35e5b4b17f03eaeb31205c8ecbe" + -+ "1ae1b110023016e40ee87370a65c5c20bfb00f100d3c6c1de6e4a1c90162" + -+ "f25bddbf300ed637330206788a4ff96903f971c9618493ad074412af625c" + -+ "ff9e0f8f183bbd5e96c1f28307e6cae8b50cc0eb1a3a8154e44e9de947af" + -+ "002e4d1098d6b0ee3f2e71a10d03eb444729c42461283f37be8af2ce81ba" + -+ "bac246a05c2c94efacc43f0cf9ff3df38ab6fc1648c796ae7026ea95752e" + -+ "b70873a6da59da10d8b5316126431c4a17289466e95dc739c061d7a4b13a" + -+ "450809479eef421bddcdade77a6df133410328c754af8999a09b1a5c056b" + -+ "ecbb6fc2c339586ab92100f46d2fa1fa689994b36aa70703d76bf7738adc" + -+ "f0589fdfa6bd215339ad69ed983f62efce0add5a63fe7dfe4bfa006ff16e" + -+ "0cc06d39199ad60adcae12b75ca98d764502a783373da3a41281e03c2037" + -+ "e1b3ca7f7eb60e2b67427e97ec72d36670db7662c6daa505701fd279f116" + -+ "ac0ef569471f204e1531c25a4ac3ce19b6f68a8994b6f89b5abf034a6507" + -+ "32c7fad4206eb4eaa7cd9a710d866bf3c3f13c16faa268ae0cf4f69be909" + -+ "bb9b79aab80dd25101d4cc813a48d3f38d870f10ac0b6768005aa0e69e87" + -+ "dfc0424deef06414c9ba6f498c93c41c692a7a6221fb5595b390a32c70e0" + -+ "2cd64471c797ee8a143725849c1e054ee2043dcfc0b4cb1c00be21a14be9" + -+ "2d9a07f1b4e975d4c86b8a5c1387e6c42bf393e078fe86d24612d497e14b" + -+ "874485a3cc922b5b6d91295d7b79ab8bfa1c7f64b51e761d19bb9da82a5a" + -+ "a34aa469699036b6b2c55e2b84f84942f10585027ab07e2e0e562e0fc3dd" + -+ "36047850ded84be4416e22aa41c7a2f7d4a4d8e3dd420d746a1d8d56d87e" + -+ "5133a1b4380bd9a89500fd6d7e68a1ec02eb9e79e4a13edfdde1273466e4" + -+ "6b0e6a75f59ff6175716629da52463ad21de27f40fa2e25a566eec4b2696" + -+ "4af3a717dfb0170a73144c0bd9b00bed67ad8c0a146eb5a055812d071209" + -+ "c9d530cd4f50a41488c2238898dea8bb36b0f1496d3ea8c4ff8e263b367f" + -+ "64977679e697d88e5295bd97ac16a0420850d1ead9621e25a3f58925c266" + -+ "ef5246488b1c15a8fe0d8ec4291864faa5a67b2388b7786f47b6d27e8fe8" + -+ "46f85f85163e54155ef95cea4901e712a44404a4d3f27f28dd961ce36b84" + -+ "f3856770f07f20a2ebd34d77405beab04ddfc09770167d7d6340f494dc6b" + -+ "7e4c3df896bd974730193b1e862b58d4a5938e6e4ae8897dba8812924379" + -+ "e54f51a71364d39f76e24fdf2c6c704479ce85b456558ca6947b8fd76f03" + -+ "78273f0a7bcd1d860ef1defe4eea8fdb81c73eda028d82fdcb2248582ac4" + -+ "59eb7698a811e6c5823be886410f6b8577ff2e8252343b6ea890016ae846" + -+ "01c5894cfb988121059fd9c8fbc1596da470a149404fc67baa15383d38cb" + -+ "d17ac107b4ff3c1ca4c76b7930de02b240e7547d39f4978e0cc1fa37f8c1" + -+ "012b677f07bb4df4486196e9b0beb823a3827585475b878e3f6f0a2d3836" + -+ "2c7d34f9f3c91ed46c39cec95c2a0b6f0279a03a00ed5035b0725c393849" + -+ "cdb1ed3c0ecbcf3c2ce108017f468e1c3d469c03e8231d4195344ced70cf" + -+ "daa667252cc1554dce8d0c54eb4cf4da62367d77d7dcc02f81e788ce9f8d" + -+ "d306ba1b48192359cfe92bdbea9980f87ea0677d7d2082205a436cf514e6" + -+ "fde5eadd21b13dc836ce33b5dfb6118bcac79ae00fbb16d61f00a923b145" + -+ "f9caa9f3a2c7f0104f8b052e390987e57c8dc80cd5f0358afb0111af1fc4" + -+ "e31f92bd832ad35fd2e0bdf768272de52ce0b152f74d43a8973ad516b3ea" + -+ "f5937ec8a236ebc86adeba610de0cf7168453111f3c983b64df07678cae0" + -+ "a75466ae15adfb127328e716448cdbd2c1b73424cc29d93df11a765441e0" + -+ "0eeed72228e1099bd20569d9d0e9e5a0b3c11d0002e2896631186483db61" + -+ "c1a0cb407951f9b1ea6d3ebc79b37afb5a7037e957985e4955979b91fb85" + -+ "61ca7d5e8b9cdd5b7ce0130a880d9241027b011fea7696b0c695d4949ca2" + -+ "d0cf22d44b9fee073ecaef66d4981e172e03ea71a6edc7144393bfea5071" + -+ "2afac137f091bae2f5700bfb073a6d57fddcba674a899d7349044a10aadb" + -+ "2e7f547887dd2f765f394de5dc9ef5dbf1eab4d869be8cb68aad8e2614ac" + -+ "37bbf21ccd5a832ee09fdd07ce50a580a2af36256b1046e646fe3dff6d20" + -+ "0c5110f1ad1311bc39b8114cd11ecdb87f94df43d4f6468932fc0ed892d0" + -+ "3d8f3db3f8323ebb29776ab7d260493a36700bcda668abd62126a8189e91" + -+ "df2d2970ef688d4e8172fc942e69ba63941a36b79ac546fff38f5f7d1176" + -+ "57612a662ea38134e1090c3e903c9adacdeefd3ac2a0467e9f5125058c19" + -+ "7b2260d2afad2b0e627a9ae52cd579ee27168065658089e1b83a2d8cdb47" + -+ "e08966e4ec0018e78c4d267f9575b8fea2a42de5c2d25356fe4b8c9cb1ac" + -+ "daf0d1af4bf58b9704cd4bc08471e3b9a0e45a5693433ede2eb1374bce44" + -+ "1f1811cdc7612d7bb61f4f34aea0a44757bbcc12a55c1ba41a7901eb004e" + -+ "689587a38e5b4df4574ddcc7b2eda97f6e480d7d39f45247ea3b03c90a93" + -+ "0dd168b65d52a59ce9c2cb4e860cc6aaa0ee02a58d0c8ba990194bce80fe" + -+ "8c34ba5693fb0943ec2cbfc919e534cc47c04f502b6c217c2f860d1d482a" + -+ "a016aa02adfc2bea3171fc4e27e2a262fd37b824099aa227fccca508f778" + -+ "b8c6ec7aaff1d15f6497753f439daa9e52060fd6e9e056e6843d770fb057" + -+ "6d9e2e782db4843c0c2c7f408a17376719a3c5cf9fa08f04f8a779885a16" + -+ "5cf93ce404be", -+ }, -+ { -+ key: "ddbd5d6c5ebd61fa72b453dd849dc302c98a0f3e300f4768bf1dc698a3827dd2", -+ tag: "af608b71a353e63c64911558baa122f3", -+ in: "c67e2524b0de16483158a0232078fadcf611e4fbdb9e642e397b21222423" + -+ "cc2ed42ed34ffcb178448919ee337eff9d7d691f622e70fd3317cfd271df" + -+ "fe6a9d9b7e07db0d20813e2331164a654386db2ab06ae2983bf2460eaaa6" + -+ "3aa0171fb87afb82e85b40d95c8993b2039d32e9d38473dd13f41fb1ff1e" + -+ "261752ab004b221a4472b9b1a0e139f0c999f826a26a7e7df362b0611aac" + -+ "fa83c55cca2f7c0138d2c30313c2f6eb357278328ea6ebd6a5077947e18a" + -+ "a97c34b9dde3b6f2de4b83778ffcebc8c9cb58756691d5e2a3d15a759a2e" + -+ "5050b6da937a6f5551aec069a08027d60dd870d175d2a5b5f0b4f3143904" + -+ "7445c368a5c866370e9426abbc1a1c5a272b96731c4128aedeee93e8e00b" + -+ "b450601a6d31ea279b9450e738b4a47c0dc22d2d8ed5d44257f6318e0c59" + -+ "b951fb6b57746062ab95cd73c23ef0a5c000a7d14c18bfff172e59b6f6de" + -+ "aa61b81009e803eb05e24fb0b706870e18889a9180ac16a042d12dfff9d9" + -+ "1b88130f045d2342fd5ddc5f443681c31090459f262d1a65654c55251fc7" + -+ "d5a67bd2e62940ccd606f3e50700e4d1e992a3fdf0388b9ce3df9de6dda1" + -+ "5c1cd6b70622ac062dcb7ed7058872c00ff3df94032853927126cf6fa4cd" + -+ "c468d91c9b52dcbc272fd7ba920dcd3ea1e048af9c3286dba74d988ce9ce" + -+ "77174e25a87935352721dc23b60a9549322fadbe6a00dd1197dfa25b33fd" + -+ "9e5713afcfd0fae6dbcf27147fa58d995580d7e0a903c895752fe9819f5b" + -+ "b002ed752719552d0f3575312f2e618173a8ae7c147ca64a709053e5d2e1" + -+ "2f4d1ea337afa9ac4f9ba62760046ec1e48f4ed8f6df66786c9fd9f5bc7f" + -+ "9ca2526e1327b042f4657c405757690e190c91f260dee2dd3d2e6616b721" + -+ "e489c7c3cb828478a3d953b88f09904e7927cdf6dbd6a5419eeeb83c0be2" + -+ "51934a80dfe61e09442f0761aa2d013e10aeec3a32df204571ce8984a430" + -+ "9bbe30ccc91977790bf0305d2651ee450b749c3e7761534e45970e70a0a8" + -+ "473cadbc88f096970c275f188c9d2644e237fd50c2e24c1eabbf7578e80e" + -+ "6500762ac513fcd68cf6f8bb7a9d9eedadca059d9ecec07fe6fe7792b468" + -+ "9311861728dd482f087c28374cf9c5ea20b2c8630029e8485fa6fe518c74" + -+ "ef77d44eb7526ca764e50b5f34ed0f253a91fb2af6e59338e2af6e041e01" + -+ "084e1efade1aebb7d1b698ccdb8b4248ac89cd40d9517d840960c08f5e86" + -+ "88d8ba2b54889c1870d315498b70e0e9720f2c8c53a3377a8c0bd2d6a1c6" + -+ "f17c6ff847eb14def6855dc3886b99039e528b421ccbf6064e39263f8f3d" + -+ "340d5d20b1b14c264ac2310b5f3a0c6f0c1006d0d4f1a69af68d28ab447f" + -+ "cd17387e1fc98f164982a6d05dd32d6b4f0f1b04e40c6c6e0fb4467dd6b1" + -+ "0c5a9c92cc8c2bc97ef669b6d55cdd0aa8a15c46af954359165949012713" + -+ "4ea9f74181d54a300d3172c9f01db73288ef6a709c763a4891666d0baf88" + -+ "8531dcc77f0911412d096aef9033fa36b5c1ed283b8b5c109e45b5cde911" + -+ "6f3da2533fa0ab81929bd5783271d5501a9e4fce2aff9eb5a70a4215b253" + -+ "46885d7e4225fe34bb55b309a114a312693d60ccc61267359a8c2dd28141" + -+ "226e7cfd99f0f12c69df57d75dd790dbabfe3145f7fd1a24fa58e03bc2e2" + -+ "6ea19288af4929e5acc517d8f52a074745ff4644d94179eae6ba7d267292" + -+ "bbd2053167a0da9be5e4b6cd0a4200fcac5182d9957dffbefa857e662b82" + -+ "fc3a7cc32506e78030ed5c5d448d7f1b4fd854a735a0c50016bb85e6e716" + -+ "0f87527bca0de235f4b7dacb75be84919c15a5b8cf6bec035795cb67061b" + -+ "7855c2134c1b1bfa6affe04b7db239f73af6ea9c02bc9f7972b7f6400b6b" + -+ "838f4653aefc42179c21765e3ca7a5e96b4402ff544d4bc2332756a23500" + -+ "11241dc42ec6848afe127c00b9c333e69bb5a54ea5c7193e59ea22bd6d32" + -+ "af4f56b1bd2d5982ef7d9c1b02d7668525e4e81b68a400f7afc2653f0f41" + -+ "a03e11c7a02bd094830093481afbab96397245b9f37a568ea1c4ae248cdf" + -+ "afc87f88b1fb5dc300d8e9039af4e6e701b458ed3f32d693f2e869b76bb5" + -+ "1358cbbe5b5089013bf452734388a176cccfc1ae9b7cff603631ca48e129" + -+ "b5c9573d4e379547272cce8aeeeb407d3fc57f782a0eb5fcbd41e6fb13be" + -+ "7e4f1067cd407b42a6121b2969c384916ba2b32563e659f52aae09c8ce2e" + -+ "3c500fbb7e58be74cc1592dcfacd9f0d4cea1a90a18658147c81cccf6fb3" + -+ "078ed27f369e7646f551386a74e1b07074d93e0c1f298c761af46cdaae9f" + -+ "f4be86808b66d0e228016d27a3a77c843365cb847fddccb0bbcfb3b9008a" + -+ "1bacac59ffb0aa759a0568c72c556caf0ac1091431b574687c5fc7bd486e" + -+ "963e0fc3bdc828d988734a21070747c955cf8dba2df1c3a0ba8146cd58b5" + -+ "91b6d54712db67a9851b1607c8445bc97406eeb7488f5f85e547850d619c" + -+ "407f97632ca1801f52c09c2b314b4ab0f8e7fb5851fd60852f4666913ca6" + -+ "bc840c1ec8f8f06caefdbfbf02ce00f20b87b14ba9e651c80f40a31d0306" + -+ "403f541776075fbf23733a6b19e3b44d04b455b29ef8effa70cce0c59331" + -+ "7119abc07aa8c8d0246a760b0b36a3d87b244e83bae8a745b8277a531298" + -+ "f5d0283498a509c89898ddf0f7a7455be1f8a6889c46d323f1dd18c3babe" + -+ "1751a05f871f0639f50967afa46c19cb93d9c2a79c81e2436a7a62f225bc" + -+ "37c90698640f5b43673e1dc276de05ff1e29acdb4ace5121659db5f23c49" + -+ "57aae22f53e6f2cc935824fbd07c2ac87672eeeab895c3f06e09e178560e" + -+ "2fcfa7097f10201dfb8b1ebac08ca806c1b3ba3aff9284846a1a3beada53" + -+ "e9f7ade12eb89b5591f462b2543bb4090e081fee9fb53bbf821dc92d6b16" + -+ "fe820ab2ee4b1f6c0b6a6f19edb0bf6479e257fc73bcd60dc2261d0a4752" + -+ "e23a0be18abf355f3065177d8c3c14e21edc178d0abd1b39f703e6335131" + -+ "ec90cba3d9846cee7354a06c320a3f61b8a269abc7138831614f57ca6c19" + -+ "a4a621142889cd924bf4ffb82b57f871b854f3157e8874c22d43a5726900" + -+ "bafbb8f2260a1eba3a462e23d4def2ccf68ebaae8e52739a1ce67c039eaf" + -+ "9a6c3232fbb5a91d1e59a8dcd3798ba71345fbf83d09b83b41cc49d5ff5f" + -+ "2e809d2b1d5fbc1e7001ea76b9b2d8f896eb6609e2e1c5c562d2a6e74960" + -+ "2d67a0f6b43a201d5087509b8dc7b0440144e308c18ff8b96b607de2f20c" + -+ "6ee99bb05367a8b25947011889f724965a2b5c52c9db1e0622df9343c548" + -+ "d054699badeb15fc41055af0d79a2bfc1a5b4574634fa0dd9dd10a6213ed" + -+ "b6991187dc560facdc27440456a0a209fd7f5ee4fb350ae71f869723e5eb" + -+ "5338e3d1448bc993afca6957f4cc7b047a2c7c9593b7234725e66cc0eb23" + -+ "3824eb4cb905701cc522ec210950b871397c6c0bb3d0b839f2eb1a120f70" + -+ "36107246df4dfb2c24891bef0bd1dc131f2c9d7c295ee967e3184d963037" + -+ "fcc9e0b8c7011c8e04b4e70038150d34caab4f8c0230418cd2d8a91146e4" + -+ "4e11cf6707452ddc03d9b4e6380658135dfb48f62c0690ebad75167f4dd1" + -+ "c0df3ed555b5081a7b82616d9e501757c83c2193d0f640236d59f9c97a4a" + -+ "5c8bf532aea2cf5964ed2dbd8a70c01ca5c7677224cf2a37f3b24d8fe4ba" + -+ "91cd3b5033715de227de51deed15afb8eda9d2b9615d197b8f98322d7096" + -+ "79c5131eed48050fbe0145a9284e236605c25a4876e2adba42f4e35a8949" + -+ "3d59bbf44b3338d9d2e65a7d7ec6c863cd47cae9e23181b07298078a5e9b" + -+ "06a5c7e1059f474eb1a4247e8f02cdd4efdca67d22035b12abecf9b15982" + -+ "de4932a28e797bc4de38442cff2cba263eeddba0ab14fc706dbca04eaca1" + -+ "b4cc13000a10e35b32461424809b299798e4d8e66c92aa3181c5df16ab65" + -+ "9611cb625e895a8021af8c60960227d6f2ebeacb17b13536a5ff139734ef" + -+ "37cb67018ef9a410b856e6f6eddbe3f59b088d538c50a8f3f0912d06e47b" + -+ "88d773069aa759cc614e1f53cf6e572c127123d1ab56b79ee753a921cb22" + -+ "a60e4e6cae768c9966de4e2625484f2e990154da7fca84b6e6c0b59201e7" + -+ "fb8a729cb20b4c774381e84f1bd6e304543d952dc76ef741b72f3a4ca7a6" + -+ "ea7958b8b6337994ed82dcf988eb70f509610b9a279ab4d0f28cc2b2dd99" + -+ "3b8637a6be0cb4b5f67c79654c6b15e1b61120374ba9b974a628c547f11e" + -+ "52d72d39f8f9c5dbfc23a89f22d38984dd8d5c3ca72cd54e6adfe2b3d163" + -+ "86afdb50967846a4c311351a51e5fd322757bdb061d44c8796a61fa4db36" + -+ "793bc11984eac83bbcefb40d0bc7bab0ca81e7df3a7f58c6fe800396716d" + -+ "832acaddff6d72c8e19dc9ea838294ead800deadb6bc18d3e399fa76c46c" + -+ "5d88ee72a86a87399423b0578eb6e27d78156ea2abf6f08b5cbf747f2f74" + -+ "5301b694bfba84bfe3c5527acd50660eea5105a2644c1aa92f954a604fb6" + -+ "a1b3b2d0331497deafc3aaadc7040b9188a36cf607ee85a0655ae963fd32" + -+ "91dd58f8bb50b4e46dcf7c2957639bffa6b12d895660dc0323b7a092f999" + -+ "813380b820e1873c60d3e3038129c66d507862100a5d5842150869e7873d" + -+ "6bb6ad022350ffa3813aca26c80ccae72692bed9c77c9d4da23178c57153" + -+ "90b5f4505240a796ec9d10a7f280bd60a570b1b693453807707651fc0464" + -+ "03e4768965a6f42f112152942134f0a38c84137c7a6e086ef1ab9ad20d24" + -+ "3b93356b305c0996ab7d02c02c44cbaf8f7e60b8c0b8c9fece3f189b099d" + -+ "dbd126b7357c1c4ea1c8bc1ad93db91ea9bf043a4320acb60b502bec37b8" + -+ "6b2a5004b8225e549e613c6f83b97b7e4aeda1b013e0a442d7ce2f14e78e" + -+ "a94bab700c9ac0abba945e28f39fdadff223c4498cb204f01ddfcb450a41" + -+ "f32ae47f99a49114c6646a5cb103e9cd75f9d81dba417e48c4053e3b0295" + -+ "2267cd30589b0f5d993a5485a6ead1ffab9f2f4294c5853ba76383a326a6" + -+ "a42fb8b78948aa49f0f1f614bd0a3fbd2a58a3197daf2094605bd838285a" + -+ "1260f1265dca74aadd95652632335fd17cafcb73b202c3f0e5da836c2dcf" + -+ "2934f005935dca80154af43fa34c8ba440d1581b74ff17dfaca369dc9aa6" + -+ "734c03916d78e1b952691cef918fe033d33f7f4323cf724ffb8cd6c219bd" + -+ "046e9f268eb0601098e93daa59dde370e46269dd7c54891f71bee2829a53" + -+ "df86a2c7fb1046cd7c98fa21cd83597be554997a70acebe0b6e60f1f7098" + -+ "6f65adcae24385cb7102bdd3e01300ffd15d00f9764b3a5c51e35e5c9cdd" + -+ "da84f4b656fe514ec4ff8dcd774373f8a9103cf36abefe875f7084b9bbd9" + -+ "42e0c997ec2d860a4b622ff1a39a628582fd81f237d3d8f6843d26ac77cf" + -+ "bd48003e8e8c591ff813a9a897e3149ff0297ff476299d717e54d885cdd4" + -+ "4c3ba6ebf54bc7a1", -+ }, -+ { -+ key: "b15578da1020f662ada0ad4f33a180d9f8ad4991b3720bc42a22b52625c7414a", -+ tag: "b0e4ad4a010afd6dd41ed82868cda555", -+ in: "6d2afb7a9154064341bdbb533f11990d4987e7c90fbfc0167c1e58d6efff" + -+ "6010f7ed569dac62ad37183b0d384519ebed0bf9c6e05a070b4858e6b846" + -+ "547ab5e45619c866f83cce83dcdab6a8a6c36b115ac832de1c6d433b94fa" + -+ "35803fa1a36f1ee114f8632402a027a74ac110394f32ec4006beb0057f09" + -+ "a94dada8bd0d1ca9a14b1f2efb8f526d79d6438bbbaac0ca1a43935627e5" + -+ "d129d52c06bf6413af07513bc579447eccc3a9406645c94dae59dab98d6a" + -+ "f92fa90fd4efaaa4bec466806ed401d2083cda587139ad7e9ee2adbb1dfe" + -+ "a88b59dd788b954a0f52c3854a3fffecb4bea83debbb2f5f8883e6415d3b" + -+ "ac1b872df1afe185468adc59364c173082f1dd6da9d348f5f5ba2d216243" + -+ "23de1f623eeec875bf31d12acec40dc0c1b9562826f3105cdad4c43cf45d" + -+ "829aa8b14012c47847aef7a2a6e3935fd972235f5d3a7ce4ad3582785393" + -+ "602e2e27329914021eff38ed2926c88acec1551f17a1b818fc1c3ed4b3b6" + -+ "6825d55bea269d710123b52e12ca9520a069d9c6a21df3a0253b3a4a6a8c" + -+ "dc226d667541548834da6bdbbdc165f39e40047d4b647c507d981be17b3a" + -+ "836063436241a8bb46b11a2867b621413c42d838e4578b72cc1982e34bde" + -+ "c303b5575ef4b8dd9fea8ed5bf69539413909d03461d3853b5fbf714a61c" + -+ "769569f42b38fac4b849104e2f2ac1dad0e388646278789f83e0b0511571" + -+ "019d3bfc5b03ca4cb5564e4e75e103ea1b6000be6588e27105d7cdc2d2f1" + -+ "f680ad34ef823ac4bd4068146e9997834665aec7dcc7a82ff28d85d52dd6" + -+ "9c18dd35f326bcf709f74df5981bb90ca8e765fef9f0698a19e12220b287" + -+ "24a6d9e4f4c7ce93f8ca9a126689ad1df820072557ce3db246cdf41599dd" + -+ "44ca841bece6c7869358005536e1189aa86b764e890ef90970d6e3831def" + -+ "fa890bf8692381123924e7d9df804fd770a0a30ee97d5dcdca302833efe8" + -+ "1d4b2505b17382f0b3429b38c41269ac95e36e9f5a1dbc6e6c8963741917" + -+ "02a23198decb4efe6809fcbeb5d0c9098a4c300155dc841610e55c8a6e27" + -+ "2a38a39de3d8ebf38a750af25836ffb1bb7822bb98886280f0cab6838c01" + -+ "cec57961bdc2e1bf158248309ff9294adcb962252b1c24646d132a3be2c9" + -+ "1ff82e8e101facbdb807826cc9d1840a90874ba08692e808c336c9d280ee" + -+ "f36a43a75c746fb864f85711e802546ab5cc3f8f117904ba1a85d6e4b729" + -+ "85122c5041891e16d55b93d6fc1b7fcfdc80ed3d72d55d64b8895bbf2f8e" + -+ "d188684e7e89afdc1e6a7ab9bd1d3da95d68698df2cdcbb2e1a4ae70e2fd" + -+ "dd4760f9e5cf4255eeb1e9e8009ab507395bacb8b2177e7c5757ad02baa9" + -+ "a96db967d20a150d2dd7f3081d90675fe0c82f94aa3cfdf6ac5585583901" + -+ "7a8e122170cc817f327a3c8ef44acd6e4fa81b73bcd0bcb5792eed470481" + -+ "152e87f7a20c3f7c69d5a8199bf9bb7c7269b450dc37a9b22102acaa8438" + -+ "134d6d733d231cee9522f7d02fbb37b5818ad3ca72df4752230ee11392ef" + -+ "8f8219be55202bc3d476f5a9078b32fb63d42bed4cda5ef90cc62467bf5e" + -+ "418ecd9d5d0cf1a33eb9a930e652ce96057fef40b65588aac67621d651a0" + -+ "9003dbc3925912e385296cd3b2b386a44113308ddf2af52ca390487eb20c" + -+ "716b76d78ad45129e7c285d918de7107ea8c3b0cfd9e73933b87c0b2b505" + -+ "cb4c95794f2ee6d6d43e2e76026923a0bbfbc3bb22df9ad729452283ce62" + -+ "dc9b26684fd45e07650581afd73713a708869a069c58b599ab478974f206" + -+ "dbd3e4e563e346ff1881723c5fd440bdf9f70f761c6f746113397d7c04b6" + -+ "b341d7e44de7de0aae79badaaef5ed372ef629dffd52926110683ab2d4da" + -+ "a4be83eb86c8700703a660edd5a5029f66f1581da96fe1feefc970ab4086" + -+ "a83ae02e959821967bd27b3b629652f5bc3db2b7f1af674f9f3fb3a788f7" + -+ "88e6dc1722382971831a7ed72502f85b25888c1534d81c0a4f7351ecc40f" + -+ "4e0412e05718403fae5746d313a78c80ac297f1391ad389070410e1330a1" + -+ "b07d683d1c795bda74bde947f2cf0dc9638b5d0851cda27df030403816dd" + -+ "3b70f042888c9c192656cc4b9fea10b81b5347900d9199c8f0f47d42f2ee" + -+ "482b68acfa5ff47d9950c950a926a497d94c6a796e0b715416520bd6c59f" + -+ "30217718d5f1d7bf7c24039f6467214ac8783cf011b25c37c67dfddde426" + -+ "40afe97f94879f4586954737b86701b32d560f08caec3fc45184bc719c7c" + -+ "5bf699074fde814acae32c189158c737665a8f94637068322f0c23ff8860" + -+ "f1b1c1bd766440afee290aa6f7150c7adefa6d72a738cd2268da7c94788e" + -+ "bb39002e9a328a51f3a92dc5c7cd9e4faed5702d3592ad16217c4978f84e" + -+ "af0fd2c9e4c6f4dcdd9112c781eb41a9aacb0f7935bb5c92d41e67cfff6b" + -+ "991ccefbd667ffeded1de325da50c33e28e2eef2f636c9726dc5bfe753ee" + -+ "c7bb6e1f080c89451f81bc8c29dc9067ce83deed02769714fa9bb477aca5" + -+ "c09089934674a0cc8e4b2c3136b2e4af8040cc601b90a4dec898dc922ca4" + -+ "976ab5ae4ac5af93fa5b1854a76ac3bcc2090bdeaa49ec4f319cf7c7b674" + -+ "6d8e617abb3361b28b27983dd1b139ec4f5af7e116439d7ecb16534817bf" + -+ "264dbd8f59e80b443be12c17fa013c7f4d029504c9bb62b296c2326f4f49" + -+ "cc3201b70ac3f62abb683c630179594a6d4cf30fd55b163bf8d01986bb6b" + -+ "cb7050fd527f095c45661920268e56f760fee80a29c9d37b7fc23f608710" + -+ "1e723038e64ee1b91c4849d69bd95fc9bc24fc4a234f4855f2a203e3f699" + -+ "c32698585c83781677739f2c48697c93b3388dcc64aa61f01118495ded33" + -+ "21ef9a1c949481f96005f8d5b277a7d6a0d906ec304cf4292df172e72d20" + -+ "29ecdeb65f06267a605f376804bf7bc5b82d5c8facfe7e41dc10806d27e0" + -+ "bcc5a341d80b3c1532407f75088716d732632cd88b0037f0d829bf385fec" + -+ "b52a202956489f61f16b0f4781bf59068b33d7330571d0b4a6ed91830258" + -+ "e1220b308784fa155be9bc821f5c0009a33802fa66dd66d1dde997dddd97" + -+ "873ddf65927dc1be979af2b5f110eee627dc1e210326ac20544a757ac168" + -+ "1823f3dd04b1ddc4bf96677a0a87633994e7af2ec99b7d5dfe44c6192be6" + -+ "a6e69d17b074256da3947808fbf68c7506a7e2c99e6b64d1ffadbd6285d8" + -+ "e7e032e24d42dde0594bf03fd550be05e5d66c91a660cd1ab7cb1f43fa9d" + -+ "69885203a7aee35a28f117427d7ac02b742f53d13b818f8631081b1730d1" + -+ "5b4e1e283cc8e5c4fc3b4652fce05fd8db821f99fcf93e6842816a549791" + -+ "7f6c49cc53d733788b2fe3c687de58bfe6153c70d99380df1fd566a7c758" + -+ "8052c62e73340d6a9eccd2ed26b763d518f3a0c4d6362212fbecebb4ffb7" + -+ "dc94d29944fcc4ab37725b105aa7571f364146782356d8ef056a0be93a55" + -+ "0c890df8fecc178776fe40703ad1bd2443d92c420be4306d99686592c030" + -+ "fd3e2230c0b48d8db79002e8a832ef27edb53a45532955f1171203d38414" + -+ "b4692e901e9f40f918528fc494430f86cf967452f456b01846ac6a383fc0" + -+ "de2243c7d804e8643aabcb78e2653b145f400a999670217c8da43bbb9c11" + -+ "e074176424be0c116c304a420120138e901eca4b12ce68fec460b23bc0c7" + -+ "765a74fc66cbda0e503e7b1baf5883744e468c97c5f1c4b0acc4b87de9f1" + -+ "4b537405dfb28195439d1ff848d9cd28a8d375038ebb540a9075b7b5074b" + -+ "ebc18418a370f1d3ac5d68f5d239513002ad11bfc2b7ff53e2e41ccffc4b" + -+ "0503acc4967c93ae8590a43439b5e7987d10cb8d1957bd9ef717ee3d12df" + -+ "5d6736c1d8bd8da102337a94b7d14f830f6c403cbaf7925a8a2a7af1311c" + -+ "57224967a38f6ca374013a9819c55fd2e2a5fac4f2490be5b059f4cd9c60" + -+ "2d62f80789eb8d9ab893c7f44a4945e41886af218179dfa754bbb59aab68" + -+ "13b71d2202eb8fc8a425625d21176a28a620e21bb0dad820c0b7051ce8d1" + -+ "3a33f3af0958bb6cd89f9d6414ab00ddd1d2f9fdece9183d0c05fcdfd117" + -+ "10d250e4b2029e6992a88293d0457e73e5b1b6a1aae182c69b9cb664992f" + -+ "073595ef68117026ad7ea579a4043cda318931eee7b2946a34cdc7c9755f" + -+ "80cc79a2bfe3ed9c79dc52faa5126b824868c965eeb37e9e4e6a49600f3a" + -+ "cce93c0853b546edb310dcd16a5755f15b1098b2f59dbd2d90e2ea8360ba" + -+ "f12108236e854465456598ae2f7bc380f008f2e3cd7c98c87643cafd7c36" + -+ "d40e2597236428d46aa5b260f84b4212d5e26804086adcf00363ce4becb4" + -+ "9b57eb2847b2f18ec82c99714ad4ddfe4ff3bcac1d0fcaa32660a1dccc68" + -+ "5bed83254c8e2ea0ae3632a70cfbcbeadef922d78a006d43ac7ab1f8a609" + -+ "c6e0ebc3ca6bb8430f1a562f41010db74b9febf931ca794fa08d1bc17780" + -+ "532ae76f25c4ee679d788835dfa4e70ca154c9e2865c3750ffe7b837eed1" + -+ "972be058fdf2bdb3eb301867bb132306c7aa237f6771d60bbc56cf31cb30" + -+ "32a87204d454542de747418470025ab84935d3eaaca01dbbdae9ef6b5d3a" + -+ "ca62ce9f871a3e1272b2b671582c096a349c00f32d742ddb17993994d8ae" + -+ "fc178cbcf9abc03114ff2bf7db8f757c63d6898faccd822f5c2e9a7570fb" + -+ "9cfff148570888be24ae42644c1a5bebb6f6287147a4bcc01c7675be9e4a" + -+ "897519dd3132a7cc2e778f8c90d23dc8073f6fa108d7ef82d561794bd9d5" + -+ "f1faa306334f338ac3ba99c853f79c24f7048fa906fde87d1ed28a7b11c0" + -+ "66a3bb98f8d21055aaafdf7e069b77b60b3d5cbe7c5e4379c7651af955cd" + -+ "82a19a09caf36becb6cd3fe9e12f40379941542709991066df21b7b12dfb" + -+ "2416d83fcdc33bb583e3b42f24f53edf8dc7c579ad3be831c99f72bf9fb7" + -+ "a35b6562e824e039e6bf1adc8f5ca53846de7bae11c4317e696d887df33c" + -+ "525f0a9c01fc29f2c26c90b85fe82ed8bd50954cd4e9ac7c85c7f3efec75" + -+ "da1da4ed173cb695cee295190527edb3cb06c5dbdabe0228cc60b6455153" + -+ "76244f27aa56da2db10f2659090137ffb82c57233c833e0bbf22d6f647fb" + -+ "97b3652d2888b3ab08010b8e8a6967d560b747757806736dc98b78226634" + -+ "f1eecaa4a2e23ba36591acb5737d735c5bc7a2e36f1a46946927e061fdf7" + -+ "7a3b68ef582c26b01f5aa9a438ecc26c6941221d1590c838072f9e471fe7" + -+ "fd59dacb0d092d40d76ea2f7c6e954a132a015bd4cb31147f3ebe4518322" + -+ "916438a62836ac85a4cf4492190a85bcc8edb37e38b99ea552d749c30f74" + -+ "ca20c298165e8ed02d4671e0b41cac3a32a345b9349ad22c2a4bb2c16a4c" + -+ "e0613ca0f0518759f7d2b33cfad2fae764f410d4d9ff8a76ae02a8107e7e" + -+ "01d9cd0552676b85ba002f19c01ad5f416d1d08bb84fec7c3555b098dbce" + -+ "48e1a5d847895e54db9c5b80cc22d5b87cd41a1a94be102bdd45a3cda5d1" + -+ "181e10446d213d6b3fdc350d486d2011d705c5f16ccf7519065c47bad7d6" + -+ "89c71e5fdf9d04bfb91eb1f07fa0f001009c1d4b1f6a116a570823a8580b", -+ }, -+ { -+ key: "392468efccff36dade31fc1c62eb38bb61394fe448def9d9d9beec2413ddb418", -+ tag: "e1122e7c8e6965b90addbd46d8a548d6", -+ in: "6a13d37f0ec933194c227351f4a19b507d93465b1f3e88dcb5f1ed1262fa" + -+ "58ea99ff31e6fc85c39c04129fa69195b71b2060122fe618dd9430a63f97" + -+ "54b52a80b3cd099f248f91a468bae211a27bdb47ba005d29881ea5143a82" + -+ "967c4c30c9a4f0dba1a4975e6407fe296d40023a00efa06be763f2d73d46" + -+ "a2901ae28b3d8ce18009a462e223b71476d7b954c138e177d15a390847de" + -+ "96a7f7fd0598748e86b0f08e64d915e67c7e3cf936f3dcd60edebd36e2a1" + -+ "d65b6ac29530c48ab3bd52d45b4f938a19b9b31e2911105a8561600d5377" + -+ "905a67112ec28025aa680350ff85b808c5b4c98b7b9567d03f5ed3911ec9" + -+ "365a8de4b15ca62adaa69e5ba710eb1756a346016c67a297d8624f9f1ab5" + -+ "b3fbce98b141049f0ce26c85d2f8a9cc6ca8ab6c6e148be968931430dcc6" + -+ "2bf58ea9698ef52a5d271cf48e6748ac9e04bc7ae7da205a1a7535478322" + -+ "d820eca146cedf4b2f9aa9fcfd77ab56a7276977401dcc1f96baa1b607e0" + -+ "256bd04ec324ec67a4313e2d5a53d3a3fb5332927929b20c63bde805f637" + -+ "eb1050fee2a152a0405634f55c48a59fe370d54b2ab1671dae2c7fd92243" + -+ "10627808e553127c74f724362b4a6ee49b697daae7df3ddc5d2ed9d6befd" + -+ "77fb9f68fe3041f6ef13f46f34ab682ab8563e8996344f82b2ef006a8d54" + -+ "3dd9c1db4979d7da97bda45e722065f8a238f0873217b783a9a629a12b3a" + -+ "4de437445039997bd243efbf5e3b6059b9459d395290efb9081c632fb694" + -+ "81000dc74c395cb507422df181aba20f776ce3fd8765ac485021992c98b1" + -+ "67c68805662cb4356a0ee7ba6bdae51ac10cd06bb5b2f3a72841c714c8ed" + -+ "bc56998fe2fefb9bf69e172fdf54b2ab138ae59372c52a67e93882a3000f" + -+ "d966992aa2250c6ff93e9cac89645d70625d79332ade5dab7eb1adbe7dce" + -+ "5a013fb65ad32fe22ed16fb9bb35eca1f37a0433c320e8752f8fc4b7618c" + -+ "5e4df2efece832e259ad98b895c474e47d0e3fc488bea8f717a17de0dcf7" + -+ "597fb8fe12e62246296f9a887dcc3a700820c190a55a4931a7d44bd3bb2e" + -+ "ab6c8a8126f1be93790cebabc1d69e01796e6cc80e7c16bbc82fb333fb21" + -+ "c774ab7db843242838e82d8e1cb8ccab385e67a4271fe7031d74b6e8edcc" + -+ "8ed585d1c05a365c7665899c1dbc561151d3b44bceace77c4f53c0e0f6f7" + -+ "74d42f9ad3e56f1c2a8d53879d695f895690afb4698472a3d52d67159313" + -+ "133c87823fe0500eb68fe286f8b9a2f59f12785d026dc97bdbf793c7d1eb" + -+ "155f1f136aae66c256583e987f718afbe733e0a5ce30d021493fb84e2242" + -+ "5b18754d126235ef80335004fa84f88361a584753df409360cd8bd45bace" + -+ "8f48156bec66577bf2c685089f5ac7e7ec76c0df068fbaa47661f8517f92" + -+ "e14723b3b278f151816537a7212c96bd340a00c15c9c9bc9a2a5d163655d" + -+ "84b38073e2be9217cad97d362d89d4baf3ce0a8d8562f19a8c97a9aaf5e7" + -+ "77d60456360ffb77b30f177d2809052020d141697ecf9cb65f42b9190caf" + -+ "6540b2c82f6e5a8482934a6a1a5711a8c24546cd8ba432068404eae5a827" + -+ "2e09efc3c6037af4feaac0a46329229b010ecac6b9f077a9b076bb6d9ce1" + -+ "38401eb38d124baa11507a994185295020bf9b754fcf78430db9253f5929" + -+ "87c46c0f8589c4e463b15a3840b1cea795e24cf6b20f29a630136e0589b3" + -+ "8dd7fbe5ea21da72c88bd8e56473586822aa3765660a45a988df9b8eb8e8" + -+ "141939d3e4cc637c5d788064d40a9f7c734e43fdf8d7189a5d76700d9743" + -+ "fe0122944663afdb88c5201318ca782f6848b742ddebe7463fd4a32280ac" + -+ "1cf8311e9137d319de05ce9cd85abab24c5364041c14d3b4ce650400498e" + -+ "122166eccc12784b7ac3b262ac0b198ffc26eeed9a5da5374f7a2a53c87a" + -+ "78c217ea1fbf8d38f62511657b73109f31691aef14d82ce6e1010eae9e6f" + -+ "a419e5c1c16c0cc70651eb3374c03549a1bc7d3ed42d60f886102c798dbc" + -+ "ba56f0a2b3b9b412530c35f5f7ed06311ee14571f9c26ed9c81ef38ff000" + -+ "2f5ef3aab7351e32049a6ef8f48a43da1d84402d229df513dfaf1b2e4043" + -+ "6ce68c70ebeddd7477c9164f0dce45a6fc5de050f52ec269659d5854bcae" + -+ "f7762ed7400713c27a4d523eaf8c136c4a1ca00b9e9e55902daf6cdf8528" + -+ "c22ca1f2fa7ce87902d75a6850e1a5a4592497be1bb401878f18b189b0e2" + -+ "c59d10705bfabde3cd2da01eb452006b294108d5d42e88e9e15424d8cd0b" + -+ "8ab43a6c546b3dbf52e47b59cde6a3e417b0395220b6d63736d429da3458" + -+ "9a2524f1629320206fa7f1d8a041e17222c4a5814561937e1030e6375c77" + -+ "9dc988bb928bbdbe2c2eb20111639725d82b5d7192cd3e4acc27581f0ba7" + -+ "286cff41f97aa5a52ea0083de5057fd2ba985aa738e4d03fcf11ebab1d97" + -+ "e2ac77d1c2beb8799150a421a07b3777d0b850f24194b8309135b13da6c7" + -+ "e38653a711e407a1811290fbb7bc15d8b12efc6916e97ead41e042a44721" + -+ "e9cde3388073d921595bcddcac758dc675173f38242e65e4a284aaa7e8fa" + -+ "6adddaf00bc46428ab2d8601205b8895bcedfc80ca0aa4619ed6bb082ddf" + -+ "33ec04fa5d417f33fcdd238c6b11320c5a08f800e0f350b75d81e3bcbd15" + -+ "58a1eab87a3c8c2ffd7ba1d7e754e607cf98ba22a3fc766c45bd6f2569b4" + -+ "84639e6611714119d188a24a5e963089a16ed34e20b9f154cad8ac6031dd" + -+ "7a3a885afc2ae5e003ae8d4e4aabdb3e51dfc423b8cf4ed9ae2010072cbb" + -+ "b1108c7da1ff075e54ed827a0963ac5523ecdf3fc5eee7b4d1a6773764ec" + -+ "5c30f41690523fd70d895edb7ca6a1806d54240c4c7b43410da73503a323" + -+ "90d9070ed30da3a2fb5eccd40d083be7cf8bf40b4279f819cf795b6f075b" + -+ "5a67a10a06a6076d0d83c72efea05f244901c4b5fd9eb380432519311baf" + -+ "8c81f6325df4d37ff4d30d318f904ebb837ec76b341dd00a8f247cf0bbe9" + -+ "6f3784dc8f5feb344958fdf1a9ececb105f8770826db1f17a5281e997951" + -+ "d3c60cc28fc3e66ffeb5dbac315f98f6d240208043f28dee963d843e68ab" + -+ "57d847f76ae2f96ce6e37f377ef5dfef2176ecd7440ce4dadcec2231b606" + -+ "e4a80420fb3ed135640e1f05d6bd58b8dce062dd7d36b885d424f6318e5e" + -+ "a0753efbb33bbc7360d2b5dfab3ae0d5e000b8d31f2ba0f5fd8b34f96b55" + -+ "28fff35e769461d0f03cf3bfdf0b801dcbbf2838180cb9b108e06c353e3f" + -+ "0b9ef61678cfed1ea37ae76bccb5ef5957ac2c8e8f4794c8145a15f1cc88" + -+ "bfb0881080326c481b373c3bc9b07a9b60a0c8bd5fa4f6f90145590a5227" + -+ "6fcc0ccc2375d0ccb571d414d1b0c38b4e02c39db4d701c5e25e90785ef4" + -+ "d26f35edd8c4b96455bdca7245cfefd9cfbd2f319615e5fdf07bb9564fa0" + -+ "44bb35a58391d02e3927780b4076bc0893dfcb4b63a32cd7a541a4a8c253" + -+ "0349c6e96e378dbeb66dedf87d813d0b744452c1c4088507dca722193827" + -+ "9e2dfa24e4a409de494acf654f44262db9206a7717fa434ac4fdc6a6eb5b" + -+ "1fd5a193b6043bc4327c8c09fd6822eaa9df37bbcac1077754a295621601" + -+ "267b68733b62dadc2563f1700af180141f29899e2689dbbe9745ba8477f4" + -+ "352921900b403a01c9dd042a8c1b0e0489959fb0b0a8431c97b41e202204" + -+ "212ebfa00c593399dbd14d7aec07b8292d2e40b48f05fcd54a15da4a24d7" + -+ "2759e409f4c7b5b98fce4abac6c30e4872d92efa1f96479ec30f21699825" + -+ "50fa60584f5a09051a00f8e7dbb3853e66ca3f05fbfe43bef9b120a25a01" + -+ "eb436ba8ecda715201eda72e517d628f883386c1503aa8b8e75610f7155e" + -+ "9f916335ab6d6f0f9589b6220cd2b81c2c937dc065d3d14a7df8cc916cd0" + -+ "0ce1bb53fd9c8974298d3bd316f3658aa8cc6904f073a1472149e4b08c64" + -+ "5e11abe0428ccb6174df2103edd735965d6454b543d3f01410f77053f65e" + -+ "c1d1aee56fdd3af23bcd4e1a7fcc4e600c4831007c33fe5f0c8300f686eb" + -+ "9b4d1e4f08fe4ddc8a90be14dc3a5a88ff96716509341d5db24c0d016863" + -+ "998b1859c5021df815a6f1ca9845f1a8e99dbad132b406227c5897a1bdf3" + -+ "e698962f799133ff4429decbef6ce036296facf38e4812fec102b76c6d30" + -+ "beba1b70722254fafbc471096153478c971db7d96263660209265cb10f13" + -+ "b34b5fd55c4abe818a5f9715d8a85094e2946b7a001b47f629e26c636d86" + -+ "4968ad2ab616dfe28840bd60b4b9855c8dbe1cb873fcbc4577b5fefeb8bb" + -+ "4832039867dc35db9c036c83bc204396e3474ddfe806c77c65c936f488b6" + -+ "7c1028739562d7bb055d21441af29ae2921290e548dccf8a56021385422b" + -+ "15da6b232b24151309a75a00296d11aa1952a1513110b0faa93d1d8cd9ae" + -+ "fa9f1c59377ec9165b2c9e07cbde40db7b81bca6d58fc28bae8f473cd0e9" + -+ "a2420e0b943a83d284108626c24ac570b1d6c1ab971e71f43fbd6c00e171" + -+ "238141a6dc987a60385c3a04dd147a2f8e80dfe727b104c0fdd80b326f59" + -+ "0b9f86fd7b2fd1122a390979889eabd803ab57159c8509a1443eb6789382" + -+ "090a770ae4eba03306f96e50e19a7d44c584ccc230d104548946efca4520" + -+ "d61de5f473e2f4eada6c8ce9c7ee975eb4f63c0483cb775ed7d3cf690a61" + -+ "7d6656d683a8512707d81ca5ba176a42bcffcfa692129f292607d2a47536" + -+ "ccaeb464c9272d6f3816074b712af602470088b253deba18771e5f67734b" + -+ "587707cdd06f35264b2262fd253c25b5d38ee7db287610e5398062b7a34e" + -+ "6e4cf7447d00873b930ad148fd96f0ab18771bc468b874bb109924101c84" + -+ "c4e239ecc7687d875e4d94a1a973620ca61e35a872c2e2e61a502169f1bb" + -+ "4e5ff5fa2bff657be6195b3e2c7151a52fc0096d98e7f08f5a98f570aee1" + -+ "7b4275f1356e87e080ce0e1b9bbabe7dea48b5903bc390ce23472ad64a89" + -+ "41c3247bfd23ea90b2dee09085571bad85568040105e098f993bb37e43c3" + -+ "e6d511171c77cfc450570dfb9fc6a3930ef43c03f8213f6203d545d791c7" + -+ "d3fa42d5dde1655038d35c5dfacc12e9dee24fe833977549eda68ae8b508" + -+ "be277e743921b584f9dfa0eefbd8bf3c23f51efdef7f7487001d29e8097b" + -+ "ba63289cfca743023d1668555a46fe6d5b7421377414df1e9ef135480622" + -+ "22e2e9a7baa618d88f407517f6317b6a0ba3384ace16d68631d59ea169d5" + -+ "092d20afc1a481b82be5e734bb092953a0a94702bae1a0f48d2a22b9a05f" + -+ "f64493b7b2e984f27582b1eb937fddf8512c49830435d146dcc291a4118d" + -+ "5dc638b99cdcbcc5860de7a92c5b13cbd1e01e051f01af40afe124346320" + -+ "d3626bf9d8f7850744e032a993c276fd388718237740c6caf260fca60b8d" + -+ "d846102e3262b6e05ceca00c6affe938fac1847350865fc858d3ddd1d130" + -+ "71d1221ce7c5d575587fcba580e544b74d877ed5ca92763ef0ca0d7bfa08" + -+ "d57a0216b2a01a2b9ec74b8430051e0074862b7be25b6766ab520f2eb75d" + -+ "eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" + -+ "f2c5b0dc5de9f5e55a97791507bc6373db26", -+ }, -+ -+ // Override initial state to ensure large h (subject to h < 2(2¹³⁰ - 5)) is -+ // deserialized from the state correctly. -+ { -+ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -+ state: "0000000000000007fffffffffffffffffffffffffffffff5", // 2(2¹³⁰ - 5) - 1 -+ in: "", -+ tag: "f9ffffffffffffffffffffffffffffff", -+ }, -+ { -+ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -+ state: "000000000000000700000000000000000000000000000000", // 2¹³⁰ -+ in: "", -+ tag: "04000000000000000000000000000000", -+ }, -+ { -+ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -+ state: "0000000000000007fffffffffffffffffffffffffffffff5", // 2(2¹³⁰ - 5) - 1 -+ in: "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff", -+ tag: "1b000e5e5dfe8f5c4da11dd17b7654e7", -+ }, -+ { -+ key: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", -+ state: "000000000000000700000000000000000000000000000001", // 2¹³⁰ -+ in: "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff" + -+ "ffffffffffffffffffffffffffffffff", -+ tag: "380859a4a5860b0e0967edfd711d37de", -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/testenv/exec.go b/ms_mod/golang.org/x/crypto/internal/testenv/exec.go -new file mode 100644 -index 00000000000000..4bacdc3ce87e31 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/testenv/exec.go -@@ -0,0 +1,120 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package testenv -+ -+import ( -+ "context" -+ "os" -+ "os/exec" -+ "reflect" -+ "strconv" -+ "testing" -+ "time" -+) -+ -+// CommandContext is like exec.CommandContext, but: -+// - skips t if the platform does not support os/exec, -+// - sends SIGQUIT (if supported by the platform) instead of SIGKILL -+// in its Cancel function -+// - if the test has a deadline, adds a Context timeout and WaitDelay -+// for an arbitrary grace period before the test's deadline expires, -+// - fails the test if the command does not complete before the test's deadline, and -+// - sets a Cleanup function that verifies that the test did not leak a subprocess. -+func CommandContext(t testing.TB, ctx context.Context, name string, args ...string) *exec.Cmd { -+ t.Helper() -+ -+ var ( -+ cancelCtx context.CancelFunc -+ gracePeriod time.Duration // unlimited unless the test has a deadline (to allow for interactive debugging) -+ ) -+ -+ if t, ok := t.(interface { -+ testing.TB -+ Deadline() (time.Time, bool) -+ }); ok { -+ if td, ok := t.Deadline(); ok { -+ // Start with a minimum grace period, just long enough to consume the -+ // output of a reasonable program after it terminates. -+ gracePeriod = 100 * time.Millisecond -+ if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { -+ scale, err := strconv.Atoi(s) -+ if err != nil { -+ t.Fatalf("invalid GO_TEST_TIMEOUT_SCALE: %v", err) -+ } -+ gracePeriod *= time.Duration(scale) -+ } -+ -+ // If time allows, increase the termination grace period to 5% of the -+ // test's remaining time. -+ testTimeout := time.Until(td) -+ if gp := testTimeout / 20; gp > gracePeriod { -+ gracePeriod = gp -+ } -+ -+ // When we run commands that execute subprocesses, we want to reserve two -+ // grace periods to clean up: one for the delay between the first -+ // termination signal being sent (via the Cancel callback when the Context -+ // expires) and the process being forcibly terminated (via the WaitDelay -+ // field), and a second one for the delay becween the process being -+ // terminated and and the test logging its output for debugging. -+ // -+ // (We want to ensure that the test process itself has enough time to -+ // log the output before it is also terminated.) -+ cmdTimeout := testTimeout - 2*gracePeriod -+ -+ if cd, ok := ctx.Deadline(); !ok || time.Until(cd) > cmdTimeout { -+ // Either ctx doesn't have a deadline, or its deadline would expire -+ // after (or too close before) the test has already timed out. -+ // Add a shorter timeout so that the test will produce useful output. -+ ctx, cancelCtx = context.WithTimeout(ctx, cmdTimeout) -+ } -+ } -+ } -+ -+ cmd := exec.CommandContext(ctx, name, args...) -+ // Set the Cancel and WaitDelay fields only if present (go 1.20 and later). -+ // TODO: When Go 1.19 is no longer supported, remove this use of reflection -+ // and instead set the fields directly. -+ if cmdCancel := reflect.ValueOf(cmd).Elem().FieldByName("Cancel"); cmdCancel.IsValid() { -+ cmdCancel.Set(reflect.ValueOf(func() error { -+ if cancelCtx != nil && ctx.Err() == context.DeadlineExceeded { -+ // The command timed out due to running too close to the test's deadline. -+ // There is no way the test did that intentionally β€” it's too close to the -+ // wire! β€” so mark it as a test failure. That way, if the test expects the -+ // command to fail for some other reason, it doesn't have to distinguish -+ // between that reason and a timeout. -+ t.Errorf("test timed out while running command: %v", cmd) -+ } else { -+ // The command is being terminated due to ctx being canceled, but -+ // apparently not due to an explicit test deadline that we added. -+ // Log that information in case it is useful for diagnosing a failure, -+ // but don't actually fail the test because of it. -+ t.Logf("%v: terminating command: %v", ctx.Err(), cmd) -+ } -+ return cmd.Process.Signal(Sigquit) -+ })) -+ } -+ if cmdWaitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); cmdWaitDelay.IsValid() { -+ cmdWaitDelay.Set(reflect.ValueOf(gracePeriod)) -+ } -+ -+ t.Cleanup(func() { -+ if cancelCtx != nil { -+ cancelCtx() -+ } -+ if cmd.Process != nil && cmd.ProcessState == nil { -+ t.Errorf("command was started, but test did not wait for it to complete: %v", cmd) -+ } -+ }) -+ -+ return cmd -+} -+ -+// Command is like exec.Command, but applies the same changes as -+// testenv.CommandContext (with a default Context). -+func Command(t testing.TB, name string, args ...string) *exec.Cmd { -+ t.Helper() -+ return CommandContext(t, context.Background(), name, args...) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go -new file mode 100644 -index 00000000000000..c8918ce592db10 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_notunix.go -@@ -0,0 +1,15 @@ -+// Copyright 2021 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build windows || plan9 || (js && wasm) || wasip1 -+ -+package testenv -+ -+import ( -+ "os" -+) -+ -+// Sigquit is the signal to send to kill a hanging subprocess. -+// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. -+var Sigquit = os.Kill -diff --git a/ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go -new file mode 100644 -index 00000000000000..4f51823ec6d245 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/testenv/testenv_unix.go -@@ -0,0 +1,15 @@ -+// Copyright 2021 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build unix -+ -+package testenv -+ -+import ( -+ "syscall" -+) -+ -+// Sigquit is the signal to send to kill a hanging subprocess. -+// Send SIGQUIT to get a stack trace. -+var Sigquit = syscall.SIGQUIT -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/README.md b/ms_mod/golang.org/x/crypto/internal/wycheproof/README.md -new file mode 100644 -index 00000000000000..8ae6c6c3d5a570 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/README.md -@@ -0,0 +1,12 @@ -+This package runs a set of the Wycheproof tests provided by -+https://github.com/google/wycheproof. -+ -+The JSON test files live in -+https://github.com/google/wycheproof/tree/master/testvectors -+and are being fetched and cached at a pinned version every time -+these tests are run. To change the version of the wycheproof -+repository that is being used for testing, update wycheproofModVer. -+ -+The structs for these tests are generated from the -+schemas provided in https://github.com/google/wycheproof/tree/master/schemas -+using https://github.com/a-h/generate. -\ No newline at end of file -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go -new file mode 100644 -index 00000000000000..292d85425fd324 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/aead_test.go -@@ -0,0 +1,176 @@ -+// Copyright 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "bytes" -+ "crypto/aes" -+ "crypto/cipher" -+ "fmt" -+ "testing" -+ -+ "golang.org/x/crypto/chacha20poly1305" -+) -+ -+func TestAEAD(t *testing.T) { -+ // AeadTestVector -+ type AeadTestVector struct { -+ -+ // additional authenticated data -+ Aad string `json:"aad,omitempty"` -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // the ciphertext (without iv and tag) -+ Ct string `json:"ct,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // the nonce -+ Iv string `json:"iv,omitempty"` -+ -+ // the key -+ Key string `json:"key,omitempty"` -+ -+ // the plaintext -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // the authentication tag -+ Tag string `json:"tag,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // AeadTestGroup -+ type AeadTestGroup struct { -+ -+ // the IV size in bits -+ IvSize int `json:"ivSize,omitempty"` -+ -+ // the keySize in bits -+ KeySize int `json:"keySize,omitempty"` -+ -+ // the expected size of the tag in bits -+ TagSize int `json:"tagSize,omitempty"` -+ Tests []*AeadTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*AeadTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ testSealOpen := func(t *testing.T, aead cipher.AEAD, tv *AeadTestVector, recoverBadNonce func()) { -+ defer recoverBadNonce() -+ -+ iv, tag, ct, msg, aad := decodeHex(tv.Iv), decodeHex(tv.Tag), decodeHex(tv.Ct), decodeHex(tv.Msg), decodeHex(tv.Aad) -+ -+ genCT := aead.Seal(nil, iv, msg, aad) -+ genMsg, err := aead.Open(nil, iv, genCT, aad) -+ if err != nil { -+ t.Errorf("failed to decrypt generated ciphertext: %s", err) -+ } -+ if !bytes.Equal(genMsg, msg) { -+ t.Errorf("unexpected roundtripped plaintext: got %x, want %x", genMsg, msg) -+ } -+ -+ ctWithTag := append(ct, tag...) -+ msg2, err := aead.Open(nil, iv, ctWithTag, aad) -+ wantPass := shouldPass(tv.Result, tv.Flags, nil) -+ if !wantPass && err == nil { -+ t.Error("decryption succeeded when it should've failed") -+ } else if wantPass { -+ if err != nil { -+ t.Fatalf("decryption failed: %s", err) -+ } -+ if !bytes.Equal(genCT, ctWithTag) { -+ t.Errorf("generated ciphertext doesn't match expected: got %x, want %x", genCT, ctWithTag) -+ } -+ if !bytes.Equal(msg, msg2) { -+ t.Errorf("decrypted ciphertext doesn't match expected: got %x, want %x", msg2, msg) -+ } -+ } -+ } -+ -+ vectors := map[string]func(*testing.T, []byte) cipher.AEAD{ -+ "aes_gcm_test.json": func(t *testing.T, key []byte) cipher.AEAD { -+ aesCipher, err := aes.NewCipher(key) -+ if err != nil { -+ t.Fatalf("failed to construct cipher: %s", err) -+ } -+ aead, err := cipher.NewGCM(aesCipher) -+ if err != nil { -+ t.Fatalf("failed to construct cipher: %s", err) -+ } -+ return aead -+ }, -+ "chacha20_poly1305_test.json": func(t *testing.T, key []byte) cipher.AEAD { -+ aead, err := chacha20poly1305.New(key) -+ if err != nil { -+ t.Fatalf("failed to construct cipher: %s", err) -+ } -+ return aead -+ }, -+ "xchacha20_poly1305_test.json": func(t *testing.T, key []byte) cipher.AEAD { -+ aead, err := chacha20poly1305.NewX(key) -+ if err != nil { -+ t.Fatalf("failed to construct cipher: %s", err) -+ } -+ return aead -+ }, -+ } -+ for file, cipherInit := range vectors { -+ var root Root -+ readTestVector(t, file, &root) -+ for _, tg := range root.TestGroups { -+ for _, tv := range tg.Tests { -+ testName := fmt.Sprintf("%s #%d", file, tv.TcId) -+ if tv.Comment != "" { -+ testName += fmt.Sprintf(" %s", tv.Comment) -+ } -+ t.Run(testName, func(t *testing.T) { -+ aead := cipherInit(t, decodeHex(tv.Key)) -+ testSealOpen(t, aead, tv, func() { -+ // A bad nonce causes a panic in AEAD.Seal and AEAD.Open, -+ // so should be recovered. Fail the test if it broke for -+ // some other reason. -+ if r := recover(); r != nil { -+ if tg.IvSize/8 == aead.NonceSize() { -+ t.Error("unexpected panic") -+ } -+ } -+ }) -+ }) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go -new file mode 100644 -index 00000000000000..0a60fc355c458c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/aes_cbc_test.go -@@ -0,0 +1,127 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "crypto/aes" -+ "crypto/cipher" -+ "encoding/hex" -+ "fmt" -+ "testing" -+) -+ -+func TestAesCbc(t *testing.T) { -+ // IndCpaTestVector -+ type IndCpaTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // the raw ciphertext (without IV) -+ Ct string `json:"ct,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // the initialization vector -+ Iv string `json:"iv,omitempty"` -+ -+ // the key -+ Key string `json:"key,omitempty"` -+ -+ // the plaintext -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // IndCpaTestGroup -+ type IndCpaTestGroup struct { -+ -+ // the IV size in bits -+ IvSize int `json:"ivSize,omitempty"` -+ -+ // the keySize in bits -+ KeySize int `json:"keySize,omitempty"` -+ -+ // the expected size of the tag in bits -+ TagSize int `json:"tagSize,omitempty"` -+ Tests []*IndCpaTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*IndCpaTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ var root Root -+ readTestVector(t, "aes_cbc_pkcs5_test.json", &root) -+ for _, tg := range root.TestGroups { -+ tests: -+ for _, tv := range tg.Tests { -+ block, err := aes.NewCipher(decodeHex(tv.Key)) -+ if err != nil { -+ t.Fatalf("#%d: %v", tv.TcId, err) -+ } -+ mode := cipher.NewCBCDecrypter(block, decodeHex(tv.Iv)) -+ ct := decodeHex(tv.Ct) -+ if len(ct)%aes.BlockSize != 0 { -+ panic(fmt.Sprintf("#%d: ciphertext is not a multiple of the block size", tv.TcId)) -+ } -+ mode.CryptBlocks(ct, ct) // decrypt the block in place -+ -+ // Skip the tests that are broken due to bad padding. Panic if there are any -+ // tests left that are invalid for some other reason in the future, to -+ // evaluate what to do with those tests. -+ for _, flag := range tv.Flags { -+ if flag == "BadPadding" { -+ continue tests -+ } -+ } -+ if !shouldPass(tv.Result, tv.Flags, nil) { -+ panic(fmt.Sprintf("#%d: found an invalid test that is broken for some reason other than bad padding", tv.TcId)) -+ } -+ -+ // Remove the PKCS#5 padding from the given ciphertext to validate it -+ padding := ct[len(ct)-1] -+ paddingNum := int(padding) -+ for i := paddingNum; i > 0; i-- { -+ if ct[len(ct)-i] != padding { // panic if the padding is unexpectedly bad -+ panic(fmt.Sprintf("#%d: bad padding at index=%d of %v", tv.TcId, i, ct)) -+ } -+ } -+ ct = ct[:len(ct)-paddingNum] -+ -+ if got, want := hex.EncodeToString(ct), tv.Msg; got != want { -+ t.Errorf("#%d, type: %s, comment: %q, decoded ciphertext not equal: %s, want %s", tv.TcId, tv.Result, tv.Comment, got, want) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go -new file mode 100644 -index 00000000000000..aefa3ab30df64a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/boring.go -@@ -0,0 +1,9 @@ -+// Copyright 2022 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build boringcrypto -+ -+package wycheproof -+ -+const boringcryptoEnabled = true -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go -new file mode 100644 -index 00000000000000..e5547084605d37 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/dsa_test.go -@@ -0,0 +1,123 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "crypto/dsa" -+ "testing" -+ -+ wdsa "golang.org/x/crypto/internal/wycheproof/internal/dsa" -+) -+ -+func TestDsa(t *testing.T) { -+ // AsnSignatureTestVector -+ type AsnSignatureTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // The message to sign -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // An ASN encoded signature for msg -+ Sig string `json:"sig,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // DsaPublicKey -+ type DsaPublicKey struct { -+ -+ // the generator of the multiplicative subgroup -+ G string `json:"g,omitempty"` -+ -+ // the key size in bits -+ KeySize int `json:"keySize,omitempty"` -+ -+ // the modulus p -+ P string `json:"p,omitempty"` -+ -+ // the order of the generator g -+ Q string `json:"q,omitempty"` -+ -+ // the key type -+ Type string `json:"type,omitempty"` -+ -+ // the public key value -+ Y string `json:"y,omitempty"` -+ } -+ -+ // DsaTestGroup -+ type DsaTestGroup struct { -+ -+ // unenocded DSA public key -+ Key *DsaPublicKey `json:"key,omitempty"` -+ -+ // DER encoded public key -+ KeyDer string `json:"keyDer,omitempty"` -+ -+ // Pem encoded public key -+ KeyPem string `json:"keyPem,omitempty"` -+ -+ // the hash function used for DSA -+ Sha string `json:"sha,omitempty"` -+ Tests []*AsnSignatureTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*DsaTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // An encoded ASN.1 integer missing a leading zero is invalid, but accepted by some implementations. -+ "NoLeadingZero": false, -+ } -+ -+ var root Root -+ readTestVector(t, "dsa_test.json", &root) -+ for _, tg := range root.TestGroups { -+ pub := decodePublicKey(tg.KeyDer).(*dsa.PublicKey) -+ h := parseHash(tg.Sha).New() -+ for _, sig := range tg.Tests { -+ h.Reset() -+ h.Write(decodeHex(sig.Msg)) -+ hashed := h.Sum(nil) -+ hashed = hashed[:pub.Q.BitLen()/8] // Truncate to the byte-length of the subgroup (Q) -+ got := wdsa.VerifyASN1(pub, hashed, decodeHex(sig.Sig)) -+ if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { -+ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go -new file mode 100644 -index 00000000000000..f7abd6b2e81e66 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_stdlib_test.go -@@ -0,0 +1,142 @@ -+// Copyright 2022 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.20 -+ -+package wycheproof -+ -+import ( -+ "bytes" -+ "crypto/ecdh" -+ "fmt" -+ "testing" -+) -+ -+func TestECDHStdLib(t *testing.T) { -+ type ECDHTestVector struct { -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ // the private key -+ Private string `json:"private,omitempty"` -+ // Encoded public key -+ Public string `json:"public,omitempty"` -+ // Test result -+ Result string `json:"result,omitempty"` -+ // The shared secret key -+ Shared string `json:"shared,omitempty"` -+ // Identifier of the test case -+ TcID int `json:"tcId,omitempty"` -+ } -+ -+ type ECDHTestGroup struct { -+ Curve string `json:"curve,omitempty"` -+ Tests []*ECDHTestVector `json:"tests,omitempty"` -+ } -+ -+ type Root struct { -+ TestGroups []*ECDHTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // We don't support compressed points. -+ "CompressedPoint": false, -+ // We don't support decoding custom curves. -+ "UnnamedCurve": false, -+ // WrongOrder and UnusedParam are only found with UnnamedCurve. -+ "WrongOrder": false, -+ "UnusedParam": false, -+ -+ // X25519 specific flags -+ "Twist": true, -+ "SmallPublicKey": false, -+ "LowOrderPublic": false, -+ "ZeroSharedSecret": false, -+ "NonCanonicalPublic": true, -+ } -+ -+ // curveToCurve is a map of all elliptic curves supported -+ // by crypto/elliptic, which can subsequently be parsed and tested. -+ curveToCurve := map[string]ecdh.Curve{ -+ "secp256r1": ecdh.P256(), -+ "secp384r1": ecdh.P384(), -+ "secp521r1": ecdh.P521(), -+ "curve25519": ecdh.X25519(), -+ } -+ -+ curveToKeySize := map[string]int{ -+ "secp256r1": 32, -+ "secp384r1": 48, -+ "secp521r1": 66, -+ "curve25519": 32, -+ } -+ -+ for _, f := range []string{ -+ "ecdh_secp256r1_ecpoint_test.json", -+ "ecdh_secp384r1_ecpoint_test.json", -+ "ecdh_secp521r1_ecpoint_test.json", -+ "x25519_test.json", -+ } { -+ var root Root -+ readTestVector(t, f, &root) -+ for _, tg := range root.TestGroups { -+ if _, ok := curveToCurve[tg.Curve]; !ok { -+ continue -+ } -+ for _, tt := range tg.Tests { -+ tg, tt := tg, tt -+ t.Run(fmt.Sprintf("%s/%d", tg.Curve, tt.TcID), func(t *testing.T) { -+ t.Logf("Type: %v", tt.Result) -+ t.Logf("Flags: %q", tt.Flags) -+ t.Log(tt.Comment) -+ -+ shouldPass := shouldPass(tt.Result, tt.Flags, flagsShouldPass) -+ -+ curve := curveToCurve[tg.Curve] -+ p := decodeHex(tt.Public) -+ pub, err := curve.NewPublicKey(p) -+ if err != nil { -+ if shouldPass { -+ t.Errorf("NewPublicKey: %v", err) -+ } -+ return -+ } -+ -+ privBytes := decodeHex(tt.Private) -+ if len(privBytes) != curveToKeySize[tg.Curve] { -+ t.Skipf("non-standard key size %d", len(privBytes)) -+ } -+ -+ priv, err := curve.NewPrivateKey(privBytes) -+ if err != nil { -+ if shouldPass { -+ t.Errorf("NewPrivateKey: %v", err) -+ } -+ return -+ } -+ -+ shared := decodeHex(tt.Shared) -+ x, err := priv.ECDH(pub) -+ if err != nil { -+ if tg.Curve == "curve25519" && !shouldPass { -+ // ECDH is expected to only return an error when using X25519, -+ // in all other cases an error is unexpected. -+ return -+ } -+ t.Fatalf("ECDH: %v", err) -+ } -+ -+ if bytes.Equal(shared, x) != shouldPass { -+ if shouldPass { -+ t.Errorf("ECDH = %x, want %x", shared, x) -+ } else { -+ t.Errorf("ECDH = %x, want anything else", shared) -+ } -+ } -+ }) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go -new file mode 100644 -index 00000000000000..a3918ba62f6116 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdh_test.go -@@ -0,0 +1,163 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "bytes" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/x509" -+ "encoding/asn1" -+ "errors" -+ "fmt" -+ "testing" -+ -+ "golang.org/x/crypto/cryptobyte" -+ casn1 "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+func TestECDH(t *testing.T) { -+ type ECDHTestVector struct { -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ // the private key -+ Private string `json:"private,omitempty"` -+ // Encoded public key -+ Public string `json:"public,omitempty"` -+ // Test result -+ Result string `json:"result,omitempty"` -+ // The shared secret key -+ Shared string `json:"shared,omitempty"` -+ // Identifier of the test case -+ TcID int `json:"tcId,omitempty"` -+ } -+ -+ type ECDHTestGroup struct { -+ Curve string `json:"curve,omitempty"` -+ Tests []*ECDHTestVector `json:"tests,omitempty"` -+ } -+ -+ type Root struct { -+ TestGroups []*ECDHTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // ParsePKIXPublicKey doesn't support compressed points, but we test -+ // them against UnmarshalCompressed anyway. -+ "CompressedPoint": true, -+ // We don't support decoding custom curves. -+ "UnnamedCurve": false, -+ // WrongOrder and UnusedParam are only found with UnnamedCurve. -+ "WrongOrder": false, -+ "UnusedParam": false, -+ } -+ -+ // supportedCurves is a map of all elliptic curves supported -+ // by crypto/elliptic, which can subsequently be parsed and tested. -+ supportedCurves := map[string]bool{ -+ "secp224r1": true, -+ "secp256r1": true, -+ "secp384r1": true, -+ "secp521r1": true, -+ } -+ -+ var root Root -+ readTestVector(t, "ecdh_test.json", &root) -+ for _, tg := range root.TestGroups { -+ if !supportedCurves[tg.Curve] { -+ continue -+ } -+ for _, tt := range tg.Tests { -+ tg, tt := tg, tt -+ t.Run(fmt.Sprintf("%s/%d", tg.Curve, tt.TcID), func(t *testing.T) { -+ t.Logf("Type: %v", tt.Result) -+ t.Logf("Flags: %q", tt.Flags) -+ t.Log(tt.Comment) -+ -+ shouldPass := shouldPass(tt.Result, tt.Flags, flagsShouldPass) -+ -+ p := decodeHex(tt.Public) -+ pp, err := x509.ParsePKIXPublicKey(p) -+ if err != nil { -+ pp, err = decodeCompressedPKIX(p) -+ } -+ if err != nil { -+ if shouldPass { -+ t.Errorf("unexpected parsing error: %s", err) -+ } -+ return -+ } -+ pub := pp.(*ecdsa.PublicKey) -+ -+ priv := decodeHex(tt.Private) -+ shared := decodeHex(tt.Shared) -+ -+ x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, priv) -+ xBytes := make([]byte, (pub.Curve.Params().BitSize+7)/8) -+ got := bytes.Equal(shared, x.FillBytes(xBytes)) -+ -+ if want := shouldPass; got != want { -+ t.Errorf("wanted success %v, got %v", want, got) -+ } -+ }) -+ } -+ } -+} -+ -+func decodeCompressedPKIX(der []byte) (interface{}, error) { -+ s := cryptobyte.String(der) -+ var s1, s2 cryptobyte.String -+ var algoOID, namedCurveOID asn1.ObjectIdentifier -+ var pointDER []byte -+ if !s.ReadASN1(&s1, casn1.SEQUENCE) || !s.Empty() || -+ !s1.ReadASN1(&s2, casn1.SEQUENCE) || -+ !s2.ReadASN1ObjectIdentifier(&algoOID) || -+ !s2.ReadASN1ObjectIdentifier(&namedCurveOID) || !s2.Empty() || -+ !s1.ReadASN1BitStringAsBytes(&pointDER) || !s1.Empty() { -+ return nil, errors.New("failed to parse PKIX structure") -+ } -+ -+ if !algoOID.Equal(oidPublicKeyECDSA) { -+ return nil, errors.New("wrong algorithm OID") -+ } -+ namedCurve := namedCurveFromOID(namedCurveOID) -+ if namedCurve == nil { -+ return nil, errors.New("unsupported elliptic curve") -+ } -+ x, y := elliptic.UnmarshalCompressed(namedCurve, pointDER) -+ if x == nil { -+ return nil, errors.New("failed to unmarshal elliptic curve point") -+ } -+ pub := &ecdsa.PublicKey{ -+ Curve: namedCurve, -+ X: x, -+ Y: y, -+ } -+ return pub, nil -+} -+ -+var ( -+ oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} -+ oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} -+ oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} -+ oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} -+ oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} -+) -+ -+func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { -+ switch { -+ case oid.Equal(oidNamedCurveP224): -+ return elliptic.P224() -+ case oid.Equal(oidNamedCurveP256): -+ return elliptic.P256() -+ case oid.Equal(oidNamedCurveP384): -+ return elliptic.P384() -+ case oid.Equal(oidNamedCurveP521): -+ return elliptic.P521() -+ } -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go -new file mode 100644 -index 00000000000000..80125ada75f53a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/ecdsa_test.go -@@ -0,0 +1,105 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "crypto/ecdsa" -+ "math/big" -+ "testing" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+func TestECDSA(t *testing.T) { -+ type ASNSignatureTestVector struct { -+ // A brief description of the test case -+ Comment string `json:"comment"` -+ // A list of flags -+ Flags []string `json:"flags"` -+ // The message to sign -+ Msg string `json:"msg"` -+ // Test result -+ Result string `json:"result"` -+ // An ASN.1 encoded signature for msg -+ Sig string `json:"sig"` -+ // Identifier of the test case -+ TcID int `json:"tcId"` -+ } -+ -+ type ECPublicKey struct { -+ // The EC group used by this public key -+ Curve interface{} `json:"curve"` -+ } -+ -+ type ECDSATestGroup struct { -+ // Unencoded EC public key -+ Key *ECPublicKey `json:"key"` -+ // DER encoded public key -+ KeyDER string `json:"keyDer"` -+ // the hash function used for ECDSA -+ SHA string `json:"sha"` -+ Tests []*ASNSignatureTestVector `json:"tests"` -+ } -+ -+ type Root struct { -+ TestGroups []*ECDSATestGroup `json:"testGroups"` -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // An encoded ASN.1 integer missing a leading zero is invalid, but -+ // accepted by some implementations. -+ "MissingZero": false, -+ // A signature using a weaker hash than the EC params is not a security -+ // risk, as long as the hash is secure. -+ // https://www.imperialviolet.org/2014/05/25/strengthmatching.html -+ "WeakHash": true, -+ } -+ -+ // supportedCurves is a map of all elliptic curves supported -+ // by crypto/elliptic, which can subsequently be parsed and tested. -+ supportedCurves := map[string]bool{ -+ "secp224r1": true, -+ "secp256r1": true, -+ "secp384r1": true, -+ "secp521r1": true, -+ } -+ -+ var root Root -+ readTestVector(t, "ecdsa_test.json", &root) -+ for _, tg := range root.TestGroups { -+ curve := tg.Key.Curve.(string) -+ if !supportedCurves[curve] { -+ continue -+ } -+ pub := decodePublicKey(tg.KeyDER).(*ecdsa.PublicKey) -+ h := parseHash(tg.SHA).New() -+ for _, sig := range tg.Tests { -+ h.Reset() -+ h.Write(decodeHex(sig.Msg)) -+ hashed := h.Sum(nil) -+ sigBytes := decodeHex(sig.Sig) -+ got := ecdsa.VerifyASN1(pub, hashed, sigBytes) -+ if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { -+ t.Errorf("tcid: %d, type: %s, comment: %q, VerifyASN1 wanted success: %t", sig.TcID, sig.Result, sig.Comment, want) -+ } -+ -+ var r, s big.Int -+ var inner cryptobyte.String -+ input := cryptobyte.String(sigBytes) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadASN1Integer(&r) || -+ !inner.ReadASN1Integer(&s) || -+ !inner.Empty() { -+ continue -+ } -+ got = ecdsa.Verify(pub, hashed, &r, &s) -+ if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want { -+ t.Errorf("tcid: %d, type: %s, comment: %q, Verify wanted success: %t", sig.TcID, sig.Result, sig.Comment, want) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go -new file mode 100644 -index 00000000000000..0a7fbb7e0e5de2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/eddsa_test.go -@@ -0,0 +1,101 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.13 -+// +build go1.13 -+ -+package wycheproof -+ -+import ( -+ "testing" -+ -+ "golang.org/x/crypto/ed25519" -+) -+ -+func TestEddsa(t *testing.T) { -+ // Jwk the private key in webcrypto format -+ type Jwk struct { -+ } -+ -+ // Key unencoded key pair -+ type Key struct { -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // SignatureTestVector -+ type SignatureTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // The message to sign -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // A signature for msg -+ Sig string `json:"sig,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // EddsaTestGroup -+ type EddsaTestGroup struct { -+ -+ // the private key in webcrypto format -+ Jwk *Jwk `json:"jwk,omitempty"` -+ -+ // unencoded key pair -+ Key *Key `json:"key,omitempty"` -+ -+ // Asn encoded public key -+ KeyDer string `json:"keyDer,omitempty"` -+ -+ // Pem encoded public key -+ KeyPem string `json:"keyPem,omitempty"` -+ Tests []*SignatureTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*EddsaTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ var root Root -+ readTestVector(t, "eddsa_test.json", &root) -+ for _, tg := range root.TestGroups { -+ pub := decodePublicKey(tg.KeyDer).(ed25519.PublicKey) -+ for _, sig := range tg.Tests { -+ got := ed25519.Verify(pub, decodeHex(sig.Msg), decodeHex(sig.Sig)) -+ if want := shouldPass(sig.Result, sig.Flags, nil); got != want { -+ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go -new file mode 100644 -index 00000000000000..6b72e2c870eb5b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/hkdf_test.go -@@ -0,0 +1,111 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "bytes" -+ "io" -+ "testing" -+ -+ "golang.org/x/crypto/hkdf" -+) -+ -+func TestHkdf(t *testing.T) { -+ -+ // HkdfTestVector -+ type HkdfTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // the key (input key material) -+ Ikm string `json:"ikm,omitempty"` -+ -+ // additional information used in the key derivation -+ Info string `json:"info,omitempty"` -+ -+ // the generated bytes (output key material) -+ Okm string `json:"okm,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // the salt for the key derivation -+ Salt string `json:"salt,omitempty"` -+ -+ // the size of the output in bytes -+ Size int `json:"size,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // HkdfTestGroup -+ type HkdfTestGroup struct { -+ -+ // the size of the ikm in bits -+ KeySize int `json:"keySize,omitempty"` -+ Tests []*HkdfTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*HkdfTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ fileHashAlgorithms := map[string]string{ -+ "hkdf_sha1_test.json": "SHA-1", -+ "hkdf_sha256_test.json": "SHA-256", -+ "hkdf_sha384_test.json": "SHA-384", -+ "hkdf_sha512_test.json": "SHA-512", -+ } -+ -+ for f := range fileHashAlgorithms { -+ var root Root -+ readTestVector(t, f, &root) -+ for _, tg := range root.TestGroups { -+ for _, tv := range tg.Tests { -+ h := parseHash(fileHashAlgorithms[f]).New -+ hkdf := hkdf.New(h, decodeHex(tv.Ikm), decodeHex(tv.Salt), decodeHex(tv.Info)) -+ key := make([]byte, tv.Size) -+ wantPass := shouldPass(tv.Result, tv.Flags, nil) -+ _, err := io.ReadFull(hkdf, key) -+ if (err == nil) != wantPass { -+ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t, got: %v", tv.TcId, tv.Result, tv.Comment, wantPass, err) -+ } -+ if err != nil { -+ continue // don't validate output text if reading failed -+ } -+ if got, want := key, decodeHex(tv.Okm); !bytes.Equal(got, want) { -+ t.Errorf("tcid: %d, type: %s, comment: %q, output bytes don't match", tv.TcId, tv.Result, tv.Comment) -+ } -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go -new file mode 100644 -index 00000000000000..bcc56f28fc8dd8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/hmac_test.go -@@ -0,0 +1,105 @@ -+// Copyright 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "crypto/hmac" -+ "testing" -+) -+ -+func TestHMAC(t *testing.T) { -+ // MacTestVector -+ type MacTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // the key -+ Key string `json:"key,omitempty"` -+ -+ // the plaintext -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // the authentication tag -+ Tag string `json:"tag,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // MacTestGroup -+ type MacTestGroup struct { -+ -+ // the keySize in bits -+ KeySize int `json:"keySize,omitempty"` -+ -+ // the expected size of the tag in bits -+ TagSize int `json:"tagSize,omitempty"` -+ Tests []*MacTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*MacTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ fileHashAlgs := map[string]string{ -+ "hmac_sha1_test.json": "SHA-1", -+ "hmac_sha224_test.json": "SHA-224", -+ "hmac_sha256_test.json": "SHA-256", -+ "hmac_sha384_test.json": "SHA-384", -+ "hmac_sha512_test.json": "SHA-512", -+ } -+ -+ for f := range fileHashAlgs { -+ var root Root -+ readTestVector(t, f, &root) -+ for _, tg := range root.TestGroups { -+ h := parseHash(fileHashAlgs[f]) -+ // Skip test vectors where the tag length does not equal the -+ // hash length, since crypto/hmac does not support generating -+ // these truncated tags. -+ if tg.TagSize/8 != h.Size() { -+ continue -+ } -+ for _, tv := range tg.Tests { -+ hm := hmac.New(h.New, decodeHex(tv.Key)) -+ hm.Write(decodeHex(tv.Msg)) -+ tag := hm.Sum(nil) -+ got := hmac.Equal(decodeHex(tv.Tag), tag) -+ if want := shouldPass(tv.Result, tv.Flags, nil); want != got { -+ t.Errorf("%s, tcid: %d, type: %s, comment: %q, unexpected result", f, tv.TcId, tv.Result, tv.Comment) -+ } -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go -new file mode 100644 -index 00000000000000..3101dfc1c23e51 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/internal/dsa/dsa.go -@@ -0,0 +1,33 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package dsa provides an internal version of dsa.Verify -+// that is used for the Wycheproof tests. -+package dsa -+ -+import ( -+ "crypto/dsa" -+ "math/big" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// VerifyASN1 verifies the ASN1 encoded signature, sig, of hash using the -+// public key, pub. Its return value records whether the signature is valid. -+func VerifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool { -+ var ( -+ r, s = &big.Int{}, &big.Int{} -+ inner cryptobyte.String -+ ) -+ input := cryptobyte.String(sig) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadASN1Integer(r) || -+ !inner.ReadASN1Integer(s) || -+ !inner.Empty() { -+ return false -+ } -+ return dsa.Verify(pub, hash, r, s) -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go -new file mode 100644 -index 00000000000000..746af130f17052 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/notboring.go -@@ -0,0 +1,9 @@ -+// Copyright 2022 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !boringcrypto -+ -+package wycheproof -+ -+const boringcryptoEnabled = false -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go -new file mode 100644 -index 00000000000000..19cc4fdcb72884 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_oaep_decrypt_test.go -@@ -0,0 +1,149 @@ -+// Copyright 2020 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "bytes" -+ "crypto/rsa" -+ "crypto/x509" -+ "fmt" -+ "testing" -+) -+ -+func TestRSAOAEPDecrypt(t *testing.T) { -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // RsaesOaepTestVector -+ type RsaesOaepTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // An encryption of msg -+ Ct string `json:"ct,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // The label used for the encryption -+ Label string `json:"label,omitempty"` -+ -+ // The encrypted message -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // RsaesOaepTestGroup -+ type RsaesOaepTestGroup struct { -+ -+ // The private exponent -+ D string `json:"d,omitempty"` -+ -+ // The public exponent -+ E string `json:"e,omitempty"` -+ -+ // the message generating function (e.g. MGF1) -+ Mgf string `json:"mgf,omitempty"` -+ -+ // The hash function used for the message generating function. -+ MgfSha string `json:"mgfSha,omitempty"` -+ -+ // The modulus of the key -+ N string `json:"n,omitempty"` -+ -+ // Pem encoded private key -+ PrivateKeyPem string `json:"privateKeyPem,omitempty"` -+ -+ // Pkcs 8 encoded private key. -+ PrivateKeyPkcs8 string `json:"privateKeyPkcs8,omitempty"` -+ -+ // The hash function for hashing the label. -+ Sha string `json:"sha,omitempty"` -+ Tests []*RsaesOaepTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*RsaesOaepTestGroup `json:"testGroups,omitempty"` -+ } -+ -+ // rsa.DecryptOAEP doesn't support using a different hash for the -+ // MGF and the label, so skip all of the test vectors that use -+ // these unbalanced constructions. rsa_oaep_misc_test.json contains -+ // both balanced and unbalanced constructions so in that case -+ // we just filter out any test groups where MgfSha != Sha -+ files := []string{ -+ "rsa_oaep_2048_sha1_mgf1sha1_test.json", -+ "rsa_oaep_2048_sha224_mgf1sha224_test.json", -+ "rsa_oaep_2048_sha256_mgf1sha256_test.json", -+ "rsa_oaep_2048_sha384_mgf1sha384_test.json", -+ "rsa_oaep_2048_sha512_mgf1sha512_test.json", -+ "rsa_oaep_3072_sha256_mgf1sha256_test.json", -+ "rsa_oaep_3072_sha512_mgf1sha512_test.json", -+ "rsa_oaep_4096_sha256_mgf1sha256_test.json", -+ "rsa_oaep_4096_sha512_mgf1sha512_test.json", -+ "rsa_oaep_misc_test.json", -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // rsa.DecryptOAEP happily supports small key sizes -+ "SmallModulus": true, -+ } -+ -+ for _, f := range files { -+ var root Root -+ readTestVector(t, f, &root) -+ for _, tg := range root.TestGroups { -+ if tg.MgfSha != tg.Sha { -+ continue -+ } -+ priv, err := x509.ParsePKCS8PrivateKey(decodeHex(tg.PrivateKeyPkcs8)) -+ if err != nil { -+ t.Fatalf("%s failed to parse PKCS #8 private key: %s", f, err) -+ } -+ hash := parseHash(tg.Sha) -+ for _, tv := range tg.Tests { -+ t.Run(fmt.Sprintf("%s #%d", f, tv.TcId), func(t *testing.T) { -+ wantPass := shouldPass(tv.Result, tv.Flags, flagsShouldPass) -+ plaintext, err := rsa.DecryptOAEP(hash.New(), nil, priv.(*rsa.PrivateKey), decodeHex(tv.Ct), decodeHex(tv.Label)) -+ if wantPass { -+ if err != nil { -+ t.Fatalf("comment: %s, expected success: %s", tv.Comment, err) -+ } -+ if !bytes.Equal(plaintext, decodeHex(tv.Msg)) { -+ t.Errorf("comment: %s, unexpected plaintext: got %x, want %s", tv.Comment, plaintext, tv.Msg) -+ } -+ } else if err == nil { -+ t.Errorf("comment: %s, expected failure", tv.Comment) -+ } -+ }) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go -new file mode 100644 -index 00000000000000..2ad9a4313b6497 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_pss_test.go -@@ -0,0 +1,169 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "crypto/rsa" -+ "testing" -+) -+ -+func TestRsaPss(t *testing.T) { -+ // KeyJwk Public key in JWK format -+ type KeyJwk struct { -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // SignatureTestVector -+ type SignatureTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // The message to sign -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // A signature for msg -+ Sig string `json:"sig,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // RsassaPkcs1TestGroup -+ type RsassaPkcs1TestGroup struct { -+ -+ // The private exponent -+ D string `json:"d,omitempty"` -+ -+ // The public exponent -+ E string `json:"e,omitempty"` -+ -+ // ASN encoding of the sequence [n, e] -+ KeyAsn string `json:"keyAsn,omitempty"` -+ -+ // ASN encoding of the public key -+ KeyDer string `json:"keyDer,omitempty"` -+ -+ // Public key in JWK format -+ KeyJwk *KeyJwk `json:"keyJwk,omitempty"` -+ -+ // Pem encoded public key -+ KeyPem string `json:"keyPem,omitempty"` -+ -+ // the size of the modulus in bits -+ KeySize int `json:"keySize,omitempty"` -+ -+ // The modulus of the key -+ N string `json:"n,omitempty"` -+ -+ // The salt length -+ SLen int `json:"sLen,omitempty"` -+ -+ // the hash function used for the message -+ Sha string `json:"sha,omitempty"` -+ Tests []*SignatureTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"` -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // A signature using a weaker hash than the EC params is not a security risk, as long as the hash is secure. -+ // https://www.imperialviolet.org/2014/05/25/strengthmatching.html -+ "WeakHash": true, -+ } -+ -+ // filesOverrideToPassZeroSLen is a map of all test files -+ // and which TcIds that should be overridden to pass if the -+ // rsa.PSSOptions.SaltLength is zero. -+ // These tests expect a failure with a PSSOptions.SaltLength: 0 -+ // and a signature that uses a different salt length. However, -+ // a salt length of 0 is defined as rsa.PSSSaltLengthAuto which -+ // works deterministically to auto-detect the length when -+ // verifying, so these tests actually pass as they should. -+ filesOverrideToPassZeroSLen := map[string][]int{ -+ "rsa_pss_2048_sha1_mgf1_20_test.json": []int{46, 47}, -+ "rsa_pss_2048_sha256_mgf1_0_test.json": []int{67, 68}, -+ "rsa_pss_2048_sha256_mgf1_32_test.json": []int{67, 68}, -+ "rsa_pss_3072_sha256_mgf1_32_test.json": []int{67, 68}, -+ "rsa_pss_4096_sha256_mgf1_32_test.json": []int{67, 68}, -+ "rsa_pss_4096_sha512_mgf1_32_test.json": []int{136, 137}, -+ // "rsa_pss_misc_test.json": nil, // TODO: This ones seems to be broken right now, but can enable later on. -+ } -+ -+ if !boringcryptoEnabled { -+ // boringcrypto doesn't support the truncated SHA-512 hashes, so only -+ // test them if boringcrypto isn't enabled. -+ filesOverrideToPassZeroSLen["rsa_pss_2048_sha512_256_mgf1_28_test.json"] = []int{13, 14, 15} -+ filesOverrideToPassZeroSLen["rsa_pss_2048_sha512_256_mgf1_32_test.json"] = []int{13, 14} -+ } -+ -+ for f := range filesOverrideToPassZeroSLen { -+ var root Root -+ readTestVector(t, f, &root) -+ for _, tg := range root.TestGroups { -+ pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey) -+ ch := parseHash(tg.Sha) -+ h := ch.New() -+ opts := &rsa.PSSOptions{ -+ Hash: ch, -+ SaltLength: rsa.PSSSaltLengthAuto, -+ } -+ // Run all the tests twice: the first time with the salt length -+ // as PSSSaltLengthAuto, and the second time with the salt length -+ // explictily set to tg.SLen. -+ for i := 0; i < 2; i++ { -+ for _, sig := range tg.Tests { -+ h.Reset() -+ h.Write(decodeHex(sig.Msg)) -+ hashed := h.Sum(nil) -+ err := rsa.VerifyPSS(pub, ch, hashed, decodeHex(sig.Sig), opts) -+ want := shouldPass(sig.Result, sig.Flags, flagsShouldPass) -+ if opts.SaltLength == 0 { -+ for _, id := range filesOverrideToPassZeroSLen[f] { -+ if sig.TcId == id { -+ want = true -+ break -+ } -+ } -+ } -+ if (err == nil) != want { -+ t.Errorf("file: %v, tcid: %d, type: %s, opts.SaltLength: %v, comment: %q, wanted success: %t", f, sig.TcId, sig.Result, opts.SaltLength, sig.Comment, want) -+ } -+ } -+ // Update opts.SaltLength for the second run of the tests. -+ opts.SaltLength = tg.SLen -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go -new file mode 100644 -index 00000000000000..3c31c225527ea7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/rsa_signature_test.go -@@ -0,0 +1,123 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package wycheproof -+ -+import ( -+ "crypto/rsa" -+ "testing" -+) -+ -+func TestRsa(t *testing.T) { -+ // KeyJwk Public key in JWK format -+ type KeyJwk struct { -+ } -+ -+ // Notes a description of the labels used in the test vectors -+ type Notes struct { -+ } -+ -+ // SignatureTestVector -+ type SignatureTestVector struct { -+ -+ // A brief description of the test case -+ Comment string `json:"comment,omitempty"` -+ -+ // A list of flags -+ Flags []string `json:"flags,omitempty"` -+ -+ // The message to sign -+ Msg string `json:"msg,omitempty"` -+ -+ // Test result -+ Result string `json:"result,omitempty"` -+ -+ // A signature for msg -+ Sig string `json:"sig,omitempty"` -+ -+ // Identifier of the test case -+ TcId int `json:"tcId,omitempty"` -+ } -+ -+ // RsassaPkcs1TestGroup -+ type RsassaPkcs1TestGroup struct { -+ -+ // The private exponent -+ D string `json:"d,omitempty"` -+ -+ // The public exponent -+ E string `json:"e,omitempty"` -+ -+ // ASN encoding of the sequence [n, e] -+ KeyAsn string `json:"keyAsn,omitempty"` -+ -+ // ASN encoding of the public key -+ KeyDer string `json:"keyDer,omitempty"` -+ -+ // Public key in JWK format -+ KeyJwk *KeyJwk `json:"keyJwk,omitempty"` -+ -+ // Pem encoded public key -+ KeyPem string `json:"keyPem,omitempty"` -+ -+ // the size of the modulus in bits -+ KeySize int `json:"keySize,omitempty"` -+ -+ // The modulus of the key -+ N string `json:"n,omitempty"` -+ -+ // the hash function used for the message -+ Sha string `json:"sha,omitempty"` -+ Tests []*SignatureTestVector `json:"tests,omitempty"` -+ Type interface{} `json:"type,omitempty"` -+ } -+ -+ // Root -+ type Root struct { -+ -+ // the primitive tested in the test file -+ Algorithm string `json:"algorithm,omitempty"` -+ -+ // the version of the test vectors. -+ GeneratorVersion string `json:"generatorVersion,omitempty"` -+ -+ // additional documentation -+ Header []string `json:"header,omitempty"` -+ -+ // a description of the labels used in the test vectors -+ Notes *Notes `json:"notes,omitempty"` -+ -+ // the number of test vectors in this test -+ NumberOfTests int `json:"numberOfTests,omitempty"` -+ Schema interface{} `json:"schema,omitempty"` -+ TestGroups []*RsassaPkcs1TestGroup `json:"testGroups,omitempty"` -+ } -+ -+ flagsShouldPass := map[string]bool{ -+ // Omitting the parameter field in an ASN encoded integer is a legacy behavior. -+ "MissingNull": false, -+ // Keys with a modulus less than 2048 bits are supported by crypto/rsa. -+ "SmallModulus": true, -+ // Small public keys are supported by crypto/rsa. -+ "SmallPublicKey": true, -+ } -+ -+ var root Root -+ readTestVector(t, "rsa_signature_test.json", &root) -+ for _, tg := range root.TestGroups { -+ pub := decodePublicKey(tg.KeyDer).(*rsa.PublicKey) -+ ch := parseHash(tg.Sha) -+ h := ch.New() -+ for _, sig := range tg.Tests { -+ h.Reset() -+ h.Write(decodeHex(sig.Msg)) -+ hashed := h.Sum(nil) -+ err := rsa.VerifyPKCS1v15(pub, ch, hashed, decodeHex(sig.Sig)) -+ want := shouldPass(sig.Result, sig.Flags, flagsShouldPass) -+ if (err == nil) != want { -+ t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcId, sig.Result, sig.Comment, want) -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go b/ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go -new file mode 100644 -index 00000000000000..bbaae3b338ba9b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/internal/wycheproof/wycheproof_test.go -@@ -0,0 +1,141 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package wycheproof runs a set of the Wycheproof tests -+// provided by https://github.com/google/wycheproof. -+package wycheproof -+ -+import ( -+ "crypto" -+ "crypto/x509" -+ "encoding/hex" -+ "encoding/json" -+ "flag" -+ "fmt" -+ "log" -+ "os" -+ "os/exec" -+ "path/filepath" -+ "testing" -+ -+ _ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+) -+ -+const wycheproofModVer = "v0.0.0-20191219022705-2196000605e4" -+ -+var wycheproofTestVectorsDir string -+ -+func TestMain(m *testing.M) { -+ flag.Parse() -+ if flag.Lookup("test.short").Value.(flag.Getter).Get().(bool) { -+ log.Println("skipping test that downloads testdata via 'go mod download' in short mode") -+ os.Exit(0) -+ } -+ if _, err := exec.LookPath("go"); err != nil { -+ log.Printf("skipping test because 'go' command is unavailable: %v", err) -+ os.Exit(0) -+ } -+ if os.Getenv("GO_BUILDER_FLAKY_NET") != "" { -+ log.Printf("skipping test because GO_BUILDER_FLAKY_NET is set") -+ os.Exit(0) -+ } -+ -+ // Download the JSON test files from github.com/google/wycheproof -+ // using `go mod download -json` so the cached source of the testdata -+ // can be used in the following tests. -+ path := "github.com/google/wycheproof@" + wycheproofModVer -+ cmd := exec.Command("go", "mod", "download", "-json", path) -+ output, err := cmd.Output() -+ if err != nil { -+ log.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output) -+ } -+ var dm struct { -+ Dir string // absolute path to cached source root directory -+ } -+ if err := json.Unmarshal(output, &dm); err != nil { -+ log.Fatal(err) -+ } -+ // Now that the module has been downloaded, use the absolute path of the -+ // cached source as the root directory for all tests going forward. -+ wycheproofTestVectorsDir = filepath.Join(dm.Dir, "testvectors") -+ os.Exit(m.Run()) -+} -+ -+func readTestVector(t *testing.T, f string, dest interface{}) { -+ b, err := os.ReadFile(filepath.Join(wycheproofTestVectorsDir, f)) -+ if err != nil { -+ t.Fatalf("failed to read json file: %v", err) -+ } -+ if err := json.Unmarshal(b, &dest); err != nil { -+ t.Fatalf("failed to unmarshal json file: %v", err) -+ } -+} -+ -+func decodeHex(s string) []byte { -+ b, err := hex.DecodeString(s) -+ if err != nil { -+ panic(err) -+ } -+ return b -+} -+ -+func decodePublicKey(der string) interface{} { -+ d := decodeHex(der) -+ pub, err := x509.ParsePKIXPublicKey(d) -+ if err != nil { -+ panic(fmt.Sprintf("failed to parse DER encoded public key: %v", err)) -+ } -+ return pub -+} -+ -+func parseHash(h string) crypto.Hash { -+ switch h { -+ case "SHA-1": -+ return crypto.SHA1 -+ case "SHA-256": -+ return crypto.SHA256 -+ case "SHA-224": -+ return crypto.SHA224 -+ case "SHA-384": -+ return crypto.SHA384 -+ case "SHA-512": -+ return crypto.SHA512 -+ case "SHA-512/224": -+ return crypto.SHA512_224 -+ case "SHA-512/256": -+ return crypto.SHA512_256 -+ default: -+ panic(fmt.Sprintf("could not identify SHA hash algorithm: %q", h)) -+ } -+} -+ -+// shouldPass returns whether or not the test should pass. -+// flagsShouldPass is a map associated with whether or not -+// a flag for an "acceptable" result should pass. -+// Every possible flag value that's associated with an -+// "acceptable" result should be explicitly specified, -+// otherwise the test will panic. -+func shouldPass(result string, flags []string, flagsShouldPass map[string]bool) bool { -+ switch result { -+ case "valid": -+ return true -+ case "invalid": -+ return false -+ case "acceptable": -+ for _, flag := range flags { -+ pass, ok := flagsShouldPass[flag] -+ if !ok { -+ panic(fmt.Sprintf("unspecified flag: %q", flag)) -+ } -+ if !pass { -+ return false -+ } -+ } -+ return true // There are no flags, or all are meant to pass. -+ default: -+ panic(fmt.Sprintf("unexpected result: %v", result)) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/md4/example_test.go b/ms_mod/golang.org/x/crypto/md4/example_test.go -new file mode 100644 -index 00000000000000..db3f59b19bce54 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/md4/example_test.go -@@ -0,0 +1,20 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package md4_test -+ -+import ( -+ "fmt" -+ "io" -+ -+ "golang.org/x/crypto/md4" -+) -+ -+func ExampleNew() { -+ h := md4.New() -+ data := "These pretzels are making me thirsty." -+ io.WriteString(h, data) -+ fmt.Printf("%x", h.Sum(nil)) -+ // Output: 48c4e365090b30a32f084c4888deceaa -+} -diff --git a/ms_mod/golang.org/x/crypto/md4/md4.go b/ms_mod/golang.org/x/crypto/md4/md4.go -new file mode 100644 -index 00000000000000..59d3480693050f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/md4/md4.go -@@ -0,0 +1,122 @@ -+// Copyright 2009 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package md4 implements the MD4 hash algorithm as defined in RFC 1320. -+// -+// Deprecated: MD4 is cryptographically broken and should should only be used -+// where compatibility with legacy systems, not security, is the goal. Instead, -+// use a secure hash like SHA-256 (from crypto/sha256). -+package md4 // import "golang.org/x/crypto/md4" -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.MD4, New) -+} -+ -+// The size of an MD4 checksum in bytes. -+const Size = 16 -+ -+// The blocksize of MD4 in bytes. -+const BlockSize = 64 -+ -+const ( -+ _Chunk = 64 -+ _Init0 = 0x67452301 -+ _Init1 = 0xEFCDAB89 -+ _Init2 = 0x98BADCFE -+ _Init3 = 0x10325476 -+) -+ -+// digest represents the partial evaluation of a checksum. -+type digest struct { -+ s [4]uint32 -+ x [_Chunk]byte -+ nx int -+ len uint64 -+} -+ -+func (d *digest) Reset() { -+ d.s[0] = _Init0 -+ d.s[1] = _Init1 -+ d.s[2] = _Init2 -+ d.s[3] = _Init3 -+ d.nx = 0 -+ d.len = 0 -+} -+ -+// New returns a new hash.Hash computing the MD4 checksum. -+func New() hash.Hash { -+ d := new(digest) -+ d.Reset() -+ return d -+} -+ -+func (d *digest) Size() int { return Size } -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Write(p []byte) (nn int, err error) { -+ nn = len(p) -+ d.len += uint64(nn) -+ if d.nx > 0 { -+ n := len(p) -+ if n > _Chunk-d.nx { -+ n = _Chunk - d.nx -+ } -+ for i := 0; i < n; i++ { -+ d.x[d.nx+i] = p[i] -+ } -+ d.nx += n -+ if d.nx == _Chunk { -+ _Block(d, d.x[0:]) -+ d.nx = 0 -+ } -+ p = p[n:] -+ } -+ n := _Block(d, p) -+ p = p[n:] -+ if len(p) > 0 { -+ d.nx = copy(d.x[:], p) -+ } -+ return -+} -+ -+func (d0 *digest) Sum(in []byte) []byte { -+ // Make a copy of d0, so that caller can keep writing and summing. -+ d := new(digest) -+ *d = *d0 -+ -+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. -+ len := d.len -+ var tmp [64]byte -+ tmp[0] = 0x80 -+ if len%64 < 56 { -+ d.Write(tmp[0 : 56-len%64]) -+ } else { -+ d.Write(tmp[0 : 64+56-len%64]) -+ } -+ -+ // Length in bits. -+ len <<= 3 -+ for i := uint(0); i < 8; i++ { -+ tmp[i] = byte(len >> (8 * i)) -+ } -+ d.Write(tmp[0:8]) -+ -+ if d.nx != 0 { -+ panic("d.nx != 0") -+ } -+ -+ for _, s := range d.s { -+ in = append(in, byte(s>>0)) -+ in = append(in, byte(s>>8)) -+ in = append(in, byte(s>>16)) -+ in = append(in, byte(s>>24)) -+ } -+ return in -+} -diff --git a/ms_mod/golang.org/x/crypto/md4/md4_test.go b/ms_mod/golang.org/x/crypto/md4/md4_test.go -new file mode 100644 -index 00000000000000..b56edd7875d8b6 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/md4/md4_test.go -@@ -0,0 +1,71 @@ -+// Copyright 2009 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package md4 -+ -+import ( -+ "fmt" -+ "io" -+ "testing" -+) -+ -+type md4Test struct { -+ out string -+ in string -+} -+ -+var golden = []md4Test{ -+ {"31d6cfe0d16ae931b73c59d7e0c089c0", ""}, -+ {"bde52cb31de33e46245e05fbdbd6fb24", "a"}, -+ {"ec388dd78999dfc7cf4632465693b6bf", "ab"}, -+ {"a448017aaf21d8525fc10ae87aa6729d", "abc"}, -+ {"41decd8f579255c5200f86a4bb3ba740", "abcd"}, -+ {"9803f4a34e8eb14f96adba49064a0c41", "abcde"}, -+ {"804e7f1c2586e50b49ac65db5b645131", "abcdef"}, -+ {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"}, -+ {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"}, -+ {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"}, -+ {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"}, -+ {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."}, -+ {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."}, -+ {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."}, -+ {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, -+ {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"}, -+ {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."}, -+ {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."}, -+ {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."}, -+ {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, -+ {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, -+ {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"}, -+ {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"}, -+ {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, -+ {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."}, -+ {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."}, -+ {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."}, -+ {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"}, -+ {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, -+ {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, -+ {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"}, -+} -+ -+func TestGolden(t *testing.T) { -+ for i := 0; i < len(golden); i++ { -+ g := golden[i] -+ c := New() -+ for j := 0; j < 3; j++ { -+ if j < 2 { -+ io.WriteString(c, g.in) -+ } else { -+ io.WriteString(c, g.in[0:len(g.in)/2]) -+ c.Sum(nil) -+ io.WriteString(c, g.in[len(g.in)/2:]) -+ } -+ s := fmt.Sprintf("%x", c.Sum(nil)) -+ if s != g.out { -+ t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) -+ } -+ c.Reset() -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/md4/md4block.go b/ms_mod/golang.org/x/crypto/md4/md4block.go -new file mode 100644 -index 00000000000000..5ea1ba966ea4d5 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/md4/md4block.go -@@ -0,0 +1,91 @@ -+// Copyright 2009 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// MD4 block step. -+// In its own file so that a faster assembly or C version -+// can be substituted easily. -+ -+package md4 -+ -+import "math/bits" -+ -+var shift1 = []int{3, 7, 11, 19} -+var shift2 = []int{3, 5, 9, 13} -+var shift3 = []int{3, 9, 11, 15} -+ -+var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15} -+var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} -+ -+func _Block(dig *digest, p []byte) int { -+ a := dig.s[0] -+ b := dig.s[1] -+ c := dig.s[2] -+ d := dig.s[3] -+ n := 0 -+ var X [16]uint32 -+ for len(p) >= _Chunk { -+ aa, bb, cc, dd := a, b, c, d -+ -+ j := 0 -+ for i := 0; i < 16; i++ { -+ X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 -+ j += 4 -+ } -+ -+ // If this needs to be made faster in the future, -+ // the usual trick is to unroll each of these -+ // loops by a factor of 4; that lets you replace -+ // the shift[] lookups with constants and, -+ // with suitable variable renaming in each -+ // unrolled body, delete the a, b, c, d = d, a, b, c -+ // (or you can let the optimizer do the renaming). -+ // -+ // The index variables are uint so that % by a power -+ // of two can be optimized easily by a compiler. -+ -+ // Round 1. -+ for i := uint(0); i < 16; i++ { -+ x := i -+ s := shift1[i%4] -+ f := ((c ^ d) & b) ^ d -+ a += f + X[x] -+ a = bits.RotateLeft32(a, s) -+ a, b, c, d = d, a, b, c -+ } -+ -+ // Round 2. -+ for i := uint(0); i < 16; i++ { -+ x := xIndex2[i] -+ s := shift2[i%4] -+ g := (b & c) | (b & d) | (c & d) -+ a += g + X[x] + 0x5a827999 -+ a = bits.RotateLeft32(a, s) -+ a, b, c, d = d, a, b, c -+ } -+ -+ // Round 3. -+ for i := uint(0); i < 16; i++ { -+ x := xIndex3[i] -+ s := shift3[i%4] -+ h := b ^ c ^ d -+ a += h + X[x] + 0x6ed9eba1 -+ a = bits.RotateLeft32(a, s) -+ a, b, c, d = d, a, b, c -+ } -+ -+ a += aa -+ b += bb -+ c += cc -+ d += dd -+ -+ p = p[_Chunk:] -+ n += _Chunk -+ } -+ -+ dig.s[0] = a -+ dig.s[1] = b -+ dig.s[2] = c -+ dig.s[3] = d -+ return n -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/auth/auth.go b/ms_mod/golang.org/x/crypto/nacl/auth/auth.go -new file mode 100644 -index 00000000000000..1d588d5c1cd21d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/auth/auth.go -@@ -0,0 +1,58 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+Package auth authenticates a message using a secret key. -+ -+The Sum function, viewed as a function of the message for a uniform random -+key, is designed to meet the standard notion of unforgeability. This means -+that an attacker cannot find authenticators for any messages not authenticated -+by the sender, even if the attacker has adaptively influenced the messages -+authenticated by the sender. For a formal definition see, e.g., Section 2.4 -+of Bellare, Kilian, and Rogaway, "The security of the cipher block chaining -+message authentication code," Journal of Computer and System Sciences 61 (2000), -+362–399; http://www-cse.ucsd.edu/~mihir/papers/cbc.html. -+ -+auth does not make any promises regarding "strong" unforgeability; perhaps -+one valid authenticator can be converted into another valid authenticator for -+the same message. NaCl also does not make any promises regarding "truncated -+unforgeability." -+ -+This package is interoperable with NaCl: https://nacl.cr.yp.to/auth.html. -+*/ -+package auth -+ -+import ( -+ "crypto/hmac" -+ "crypto/sha512" -+) -+ -+const ( -+ // Size is the size, in bytes, of an authenticated digest. -+ Size = 32 -+ // KeySize is the size, in bytes, of an authentication key. -+ KeySize = 32 -+) -+ -+// Sum generates an authenticator for m using a secret key and returns the -+// 32-byte digest. -+func Sum(m []byte, key *[KeySize]byte) *[Size]byte { -+ mac := hmac.New(sha512.New, key[:]) -+ mac.Write(m) -+ out := new([Size]byte) -+ copy(out[:], mac.Sum(nil)[:Size]) -+ return out -+} -+ -+// Verify checks that digest is a valid authenticator of message m under the -+// given secret key. Verify does not leak timing information. -+func Verify(digest []byte, m []byte, key *[KeySize]byte) bool { -+ if len(digest) != Size { -+ return false -+ } -+ mac := hmac.New(sha512.New, key[:]) -+ mac.Write(m) -+ expectedMAC := mac.Sum(nil) // first 256 bits of 512-bit sum -+ return hmac.Equal(digest, expectedMAC[:Size]) -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go b/ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go -new file mode 100644 -index 00000000000000..92074b50b60e64 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/auth/auth_test.go -@@ -0,0 +1,172 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package auth -+ -+import ( -+ "bytes" -+ rand "crypto/rand" -+ mrand "math/rand" -+ "testing" -+) -+ -+// Test cases are from RFC 4231, and match those present in the tests directory -+// of the download here: https://nacl.cr.yp.to/install.html -+var testCases = []struct { -+ key [32]byte -+ msg []byte -+ out [32]byte -+}{ -+ { -+ key: [32]byte{ -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, -+ 0x0b, 0x0b, 0x0b, 0x0b, -+ }, -+ msg: []byte("Hi There"), -+ out: [32]byte{ -+ 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, -+ 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, -+ 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, -+ 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, -+ }, -+ }, -+ { -+ key: [32]byte{'J', 'e', 'f', 'e'}, -+ msg: []byte("what do ya want for nothing?"), -+ out: [32]byte{ -+ 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, -+ 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, -+ 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, -+ 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, -+ }, -+ }, -+ { -+ key: [32]byte{ -+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -+ 0xaa, 0xaa, 0xaa, 0xaa, -+ }, -+ msg: []byte{ // 50 bytes of 0xdd -+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, -+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, -+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, -+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, -+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, -+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, -+ 0xdd, 0xdd, -+ }, -+ out: [32]byte{ -+ 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, -+ 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, -+ 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, -+ 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, -+ }, -+ }, -+ { -+ key: [32]byte{ -+ 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, -+ }, -+ msg: []byte{ -+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -+ 0xcd, 0xcd, -+ }, -+ out: [32]byte{ -+ 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, -+ 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, -+ 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, -+ 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, -+ }, -+ }, -+} -+ -+func TestSum(t *testing.T) { -+ for i, test := range testCases { -+ tag := Sum(test.msg, &test.key) -+ if !bytes.Equal(tag[:], test.out[:]) { -+ t.Errorf("#%d: Sum: got\n%x\nwant\n%x", i, tag, test.out) -+ } -+ } -+} -+ -+func TestVerify(t *testing.T) { -+ wrongMsg := []byte("unknown msg") -+ -+ for i, test := range testCases { -+ if !Verify(test.out[:], test.msg, &test.key) { -+ t.Errorf("#%d: Verify(%x, %q, %x) failed", i, test.out, test.msg, test.key) -+ } -+ if Verify(test.out[:], wrongMsg, &test.key) { -+ t.Errorf("#%d: Verify(%x, %q, %x) unexpectedly passed", i, test.out, wrongMsg, test.key) -+ } -+ } -+} -+ -+func TestStress(t *testing.T) { -+ if testing.Short() { -+ t.Skip("exhaustiveness test") -+ } -+ -+ var key [32]byte -+ msg := make([]byte, 10000) -+ prng := mrand.New(mrand.NewSource(0)) -+ -+ // copied from tests/auth5.c in nacl -+ for i := 0; i < 10000; i++ { -+ if _, err := rand.Read(key[:]); err != nil { -+ t.Fatal(err) -+ } -+ if _, err := rand.Read(msg[:i]); err != nil { -+ t.Fatal(err) -+ } -+ tag := Sum(msg[:i], &key) -+ if !Verify(tag[:], msg[:i], &key) { -+ t.Errorf("#%d: unexpected failure from Verify", i) -+ } -+ if i > 0 { -+ msgIndex := prng.Intn(i) -+ oldMsgByte := msg[msgIndex] -+ msg[msgIndex] += byte(1 + prng.Intn(255)) -+ if Verify(tag[:], msg[:i], &key) { -+ t.Errorf("#%d: unexpected success from Verify after corrupting message", i) -+ } -+ msg[msgIndex] = oldMsgByte -+ -+ tag[prng.Intn(len(tag))] += byte(1 + prng.Intn(255)) -+ if Verify(tag[:], msg[:i], &key) { -+ t.Errorf("#%d: unexpected success from Verify after corrupting authenticator", i) -+ } -+ } -+ } -+} -+ -+func BenchmarkAuth(b *testing.B) { -+ var key [32]byte -+ if _, err := rand.Read(key[:]); err != nil { -+ b.Fatal(err) -+ } -+ buf := make([]byte, 1024) -+ if _, err := rand.Read(buf[:]); err != nil { -+ b.Fatal(err) -+ } -+ -+ b.SetBytes(int64(len(buf))) -+ b.ReportAllocs() -+ b.ResetTimer() -+ -+ for i := 0; i < b.N; i++ { -+ tag := Sum(buf, &key) -+ if Verify(tag[:], buf, &key) == false { -+ b.Fatal("unexpected failure from Verify") -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/auth/example_test.go b/ms_mod/golang.org/x/crypto/nacl/auth/example_test.go -new file mode 100644 -index 00000000000000..02a2cd6c46a8f4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/auth/example_test.go -@@ -0,0 +1,36 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package auth_test -+ -+import ( -+ "encoding/hex" -+ "fmt" -+ -+ "golang.org/x/crypto/nacl/auth" -+) -+ -+func Example() { -+ // Load your secret key from a safe place and reuse it across multiple -+ // Sum calls. (Obviously don't use this example key for anything -+ // real.) If you want to convert a passphrase to a key, use a suitable -+ // package like bcrypt or scrypt. -+ secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") -+ if err != nil { -+ panic(err) -+ } -+ -+ var secretKey [32]byte -+ copy(secretKey[:], secretKeyBytes) -+ -+ mac := auth.Sum([]byte("hello world"), &secretKey) -+ fmt.Printf("%x\n", *mac) -+ result := auth.Verify(mac[:], []byte("hello world"), &secretKey) -+ fmt.Println(result) -+ badResult := auth.Verify(mac[:], []byte("different message"), &secretKey) -+ fmt.Println(badResult) -+ // Output: eca5a521f3d77b63f567fb0cb6f5f2d200641bc8dada42f60c5f881260c30317 -+ // true -+ // false -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/box/box.go b/ms_mod/golang.org/x/crypto/nacl/box/box.go -new file mode 100644 -index 00000000000000..7f3b830ee22f96 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/box/box.go -@@ -0,0 +1,182 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+Package box authenticates and encrypts small messages using public-key cryptography. -+ -+Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate -+messages. The length of messages is not hidden. -+ -+It is the caller's responsibility to ensure the uniqueness of noncesβ€”for -+example, by using nonce 1 for the first message, nonce 2 for the second -+message, etc. Nonces are long enough that randomly generated nonces have -+negligible risk of collision. -+ -+Messages should be small because: -+ -+1. The whole message needs to be held in memory to be processed. -+ -+2. Using large messages pressures implementations on small machines to decrypt -+and process plaintext before authenticating it. This is very dangerous, and -+this API does not allow it, but a protocol that uses excessive message sizes -+might present some implementations with no other choice. -+ -+3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. -+ -+4. Performance may be improved by working with messages that fit into data caches. -+ -+Thus large amounts of data should be chunked so that each message is small. -+(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable -+chunk size. -+ -+This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. -+Anonymous sealing/opening is an extension of NaCl defined by and interoperable -+with libsodium: -+https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes. -+*/ -+package box // import "golang.org/x/crypto/nacl/box" -+ -+import ( -+ cryptorand "crypto/rand" -+ "io" -+ -+ "golang.org/x/crypto/blake2b" -+ "golang.org/x/crypto/curve25519" -+ "golang.org/x/crypto/nacl/secretbox" -+ "golang.org/x/crypto/salsa20/salsa" -+) -+ -+const ( -+ // Overhead is the number of bytes of overhead when boxing a message. -+ Overhead = secretbox.Overhead -+ -+ // AnonymousOverhead is the number of bytes of overhead when using anonymous -+ // sealed boxes. -+ AnonymousOverhead = Overhead + 32 -+) -+ -+// GenerateKey generates a new public/private key pair suitable for use with -+// Seal and Open. -+func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { -+ publicKey = new([32]byte) -+ privateKey = new([32]byte) -+ _, err = io.ReadFull(rand, privateKey[:]) -+ if err != nil { -+ publicKey = nil -+ privateKey = nil -+ return -+ } -+ -+ curve25519.ScalarBaseMult(publicKey, privateKey) -+ return -+} -+ -+var zeros [16]byte -+ -+// Precompute calculates the shared key between peersPublicKey and privateKey -+// and writes it to sharedKey. The shared key can be used with -+// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing -+// when using the same pair of keys repeatedly. -+func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { -+ curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) -+ salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) -+} -+ -+// Seal appends an encrypted and authenticated copy of message to out, which -+// will be Overhead bytes longer than the original and must not overlap it. The -+// nonce must be unique for each distinct message for a given pair of keys. -+func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { -+ var sharedKey [32]byte -+ Precompute(&sharedKey, peersPublicKey, privateKey) -+ return secretbox.Seal(out, message, nonce, &sharedKey) -+} -+ -+// SealAfterPrecomputation performs the same actions as Seal, but takes a -+// shared key as generated by Precompute. -+func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { -+ return secretbox.Seal(out, message, nonce, sharedKey) -+} -+ -+// Open authenticates and decrypts a box produced by Seal and appends the -+// message to out, which must not overlap box. The output will be Overhead -+// bytes smaller than box. -+func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { -+ var sharedKey [32]byte -+ Precompute(&sharedKey, peersPublicKey, privateKey) -+ return secretbox.Open(out, box, nonce, &sharedKey) -+} -+ -+// OpenAfterPrecomputation performs the same actions as Open, but takes a -+// shared key as generated by Precompute. -+func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { -+ return secretbox.Open(out, box, nonce, sharedKey) -+} -+ -+// SealAnonymous appends an encrypted and authenticated copy of message to out, -+// which will be AnonymousOverhead bytes longer than the original and must not -+// overlap it. This differs from Seal in that the sender is not required to -+// provide a private key. -+func SealAnonymous(out, message []byte, recipient *[32]byte, rand io.Reader) ([]byte, error) { -+ if rand == nil { -+ rand = cryptorand.Reader -+ } -+ ephemeralPub, ephemeralPriv, err := GenerateKey(rand) -+ if err != nil { -+ return nil, err -+ } -+ -+ var nonce [24]byte -+ if err := sealNonce(ephemeralPub, recipient, &nonce); err != nil { -+ return nil, err -+ } -+ -+ if total := len(out) + AnonymousOverhead + len(message); cap(out) < total { -+ original := out -+ out = make([]byte, 0, total) -+ out = append(out, original...) -+ } -+ out = append(out, ephemeralPub[:]...) -+ -+ return Seal(out, message, &nonce, recipient, ephemeralPriv), nil -+} -+ -+// OpenAnonymous authenticates and decrypts a box produced by SealAnonymous and -+// appends the message to out, which must not overlap box. The output will be -+// AnonymousOverhead bytes smaller than box. -+func OpenAnonymous(out, box []byte, publicKey, privateKey *[32]byte) (message []byte, ok bool) { -+ if len(box) < AnonymousOverhead { -+ return nil, false -+ } -+ -+ var ephemeralPub [32]byte -+ copy(ephemeralPub[:], box[:32]) -+ -+ var nonce [24]byte -+ if err := sealNonce(&ephemeralPub, publicKey, &nonce); err != nil { -+ return nil, false -+ } -+ -+ return Open(out, box[32:], &nonce, &ephemeralPub, privateKey) -+} -+ -+// sealNonce generates a 24 byte nonce that is a blake2b digest of the -+// ephemeral public key and the receiver's public key. -+func sealNonce(ephemeralPub, peersPublicKey *[32]byte, nonce *[24]byte) error { -+ h, err := blake2b.New(24, nil) -+ if err != nil { -+ return err -+ } -+ -+ if _, err = h.Write(ephemeralPub[:]); err != nil { -+ return err -+ } -+ -+ if _, err = h.Write(peersPublicKey[:]); err != nil { -+ return err -+ } -+ -+ h.Sum(nonce[:0]) -+ -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/box/box_test.go b/ms_mod/golang.org/x/crypto/nacl/box/box_test.go -new file mode 100644 -index 00000000000000..cce1f3b4da1a20 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/box/box_test.go -@@ -0,0 +1,181 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package box -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/hex" -+ "testing" -+ -+ "golang.org/x/crypto/curve25519" -+) -+ -+func TestSealOpen(t *testing.T) { -+ publicKey1, privateKey1, _ := GenerateKey(rand.Reader) -+ publicKey2, privateKey2, _ := GenerateKey(rand.Reader) -+ -+ if *privateKey1 == *privateKey2 { -+ t.Fatalf("private keys are equal!") -+ } -+ if *publicKey1 == *publicKey2 { -+ t.Fatalf("public keys are equal!") -+ } -+ message := []byte("test message") -+ var nonce [24]byte -+ -+ box := Seal(nil, message, &nonce, publicKey1, privateKey2) -+ opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1) -+ if !ok { -+ t.Fatalf("failed to open box") -+ } -+ -+ if !bytes.Equal(opened, message) { -+ t.Fatalf("got %x, want %x", opened, message) -+ } -+ -+ for i := range box { -+ box[i] ^= 0x40 -+ _, ok := Open(nil, box, &nonce, publicKey2, privateKey1) -+ if ok { -+ t.Fatalf("opened box with byte %d corrupted", i) -+ } -+ box[i] ^= 0x40 -+ } -+} -+ -+func TestBox(t *testing.T) { -+ var privateKey1, privateKey2 [32]byte -+ for i := range privateKey1[:] { -+ privateKey1[i] = 1 -+ } -+ for i := range privateKey2[:] { -+ privateKey2[i] = 2 -+ } -+ -+ var publicKey1 [32]byte -+ curve25519.ScalarBaseMult(&publicKey1, &privateKey1) -+ var message [64]byte -+ for i := range message[:] { -+ message[i] = 3 -+ } -+ -+ var nonce [24]byte -+ for i := range nonce[:] { -+ nonce[i] = 4 -+ } -+ -+ box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2) -+ -+ // expected was generated using the C implementation of NaCl. -+ expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc") -+ -+ if !bytes.Equal(box, expected) { -+ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) -+ } -+} -+ -+func TestSealOpenAnonymous(t *testing.T) { -+ publicKey, privateKey, _ := GenerateKey(rand.Reader) -+ message := []byte("test message") -+ -+ box, err := SealAnonymous(nil, message, publicKey, nil) -+ if err != nil { -+ t.Fatalf("Unexpected error sealing %v", err) -+ } -+ opened, ok := OpenAnonymous(nil, box, publicKey, privateKey) -+ if !ok { -+ t.Fatalf("failed to open box") -+ } -+ -+ if !bytes.Equal(opened, message) { -+ t.Fatalf("got %x, want %x", opened, message) -+ } -+ -+ for i := range box { -+ box[i] ^= 0x40 -+ _, ok := OpenAnonymous(nil, box, publicKey, privateKey) -+ if ok { -+ t.Fatalf("opened box with byte %d corrupted", i) -+ } -+ box[i] ^= 0x40 -+ } -+ -+ // allocates new slice if out isn't long enough -+ out := []byte("hello") -+ orig := append([]byte(nil), out...) -+ box, err = SealAnonymous(out, message, publicKey, nil) -+ if err != nil { -+ t.Fatalf("Unexpected error sealing %v", err) -+ } -+ if !bytes.Equal(out, orig) { -+ t.Fatal("expected out to be unchanged") -+ } -+ if !bytes.HasPrefix(box, orig) { -+ t.Fatal("expected out to be coppied to returned slice") -+ } -+ _, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey) -+ if !ok { -+ t.Fatalf("failed to open box") -+ } -+ -+ // uses provided slice if it's long enough -+ out = append(make([]byte, 0, 1000), []byte("hello")...) -+ orig = append([]byte(nil), out...) -+ box, err = SealAnonymous(out, message, publicKey, nil) -+ if err != nil { -+ t.Fatalf("Unexpected error sealing %v", err) -+ } -+ if !bytes.Equal(out, orig) { -+ t.Fatal("expected out to be unchanged") -+ } -+ if &out[0] != &box[0] { -+ t.Fatal("expected box to point to out") -+ } -+ _, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey) -+ if !ok { -+ t.Fatalf("failed to open box") -+ } -+} -+ -+func TestSealedBox(t *testing.T) { -+ var privateKey [32]byte -+ for i := range privateKey[:] { -+ privateKey[i] = 1 -+ } -+ -+ var publicKey [32]byte -+ curve25519.ScalarBaseMult(&publicKey, &privateKey) -+ var message [64]byte -+ for i := range message[:] { -+ message[i] = 3 -+ } -+ -+ fakeRand := bytes.NewReader([]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}) -+ box, err := SealAnonymous(nil, message[:], &publicKey, fakeRand) -+ if err != nil { -+ t.Fatalf("Unexpected error sealing %v", err) -+ } -+ -+ // expected was generated using the C implementation of libsodium with a -+ // random implementation that always returns 5. -+ // https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7 -+ expected, _ := hex.DecodeString("50a61409b1ddd0325e9b16b700e719e9772c07000b1bd7786e907c653d20495d2af1697137a53b1b1dfc9befc49b6eeb38f86be720e155eb2be61976d2efb34d67ecd44a6ad634625eb9c288bfc883431a84ab0f5557dfe673aa6f74c19f033e648a947358cfcc606397fa1747d5219a") -+ -+ if !bytes.Equal(box, expected) { -+ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) -+ } -+ -+ // box was generated using the C implementation of libsodium. -+ // https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7 -+ box, _ = hex.DecodeString("3462e0640728247a6f581e3812850d6edc3dcad1ea5d8184c072f62fb65cb357e27ffa8b76f41656bc66a0882c4d359568410665746d27462a700f01e314f382edd7aae9064879b0f8ba7b88866f88f5e4fbd7649c850541877f9f33ebd25d46d9cbcce09b69a9ba07f0eb1d105d4264") -+ result, ok := OpenAnonymous(nil, box, &publicKey, &privateKey) -+ if !ok { -+ t.Fatalf("failed to open box") -+ } -+ if !bytes.Equal(result, message[:]) { -+ t.Fatalf("message didn't match, got\n%x\n, expected\n%x", result, message[:]) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/box/example_test.go b/ms_mod/golang.org/x/crypto/nacl/box/example_test.go -new file mode 100644 -index 00000000000000..25e42d2be9aa80 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/box/example_test.go -@@ -0,0 +1,95 @@ -+package box_test -+ -+import ( -+ crypto_rand "crypto/rand" // Custom so it's clear which rand we're using. -+ "fmt" -+ "io" -+ -+ "golang.org/x/crypto/nacl/box" -+) -+ -+func Example() { -+ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ -+ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ -+ // You must use a different nonce for each message you encrypt with the -+ // same key. Since the nonce here is 192 bits long, a random value -+ // provides a sufficiently small probability of repeats. -+ var nonce [24]byte -+ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil { -+ panic(err) -+ } -+ -+ msg := []byte("Alas, poor Yorick! I knew him, Horatio") -+ // This encrypts msg and appends the result to the nonce. -+ encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey) -+ -+ // The recipient can decrypt the message using their private key and the -+ // sender's public key. When you decrypt, you must use the same nonce you -+ // used to encrypt the message. One way to achieve this is to store the -+ // nonce alongside the encrypted message. Above, we stored the nonce in the -+ // first 24 bytes of the encrypted text. -+ var decryptNonce [24]byte -+ copy(decryptNonce[:], encrypted[:24]) -+ decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey) -+ if !ok { -+ panic("decryption error") -+ } -+ fmt.Println(string(decrypted)) -+ // Output: Alas, poor Yorick! I knew him, Horatio -+} -+ -+func Example_precompute() { -+ senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ -+ recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ -+ // The shared key can be used to speed up processing when using the same -+ // pair of keys repeatedly. -+ sharedEncryptKey := new([32]byte) -+ box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey) -+ -+ // You must use a different nonce for each message you encrypt with the -+ // same key. Since the nonce here is 192 bits long, a random value -+ // provides a sufficiently small probability of repeats. -+ var nonce [24]byte -+ if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil { -+ panic(err) -+ } -+ -+ msg := []byte("A fellow of infinite jest, of most excellent fancy") -+ // This encrypts msg and appends the result to the nonce. -+ encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey) -+ -+ // The shared key can be used to speed up processing when using the same -+ // pair of keys repeatedly. -+ var sharedDecryptKey [32]byte -+ box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey) -+ -+ // The recipient can decrypt the message using the shared key. When you -+ // decrypt, you must use the same nonce you used to encrypt the message. -+ // One way to achieve this is to store the nonce alongside the encrypted -+ // message. Above, we stored the nonce in the first 24 bytes of the -+ // encrypted text. -+ var decryptNonce [24]byte -+ copy(decryptNonce[:], encrypted[:24]) -+ decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey) -+ if !ok { -+ panic("decryption error") -+ } -+ fmt.Println(string(decrypted)) -+ // Output: A fellow of infinite jest, of most excellent fancy -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go b/ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go -new file mode 100644 -index 00000000000000..789f4ff03f2ff8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/secretbox/example_test.go -@@ -0,0 +1,53 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package secretbox_test -+ -+import ( -+ "crypto/rand" -+ "encoding/hex" -+ "fmt" -+ "io" -+ -+ "golang.org/x/crypto/nacl/secretbox" -+) -+ -+func Example() { -+ // Load your secret key from a safe place and reuse it across multiple -+ // Seal calls. (Obviously don't use this example key for anything -+ // real.) If you want to convert a passphrase to a key, use a suitable -+ // package like bcrypt or scrypt. -+ secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") -+ if err != nil { -+ panic(err) -+ } -+ -+ var secretKey [32]byte -+ copy(secretKey[:], secretKeyBytes) -+ -+ // You must use a different nonce for each message you encrypt with the -+ // same key. Since the nonce here is 192 bits long, a random value -+ // provides a sufficiently small probability of repeats. -+ var nonce [24]byte -+ if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { -+ panic(err) -+ } -+ -+ // This encrypts "hello world" and appends the result to the nonce. -+ encrypted := secretbox.Seal(nonce[:], []byte("hello world"), &nonce, &secretKey) -+ -+ // When you decrypt, you must use the same nonce and key you used to -+ // encrypt the message. One way to achieve this is to store the nonce -+ // alongside the encrypted message. Above, we stored the nonce in the first -+ // 24 bytes of the encrypted text. -+ var decryptNonce [24]byte -+ copy(decryptNonce[:], encrypted[:24]) -+ decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey) -+ if !ok { -+ panic("decryption error") -+ } -+ -+ fmt.Println(string(decrypted)) -+ // Output: hello world -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go -new file mode 100644 -index 00000000000000..f3c3242a0471da ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox.go -@@ -0,0 +1,173 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+Package secretbox encrypts and authenticates small messages. -+ -+Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with -+secret-key cryptography. The length of messages is not hidden. -+ -+It is the caller's responsibility to ensure the uniqueness of noncesβ€”for -+example, by using nonce 1 for the first message, nonce 2 for the second -+message, etc. Nonces are long enough that randomly generated nonces have -+negligible risk of collision. -+ -+Messages should be small because: -+ -+1. The whole message needs to be held in memory to be processed. -+ -+2. Using large messages pressures implementations on small machines to decrypt -+and process plaintext before authenticating it. This is very dangerous, and -+this API does not allow it, but a protocol that uses excessive message sizes -+might present some implementations with no other choice. -+ -+3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. -+ -+4. Performance may be improved by working with messages that fit into data caches. -+ -+Thus large amounts of data should be chunked so that each message is small. -+(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable -+chunk size. -+ -+This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. -+*/ -+package secretbox // import "golang.org/x/crypto/nacl/secretbox" -+ -+import ( -+ "golang.org/x/crypto/internal/alias" -+ "golang.org/x/crypto/internal/poly1305" -+ "golang.org/x/crypto/salsa20/salsa" -+) -+ -+// Overhead is the number of bytes of overhead when boxing a message. -+const Overhead = poly1305.TagSize -+ -+// setup produces a sub-key and Salsa20 counter given a nonce and key. -+func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { -+ // We use XSalsa20 for encryption so first we need to generate a -+ // key and nonce with HSalsa20. -+ var hNonce [16]byte -+ copy(hNonce[:], nonce[:]) -+ salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) -+ -+ // The final 8 bytes of the original nonce form the new nonce. -+ copy(counter[:], nonce[16:]) -+} -+ -+// sliceForAppend takes a slice and a requested number of bytes. It returns a -+// slice with the contents of the given slice followed by that many bytes and a -+// second slice that aliases into it and contains only the extra bytes. If the -+// original slice has sufficient capacity then no allocation is performed. -+func sliceForAppend(in []byte, n int) (head, tail []byte) { -+ if total := len(in) + n; cap(in) >= total { -+ head = in[:total] -+ } else { -+ head = make([]byte, total) -+ copy(head, in) -+ } -+ tail = head[len(in):] -+ return -+} -+ -+// Seal appends an encrypted and authenticated copy of message to out, which -+// must not overlap message. The key and nonce pair must be unique for each -+// distinct message and the output will be Overhead bytes longer than message. -+func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { -+ var subKey [32]byte -+ var counter [16]byte -+ setup(&subKey, &counter, nonce, key) -+ -+ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since -+ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of -+ // keystream as a side effect. -+ var firstBlock [64]byte -+ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) -+ -+ var poly1305Key [32]byte -+ copy(poly1305Key[:], firstBlock[:]) -+ -+ ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) -+ if alias.AnyOverlap(out, message) { -+ panic("nacl: invalid buffer overlap") -+ } -+ -+ // We XOR up to 32 bytes of message with the keystream generated from -+ // the first block. -+ firstMessageBlock := message -+ if len(firstMessageBlock) > 32 { -+ firstMessageBlock = firstMessageBlock[:32] -+ } -+ -+ tagOut := out -+ out = out[poly1305.TagSize:] -+ for i, x := range firstMessageBlock { -+ out[i] = firstBlock[32+i] ^ x -+ } -+ message = message[len(firstMessageBlock):] -+ ciphertext := out -+ out = out[len(firstMessageBlock):] -+ -+ // Now encrypt the rest. -+ counter[8] = 1 -+ salsa.XORKeyStream(out, message, &counter, &subKey) -+ -+ var tag [poly1305.TagSize]byte -+ poly1305.Sum(&tag, ciphertext, &poly1305Key) -+ copy(tagOut, tag[:]) -+ -+ return ret -+} -+ -+// Open authenticates and decrypts a box produced by Seal and appends the -+// message to out, which must not overlap box. The output will be Overhead -+// bytes smaller than box. -+func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { -+ if len(box) < Overhead { -+ return nil, false -+ } -+ -+ var subKey [32]byte -+ var counter [16]byte -+ setup(&subKey, &counter, nonce, key) -+ -+ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since -+ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of -+ // keystream as a side effect. -+ var firstBlock [64]byte -+ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) -+ -+ var poly1305Key [32]byte -+ copy(poly1305Key[:], firstBlock[:]) -+ var tag [poly1305.TagSize]byte -+ copy(tag[:], box) -+ -+ if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { -+ return nil, false -+ } -+ -+ ret, out := sliceForAppend(out, len(box)-Overhead) -+ if alias.AnyOverlap(out, box) { -+ panic("nacl: invalid buffer overlap") -+ } -+ -+ // We XOR up to 32 bytes of box with the keystream generated from -+ // the first block. -+ box = box[Overhead:] -+ firstMessageBlock := box -+ if len(firstMessageBlock) > 32 { -+ firstMessageBlock = firstMessageBlock[:32] -+ } -+ for i, x := range firstMessageBlock { -+ out[i] = firstBlock[32+i] ^ x -+ } -+ -+ box = box[len(firstMessageBlock):] -+ out = out[len(firstMessageBlock):] -+ -+ // Now decrypt the rest. -+ counter[8] = 1 -+ salsa.XORKeyStream(out, box, &counter, &subKey) -+ -+ return ret, true -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go -new file mode 100644 -index 00000000000000..3c70b0f4b3d230 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/secretbox/secretbox_test.go -@@ -0,0 +1,154 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package secretbox -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/hex" -+ "testing" -+) -+ -+func TestSealOpen(t *testing.T) { -+ var key [32]byte -+ var nonce [24]byte -+ -+ rand.Reader.Read(key[:]) -+ rand.Reader.Read(nonce[:]) -+ -+ var box, opened []byte -+ -+ for msgLen := 0; msgLen < 128; msgLen += 17 { -+ message := make([]byte, msgLen) -+ rand.Reader.Read(message) -+ -+ box = Seal(box[:0], message, &nonce, &key) -+ var ok bool -+ opened, ok = Open(opened[:0], box, &nonce, &key) -+ if !ok { -+ t.Errorf("%d: failed to open box", msgLen) -+ continue -+ } -+ -+ if !bytes.Equal(opened, message) { -+ t.Errorf("%d: got %x, expected %x", msgLen, opened, message) -+ continue -+ } -+ } -+ -+ for i := range box { -+ box[i] ^= 0x20 -+ _, ok := Open(opened[:0], box, &nonce, &key) -+ if ok { -+ t.Errorf("box was opened after corrupting byte %d", i) -+ } -+ box[i] ^= 0x20 -+ } -+} -+ -+func TestSecretBox(t *testing.T) { -+ var key [32]byte -+ var nonce [24]byte -+ var message [64]byte -+ -+ for i := range key[:] { -+ key[i] = 1 -+ } -+ for i := range nonce[:] { -+ nonce[i] = 2 -+ } -+ for i := range message[:] { -+ message[i] = 3 -+ } -+ -+ box := Seal(nil, message[:], &nonce, &key) -+ // expected was generated using the C implementation of NaCl. -+ expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") -+ -+ if !bytes.Equal(box, expected) { -+ t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) -+ } -+} -+ -+func TestAppend(t *testing.T) { -+ var key [32]byte -+ var nonce [24]byte -+ var message [8]byte -+ -+ out := make([]byte, 4) -+ box := Seal(out, message[:], &nonce, &key) -+ if !bytes.Equal(box[:4], out[:4]) { -+ t.Fatalf("Seal didn't correctly append") -+ } -+ -+ out = make([]byte, 4, 100) -+ box = Seal(out, message[:], &nonce, &key) -+ if !bytes.Equal(box[:4], out[:4]) { -+ t.Fatalf("Seal didn't correctly append with sufficient capacity.") -+ } -+} -+ -+func benchmarkSealSize(b *testing.B, size int) { -+ message := make([]byte, size) -+ out := make([]byte, size+Overhead) -+ var nonce [24]byte -+ var key [32]byte -+ -+ b.SetBytes(int64(size)) -+ b.ResetTimer() -+ -+ for i := 0; i < b.N; i++ { -+ out = Seal(out[:0], message, &nonce, &key) -+ } -+} -+ -+func BenchmarkSeal8Bytes(b *testing.B) { -+ benchmarkSealSize(b, 8) -+} -+ -+func BenchmarkSeal100Bytes(b *testing.B) { -+ benchmarkSealSize(b, 100) -+} -+ -+func BenchmarkSeal1K(b *testing.B) { -+ benchmarkSealSize(b, 1024) -+} -+ -+func BenchmarkSeal8K(b *testing.B) { -+ benchmarkSealSize(b, 8192) -+} -+ -+func benchmarkOpenSize(b *testing.B, size int) { -+ msg := make([]byte, size) -+ result := make([]byte, size) -+ var nonce [24]byte -+ var key [32]byte -+ box := Seal(nil, msg, &nonce, &key) -+ -+ b.SetBytes(int64(size)) -+ b.ResetTimer() -+ -+ for i := 0; i < b.N; i++ { -+ if _, ok := Open(result[:0], box, &nonce, &key); !ok { -+ panic("Open failed") -+ } -+ } -+} -+ -+func BenchmarkOpen8Bytes(b *testing.B) { -+ benchmarkOpenSize(b, 8) -+} -+ -+func BenchmarkOpen100Bytes(b *testing.B) { -+ benchmarkOpenSize(b, 100) -+} -+ -+func BenchmarkOpen1K(b *testing.B) { -+ benchmarkOpenSize(b, 1024) -+} -+ -+func BenchmarkOpen8K(b *testing.B) { -+ benchmarkOpenSize(b, 8192) -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/sign/sign.go b/ms_mod/golang.org/x/crypto/nacl/sign/sign.go -new file mode 100644 -index 00000000000000..8a6acdcc090abf ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/sign/sign.go -@@ -0,0 +1,90 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package sign signs small messages using public-key cryptography. -+// -+// Sign uses Ed25519 to sign messages. The length of messages is not hidden. -+// Messages should be small because: -+// 1. The whole message needs to be held in memory to be processed. -+// 2. Using large messages pressures implementations on small machines to process -+// plaintext without verifying the signature. This is very dangerous, and this API -+// discourages it, but a protocol that uses excessive message sizes might present -+// some implementations with no other choice. -+// 3. Performance may be improved by working with messages that fit into data caches. -+// Thus large amounts of data should be chunked so that each message is small. -+// -+// This package is not interoperable with the current release of NaCl -+// (https://nacl.cr.yp.to/sign.html), which does not support Ed25519 yet. However, -+// it is compatible with the NaCl fork libsodium (https://www.libsodium.org), as well -+// as TweetNaCl (https://tweetnacl.cr.yp.to/). -+package sign -+ -+import ( -+ "io" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/internal/alias" -+) -+ -+// Overhead is the number of bytes of overhead when signing a message. -+const Overhead = 64 -+ -+// GenerateKey generates a new public/private key pair suitable for use with -+// Sign and Open. -+func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err error) { -+ pub, priv, err := ed25519.GenerateKey(rand) -+ if err != nil { -+ return nil, nil, err -+ } -+ publicKey, privateKey = new([32]byte), new([64]byte) -+ copy((*publicKey)[:], pub) -+ copy((*privateKey)[:], priv) -+ return publicKey, privateKey, nil -+} -+ -+// Sign appends a signed copy of message to out, which will be Overhead bytes -+// longer than the original and must not overlap it. -+func Sign(out, message []byte, privateKey *[64]byte) []byte { -+ sig := ed25519.Sign(ed25519.PrivateKey((*privateKey)[:]), message) -+ ret, out := sliceForAppend(out, Overhead+len(message)) -+ if alias.AnyOverlap(out, message) { -+ panic("nacl: invalid buffer overlap") -+ } -+ copy(out, sig) -+ copy(out[Overhead:], message) -+ return ret -+} -+ -+// Open verifies a signed message produced by Sign and appends the message to -+// out, which must not overlap the signed message. The output will be Overhead -+// bytes smaller than the signed message. -+func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool) { -+ if len(signedMessage) < Overhead { -+ return nil, false -+ } -+ if !ed25519.Verify(ed25519.PublicKey((*publicKey)[:]), signedMessage[Overhead:], signedMessage[:Overhead]) { -+ return nil, false -+ } -+ ret, out := sliceForAppend(out, len(signedMessage)-Overhead) -+ if alias.AnyOverlap(out, signedMessage) { -+ panic("nacl: invalid buffer overlap") -+ } -+ copy(out, signedMessage[Overhead:]) -+ return ret, true -+} -+ -+// sliceForAppend takes a slice and a requested number of bytes. It returns a -+// slice with the contents of the given slice followed by that many bytes and a -+// second slice that aliases into it and contains only the extra bytes. If the -+// original slice has sufficient capacity then no allocation is performed. -+func sliceForAppend(in []byte, n int) (head, tail []byte) { -+ if total := len(in) + n; cap(in) >= total { -+ head = in[:total] -+ } else { -+ head = make([]byte, total) -+ copy(head, in) -+ } -+ tail = head[len(in):] -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go b/ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go -new file mode 100644 -index 00000000000000..db269014c2b9a7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/nacl/sign/sign_test.go -@@ -0,0 +1,74 @@ -+// Copyright 2018 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sign -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/hex" -+ "testing" -+) -+ -+var testSignedMessage, _ = hex.DecodeString("26a0a47f733d02ddb74589b6cbd6f64a7dab1947db79395a1a9e00e4c902c0f185b119897b89b248d16bab4ea781b5a3798d25c2984aec833dddab57e0891e0d68656c6c6f20776f726c64") -+var testMessage = testSignedMessage[Overhead:] -+var testPublicKey [32]byte -+var testPrivateKey = [64]byte{ -+ 0x98, 0x3c, 0x6a, 0xa6, 0x21, 0xcc, 0xbb, 0xb2, 0xa7, 0xe8, 0x97, 0x94, 0xde, 0x5f, 0xf8, 0x11, -+ 0x8a, 0xf3, 0x33, 0x1a, 0x03, 0x5c, 0x43, 0x99, 0x03, 0x13, 0x2d, 0xd7, 0xb4, 0xc4, 0x8b, 0xb0, -+ 0xf6, 0x33, 0x20, 0xa3, 0x34, 0x8b, 0x7b, 0xe2, 0xfe, 0xb4, 0xe7, 0x3a, 0x54, 0x08, 0x2d, 0xd7, -+ 0x0c, 0xb7, 0xc0, 0xe3, 0xbf, 0x62, 0x6c, 0x55, 0xf0, 0x33, 0x28, 0x52, 0xf8, 0x48, 0x7d, 0xfd, -+} -+ -+func init() { -+ copy(testPublicKey[:], testPrivateKey[32:]) -+} -+ -+func TestSign(t *testing.T) { -+ signedMessage := Sign(nil, testMessage, &testPrivateKey) -+ if !bytes.Equal(signedMessage, testSignedMessage) { -+ t.Fatalf("signed message did not match, got\n%x\n, expected\n%x", signedMessage, testSignedMessage) -+ } -+} -+ -+func TestOpen(t *testing.T) { -+ message, ok := Open(nil, testSignedMessage, &testPublicKey) -+ if !ok { -+ t.Fatalf("valid signed message not successfully verified") -+ } -+ if !bytes.Equal(message, testMessage) { -+ t.Fatalf("message did not match, got\n%x\n, expected\n%x", message, testMessage) -+ } -+ _, ok = Open(nil, testSignedMessage[1:], &testPublicKey) -+ if ok { -+ t.Fatalf("invalid signed message successfully verified") -+ } -+ -+ badMessage := make([]byte, len(testSignedMessage)) -+ copy(badMessage, testSignedMessage) -+ badMessage[5] ^= 1 -+ if _, ok := Open(nil, badMessage, &testPublicKey); ok { -+ t.Fatalf("Open succeeded with a corrupt message") -+ } -+ -+ var badPublicKey [32]byte -+ copy(badPublicKey[:], testPublicKey[:]) -+ badPublicKey[5] ^= 1 -+ if _, ok := Open(nil, testSignedMessage, &badPublicKey); ok { -+ t.Fatalf("Open succeeded with a corrupt public key") -+ } -+} -+ -+func TestGenerateSignOpen(t *testing.T) { -+ publicKey, privateKey, _ := GenerateKey(rand.Reader) -+ signedMessage := Sign(nil, testMessage, privateKey) -+ message, ok := Open(nil, signedMessage, publicKey) -+ if !ok { -+ t.Fatalf("failed to verify signed message") -+ } -+ -+ if !bytes.Equal(message, testMessage) { -+ t.Fatalf("verified message does not match signed messge, got\n%x\n, expected\n%x", message, testMessage) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ocsp/ocsp.go b/ms_mod/golang.org/x/crypto/ocsp/ocsp.go -new file mode 100644 -index 00000000000000..4269ed113be905 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ocsp/ocsp.go -@@ -0,0 +1,792 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses -+// are signed messages attesting to the validity of a certificate for a small -+// period of time. This is used to manage revocation for X.509 certificates. -+package ocsp // import "golang.org/x/crypto/ocsp" -+ -+import ( -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ _ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "errors" -+ "fmt" -+ "math/big" -+ "strconv" -+ "time" -+) -+ -+var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) -+ -+// ResponseStatus contains the result of an OCSP request. See -+// https://tools.ietf.org/html/rfc6960#section-2.3 -+type ResponseStatus int -+ -+const ( -+ Success ResponseStatus = 0 -+ Malformed ResponseStatus = 1 -+ InternalError ResponseStatus = 2 -+ TryLater ResponseStatus = 3 -+ // Status code four is unused in OCSP. See -+ // https://tools.ietf.org/html/rfc6960#section-4.2.1 -+ SignatureRequired ResponseStatus = 5 -+ Unauthorized ResponseStatus = 6 -+) -+ -+func (r ResponseStatus) String() string { -+ switch r { -+ case Success: -+ return "success" -+ case Malformed: -+ return "malformed" -+ case InternalError: -+ return "internal error" -+ case TryLater: -+ return "try later" -+ case SignatureRequired: -+ return "signature required" -+ case Unauthorized: -+ return "unauthorized" -+ default: -+ return "unknown OCSP status: " + strconv.Itoa(int(r)) -+ } -+} -+ -+// ResponseError is an error that may be returned by ParseResponse to indicate -+// that the response itself is an error, not just that it's indicating that a -+// certificate is revoked, unknown, etc. -+type ResponseError struct { -+ Status ResponseStatus -+} -+ -+func (r ResponseError) Error() string { -+ return "ocsp: error from server: " + r.Status.String() -+} -+ -+// These are internal structures that reflect the ASN.1 structure of an OCSP -+// response. See RFC 2560, section 4.2. -+ -+type certID struct { -+ HashAlgorithm pkix.AlgorithmIdentifier -+ NameHash []byte -+ IssuerKeyHash []byte -+ SerialNumber *big.Int -+} -+ -+// https://tools.ietf.org/html/rfc2560#section-4.1.1 -+type ocspRequest struct { -+ TBSRequest tbsRequest -+} -+ -+type tbsRequest struct { -+ Version int `asn1:"explicit,tag:0,default:0,optional"` -+ RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` -+ RequestList []request -+} -+ -+type request struct { -+ Cert certID -+} -+ -+type responseASN1 struct { -+ Status asn1.Enumerated -+ Response responseBytes `asn1:"explicit,tag:0,optional"` -+} -+ -+type responseBytes struct { -+ ResponseType asn1.ObjectIdentifier -+ Response []byte -+} -+ -+type basicResponse struct { -+ TBSResponseData responseData -+ SignatureAlgorithm pkix.AlgorithmIdentifier -+ Signature asn1.BitString -+ Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` -+} -+ -+type responseData struct { -+ Raw asn1.RawContent -+ Version int `asn1:"optional,default:0,explicit,tag:0"` -+ RawResponderID asn1.RawValue -+ ProducedAt time.Time `asn1:"generalized"` -+ Responses []singleResponse -+} -+ -+type singleResponse struct { -+ CertID certID -+ Good asn1.Flag `asn1:"tag:0,optional"` -+ Revoked revokedInfo `asn1:"tag:1,optional"` -+ Unknown asn1.Flag `asn1:"tag:2,optional"` -+ ThisUpdate time.Time `asn1:"generalized"` -+ NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` -+ SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` -+} -+ -+type revokedInfo struct { -+ RevocationTime time.Time `asn1:"generalized"` -+ Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` -+} -+ -+var ( -+ oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} -+ oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} -+ oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} -+ oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} -+ oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} -+ oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} -+ oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} -+ oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} -+ oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} -+ oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} -+ oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} -+ oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} -+) -+ -+var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ -+ crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), -+ crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), -+ crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), -+ crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), -+} -+ -+// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below -+var signatureAlgorithmDetails = []struct { -+ algo x509.SignatureAlgorithm -+ oid asn1.ObjectIdentifier -+ pubKeyAlgo x509.PublicKeyAlgorithm -+ hash crypto.Hash -+}{ -+ {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, -+ {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, -+ {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, -+ {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, -+ {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, -+ {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, -+ {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, -+ {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, -+ {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, -+ {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, -+ {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, -+ {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, -+} -+ -+// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below -+func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { -+ var pubType x509.PublicKeyAlgorithm -+ -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ pubType = x509.RSA -+ hashFunc = crypto.SHA256 -+ sigAlgo.Algorithm = oidSignatureSHA256WithRSA -+ sigAlgo.Parameters = asn1.RawValue{ -+ Tag: 5, -+ } -+ -+ case *ecdsa.PublicKey: -+ pubType = x509.ECDSA -+ -+ switch pub.Curve { -+ case elliptic.P224(), elliptic.P256(): -+ hashFunc = crypto.SHA256 -+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 -+ case elliptic.P384(): -+ hashFunc = crypto.SHA384 -+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 -+ case elliptic.P521(): -+ hashFunc = crypto.SHA512 -+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 -+ default: -+ err = errors.New("x509: unknown elliptic curve") -+ } -+ -+ default: -+ err = errors.New("x509: only RSA and ECDSA keys supported") -+ } -+ -+ if err != nil { -+ return -+ } -+ -+ if requestedSigAlgo == 0 { -+ return -+ } -+ -+ found := false -+ for _, details := range signatureAlgorithmDetails { -+ if details.algo == requestedSigAlgo { -+ if details.pubKeyAlgo != pubType { -+ err = errors.New("x509: requested SignatureAlgorithm does not match private key type") -+ return -+ } -+ sigAlgo.Algorithm, hashFunc = details.oid, details.hash -+ if hashFunc == 0 { -+ err = errors.New("x509: cannot sign with hash function requested") -+ return -+ } -+ found = true -+ break -+ } -+ } -+ -+ if !found { -+ err = errors.New("x509: unknown SignatureAlgorithm") -+ } -+ -+ return -+} -+ -+// TODO(agl): this is taken from crypto/x509 and so should probably be exported -+// from crypto/x509 or crypto/x509/pkix. -+func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { -+ for _, details := range signatureAlgorithmDetails { -+ if oid.Equal(details.oid) { -+ return details.algo -+ } -+ } -+ return x509.UnknownSignatureAlgorithm -+} -+ -+// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. -+func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { -+ for hash, oid := range hashOIDs { -+ if oid.Equal(target) { -+ return hash -+ } -+ } -+ return crypto.Hash(0) -+} -+ -+func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { -+ for hash, oid := range hashOIDs { -+ if hash == target { -+ return oid -+ } -+ } -+ return nil -+} -+ -+// This is the exposed reflection of the internal OCSP structures. -+ -+// The status values that can be expressed in OCSP. See RFC 6960. -+const ( -+ // Good means that the certificate is valid. -+ Good = iota -+ // Revoked means that the certificate has been deliberately revoked. -+ Revoked -+ // Unknown means that the OCSP responder doesn't know about the certificate. -+ Unknown -+ // ServerFailed is unused and was never used (see -+ // https://go-review.googlesource.com/#/c/18944). ParseResponse will -+ // return a ResponseError when an error response is parsed. -+ ServerFailed -+) -+ -+// The enumerated reasons for revoking a certificate. See RFC 5280. -+const ( -+ Unspecified = 0 -+ KeyCompromise = 1 -+ CACompromise = 2 -+ AffiliationChanged = 3 -+ Superseded = 4 -+ CessationOfOperation = 5 -+ CertificateHold = 6 -+ -+ RemoveFromCRL = 8 -+ PrivilegeWithdrawn = 9 -+ AACompromise = 10 -+) -+ -+// Request represents an OCSP request. See RFC 6960. -+type Request struct { -+ HashAlgorithm crypto.Hash -+ IssuerNameHash []byte -+ IssuerKeyHash []byte -+ SerialNumber *big.Int -+} -+ -+// Marshal marshals the OCSP request to ASN.1 DER encoded form. -+func (req *Request) Marshal() ([]byte, error) { -+ hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm) -+ if hashAlg == nil { -+ return nil, errors.New("Unknown hash algorithm") -+ } -+ return asn1.Marshal(ocspRequest{ -+ tbsRequest{ -+ Version: 0, -+ RequestList: []request{ -+ { -+ Cert: certID{ -+ pkix.AlgorithmIdentifier{ -+ Algorithm: hashAlg, -+ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, -+ }, -+ req.IssuerNameHash, -+ req.IssuerKeyHash, -+ req.SerialNumber, -+ }, -+ }, -+ }, -+ }, -+ }) -+} -+ -+// Response represents an OCSP response containing a single SingleResponse. See -+// RFC 6960. -+type Response struct { -+ Raw []byte -+ -+ // Status is one of {Good, Revoked, Unknown} -+ Status int -+ SerialNumber *big.Int -+ ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time -+ RevocationReason int -+ Certificate *x509.Certificate -+ // TBSResponseData contains the raw bytes of the signed response. If -+ // Certificate is nil then this can be used to verify Signature. -+ TBSResponseData []byte -+ Signature []byte -+ SignatureAlgorithm x509.SignatureAlgorithm -+ -+ // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash. -+ // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512. -+ // If zero, the default is crypto.SHA1. -+ IssuerHash crypto.Hash -+ -+ // RawResponderName optionally contains the DER-encoded subject of the -+ // responder certificate. Exactly one of RawResponderName and -+ // ResponderKeyHash is set. -+ RawResponderName []byte -+ // ResponderKeyHash optionally contains the SHA-1 hash of the -+ // responder's public key. Exactly one of RawResponderName and -+ // ResponderKeyHash is set. -+ ResponderKeyHash []byte -+ -+ // Extensions contains raw X.509 extensions from the singleExtensions field -+ // of the OCSP response. When parsing certificates, this can be used to -+ // extract non-critical extensions that are not parsed by this package. When -+ // marshaling OCSP responses, the Extensions field is ignored, see -+ // ExtraExtensions. -+ Extensions []pkix.Extension -+ -+ // ExtraExtensions contains extensions to be copied, raw, into any marshaled -+ // OCSP response (in the singleExtensions field). Values override any -+ // extensions that would otherwise be produced based on the other fields. The -+ // ExtraExtensions field is not populated when parsing certificates, see -+ // Extensions. -+ ExtraExtensions []pkix.Extension -+} -+ -+// These are pre-serialized error responses for the various non-success codes -+// defined by OCSP. The Unauthorized code in particular can be used by an OCSP -+// responder that supports only pre-signed responses as a response to requests -+// for certificates with unknown status. See RFC 5019. -+var ( -+ MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} -+ InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} -+ TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} -+ SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} -+ UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} -+) -+ -+// CheckSignatureFrom checks that the signature in resp is a valid signature -+// from issuer. This should only be used if resp.Certificate is nil. Otherwise, -+// the OCSP response contained an intermediate certificate that created the -+// signature. That signature is checked by ParseResponse and only -+// resp.Certificate remains to be validated. -+func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { -+ return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) -+} -+ -+// ParseError results from an invalid OCSP response. -+type ParseError string -+ -+func (p ParseError) Error() string { -+ return string(p) -+} -+ -+// ParseRequest parses an OCSP request in DER form. It only supports -+// requests for a single certificate. Signed requests are not supported. -+// If a request includes a signature, it will result in a ParseError. -+func ParseRequest(bytes []byte) (*Request, error) { -+ var req ocspRequest -+ rest, err := asn1.Unmarshal(bytes, &req) -+ if err != nil { -+ return nil, err -+ } -+ if len(rest) > 0 { -+ return nil, ParseError("trailing data in OCSP request") -+ } -+ -+ if len(req.TBSRequest.RequestList) == 0 { -+ return nil, ParseError("OCSP request contains no request body") -+ } -+ innerRequest := req.TBSRequest.RequestList[0] -+ -+ hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) -+ if hashFunc == crypto.Hash(0) { -+ return nil, ParseError("OCSP request uses unknown hash function") -+ } -+ -+ return &Request{ -+ HashAlgorithm: hashFunc, -+ IssuerNameHash: innerRequest.Cert.NameHash, -+ IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, -+ SerialNumber: innerRequest.Cert.SerialNumber, -+ }, nil -+} -+ -+// ParseResponse parses an OCSP response in DER form. The response must contain -+// only one certificate status. To parse the status of a specific certificate -+// from a response which may contain multiple statuses, use ParseResponseForCert -+// instead. -+// -+// If the response contains an embedded certificate, then that certificate will -+// be used to verify the response signature. If the response contains an -+// embedded certificate and issuer is not nil, then issuer will be used to verify -+// the signature on the embedded certificate. -+// -+// If the response does not contain an embedded certificate and issuer is not -+// nil, then issuer will be used to verify the response signature. -+// -+// Invalid responses and parse failures will result in a ParseError. -+// Error responses will result in a ResponseError. -+func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { -+ return ParseResponseForCert(bytes, nil, issuer) -+} -+ -+// ParseResponseForCert acts identically to ParseResponse, except it supports -+// parsing responses that contain multiple statuses. If the response contains -+// multiple statuses and cert is not nil, then ParseResponseForCert will return -+// the first status which contains a matching serial, otherwise it will return an -+// error. If cert is nil, then the first status in the response will be returned. -+func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { -+ var resp responseASN1 -+ rest, err := asn1.Unmarshal(bytes, &resp) -+ if err != nil { -+ return nil, err -+ } -+ if len(rest) > 0 { -+ return nil, ParseError("trailing data in OCSP response") -+ } -+ -+ if status := ResponseStatus(resp.Status); status != Success { -+ return nil, ResponseError{status} -+ } -+ -+ if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { -+ return nil, ParseError("bad OCSP response type") -+ } -+ -+ var basicResp basicResponse -+ rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) -+ if err != nil { -+ return nil, err -+ } -+ if len(rest) > 0 { -+ return nil, ParseError("trailing data in OCSP response") -+ } -+ -+ if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { -+ return nil, ParseError("OCSP response contains bad number of responses") -+ } -+ -+ var singleResp singleResponse -+ if cert == nil { -+ singleResp = basicResp.TBSResponseData.Responses[0] -+ } else { -+ match := false -+ for _, resp := range basicResp.TBSResponseData.Responses { -+ if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 { -+ singleResp = resp -+ match = true -+ break -+ } -+ } -+ if !match { -+ return nil, ParseError("no response matching the supplied certificate") -+ } -+ } -+ -+ ret := &Response{ -+ Raw: bytes, -+ TBSResponseData: basicResp.TBSResponseData.Raw, -+ Signature: basicResp.Signature.RightAlign(), -+ SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), -+ Extensions: singleResp.SingleExtensions, -+ SerialNumber: singleResp.CertID.SerialNumber, -+ ProducedAt: basicResp.TBSResponseData.ProducedAt, -+ ThisUpdate: singleResp.ThisUpdate, -+ NextUpdate: singleResp.NextUpdate, -+ } -+ -+ // Handle the ResponderID CHOICE tag. ResponderID can be flattened into -+ // TBSResponseData once https://go-review.googlesource.com/34503 has been -+ // released. -+ rawResponderID := basicResp.TBSResponseData.RawResponderID -+ switch rawResponderID.Tag { -+ case 1: // Name -+ var rdn pkix.RDNSequence -+ if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 { -+ return nil, ParseError("invalid responder name") -+ } -+ ret.RawResponderName = rawResponderID.Bytes -+ case 2: // KeyHash -+ if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 { -+ return nil, ParseError("invalid responder key hash") -+ } -+ default: -+ return nil, ParseError("invalid responder id tag") -+ } -+ -+ if len(basicResp.Certificates) > 0 { -+ // Responders should only send a single certificate (if they -+ // send any) that connects the responder's certificate to the -+ // original issuer. We accept responses with multiple -+ // certificates due to a number responders sending them[1], but -+ // ignore all but the first. -+ // -+ // [1] https://github.com/golang/go/issues/21527 -+ ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { -+ return nil, ParseError("bad signature on embedded certificate: " + err.Error()) -+ } -+ -+ if issuer != nil { -+ if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { -+ return nil, ParseError("bad OCSP signature: " + err.Error()) -+ } -+ } -+ } else if issuer != nil { -+ if err := ret.CheckSignatureFrom(issuer); err != nil { -+ return nil, ParseError("bad OCSP signature: " + err.Error()) -+ } -+ } -+ -+ for _, ext := range singleResp.SingleExtensions { -+ if ext.Critical { -+ return nil, ParseError("unsupported critical extension") -+ } -+ } -+ -+ for h, oid := range hashOIDs { -+ if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) { -+ ret.IssuerHash = h -+ break -+ } -+ } -+ if ret.IssuerHash == 0 { -+ return nil, ParseError("unsupported issuer hash algorithm") -+ } -+ -+ switch { -+ case bool(singleResp.Good): -+ ret.Status = Good -+ case bool(singleResp.Unknown): -+ ret.Status = Unknown -+ default: -+ ret.Status = Revoked -+ ret.RevokedAt = singleResp.Revoked.RevocationTime -+ ret.RevocationReason = int(singleResp.Revoked.Reason) -+ } -+ -+ return ret, nil -+} -+ -+// RequestOptions contains options for constructing OCSP requests. -+type RequestOptions struct { -+ // Hash contains the hash function that should be used when -+ // constructing the OCSP request. If zero, SHA-1 will be used. -+ Hash crypto.Hash -+} -+ -+func (opts *RequestOptions) hash() crypto.Hash { -+ if opts == nil || opts.Hash == 0 { -+ // SHA-1 is nearly universally used in OCSP. -+ return crypto.SHA1 -+ } -+ return opts.Hash -+} -+ -+// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If -+// opts is nil then sensible defaults are used. -+func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { -+ hashFunc := opts.hash() -+ -+ // OCSP seems to be the only place where these raw hash identifiers are -+ // used. I took the following from -+ // http://msdn.microsoft.com/en-us/library/ff635603.aspx -+ _, ok := hashOIDs[hashFunc] -+ if !ok { -+ return nil, x509.ErrUnsupportedAlgorithm -+ } -+ -+ if !hashFunc.Available() { -+ return nil, x509.ErrUnsupportedAlgorithm -+ } -+ h := opts.hash().New() -+ -+ var publicKeyInfo struct { -+ Algorithm pkix.AlgorithmIdentifier -+ PublicKey asn1.BitString -+ } -+ if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { -+ return nil, err -+ } -+ -+ h.Write(publicKeyInfo.PublicKey.RightAlign()) -+ issuerKeyHash := h.Sum(nil) -+ -+ h.Reset() -+ h.Write(issuer.RawSubject) -+ issuerNameHash := h.Sum(nil) -+ -+ req := &Request{ -+ HashAlgorithm: hashFunc, -+ IssuerNameHash: issuerNameHash, -+ IssuerKeyHash: issuerKeyHash, -+ SerialNumber: cert.SerialNumber, -+ } -+ return req.Marshal() -+} -+ -+// CreateResponse returns a DER-encoded OCSP response with the specified contents. -+// The fields in the response are populated as follows: -+// -+// The responder cert is used to populate the responder's name field, and the -+// certificate itself is provided alongside the OCSP response signature. -+// -+// The issuer cert is used to populate the IssuerNameHash and IssuerKeyHash fields. -+// -+// The template is used to populate the SerialNumber, Status, RevokedAt, -+// RevocationReason, ThisUpdate, and NextUpdate fields. -+// -+// If template.IssuerHash is not set, SHA1 will be used. -+// -+// The ProducedAt date is automatically set to the current date, to the nearest minute. -+func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { -+ var publicKeyInfo struct { -+ Algorithm pkix.AlgorithmIdentifier -+ PublicKey asn1.BitString -+ } -+ if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { -+ return nil, err -+ } -+ -+ if template.IssuerHash == 0 { -+ template.IssuerHash = crypto.SHA1 -+ } -+ hashOID := getOIDFromHashAlgorithm(template.IssuerHash) -+ if hashOID == nil { -+ return nil, errors.New("unsupported issuer hash algorithm") -+ } -+ -+ if !template.IssuerHash.Available() { -+ return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash) -+ } -+ h := template.IssuerHash.New() -+ h.Write(publicKeyInfo.PublicKey.RightAlign()) -+ issuerKeyHash := h.Sum(nil) -+ -+ h.Reset() -+ h.Write(issuer.RawSubject) -+ issuerNameHash := h.Sum(nil) -+ -+ innerResponse := singleResponse{ -+ CertID: certID{ -+ HashAlgorithm: pkix.AlgorithmIdentifier{ -+ Algorithm: hashOID, -+ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, -+ }, -+ NameHash: issuerNameHash, -+ IssuerKeyHash: issuerKeyHash, -+ SerialNumber: template.SerialNumber, -+ }, -+ ThisUpdate: template.ThisUpdate.UTC(), -+ NextUpdate: template.NextUpdate.UTC(), -+ SingleExtensions: template.ExtraExtensions, -+ } -+ -+ switch template.Status { -+ case Good: -+ innerResponse.Good = true -+ case Unknown: -+ innerResponse.Unknown = true -+ case Revoked: -+ innerResponse.Revoked = revokedInfo{ -+ RevocationTime: template.RevokedAt.UTC(), -+ Reason: asn1.Enumerated(template.RevocationReason), -+ } -+ } -+ -+ rawResponderID := asn1.RawValue{ -+ Class: 2, // context-specific -+ Tag: 1, // Name (explicit tag) -+ IsCompound: true, -+ Bytes: responderCert.RawSubject, -+ } -+ tbsResponseData := responseData{ -+ Version: 0, -+ RawResponderID: rawResponderID, -+ ProducedAt: time.Now().Truncate(time.Minute).UTC(), -+ Responses: []singleResponse{innerResponse}, -+ } -+ -+ tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) -+ if err != nil { -+ return nil, err -+ } -+ -+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) -+ if err != nil { -+ return nil, err -+ } -+ -+ responseHash := hashFunc.New() -+ responseHash.Write(tbsResponseDataDER) -+ signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) -+ if err != nil { -+ return nil, err -+ } -+ -+ response := basicResponse{ -+ TBSResponseData: tbsResponseData, -+ SignatureAlgorithm: signatureAlgorithm, -+ Signature: asn1.BitString{ -+ Bytes: signature, -+ BitLength: 8 * len(signature), -+ }, -+ } -+ if template.Certificate != nil { -+ response.Certificates = []asn1.RawValue{ -+ {FullBytes: template.Certificate.Raw}, -+ } -+ } -+ responseDER, err := asn1.Marshal(response) -+ if err != nil { -+ return nil, err -+ } -+ -+ return asn1.Marshal(responseASN1{ -+ Status: asn1.Enumerated(Success), -+ Response: responseBytes{ -+ ResponseType: idPKIXOCSPBasic, -+ Response: responseDER, -+ }, -+ }) -+} -diff --git a/ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go b/ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go -new file mode 100644 -index 00000000000000..0bc194b2f4ab84 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ocsp/ocsp_test.go -@@ -0,0 +1,746 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.7 -+// +build go1.7 -+ -+package ocsp -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/sha1" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/hex" -+ "encoding/pem" -+ "math/big" -+ "reflect" -+ "testing" -+ "time" -+) -+ -+func TestOCSPDecode(t *testing.T) { -+ responseBytes, _ := hex.DecodeString(ocspResponseHex) -+ resp, err := ParseResponse(responseBytes, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // keyHash is the SKID of the issuer of the certificate the OCSP -+ // response is for. -+ keyHash, err := hex.DecodeString("8a747faf85cdee95cd3d9cd0e24614f371351d27") -+ if err != nil { -+ t.Fatal(err) -+ } -+ // serialBytes is the serial number of the certificate the OCSP -+ // response is for. -+ serialBytes, err := hex.DecodeString("f374542e3c7a68360a00000001103462") -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ expected := Response{ -+ Status: Good, -+ SerialNumber: big.NewInt(0).SetBytes(serialBytes), -+ RevocationReason: Unspecified, -+ ThisUpdate: time.Date(2021, 11, 7, 14, 25, 51, 0, time.UTC), -+ NextUpdate: time.Date(2021, 11, 14, 13, 25, 50, 0, time.UTC), -+ ResponderKeyHash: keyHash, -+ } -+ -+ if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) { -+ t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, expected.ThisUpdate) -+ } -+ -+ if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) { -+ t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, expected.NextUpdate) -+ } -+ -+ if resp.Status != expected.Status { -+ t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status) -+ } -+ -+ if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 { -+ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber) -+ } -+ -+ if resp.RevocationReason != expected.RevocationReason { -+ t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason) -+ } -+ -+ if !bytes.Equal(resp.RawResponderName, expected.RawResponderName) { -+ t.Errorf("resp.RawResponderName: got %x, want %x", resp.RawResponderName, expected.RawResponderName) -+ } -+ -+ if !bytes.Equal(resp.ResponderKeyHash, expected.ResponderKeyHash) { -+ t.Errorf("resp.ResponderKeyHash: got %x, want %x", resp.ResponderKeyHash, expected.ResponderKeyHash) -+ } -+} -+ -+func TestOCSPDecodeWithoutCert(t *testing.T) { -+ responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex) -+ _, err := ParseResponse(responseBytes, nil) -+ if err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestOCSPDecodeWithExtensions(t *testing.T) { -+ responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex) -+ _, err := ParseResponse(responseBytes, nil) -+ if err == nil { -+ t.Error(err) -+ } -+ -+ responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex) -+ response, err := ParseResponse(responseBytes, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if len(response.Extensions) != 1 { -+ t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1) -+ } -+ -+ extensionBytes := response.Extensions[0].Value -+ expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex) -+ if !bytes.Equal(extensionBytes, expectedBytes) { -+ t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes) -+ } -+} -+ -+func TestOCSPSignature(t *testing.T) { -+ b, _ := pem.Decode([]byte(GTSRoot)) -+ issuer, err := x509.ParseCertificate(b.Bytes) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ response, _ := hex.DecodeString(ocspResponseHex) -+ if _, err := ParseResponse(response, issuer); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestOCSPRequest(t *testing.T) { -+ leafCert, _ := hex.DecodeString(leafCertHex) -+ cert, err := x509.ParseCertificate(leafCert) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ issuerCert, _ := hex.DecodeString(issuerCertHex) -+ issuer, err := x509.ParseCertificate(issuerCert) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ request, err := CreateRequest(cert, issuer, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ expectedBytes, _ := hex.DecodeString(ocspRequestHex) -+ if !bytes.Equal(request, expectedBytes) { -+ t.Errorf("request: got %x, wanted %x", request, expectedBytes) -+ } -+ -+ decodedRequest, err := ParseRequest(expectedBytes) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if decodedRequest.HashAlgorithm != crypto.SHA1 { -+ t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1) -+ } -+ -+ var publicKeyInfo struct { -+ Algorithm pkix.AlgorithmIdentifier -+ PublicKey asn1.BitString -+ } -+ _, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ h := sha1.New() -+ h.Write(publicKeyInfo.PublicKey.RightAlign()) -+ issuerKeyHash := h.Sum(nil) -+ -+ h.Reset() -+ h.Write(issuer.RawSubject) -+ issuerNameHash := h.Sum(nil) -+ -+ if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) { -+ t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash) -+ } -+ -+ if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) { -+ t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash) -+ } -+ -+ if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 { -+ t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber) -+ } -+ -+ marshaledRequest, err := decodedRequest.Marshal() -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if bytes.Compare(expectedBytes, marshaledRequest) != 0 { -+ t.Errorf( -+ "Marshaled request doesn't match expected: wanted %x, got %x", -+ expectedBytes, -+ marshaledRequest, -+ ) -+ } -+} -+ -+func TestOCSPResponse(t *testing.T) { -+ leafCert, _ := hex.DecodeString(leafCertHex) -+ leaf, err := x509.ParseCertificate(leafCert) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ issuerCert, _ := hex.DecodeString(issuerCertHex) -+ issuer, err := x509.ParseCertificate(issuerCert) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ responderCert, _ := hex.DecodeString(responderCertHex) -+ responder, err := x509.ParseCertificate(responderCert) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex) -+ responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex) -+ extensions := []pkix.Extension{ -+ { -+ Id: ocspExtensionOID, -+ Critical: false, -+ Value: extensionBytes, -+ }, -+ } -+ -+ thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC) -+ nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC) -+ template := Response{ -+ Status: Revoked, -+ SerialNumber: leaf.SerialNumber, -+ ThisUpdate: thisUpdate, -+ NextUpdate: nextUpdate, -+ RevokedAt: thisUpdate, -+ RevocationReason: KeyCompromise, -+ Certificate: responder, -+ ExtraExtensions: extensions, -+ } -+ -+ template.IssuerHash = crypto.MD5 -+ _, err = CreateResponse(issuer, responder, template, responderPrivateKey) -+ if err == nil { -+ t.Fatal("CreateResponse didn't fail with non-valid template.IssuerHash value crypto.MD5") -+ } -+ -+ testCases := []struct { -+ name string -+ issuerHash crypto.Hash -+ }{ -+ {"Zero value", 0}, -+ {"crypto.SHA1", crypto.SHA1}, -+ {"crypto.SHA256", crypto.SHA256}, -+ {"crypto.SHA384", crypto.SHA384}, -+ {"crypto.SHA512", crypto.SHA512}, -+ } -+ for _, tc := range testCases { -+ t.Run(tc.name, func(t *testing.T) { -+ template.IssuerHash = tc.issuerHash -+ responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey) -+ if err != nil { -+ t.Fatalf("CreateResponse failed: %s", err) -+ } -+ -+ resp, err := ParseResponse(responseBytes, nil) -+ if err != nil { -+ t.Fatalf("ParseResponse failed: %s", err) -+ } -+ -+ if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) { -+ t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, template.ThisUpdate) -+ } -+ -+ if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) { -+ t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, template.NextUpdate) -+ } -+ -+ if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) { -+ t.Errorf("resp.RevokedAt: got %v, want %v", resp.RevokedAt, template.RevokedAt) -+ } -+ -+ if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) { -+ t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions) -+ } -+ -+ delay := time.Since(resp.ProducedAt) -+ if delay < -time.Hour || delay > time.Hour { -+ t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now()) -+ } -+ -+ if resp.Status != template.Status { -+ t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status) -+ } -+ -+ if resp.SerialNumber.Cmp(template.SerialNumber) != 0 { -+ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber) -+ } -+ -+ if resp.RevocationReason != template.RevocationReason { -+ t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason) -+ } -+ -+ expectedHash := tc.issuerHash -+ if tc.issuerHash == 0 { -+ expectedHash = crypto.SHA1 -+ } -+ -+ if resp.IssuerHash != expectedHash { -+ t.Errorf("resp.IssuerHash: got %d, want %d", resp.IssuerHash, expectedHash) -+ } -+ }) -+ } -+} -+ -+func TestErrorResponse(t *testing.T) { -+ responseBytes, _ := hex.DecodeString(errorResponseHex) -+ _, err := ParseResponse(responseBytes, nil) -+ -+ respErr, ok := err.(ResponseError) -+ if !ok { -+ t.Fatalf("expected ResponseError from ParseResponse but got %#v", err) -+ } -+ if respErr.Status != Malformed { -+ t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status) -+ } -+} -+ -+func createMultiResp() ([]byte, error) { -+ rawResponderID := asn1.RawValue{ -+ Class: 2, // context-specific -+ Tag: 1, // Name (explicit tag) -+ IsCompound: true, -+ Bytes: []byte{48, 0}, -+ } -+ tbsResponseData := responseData{ -+ Version: 0, -+ RawResponderID: rawResponderID, -+ ProducedAt: time.Now().Truncate(time.Minute).UTC(), -+ } -+ this := time.Now() -+ next := this.Add(time.Hour * 24 * 4) -+ for i := int64(0); i < 5; i++ { -+ tbsResponseData.Responses = append(tbsResponseData.Responses, singleResponse{ -+ CertID: certID{ -+ HashAlgorithm: pkix.AlgorithmIdentifier{ -+ Algorithm: hashOIDs[crypto.SHA1], -+ Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, -+ }, -+ NameHash: []byte{1, 2, 3}, -+ IssuerKeyHash: []byte{4, 5, 6}, -+ SerialNumber: big.NewInt(i), -+ }, -+ ThisUpdate: this.UTC(), -+ NextUpdate: next.UTC(), -+ Good: true, -+ }) -+ } -+ -+ tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) -+ if err != nil { -+ return nil, err -+ } -+ -+ k, err := rsa.GenerateKey(rand.Reader, 1024) -+ if err != nil { -+ return nil, err -+ } -+ -+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(k.Public(), x509.SHA1WithRSA) -+ if err != nil { -+ return nil, err -+ } -+ -+ responseHash := hashFunc.New() -+ responseHash.Write(tbsResponseDataDER) -+ signature, err := k.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) -+ if err != nil { -+ return nil, err -+ } -+ -+ response := basicResponse{ -+ TBSResponseData: tbsResponseData, -+ SignatureAlgorithm: signatureAlgorithm, -+ Signature: asn1.BitString{ -+ Bytes: signature, -+ BitLength: 8 * len(signature), -+ }, -+ } -+ responseDER, err := asn1.Marshal(response) -+ if err != nil { -+ return nil, err -+ } -+ -+ return asn1.Marshal(responseASN1{ -+ Status: asn1.Enumerated(Success), -+ Response: responseBytes{ -+ ResponseType: idPKIXOCSPBasic, -+ Response: responseDER, -+ }, -+ }) -+} -+ -+func TestOCSPDecodeMultiResponse(t *testing.T) { -+ respBytes, err := createMultiResp() -+ if err != nil { -+ t.Fatal(err) -+ } -+ matchingCert := &x509.Certificate{SerialNumber: big.NewInt(3)} -+ resp, err := ParseResponseForCert(respBytes, matchingCert, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if resp.SerialNumber.Cmp(matchingCert.SerialNumber) != 0 { -+ t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, 3) -+ } -+} -+ -+func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) { -+ respBytes, err := createMultiResp() -+ if err != nil { -+ t.Fatal(err) -+ } -+ _, err = ParseResponseForCert(respBytes, &x509.Certificate{SerialNumber: big.NewInt(100)}, nil) -+ want := ParseError("no response matching the supplied certificate") -+ if err != want { -+ t.Errorf("err: got %q, want %q", err, want) -+ } -+} -+ -+// This OCSP response was taken from GTS's public OCSP responder. -+// To recreate: -+// $ openssl s_client -tls1 -showcerts -servername golang.org -connect golang.org:443 -+// Copy and paste the first certificate into /tmp/cert.crt and the second into -+// /tmp/intermediate.crt -+// Note: depending on what version of openssl you are using, you may need to use the key=value -+// form for the header argument (i.e. -header host=ocsp.pki.goog) -+// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.pki.goog/gts1c3 -header host ocsp.pki.goog -resp_text -respout /tmp/ocsp.der -+// Then hex encode the result: -+// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")' -+ -+const ocspResponseHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba308201b630819fa21604148a747faf85cdee95cd3d9cd0e24614f371351d27180f32303231313130373134323535335a30743072304a300906052b0e03021a05000414c72e798addff6134b3baed4742b8bbc6c024076304148a747faf85cdee95cd3d9cd0e24614f371351d27021100f374542e3c7a68360a000000011034628000180f32303231313130373134323535315aa011180f32303231313131343133323535305a300d06092a864886f70d01010b0500038201010087749296e681abe36f2efef047730178ce57e948426959ac62ac5f25b9a63ba3b7f31b9f683aea384d21845c8dda09498f2531c78f3add3969ca4092f31f58ac3c2613719d63b7b9a5260e52814c827f8dd44f4f753b2528bcd03ccec02cdcd4918247f5323f8cfc12cee4ac8f0361587b267019cfd12336db09b04eac59807a480213cfcd9913a3aa2d13a6c88c0a750475a0e991806d94ec0fc9dab599171a43a08e6d935b4a4a13dff9c4a97ad46cef6fb4d61cb2363d788c12d81cce851b478889c2e05d80cd00ae346772a1e7502f011e2ed9be8ef4b194c8b65d6e33671d878cfb30267972075b062ff3d56b51984bf685161afc6e2538dd6e6a23063c" -+ -+const GTSRoot = `-----BEGIN CERTIFICATE----- -+MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw -+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw -+MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -+Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD -+ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp -+kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX -+lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm -+BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA -+gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL -+tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud -+DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T -+AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD -+VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG -+CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw -+AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt -+MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG -+A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br -+aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN -+AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ -+cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL -+RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U -++o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr -+PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER -+lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs -+Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO -+z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG -+AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw -+juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl -+1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd -+-----END CERTIFICATE-----` -+ -+const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + -+ "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + -+ "3029060355040b1322536563757265204469676974616c20436572746966696361746520" + -+ "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" + -+ "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" + -+ "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" + -+ "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" + -+ "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" + -+ "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" + -+ "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" + -+ "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" + -+ "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" + -+ "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" + -+ "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" + -+ "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" + -+ "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" + -+ "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" + -+ "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" + -+ "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" + -+ "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" + -+ "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" + -+ "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" + -+ "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" + -+ "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" + -+ "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" + -+ "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" + -+ "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" + -+ "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" + -+ "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" + -+ "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" + -+ "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" + -+ "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" + -+ "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" + -+ "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" + -+ "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" + -+ "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" + -+ "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" + -+ "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" + -+ "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" + -+ "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" + -+ "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" + -+ "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" + -+ "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" + -+ "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" + -+ "d2ae83a7a8ce5ba7" -+ -+const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" + -+ "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" + -+ "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" + -+ "456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" + -+ "1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" + -+ "5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" + -+ "82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" + -+ "5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" + -+ "8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" + -+ "6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" + -+ "0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" + -+ "9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" + -+ "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" + -+ "5a35fca2e054dfa8" -+ -+// PKIX nonce extension -+var ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2} -+var ocspExtensionValueHex = "0403000000" -+ -+const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" + -+ "dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + -+ "0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" + -+ "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + -+ "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + -+ "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + -+ "3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" + -+ "03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" + -+ "911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" + -+ "5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" + -+ "e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" + -+ "b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" + -+ "eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" + -+ "a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" + -+ "28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" + -+ "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + -+ "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + -+ "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + -+ "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + -+ "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + -+ "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + -+ "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + -+ "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + -+ "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + -+ "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + -+ "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + -+ "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + -+ "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + -+ "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + -+ "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + -+ "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + -+ "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + -+ "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + -+ "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + -+ "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + -+ "3a25439a94299a65a709756c7a3e568be049d5c38839" -+ -+const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" + -+ "d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + -+ "0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" + -+ "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + -+ "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + -+ "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + -+ "3130303730373138333531375aa1163014301206092b0601050507300102040504030000" + -+ "00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" + -+ "9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" + -+ "779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" + -+ "9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" + -+ "d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" + -+ "b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" + -+ "7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" + -+ "f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" + -+ "e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" + -+ "550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" + -+ "170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" + -+ "706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" + -+ "010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" + -+ "56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" + -+ "70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" + -+ "a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" + -+ "3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" + -+ "04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" + -+ "9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" + -+ "920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" + -+ "551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" + -+ "864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" + -+ "d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" + -+ "aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" + -+ "2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" + -+ "e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" + -+ "d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" + -+ "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" + -+ "9a94299a65a709756c7a3e568be049d5c38839" -+ -+const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + -+ "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + -+ "bcbb235d44ccc7dba62e72" -+ -+const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" + -+ "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" + -+ "7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" + -+ "333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" + -+ "766572204341202d20436c617373203331493047060355040b13407777772e7665726973" + -+ "69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" + -+ "204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" + -+ "170d3133313233313233353935395a3068310b3009060355040613025553311330110603" + -+ "550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" + -+ "173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" + -+ "2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" + -+ "818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" + -+ "23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" + -+ "5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" + -+ "c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" + -+ "82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" + -+ "01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" + -+ "7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" + -+ "2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" + -+ "726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" + -+ "03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" + -+ "30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" + -+ "20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" + -+ "092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" + -+ "81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" + -+ "67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" + -+ "9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817" -+ -+const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" + -+ "864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" + -+ "566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" + -+ "6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" + -+ "1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" + -+ "301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" + -+ "0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" + -+ "69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" + -+ "3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" + -+ "6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" + -+ "5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" + -+ "e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" + -+ "bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" + -+ "3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" + -+ "f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" + -+ "0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" + -+ "2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" + -+ "636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" + -+ "030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" + -+ "0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" + -+ "a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" + -+ "300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" + -+ "adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" + -+ "f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" + -+ "e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" + -+ "d68071" -+ -+// Key and certificate for the OCSP responder were not taken from the Thawte -+// responder, since CreateResponse requires that we have the private key. -+// Instead, they were generated randomly. -+const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" + -+ "1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" + -+ "1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" + -+ "fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" + -+ "c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" + -+ "7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" + -+ "1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" + -+ "6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" + -+ "72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" + -+ "56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" + -+ "575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" + -+ "679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" + -+ "05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" + -+ "5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" + -+ "1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" + -+ "ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" + -+ "daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" + -+ "e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" + -+ "07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" + -+ "87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" + -+ "327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" + -+ "497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" + -+ "6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" + -+ "4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" + -+ "7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" + -+ "0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" + -+ "d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" + -+ "c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" + -+ "c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" + -+ "0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" + -+ "120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" + -+ "45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" + -+ "48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" + -+ "6bdaa059" -+ -+const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + -+ "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + -+ "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + -+ "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + -+ "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + -+ "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + -+ "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + -+ "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + -+ "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + -+ "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + -+ "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + -+ "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + -+ "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + -+ "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + -+ "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + -+ "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + -+ "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + -+ "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + -+ "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + -+ "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + -+ "3a25439a94299a65a709756c7a3e568be049d5c38839" -+ -+const errorResponseHex = "30030a0101" -diff --git a/ms_mod/golang.org/x/crypto/openpgp/armor/armor.go b/ms_mod/golang.org/x/crypto/openpgp/armor/armor.go -new file mode 100644 -index 00000000000000..8907183ec0ab9c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/armor/armor.go -@@ -0,0 +1,232 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is -+// very similar to PEM except that it has an additional CRC checksum. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package armor // import "golang.org/x/crypto/openpgp/armor" -+ -+import ( -+ "bufio" -+ "bytes" -+ "encoding/base64" -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+) -+ -+// A Block represents an OpenPGP armored structure. -+// -+// The encoded form is: -+// -+// -----BEGIN Type----- -+// Headers -+// -+// base64-encoded Bytes -+// '=' base64 encoded checksum -+// -----END Type----- -+// -+// where Headers is a possibly empty sequence of Key: Value lines. -+// -+// Since the armored data can be very large, this package presents a streaming -+// interface. -+type Block struct { -+ Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). -+ Header map[string]string // Optional headers. -+ Body io.Reader // A Reader from which the contents can be read -+ lReader lineReader -+ oReader openpgpReader -+} -+ -+var ArmorCorrupt error = errors.StructuralError("armor invalid") -+ -+const crc24Init = 0xb704ce -+const crc24Poly = 0x1864cfb -+const crc24Mask = 0xffffff -+ -+// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 -+func crc24(crc uint32, d []byte) uint32 { -+ for _, b := range d { -+ crc ^= uint32(b) << 16 -+ for i := 0; i < 8; i++ { -+ crc <<= 1 -+ if crc&0x1000000 != 0 { -+ crc ^= crc24Poly -+ } -+ } -+ } -+ return crc -+} -+ -+var armorStart = []byte("-----BEGIN ") -+var armorEnd = []byte("-----END ") -+var armorEndOfLine = []byte("-----") -+ -+// lineReader wraps a line based reader. It watches for the end of an armor -+// block and records the expected CRC value. -+type lineReader struct { -+ in *bufio.Reader -+ buf []byte -+ eof bool -+ crc uint32 -+ crcSet bool -+} -+ -+func (l *lineReader) Read(p []byte) (n int, err error) { -+ if l.eof { -+ return 0, io.EOF -+ } -+ -+ if len(l.buf) > 0 { -+ n = copy(p, l.buf) -+ l.buf = l.buf[n:] -+ return -+ } -+ -+ line, isPrefix, err := l.in.ReadLine() -+ if err != nil { -+ return -+ } -+ if isPrefix { -+ return 0, ArmorCorrupt -+ } -+ -+ if bytes.HasPrefix(line, armorEnd) { -+ l.eof = true -+ return 0, io.EOF -+ } -+ -+ if len(line) == 5 && line[0] == '=' { -+ // This is the checksum line -+ var expectedBytes [3]byte -+ var m int -+ m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) -+ if m != 3 || err != nil { -+ return -+ } -+ l.crc = uint32(expectedBytes[0])<<16 | -+ uint32(expectedBytes[1])<<8 | -+ uint32(expectedBytes[2]) -+ -+ line, _, err = l.in.ReadLine() -+ if err != nil && err != io.EOF { -+ return -+ } -+ if !bytes.HasPrefix(line, armorEnd) { -+ return 0, ArmorCorrupt -+ } -+ -+ l.eof = true -+ l.crcSet = true -+ return 0, io.EOF -+ } -+ -+ if len(line) > 96 { -+ return 0, ArmorCorrupt -+ } -+ -+ n = copy(p, line) -+ bytesToSave := len(line) - n -+ if bytesToSave > 0 { -+ if cap(l.buf) < bytesToSave { -+ l.buf = make([]byte, 0, bytesToSave) -+ } -+ l.buf = l.buf[0:bytesToSave] -+ copy(l.buf, line[n:]) -+ } -+ -+ return -+} -+ -+// openpgpReader passes Read calls to the underlying base64 decoder, but keeps -+// a running CRC of the resulting data and checks the CRC against the value -+// found by the lineReader at EOF. -+type openpgpReader struct { -+ lReader *lineReader -+ b64Reader io.Reader -+ currentCRC uint32 -+} -+ -+func (r *openpgpReader) Read(p []byte) (n int, err error) { -+ n, err = r.b64Reader.Read(p) -+ r.currentCRC = crc24(r.currentCRC, p[:n]) -+ -+ if err == io.EOF && r.lReader.crcSet && r.lReader.crc != r.currentCRC&crc24Mask { -+ return 0, ArmorCorrupt -+ } -+ -+ return -+} -+ -+// Decode reads a PGP armored block from the given Reader. It will ignore -+// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The -+// given Reader is not usable after calling this function: an arbitrary amount -+// of data may have been read past the end of the block. -+func Decode(in io.Reader) (p *Block, err error) { -+ r := bufio.NewReaderSize(in, 100) -+ var line []byte -+ ignoreNext := false -+ -+TryNextBlock: -+ p = nil -+ -+ // Skip leading garbage -+ for { -+ ignoreThis := ignoreNext -+ line, ignoreNext, err = r.ReadLine() -+ if err != nil { -+ return -+ } -+ if ignoreNext || ignoreThis { -+ continue -+ } -+ line = bytes.TrimSpace(line) -+ if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { -+ break -+ } -+ } -+ -+ p = new(Block) -+ p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) -+ p.Header = make(map[string]string) -+ nextIsContinuation := false -+ var lastKey string -+ -+ // Read headers -+ for { -+ isContinuation := nextIsContinuation -+ line, nextIsContinuation, err = r.ReadLine() -+ if err != nil { -+ p = nil -+ return -+ } -+ if isContinuation { -+ p.Header[lastKey] += string(line) -+ continue -+ } -+ line = bytes.TrimSpace(line) -+ if len(line) == 0 { -+ break -+ } -+ -+ i := bytes.Index(line, []byte(": ")) -+ if i == -1 { -+ goto TryNextBlock -+ } -+ lastKey = string(line[:i]) -+ p.Header[lastKey] = string(line[i+2:]) -+ } -+ -+ p.lReader.in = r -+ p.oReader.currentCRC = crc24Init -+ p.oReader.lReader = &p.lReader -+ p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) -+ p.Body = &p.oReader -+ -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go b/ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go -new file mode 100644 -index 00000000000000..c05af95fdec6d4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/armor/armor_test.go -@@ -0,0 +1,95 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package armor -+ -+import ( -+ "bytes" -+ "hash/adler32" -+ "io" -+ "testing" -+) -+ -+func TestDecodeEncode(t *testing.T) { -+ buf := bytes.NewBuffer([]byte(armorExample1)) -+ result, err := Decode(buf) -+ if err != nil { -+ t.Error(err) -+ } -+ expectedType := "PGP SIGNATURE" -+ if result.Type != expectedType { -+ t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType) -+ } -+ if len(result.Header) != 1 { -+ t.Errorf("len(result.Header): got:%d want:1", len(result.Header)) -+ } -+ v, ok := result.Header["Version"] -+ if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" { -+ t.Errorf("result.Header: got:%#v", result.Header) -+ } -+ -+ contents, err := io.ReadAll(result.Body) -+ if err != nil { -+ t.Error(err) -+ } -+ -+ if adler32.Checksum(contents) != 0x27b144be { -+ t.Errorf("contents: got: %x", contents) -+ } -+ -+ buf = bytes.NewBuffer(nil) -+ w, err := Encode(buf, result.Type, result.Header) -+ if err != nil { -+ t.Error(err) -+ } -+ _, err = w.Write(contents) -+ if err != nil { -+ t.Error(err) -+ } -+ w.Close() -+ -+ if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) { -+ t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1) -+ } -+} -+ -+func TestLongHeader(t *testing.T) { -+ buf := bytes.NewBuffer([]byte(armorLongLine)) -+ result, err := Decode(buf) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ value, ok := result.Header["Version"] -+ if !ok { -+ t.Errorf("missing Version header") -+ } -+ if value != longValueExpected { -+ t.Errorf("got: %s want: %s", value, longValueExpected) -+ } -+} -+ -+const armorExample1 = `-----BEGIN PGP SIGNATURE----- -+Version: GnuPG v1.4.10 (GNU/Linux) -+ -+iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm -+4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt -+p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW -+TxRjs+fJCIFuo71xb1g= -+=/teI -+-----END PGP SIGNATURE-----` -+ -+const armorLongLine = `-----BEGIN PGP SIGNATURE----- -+Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz -+ -+iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8 -+kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp -+cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA -+byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3 -+WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv -+okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4= -+=wfQG -+-----END PGP SIGNATURE-----` -+ -+const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" -diff --git a/ms_mod/golang.org/x/crypto/openpgp/armor/encode.go b/ms_mod/golang.org/x/crypto/openpgp/armor/encode.go -new file mode 100644 -index 00000000000000..5b6e16c19d5239 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/armor/encode.go -@@ -0,0 +1,161 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package armor -+ -+import ( -+ "encoding/base64" -+ "io" -+) -+ -+var armorHeaderSep = []byte(": ") -+var blockEnd = []byte("\n=") -+var newline = []byte("\n") -+var armorEndOfLineOut = []byte("-----\n") -+ -+// writeSlices writes its arguments to the given Writer. -+func writeSlices(out io.Writer, slices ...[]byte) (err error) { -+ for _, s := range slices { -+ _, err = out.Write(s) -+ if err != nil { -+ return err -+ } -+ } -+ return -+} -+ -+// lineBreaker breaks data across several lines, all of the same byte length -+// (except possibly the last). Lines are broken with a single '\n'. -+type lineBreaker struct { -+ lineLength int -+ line []byte -+ used int -+ out io.Writer -+ haveWritten bool -+} -+ -+func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { -+ return &lineBreaker{ -+ lineLength: lineLength, -+ line: make([]byte, lineLength), -+ used: 0, -+ out: out, -+ } -+} -+ -+func (l *lineBreaker) Write(b []byte) (n int, err error) { -+ n = len(b) -+ -+ if n == 0 { -+ return -+ } -+ -+ if l.used == 0 && l.haveWritten { -+ _, err = l.out.Write([]byte{'\n'}) -+ if err != nil { -+ return -+ } -+ } -+ -+ if l.used+len(b) < l.lineLength { -+ l.used += copy(l.line[l.used:], b) -+ return -+ } -+ -+ l.haveWritten = true -+ _, err = l.out.Write(l.line[0:l.used]) -+ if err != nil { -+ return -+ } -+ excess := l.lineLength - l.used -+ l.used = 0 -+ -+ _, err = l.out.Write(b[0:excess]) -+ if err != nil { -+ return -+ } -+ -+ _, err = l.Write(b[excess:]) -+ return -+} -+ -+func (l *lineBreaker) Close() (err error) { -+ if l.used > 0 { -+ _, err = l.out.Write(l.line[0:l.used]) -+ if err != nil { -+ return -+ } -+ } -+ -+ return -+} -+ -+// encoding keeps track of a running CRC24 over the data which has been written -+// to it and outputs a OpenPGP checksum when closed, followed by an armor -+// trailer. -+// -+// It's built into a stack of io.Writers: -+// -+// encoding -> base64 encoder -> lineBreaker -> out -+type encoding struct { -+ out io.Writer -+ breaker *lineBreaker -+ b64 io.WriteCloser -+ crc uint32 -+ blockType []byte -+} -+ -+func (e *encoding) Write(data []byte) (n int, err error) { -+ e.crc = crc24(e.crc, data) -+ return e.b64.Write(data) -+} -+ -+func (e *encoding) Close() (err error) { -+ err = e.b64.Close() -+ if err != nil { -+ return -+ } -+ e.breaker.Close() -+ -+ var checksumBytes [3]byte -+ checksumBytes[0] = byte(e.crc >> 16) -+ checksumBytes[1] = byte(e.crc >> 8) -+ checksumBytes[2] = byte(e.crc) -+ -+ var b64ChecksumBytes [4]byte -+ base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) -+ -+ return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) -+} -+ -+// Encode returns a WriteCloser which will encode the data written to it in -+// OpenPGP armor. -+func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { -+ bType := []byte(blockType) -+ err = writeSlices(out, armorStart, bType, armorEndOfLineOut) -+ if err != nil { -+ return -+ } -+ -+ for k, v := range headers { -+ err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) -+ if err != nil { -+ return -+ } -+ } -+ -+ _, err = out.Write(newline) -+ if err != nil { -+ return -+ } -+ -+ e := &encoding{ -+ out: out, -+ breaker: newLineBreaker(out, 64), -+ crc: crc24Init, -+ blockType: bType, -+ } -+ e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) -+ return e, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/canonical_text.go b/ms_mod/golang.org/x/crypto/openpgp/canonical_text.go -new file mode 100644 -index 00000000000000..e601e389f1299c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/canonical_text.go -@@ -0,0 +1,59 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package openpgp -+ -+import "hash" -+ -+// NewCanonicalTextHash reformats text written to it into the canonical -+// form and then applies the hash h. See RFC 4880, section 5.2.1. -+func NewCanonicalTextHash(h hash.Hash) hash.Hash { -+ return &canonicalTextHash{h, 0} -+} -+ -+type canonicalTextHash struct { -+ h hash.Hash -+ s int -+} -+ -+var newline = []byte{'\r', '\n'} -+ -+func (cth *canonicalTextHash) Write(buf []byte) (int, error) { -+ start := 0 -+ -+ for i, c := range buf { -+ switch cth.s { -+ case 0: -+ if c == '\r' { -+ cth.s = 1 -+ } else if c == '\n' { -+ cth.h.Write(buf[start:i]) -+ cth.h.Write(newline) -+ start = i + 1 -+ } -+ case 1: -+ cth.s = 0 -+ } -+ } -+ -+ cth.h.Write(buf[start:]) -+ return len(buf), nil -+} -+ -+func (cth *canonicalTextHash) Sum(in []byte) []byte { -+ return cth.h.Sum(in) -+} -+ -+func (cth *canonicalTextHash) Reset() { -+ cth.h.Reset() -+ cth.s = 0 -+} -+ -+func (cth *canonicalTextHash) Size() int { -+ return cth.h.Size() -+} -+ -+func (cth *canonicalTextHash) BlockSize() int { -+ return cth.h.BlockSize() -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go b/ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go -new file mode 100644 -index 00000000000000..8f3ba2a8814ea9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/canonical_text_test.go -@@ -0,0 +1,52 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package openpgp -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+type recordingHash struct { -+ buf *bytes.Buffer -+} -+ -+func (r recordingHash) Write(b []byte) (n int, err error) { -+ return r.buf.Write(b) -+} -+ -+func (r recordingHash) Sum(in []byte) []byte { -+ return append(in, r.buf.Bytes()...) -+} -+ -+func (r recordingHash) Reset() { -+ panic("shouldn't be called") -+} -+ -+func (r recordingHash) Size() int { -+ panic("shouldn't be called") -+} -+ -+func (r recordingHash) BlockSize() int { -+ panic("shouldn't be called") -+} -+ -+func testCanonicalText(t *testing.T, input, expected string) { -+ r := recordingHash{bytes.NewBuffer(nil)} -+ c := NewCanonicalTextHash(r) -+ c.Write([]byte(input)) -+ result := c.Sum(nil) -+ if expected != string(result) { -+ t.Errorf("input: %x got: %x want: %x", input, result, expected) -+ } -+} -+ -+func TestCanonicalText(t *testing.T) { -+ testCanonicalText(t, "foo\n", "foo\r\n") -+ testCanonicalText(t, "foo", "foo") -+ testCanonicalText(t, "foo\r\n", "foo\r\n") -+ testCanonicalText(t, "foo\r\nbar", "foo\r\nbar") -+ testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n") -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go -new file mode 100644 -index 00000000000000..644b2e078bc9c8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign.go -@@ -0,0 +1,424 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package clearsign generates and processes OpenPGP, clear-signed data. See -+// RFC 4880, section 7. -+// -+// Clearsigned messages are cryptographically signed, but the contents of the -+// message are kept in plaintext so that it can be read without special tools. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package clearsign // import "golang.org/x/crypto/openpgp/clearsign" -+ -+import ( -+ "bufio" -+ "bytes" -+ "crypto" -+ "fmt" -+ "hash" -+ "io" -+ "net/textproto" -+ "strconv" -+ "strings" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+// A Block represents a clearsigned message. A signature on a Block can -+// be checked by passing Bytes into openpgp.CheckDetachedSignature. -+type Block struct { -+ Headers textproto.MIMEHeader // Optional unverified Hash headers -+ Plaintext []byte // The original message text -+ Bytes []byte // The signed message -+ ArmoredSignature *armor.Block // The signature block -+} -+ -+// start is the marker which denotes the beginning of a clearsigned message. -+var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----") -+ -+// dashEscape is prefixed to any lines that begin with a hyphen so that they -+// can't be confused with endText. -+var dashEscape = []byte("- ") -+ -+// endText is a marker which denotes the end of the message and the start of -+// an armored signature. -+var endText = []byte("-----BEGIN PGP SIGNATURE-----") -+ -+// end is a marker which denotes the end of the armored signature. -+var end = []byte("\n-----END PGP SIGNATURE-----") -+ -+var crlf = []byte("\r\n") -+var lf = byte('\n') -+ -+// getLine returns the first \r\n or \n delineated line from the given byte -+// array. The line does not include the \r\n or \n. The remainder of the byte -+// array (also not including the new line bytes) is also returned and this will -+// always be smaller than the original argument. -+func getLine(data []byte) (line, rest []byte) { -+ i := bytes.Index(data, []byte{'\n'}) -+ var j int -+ if i < 0 { -+ i = len(data) -+ j = i -+ } else { -+ j = i + 1 -+ if i > 0 && data[i-1] == '\r' { -+ i-- -+ } -+ } -+ return data[0:i], data[j:] -+} -+ -+// Decode finds the first clearsigned message in data and returns it, as well as -+// the suffix of data which remains after the message. Any prefix data is -+// discarded. -+// -+// If no message is found, or if the message is invalid, Decode returns nil and -+// the whole data slice. The only allowed header type is Hash, and it is not -+// verified against the signature hash. -+func Decode(data []byte) (b *Block, rest []byte) { -+ // start begins with a newline. However, at the very beginning of -+ // the byte array, we'll accept the start string without it. -+ rest = data -+ if bytes.HasPrefix(data, start[1:]) { -+ rest = rest[len(start)-1:] -+ } else if i := bytes.Index(data, start); i >= 0 { -+ rest = rest[i+len(start):] -+ } else { -+ return nil, data -+ } -+ -+ // Consume the start line and check it does not have a suffix. -+ suffix, rest := getLine(rest) -+ if len(suffix) != 0 { -+ return nil, data -+ } -+ -+ var line []byte -+ b = &Block{ -+ Headers: make(textproto.MIMEHeader), -+ } -+ -+ // Next come a series of header lines. -+ for { -+ // This loop terminates because getLine's second result is -+ // always smaller than its argument. -+ if len(rest) == 0 { -+ return nil, data -+ } -+ // An empty line marks the end of the headers. -+ if line, rest = getLine(rest); len(line) == 0 { -+ break -+ } -+ -+ // Reject headers with control or Unicode characters. -+ if i := bytes.IndexFunc(line, func(r rune) bool { -+ return r < 0x20 || r > 0x7e -+ }); i != -1 { -+ return nil, data -+ } -+ -+ i := bytes.Index(line, []byte{':'}) -+ if i == -1 { -+ return nil, data -+ } -+ -+ key, val := string(line[0:i]), string(line[i+1:]) -+ key = strings.TrimSpace(key) -+ if key != "Hash" { -+ return nil, data -+ } -+ val = strings.TrimSpace(val) -+ b.Headers.Add(key, val) -+ } -+ -+ firstLine := true -+ for { -+ start := rest -+ -+ line, rest = getLine(rest) -+ if len(line) == 0 && len(rest) == 0 { -+ // No armored data was found, so this isn't a complete message. -+ return nil, data -+ } -+ if bytes.Equal(line, endText) { -+ // Back up to the start of the line because armor expects to see the -+ // header line. -+ rest = start -+ break -+ } -+ -+ // The final CRLF isn't included in the hash so we don't write it until -+ // we've seen the next line. -+ if firstLine { -+ firstLine = false -+ } else { -+ b.Bytes = append(b.Bytes, crlf...) -+ } -+ -+ if bytes.HasPrefix(line, dashEscape) { -+ line = line[2:] -+ } -+ line = bytes.TrimRight(line, " \t") -+ b.Bytes = append(b.Bytes, line...) -+ -+ b.Plaintext = append(b.Plaintext, line...) -+ b.Plaintext = append(b.Plaintext, lf) -+ } -+ -+ // We want to find the extent of the armored data (including any newlines at -+ // the end). -+ i := bytes.Index(rest, end) -+ if i == -1 { -+ return nil, data -+ } -+ i += len(end) -+ for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { -+ i++ -+ } -+ armored := rest[:i] -+ rest = rest[i:] -+ -+ var err error -+ b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) -+ if err != nil { -+ return nil, data -+ } -+ -+ return b, rest -+} -+ -+// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed -+// message. The clear-signed message is written to buffered and a hash, suitable -+// for signing, is maintained in h. -+// -+// When closed, an armored signature is created and written to complete the -+// message. -+type dashEscaper struct { -+ buffered *bufio.Writer -+ hashers []hash.Hash // one per key in privateKeys -+ hashType crypto.Hash -+ toHash io.Writer // writes to all the hashes in hashers -+ -+ atBeginningOfLine bool -+ isFirstLine bool -+ -+ whitespace []byte -+ byteBuf []byte // a one byte buffer to save allocations -+ -+ privateKeys []*packet.PrivateKey -+ config *packet.Config -+} -+ -+func (d *dashEscaper) Write(data []byte) (n int, err error) { -+ for _, b := range data { -+ d.byteBuf[0] = b -+ -+ if d.atBeginningOfLine { -+ // The final CRLF isn't included in the hash so we have to wait -+ // until this point (the start of the next line) before writing it. -+ if !d.isFirstLine { -+ d.toHash.Write(crlf) -+ } -+ d.isFirstLine = false -+ } -+ -+ // Any whitespace at the end of the line has to be removed so we -+ // buffer it until we find out whether there's more on this line. -+ if b == ' ' || b == '\t' || b == '\r' { -+ d.whitespace = append(d.whitespace, b) -+ d.atBeginningOfLine = false -+ continue -+ } -+ -+ if d.atBeginningOfLine { -+ // At the beginning of a line, hyphens have to be escaped. -+ if b == '-' { -+ // The signature isn't calculated over the dash-escaped text so -+ // the escape is only written to buffered. -+ if _, err = d.buffered.Write(dashEscape); err != nil { -+ return -+ } -+ d.toHash.Write(d.byteBuf) -+ d.atBeginningOfLine = false -+ } else if b == '\n' { -+ // Nothing to do because we delay writing CRLF to the hash. -+ } else { -+ d.toHash.Write(d.byteBuf) -+ d.atBeginningOfLine = false -+ } -+ if err = d.buffered.WriteByte(b); err != nil { -+ return -+ } -+ } else { -+ if b == '\n' { -+ // We got a raw \n. Drop any trailing whitespace and write a -+ // CRLF. -+ d.whitespace = d.whitespace[:0] -+ // We delay writing CRLF to the hash until the start of the -+ // next line. -+ if err = d.buffered.WriteByte(b); err != nil { -+ return -+ } -+ d.atBeginningOfLine = true -+ } else { -+ // Any buffered whitespace wasn't at the end of the line so -+ // we need to write it out. -+ if len(d.whitespace) > 0 { -+ d.toHash.Write(d.whitespace) -+ if _, err = d.buffered.Write(d.whitespace); err != nil { -+ return -+ } -+ d.whitespace = d.whitespace[:0] -+ } -+ d.toHash.Write(d.byteBuf) -+ if err = d.buffered.WriteByte(b); err != nil { -+ return -+ } -+ } -+ } -+ } -+ -+ n = len(data) -+ return -+} -+ -+func (d *dashEscaper) Close() (err error) { -+ if !d.atBeginningOfLine { -+ if err = d.buffered.WriteByte(lf); err != nil { -+ return -+ } -+ } -+ -+ out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil) -+ if err != nil { -+ return -+ } -+ -+ t := d.config.Now() -+ for i, k := range d.privateKeys { -+ sig := new(packet.Signature) -+ sig.SigType = packet.SigTypeText -+ sig.PubKeyAlgo = k.PubKeyAlgo -+ sig.Hash = d.hashType -+ sig.CreationTime = t -+ sig.IssuerKeyId = &k.KeyId -+ -+ if err = sig.Sign(d.hashers[i], k, d.config); err != nil { -+ return -+ } -+ if err = sig.Serialize(out); err != nil { -+ return -+ } -+ } -+ -+ if err = out.Close(); err != nil { -+ return -+ } -+ if err = d.buffered.Flush(); err != nil { -+ return -+ } -+ return -+} -+ -+// Encode returns a WriteCloser which will clear-sign a message with privateKey -+// and write it to w. If config is nil, sensible defaults are used. -+func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ return EncodeMulti(w, []*packet.PrivateKey{privateKey}, config) -+} -+ -+// EncodeMulti returns a WriteCloser which will clear-sign a message with all the -+// private keys indicated and write it to w. If config is nil, sensible defaults -+// are used. -+func EncodeMulti(w io.Writer, privateKeys []*packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ for _, k := range privateKeys { -+ if k.Encrypted { -+ return nil, errors.InvalidArgumentError(fmt.Sprintf("signing key %s is encrypted", k.KeyIdString())) -+ } -+ } -+ -+ hashType := config.Hash() -+ name := nameOfHash(hashType) -+ if len(name) == 0 { -+ return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType))) -+ } -+ -+ if !hashType.Available() { -+ return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType))) -+ } -+ var hashers []hash.Hash -+ var ws []io.Writer -+ for range privateKeys { -+ h := hashType.New() -+ hashers = append(hashers, h) -+ ws = append(ws, h) -+ } -+ toHash := io.MultiWriter(ws...) -+ -+ buffered := bufio.NewWriter(w) -+ // start has a \n at the beginning that we don't want here. -+ if _, err = buffered.Write(start[1:]); err != nil { -+ return -+ } -+ if err = buffered.WriteByte(lf); err != nil { -+ return -+ } -+ if _, err = buffered.WriteString("Hash: "); err != nil { -+ return -+ } -+ if _, err = buffered.WriteString(name); err != nil { -+ return -+ } -+ if err = buffered.WriteByte(lf); err != nil { -+ return -+ } -+ if err = buffered.WriteByte(lf); err != nil { -+ return -+ } -+ -+ plaintext = &dashEscaper{ -+ buffered: buffered, -+ hashers: hashers, -+ hashType: hashType, -+ toHash: toHash, -+ -+ atBeginningOfLine: true, -+ isFirstLine: true, -+ -+ byteBuf: make([]byte, 1), -+ -+ privateKeys: privateKeys, -+ config: config, -+ } -+ -+ return -+} -+ -+// nameOfHash returns the OpenPGP name for the given hash, or the empty string -+// if the name isn't known. See RFC 4880, section 9.4. -+func nameOfHash(h crypto.Hash) string { -+ switch h { -+ case crypto.MD5: -+ return "MD5" -+ case crypto.SHA1: -+ return "SHA1" -+ case crypto.RIPEMD160: -+ return "RIPEMD160" -+ case crypto.SHA224: -+ return "SHA224" -+ case crypto.SHA256: -+ return "SHA256" -+ case crypto.SHA384: -+ return "SHA384" -+ case crypto.SHA512: -+ return "SHA512" -+ } -+ return "" -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go -new file mode 100644 -index 00000000000000..051b8f16ffa3b4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go -@@ -0,0 +1,398 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package clearsign -+ -+import ( -+ "bytes" -+ "fmt" -+ "io" -+ "testing" -+ -+ "golang.org/x/crypto/openpgp" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) { -+ b, rest := Decode(input) -+ if b == nil { -+ t.Fatal("failed to decode clearsign message") -+ } -+ if !bytes.Equal(rest, []byte("trailing")) { -+ t.Errorf("unexpected remaining bytes returned: %s", string(rest)) -+ } -+ if b.ArmoredSignature.Type != "PGP SIGNATURE" { -+ t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type) -+ } -+ if !bytes.Equal(b.Bytes, []byte(expected)) { -+ t.Errorf("bad body, got:%x want:%x", b.Bytes, expected) -+ } -+ -+ if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) { -+ t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext) -+ } -+ -+ keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) -+ if err != nil { -+ t.Errorf("failed to parse public key: %s", err) -+ } -+ -+ if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { -+ t.Errorf("failed to check signature: %s", err) -+ } -+} -+ -+func TestParse(t *testing.T) { -+ testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n") -+ testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n") -+} -+ -+func TestParseWithNoNewlineAtEnd(t *testing.T) { -+ input := clearsignInput -+ input = input[:len(input)-len("trailing")-1] -+ b, rest := Decode(input) -+ if b == nil { -+ t.Fatal("failed to decode clearsign message") -+ } -+ if len(rest) > 0 { -+ t.Errorf("unexpected remaining bytes returned: %s", string(rest)) -+ } -+} -+ -+var signingTests = []struct { -+ in, signed, plaintext string -+}{ -+ {"", "", ""}, -+ {"a", "a", "a\n"}, -+ {"a\n", "a", "a\n"}, -+ {"-a\n", "-a", "-a\n"}, -+ {"--a\nb", "--a\r\nb", "--a\nb\n"}, -+ // leading whitespace -+ {" a\n", " a", " a\n"}, -+ {" a\n", " a", " a\n"}, -+ // trailing whitespace (should be stripped) -+ {"a \n", "a", "a\n"}, -+ {"a ", "a", "a\n"}, -+ // whitespace-only lines (should be stripped) -+ {" \n", "", "\n"}, -+ {" ", "", "\n"}, -+ {"a\n \n \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"}, -+} -+ -+func TestSigning(t *testing.T) { -+ keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) -+ if err != nil { -+ t.Errorf("failed to parse public key: %s", err) -+ } -+ -+ for i, test := range signingTests { -+ var buf bytes.Buffer -+ -+ plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil) -+ if err != nil { -+ t.Errorf("#%d: error from Encode: %s", i, err) -+ continue -+ } -+ if _, err := plaintext.Write([]byte(test.in)); err != nil { -+ t.Errorf("#%d: error from Write: %s", i, err) -+ continue -+ } -+ if err := plaintext.Close(); err != nil { -+ t.Fatalf("#%d: error from Close: %s", i, err) -+ continue -+ } -+ -+ b, _ := Decode(buf.Bytes()) -+ if b == nil { -+ t.Errorf("#%d: failed to decode clearsign message", i) -+ continue -+ } -+ if !bytes.Equal(b.Bytes, []byte(test.signed)) { -+ t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed) -+ continue -+ } -+ if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) { -+ t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext) -+ continue -+ } -+ -+ if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { -+ t.Errorf("#%d: failed to check signature: %s", i, err) -+ } -+ } -+} -+ -+// We use this to make test keys, so that they aren't all the same. -+type quickRand byte -+ -+func (qr *quickRand) Read(p []byte) (int, error) { -+ for i := range p { -+ p[i] = byte(*qr) -+ } -+ *qr++ -+ return len(p), nil -+} -+ -+func TestMultiSign(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping long test in -short mode") -+ } -+ -+ zero := quickRand(0) -+ config := packet.Config{Rand: &zero} -+ -+ for nKeys := 0; nKeys < 4; nKeys++ { -+ nextTest: -+ for nExtra := 0; nExtra < 4; nExtra++ { -+ var signKeys []*packet.PrivateKey -+ var verifyKeys openpgp.EntityList -+ -+ desc := fmt.Sprintf("%d keys; %d of which will be used to verify", nKeys+nExtra, nKeys) -+ for i := 0; i < nKeys+nExtra; i++ { -+ e, err := openpgp.NewEntity("name", "comment", "email", &config) -+ if err != nil { -+ t.Errorf("cannot create key: %v", err) -+ continue nextTest -+ } -+ if i < nKeys { -+ verifyKeys = append(verifyKeys, e) -+ } -+ signKeys = append(signKeys, e.PrivateKey) -+ } -+ -+ input := []byte("this is random text\r\n4 17") -+ var output bytes.Buffer -+ w, err := EncodeMulti(&output, signKeys, nil) -+ if err != nil { -+ t.Errorf("EncodeMulti (%s) failed: %v", desc, err) -+ } -+ if _, err := w.Write(input); err != nil { -+ t.Errorf("Write(%q) to signer (%s) failed: %v", string(input), desc, err) -+ } -+ if err := w.Close(); err != nil { -+ t.Errorf("Close() of signer (%s) failed: %v", desc, err) -+ } -+ -+ block, _ := Decode(output.Bytes()) -+ if string(block.Bytes) != string(input) { -+ t.Errorf("Inline data didn't match original; got %q want %q", string(block.Bytes), string(input)) -+ } -+ _, err = openpgp.CheckDetachedSignature(verifyKeys, bytes.NewReader(block.Bytes), block.ArmoredSignature.Body) -+ if nKeys == 0 { -+ if err == nil { -+ t.Errorf("verifying inline (%s) succeeded; want failure", desc) -+ } -+ } else { -+ if err != nil { -+ t.Errorf("verifying inline (%s) failed (%v); want success", desc, err) -+ } -+ } -+ } -+ } -+} -+ -+func TestDecodeMissingCRC(t *testing.T) { -+ block, rest := Decode(clearsignInput3) -+ if block == nil { -+ t.Fatal("failed to decode PGP signature missing a CRC") -+ } -+ if len(rest) > 0 { -+ t.Fatalf("Decode should not have any remaining data left: %s", rest) -+ } -+ if _, err := packet.Read(block.ArmoredSignature.Body); err != nil { -+ t.Error(err) -+ } -+ if _, err := packet.Read(block.ArmoredSignature.Body); err != io.EOF { -+ t.Error(err) -+ } -+} -+ -+const signatureBlock = ` -+-----BEGIN PGP SIGNATURE----- -+Version: OpenPrivacy 0.99 -+ -+yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS -+vBSFjNSiVHsuAA== -+=njUN -+-----END PGP SIGNATURE----- -+` -+ -+var invalidInputs = []string{ -+ ` -+-----BEGIN PGP SIGNED MESSAGE----- -+Hash: SHA256 -+ -+(This message was truncated.) -+`, -+ ` -+-----BEGIN PGP SIGNED MESSAGE-----garbage -+Hash: SHA256 -+ -+_o/ -+` + signatureBlock, -+ ` -+garbage-----BEGIN PGP SIGNED MESSAGE----- -+Hash: SHA256 -+ -+_o/ -+` + signatureBlock, -+ ` -+-----BEGIN PGP SIGNED MESSAGE----- -+Hash: SHA` + "\x0b\x0b" + `256 -+ -+_o/ -+` + signatureBlock, -+ ` -+-----BEGIN PGP SIGNED MESSAGE----- -+NotHash: SHA256 -+ -+_o/ -+` + signatureBlock, -+} -+ -+func TestParseInvalid(t *testing.T) { -+ for i, input := range invalidInputs { -+ if b, rest := Decode([]byte(input)); b != nil { -+ t.Errorf("#%d: decoded a bad clearsigned message without any error", i) -+ } else if string(rest) != input { -+ t.Errorf("#%d: did not return all data with a bad message", i) -+ } -+ } -+} -+ -+var clearsignInput = []byte(` -+;lasjlkfdsa -+ -+-----BEGIN PGP SIGNED MESSAGE----- -+Hash: SHA1 -+ -+Hello world -+line 2 -+-----BEGIN PGP SIGNATURE----- -+Version: GnuPG v1.4.10 (GNU/Linux) -+ -+iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8 -+pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog -+2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9 -+MyTpno24AjIAGb+mH1U= -+=hIJ6 -+-----END PGP SIGNATURE----- -+trailing`) -+ -+var clearsignInput2 = []byte(` -+asdlfkjasdlkfjsadf -+ -+-----BEGIN PGP SIGNED MESSAGE----- -+Hash: SHA256 -+ -+ -+ -+(This message has a couple of blank lines at the start and end.) -+ -+ -+-----BEGIN PGP SIGNATURE----- -+Version: GnuPG v1.4.11 (GNU/Linux) -+ -+iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v -+pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI -+ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+ -+qZg6BaTvOxepqOxnhVU= -+=e+C6 -+-----END PGP SIGNATURE----- -+ -+trailing`) -+ -+var clearsignInput3 = []byte(`-----BEGIN PGP SIGNED MESSAGE----- -+Hash: SHA256 -+ -+Origin: vscode stable -+Label: vscode stable -+Suite: stable -+Codename: stable -+Date: Mon, 13 Jan 2020 08:41:45 UTC -+Architectures: amd64 -+Components: main -+Description: Generated by aptly -+MD5Sum: -+ 66437152b3082616d8053e52c4bafafb 5821166 Contents-amd64 -+ 8024662ed51109946a517754bbafdd33 286298 Contents-amd64.gz -+ 66437152b3082616d8053e52c4bafafb 5821166 main/Contents-amd64 -+ 8024662ed51109946a517754bbafdd33 286298 main/Contents-amd64.gz -+ 3062a08b3eca94a65d6d17ba1dafcf3e 1088265 main/binary-amd64/Packages -+ b8ee22200fba8fa3be56c1ff946cdd24 159344 main/binary-amd64/Packages.bz2 -+ f89c47c81ebd25caf287c8e6dda16c1a 169456 main/binary-amd64/Packages.gz -+ 4c9ca25b556f111a5536c78df885ad82 95 main/binary-amd64/Release -+SHA1: -+ 2b62d0e322746b7d094878278f49993ca4314bf7 5821166 Contents-amd64 -+ aafe35cce12e03d8b1939e403ddf5c0958c6e9bd 286298 Contents-amd64.gz -+ 2b62d0e322746b7d094878278f49993ca4314bf7 5821166 main/Contents-amd64 -+ aafe35cce12e03d8b1939e403ddf5c0958c6e9bd 286298 main/Contents-amd64.gz -+ 30316ac5d4ce3b472a96a797eeb0a2a82d43ed3e 1088265 main/binary-amd64/Packages -+ 6507e0b4da8194fd1048fcbb74c6e7433edaf3d6 159344 main/binary-amd64/Packages.bz2 -+ ec9d39c39567c74001221e4900fb5d11ec11b833 169456 main/binary-amd64/Packages.gz -+ 58bf20987a91d35936f18efce75ea233d43dbf8b 95 main/binary-amd64/Release -+SHA256: -+ deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39 5821166 Contents-amd64 -+ f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462 286298 Contents-amd64.gz -+ deff9ebfc44bf482e10a6ea10f608c6bb0fdc8373bf86b88cad9d99879ae3c39 5821166 main/Contents-amd64 -+ f163bc65c7666ef58e0be3336e8c846ae2b7b388fbb2d7db0bcdc3fd1abae462 286298 main/Contents-amd64.gz -+ 0fba50799ef72d0c2b354d0bcbbc8c623f6dae5a7fd7c218a54ea44dd8a49d5e 1088265 main/binary-amd64/Packages -+ 69382470a88b67acde80fe45ab223016adebc445713ff0aa3272902581d21f13 159344 main/binary-amd64/Packages.bz2 -+ 1724b8ace5bd8882943e9463d8525006f33ca704480da0186fd47937451dc216 169456 main/binary-amd64/Packages.gz -+ 0f509a0cb07e0ab433176fa47a21dccccc6b519f25f640cc58561104c11de6c2 95 main/binary-amd64/Release -+SHA512: -+ f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c 5821166 Contents-amd64 -+ 46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a 286298 Contents-amd64.gz -+ f69f09c6180ceb6625a84b5f7123ad27972983146979dcfd9c38b2990459b52b4975716f85374511486bb5ad5852ebb1ef8265176df7134fc15b17ada3ba596c 5821166 main/Contents-amd64 -+ 46031bf89166188989368957d20cdcaac6eec72bab3f9839c9704bb08cbee3174ca6da11e290b0eab0e6b5754c1e7feb06d18ec9c5a0c955029cef53235e0a3a 286298 main/Contents-amd64.gz -+ 3f78baf5adbaf0100996555b154807c794622fd0b5879b568ae0b6560e988fbfabed8d97db5a703d1a58514b9690fc6b60f9ad2eeece473d86ab257becd0ae41 1088265 main/binary-amd64/Packages -+ 18f26df90beff29192662ca40525367c3c04f4581d59d2e9ab1cd0700a145b6a292a1609ca33ebe1c211f13718a8eee751f41fd8189cf93d52aa3e0851542dfc 159344 main/binary-amd64/Packages.bz2 -+ 6a6d917229e0cf06c493e174a87d76e815717676f2c70bcbd3bc689a80bd3c5489ea97db83b8f74cba8e70f374f9d9974f22b1ed2687a4ba1dacd22fdef7e14d 169456 main/binary-amd64/Packages.gz -+ e1a4378ad266c13c2edf8a0e590fa4d11973ab99ce79f15af005cb838f1600f66f3dc6da8976fa8b474da9073c118039c27623ab3360c6df115071497fe4f50c 95 main/binary-amd64/Release -+ -+-----BEGIN PGP SIGNATURE----- -+Version: BSN Pgp v1.0.0.0 -+ -+iQEcBAEBCAAGBQJeHC1bAAoJEOs+lK2+EinPAg8H/1rrhcgfm1HYL+Vmr9Ns6ton -+LWQ8r13ADN66UTRa3XsO9V+q1fYowTqpXq6EZt2Gmlby/cpDf7mFPM5IteOXWLl7 -+QcWxPKHcdPIUi+h5F7BkFW65imP9GyX+V5Pxx5X544op7hYKaI0gAQ1oYtWDb3HE -+4D27fju6icbj8w6E8TePcrDn82UvWAcaI5WSLboyhXCt2DxS3PNGFlyaP58zKJ8F -+9cbBzksuMgMaTPAAMrU0zrFGfGeQz0Yo6nV/gRGiQaL9pSeIJWSKLNCMG/nIGmv2 -+xHVNFqTEetREY6UcQmuhwOn4HezyigH6XCBVp/Uez1izXiNdwBOet34SSvnkuJ4= -+-----END PGP SIGNATURE-----`) -+ -+var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- -+Version: GnuPG v1.4.10 (GNU/Linux) -+ -+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp -+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn -+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB -+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X -+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL -+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk -+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn -+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 -+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx -+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz -+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA -+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 -+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ -+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid -+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV -+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK -+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA -+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX -+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc -+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 -+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN -+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 -+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU -+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC -+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp -+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad -+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL -+VrM0m72/jnpKo04= -+=zNCn -+-----END PGP PRIVATE KEY BLOCK----- -+` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go -new file mode 100644 -index 00000000000000..743b35a1204f5f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal.go -@@ -0,0 +1,130 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package elgamal implements ElGamal encryption, suitable for OpenPGP, -+// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on -+// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, -+// n. 4, 1985, pp. 469-472. -+// -+// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it -+// unsuitable for other protocols. RSA should be used in preference in any -+// case. -+// -+// Deprecated: this package was only provided to support ElGamal encryption in -+// OpenPGP. The golang.org/x/crypto/openpgp package is now deprecated (see -+// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has -+// compatibility and security issues (see https://eprint.iacr.org/2021/923). -+// Moreover, this package doesn't protect against side-channel attacks. -+package elgamal // import "golang.org/x/crypto/openpgp/elgamal" -+ -+import ( -+ "crypto/rand" -+ "crypto/subtle" -+ "errors" -+ "io" -+ "math/big" -+) -+ -+// PublicKey represents an ElGamal public key. -+type PublicKey struct { -+ G, P, Y *big.Int -+} -+ -+// PrivateKey represents an ElGamal private key. -+type PrivateKey struct { -+ PublicKey -+ X *big.Int -+} -+ -+// Encrypt encrypts the given message to the given public key. The result is a -+// pair of integers. Errors can result from reading random, or because msg is -+// too large to be encrypted to the public key. -+func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { -+ pLen := (pub.P.BitLen() + 7) / 8 -+ if len(msg) > pLen-11 { -+ err = errors.New("elgamal: message too long") -+ return -+ } -+ -+ // EM = 0x02 || PS || 0x00 || M -+ em := make([]byte, pLen-1) -+ em[0] = 2 -+ ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] -+ err = nonZeroRandomBytes(ps, random) -+ if err != nil { -+ return -+ } -+ em[len(em)-len(msg)-1] = 0 -+ copy(mm, msg) -+ -+ m := new(big.Int).SetBytes(em) -+ -+ k, err := rand.Int(random, pub.P) -+ if err != nil { -+ return -+ } -+ -+ c1 = new(big.Int).Exp(pub.G, k, pub.P) -+ s := new(big.Int).Exp(pub.Y, k, pub.P) -+ c2 = s.Mul(s, m) -+ c2.Mod(c2, pub.P) -+ -+ return -+} -+ -+// Decrypt takes two integers, resulting from an ElGamal encryption, and -+// returns the plaintext of the message. An error can result only if the -+// ciphertext is invalid. Users should keep in mind that this is a padding -+// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can -+// be used to break the cryptosystem. See β€œChosen Ciphertext Attacks -+// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel -+// Bleichenbacher, Advances in Cryptology (Crypto '98), -+func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { -+ s := new(big.Int).Exp(c1, priv.X, priv.P) -+ if s.ModInverse(s, priv.P) == nil { -+ return nil, errors.New("elgamal: invalid private key") -+ } -+ s.Mul(s, c2) -+ s.Mod(s, priv.P) -+ em := s.Bytes() -+ -+ firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) -+ -+ // The remainder of the plaintext must be a string of non-zero random -+ // octets, followed by a 0, followed by the message. -+ // lookingForIndex: 1 iff we are still looking for the zero. -+ // index: the offset of the first zero byte. -+ var lookingForIndex, index int -+ lookingForIndex = 1 -+ -+ for i := 1; i < len(em); i++ { -+ equals0 := subtle.ConstantTimeByteEq(em[i], 0) -+ index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) -+ lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) -+ } -+ -+ if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { -+ return nil, errors.New("elgamal: decryption error") -+ } -+ return em[index+1:], nil -+} -+ -+// nonZeroRandomBytes fills the given slice with non-zero random octets. -+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { -+ _, err = io.ReadFull(rand, s) -+ if err != nil { -+ return -+ } -+ -+ for i := 0; i < len(s); i++ { -+ for s[i] == 0 { -+ _, err = io.ReadFull(rand, s[i:i+1]) -+ if err != nil { -+ return -+ } -+ } -+ } -+ -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go -new file mode 100644 -index 00000000000000..9f0a8547c3ef55 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go -@@ -0,0 +1,64 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package elgamal -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "math/big" -+ "testing" -+) -+ -+// This is the 1024-bit MODP group from RFC 5114, section 2.1: -+const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371" -+ -+const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5" -+ -+func fromHex(hex string) *big.Int { -+ n, ok := new(big.Int).SetString(hex, 16) -+ if !ok { -+ panic("failed to parse hex number") -+ } -+ return n -+} -+ -+func TestEncryptDecrypt(t *testing.T) { -+ priv := &PrivateKey{ -+ PublicKey: PublicKey{ -+ G: fromHex(generatorHex), -+ P: fromHex(primeHex), -+ }, -+ X: fromHex("42"), -+ } -+ priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) -+ -+ message := []byte("hello world") -+ c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message) -+ if err != nil { -+ t.Errorf("error encrypting: %s", err) -+ } -+ message2, err := Decrypt(priv, c1, c2) -+ if err != nil { -+ t.Errorf("error decrypting: %s", err) -+ } -+ if !bytes.Equal(message2, message) { -+ t.Errorf("decryption failed, got: %x, want: %x", message2, message) -+ } -+} -+ -+func TestDecryptBadKey(t *testing.T) { -+ priv := &PrivateKey{ -+ PublicKey: PublicKey{ -+ G: fromHex(generatorHex), -+ P: fromHex("2"), -+ }, -+ X: fromHex("42"), -+ } -+ priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) -+ c1, c2 := fromHex("8"), fromHex("8") -+ if _, err := Decrypt(priv, c1, c2); err == nil { -+ t.Errorf("unexpected success decrypting") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/errors/errors.go b/ms_mod/golang.org/x/crypto/openpgp/errors/errors.go -new file mode 100644 -index 00000000000000..1d7a0ea05adf17 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/errors/errors.go -@@ -0,0 +1,78 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package errors contains common error types for the OpenPGP packages. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package errors // import "golang.org/x/crypto/openpgp/errors" -+ -+import ( -+ "strconv" -+) -+ -+// A StructuralError is returned when OpenPGP data is found to be syntactically -+// invalid. -+type StructuralError string -+ -+func (s StructuralError) Error() string { -+ return "openpgp: invalid data: " + string(s) -+} -+ -+// UnsupportedError indicates that, although the OpenPGP data is valid, it -+// makes use of currently unimplemented features. -+type UnsupportedError string -+ -+func (s UnsupportedError) Error() string { -+ return "openpgp: unsupported feature: " + string(s) -+} -+ -+// InvalidArgumentError indicates that the caller is in error and passed an -+// incorrect value. -+type InvalidArgumentError string -+ -+func (i InvalidArgumentError) Error() string { -+ return "openpgp: invalid argument: " + string(i) -+} -+ -+// SignatureError indicates that a syntactically valid signature failed to -+// validate. -+type SignatureError string -+ -+func (b SignatureError) Error() string { -+ return "openpgp: invalid signature: " + string(b) -+} -+ -+type keyIncorrectError int -+ -+func (ki keyIncorrectError) Error() string { -+ return "openpgp: incorrect key" -+} -+ -+var ErrKeyIncorrect error = keyIncorrectError(0) -+ -+type unknownIssuerError int -+ -+func (unknownIssuerError) Error() string { -+ return "openpgp: signature made by unknown entity" -+} -+ -+var ErrUnknownIssuer error = unknownIssuerError(0) -+ -+type keyRevokedError int -+ -+func (keyRevokedError) Error() string { -+ return "openpgp: signature made by revoked key" -+} -+ -+var ErrKeyRevoked error = keyRevokedError(0) -+ -+type UnknownPacketTypeError uint8 -+ -+func (upte UnknownPacketTypeError) Error() string { -+ return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/keys.go b/ms_mod/golang.org/x/crypto/openpgp/keys.go -new file mode 100644 -index 00000000000000..d62f787e9d5a36 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/keys.go -@@ -0,0 +1,693 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package openpgp -+ -+import ( -+ "crypto/rsa" -+ "io" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+// PublicKeyType is the armor type for a PGP public key. -+var PublicKeyType = "PGP PUBLIC KEY BLOCK" -+ -+// PrivateKeyType is the armor type for a PGP private key. -+var PrivateKeyType = "PGP PRIVATE KEY BLOCK" -+ -+// An Entity represents the components of an OpenPGP key: a primary public key -+// (which must be a signing key), one or more identities claimed by that key, -+// and zero or more subkeys, which may be encryption keys. -+type Entity struct { -+ PrimaryKey *packet.PublicKey -+ PrivateKey *packet.PrivateKey -+ Identities map[string]*Identity // indexed by Identity.Name -+ Revocations []*packet.Signature -+ Subkeys []Subkey -+} -+ -+// An Identity represents an identity claimed by an Entity and zero or more -+// assertions by other entities about that claim. -+type Identity struct { -+ Name string // by convention, has the form "Full Name (comment) " -+ UserId *packet.UserId -+ SelfSignature *packet.Signature -+ Signatures []*packet.Signature -+} -+ -+// A Subkey is an additional public key in an Entity. Subkeys can be used for -+// encryption. -+type Subkey struct { -+ PublicKey *packet.PublicKey -+ PrivateKey *packet.PrivateKey -+ Sig *packet.Signature -+} -+ -+// A Key identifies a specific public key in an Entity. This is either the -+// Entity's primary key or a subkey. -+type Key struct { -+ Entity *Entity -+ PublicKey *packet.PublicKey -+ PrivateKey *packet.PrivateKey -+ SelfSignature *packet.Signature -+} -+ -+// A KeyRing provides access to public and private keys. -+type KeyRing interface { -+ // KeysById returns the set of keys that have the given key id. -+ KeysById(id uint64) []Key -+ // KeysByIdUsage returns the set of keys with the given id -+ // that also meet the key usage given by requiredUsage. -+ // The requiredUsage is expressed as the bitwise-OR of -+ // packet.KeyFlag* values. -+ KeysByIdUsage(id uint64, requiredUsage byte) []Key -+ // DecryptionKeys returns all private keys that are valid for -+ // decryption. -+ DecryptionKeys() []Key -+} -+ -+// primaryIdentity returns the Identity marked as primary or the first identity -+// if none are so marked. -+func (e *Entity) primaryIdentity() *Identity { -+ var firstIdentity *Identity -+ for _, ident := range e.Identities { -+ if firstIdentity == nil { -+ firstIdentity = ident -+ } -+ if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { -+ return ident -+ } -+ } -+ return firstIdentity -+} -+ -+// encryptionKey returns the best candidate Key for encrypting a message to the -+// given Entity. -+func (e *Entity) encryptionKey(now time.Time) (Key, bool) { -+ candidateSubkey := -1 -+ -+ // Iterate the keys to find the newest key -+ var maxTime time.Time -+ for i, subkey := range e.Subkeys { -+ if subkey.Sig.FlagsValid && -+ subkey.Sig.FlagEncryptCommunications && -+ subkey.PublicKey.PubKeyAlgo.CanEncrypt() && -+ !subkey.Sig.KeyExpired(now) && -+ (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { -+ candidateSubkey = i -+ maxTime = subkey.Sig.CreationTime -+ } -+ } -+ -+ if candidateSubkey != -1 { -+ subkey := e.Subkeys[candidateSubkey] -+ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true -+ } -+ -+ // If we don't have any candidate subkeys for encryption and -+ // the primary key doesn't have any usage metadata then we -+ // assume that the primary key is ok. Or, if the primary key is -+ // marked as ok to encrypt to, then we can obviously use it. -+ i := e.primaryIdentity() -+ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && -+ e.PrimaryKey.PubKeyAlgo.CanEncrypt() && -+ !i.SelfSignature.KeyExpired(now) { -+ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true -+ } -+ -+ // This Entity appears to be signing only. -+ return Key{}, false -+} -+ -+// signingKey return the best candidate Key for signing a message with this -+// Entity. -+func (e *Entity) signingKey(now time.Time) (Key, bool) { -+ candidateSubkey := -1 -+ -+ for i, subkey := range e.Subkeys { -+ if subkey.Sig.FlagsValid && -+ subkey.Sig.FlagSign && -+ subkey.PublicKey.PubKeyAlgo.CanSign() && -+ !subkey.Sig.KeyExpired(now) { -+ candidateSubkey = i -+ break -+ } -+ } -+ -+ if candidateSubkey != -1 { -+ subkey := e.Subkeys[candidateSubkey] -+ return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true -+ } -+ -+ // If we have no candidate subkey then we assume that it's ok to sign -+ // with the primary key. -+ i := e.primaryIdentity() -+ if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && -+ !i.SelfSignature.KeyExpired(now) { -+ return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true -+ } -+ -+ return Key{}, false -+} -+ -+// An EntityList contains one or more Entities. -+type EntityList []*Entity -+ -+// KeysById returns the set of keys that have the given key id. -+func (el EntityList) KeysById(id uint64) (keys []Key) { -+ for _, e := range el { -+ if e.PrimaryKey.KeyId == id { -+ var selfSig *packet.Signature -+ for _, ident := range e.Identities { -+ if selfSig == nil { -+ selfSig = ident.SelfSignature -+ } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { -+ selfSig = ident.SelfSignature -+ break -+ } -+ } -+ keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) -+ } -+ -+ for _, subKey := range e.Subkeys { -+ if subKey.PublicKey.KeyId == id { -+ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) -+ } -+ } -+ } -+ return -+} -+ -+// KeysByIdUsage returns the set of keys with the given id that also meet -+// the key usage given by requiredUsage. The requiredUsage is expressed as -+// the bitwise-OR of packet.KeyFlag* values. -+func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { -+ for _, key := range el.KeysById(id) { -+ if len(key.Entity.Revocations) > 0 { -+ continue -+ } -+ -+ if key.SelfSignature.RevocationReason != nil { -+ continue -+ } -+ -+ if key.SelfSignature.FlagsValid && requiredUsage != 0 { -+ var usage byte -+ if key.SelfSignature.FlagCertify { -+ usage |= packet.KeyFlagCertify -+ } -+ if key.SelfSignature.FlagSign { -+ usage |= packet.KeyFlagSign -+ } -+ if key.SelfSignature.FlagEncryptCommunications { -+ usage |= packet.KeyFlagEncryptCommunications -+ } -+ if key.SelfSignature.FlagEncryptStorage { -+ usage |= packet.KeyFlagEncryptStorage -+ } -+ if usage&requiredUsage != requiredUsage { -+ continue -+ } -+ } -+ -+ keys = append(keys, key) -+ } -+ return -+} -+ -+// DecryptionKeys returns all private keys that are valid for decryption. -+func (el EntityList) DecryptionKeys() (keys []Key) { -+ for _, e := range el { -+ for _, subKey := range e.Subkeys { -+ if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { -+ keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) -+ } -+ } -+ } -+ return -+} -+ -+// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. -+func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { -+ block, err := armor.Decode(r) -+ if err == io.EOF { -+ return nil, errors.InvalidArgumentError("no armored data found") -+ } -+ if err != nil { -+ return nil, err -+ } -+ if block.Type != PublicKeyType && block.Type != PrivateKeyType { -+ return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) -+ } -+ -+ return ReadKeyRing(block.Body) -+} -+ -+// ReadKeyRing reads one or more public/private keys. Unsupported keys are -+// ignored as long as at least a single valid key is found. -+func ReadKeyRing(r io.Reader) (el EntityList, err error) { -+ packets := packet.NewReader(r) -+ var lastUnsupportedError error -+ -+ for { -+ var e *Entity -+ e, err = ReadEntity(packets) -+ if err != nil { -+ // TODO: warn about skipped unsupported/unreadable keys -+ if _, ok := err.(errors.UnsupportedError); ok { -+ lastUnsupportedError = err -+ err = readToNextPublicKey(packets) -+ } else if _, ok := err.(errors.StructuralError); ok { -+ // Skip unreadable, badly-formatted keys -+ lastUnsupportedError = err -+ err = readToNextPublicKey(packets) -+ } -+ if err == io.EOF { -+ err = nil -+ break -+ } -+ if err != nil { -+ el = nil -+ break -+ } -+ } else { -+ el = append(el, e) -+ } -+ } -+ -+ if len(el) == 0 && err == nil { -+ err = lastUnsupportedError -+ } -+ return -+} -+ -+// readToNextPublicKey reads packets until the start of the entity and leaves -+// the first packet of the new entity in the Reader. -+func readToNextPublicKey(packets *packet.Reader) (err error) { -+ var p packet.Packet -+ for { -+ p, err = packets.Next() -+ if err == io.EOF { -+ return -+ } else if err != nil { -+ if _, ok := err.(errors.UnsupportedError); ok { -+ err = nil -+ continue -+ } -+ return -+ } -+ -+ if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { -+ packets.Unread(p) -+ return -+ } -+ } -+} -+ -+// ReadEntity reads an entity (public key, identities, subkeys etc) from the -+// given Reader. -+func ReadEntity(packets *packet.Reader) (*Entity, error) { -+ e := new(Entity) -+ e.Identities = make(map[string]*Identity) -+ -+ p, err := packets.Next() -+ if err != nil { -+ return nil, err -+ } -+ -+ var ok bool -+ if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { -+ if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { -+ packets.Unread(p) -+ return nil, errors.StructuralError("first packet was not a public/private key") -+ } -+ e.PrimaryKey = &e.PrivateKey.PublicKey -+ } -+ -+ if !e.PrimaryKey.PubKeyAlgo.CanSign() { -+ return nil, errors.StructuralError("primary key cannot be used for signatures") -+ } -+ -+ var revocations []*packet.Signature -+EachPacket: -+ for { -+ p, err := packets.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ return nil, err -+ } -+ -+ switch pkt := p.(type) { -+ case *packet.UserId: -+ if err := addUserID(e, packets, pkt); err != nil { -+ return nil, err -+ } -+ case *packet.Signature: -+ if pkt.SigType == packet.SigTypeKeyRevocation { -+ revocations = append(revocations, pkt) -+ } else if pkt.SigType == packet.SigTypeDirectSignature { -+ // TODO: RFC4880 5.2.1 permits signatures -+ // directly on keys (eg. to bind additional -+ // revocation keys). -+ } -+ // Else, ignoring the signature as it does not follow anything -+ // we would know to attach it to. -+ case *packet.PrivateKey: -+ if pkt.IsSubkey == false { -+ packets.Unread(p) -+ break EachPacket -+ } -+ err = addSubkey(e, packets, &pkt.PublicKey, pkt) -+ if err != nil { -+ return nil, err -+ } -+ case *packet.PublicKey: -+ if pkt.IsSubkey == false { -+ packets.Unread(p) -+ break EachPacket -+ } -+ err = addSubkey(e, packets, pkt, nil) -+ if err != nil { -+ return nil, err -+ } -+ default: -+ // we ignore unknown packets -+ } -+ } -+ -+ if len(e.Identities) == 0 { -+ return nil, errors.StructuralError("entity without any identities") -+ } -+ -+ for _, revocation := range revocations { -+ err = e.PrimaryKey.VerifyRevocationSignature(revocation) -+ if err == nil { -+ e.Revocations = append(e.Revocations, revocation) -+ } else { -+ // TODO: RFC 4880 5.2.3.15 defines revocation keys. -+ return nil, errors.StructuralError("revocation signature signed by alternate key") -+ } -+ } -+ -+ return e, nil -+} -+ -+func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { -+ // Make a new Identity object, that we might wind up throwing away. -+ // We'll only add it if we get a valid self-signature over this -+ // userID. -+ identity := new(Identity) -+ identity.Name = pkt.Id -+ identity.UserId = pkt -+ -+ for { -+ p, err := packets.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ return err -+ } -+ -+ sig, ok := p.(*packet.Signature) -+ if !ok { -+ packets.Unread(p) -+ break -+ } -+ -+ if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { -+ if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { -+ return errors.StructuralError("user ID self-signature invalid: " + err.Error()) -+ } -+ identity.SelfSignature = sig -+ e.Identities[pkt.Id] = identity -+ } else { -+ identity.Signatures = append(identity.Signatures, sig) -+ } -+ } -+ -+ return nil -+} -+ -+func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { -+ var subKey Subkey -+ subKey.PublicKey = pub -+ subKey.PrivateKey = priv -+ -+ for { -+ p, err := packets.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ return errors.StructuralError("subkey signature invalid: " + err.Error()) -+ } -+ -+ sig, ok := p.(*packet.Signature) -+ if !ok { -+ packets.Unread(p) -+ break -+ } -+ -+ if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation { -+ return errors.StructuralError("subkey signature with wrong type") -+ } -+ -+ if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil { -+ return errors.StructuralError("subkey signature invalid: " + err.Error()) -+ } -+ -+ switch sig.SigType { -+ case packet.SigTypeSubkeyRevocation: -+ subKey.Sig = sig -+ case packet.SigTypeSubkeyBinding: -+ -+ if shouldReplaceSubkeySig(subKey.Sig, sig) { -+ subKey.Sig = sig -+ } -+ } -+ } -+ -+ if subKey.Sig == nil { -+ return errors.StructuralError("subkey packet not followed by signature") -+ } -+ -+ e.Subkeys = append(e.Subkeys, subKey) -+ -+ return nil -+} -+ -+func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool { -+ if potentialNewSig == nil { -+ return false -+ } -+ -+ if existingSig == nil { -+ return true -+ } -+ -+ if existingSig.SigType == packet.SigTypeSubkeyRevocation { -+ return false // never override a revocation signature -+ } -+ -+ return potentialNewSig.CreationTime.After(existingSig.CreationTime) -+} -+ -+const defaultRSAKeyBits = 2048 -+ -+// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a -+// single identity composed of the given full name, comment and email, any of -+// which may be empty but must not contain any of "()<>\x00". -+// If config is nil, sensible defaults will be used. -+func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { -+ creationTime := config.Now() -+ -+ bits := defaultRSAKeyBits -+ if config != nil && config.RSABits != 0 { -+ bits = config.RSABits -+ } -+ -+ uid := packet.NewUserId(name, comment, email) -+ if uid == nil { -+ return nil, errors.InvalidArgumentError("user id field contained invalid characters") -+ } -+ signingPriv, err := rsa.GenerateKey(config.Random(), bits) -+ if err != nil { -+ return nil, err -+ } -+ encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) -+ if err != nil { -+ return nil, err -+ } -+ -+ e := &Entity{ -+ PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey), -+ PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv), -+ Identities: make(map[string]*Identity), -+ } -+ isPrimaryId := true -+ e.Identities[uid.Id] = &Identity{ -+ Name: uid.Id, -+ UserId: uid, -+ SelfSignature: &packet.Signature{ -+ CreationTime: creationTime, -+ SigType: packet.SigTypePositiveCert, -+ PubKeyAlgo: packet.PubKeyAlgoRSA, -+ Hash: config.Hash(), -+ IsPrimaryId: &isPrimaryId, -+ FlagsValid: true, -+ FlagSign: true, -+ FlagCertify: true, -+ IssuerKeyId: &e.PrimaryKey.KeyId, -+ }, -+ } -+ err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) -+ if err != nil { -+ return nil, err -+ } -+ -+ // If the user passes in a DefaultHash via packet.Config, -+ // set the PreferredHash for the SelfSignature. -+ if config != nil && config.DefaultHash != 0 { -+ e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} -+ } -+ -+ // Likewise for DefaultCipher. -+ if config != nil && config.DefaultCipher != 0 { -+ e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} -+ } -+ -+ e.Subkeys = make([]Subkey, 1) -+ e.Subkeys[0] = Subkey{ -+ PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey), -+ PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv), -+ Sig: &packet.Signature{ -+ CreationTime: creationTime, -+ SigType: packet.SigTypeSubkeyBinding, -+ PubKeyAlgo: packet.PubKeyAlgoRSA, -+ Hash: config.Hash(), -+ FlagsValid: true, -+ FlagEncryptStorage: true, -+ FlagEncryptCommunications: true, -+ IssuerKeyId: &e.PrimaryKey.KeyId, -+ }, -+ } -+ e.Subkeys[0].PublicKey.IsSubkey = true -+ e.Subkeys[0].PrivateKey.IsSubkey = true -+ err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) -+ if err != nil { -+ return nil, err -+ } -+ return e, nil -+} -+ -+// SerializePrivate serializes an Entity, including private key material, but -+// excluding signatures from other entities, to the given Writer. -+// Identities and subkeys are re-signed in case they changed since NewEntry. -+// If config is nil, sensible defaults will be used. -+func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { -+ err = e.PrivateKey.Serialize(w) -+ if err != nil { -+ return -+ } -+ for _, ident := range e.Identities { -+ err = ident.UserId.Serialize(w) -+ if err != nil { -+ return -+ } -+ err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) -+ if err != nil { -+ return -+ } -+ err = ident.SelfSignature.Serialize(w) -+ if err != nil { -+ return -+ } -+ } -+ for _, subkey := range e.Subkeys { -+ err = subkey.PrivateKey.Serialize(w) -+ if err != nil { -+ return -+ } -+ err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) -+ if err != nil { -+ return -+ } -+ err = subkey.Sig.Serialize(w) -+ if err != nil { -+ return -+ } -+ } -+ return nil -+} -+ -+// Serialize writes the public part of the given Entity to w, including -+// signatures from other entities. No private key material will be output. -+func (e *Entity) Serialize(w io.Writer) error { -+ err := e.PrimaryKey.Serialize(w) -+ if err != nil { -+ return err -+ } -+ for _, ident := range e.Identities { -+ err = ident.UserId.Serialize(w) -+ if err != nil { -+ return err -+ } -+ err = ident.SelfSignature.Serialize(w) -+ if err != nil { -+ return err -+ } -+ for _, sig := range ident.Signatures { -+ err = sig.Serialize(w) -+ if err != nil { -+ return err -+ } -+ } -+ } -+ for _, subkey := range e.Subkeys { -+ err = subkey.PublicKey.Serialize(w) -+ if err != nil { -+ return err -+ } -+ err = subkey.Sig.Serialize(w) -+ if err != nil { -+ return err -+ } -+ } -+ return nil -+} -+ -+// SignIdentity adds a signature to e, from signer, attesting that identity is -+// associated with e. The provided identity must already be an element of -+// e.Identities and the private key of signer must have been decrypted if -+// necessary. -+// If config is nil, sensible defaults will be used. -+func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { -+ if signer.PrivateKey == nil { -+ return errors.InvalidArgumentError("signing Entity must have a private key") -+ } -+ if signer.PrivateKey.Encrypted { -+ return errors.InvalidArgumentError("signing Entity's private key must be decrypted") -+ } -+ ident, ok := e.Identities[identity] -+ if !ok { -+ return errors.InvalidArgumentError("given identity string not found in Entity") -+ } -+ -+ sig := &packet.Signature{ -+ SigType: packet.SigTypeGenericCert, -+ PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, -+ Hash: config.Hash(), -+ CreationTime: config.Now(), -+ IssuerKeyId: &signer.PrivateKey.KeyId, -+ } -+ if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { -+ return err -+ } -+ ident.Signatures = append(ident.Signatures, sig) -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go b/ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go -new file mode 100644 -index 00000000000000..7779bd97748f4b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/keys_data_test.go -@@ -0,0 +1,200 @@ -+package openpgp -+ -+const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" -+const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" -+const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" -+const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" -+ -+const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+Charset: UTF-8 -+ -+mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY -+ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG -+zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 -+QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ -+QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo -+9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu -+Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ -+dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R -+JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL -+ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew -+RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW -+/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu -+yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv -+2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR -+bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL -+C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP -+WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y -+MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA -+EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ -+MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N -+1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm -++ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N -+lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW -+CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF -+4artDmrG -+=7FfJ -+-----END PGP PUBLIC KEY BLOCK-----` -+ -+const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+ -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 -+6LCg2mg= -+=Dhm4 -+-----END PGP PUBLIC KEY BLOCK-----` -+ -+const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+Version: GnuPG v1 -+ -+mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo -+7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom -+lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0 -+E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC -+CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw -+6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH -+7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv -+X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7 -+GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl -+y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw -+R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW -+CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+ -+LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO -+aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx -+yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl -+BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr -+Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK -+CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp -+C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ -+SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ -+MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= -+=vtbN -+-----END PGP PUBLIC KEY BLOCK-----` -+ -+const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+ -+mQENBFsgO5EBCADhREPmcjsPkXe1z7ctvyWL0S7oa9JaoGZ9oPDHFDlQxd0qlX2e -+DZJZDg0qYvVixmaULIulApq1puEsaJCn3lHUbHlb4PYKwLEywYXM28JN91KtLsz/ -+uaEX2KC5WqeP40utmzkNLq+oRX/xnRMgwbO7yUNVG2UlEa6eI+xOXO3YtLdmJMBW -+ClQ066ZnOIzEo1JxnIwha1CDBMWLLfOLrg6l8InUqaXbtEBbnaIYO6fXVXELUjkx -+nmk7t/QOk0tXCy8muH9UDqJkwDUESY2l79XwBAcx9riX8vY7vwC34pm22fAUVLCJ -+x1SJx0J8bkeNp38jKM2Zd9SUQqSbfBopQ4pPABEBAAG0I0dvbGFuZyBHb3BoZXIg -+PG5vLXJlcGx5QGdvbGFuZy5jb20+iQFUBBMBCgA+FiEE5Ik5JLcNx6l6rZfw1oFy -+9I6cUoMFAlsgO5ECGwMFCQPCZwAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ -+1oFy9I6cUoMIkwf8DNPeD23i4jRwd/pylbvxwZintZl1fSwTJW1xcOa1emXaEtX2 -+depuqhP04fjlRQGfsYAQh7X9jOJxAHjTmhqFBi5sD7QvKU00cPFYbJ/JTx0B41bl -+aXnSbGhRPh63QtEZL7ACAs+shwvvojJqysx7kyVRu0EW2wqjXdHwR/SJO6nhNBa2 -+DXzSiOU/SUA42mmG+5kjF8Aabq9wPwT9wjraHShEweNerNMmOqJExBOy3yFeyDpa -+XwEZFzBfOKoxFNkIaVf5GSdIUGhFECkGvBMB935khftmgR8APxdU4BE7XrXexFJU -+8RCuPXonm4WQOwTWR0vQg64pb2WKAzZ8HhwTGbQiR29sYW5nIEdvcGhlciA8cmV2 -+b2tlZEBnb2xhbmcuY29tPokBNgQwAQoAIBYhBOSJOSS3Dcepeq2X8NaBcvSOnFKD -+BQJbIDv3Ah0AAAoJENaBcvSOnFKDfWMIAKhI/Tvu3h8fSUxp/gSAcduT6bC1JttG -+0lYQ5ilKB/58lBUA5CO3ZrKDKlzW3M8VEcvohVaqeTMKeoQd5rCZq8KxHn/KvN6N -+s85REfXfniCKfAbnGgVXX3kDmZ1g63pkxrFu0fDZjVDXC6vy+I0sGyI/Inro0Pzb -+tvn0QCsxjapKK15BtmSrpgHgzVqVg0cUp8vqZeKFxarYbYB2idtGRci4b9tObOK0 -+BSTVFy26+I/mrFGaPrySYiy2Kz5NMEcRhjmTxJ8jSwEr2O2sUR0yjbgUAXbTxDVE -+/jg5fQZ1ACvBRQnB7LvMHcInbzjyeTM3FazkkSYQD6b97+dkWwb1iWG5AQ0EWyA7 -+kQEIALkg04REDZo1JgdYV4x8HJKFS4xAYWbIva1ZPqvDNmZRUbQZR2+gpJGEwn7z -+VofGvnOYiGW56AS5j31SFf5kro1+1bZQ5iOONBng08OOo58/l1hRseIIVGB5TGSa -+PCdChKKHreJI6hS3mShxH6hdfFtiZuB45rwoaArMMsYcjaezLwKeLc396cpUwwcZ -+snLUNd1Xu5EWEF2OdFkZ2a1qYdxBvAYdQf4+1Nr+NRIx1u1NS9c8jp3PuMOkrQEi -+bNtc1v6v0Jy52mKLG4y7mC/erIkvkQBYJdxPaP7LZVaPYc3/xskcyijrJ/5ufoD8 -+K71/ShtsZUXSQn9jlRaYR0EbojMAEQEAAYkBPAQYAQoAJhYhBOSJOSS3Dcepeq2X -+8NaBcvSOnFKDBQJbIDuRAhsMBQkDwmcAAAoJENaBcvSOnFKDkFMIAIt64bVZ8x7+ -+TitH1bR4pgcNkaKmgKoZz6FXu80+SnbuEt2NnDyf1cLOSimSTILpwLIuv9Uft5Pb -+OraQbYt3xi9yrqdKqGLv80bxqK0NuryNkvh9yyx5WoG1iKqMj9/FjGghuPrRaT4l -+QinNAghGVkEy1+aXGFrG2DsOC1FFI51CC2WVTzZ5RwR2GpiNRfESsU1rZAUqf/2V -+yJl9bD5R4SUNy8oQmhOxi+gbhD4Ao34e4W0ilibslI/uawvCiOwlu5NGd8zv5n+U -+heiQvzkApQup5c+BhH5zFDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB -+7qTZOahrETw= -+=IKnw -+-----END PGP PUBLIC KEY BLOCK-----` -+ -+const keyWithSubKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+ -+mI0EWyKwKQEEALwXhKBnyaaNFeK3ljfc/qn9X/QFw+28EUfgZPHjRmHubuXLE2uR -+s3ZoSXY2z7Dkv+NyHYMt8p+X8q5fR7JvUjK2XbPyKoiJVnHINll83yl67DaWfKNL -+EjNoO0kIfbXfCkZ7EG6DL+iKtuxniGTcnGT47e+HJSqb/STpLMnWwXjBABEBAAG0 -+I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQQ/ -+lRafP/p9PytHbwxMvYJsOQdOOAUCWyKwKQIbAwULCQgHAwUVCgkICwUWAgMBAAIe -+AQIXgAAKCRBMvYJsOQdOOOsFBAC62mXww8XuqvYLcVOvHkWLT6mhxrQOJXnlfpn7 -+2uBV9CMhoG/Ycd43NONsJrB95Apr9TDIqWnVszNbqPCuBhZQSGLdbiDKjxnCWBk0 -+69qv4RNtkpOhYB7jK4s8F5oQZqId6JasT/PmJTH92mhBYhhTQr0GYFuPX2UJdkw9 -+Sn9C67iNBFsisDUBBAC3A+Yo9lgCnxi/pfskyLrweYif6kIXWLAtLTsM6g/6jt7b -+wTrknuCPyTv0QKGXsAEe/cK/Xq3HvX9WfXPGIHc/X56ZIsHQ+RLowbZV/Lhok1IW -+FAuQm8axr/by80cRwFnzhfPc/ukkAq2Qyj4hLsGblu6mxeAhzcp8aqmWOO2H9QAR -+AQABiLYEKAEKACAWIQQ/lRafP/p9PytHbwxMvYJsOQdOOAUCWyK16gIdAAAKCRBM -+vYJsOQdOOB1vA/4u4uLONsE+2GVOyBsHyy7uTdkuxaR9b54A/cz6jT/tzUbeIzgx -+22neWhgvIEghnUZd0vEyK9k1wy5vbDlEo6nKzHso32N1QExGr5upRERAxweDxGOj -+7luDwNypI7QcifE64lS/JmlnunwRCdRWMKc0Fp+7jtRc5mpwyHN/Suf5RokBagQY -+AQoAIBYhBD+VFp8/+n0/K0dvDEy9gmw5B044BQJbIrA1AhsCAL8JEEy9gmw5B044 -+tCAEGQEKAB0WIQSNdnkaWY6t62iX336UXbGvYdhXJwUCWyKwNQAKCRCUXbGvYdhX -+JxJSA/9fCPHP6sUtGF1o3G1a3yvOUDGr1JWcct9U+QpbCt1mZoNopCNDDQAJvDWl -+mvDgHfuogmgNJRjOMznvahbF+wpTXmB7LS0SK412gJzl1fFIpK4bgnhu0TwxNsO1 -+8UkCZWqxRMgcNUn9z6XWONK8dgt5JNvHSHrwF4CxxwjL23AAtK+FA/UUoi3U4kbC -+0XnSr1Sl+mrzQi1+H7xyMe7zjqe+gGANtskqexHzwWPUJCPZ5qpIa2l8ghiUim6b -+4ymJ+N8/T8Yva1FaPEqfMzzqJr8McYFm0URioXJPvOAlRxdHPteZ0qUopt/Jawxl -+Xt6B9h1YpeLoJwjwsvbi98UTRs0jXwoY -+=3fWu -+-----END PGP PUBLIC KEY BLOCK-----` -+ -+const keyWithSubKeyAndBadSelfSigOrder = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+ -+mI0EWyLLDQEEAOqIOpJ/ha1OYAGduu9tS3rBz5vyjbNgJO4sFveEM0mgsHQ0X9/L -+plonW+d0gRoO1dhJ8QICjDAc6+cna1DE3tEb5m6JtQ30teLZuqrR398Cf6w7NNVz -+r3lrlmnH9JaKRuXl7tZciwyovneBfZVCdtsRZjaLI1uMQCz/BToiYe3DABEBAAG0 -+I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQRZ -+sixZOfQcZdW0wUqmgmdsv1O9xgUCWyLLDQIbAwULCQgHAwUVCgkICwUWAgMBAAIe -+AQIXgAAKCRCmgmdsv1O9xql2A/4pix98NxjhdsXtazA9agpAKeADf9tG4Za27Gj+ -+3DCww/E4iP2X35jZimSm/30QRB6j08uGCqd9vXkkJxtOt63y/IpVOtWX6vMWSTUm -+k8xKkaYMP0/IzKNJ1qC/qYEUYpwERBKg9Z+k99E2Ql4kRHdxXUHq6OzY79H18Y+s -+GdeM/riNBFsiyxsBBAC54Pxg/8ZWaZX1phGdwfe5mek27SOYpC0AxIDCSOdMeQ6G -+HPk38pywl1d+S+KmF/F4Tdi+kWro62O4eG2uc/T8JQuRDUhSjX0Qa51gPzJrUOVT -+CFyUkiZ/3ZDhtXkgfuso8ua2ChBgR9Ngr4v43tSqa9y6AK7v0qjxD1x+xMrjXQAR -+AQABiQFxBBgBCgAmAhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsizTIFCQAN -+MRcAv7QgBBkBCgAdFiEEJcoVUVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62j -+UpRPICQq5gQApoWIigZxXFoM0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBS -+YnjyA4+n1D+zB2VqliD2QrsX12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZs -+nRJmXV+bsvD4sidLZLjdwOVa3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/ -+U73GGi0D/i20VW8AWYAPACm2zMlzExKTOAV01YTQH/3vW0WLrOse53WcIVZga6es -+HuO4So0SOEAvxKMe5HpRIu2dJxTvd99Bo9xk9xJU0AoFrO0vNCRnL+5y68xMlODK -+lEw5/kl0jeaTBp6xX0HDQOEVOpPGUwWV4Ij2EnvfNDXaE1vK1kffiQFrBBgBCgAg -+AhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsi0AYAv7QgBBkBCgAdFiEEJcoV -+UVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62jUpRPICQq5gQApoWIigZxXFoM -+0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBSYnjyA4+n1D+zB2VqliD2QrsX -+12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZsnRJmXV+bsvD4sidLZLjdwOVa -+3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/U73GRl0EAJokkXmy4zKDHWWi -+wvK9gi2gQgRkVnu2AiONxJb5vjeLhM/07BRmH6K1o+w3fOeEQp4FjXj1eQ5fPSM6 -+Hhwx2CTl9SDnPSBMiKXsEFRkmwQ2AAsQZLmQZvKBkLZYeBiwf+IY621eYDhZfo+G -+1dh1WoUCyREZsJQg2YoIpWIcvw+a -+=bNRo -+-----END PGP PUBLIC KEY BLOCK----- -+` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/keys_test.go b/ms_mod/golang.org/x/crypto/openpgp/keys_test.go -new file mode 100644 -index 00000000000000..0eb1a9ef29704e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/keys_test.go -@@ -0,0 +1,495 @@ -+package openpgp -+ -+import ( -+ "bytes" -+ "crypto" -+ "strings" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+func TestKeyExpiry(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(expiringKeyHex)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ entity := kring[0] -+ -+ const timeFormat = "2006-01-02" -+ time1, _ := time.Parse(timeFormat, "2013-07-01") -+ -+ // The expiringKeyHex key is structured as: -+ // -+ // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC -+ // sub 1024R/1ABB25A0 created: 2013-07-01 23:11:07 +0200 CEST expires: 2013-07-08 usage: E -+ // sub 1024R/96A672F5 created: 2013-07-01 23:11:23 +0200 CEST expires: 2013-07-31 usage: E -+ // -+ // So this should select the newest, non-expired encryption key. -+ key, _ := entity.encryptionKey(time1) -+ if id, expected := key.PublicKey.KeyIdShortString(), "96A672F5"; id != expected { -+ t.Errorf("Expected key %s at time %s, but got key %s", expected, time1.Format(timeFormat), id) -+ } -+ -+ // Once the first encryption subkey has expired, the second should be -+ // selected. -+ time2, _ := time.Parse(timeFormat, "2013-07-09") -+ key, _ = entity.encryptionKey(time2) -+ if id, expected := key.PublicKey.KeyIdShortString(), "96A672F5"; id != expected { -+ t.Errorf("Expected key %s at time %s, but got key %s", expected, time2.Format(timeFormat), id) -+ } -+ -+ // Once all the keys have expired, nothing should be returned. -+ time3, _ := time.Parse(timeFormat, "2013-08-01") -+ if key, ok := entity.encryptionKey(time3); ok { -+ t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString()) -+ } -+} -+ -+func TestMissingCrossSignature(t *testing.T) { -+ // This public key has a signing subkey, but the subkey does not -+ // contain a cross-signature. -+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(missingCrossSignatureKey)) -+ if len(keys) != 0 { -+ t.Errorf("Accepted key with missing cross signature") -+ } -+ if err == nil { -+ t.Fatal("Failed to detect error in keyring with missing cross signature") -+ } -+ structural, ok := err.(errors.StructuralError) -+ if !ok { -+ t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) -+ } -+ const expectedMsg = "signing subkey is missing cross-signature" -+ if !strings.Contains(string(structural), expectedMsg) { -+ t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) -+ } -+} -+ -+func TestInvalidCrossSignature(t *testing.T) { -+ // This public key has a signing subkey, and the subkey has an -+ // embedded cross-signature. However, the cross-signature does -+ // not correctly validate over the primary and subkey. -+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(invalidCrossSignatureKey)) -+ if len(keys) != 0 { -+ t.Errorf("Accepted key with invalid cross signature") -+ } -+ if err == nil { -+ t.Fatal("Failed to detect error in keyring with an invalid cross signature") -+ } -+ structural, ok := err.(errors.StructuralError) -+ if !ok { -+ t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) -+ } -+ const expectedMsg = "subkey signature invalid" -+ if !strings.Contains(string(structural), expectedMsg) { -+ t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) -+ } -+} -+ -+func TestGoodCrossSignature(t *testing.T) { -+ // This public key has a signing subkey, and the subkey has an -+ // embedded cross-signature which correctly validates over the -+ // primary and subkey. -+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(goodCrossSignatureKey)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if len(keys) != 1 { -+ t.Errorf("Failed to accept key with good cross signature, %d", len(keys)) -+ } -+ if len(keys[0].Subkeys) != 1 { -+ t.Errorf("Failed to accept good subkey, %d", len(keys[0].Subkeys)) -+ } -+} -+ -+func TestRevokedUserID(t *testing.T) { -+ // This key contains 2 UIDs, one of which is revoked: -+ // [ultimate] (1) Golang Gopher -+ // [ revoked] (2) Golang Gopher -+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(revokedUserIDKey)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if len(keys) != 1 { -+ t.Fatal("Failed to read key with a revoked user id") -+ } -+ -+ var identities []*Identity -+ for _, identity := range keys[0].Identities { -+ identities = append(identities, identity) -+ } -+ -+ if numIdentities, numExpected := len(identities), 1; numIdentities != numExpected { -+ t.Errorf("obtained %d identities, expected %d", numIdentities, numExpected) -+ } -+ -+ if identityName, expectedName := identities[0].Name, "Golang Gopher "; identityName != expectedName { -+ t.Errorf("obtained identity %s expected %s", identityName, expectedName) -+ } -+} -+ -+// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. -+func TestExternallyRevocableKey(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C -+ // according to this signature that appears within the key: -+ // :signature packet: algo 1, keyid A42704B92866382A -+ // version 4, created 1396409682, md5len 0, sigclass 0x1f -+ // digest algo 2, begin of digest a9 84 -+ // hashed subpkt 2 len 4 (sig created 2014-04-02) -+ // hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C) -+ // hashed subpkt 7 len 1 (not revocable) -+ // subpkt 16 len 8 (issuer key ID A42704B92866382A) -+ // data: [1024 bits] -+ -+ id := uint64(0xA42704B92866382A) -+ keys := kring.KeysById(id) -+ if len(keys) != 1 { -+ t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys)) -+ } -+} -+ -+func TestKeyRevocation(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(revokedKeyHex)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // revokedKeyHex contains these keys: -+ // pub 1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25] -+ // sub 1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25] -+ ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60} -+ -+ for _, id := range ids { -+ keys := kring.KeysById(id) -+ if len(keys) != 1 { -+ t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys)) -+ } -+ keys = kring.KeysByIdUsage(id, 0) -+ if len(keys) != 0 { -+ t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys)) -+ } -+ } -+} -+ -+func TestKeyWithRevokedSubKey(t *testing.T) { -+ // This key contains a revoked sub key: -+ // pub rsa1024/0x4CBD826C39074E38 2018-06-14 [SC] -+ // Key fingerprint = 3F95 169F 3FFA 7D3F 2B47 6F0C 4CBD 826C 3907 4E38 -+ // uid Golang Gopher -+ // sub rsa1024/0x945DB1AF61D85727 2018-06-14 [S] [revoked: 2018-06-14] -+ -+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(keyWithSubKey)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if len(keys) != 1 { -+ t.Fatal("Failed to read key with a sub key") -+ } -+ -+ identity := keys[0].Identities["Golang Gopher "] -+ -+ // Test for an issue where Subkey Binding Signatures (RFC 4880 5.2.1) were added to the identity -+ // preceding the Subkey Packet if the Subkey Packet was followed by more than one signature. -+ // For example, the current key has the following layout: -+ // PUBKEY UID SELFSIG SUBKEY REV SELFSIG -+ // The last SELFSIG would be added to the UID's signatures. This is wrong. -+ if numIdentitySigs, numExpected := len(identity.Signatures), 0; numIdentitySigs != numExpected { -+ t.Fatalf("got %d identity signatures, expected %d", numIdentitySigs, numExpected) -+ } -+ -+ if numSubKeys, numExpected := len(keys[0].Subkeys), 1; numSubKeys != numExpected { -+ t.Fatalf("got %d subkeys, expected %d", numSubKeys, numExpected) -+ } -+ -+ subKey := keys[0].Subkeys[0] -+ if subKey.Sig == nil { -+ t.Fatalf("subkey signature is nil") -+ } -+ -+} -+ -+func TestSubkeyRevocation(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(revokedSubkeyHex)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // revokedSubkeyHex contains these keys: -+ // pub 1024R/4EF7E4BECCDE97F0 2014-03-25 -+ // sub 1024R/D63636E2B96AE423 2014-03-25 -+ // sub 1024D/DBCE4EE19529437F 2014-03-25 -+ // sub 1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25] -+ validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F} -+ revokedKey := uint64(0x677815E371C2FD23) -+ -+ for _, id := range validKeys { -+ keys := kring.KeysById(id) -+ if len(keys) != 1 { -+ t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys)) -+ } -+ keys = kring.KeysByIdUsage(id, 0) -+ if len(keys) != 1 { -+ t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys)) -+ } -+ } -+ -+ keys := kring.KeysById(revokedKey) -+ if len(keys) != 1 { -+ t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys)) -+ } -+ -+ keys = kring.KeysByIdUsage(revokedKey, 0) -+ if len(keys) != 0 { -+ t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys)) -+ } -+} -+ -+func TestKeyWithSubKeyAndBadSelfSigOrder(t *testing.T) { -+ // This key was altered so that the self signatures following the -+ // subkey are in a sub-optimal order. -+ // -+ // Note: Should someone have to create a similar key again, look into -+ // gpgsplit, gpg --dearmor, and gpg --enarmor. -+ // -+ // The packet ordering is the following: -+ // PUBKEY UID UIDSELFSIG SUBKEY SELFSIG1 SELFSIG2 -+ // -+ // Where: -+ // SELFSIG1 expires on 2018-06-14 and was created first -+ // SELFSIG2 does not expire and was created after SELFSIG1 -+ // -+ // Test for RFC 4880 5.2.3.3: -+ // > An implementation that encounters multiple self-signatures on the -+ // > same object may resolve the ambiguity in any way it sees fit, but it -+ // > is RECOMMENDED that priority be given to the most recent self- -+ // > signature. -+ // -+ // This means that we should keep SELFSIG2. -+ -+ keys, err := ReadArmoredKeyRing(bytes.NewBufferString(keyWithSubKeyAndBadSelfSigOrder)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if len(keys) != 1 { -+ t.Fatal("Failed to read key with a sub key and a bad selfsig packet order") -+ } -+ -+ key := keys[0] -+ -+ if numKeys, expected := len(key.Subkeys), 1; numKeys != expected { -+ t.Fatalf("Read %d subkeys, expected %d", numKeys, expected) -+ } -+ -+ subKey := key.Subkeys[0] -+ -+ if lifetime := subKey.Sig.KeyLifetimeSecs; lifetime != nil { -+ t.Errorf("The signature has a key lifetime (%d), but it should be nil", *lifetime) -+ } -+ -+} -+ -+func TestKeyUsage(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // subkeyUsageHex contains these keys: -+ // pub 1024R/2866382A created: 2014-04-01 expires: never usage: SC -+ // sub 1024R/936C9153 created: 2014-04-01 expires: never usage: E -+ // sub 1024R/64D5F5BB created: 2014-04-02 expires: never usage: E -+ // sub 1024D/BC0BA992 created: 2014-04-02 expires: never usage: S -+ certifiers := []uint64{0xA42704B92866382A} -+ signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992} -+ encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB} -+ -+ for _, id := range certifiers { -+ keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify) -+ if len(keys) == 1 { -+ if keys[0].PublicKey.KeyId != id { -+ t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId) -+ } -+ } else { -+ t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys)) -+ } -+ } -+ -+ for _, id := range signers { -+ keys := kring.KeysByIdUsage(id, packet.KeyFlagSign) -+ if len(keys) == 1 { -+ if keys[0].PublicKey.KeyId != id { -+ t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId) -+ } -+ } else { -+ t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys)) -+ } -+ -+ // This keyring contains no encryption keys that are also good for signing. -+ keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) -+ if len(keys) != 0 { -+ t.Errorf("Unexpected match for encryption key id %X", id) -+ } -+ } -+ -+ for _, id := range encrypters { -+ keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) -+ if len(keys) == 1 { -+ if keys[0].PublicKey.KeyId != id { -+ t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId) -+ } -+ } else { -+ t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys)) -+ } -+ -+ // This keyring contains no encryption keys that are also good for signing. -+ keys = kring.KeysByIdUsage(id, packet.KeyFlagSign) -+ if len(keys) != 0 { -+ t.Errorf("Unexpected match for signing key id %X", id) -+ } -+ } -+} -+ -+func TestIdVerification(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil { -+ t.Fatal(err) -+ } -+ -+ const identity = "Test Key 1 (RSA)" -+ if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil { -+ t.Fatal(err) -+ } -+ -+ ident, ok := kring[0].Identities[identity] -+ if !ok { -+ t.Fatal("identity missing from key after signing") -+ } -+ -+ checked := false -+ for _, sig := range ident.Signatures { -+ if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId { -+ continue -+ } -+ -+ if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil { -+ t.Fatalf("error verifying new identity signature: %s", err) -+ } -+ checked = true -+ break -+ } -+ -+ if !checked { -+ t.Fatal("didn't find identity signature in Entity") -+ } -+} -+ -+func TestNewEntityWithPreferredHash(t *testing.T) { -+ c := &packet.Config{ -+ DefaultHash: crypto.SHA256, -+ } -+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ for _, identity := range entity.Identities { -+ if len(identity.SelfSignature.PreferredHash) == 0 { -+ t.Fatal("didn't find a preferred hash in self signature") -+ } -+ ph := hashToHashId(c.DefaultHash) -+ if identity.SelfSignature.PreferredHash[0] != ph { -+ t.Fatalf("Expected preferred hash to be %d, got %d", ph, identity.SelfSignature.PreferredHash[0]) -+ } -+ } -+} -+ -+func TestNewEntityWithoutPreferredHash(t *testing.T) { -+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ for _, identity := range entity.Identities { -+ if len(identity.SelfSignature.PreferredHash) != 0 { -+ t.Fatalf("Expected preferred hash to be empty but got length %d", len(identity.SelfSignature.PreferredHash)) -+ } -+ } -+} -+ -+func TestNewEntityCorrectName(t *testing.T) { -+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if len(entity.Identities) != 1 { -+ t.Fatalf("len(entity.Identities) = %d, want 1", len(entity.Identities)) -+ } -+ var got string -+ for _, i := range entity.Identities { -+ got = i.Name -+ } -+ want := "Golang Gopher (Test Key) " -+ if got != want { -+ t.Fatalf("Identity.Name = %q, want %q", got, want) -+ } -+} -+ -+func TestNewEntityWithPreferredSymmetric(t *testing.T) { -+ c := &packet.Config{ -+ DefaultCipher: packet.CipherAES256, -+ } -+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ for _, identity := range entity.Identities { -+ if len(identity.SelfSignature.PreferredSymmetric) == 0 { -+ t.Fatal("didn't find a preferred cipher in self signature") -+ } -+ if identity.SelfSignature.PreferredSymmetric[0] != uint8(c.DefaultCipher) { -+ t.Fatalf("Expected preferred cipher to be %d, got %d", uint8(c.DefaultCipher), identity.SelfSignature.PreferredSymmetric[0]) -+ } -+ } -+} -+ -+func TestNewEntityWithoutPreferredSymmetric(t *testing.T) { -+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ for _, identity := range entity.Identities { -+ if len(identity.SelfSignature.PreferredSymmetric) != 0 { -+ t.Fatalf("Expected preferred cipher to be empty but got length %d", len(identity.SelfSignature.PreferredSymmetric)) -+ } -+ } -+} -+ -+func TestNewEntityPublicSerialization(t *testing.T) { -+ entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ serializedEntity := bytes.NewBuffer(nil) -+ entity.Serialize(serializedEntity) -+ -+ _, err = ReadEntity(packet.NewReader(bytes.NewBuffer(serializedEntity.Bytes()))) -+ if err != nil { -+ t.Fatal(err) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go -new file mode 100644 -index 00000000000000..353f945247cfdc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed.go -@@ -0,0 +1,123 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "compress/bzip2" -+ "compress/flate" -+ "compress/zlib" -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+ "strconv" -+) -+ -+// Compressed represents a compressed OpenPGP packet. The decompressed contents -+// will contain more OpenPGP packets. See RFC 4880, section 5.6. -+type Compressed struct { -+ Body io.Reader -+} -+ -+const ( -+ NoCompression = flate.NoCompression -+ BestSpeed = flate.BestSpeed -+ BestCompression = flate.BestCompression -+ DefaultCompression = flate.DefaultCompression -+) -+ -+// CompressionConfig contains compressor configuration settings. -+type CompressionConfig struct { -+ // Level is the compression level to use. It must be set to -+ // between -1 and 9, with -1 causing the compressor to use the -+ // default compression level, 0 causing the compressor to use -+ // no compression and 1 to 9 representing increasing (better, -+ // slower) compression levels. If Level is less than -1 or -+ // more then 9, a non-nil error will be returned during -+ // encryption. See the constants above for convenient common -+ // settings for Level. -+ Level int -+} -+ -+func (c *Compressed) parse(r io.Reader) error { -+ var buf [1]byte -+ _, err := readFull(r, buf[:]) -+ if err != nil { -+ return err -+ } -+ -+ switch buf[0] { -+ case 1: -+ c.Body = flate.NewReader(r) -+ case 2: -+ c.Body, err = zlib.NewReader(r) -+ case 3: -+ c.Body = bzip2.NewReader(r) -+ default: -+ err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) -+ } -+ -+ return err -+} -+ -+// compressedWriteCloser represents the serialized compression stream -+// header and the compressor. Its Close() method ensures that both the -+// compressor and serialized stream header are closed. Its Write() -+// method writes to the compressor. -+type compressedWriteCloser struct { -+ sh io.Closer // Stream Header -+ c io.WriteCloser // Compressor -+} -+ -+func (cwc compressedWriteCloser) Write(p []byte) (int, error) { -+ return cwc.c.Write(p) -+} -+ -+func (cwc compressedWriteCloser) Close() (err error) { -+ err = cwc.c.Close() -+ if err != nil { -+ return err -+ } -+ -+ return cwc.sh.Close() -+} -+ -+// SerializeCompressed serializes a compressed data packet to w and -+// returns a WriteCloser to which the literal data packets themselves -+// can be written and which MUST be closed on completion. If cc is -+// nil, sensible defaults will be used to configure the compression -+// algorithm. -+func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { -+ compressed, err := serializeStreamHeader(w, packetTypeCompressed) -+ if err != nil { -+ return -+ } -+ -+ _, err = compressed.Write([]byte{uint8(algo)}) -+ if err != nil { -+ return -+ } -+ -+ level := DefaultCompression -+ if cc != nil { -+ level = cc.Level -+ } -+ -+ var compressor io.WriteCloser -+ switch algo { -+ case CompressionZIP: -+ compressor, err = flate.NewWriter(compressed, level) -+ case CompressionZLIB: -+ compressor, err = zlib.NewWriterLevel(compressed, level) -+ default: -+ s := strconv.Itoa(int(algo)) -+ err = errors.UnsupportedError("Unsupported compression algorithm: " + s) -+ } -+ if err != nil { -+ return -+ } -+ -+ literaldata = compressedWriteCloser{compressed, compressor} -+ -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go -new file mode 100644 -index 00000000000000..37fcc0b097bebd ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/compressed_test.go -@@ -0,0 +1,40 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "io" -+ "testing" -+) -+ -+func TestCompressed(t *testing.T) { -+ packet, err := Read(readerFromHex(compressedHex)) -+ if err != nil { -+ t.Errorf("failed to read Compressed: %s", err) -+ return -+ } -+ -+ c, ok := packet.(*Compressed) -+ if !ok { -+ t.Error("didn't find Compressed packet") -+ return -+ } -+ -+ contents, err := io.ReadAll(c.Body) -+ if err != nil && err != io.EOF { -+ t.Error(err) -+ return -+ } -+ -+ expected, _ := hex.DecodeString(compressedExpectedHex) -+ if !bytes.Equal(expected, contents) { -+ t.Errorf("got:%x want:%x", contents, expected) -+ } -+} -+ -+const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700" -+const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a" -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/config.go b/ms_mod/golang.org/x/crypto/openpgp/packet/config.go -new file mode 100644 -index 00000000000000..c76eecc963acd2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/config.go -@@ -0,0 +1,91 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "crypto" -+ "crypto/rand" -+ "io" -+ "time" -+) -+ -+// Config collects a number of parameters along with sensible defaults. -+// A nil *Config is valid and results in all default values. -+type Config struct { -+ // Rand provides the source of entropy. -+ // If nil, the crypto/rand Reader is used. -+ Rand io.Reader -+ // DefaultHash is the default hash function to be used. -+ // If zero, SHA-256 is used. -+ DefaultHash crypto.Hash -+ // DefaultCipher is the cipher to be used. -+ // If zero, AES-128 is used. -+ DefaultCipher CipherFunction -+ // Time returns the current time as the number of seconds since the -+ // epoch. If Time is nil, time.Now is used. -+ Time func() time.Time -+ // DefaultCompressionAlgo is the compression algorithm to be -+ // applied to the plaintext before encryption. If zero, no -+ // compression is done. -+ DefaultCompressionAlgo CompressionAlgo -+ // CompressionConfig configures the compression settings. -+ CompressionConfig *CompressionConfig -+ // S2KCount is only used for symmetric encryption. It -+ // determines the strength of the passphrase stretching when -+ // the said passphrase is hashed to produce a key. S2KCount -+ // should be between 1024 and 65011712, inclusive. If Config -+ // is nil or S2KCount is 0, the value 65536 used. Not all -+ // values in the above range can be represented. S2KCount will -+ // be rounded up to the next representable value if it cannot -+ // be encoded exactly. When set, it is strongly encrouraged to -+ // use a value that is at least 65536. See RFC 4880 Section -+ // 3.7.1.3. -+ S2KCount int -+ // RSABits is the number of bits in new RSA keys made with NewEntity. -+ // If zero, then 2048 bit keys are created. -+ RSABits int -+} -+ -+func (c *Config) Random() io.Reader { -+ if c == nil || c.Rand == nil { -+ return rand.Reader -+ } -+ return c.Rand -+} -+ -+func (c *Config) Hash() crypto.Hash { -+ if c == nil || uint(c.DefaultHash) == 0 { -+ return crypto.SHA256 -+ } -+ return c.DefaultHash -+} -+ -+func (c *Config) Cipher() CipherFunction { -+ if c == nil || uint8(c.DefaultCipher) == 0 { -+ return CipherAES128 -+ } -+ return c.DefaultCipher -+} -+ -+func (c *Config) Now() time.Time { -+ if c == nil || c.Time == nil { -+ return time.Now() -+ } -+ return c.Time() -+} -+ -+func (c *Config) Compression() CompressionAlgo { -+ if c == nil { -+ return CompressionNone -+ } -+ return c.DefaultCompressionAlgo -+} -+ -+func (c *Config) PasswordHashIterations() int { -+ if c == nil || c.S2KCount == 0 { -+ return 0 -+ } -+ return c.S2KCount -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go -new file mode 100644 -index 00000000000000..6d7639722c906b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key.go -@@ -0,0 +1,208 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "crypto" -+ "crypto/rsa" -+ "encoding/binary" -+ "io" -+ "math/big" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/elgamal" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+const encryptedKeyVersion = 3 -+ -+// EncryptedKey represents a public-key encrypted session key. See RFC 4880, -+// section 5.1. -+type EncryptedKey struct { -+ KeyId uint64 -+ Algo PublicKeyAlgorithm -+ CipherFunc CipherFunction // only valid after a successful Decrypt -+ Key []byte // only valid after a successful Decrypt -+ -+ encryptedMPI1, encryptedMPI2 parsedMPI -+} -+ -+func (e *EncryptedKey) parse(r io.Reader) (err error) { -+ var buf [10]byte -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ if buf[0] != encryptedKeyVersion { -+ return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) -+ } -+ e.KeyId = binary.BigEndian.Uint64(buf[1:9]) -+ e.Algo = PublicKeyAlgorithm(buf[9]) -+ switch e.Algo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ case PubKeyAlgoElGamal: -+ e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ } -+ _, err = consumeAll(r) -+ return -+} -+ -+func checksumKeyMaterial(key []byte) uint16 { -+ var checksum uint16 -+ for _, v := range key { -+ checksum += uint16(v) -+ } -+ return checksum -+} -+ -+// Decrypt decrypts an encrypted session key with the given private key. The -+// private key must have been decrypted first. -+// If config is nil, sensible defaults will be used. -+func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { -+ var err error -+ var b []byte -+ -+ // TODO(agl): use session key decryption routines here to avoid -+ // padding oracle attacks. -+ switch priv.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ // Supports both *rsa.PrivateKey and crypto.Decrypter -+ k := priv.PrivateKey.(crypto.Decrypter) -+ b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) -+ case PubKeyAlgoElGamal: -+ c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) -+ c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) -+ b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) -+ default: -+ err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) -+ } -+ -+ if err != nil { -+ return err -+ } -+ -+ e.CipherFunc = CipherFunction(b[0]) -+ e.Key = b[1 : len(b)-2] -+ expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) -+ checksum := checksumKeyMaterial(e.Key) -+ if checksum != expectedChecksum { -+ return errors.StructuralError("EncryptedKey checksum incorrect") -+ } -+ -+ return nil -+} -+ -+// Serialize writes the encrypted key packet, e, to w. -+func (e *EncryptedKey) Serialize(w io.Writer) error { -+ var mpiLen int -+ switch e.Algo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ mpiLen = 2 + len(e.encryptedMPI1.bytes) -+ case PubKeyAlgoElGamal: -+ mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) -+ default: -+ return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) -+ } -+ -+ serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) -+ -+ w.Write([]byte{encryptedKeyVersion}) -+ binary.Write(w, binary.BigEndian, e.KeyId) -+ w.Write([]byte{byte(e.Algo)}) -+ -+ switch e.Algo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ writeMPIs(w, e.encryptedMPI1) -+ case PubKeyAlgoElGamal: -+ writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) -+ default: -+ panic("internal error") -+ } -+ -+ return nil -+} -+ -+// SerializeEncryptedKey serializes an encrypted key packet to w that contains -+// key, encrypted to pub. -+// If config is nil, sensible defaults will be used. -+func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { -+ var buf [10]byte -+ buf[0] = encryptedKeyVersion -+ binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) -+ buf[9] = byte(pub.PubKeyAlgo) -+ -+ keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) -+ keyBlock[0] = byte(cipherFunc) -+ copy(keyBlock[1:], key) -+ checksum := checksumKeyMaterial(key) -+ keyBlock[1+len(key)] = byte(checksum >> 8) -+ keyBlock[1+len(key)+1] = byte(checksum) -+ -+ switch pub.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: -+ return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) -+ case PubKeyAlgoElGamal: -+ return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) -+ case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: -+ return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) -+ } -+ -+ return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) -+} -+ -+func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { -+ cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) -+ if err != nil { -+ return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) -+ } -+ -+ packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) -+ -+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen) -+ if err != nil { -+ return err -+ } -+ _, err = w.Write(header[:]) -+ if err != nil { -+ return err -+ } -+ return writeMPI(w, 8*uint16(len(cipherText)), cipherText) -+} -+ -+func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { -+ c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) -+ if err != nil { -+ return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) -+ } -+ -+ packetLen := 10 /* header length */ -+ packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 -+ packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 -+ -+ err = serializeHeader(w, packetTypeEncryptedKey, packetLen) -+ if err != nil { -+ return err -+ } -+ _, err = w.Write(header[:]) -+ if err != nil { -+ return err -+ } -+ err = writeBig(w, c1) -+ if err != nil { -+ return err -+ } -+ return writeBig(w, c2) -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go -new file mode 100644 -index 00000000000000..ecb22bc2ba8c8f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go -@@ -0,0 +1,220 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/rsa" -+ "encoding/hex" -+ "fmt" -+ "io" -+ "math/big" -+ "testing" -+) -+ -+func bigFromBase10(s string) *big.Int { -+ b, ok := new(big.Int).SetString(s, 10) -+ if !ok { -+ panic("bigFromBase10 failed") -+ } -+ return b -+} -+ -+var encryptedKeyPub = rsa.PublicKey{ -+ E: 65537, -+ N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"), -+} -+ -+var encryptedKeyRSAPriv = &rsa.PrivateKey{ -+ PublicKey: encryptedKeyPub, -+ D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"), -+} -+ -+var encryptedKeyPriv = &PrivateKey{ -+ PublicKey: PublicKey{ -+ PubKeyAlgo: PubKeyAlgoRSA, -+ }, -+ PrivateKey: encryptedKeyRSAPriv, -+} -+ -+func TestDecryptingEncryptedKey(t *testing.T) { -+ for i, encryptedKeyHex := range []string{ -+ "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8", -+ // MPI can be shorter than the length of the key. -+ "c18b032a67d68660df41c70103f8e520c52ae9807183c669ce26e772e482dc5d8cf60e6f59316e145be14d2e5221ee69550db1d5618a8cb002a719f1f0b9345bde21536d410ec90ba86cac37748dec7933eb7f9873873b2d61d3321d1cd44535014f6df58f7bc0c7afb5edc38e1a974428997d2f747f9a173bea9ca53079b409517d332df62d805564cffc9be6", -+ } { -+ const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" -+ -+ p, err := Read(readerFromHex(encryptedKeyHex)) -+ if err != nil { -+ t.Errorf("#%d: error from Read: %s", i, err) -+ return -+ } -+ ek, ok := p.(*EncryptedKey) -+ if !ok { -+ t.Errorf("#%d: didn't parse an EncryptedKey, got %#v", i, p) -+ return -+ } -+ -+ if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { -+ t.Errorf("#%d: unexpected EncryptedKey contents: %#v", i, ek) -+ return -+ } -+ -+ err = ek.Decrypt(encryptedKeyPriv, nil) -+ if err != nil { -+ t.Errorf("#%d: error from Decrypt: %s", i, err) -+ return -+ } -+ -+ if ek.CipherFunc != CipherAES256 { -+ t.Errorf("#%d: unexpected EncryptedKey contents: %#v", i, ek) -+ return -+ } -+ -+ keyHex := fmt.Sprintf("%x", ek.Key) -+ if keyHex != expectedKeyHex { -+ t.Errorf("#%d: bad key, got %s want %s", i, keyHex, expectedKeyHex) -+ } -+ } -+} -+ -+type rsaDecrypter struct { -+ rsaPrivateKey *rsa.PrivateKey -+ decryptCount int -+} -+ -+func (r *rsaDecrypter) Public() crypto.PublicKey { -+ return &r.rsaPrivateKey.PublicKey -+} -+ -+func (r *rsaDecrypter) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error) { -+ r.decryptCount++ -+ return r.rsaPrivateKey.Decrypt(rand, msg, opts) -+} -+ -+func TestRSADecrypter(t *testing.T) { -+ const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" -+ -+ const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" -+ -+ p, err := Read(readerFromHex(encryptedKeyHex)) -+ if err != nil { -+ t.Errorf("error from Read: %s", err) -+ return -+ } -+ ek, ok := p.(*EncryptedKey) -+ if !ok { -+ t.Errorf("didn't parse an EncryptedKey, got %#v", p) -+ return -+ } -+ -+ if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { -+ t.Errorf("unexpected EncryptedKey contents: %#v", ek) -+ return -+ } -+ -+ customDecrypter := &rsaDecrypter{ -+ rsaPrivateKey: encryptedKeyRSAPriv, -+ } -+ -+ customKeyPriv := &PrivateKey{ -+ PublicKey: PublicKey{ -+ PubKeyAlgo: PubKeyAlgoRSA, -+ }, -+ PrivateKey: customDecrypter, -+ } -+ -+ err = ek.Decrypt(customKeyPriv, nil) -+ if err != nil { -+ t.Errorf("error from Decrypt: %s", err) -+ return -+ } -+ -+ if ek.CipherFunc != CipherAES256 { -+ t.Errorf("unexpected EncryptedKey contents: %#v", ek) -+ return -+ } -+ -+ keyHex := fmt.Sprintf("%x", ek.Key) -+ if keyHex != expectedKeyHex { -+ t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) -+ } -+ -+ if customDecrypter.decryptCount != 1 { -+ t.Errorf("Expected customDecrypter.Decrypt() to be called 1 time, but was called %d times", customDecrypter.decryptCount) -+ } -+} -+ -+func TestEncryptingEncryptedKey(t *testing.T) { -+ key := []byte{1, 2, 3, 4} -+ const expectedKeyHex = "01020304" -+ const keyId = 42 -+ -+ pub := &PublicKey{ -+ PublicKey: &encryptedKeyPub, -+ KeyId: keyId, -+ PubKeyAlgo: PubKeyAlgoRSAEncryptOnly, -+ } -+ -+ buf := new(bytes.Buffer) -+ err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil) -+ if err != nil { -+ t.Errorf("error writing encrypted key packet: %s", err) -+ } -+ -+ p, err := Read(buf) -+ if err != nil { -+ t.Errorf("error from Read: %s", err) -+ return -+ } -+ ek, ok := p.(*EncryptedKey) -+ if !ok { -+ t.Errorf("didn't parse an EncryptedKey, got %#v", p) -+ return -+ } -+ -+ if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly { -+ t.Errorf("unexpected EncryptedKey contents: %#v", ek) -+ return -+ } -+ -+ err = ek.Decrypt(encryptedKeyPriv, nil) -+ if err != nil { -+ t.Errorf("error from Decrypt: %s", err) -+ return -+ } -+ -+ if ek.CipherFunc != CipherAES128 { -+ t.Errorf("unexpected EncryptedKey contents: %#v", ek) -+ return -+ } -+ -+ keyHex := fmt.Sprintf("%x", ek.Key) -+ if keyHex != expectedKeyHex { -+ t.Errorf("bad key, got %s want %s", keyHex, expectedKeyHex) -+ } -+} -+ -+func TestSerializingEncryptedKey(t *testing.T) { -+ const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" -+ -+ p, err := Read(readerFromHex(encryptedKeyHex)) -+ if err != nil { -+ t.Fatalf("error from Read: %s", err) -+ } -+ ek, ok := p.(*EncryptedKey) -+ if !ok { -+ t.Fatalf("didn't parse an EncryptedKey, got %#v", p) -+ } -+ -+ var buf bytes.Buffer -+ ek.Serialize(&buf) -+ -+ if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex { -+ t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/literal.go b/ms_mod/golang.org/x/crypto/openpgp/packet/literal.go -new file mode 100644 -index 00000000000000..1a9ec6e51e81d4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/literal.go -@@ -0,0 +1,89 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "encoding/binary" -+ "io" -+) -+ -+// LiteralData represents an encrypted file. See RFC 4880, section 5.9. -+type LiteralData struct { -+ IsBinary bool -+ FileName string -+ Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. -+ Body io.Reader -+} -+ -+// ForEyesOnly returns whether the contents of the LiteralData have been marked -+// as especially sensitive. -+func (l *LiteralData) ForEyesOnly() bool { -+ return l.FileName == "_CONSOLE" -+} -+ -+func (l *LiteralData) parse(r io.Reader) (err error) { -+ var buf [256]byte -+ -+ _, err = readFull(r, buf[:2]) -+ if err != nil { -+ return -+ } -+ -+ l.IsBinary = buf[0] == 'b' -+ fileNameLen := int(buf[1]) -+ -+ _, err = readFull(r, buf[:fileNameLen]) -+ if err != nil { -+ return -+ } -+ -+ l.FileName = string(buf[:fileNameLen]) -+ -+ _, err = readFull(r, buf[:4]) -+ if err != nil { -+ return -+ } -+ -+ l.Time = binary.BigEndian.Uint32(buf[:4]) -+ l.Body = r -+ return -+} -+ -+// SerializeLiteral serializes a literal data packet to w and returns a -+// WriteCloser to which the data itself can be written and which MUST be closed -+// on completion. The fileName is truncated to 255 bytes. -+func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { -+ var buf [4]byte -+ buf[0] = 't' -+ if isBinary { -+ buf[0] = 'b' -+ } -+ if len(fileName) > 255 { -+ fileName = fileName[:255] -+ } -+ buf[1] = byte(len(fileName)) -+ -+ inner, err := serializeStreamHeader(w, packetTypeLiteralData) -+ if err != nil { -+ return -+ } -+ -+ _, err = inner.Write(buf[:2]) -+ if err != nil { -+ return -+ } -+ _, err = inner.Write([]byte(fileName)) -+ if err != nil { -+ return -+ } -+ binary.BigEndian.PutUint32(buf[:], time) -+ _, err = inner.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ -+ plaintext = inner -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go -new file mode 100644 -index 00000000000000..ce2a33a547cef9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb.go -@@ -0,0 +1,143 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 -+ -+package packet -+ -+import ( -+ "crypto/cipher" -+) -+ -+type ocfbEncrypter struct { -+ b cipher.Block -+ fre []byte -+ outUsed int -+} -+ -+// An OCFBResyncOption determines if the "resynchronization step" of OCFB is -+// performed. -+type OCFBResyncOption bool -+ -+const ( -+ OCFBResync OCFBResyncOption = true -+ OCFBNoResync OCFBResyncOption = false -+) -+ -+// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's -+// cipher feedback mode using the given cipher.Block, and an initial amount of -+// ciphertext. randData must be random bytes and be the same length as the -+// cipher.Block's block size. Resync determines if the "resynchronization step" -+// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on -+// this point. -+func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { -+ blockSize := block.BlockSize() -+ if len(randData) != blockSize { -+ return nil, nil -+ } -+ -+ x := &ocfbEncrypter{ -+ b: block, -+ fre: make([]byte, blockSize), -+ outUsed: 0, -+ } -+ prefix := make([]byte, blockSize+2) -+ -+ block.Encrypt(x.fre, x.fre) -+ for i := 0; i < blockSize; i++ { -+ prefix[i] = randData[i] ^ x.fre[i] -+ } -+ -+ block.Encrypt(x.fre, prefix[:blockSize]) -+ prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] -+ prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] -+ -+ if resync { -+ block.Encrypt(x.fre, prefix[2:]) -+ } else { -+ x.fre[0] = prefix[blockSize] -+ x.fre[1] = prefix[blockSize+1] -+ x.outUsed = 2 -+ } -+ return x, prefix -+} -+ -+func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { -+ for i := 0; i < len(src); i++ { -+ if x.outUsed == len(x.fre) { -+ x.b.Encrypt(x.fre, x.fre) -+ x.outUsed = 0 -+ } -+ -+ x.fre[x.outUsed] ^= src[i] -+ dst[i] = x.fre[x.outUsed] -+ x.outUsed++ -+ } -+} -+ -+type ocfbDecrypter struct { -+ b cipher.Block -+ fre []byte -+ outUsed int -+} -+ -+// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's -+// cipher feedback mode using the given cipher.Block. Prefix must be the first -+// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's -+// block size. If an incorrect key is detected then nil is returned. On -+// successful exit, blockSize+2 bytes of decrypted data are written into -+// prefix. Resync determines if the "resynchronization step" from RFC 4880, -+// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. -+func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { -+ blockSize := block.BlockSize() -+ if len(prefix) != blockSize+2 { -+ return nil -+ } -+ -+ x := &ocfbDecrypter{ -+ b: block, -+ fre: make([]byte, blockSize), -+ outUsed: 0, -+ } -+ prefixCopy := make([]byte, len(prefix)) -+ copy(prefixCopy, prefix) -+ -+ block.Encrypt(x.fre, x.fre) -+ for i := 0; i < blockSize; i++ { -+ prefixCopy[i] ^= x.fre[i] -+ } -+ -+ block.Encrypt(x.fre, prefix[:blockSize]) -+ prefixCopy[blockSize] ^= x.fre[0] -+ prefixCopy[blockSize+1] ^= x.fre[1] -+ -+ if prefixCopy[blockSize-2] != prefixCopy[blockSize] || -+ prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { -+ return nil -+ } -+ -+ if resync { -+ block.Encrypt(x.fre, prefix[2:]) -+ } else { -+ x.fre[0] = prefix[blockSize] -+ x.fre[1] = prefix[blockSize+1] -+ x.outUsed = 2 -+ } -+ copy(prefix, prefixCopy) -+ return x -+} -+ -+func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { -+ for i := 0; i < len(src); i++ { -+ if x.outUsed == len(x.fre) { -+ x.b.Encrypt(x.fre, x.fre) -+ x.outUsed = 0 -+ } -+ -+ c := src[i] -+ dst[i] = x.fre[x.outUsed] ^ src[i] -+ x.fre[x.outUsed] = c -+ x.outUsed++ -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go -new file mode 100644 -index 00000000000000..91022c042d4517 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/ocfb_test.go -@@ -0,0 +1,46 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto/aes" -+ "crypto/rand" -+ "testing" -+) -+ -+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c} -+ -+func testOCFB(t *testing.T, resync OCFBResyncOption) { -+ block, err := aes.NewCipher(commonKey128) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ -+ plaintext := []byte("this is the plaintext, which is long enough to span several blocks.") -+ randData := make([]byte, block.BlockSize()) -+ rand.Reader.Read(randData) -+ ocfb, prefix := NewOCFBEncrypter(block, randData, resync) -+ ciphertext := make([]byte, len(plaintext)) -+ ocfb.XORKeyStream(ciphertext, plaintext) -+ -+ ocfbdec := NewOCFBDecrypter(block, prefix, resync) -+ if ocfbdec == nil { -+ t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync) -+ return -+ } -+ plaintextCopy := make([]byte, len(plaintext)) -+ ocfbdec.XORKeyStream(plaintextCopy, ciphertext) -+ -+ if !bytes.Equal(plaintextCopy, plaintext) { -+ t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync) -+ } -+} -+ -+func TestOCFB(t *testing.T) { -+ testOCFB(t, OCFBNoResync) -+ testOCFB(t, OCFBResync) -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go -new file mode 100644 -index 00000000000000..1713503395e3c8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/one_pass_signature.go -@@ -0,0 +1,73 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "crypto" -+ "encoding/binary" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+ "io" -+ "strconv" -+) -+ -+// OnePassSignature represents a one-pass signature packet. See RFC 4880, -+// section 5.4. -+type OnePassSignature struct { -+ SigType SignatureType -+ Hash crypto.Hash -+ PubKeyAlgo PublicKeyAlgorithm -+ KeyId uint64 -+ IsLast bool -+} -+ -+const onePassSignatureVersion = 3 -+ -+func (ops *OnePassSignature) parse(r io.Reader) (err error) { -+ var buf [13]byte -+ -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ if buf[0] != onePassSignatureVersion { -+ err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) -+ } -+ -+ var ok bool -+ ops.Hash, ok = s2k.HashIdToHash(buf[2]) -+ if !ok { -+ return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) -+ } -+ -+ ops.SigType = SignatureType(buf[1]) -+ ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) -+ ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) -+ ops.IsLast = buf[12] != 0 -+ return -+} -+ -+// Serialize marshals the given OnePassSignature to w. -+func (ops *OnePassSignature) Serialize(w io.Writer) error { -+ var buf [13]byte -+ buf[0] = onePassSignatureVersion -+ buf[1] = uint8(ops.SigType) -+ var ok bool -+ buf[2], ok = s2k.HashToHashId(ops.Hash) -+ if !ok { -+ return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) -+ } -+ buf[3] = uint8(ops.PubKeyAlgo) -+ binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) -+ if ops.IsLast { -+ buf[12] = 1 -+ } -+ -+ if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { -+ return err -+ } -+ _, err := w.Write(buf[:]) -+ return err -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go -new file mode 100644 -index 00000000000000..3984477310fe70 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque.go -@@ -0,0 +1,161 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "io" -+ -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is -+// useful for splitting and storing the original packet contents separately, -+// handling unsupported packet types or accessing parts of the packet not yet -+// implemented by this package. -+type OpaquePacket struct { -+ // Packet type -+ Tag uint8 -+ // Reason why the packet was parsed opaquely -+ Reason error -+ // Binary contents of the packet data -+ Contents []byte -+} -+ -+func (op *OpaquePacket) parse(r io.Reader) (err error) { -+ op.Contents, err = io.ReadAll(r) -+ return -+} -+ -+// Serialize marshals the packet to a writer in its original form, including -+// the packet header. -+func (op *OpaquePacket) Serialize(w io.Writer) (err error) { -+ err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) -+ if err == nil { -+ _, err = w.Write(op.Contents) -+ } -+ return -+} -+ -+// Parse attempts to parse the opaque contents into a structure supported by -+// this package. If the packet is not known then the result will be another -+// OpaquePacket. -+func (op *OpaquePacket) Parse() (p Packet, err error) { -+ hdr := bytes.NewBuffer(nil) -+ err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) -+ if err != nil { -+ op.Reason = err -+ return op, err -+ } -+ p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) -+ if err != nil { -+ op.Reason = err -+ p = op -+ } -+ return -+} -+ -+// OpaqueReader reads OpaquePackets from an io.Reader. -+type OpaqueReader struct { -+ r io.Reader -+} -+ -+func NewOpaqueReader(r io.Reader) *OpaqueReader { -+ return &OpaqueReader{r: r} -+} -+ -+// Read the next OpaquePacket. -+func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { -+ tag, _, contents, err := readHeader(or.r) -+ if err != nil { -+ return -+ } -+ op = &OpaquePacket{Tag: uint8(tag), Reason: err} -+ err = op.parse(contents) -+ if err != nil { -+ consumeAll(contents) -+ } -+ return -+} -+ -+// OpaqueSubpacket represents an unparsed OpenPGP subpacket, -+// as found in signature and user attribute packets. -+type OpaqueSubpacket struct { -+ SubType uint8 -+ Contents []byte -+} -+ -+// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from -+// their byte representation. -+func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { -+ var ( -+ subHeaderLen int -+ subPacket *OpaqueSubpacket -+ ) -+ for len(contents) > 0 { -+ subHeaderLen, subPacket, err = nextSubpacket(contents) -+ if err != nil { -+ break -+ } -+ result = append(result, subPacket) -+ contents = contents[subHeaderLen+len(subPacket.Contents):] -+ } -+ return -+} -+ -+func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { -+ // RFC 4880, section 5.2.3.1 -+ var subLen uint32 -+ if len(contents) < 1 { -+ goto Truncated -+ } -+ subPacket = &OpaqueSubpacket{} -+ switch { -+ case contents[0] < 192: -+ subHeaderLen = 2 // 1 length byte, 1 subtype byte -+ if len(contents) < subHeaderLen { -+ goto Truncated -+ } -+ subLen = uint32(contents[0]) -+ contents = contents[1:] -+ case contents[0] < 255: -+ subHeaderLen = 3 // 2 length bytes, 1 subtype -+ if len(contents) < subHeaderLen { -+ goto Truncated -+ } -+ subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 -+ contents = contents[2:] -+ default: -+ subHeaderLen = 6 // 5 length bytes, 1 subtype -+ if len(contents) < subHeaderLen { -+ goto Truncated -+ } -+ subLen = uint32(contents[1])<<24 | -+ uint32(contents[2])<<16 | -+ uint32(contents[3])<<8 | -+ uint32(contents[4]) -+ contents = contents[5:] -+ } -+ if subLen > uint32(len(contents)) || subLen == 0 { -+ goto Truncated -+ } -+ subPacket.SubType = contents[0] -+ subPacket.Contents = contents[1:subLen] -+ return -+Truncated: -+ err = errors.StructuralError("subpacket truncated") -+ return -+} -+ -+func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { -+ buf := make([]byte, 6) -+ n := serializeSubpacketLength(buf, len(osp.Contents)+1) -+ buf[n] = osp.SubType -+ if _, err = w.Write(buf[:n+1]); err != nil { -+ return -+ } -+ _, err = w.Write(osp.Contents) -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go -new file mode 100644 -index 00000000000000..61159f468389e7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/opaque_test.go -@@ -0,0 +1,67 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "io" -+ "testing" -+) -+ -+// Test packet.Read error handling in OpaquePacket.Parse, -+// which attempts to re-read an OpaquePacket as a supported -+// Packet type. -+func TestOpaqueParseReason(t *testing.T) { -+ buf, err := hex.DecodeString(UnsupportedKeyHex) -+ if err != nil { -+ t.Fatal(err) -+ } -+ or := NewOpaqueReader(bytes.NewBuffer(buf)) -+ count := 0 -+ badPackets := 0 -+ var uid *UserId -+ for { -+ op, err := or.Next() -+ if err == io.EOF { -+ break -+ } else if err != nil { -+ t.Errorf("#%d: opaque read error: %v", count, err) -+ break -+ } -+ // try to parse opaque packet -+ p, _ := op.Parse() -+ switch pkt := p.(type) { -+ case *UserId: -+ uid = pkt -+ case *OpaquePacket: -+ // If an OpaquePacket can't re-parse, packet.Read -+ // certainly had its reasons. -+ if pkt.Reason == nil { -+ t.Errorf("#%d: opaque packet, no reason", count) -+ } else { -+ badPackets++ -+ } -+ } -+ count++ -+ } -+ -+ const expectedBad = 3 -+ // Test post-conditions, make sure we actually parsed packets as expected. -+ if badPackets != expectedBad { -+ t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad) -+ } -+ if uid == nil { -+ t.Errorf("failed to find expected UID in unsupported keyring") -+ } else if uid.Id != "Armin M. Warda " { -+ t.Errorf("unexpected UID: %v", uid.Id) -+ } -+} -+ -+// This key material has public key and signature packet versions modified to -+// an unsupported value (1), so that trying to parse the OpaquePacket to -+// a typed packet will get an error. It also contains a GnuPG trust packet. -+// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g') -+const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/packet.go b/ms_mod/golang.org/x/crypto/openpgp/packet/packet.go -new file mode 100644 -index 00000000000000..0a19794a8e49c1 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/packet.go -@@ -0,0 +1,590 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package packet implements parsing and serialization of OpenPGP packets, as -+// specified in RFC 4880. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package packet // import "golang.org/x/crypto/openpgp/packet" -+ -+import ( -+ "bufio" -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/des" -+ "crypto/rsa" -+ "io" -+ "math/big" -+ "math/bits" -+ -+ "golang.org/x/crypto/cast5" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// readFull is the same as io.ReadFull except that reading zero bytes returns -+// ErrUnexpectedEOF rather than EOF. -+func readFull(r io.Reader, buf []byte) (n int, err error) { -+ n, err = io.ReadFull(r, buf) -+ if err == io.EOF { -+ err = io.ErrUnexpectedEOF -+ } -+ return -+} -+ -+// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. -+func readLength(r io.Reader) (length int64, isPartial bool, err error) { -+ var buf [4]byte -+ _, err = readFull(r, buf[:1]) -+ if err != nil { -+ return -+ } -+ switch { -+ case buf[0] < 192: -+ length = int64(buf[0]) -+ case buf[0] < 224: -+ length = int64(buf[0]-192) << 8 -+ _, err = readFull(r, buf[0:1]) -+ if err != nil { -+ return -+ } -+ length += int64(buf[0]) + 192 -+ case buf[0] < 255: -+ length = int64(1) << (buf[0] & 0x1f) -+ isPartial = true -+ default: -+ _, err = readFull(r, buf[0:4]) -+ if err != nil { -+ return -+ } -+ length = int64(buf[0])<<24 | -+ int64(buf[1])<<16 | -+ int64(buf[2])<<8 | -+ int64(buf[3]) -+ } -+ return -+} -+ -+// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. -+// The continuation lengths are parsed and removed from the stream and EOF is -+// returned at the end of the packet. See RFC 4880, section 4.2.2.4. -+type partialLengthReader struct { -+ r io.Reader -+ remaining int64 -+ isPartial bool -+} -+ -+func (r *partialLengthReader) Read(p []byte) (n int, err error) { -+ for r.remaining == 0 { -+ if !r.isPartial { -+ return 0, io.EOF -+ } -+ r.remaining, r.isPartial, err = readLength(r.r) -+ if err != nil { -+ return 0, err -+ } -+ } -+ -+ toRead := int64(len(p)) -+ if toRead > r.remaining { -+ toRead = r.remaining -+ } -+ -+ n, err = r.r.Read(p[:int(toRead)]) -+ r.remaining -= int64(n) -+ if n < int(toRead) && err == io.EOF { -+ err = io.ErrUnexpectedEOF -+ } -+ return -+} -+ -+// partialLengthWriter writes a stream of data using OpenPGP partial lengths. -+// See RFC 4880, section 4.2.2.4. -+type partialLengthWriter struct { -+ w io.WriteCloser -+ lengthByte [1]byte -+ sentFirst bool -+ buf []byte -+} -+ -+// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long. -+const minFirstPartialWrite = 512 -+ -+func (w *partialLengthWriter) Write(p []byte) (n int, err error) { -+ off := 0 -+ if !w.sentFirst { -+ if len(w.buf) > 0 || len(p) < minFirstPartialWrite { -+ off = len(w.buf) -+ w.buf = append(w.buf, p...) -+ if len(w.buf) < minFirstPartialWrite { -+ return len(p), nil -+ } -+ p = w.buf -+ w.buf = nil -+ } -+ w.sentFirst = true -+ } -+ -+ power := uint8(30) -+ for len(p) > 0 { -+ l := 1 << power -+ if len(p) < l { -+ power = uint8(bits.Len32(uint32(len(p)))) - 1 -+ l = 1 << power -+ } -+ w.lengthByte[0] = 224 + power -+ _, err = w.w.Write(w.lengthByte[:]) -+ if err == nil { -+ var m int -+ m, err = w.w.Write(p[:l]) -+ n += m -+ } -+ if err != nil { -+ if n < off { -+ return 0, err -+ } -+ return n - off, err -+ } -+ p = p[l:] -+ } -+ return n - off, nil -+} -+ -+func (w *partialLengthWriter) Close() error { -+ if len(w.buf) > 0 { -+ // In this case we can't send a 512 byte packet. -+ // Just send what we have. -+ p := w.buf -+ w.sentFirst = true -+ w.buf = nil -+ if _, err := w.Write(p); err != nil { -+ return err -+ } -+ } -+ -+ w.lengthByte[0] = 0 -+ _, err := w.w.Write(w.lengthByte[:]) -+ if err != nil { -+ return err -+ } -+ return w.w.Close() -+} -+ -+// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the -+// underlying Reader returns EOF before the limit has been reached. -+type spanReader struct { -+ r io.Reader -+ n int64 -+} -+ -+func (l *spanReader) Read(p []byte) (n int, err error) { -+ if l.n <= 0 { -+ return 0, io.EOF -+ } -+ if int64(len(p)) > l.n { -+ p = p[0:l.n] -+ } -+ n, err = l.r.Read(p) -+ l.n -= int64(n) -+ if l.n > 0 && err == io.EOF { -+ err = io.ErrUnexpectedEOF -+ } -+ return -+} -+ -+// readHeader parses a packet header and returns an io.Reader which will return -+// the contents of the packet. See RFC 4880, section 4.2. -+func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { -+ var buf [4]byte -+ _, err = io.ReadFull(r, buf[:1]) -+ if err != nil { -+ return -+ } -+ if buf[0]&0x80 == 0 { -+ err = errors.StructuralError("tag byte does not have MSB set") -+ return -+ } -+ if buf[0]&0x40 == 0 { -+ // Old format packet -+ tag = packetType((buf[0] & 0x3f) >> 2) -+ lengthType := buf[0] & 3 -+ if lengthType == 3 { -+ length = -1 -+ contents = r -+ return -+ } -+ lengthBytes := 1 << lengthType -+ _, err = readFull(r, buf[0:lengthBytes]) -+ if err != nil { -+ return -+ } -+ for i := 0; i < lengthBytes; i++ { -+ length <<= 8 -+ length |= int64(buf[i]) -+ } -+ contents = &spanReader{r, length} -+ return -+ } -+ -+ // New format packet -+ tag = packetType(buf[0] & 0x3f) -+ length, isPartial, err := readLength(r) -+ if err != nil { -+ return -+ } -+ if isPartial { -+ contents = &partialLengthReader{ -+ remaining: length, -+ isPartial: true, -+ r: r, -+ } -+ length = -1 -+ } else { -+ contents = &spanReader{r, length} -+ } -+ return -+} -+ -+// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section -+// 4.2. -+func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { -+ var buf [6]byte -+ var n int -+ -+ buf[0] = 0x80 | 0x40 | byte(ptype) -+ if length < 192 { -+ buf[1] = byte(length) -+ n = 2 -+ } else if length < 8384 { -+ length -= 192 -+ buf[1] = 192 + byte(length>>8) -+ buf[2] = byte(length) -+ n = 3 -+ } else { -+ buf[1] = 255 -+ buf[2] = byte(length >> 24) -+ buf[3] = byte(length >> 16) -+ buf[4] = byte(length >> 8) -+ buf[5] = byte(length) -+ n = 6 -+ } -+ -+ _, err = w.Write(buf[:n]) -+ return -+} -+ -+// serializeStreamHeader writes an OpenPGP packet header to w where the -+// length of the packet is unknown. It returns a io.WriteCloser which can be -+// used to write the contents of the packet. See RFC 4880, section 4.2. -+func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { -+ var buf [1]byte -+ buf[0] = 0x80 | 0x40 | byte(ptype) -+ _, err = w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ out = &partialLengthWriter{w: w} -+ return -+} -+ -+// Packet represents an OpenPGP packet. Users are expected to try casting -+// instances of this interface to specific packet types. -+type Packet interface { -+ parse(io.Reader) error -+} -+ -+// consumeAll reads from the given Reader until error, returning the number of -+// bytes read. -+func consumeAll(r io.Reader) (n int64, err error) { -+ var m int -+ var buf [1024]byte -+ -+ for { -+ m, err = r.Read(buf[:]) -+ n += int64(m) -+ if err == io.EOF { -+ err = nil -+ return -+ } -+ if err != nil { -+ return -+ } -+ } -+} -+ -+// packetType represents the numeric ids of the different OpenPGP packet types. See -+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 -+type packetType uint8 -+ -+const ( -+ packetTypeEncryptedKey packetType = 1 -+ packetTypeSignature packetType = 2 -+ packetTypeSymmetricKeyEncrypted packetType = 3 -+ packetTypeOnePassSignature packetType = 4 -+ packetTypePrivateKey packetType = 5 -+ packetTypePublicKey packetType = 6 -+ packetTypePrivateSubkey packetType = 7 -+ packetTypeCompressed packetType = 8 -+ packetTypeSymmetricallyEncrypted packetType = 9 -+ packetTypeLiteralData packetType = 11 -+ packetTypeUserId packetType = 13 -+ packetTypePublicSubkey packetType = 14 -+ packetTypeUserAttribute packetType = 17 -+ packetTypeSymmetricallyEncryptedMDC packetType = 18 -+) -+ -+// peekVersion detects the version of a public key packet about to -+// be read. A bufio.Reader at the original position of the io.Reader -+// is returned. -+func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { -+ bufr = bufio.NewReader(r) -+ var verBuf []byte -+ if verBuf, err = bufr.Peek(1); err != nil { -+ return -+ } -+ ver = verBuf[0] -+ return -+} -+ -+// Read reads a single OpenPGP packet from the given io.Reader. If there is an -+// error parsing a packet, the whole packet is consumed from the input. -+func Read(r io.Reader) (p Packet, err error) { -+ tag, _, contents, err := readHeader(r) -+ if err != nil { -+ return -+ } -+ -+ switch tag { -+ case packetTypeEncryptedKey: -+ p = new(EncryptedKey) -+ case packetTypeSignature: -+ var version byte -+ // Detect signature version -+ if contents, version, err = peekVersion(contents); err != nil { -+ return -+ } -+ if version < 4 { -+ p = new(SignatureV3) -+ } else { -+ p = new(Signature) -+ } -+ case packetTypeSymmetricKeyEncrypted: -+ p = new(SymmetricKeyEncrypted) -+ case packetTypeOnePassSignature: -+ p = new(OnePassSignature) -+ case packetTypePrivateKey, packetTypePrivateSubkey: -+ pk := new(PrivateKey) -+ if tag == packetTypePrivateSubkey { -+ pk.IsSubkey = true -+ } -+ p = pk -+ case packetTypePublicKey, packetTypePublicSubkey: -+ var version byte -+ if contents, version, err = peekVersion(contents); err != nil { -+ return -+ } -+ isSubkey := tag == packetTypePublicSubkey -+ if version < 4 { -+ p = &PublicKeyV3{IsSubkey: isSubkey} -+ } else { -+ p = &PublicKey{IsSubkey: isSubkey} -+ } -+ case packetTypeCompressed: -+ p = new(Compressed) -+ case packetTypeSymmetricallyEncrypted: -+ p = new(SymmetricallyEncrypted) -+ case packetTypeLiteralData: -+ p = new(LiteralData) -+ case packetTypeUserId: -+ p = new(UserId) -+ case packetTypeUserAttribute: -+ p = new(UserAttribute) -+ case packetTypeSymmetricallyEncryptedMDC: -+ se := new(SymmetricallyEncrypted) -+ se.MDC = true -+ p = se -+ default: -+ err = errors.UnknownPacketTypeError(tag) -+ } -+ if p != nil { -+ err = p.parse(contents) -+ } -+ if err != nil { -+ consumeAll(contents) -+ } -+ return -+} -+ -+// SignatureType represents the different semantic meanings of an OpenPGP -+// signature. See RFC 4880, section 5.2.1. -+type SignatureType uint8 -+ -+const ( -+ SigTypeBinary SignatureType = 0 -+ SigTypeText = 1 -+ SigTypeGenericCert = 0x10 -+ SigTypePersonaCert = 0x11 -+ SigTypeCasualCert = 0x12 -+ SigTypePositiveCert = 0x13 -+ SigTypeSubkeyBinding = 0x18 -+ SigTypePrimaryKeyBinding = 0x19 -+ SigTypeDirectSignature = 0x1F -+ SigTypeKeyRevocation = 0x20 -+ SigTypeSubkeyRevocation = 0x28 -+) -+ -+// PublicKeyAlgorithm represents the different public key system specified for -+// OpenPGP. See -+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 -+type PublicKeyAlgorithm uint8 -+ -+const ( -+ PubKeyAlgoRSA PublicKeyAlgorithm = 1 -+ PubKeyAlgoElGamal PublicKeyAlgorithm = 16 -+ PubKeyAlgoDSA PublicKeyAlgorithm = 17 -+ // RFC 6637, Section 5. -+ PubKeyAlgoECDH PublicKeyAlgorithm = 18 -+ PubKeyAlgoECDSA PublicKeyAlgorithm = 19 -+ -+ // Deprecated in RFC 4880, Section 13.5. Use key flags instead. -+ PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 -+ PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 -+) -+ -+// CanEncrypt returns true if it's possible to encrypt a message to a public -+// key of the given type. -+func (pka PublicKeyAlgorithm) CanEncrypt() bool { -+ switch pka { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: -+ return true -+ } -+ return false -+} -+ -+// CanSign returns true if it's possible for a public key of the given type to -+// sign a message. -+func (pka PublicKeyAlgorithm) CanSign() bool { -+ switch pka { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: -+ return true -+ } -+ return false -+} -+ -+// CipherFunction represents the different block ciphers specified for OpenPGP. See -+// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 -+type CipherFunction uint8 -+ -+const ( -+ Cipher3DES CipherFunction = 2 -+ CipherCAST5 CipherFunction = 3 -+ CipherAES128 CipherFunction = 7 -+ CipherAES192 CipherFunction = 8 -+ CipherAES256 CipherFunction = 9 -+) -+ -+// KeySize returns the key size, in bytes, of cipher. -+func (cipher CipherFunction) KeySize() int { -+ switch cipher { -+ case Cipher3DES: -+ return 24 -+ case CipherCAST5: -+ return cast5.KeySize -+ case CipherAES128: -+ return 16 -+ case CipherAES192: -+ return 24 -+ case CipherAES256: -+ return 32 -+ } -+ return 0 -+} -+ -+// blockSize returns the block size, in bytes, of cipher. -+func (cipher CipherFunction) blockSize() int { -+ switch cipher { -+ case Cipher3DES: -+ return des.BlockSize -+ case CipherCAST5: -+ return 8 -+ case CipherAES128, CipherAES192, CipherAES256: -+ return 16 -+ } -+ return 0 -+} -+ -+// new returns a fresh instance of the given cipher. -+func (cipher CipherFunction) new(key []byte) (block cipher.Block) { -+ switch cipher { -+ case Cipher3DES: -+ block, _ = des.NewTripleDESCipher(key) -+ case CipherCAST5: -+ block, _ = cast5.NewCipher(key) -+ case CipherAES128, CipherAES192, CipherAES256: -+ block, _ = aes.NewCipher(key) -+ } -+ return -+} -+ -+// readMPI reads a big integer from r. The bit length returned is the bit -+// length that was specified in r. This is preserved so that the integer can be -+// reserialized exactly. -+func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { -+ var buf [2]byte -+ _, err = readFull(r, buf[0:]) -+ if err != nil { -+ return -+ } -+ bitLength = uint16(buf[0])<<8 | uint16(buf[1]) -+ numBytes := (int(bitLength) + 7) / 8 -+ mpi = make([]byte, numBytes) -+ _, err = readFull(r, mpi) -+ // According to RFC 4880 3.2. we should check that the MPI has no leading -+ // zeroes (at least when not an encrypted MPI?), but this implementation -+ // does generate leading zeroes, so we keep accepting them. -+ return -+} -+ -+// writeMPI serializes a big integer to w. -+func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { -+ // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. -+ // Implementations seem to be tolerant of them, and stripping them would -+ // make it complex to guarantee matching re-serialization. -+ _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) -+ if err == nil { -+ _, err = w.Write(mpiBytes) -+ } -+ return -+} -+ -+// writeBig serializes a *big.Int to w. -+func writeBig(w io.Writer, i *big.Int) error { -+ return writeMPI(w, uint16(i.BitLen()), i.Bytes()) -+} -+ -+// padToKeySize left-pads a MPI with zeroes to match the length of the -+// specified RSA public. -+func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { -+ k := (pub.N.BitLen() + 7) / 8 -+ if len(b) >= k { -+ return b -+ } -+ bb := make([]byte, k) -+ copy(bb[len(bb)-len(b):], b) -+ return bb -+} -+ -+// CompressionAlgo Represents the different compression algorithms -+// supported by OpenPGP (except for BZIP2, which is not currently -+// supported). See Section 9.3 of RFC 4880. -+type CompressionAlgo uint8 -+ -+const ( -+ CompressionNone CompressionAlgo = 0 -+ CompressionZIP CompressionAlgo = 1 -+ CompressionZLIB CompressionAlgo = 2 -+) -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go -new file mode 100644 -index 00000000000000..c8fc4e50c0b994 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/packet_test.go -@@ -0,0 +1,290 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "fmt" -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+ "testing" -+) -+ -+func TestReadFull(t *testing.T) { -+ var out [4]byte -+ -+ b := bytes.NewBufferString("foo") -+ n, err := readFull(b, out[:3]) -+ if n != 3 || err != nil { -+ t.Errorf("full read failed n:%d err:%s", n, err) -+ } -+ -+ b = bytes.NewBufferString("foo") -+ n, err = readFull(b, out[:4]) -+ if n != 3 || err != io.ErrUnexpectedEOF { -+ t.Errorf("partial read failed n:%d err:%s", n, err) -+ } -+ -+ b = bytes.NewBuffer(nil) -+ n, err = readFull(b, out[:3]) -+ if n != 0 || err != io.ErrUnexpectedEOF { -+ t.Errorf("empty read failed n:%d err:%s", n, err) -+ } -+} -+ -+func readerFromHex(s string) io.Reader { -+ data, err := hex.DecodeString(s) -+ if err != nil { -+ panic("readerFromHex: bad input") -+ } -+ return bytes.NewBuffer(data) -+} -+ -+var readLengthTests = []struct { -+ hexInput string -+ length int64 -+ isPartial bool -+ err error -+}{ -+ {"", 0, false, io.ErrUnexpectedEOF}, -+ {"1f", 31, false, nil}, -+ {"c0", 0, false, io.ErrUnexpectedEOF}, -+ {"c101", 256 + 1 + 192, false, nil}, -+ {"e0", 1, true, nil}, -+ {"e1", 2, true, nil}, -+ {"e2", 4, true, nil}, -+ {"ff", 0, false, io.ErrUnexpectedEOF}, -+ {"ff00", 0, false, io.ErrUnexpectedEOF}, -+ {"ff0000", 0, false, io.ErrUnexpectedEOF}, -+ {"ff000000", 0, false, io.ErrUnexpectedEOF}, -+ {"ff00000000", 0, false, nil}, -+ {"ff01020304", 16909060, false, nil}, -+} -+ -+func TestReadLength(t *testing.T) { -+ for i, test := range readLengthTests { -+ length, isPartial, err := readLength(readerFromHex(test.hexInput)) -+ if test.err != nil { -+ if err != test.err { -+ t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) -+ } -+ continue -+ } -+ if err != nil { -+ t.Errorf("%d: unexpected error: %s", i, err) -+ continue -+ } -+ if length != test.length || isPartial != test.isPartial { -+ t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial) -+ } -+ } -+} -+ -+var partialLengthReaderTests = []struct { -+ hexInput string -+ err error -+ hexOutput string -+}{ -+ {"e0", io.ErrUnexpectedEOF, ""}, -+ {"e001", io.ErrUnexpectedEOF, ""}, -+ {"e0010102", nil, "0102"}, -+ {"ff00000000", nil, ""}, -+ {"e10102e1030400", nil, "01020304"}, -+ {"e101", io.ErrUnexpectedEOF, ""}, -+} -+ -+func TestPartialLengthReader(t *testing.T) { -+ for i, test := range partialLengthReaderTests { -+ r := &partialLengthReader{readerFromHex(test.hexInput), 0, true} -+ out, err := io.ReadAll(r) -+ if test.err != nil { -+ if err != test.err { -+ t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) -+ } -+ continue -+ } -+ if err != nil { -+ t.Errorf("%d: unexpected error: %s", i, err) -+ continue -+ } -+ -+ got := fmt.Sprintf("%x", out) -+ if got != test.hexOutput { -+ t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got) -+ } -+ } -+} -+ -+var readHeaderTests = []struct { -+ hexInput string -+ structuralError bool -+ unexpectedEOF bool -+ tag int -+ length int64 -+ hexOutput string -+}{ -+ {"", false, false, 0, 0, ""}, -+ {"7f", true, false, 0, 0, ""}, -+ -+ // Old format headers -+ {"80", false, true, 0, 0, ""}, -+ {"8001", false, true, 0, 1, ""}, -+ {"800102", false, false, 0, 1, "02"}, -+ {"81000102", false, false, 0, 1, "02"}, -+ {"820000000102", false, false, 0, 1, "02"}, -+ {"860000000102", false, false, 1, 1, "02"}, -+ {"83010203", false, false, 0, -1, "010203"}, -+ -+ // New format headers -+ {"c0", false, true, 0, 0, ""}, -+ {"c000", false, false, 0, 0, ""}, -+ {"c00102", false, false, 0, 1, "02"}, -+ {"c0020203", false, false, 0, 2, "0203"}, -+ {"c00202", false, true, 0, 2, ""}, -+ {"c3020203", false, false, 3, 2, "0203"}, -+} -+ -+func TestReadHeader(t *testing.T) { -+ for i, test := range readHeaderTests { -+ tag, length, contents, err := readHeader(readerFromHex(test.hexInput)) -+ if test.structuralError { -+ if _, ok := err.(errors.StructuralError); ok { -+ continue -+ } -+ t.Errorf("%d: expected StructuralError, got:%s", i, err) -+ continue -+ } -+ if err != nil { -+ if len(test.hexInput) == 0 && err == io.EOF { -+ continue -+ } -+ if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { -+ t.Errorf("%d: unexpected error from readHeader: %s", i, err) -+ } -+ continue -+ } -+ if int(tag) != test.tag || length != test.length { -+ t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length) -+ continue -+ } -+ -+ body, err := io.ReadAll(contents) -+ if err != nil { -+ if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { -+ t.Errorf("%d: unexpected error from contents: %s", i, err) -+ } -+ continue -+ } -+ if test.unexpectedEOF { -+ t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i) -+ continue -+ } -+ got := fmt.Sprintf("%x", body) -+ if got != test.hexOutput { -+ t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput) -+ } -+ } -+} -+ -+func TestSerializeHeader(t *testing.T) { -+ tag := packetTypePublicKey -+ lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000} -+ -+ for _, length := range lengths { -+ buf := bytes.NewBuffer(nil) -+ serializeHeader(buf, tag, length) -+ tag2, length2, _, err := readHeader(buf) -+ if err != nil { -+ t.Errorf("length %d, err: %s", length, err) -+ } -+ if tag2 != tag { -+ t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag) -+ } -+ if int(length2) != length { -+ t.Errorf("length %d, length incorrect (got %d)", length, length2) -+ } -+ } -+} -+ -+func TestPartialLengths(t *testing.T) { -+ buf := bytes.NewBuffer(nil) -+ w := new(partialLengthWriter) -+ w.w = noOpCloser{buf} -+ -+ const maxChunkSize = 64 -+ -+ var b [maxChunkSize]byte -+ var n uint8 -+ for l := 1; l <= maxChunkSize; l++ { -+ for i := 0; i < l; i++ { -+ b[i] = n -+ n++ -+ } -+ m, err := w.Write(b[:l]) -+ if m != l { -+ t.Errorf("short write got: %d want: %d", m, l) -+ } -+ if err != nil { -+ t.Errorf("error from write: %s", err) -+ } -+ } -+ if err := w.Close(); err != nil { -+ t.Fatal(err) -+ } -+ -+ // The first packet should be at least 512 bytes. -+ first, err := buf.ReadByte() -+ if err != nil { -+ t.Fatal(err) -+ } -+ if plen := 1 << (first & 0x1f); plen < 512 { -+ t.Errorf("first packet too short: got %d want at least %d", plen, 512) -+ } -+ if err := buf.UnreadByte(); err != nil { -+ t.Fatal(err) -+ } -+ -+ want := (maxChunkSize * (maxChunkSize + 1)) / 2 -+ copyBuf := bytes.NewBuffer(nil) -+ r := &partialLengthReader{buf, 0, true} -+ m, err := io.Copy(copyBuf, r) -+ if m != int64(want) { -+ t.Errorf("short copy got: %d want: %d", m, want) -+ } -+ if err != nil { -+ t.Errorf("error from copy: %s", err) -+ } -+ -+ copyBytes := copyBuf.Bytes() -+ for i := 0; i < want; i++ { -+ if copyBytes[i] != uint8(i) { -+ t.Errorf("bad pattern in copy at %d", i) -+ break -+ } -+ } -+} -+ -+func TestPartialLengthsShortWrite(t *testing.T) { -+ buf := bytes.NewBuffer(nil) -+ w := &partialLengthWriter{ -+ w: noOpCloser{buf}, -+ } -+ data := bytes.Repeat([]byte("a"), 510) -+ if _, err := w.Write(data); err != nil { -+ t.Fatal(err) -+ } -+ if err := w.Close(); err != nil { -+ t.Fatal(err) -+ } -+ copyBuf := bytes.NewBuffer(nil) -+ r := &partialLengthReader{buf, 0, true} -+ if _, err := io.Copy(copyBuf, r); err != nil { -+ t.Fatal(err) -+ } -+ if !bytes.Equal(copyBuf.Bytes(), data) { -+ t.Errorf("got %q want %q", buf.Bytes(), data) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go -new file mode 100644 -index 00000000000000..192aac376d1af0 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key.go -@@ -0,0 +1,384 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/cipher" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/rsa" -+ "crypto/sha1" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/elgamal" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// PrivateKey represents a possibly encrypted private key. See RFC 4880, -+// section 5.5.3. -+type PrivateKey struct { -+ PublicKey -+ Encrypted bool // if true then the private key is unavailable until Decrypt has been called. -+ encryptedData []byte -+ cipher CipherFunction -+ s2k func(out, in []byte) -+ PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). -+ sha1Checksum bool -+ iv []byte -+} -+ -+func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { -+ pk := new(PrivateKey) -+ pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) -+ pk.PrivateKey = priv -+ return pk -+} -+ -+// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that -+// implements RSA or ECDSA. -+func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey { -+ pk := new(PrivateKey) -+ // In general, the public Keys should be used as pointers. We still -+ // type-switch on the values, for backwards-compatibility. -+ switch pubkey := signer.Public().(type) { -+ case *rsa.PublicKey: -+ pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey) -+ case rsa.PublicKey: -+ pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey) -+ case *ecdsa.PublicKey: -+ pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey) -+ case ecdsa.PublicKey: -+ pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey) -+ default: -+ panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") -+ } -+ pk.PrivateKey = signer -+ return pk -+} -+ -+func (pk *PrivateKey) parse(r io.Reader) (err error) { -+ err = (&pk.PublicKey).parse(r) -+ if err != nil { -+ return -+ } -+ var buf [1]byte -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ -+ s2kType := buf[0] -+ -+ switch s2kType { -+ case 0: -+ pk.s2k = nil -+ pk.Encrypted = false -+ case 254, 255: -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ pk.cipher = CipherFunction(buf[0]) -+ pk.Encrypted = true -+ pk.s2k, err = s2k.Parse(r) -+ if err != nil { -+ return -+ } -+ if s2kType == 254 { -+ pk.sha1Checksum = true -+ } -+ default: -+ return errors.UnsupportedError("deprecated s2k function in private key") -+ } -+ -+ if pk.Encrypted { -+ blockSize := pk.cipher.blockSize() -+ if blockSize == 0 { -+ return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) -+ } -+ pk.iv = make([]byte, blockSize) -+ _, err = readFull(r, pk.iv) -+ if err != nil { -+ return -+ } -+ } -+ -+ pk.encryptedData, err = io.ReadAll(r) -+ if err != nil { -+ return -+ } -+ -+ if !pk.Encrypted { -+ return pk.parsePrivateKey(pk.encryptedData) -+ } -+ -+ return -+} -+ -+func mod64kHash(d []byte) uint16 { -+ var h uint16 -+ for _, b := range d { -+ h += uint16(b) -+ } -+ return h -+} -+ -+func (pk *PrivateKey) Serialize(w io.Writer) (err error) { -+ // TODO(agl): support encrypted private keys -+ buf := bytes.NewBuffer(nil) -+ err = pk.PublicKey.serializeWithoutHeaders(buf) -+ if err != nil { -+ return -+ } -+ buf.WriteByte(0 /* no encryption */) -+ -+ privateKeyBuf := bytes.NewBuffer(nil) -+ -+ switch priv := pk.PrivateKey.(type) { -+ case *rsa.PrivateKey: -+ err = serializeRSAPrivateKey(privateKeyBuf, priv) -+ case *dsa.PrivateKey: -+ err = serializeDSAPrivateKey(privateKeyBuf, priv) -+ case *elgamal.PrivateKey: -+ err = serializeElGamalPrivateKey(privateKeyBuf, priv) -+ case *ecdsa.PrivateKey: -+ err = serializeECDSAPrivateKey(privateKeyBuf, priv) -+ default: -+ err = errors.InvalidArgumentError("unknown private key type") -+ } -+ if err != nil { -+ return -+ } -+ -+ ptype := packetTypePrivateKey -+ contents := buf.Bytes() -+ privateKeyBytes := privateKeyBuf.Bytes() -+ if pk.IsSubkey { -+ ptype = packetTypePrivateSubkey -+ } -+ err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(contents) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(privateKeyBytes) -+ if err != nil { -+ return -+ } -+ -+ checksum := mod64kHash(privateKeyBytes) -+ var checksumBytes [2]byte -+ checksumBytes[0] = byte(checksum >> 8) -+ checksumBytes[1] = byte(checksum) -+ _, err = w.Write(checksumBytes[:]) -+ -+ return -+} -+ -+func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { -+ err := writeBig(w, priv.D) -+ if err != nil { -+ return err -+ } -+ err = writeBig(w, priv.Primes[1]) -+ if err != nil { -+ return err -+ } -+ err = writeBig(w, priv.Primes[0]) -+ if err != nil { -+ return err -+ } -+ return writeBig(w, priv.Precomputed.Qinv) -+} -+ -+func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { -+ return writeBig(w, priv.X) -+} -+ -+func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { -+ return writeBig(w, priv.X) -+} -+ -+func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { -+ return writeBig(w, priv.D) -+} -+ -+// Decrypt decrypts an encrypted private key using a passphrase. -+func (pk *PrivateKey) Decrypt(passphrase []byte) error { -+ if !pk.Encrypted { -+ return nil -+ } -+ -+ key := make([]byte, pk.cipher.KeySize()) -+ pk.s2k(key, passphrase) -+ block := pk.cipher.new(key) -+ cfb := cipher.NewCFBDecrypter(block, pk.iv) -+ -+ data := make([]byte, len(pk.encryptedData)) -+ cfb.XORKeyStream(data, pk.encryptedData) -+ -+ if pk.sha1Checksum { -+ if len(data) < sha1.Size { -+ return errors.StructuralError("truncated private key data") -+ } -+ h := sha1.New() -+ h.Write(data[:len(data)-sha1.Size]) -+ sum := h.Sum(nil) -+ if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { -+ return errors.StructuralError("private key checksum failure") -+ } -+ data = data[:len(data)-sha1.Size] -+ } else { -+ if len(data) < 2 { -+ return errors.StructuralError("truncated private key data") -+ } -+ var sum uint16 -+ for i := 0; i < len(data)-2; i++ { -+ sum += uint16(data[i]) -+ } -+ if data[len(data)-2] != uint8(sum>>8) || -+ data[len(data)-1] != uint8(sum) { -+ return errors.StructuralError("private key checksum failure") -+ } -+ data = data[:len(data)-2] -+ } -+ -+ return pk.parsePrivateKey(data) -+} -+ -+func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { -+ switch pk.PublicKey.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: -+ return pk.parseRSAPrivateKey(data) -+ case PubKeyAlgoDSA: -+ return pk.parseDSAPrivateKey(data) -+ case PubKeyAlgoElGamal: -+ return pk.parseElGamalPrivateKey(data) -+ case PubKeyAlgoECDSA: -+ return pk.parseECDSAPrivateKey(data) -+ } -+ panic("impossible") -+} -+ -+func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { -+ rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) -+ rsaPriv := new(rsa.PrivateKey) -+ rsaPriv.PublicKey = *rsaPub -+ -+ buf := bytes.NewBuffer(data) -+ d, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ p, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ q, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ rsaPriv.D = new(big.Int).SetBytes(d) -+ rsaPriv.Primes = make([]*big.Int, 2) -+ rsaPriv.Primes[0] = new(big.Int).SetBytes(p) -+ rsaPriv.Primes[1] = new(big.Int).SetBytes(q) -+ if err := rsaPriv.Validate(); err != nil { -+ return err -+ } -+ rsaPriv.Precompute() -+ pk.PrivateKey = rsaPriv -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -+ -+func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { -+ dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) -+ dsaPriv := new(dsa.PrivateKey) -+ dsaPriv.PublicKey = *dsaPub -+ -+ buf := bytes.NewBuffer(data) -+ x, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ dsaPriv.X = new(big.Int).SetBytes(x) -+ pk.PrivateKey = dsaPriv -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -+ -+func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { -+ pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) -+ priv := new(elgamal.PrivateKey) -+ priv.PublicKey = *pub -+ -+ buf := bytes.NewBuffer(data) -+ x, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ priv.X = new(big.Int).SetBytes(x) -+ pk.PrivateKey = priv -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -+ -+func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { -+ ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) -+ -+ buf := bytes.NewBuffer(data) -+ d, _, err := readMPI(buf) -+ if err != nil { -+ return -+ } -+ -+ pk.PrivateKey = &ecdsa.PrivateKey{ -+ PublicKey: *ecdsaPub, -+ D: new(big.Int).SetBytes(d), -+ } -+ pk.Encrypted = false -+ pk.encryptedData = nil -+ -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go -new file mode 100644 -index 00000000000000..cc08b48371e40b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/private_key_test.go -@@ -0,0 +1,249 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/x509" -+ "encoding/hex" -+ "hash" -+ "testing" -+ "time" -+) -+ -+var privateKeyTests = []struct { -+ privateKeyHex string -+ creationTime time.Time -+}{ -+ { -+ privKeyRSAHex, -+ time.Unix(0x4cc349a8, 0), -+ }, -+ { -+ privKeyElGamalHex, -+ time.Unix(0x4df9ee1a, 0), -+ }, -+} -+ -+func TestPrivateKeyRead(t *testing.T) { -+ for i, test := range privateKeyTests { -+ packet, err := Read(readerFromHex(test.privateKeyHex)) -+ if err != nil { -+ t.Errorf("#%d: failed to parse: %s", i, err) -+ continue -+ } -+ -+ privKey := packet.(*PrivateKey) -+ -+ if !privKey.Encrypted { -+ t.Errorf("#%d: private key isn't encrypted", i) -+ continue -+ } -+ -+ err = privKey.Decrypt([]byte("wrong password")) -+ if err == nil { -+ t.Errorf("#%d: decrypted with incorrect key", i) -+ continue -+ } -+ -+ err = privKey.Decrypt([]byte("testing")) -+ if err != nil { -+ t.Errorf("#%d: failed to decrypt: %s", i, err) -+ continue -+ } -+ -+ if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted { -+ t.Errorf("#%d: bad result, got: %#v", i, privKey) -+ } -+ } -+} -+ -+func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) { -+ h := hashFunc.New() -+ if _, err := h.Write(msg); err != nil { -+ return nil, err -+ } -+ return h, nil -+} -+ -+func TestRSAPrivateKey(t *testing.T) { -+ privKeyDER, _ := hex.DecodeString(pkcs1PrivKeyHex) -+ rsaPriv, err := x509.ParsePKCS1PrivateKey(privKeyDER) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ var buf bytes.Buffer -+ if err := NewRSAPrivateKey(time.Now(), rsaPriv).Serialize(&buf); err != nil { -+ t.Fatal(err) -+ } -+ -+ p, err := Read(&buf) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ priv, ok := p.(*PrivateKey) -+ if !ok { -+ t.Fatal("didn't parse private key") -+ } -+ -+ sig := &Signature{ -+ PubKeyAlgo: PubKeyAlgoRSA, -+ Hash: crypto.SHA256, -+ } -+ msg := []byte("Hello World!") -+ -+ h, err := populateHash(sig.Hash, msg) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := sig.Sign(h, priv, nil); err != nil { -+ t.Fatal(err) -+ } -+ -+ if h, err = populateHash(sig.Hash, msg); err != nil { -+ t.Fatal(err) -+ } -+ if err := priv.VerifySignature(h, sig); err != nil { -+ t.Fatal(err) -+ } -+} -+ -+func TestECDSAPrivateKey(t *testing.T) { -+ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ var buf bytes.Buffer -+ if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil { -+ t.Fatal(err) -+ } -+ -+ p, err := Read(&buf) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ priv, ok := p.(*PrivateKey) -+ if !ok { -+ t.Fatal("didn't parse private key") -+ } -+ -+ sig := &Signature{ -+ PubKeyAlgo: PubKeyAlgoECDSA, -+ Hash: crypto.SHA256, -+ } -+ msg := []byte("Hello World!") -+ -+ h, err := populateHash(sig.Hash, msg) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := sig.Sign(h, priv, nil); err != nil { -+ t.Fatal(err) -+ } -+ -+ if h, err = populateHash(sig.Hash, msg); err != nil { -+ t.Fatal(err) -+ } -+ if err := priv.VerifySignature(h, sig); err != nil { -+ t.Fatal(err) -+ } -+} -+ -+type rsaSigner struct { -+ *rsa.PrivateKey -+} -+ -+func TestRSASignerPrivateKey(t *testing.T) { -+ rsaPriv, err := rsa.GenerateKey(rand.Reader, 1024) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ priv := NewSignerPrivateKey(time.Now(), &rsaSigner{rsaPriv}) -+ -+ sig := &Signature{ -+ PubKeyAlgo: PubKeyAlgoRSA, -+ Hash: crypto.SHA256, -+ } -+ msg := []byte("Hello World!") -+ -+ h, err := populateHash(sig.Hash, msg) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := sig.Sign(h, priv, nil); err != nil { -+ t.Fatal(err) -+ } -+ -+ if h, err = populateHash(sig.Hash, msg); err != nil { -+ t.Fatal(err) -+ } -+ if err := priv.VerifySignature(h, sig); err != nil { -+ t.Fatal(err) -+ } -+} -+ -+type ecdsaSigner struct { -+ *ecdsa.PrivateKey -+} -+ -+func TestECDSASignerPrivateKey(t *testing.T) { -+ ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ priv := NewSignerPrivateKey(time.Now(), &ecdsaSigner{ecdsaPriv}) -+ -+ if priv.PubKeyAlgo != PubKeyAlgoECDSA { -+ t.Fatal("NewSignerPrivateKey should have made an ECSDA private key") -+ } -+ -+ sig := &Signature{ -+ PubKeyAlgo: PubKeyAlgoECDSA, -+ Hash: crypto.SHA256, -+ } -+ msg := []byte("Hello World!") -+ -+ h, err := populateHash(sig.Hash, msg) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := sig.Sign(h, priv, nil); err != nil { -+ t.Fatal(err) -+ } -+ -+ if h, err = populateHash(sig.Hash, msg); err != nil { -+ t.Fatal(err) -+ } -+ if err := priv.VerifySignature(h, sig); err != nil { -+ t.Fatal(err) -+ } -+} -+ -+func TestIssue11505(t *testing.T) { -+ // parsing a rsa private key with p or q == 1 used to panic due to a divide by zero -+ _, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030")) -+} -+ -+// Generated with `gpg --export-secret-keys "Test Key 2"` -+const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" -+ -+// Generated by `gpg --export-secret-keys` followed by a manual extraction of -+// the ElGamal subkey from the packets. -+const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" -+ -+// pkcs1PrivKeyHex is a PKCS#1, RSA private key. -+// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p` -+const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7" -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go -new file mode 100644 -index 00000000000000..fcd5f5251963b3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key.go -@@ -0,0 +1,753 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+ "encoding/binary" -+ "fmt" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/elgamal" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+var ( -+ // NIST curve P-256 -+ oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} -+ // NIST curve P-384 -+ oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} -+ // NIST curve P-521 -+ oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} -+) -+ -+const maxOIDLength = 8 -+ -+// ecdsaKey stores the algorithm-specific fields for ECDSA keys. -+// as defined in RFC 6637, Section 9. -+type ecdsaKey struct { -+ // oid contains the OID byte sequence identifying the elliptic curve used -+ oid []byte -+ // p contains the elliptic curve point that represents the public key -+ p parsedMPI -+} -+ -+// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. -+func parseOID(r io.Reader) (oid []byte, err error) { -+ buf := make([]byte, maxOIDLength) -+ if _, err = readFull(r, buf[:1]); err != nil { -+ return -+ } -+ oidLen := buf[0] -+ if int(oidLen) > len(buf) { -+ err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) -+ return -+ } -+ oid = buf[:oidLen] -+ _, err = readFull(r, oid) -+ return -+} -+ -+func (f *ecdsaKey) parse(r io.Reader) (err error) { -+ if f.oid, err = parseOID(r); err != nil { -+ return err -+ } -+ f.p.bytes, f.p.bitLength, err = readMPI(r) -+ return -+} -+ -+func (f *ecdsaKey) serialize(w io.Writer) (err error) { -+ buf := make([]byte, maxOIDLength+1) -+ buf[0] = byte(len(f.oid)) -+ copy(buf[1:], f.oid) -+ if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { -+ return -+ } -+ return writeMPIs(w, f.p) -+} -+ -+func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { -+ var c elliptic.Curve -+ if bytes.Equal(f.oid, oidCurveP256) { -+ c = elliptic.P256() -+ } else if bytes.Equal(f.oid, oidCurveP384) { -+ c = elliptic.P384() -+ } else if bytes.Equal(f.oid, oidCurveP521) { -+ c = elliptic.P521() -+ } else { -+ return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) -+ } -+ x, y := elliptic.Unmarshal(c, f.p.bytes) -+ if x == nil { -+ return nil, errors.UnsupportedError("failed to parse EC point") -+ } -+ return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil -+} -+ -+func (f *ecdsaKey) byteLen() int { -+ return 1 + len(f.oid) + 2 + len(f.p.bytes) -+} -+ -+type kdfHashFunction byte -+type kdfAlgorithm byte -+ -+// ecdhKdf stores key derivation function parameters -+// used for ECDH encryption. See RFC 6637, Section 9. -+type ecdhKdf struct { -+ KdfHash kdfHashFunction -+ KdfAlgo kdfAlgorithm -+} -+ -+func (f *ecdhKdf) parse(r io.Reader) (err error) { -+ buf := make([]byte, 1) -+ if _, err = readFull(r, buf); err != nil { -+ return -+ } -+ kdfLen := int(buf[0]) -+ if kdfLen < 3 { -+ return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) -+ } -+ buf = make([]byte, kdfLen) -+ if _, err = readFull(r, buf); err != nil { -+ return -+ } -+ reserved := int(buf[0]) -+ f.KdfHash = kdfHashFunction(buf[1]) -+ f.KdfAlgo = kdfAlgorithm(buf[2]) -+ if reserved != 0x01 { -+ return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) -+ } -+ return -+} -+ -+func (f *ecdhKdf) serialize(w io.Writer) (err error) { -+ buf := make([]byte, 4) -+ // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. -+ buf[0] = byte(0x03) // Length of the following fields -+ buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now -+ buf[2] = byte(f.KdfHash) -+ buf[3] = byte(f.KdfAlgo) -+ _, err = w.Write(buf[:]) -+ return -+} -+ -+func (f *ecdhKdf) byteLen() int { -+ return 4 -+} -+ -+// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. -+type PublicKey struct { -+ CreationTime time.Time -+ PubKeyAlgo PublicKeyAlgorithm -+ PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey -+ Fingerprint [20]byte -+ KeyId uint64 -+ IsSubkey bool -+ -+ n, e, p, q, g, y parsedMPI -+ -+ // RFC 6637 fields -+ ec *ecdsaKey -+ ecdh *ecdhKdf -+} -+ -+// signingKey provides a convenient abstraction over signature verification -+// for v3 and v4 public keys. -+type signingKey interface { -+ SerializeSignaturePrefix(io.Writer) -+ serializeWithoutHeaders(io.Writer) error -+} -+ -+func fromBig(n *big.Int) parsedMPI { -+ return parsedMPI{ -+ bytes: n.Bytes(), -+ bitLength: uint16(n.BitLen()), -+ } -+} -+ -+// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. -+func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoRSA, -+ PublicKey: pub, -+ n: fromBig(pub.N), -+ e: fromBig(big.NewInt(int64(pub.E))), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. -+func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoDSA, -+ PublicKey: pub, -+ p: fromBig(pub.P), -+ q: fromBig(pub.Q), -+ g: fromBig(pub.G), -+ y: fromBig(pub.Y), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. -+func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoElGamal, -+ PublicKey: pub, -+ p: fromBig(pub.P), -+ g: fromBig(pub.G), -+ y: fromBig(pub.Y), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { -+ pk := &PublicKey{ -+ CreationTime: creationTime, -+ PubKeyAlgo: PubKeyAlgoECDSA, -+ PublicKey: pub, -+ ec: new(ecdsaKey), -+ } -+ -+ switch pub.Curve { -+ case elliptic.P256(): -+ pk.ec.oid = oidCurveP256 -+ case elliptic.P384(): -+ pk.ec.oid = oidCurveP384 -+ case elliptic.P521(): -+ pk.ec.oid = oidCurveP521 -+ default: -+ panic("unknown elliptic curve") -+ } -+ -+ pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) -+ -+ // The bit length is 3 (for the 0x04 specifying an uncompressed key) -+ // plus two field elements (for x and y), which are rounded up to the -+ // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 -+ fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 -+ pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+func (pk *PublicKey) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.5.2 -+ var buf [6]byte -+ _, err = readFull(r, buf[:]) -+ if err != nil { -+ return -+ } -+ if buf[0] != 4 { -+ return errors.UnsupportedError("public key version") -+ } -+ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) -+ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ err = pk.parseRSA(r) -+ case PubKeyAlgoDSA: -+ err = pk.parseDSA(r) -+ case PubKeyAlgoElGamal: -+ err = pk.parseElGamal(r) -+ case PubKeyAlgoECDSA: -+ pk.ec = new(ecdsaKey) -+ if err = pk.ec.parse(r); err != nil { -+ return err -+ } -+ pk.PublicKey, err = pk.ec.newECDSA() -+ case PubKeyAlgoECDH: -+ pk.ec = new(ecdsaKey) -+ if err = pk.ec.parse(r); err != nil { -+ return -+ } -+ pk.ecdh = new(ecdhKdf) -+ if err = pk.ecdh.parse(r); err != nil { -+ return -+ } -+ // The ECDH key is stored in an ecdsa.PublicKey for convenience. -+ pk.PublicKey, err = pk.ec.newECDSA() -+ default: -+ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) -+ } -+ if err != nil { -+ return -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return -+} -+ -+func (pk *PublicKey) setFingerPrintAndKeyId() { -+ // RFC 4880, section 12.2 -+ fingerPrint := sha1.New() -+ pk.SerializeSignaturePrefix(fingerPrint) -+ pk.serializeWithoutHeaders(fingerPrint) -+ copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) -+ pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) -+} -+ -+// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -+// section 5.5.2. -+func (pk *PublicKey) parseRSA(r io.Reader) (err error) { -+ pk.n.bytes, pk.n.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.e.bytes, pk.e.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ -+ if len(pk.e.bytes) > 3 { -+ err = errors.UnsupportedError("large public exponent") -+ return -+ } -+ rsa := &rsa.PublicKey{ -+ N: new(big.Int).SetBytes(pk.n.bytes), -+ E: 0, -+ } -+ for i := 0; i < len(pk.e.bytes); i++ { -+ rsa.E <<= 8 -+ rsa.E |= int(pk.e.bytes[i]) -+ } -+ pk.PublicKey = rsa -+ return -+} -+ -+// parseDSA parses DSA public key material from the given Reader. See RFC 4880, -+// section 5.5.2. -+func (pk *PublicKey) parseDSA(r io.Reader) (err error) { -+ pk.p.bytes, pk.p.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.q.bytes, pk.q.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.g.bytes, pk.g.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.y.bytes, pk.y.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ -+ dsa := new(dsa.PublicKey) -+ dsa.P = new(big.Int).SetBytes(pk.p.bytes) -+ dsa.Q = new(big.Int).SetBytes(pk.q.bytes) -+ dsa.G = new(big.Int).SetBytes(pk.g.bytes) -+ dsa.Y = new(big.Int).SetBytes(pk.y.bytes) -+ pk.PublicKey = dsa -+ return -+} -+ -+// parseElGamal parses ElGamal public key material from the given Reader. See -+// RFC 4880, section 5.5.2. -+func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { -+ pk.p.bytes, pk.p.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.g.bytes, pk.g.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ pk.y.bytes, pk.y.bitLength, err = readMPI(r) -+ if err != nil { -+ return -+ } -+ -+ elgamal := new(elgamal.PublicKey) -+ elgamal.P = new(big.Int).SetBytes(pk.p.bytes) -+ elgamal.G = new(big.Int).SetBytes(pk.g.bytes) -+ elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) -+ pk.PublicKey = elgamal -+ return -+} -+ -+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -+// The prefix is used when calculating a signature over this public key. See -+// RFC 4880, section 5.2.4. -+func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { -+ var pLength uint16 -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ pLength += 2 + uint16(len(pk.n.bytes)) -+ pLength += 2 + uint16(len(pk.e.bytes)) -+ case PubKeyAlgoDSA: -+ pLength += 2 + uint16(len(pk.p.bytes)) -+ pLength += 2 + uint16(len(pk.q.bytes)) -+ pLength += 2 + uint16(len(pk.g.bytes)) -+ pLength += 2 + uint16(len(pk.y.bytes)) -+ case PubKeyAlgoElGamal: -+ pLength += 2 + uint16(len(pk.p.bytes)) -+ pLength += 2 + uint16(len(pk.g.bytes)) -+ pLength += 2 + uint16(len(pk.y.bytes)) -+ case PubKeyAlgoECDSA: -+ pLength += uint16(pk.ec.byteLen()) -+ case PubKeyAlgoECDH: -+ pLength += uint16(pk.ec.byteLen()) -+ pLength += uint16(pk.ecdh.byteLen()) -+ default: -+ panic("unknown public key algorithm") -+ } -+ pLength += 6 -+ h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) -+ return -+} -+ -+func (pk *PublicKey) Serialize(w io.Writer) (err error) { -+ length := 6 // 6 byte header -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ length += 2 + len(pk.n.bytes) -+ length += 2 + len(pk.e.bytes) -+ case PubKeyAlgoDSA: -+ length += 2 + len(pk.p.bytes) -+ length += 2 + len(pk.q.bytes) -+ length += 2 + len(pk.g.bytes) -+ length += 2 + len(pk.y.bytes) -+ case PubKeyAlgoElGamal: -+ length += 2 + len(pk.p.bytes) -+ length += 2 + len(pk.g.bytes) -+ length += 2 + len(pk.y.bytes) -+ case PubKeyAlgoECDSA: -+ length += pk.ec.byteLen() -+ case PubKeyAlgoECDH: -+ length += pk.ec.byteLen() -+ length += pk.ecdh.byteLen() -+ default: -+ panic("unknown public key algorithm") -+ } -+ -+ packetType := packetTypePublicKey -+ if pk.IsSubkey { -+ packetType = packetTypePublicSubkey -+ } -+ err = serializeHeader(w, packetType, length) -+ if err != nil { -+ return -+ } -+ return pk.serializeWithoutHeaders(w) -+} -+ -+// serializeWithoutHeaders marshals the PublicKey to w in the form of an -+// OpenPGP public key packet, not including the packet header. -+func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { -+ var buf [6]byte -+ buf[0] = 4 -+ t := uint32(pk.CreationTime.Unix()) -+ buf[1] = byte(t >> 24) -+ buf[2] = byte(t >> 16) -+ buf[3] = byte(t >> 8) -+ buf[4] = byte(t) -+ buf[5] = byte(pk.PubKeyAlgo) -+ -+ _, err = w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ return writeMPIs(w, pk.n, pk.e) -+ case PubKeyAlgoDSA: -+ return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) -+ case PubKeyAlgoElGamal: -+ return writeMPIs(w, pk.p, pk.g, pk.y) -+ case PubKeyAlgoECDSA: -+ return pk.ec.serialize(w) -+ case PubKeyAlgoECDH: -+ if err = pk.ec.serialize(w); err != nil { -+ return -+ } -+ return pk.ecdh.serialize(w) -+ } -+ return errors.InvalidArgumentError("bad public-key algorithm") -+} -+ -+// CanSign returns true iff this public key can generate signatures -+func (pk *PublicKey) CanSign() bool { -+ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal -+} -+ -+// VerifySignature returns nil iff sig is a valid signature, made by this -+// public key, of the data hashed into signed. signed is mutated by this call. -+func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { -+ if !pk.CanSign() { -+ return errors.InvalidArgumentError("public key cannot generate signatures") -+ } -+ -+ signed.Write(sig.HashSuffix) -+ hashBytes := signed.Sum(nil) -+ -+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { -+ return errors.SignatureError("hash tag doesn't match") -+ } -+ -+ if pk.PubKeyAlgo != sig.PubKeyAlgo { -+ return errors.InvalidArgumentError("public key and signature use different algorithms") -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) -+ err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) -+ if err != nil { -+ return errors.SignatureError("RSA verification failure") -+ } -+ return nil -+ case PubKeyAlgoDSA: -+ dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) -+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. -+ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 -+ if len(hashBytes) > subgroupSize { -+ hashBytes = hashBytes[:subgroupSize] -+ } -+ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { -+ return errors.SignatureError("DSA verification failure") -+ } -+ return nil -+ case PubKeyAlgoECDSA: -+ ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) -+ if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { -+ return errors.SignatureError("ECDSA verification failure") -+ } -+ return nil -+ default: -+ return errors.SignatureError("Unsupported public key algorithm used in signature") -+ } -+} -+ -+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, of the data hashed into signed. signed is mutated by this call. -+func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { -+ if !pk.CanSign() { -+ return errors.InvalidArgumentError("public key cannot generate signatures") -+ } -+ -+ suffix := make([]byte, 5) -+ suffix[0] = byte(sig.SigType) -+ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) -+ signed.Write(suffix) -+ hashBytes := signed.Sum(nil) -+ -+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { -+ return errors.SignatureError("hash tag doesn't match") -+ } -+ -+ if pk.PubKeyAlgo != sig.PubKeyAlgo { -+ return errors.InvalidArgumentError("public key and signature use different algorithms") -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) -+ if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { -+ return errors.SignatureError("RSA verification failure") -+ } -+ return -+ case PubKeyAlgoDSA: -+ dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) -+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. -+ subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 -+ if len(hashBytes) > subgroupSize { -+ hashBytes = hashBytes[:subgroupSize] -+ } -+ if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { -+ return errors.SignatureError("DSA verification failure") -+ } -+ return nil -+ default: -+ panic("shouldn't happen") -+ } -+} -+ -+// keySignatureHash returns a Hash of the message that needs to be signed for -+// pk to assert a subkey relationship to signed. -+func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { -+ if !hashFunc.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hashFunc.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ signed.SerializeSignaturePrefix(h) -+ signed.serializeWithoutHeaders(h) -+ return -+} -+ -+// VerifyKeySignature returns nil iff sig is a valid signature, made by this -+// public key, of signed. -+func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { -+ h, err := keySignatureHash(pk, signed, sig.Hash) -+ if err != nil { -+ return err -+ } -+ if err = pk.VerifySignature(h, sig); err != nil { -+ return err -+ } -+ -+ if sig.FlagSign { -+ // Signing subkeys must be cross-signed. See -+ // https://www.gnupg.org/faq/subkey-cross-certify.html. -+ if sig.EmbeddedSignature == nil { -+ return errors.StructuralError("signing subkey is missing cross-signature") -+ } -+ // Verify the cross-signature. This is calculated over the same -+ // data as the main signature, so we cannot just recursively -+ // call signed.VerifyKeySignature(...) -+ if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { -+ return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) -+ } -+ if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { -+ return errors.StructuralError("error while verifying cross-signature: " + err.Error()) -+ } -+ } -+ -+ return nil -+} -+ -+func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { -+ if !hashFunc.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hashFunc.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ -+ return -+} -+ -+// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this -+// public key. -+func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { -+ h, err := keyRevocationHash(pk, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignature(h, sig) -+} -+ -+// userIdSignatureHash returns a Hash of the message that needs to be signed -+// to assert that pk is a valid key for id. -+func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { -+ if !hashFunc.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hashFunc.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ -+ var buf [5]byte -+ buf[0] = 0xb4 -+ buf[1] = byte(len(id) >> 24) -+ buf[2] = byte(len(id) >> 16) -+ buf[3] = byte(len(id) >> 8) -+ buf[4] = byte(len(id)) -+ h.Write(buf[:]) -+ h.Write([]byte(id)) -+ -+ return -+} -+ -+// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this -+// public key, that id is the identity of pub. -+func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { -+ h, err := userIdSignatureHash(id, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignature(h, sig) -+} -+ -+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, that id is the identity of pub. -+func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { -+ h, err := userIdSignatureV3Hash(id, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignatureV3(h, sig) -+} -+ -+// KeyIdString returns the public key's fingerprint in capital hex -+// (e.g. "6C7EE1B8621CC013"). -+func (pk *PublicKey) KeyIdString() string { -+ return fmt.Sprintf("%X", pk.Fingerprint[12:20]) -+} -+ -+// KeyIdShortString returns the short form of public key's fingerprint -+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -+func (pk *PublicKey) KeyIdShortString() string { -+ return fmt.Sprintf("%X", pk.Fingerprint[16:20]) -+} -+ -+// A parsedMPI is used to store the contents of a big integer, along with the -+// bit length that was specified in the original input. This allows the MPI to -+// be reserialized exactly. -+type parsedMPI struct { -+ bytes []byte -+ bitLength uint16 -+} -+ -+// writeMPIs is a utility function for serializing several big integers to the -+// given Writer. -+func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { -+ for _, mpi := range mpis { -+ err = writeMPI(w, mpi.bitLength, mpi.bytes) -+ if err != nil { -+ return -+ } -+ } -+ return -+} -+ -+// BitLength returns the bit length for the given public key. -+func (pk *PublicKey) BitLength() (bitLength uint16, err error) { -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ bitLength = pk.n.bitLength -+ case PubKeyAlgoDSA: -+ bitLength = pk.p.bitLength -+ case PubKeyAlgoElGamal: -+ bitLength = pk.p.bitLength -+ default: -+ err = errors.InvalidArgumentError("bad public-key algorithm") -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go -new file mode 100644 -index 00000000000000..103696ee7ce1cf ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_test.go -@@ -0,0 +1,228 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "encoding/hex" -+ "math/big" -+ "testing" -+ "time" -+) -+ -+var pubKeyTests = []struct { -+ hexData string -+ hexFingerprint string -+ creationTime time.Time -+ pubKeyAlgo PublicKeyAlgorithm -+ keyId uint64 -+ keyIdString string -+ keyIdShort string -+}{ -+ {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"}, -+ {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"}, -+ {ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"}, -+} -+ -+func TestPublicKeyRead(t *testing.T) { -+ for i, test := range pubKeyTests { -+ packet, err := Read(readerFromHex(test.hexData)) -+ if err != nil { -+ t.Errorf("#%d: Read error: %s", i, err) -+ continue -+ } -+ pk, ok := packet.(*PublicKey) -+ if !ok { -+ t.Errorf("#%d: failed to parse, got: %#v", i, packet) -+ continue -+ } -+ if pk.PubKeyAlgo != test.pubKeyAlgo { -+ t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) -+ } -+ if !pk.CreationTime.Equal(test.creationTime) { -+ t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) -+ } -+ expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) -+ if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { -+ t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) -+ } -+ if pk.KeyId != test.keyId { -+ t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) -+ } -+ if g, e := pk.KeyIdString(), test.keyIdString; g != e { -+ t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) -+ } -+ if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { -+ t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) -+ } -+ } -+} -+ -+func TestPublicKeySerialize(t *testing.T) { -+ for i, test := range pubKeyTests { -+ packet, err := Read(readerFromHex(test.hexData)) -+ if err != nil { -+ t.Errorf("#%d: Read error: %s", i, err) -+ continue -+ } -+ pk, ok := packet.(*PublicKey) -+ if !ok { -+ t.Errorf("#%d: failed to parse, got: %#v", i, packet) -+ continue -+ } -+ serializeBuf := bytes.NewBuffer(nil) -+ err = pk.Serialize(serializeBuf) -+ if err != nil { -+ t.Errorf("#%d: failed to serialize: %s", i, err) -+ continue -+ } -+ -+ packet, err = Read(serializeBuf) -+ if err != nil { -+ t.Errorf("#%d: Read error (from serialized data): %s", i, err) -+ continue -+ } -+ pk, ok = packet.(*PublicKey) -+ if !ok { -+ t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet) -+ continue -+ } -+ } -+} -+ -+func TestEcc384Serialize(t *testing.T) { -+ r := readerFromHex(ecc384PubHex) -+ var w bytes.Buffer -+ for i := 0; i < 2; i++ { -+ // Public key -+ p, err := Read(r) -+ if err != nil { -+ t.Error(err) -+ } -+ pubkey := p.(*PublicKey) -+ if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { -+ t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid) -+ } -+ if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) { -+ t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes) -+ } -+ if pubkey.KeyId != 0x098033880F54719F { -+ t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId) -+ } -+ err = pubkey.Serialize(&w) -+ if err != nil { -+ t.Error(err) -+ } -+ // User ID -+ p, err = Read(r) -+ if err != nil { -+ t.Error(err) -+ } -+ uid := p.(*UserId) -+ if uid.Id != "ec_dsa_dh_384 " { -+ t.Error("Unexpected UID:", uid.Id) -+ } -+ err = uid.Serialize(&w) -+ if err != nil { -+ t.Error(err) -+ } -+ // User ID Sig -+ p, err = Read(r) -+ if err != nil { -+ t.Error(err) -+ } -+ uidSig := p.(*Signature) -+ err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig) -+ if err != nil { -+ t.Error(err, ": UID") -+ } -+ err = uidSig.Serialize(&w) -+ if err != nil { -+ t.Error(err) -+ } -+ // Subkey -+ p, err = Read(r) -+ if err != nil { -+ t.Error(err) -+ } -+ subkey := p.(*PublicKey) -+ if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { -+ t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid) -+ } -+ if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) { -+ t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes) -+ } -+ if subkey.ecdh.KdfHash != 0x09 { -+ t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash) -+ } -+ if subkey.ecdh.KdfAlgo != 0x09 { -+ t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo) -+ } -+ if subkey.KeyId != 0xAA8B938F9A201946 { -+ t.Errorf("Unexpected subkey ID: %x", subkey.KeyId) -+ } -+ err = subkey.Serialize(&w) -+ if err != nil { -+ t.Error(err) -+ } -+ // Subkey Sig -+ p, err = Read(r) -+ if err != nil { -+ t.Error(err) -+ } -+ subkeySig := p.(*Signature) -+ err = pubkey.VerifyKeySignature(subkey, subkeySig) -+ if err != nil { -+ t.Error(err) -+ } -+ err = subkeySig.Serialize(&w) -+ if err != nil { -+ t.Error(err) -+ } -+ // Now read back what we've written again -+ r = bytes.NewBuffer(w.Bytes()) -+ w.Reset() -+ } -+} -+ -+func TestP256KeyID(t *testing.T) { -+ // Confirm that key IDs are correctly calculated for ECC keys. -+ ecdsaPub := &ecdsa.PublicKey{ -+ Curve: elliptic.P256(), -+ X: fromHex("81fbbc20eea9e8d1c3ceabb0a8185925b113d1ac42cd5c78403bd83da19235c6"), -+ Y: fromHex("5ed6db13d91db34507d0129bf88981878d29adbf8fcd1720afdb767bb3fcaaff"), -+ } -+ pub := NewECDSAPublicKey(time.Unix(1297309478, 0), ecdsaPub) -+ -+ const want = uint64(0xd01055fbcadd268e) -+ if pub.KeyId != want { -+ t.Errorf("want key ID: %x, got %x", want, pub.KeyId) -+ } -+} -+ -+func fromHex(hex string) *big.Int { -+ n, ok := new(big.Int).SetString(hex, 16) -+ if !ok { -+ panic("bad hex number: " + hex) -+ } -+ return n -+} -+ -+const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" -+ -+const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" -+ -+const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" -+ -+const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" -+ -+const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" -+ -+const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" -+ -+// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key -+const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go -new file mode 100644 -index 00000000000000..5daf7b6cfd4a06 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3.go -@@ -0,0 +1,279 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "crypto" -+ "crypto/md5" -+ "crypto/rsa" -+ "encoding/binary" -+ "fmt" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and -+// should not be used for signing or encrypting. They are supported here only for -+// parsing version 3 key material and validating signatures. -+// See RFC 4880, section 5.5.2. -+type PublicKeyV3 struct { -+ CreationTime time.Time -+ DaysToExpire uint16 -+ PubKeyAlgo PublicKeyAlgorithm -+ PublicKey *rsa.PublicKey -+ Fingerprint [16]byte -+ KeyId uint64 -+ IsSubkey bool -+ -+ n, e parsedMPI -+} -+ -+// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. -+// Included here for testing purposes only. RFC 4880, section 5.5.2: -+// "an implementation MUST NOT generate a V3 key, but MAY accept it." -+func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { -+ pk := &PublicKeyV3{ -+ CreationTime: creationTime, -+ PublicKey: pub, -+ n: fromBig(pub.N), -+ e: fromBig(big.NewInt(int64(pub.E))), -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return pk -+} -+ -+func (pk *PublicKeyV3) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.5.2 -+ var buf [8]byte -+ if _, err = readFull(r, buf[:]); err != nil { -+ return -+ } -+ if buf[0] < 2 || buf[0] > 3 { -+ return errors.UnsupportedError("public key version") -+ } -+ pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) -+ pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) -+ pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ err = pk.parseRSA(r) -+ default: -+ err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) -+ } -+ if err != nil { -+ return -+ } -+ -+ pk.setFingerPrintAndKeyId() -+ return -+} -+ -+func (pk *PublicKeyV3) setFingerPrintAndKeyId() { -+ // RFC 4880, section 12.2 -+ fingerPrint := md5.New() -+ fingerPrint.Write(pk.n.bytes) -+ fingerPrint.Write(pk.e.bytes) -+ fingerPrint.Sum(pk.Fingerprint[:0]) -+ pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) -+} -+ -+// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -+// section 5.5.2. -+func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { -+ if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { -+ return -+ } -+ if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { -+ return -+ } -+ -+ // RFC 4880 Section 12.2 requires the low 8 bytes of the -+ // modulus to form the key id. -+ if len(pk.n.bytes) < 8 { -+ return errors.StructuralError("v3 public key modulus is too short") -+ } -+ if len(pk.e.bytes) > 3 { -+ err = errors.UnsupportedError("large public exponent") -+ return -+ } -+ rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} -+ for i := 0; i < len(pk.e.bytes); i++ { -+ rsa.E <<= 8 -+ rsa.E |= int(pk.e.bytes[i]) -+ } -+ pk.PublicKey = rsa -+ return -+} -+ -+// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -+// The prefix is used when calculating a signature over this public key. See -+// RFC 4880, section 5.2.4. -+func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { -+ var pLength uint16 -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ pLength += 2 + uint16(len(pk.n.bytes)) -+ pLength += 2 + uint16(len(pk.e.bytes)) -+ default: -+ panic("unknown public key algorithm") -+ } -+ pLength += 6 -+ w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) -+ return -+} -+ -+func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { -+ length := 8 // 8 byte header -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ length += 2 + len(pk.n.bytes) -+ length += 2 + len(pk.e.bytes) -+ default: -+ panic("unknown public key algorithm") -+ } -+ -+ packetType := packetTypePublicKey -+ if pk.IsSubkey { -+ packetType = packetTypePublicSubkey -+ } -+ if err = serializeHeader(w, packetType, length); err != nil { -+ return -+ } -+ return pk.serializeWithoutHeaders(w) -+} -+ -+// serializeWithoutHeaders marshals the PublicKey to w in the form of an -+// OpenPGP public key packet, not including the packet header. -+func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { -+ var buf [8]byte -+ // Version 3 -+ buf[0] = 3 -+ // Creation time -+ t := uint32(pk.CreationTime.Unix()) -+ buf[1] = byte(t >> 24) -+ buf[2] = byte(t >> 16) -+ buf[3] = byte(t >> 8) -+ buf[4] = byte(t) -+ // Days to expire -+ buf[5] = byte(pk.DaysToExpire >> 8) -+ buf[6] = byte(pk.DaysToExpire) -+ // Public key algorithm -+ buf[7] = byte(pk.PubKeyAlgo) -+ -+ if _, err = w.Write(buf[:]); err != nil { -+ return -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ return writeMPIs(w, pk.n, pk.e) -+ } -+ return errors.InvalidArgumentError("bad public-key algorithm") -+} -+ -+// CanSign returns true iff this public key can generate signatures -+func (pk *PublicKeyV3) CanSign() bool { -+ return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly -+} -+ -+// VerifySignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, of the data hashed into signed. signed is mutated by this call. -+func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { -+ if !pk.CanSign() { -+ return errors.InvalidArgumentError("public key cannot generate signatures") -+ } -+ -+ suffix := make([]byte, 5) -+ suffix[0] = byte(sig.SigType) -+ binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) -+ signed.Write(suffix) -+ hashBytes := signed.Sum(nil) -+ -+ if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { -+ return errors.SignatureError("hash tag doesn't match") -+ } -+ -+ if pk.PubKeyAlgo != sig.PubKeyAlgo { -+ return errors.InvalidArgumentError("public key and signature use different algorithms") -+ } -+ -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { -+ return errors.SignatureError("RSA verification failure") -+ } -+ return -+ default: -+ // V3 public keys only support RSA. -+ panic("shouldn't happen") -+ } -+} -+ -+// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, that id is the identity of pub. -+func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { -+ h, err := userIdSignatureV3Hash(id, pk, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignatureV3(h, sig) -+} -+ -+// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this -+// public key, of signed. -+func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { -+ h, err := keySignatureHash(pk, signed, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return pk.VerifySignatureV3(h, sig) -+} -+ -+// userIdSignatureV3Hash returns a Hash of the message that needs to be signed -+// to assert that pk is a valid key for id. -+func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { -+ if !hfn.Available() { -+ return nil, errors.UnsupportedError("hash function") -+ } -+ h = hfn.New() -+ -+ // RFC 4880, section 5.2.4 -+ pk.SerializeSignaturePrefix(h) -+ pk.serializeWithoutHeaders(h) -+ -+ h.Write([]byte(id)) -+ -+ return -+} -+ -+// KeyIdString returns the public key's fingerprint in capital hex -+// (e.g. "6C7EE1B8621CC013"). -+func (pk *PublicKeyV3) KeyIdString() string { -+ return fmt.Sprintf("%X", pk.KeyId) -+} -+ -+// KeyIdShortString returns the short form of public key's fingerprint -+// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -+func (pk *PublicKeyV3) KeyIdShortString() string { -+ return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) -+} -+ -+// BitLength returns the bit length for the given public key. -+func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { -+ switch pk.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: -+ bitLength = pk.n.bitLength -+ default: -+ err = errors.InvalidArgumentError("bad public-key algorithm") -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go -new file mode 100644 -index 00000000000000..e06405904b3e3b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go -@@ -0,0 +1,82 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "testing" -+ "time" -+) -+ -+var pubKeyV3Test = struct { -+ hexFingerprint string -+ creationTime time.Time -+ pubKeyAlgo PublicKeyAlgorithm -+ keyId uint64 -+ keyIdString string -+ keyIdShort string -+}{ -+ "103BECF5BD1E837C89D19E98487767F7", -+ time.Unix(779753634, 0), -+ PubKeyAlgoRSA, -+ 0xDE0F188A5DA5E3C9, -+ "DE0F188A5DA5E3C9", -+ "5DA5E3C9"} -+ -+func TestPublicKeyV3Read(t *testing.T) { -+ i, test := 0, pubKeyV3Test -+ packet, err := Read(v3KeyReader(t)) -+ if err != nil { -+ t.Fatalf("#%d: Read error: %s", i, err) -+ } -+ pk, ok := packet.(*PublicKeyV3) -+ if !ok { -+ t.Fatalf("#%d: failed to parse, got: %#v", i, packet) -+ } -+ if pk.PubKeyAlgo != test.pubKeyAlgo { -+ t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) -+ } -+ if !pk.CreationTime.Equal(test.creationTime) { -+ t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) -+ } -+ expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) -+ if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { -+ t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) -+ } -+ if pk.KeyId != test.keyId { -+ t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) -+ } -+ if g, e := pk.KeyIdString(), test.keyIdString; g != e { -+ t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) -+ } -+ if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { -+ t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) -+ } -+} -+ -+func TestPublicKeyV3Serialize(t *testing.T) { -+ //for i, test := range pubKeyV3Tests { -+ i := 0 -+ packet, err := Read(v3KeyReader(t)) -+ if err != nil { -+ t.Fatalf("#%d: Read error: %s", i, err) -+ } -+ pk, ok := packet.(*PublicKeyV3) -+ if !ok { -+ t.Fatalf("#%d: failed to parse, got: %#v", i, packet) -+ } -+ var serializeBuf bytes.Buffer -+ if err = pk.Serialize(&serializeBuf); err != nil { -+ t.Fatalf("#%d: failed to serialize: %s", i, err) -+ } -+ -+ if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil { -+ t.Fatalf("#%d: Read error (from serialized data): %s", i, err) -+ } -+ if pk, ok = packet.(*PublicKeyV3); !ok { -+ t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/reader.go b/ms_mod/golang.org/x/crypto/openpgp/packet/reader.go -new file mode 100644 -index 00000000000000..34bc7c613e6e23 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/reader.go -@@ -0,0 +1,76 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+) -+ -+// Reader reads packets from an io.Reader and allows packets to be 'unread' so -+// that they result from the next call to Next. -+type Reader struct { -+ q []Packet -+ readers []io.Reader -+} -+ -+// New io.Readers are pushed when a compressed or encrypted packet is processed -+// and recursively treated as a new source of packets. However, a carefully -+// crafted packet can trigger an infinite recursive sequence of packets. See -+// http://mumble.net/~campbell/misc/pgp-quine -+// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 -+// This constant limits the number of recursive packets that may be pushed. -+const maxReaders = 32 -+ -+// Next returns the most recently unread Packet, or reads another packet from -+// the top-most io.Reader. Unknown packet types are skipped. -+func (r *Reader) Next() (p Packet, err error) { -+ if len(r.q) > 0 { -+ p = r.q[len(r.q)-1] -+ r.q = r.q[:len(r.q)-1] -+ return -+ } -+ -+ for len(r.readers) > 0 { -+ p, err = Read(r.readers[len(r.readers)-1]) -+ if err == nil { -+ return -+ } -+ if err == io.EOF { -+ r.readers = r.readers[:len(r.readers)-1] -+ continue -+ } -+ if _, ok := err.(errors.UnknownPacketTypeError); !ok { -+ return nil, err -+ } -+ } -+ -+ return nil, io.EOF -+} -+ -+// Push causes the Reader to start reading from a new io.Reader. When an EOF -+// error is seen from the new io.Reader, it is popped and the Reader continues -+// to read from the next most recent io.Reader. Push returns a StructuralError -+// if pushing the reader would exceed the maximum recursion level, otherwise it -+// returns nil. -+func (r *Reader) Push(reader io.Reader) (err error) { -+ if len(r.readers) >= maxReaders { -+ return errors.StructuralError("too many layers of packets") -+ } -+ r.readers = append(r.readers, reader) -+ return nil -+} -+ -+// Unread causes the given Packet to be returned from the next call to Next. -+func (r *Reader) Unread(p Packet) { -+ r.q = append(r.q, p) -+} -+ -+func NewReader(r io.Reader) *Reader { -+ return &Reader{ -+ q: nil, -+ readers: []io.Reader{r}, -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature.go -new file mode 100644 -index 00000000000000..b2a24a532327b5 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature.go -@@ -0,0 +1,731 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "encoding/asn1" -+ "encoding/binary" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+const ( -+ // See RFC 4880, section 5.2.3.21 for details. -+ KeyFlagCertify = 1 << iota -+ KeyFlagSign -+ KeyFlagEncryptCommunications -+ KeyFlagEncryptStorage -+) -+ -+// Signature represents a signature. See RFC 4880, section 5.2. -+type Signature struct { -+ SigType SignatureType -+ PubKeyAlgo PublicKeyAlgorithm -+ Hash crypto.Hash -+ -+ // HashSuffix is extra data that is hashed in after the signed data. -+ HashSuffix []byte -+ // HashTag contains the first two bytes of the hash for fast rejection -+ // of bad signed data. -+ HashTag [2]byte -+ CreationTime time.Time -+ -+ RSASignature parsedMPI -+ DSASigR, DSASigS parsedMPI -+ ECDSASigR, ECDSASigS parsedMPI -+ -+ // rawSubpackets contains the unparsed subpackets, in order. -+ rawSubpackets []outputSubpacket -+ -+ // The following are optional so are nil when not included in the -+ // signature. -+ -+ SigLifetimeSecs, KeyLifetimeSecs *uint32 -+ PreferredSymmetric, PreferredHash, PreferredCompression []uint8 -+ IssuerKeyId *uint64 -+ IsPrimaryId *bool -+ -+ // FlagsValid is set if any flags were given. See RFC 4880, section -+ // 5.2.3.21 for details. -+ FlagsValid bool -+ FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool -+ -+ // RevocationReason is set if this signature has been revoked. -+ // See RFC 4880, section 5.2.3.23 for details. -+ RevocationReason *uint8 -+ RevocationReasonText string -+ -+ // MDC is set if this signature has a feature packet that indicates -+ // support for MDC subpackets. -+ MDC bool -+ -+ // EmbeddedSignature, if non-nil, is a signature of the parent key, by -+ // this key. This prevents an attacker from claiming another's signing -+ // subkey as their own. -+ EmbeddedSignature *Signature -+ -+ outSubpackets []outputSubpacket -+} -+ -+func (sig *Signature) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.2.3 -+ var buf [5]byte -+ _, err = readFull(r, buf[:1]) -+ if err != nil { -+ return -+ } -+ if buf[0] != 4 { -+ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) -+ return -+ } -+ -+ _, err = readFull(r, buf[:5]) -+ if err != nil { -+ return -+ } -+ sig.SigType = SignatureType(buf[0]) -+ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: -+ default: -+ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) -+ return -+ } -+ -+ var ok bool -+ sig.Hash, ok = s2k.HashIdToHash(buf[2]) -+ if !ok { -+ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) -+ } -+ -+ hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) -+ l := 6 + hashedSubpacketsLength -+ sig.HashSuffix = make([]byte, l+6) -+ sig.HashSuffix[0] = 4 -+ copy(sig.HashSuffix[1:], buf[:5]) -+ hashedSubpackets := sig.HashSuffix[6:l] -+ _, err = readFull(r, hashedSubpackets) -+ if err != nil { -+ return -+ } -+ // See RFC 4880, section 5.2.4 -+ trailer := sig.HashSuffix[l:] -+ trailer[0] = 4 -+ trailer[1] = 0xff -+ trailer[2] = uint8(l >> 24) -+ trailer[3] = uint8(l >> 16) -+ trailer[4] = uint8(l >> 8) -+ trailer[5] = uint8(l) -+ -+ err = parseSignatureSubpackets(sig, hashedSubpackets, true) -+ if err != nil { -+ return -+ } -+ -+ _, err = readFull(r, buf[:2]) -+ if err != nil { -+ return -+ } -+ unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) -+ unhashedSubpackets := make([]byte, unhashedSubpacketsLength) -+ _, err = readFull(r, unhashedSubpackets) -+ if err != nil { -+ return -+ } -+ err = parseSignatureSubpackets(sig, unhashedSubpackets, false) -+ if err != nil { -+ return -+ } -+ -+ _, err = readFull(r, sig.HashTag[:2]) -+ if err != nil { -+ return -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) -+ case PubKeyAlgoDSA: -+ sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) -+ if err == nil { -+ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) -+ } -+ case PubKeyAlgoECDSA: -+ sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) -+ if err == nil { -+ sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) -+ } -+ default: -+ panic("unreachable") -+ } -+ return -+} -+ -+// parseSignatureSubpackets parses subpackets of the main signature packet. See -+// RFC 4880, section 5.2.3.1. -+func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { -+ for len(subpackets) > 0 { -+ subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) -+ if err != nil { -+ return -+ } -+ } -+ -+ if sig.CreationTime.IsZero() { -+ err = errors.StructuralError("no creation time in signature") -+ } -+ -+ return -+} -+ -+type signatureSubpacketType uint8 -+ -+const ( -+ creationTimeSubpacket signatureSubpacketType = 2 -+ signatureExpirationSubpacket signatureSubpacketType = 3 -+ keyExpirationSubpacket signatureSubpacketType = 9 -+ prefSymmetricAlgosSubpacket signatureSubpacketType = 11 -+ issuerSubpacket signatureSubpacketType = 16 -+ prefHashAlgosSubpacket signatureSubpacketType = 21 -+ prefCompressionSubpacket signatureSubpacketType = 22 -+ primaryUserIdSubpacket signatureSubpacketType = 25 -+ keyFlagsSubpacket signatureSubpacketType = 27 -+ reasonForRevocationSubpacket signatureSubpacketType = 29 -+ featuresSubpacket signatureSubpacketType = 30 -+ embeddedSignatureSubpacket signatureSubpacketType = 32 -+) -+ -+// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. -+func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { -+ // RFC 4880, section 5.2.3.1 -+ var ( -+ length uint32 -+ packetType signatureSubpacketType -+ isCritical bool -+ ) -+ switch { -+ case subpacket[0] < 192: -+ length = uint32(subpacket[0]) -+ subpacket = subpacket[1:] -+ case subpacket[0] < 255: -+ if len(subpacket) < 2 { -+ goto Truncated -+ } -+ length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 -+ subpacket = subpacket[2:] -+ default: -+ if len(subpacket) < 5 { -+ goto Truncated -+ } -+ length = uint32(subpacket[1])<<24 | -+ uint32(subpacket[2])<<16 | -+ uint32(subpacket[3])<<8 | -+ uint32(subpacket[4]) -+ subpacket = subpacket[5:] -+ } -+ if length > uint32(len(subpacket)) { -+ goto Truncated -+ } -+ rest = subpacket[length:] -+ subpacket = subpacket[:length] -+ if len(subpacket) == 0 { -+ err = errors.StructuralError("zero length signature subpacket") -+ return -+ } -+ packetType = signatureSubpacketType(subpacket[0] & 0x7f) -+ isCritical = subpacket[0]&0x80 == 0x80 -+ subpacket = subpacket[1:] -+ sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) -+ switch packetType { -+ case creationTimeSubpacket: -+ if !isHashed { -+ err = errors.StructuralError("signature creation time in non-hashed area") -+ return -+ } -+ if len(subpacket) != 4 { -+ err = errors.StructuralError("signature creation time not four bytes") -+ return -+ } -+ t := binary.BigEndian.Uint32(subpacket) -+ sig.CreationTime = time.Unix(int64(t), 0) -+ case signatureExpirationSubpacket: -+ // Signature expiration time, section 5.2.3.10 -+ if !isHashed { -+ return -+ } -+ if len(subpacket) != 4 { -+ err = errors.StructuralError("expiration subpacket with bad length") -+ return -+ } -+ sig.SigLifetimeSecs = new(uint32) -+ *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) -+ case keyExpirationSubpacket: -+ // Key expiration time, section 5.2.3.6 -+ if !isHashed { -+ return -+ } -+ if len(subpacket) != 4 { -+ err = errors.StructuralError("key expiration subpacket with bad length") -+ return -+ } -+ sig.KeyLifetimeSecs = new(uint32) -+ *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) -+ case prefSymmetricAlgosSubpacket: -+ // Preferred symmetric algorithms, section 5.2.3.7 -+ if !isHashed { -+ return -+ } -+ sig.PreferredSymmetric = make([]byte, len(subpacket)) -+ copy(sig.PreferredSymmetric, subpacket) -+ case issuerSubpacket: -+ // Issuer, section 5.2.3.5 -+ if len(subpacket) != 8 { -+ err = errors.StructuralError("issuer subpacket with bad length") -+ return -+ } -+ sig.IssuerKeyId = new(uint64) -+ *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) -+ case prefHashAlgosSubpacket: -+ // Preferred hash algorithms, section 5.2.3.8 -+ if !isHashed { -+ return -+ } -+ sig.PreferredHash = make([]byte, len(subpacket)) -+ copy(sig.PreferredHash, subpacket) -+ case prefCompressionSubpacket: -+ // Preferred compression algorithms, section 5.2.3.9 -+ if !isHashed { -+ return -+ } -+ sig.PreferredCompression = make([]byte, len(subpacket)) -+ copy(sig.PreferredCompression, subpacket) -+ case primaryUserIdSubpacket: -+ // Primary User ID, section 5.2.3.19 -+ if !isHashed { -+ return -+ } -+ if len(subpacket) != 1 { -+ err = errors.StructuralError("primary user id subpacket with bad length") -+ return -+ } -+ sig.IsPrimaryId = new(bool) -+ if subpacket[0] > 0 { -+ *sig.IsPrimaryId = true -+ } -+ case keyFlagsSubpacket: -+ // Key flags, section 5.2.3.21 -+ if !isHashed { -+ return -+ } -+ if len(subpacket) == 0 { -+ err = errors.StructuralError("empty key flags subpacket") -+ return -+ } -+ sig.FlagsValid = true -+ if subpacket[0]&KeyFlagCertify != 0 { -+ sig.FlagCertify = true -+ } -+ if subpacket[0]&KeyFlagSign != 0 { -+ sig.FlagSign = true -+ } -+ if subpacket[0]&KeyFlagEncryptCommunications != 0 { -+ sig.FlagEncryptCommunications = true -+ } -+ if subpacket[0]&KeyFlagEncryptStorage != 0 { -+ sig.FlagEncryptStorage = true -+ } -+ case reasonForRevocationSubpacket: -+ // Reason For Revocation, section 5.2.3.23 -+ if !isHashed { -+ return -+ } -+ if len(subpacket) == 0 { -+ err = errors.StructuralError("empty revocation reason subpacket") -+ return -+ } -+ sig.RevocationReason = new(uint8) -+ *sig.RevocationReason = subpacket[0] -+ sig.RevocationReasonText = string(subpacket[1:]) -+ case featuresSubpacket: -+ // Features subpacket, section 5.2.3.24 specifies a very general -+ // mechanism for OpenPGP implementations to signal support for new -+ // features. In practice, the subpacket is used exclusively to -+ // indicate support for MDC-protected encryption. -+ sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 -+ case embeddedSignatureSubpacket: -+ // Only usage is in signatures that cross-certify -+ // signing subkeys. section 5.2.3.26 describes the -+ // format, with its usage described in section 11.1 -+ if sig.EmbeddedSignature != nil { -+ err = errors.StructuralError("Cannot have multiple embedded signatures") -+ return -+ } -+ sig.EmbeddedSignature = new(Signature) -+ // Embedded signatures are required to be v4 signatures see -+ // section 12.1. However, we only parse v4 signatures in this -+ // file anyway. -+ if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { -+ return nil, err -+ } -+ if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { -+ return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) -+ } -+ default: -+ if isCritical { -+ err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) -+ return -+ } -+ } -+ return -+ -+Truncated: -+ err = errors.StructuralError("signature subpacket truncated") -+ return -+} -+ -+// subpacketLengthLength returns the length, in bytes, of an encoded length value. -+func subpacketLengthLength(length int) int { -+ if length < 192 { -+ return 1 -+ } -+ if length < 16320 { -+ return 2 -+ } -+ return 5 -+} -+ -+// serializeSubpacketLength marshals the given length into to. -+func serializeSubpacketLength(to []byte, length int) int { -+ // RFC 4880, Section 4.2.2. -+ if length < 192 { -+ to[0] = byte(length) -+ return 1 -+ } -+ if length < 16320 { -+ length -= 192 -+ to[0] = byte((length >> 8) + 192) -+ to[1] = byte(length) -+ return 2 -+ } -+ to[0] = 255 -+ to[1] = byte(length >> 24) -+ to[2] = byte(length >> 16) -+ to[3] = byte(length >> 8) -+ to[4] = byte(length) -+ return 5 -+} -+ -+// subpacketsLength returns the serialized length, in bytes, of the given -+// subpackets. -+func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { -+ for _, subpacket := range subpackets { -+ if subpacket.hashed == hashed { -+ length += subpacketLengthLength(len(subpacket.contents) + 1) -+ length += 1 // type byte -+ length += len(subpacket.contents) -+ } -+ } -+ return -+} -+ -+// serializeSubpackets marshals the given subpackets into to. -+func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { -+ for _, subpacket := range subpackets { -+ if subpacket.hashed == hashed { -+ n := serializeSubpacketLength(to, len(subpacket.contents)+1) -+ to[n] = byte(subpacket.subpacketType) -+ to = to[1+n:] -+ n = copy(to, subpacket.contents) -+ to = to[n:] -+ } -+ } -+ return -+} -+ -+// KeyExpired returns whether sig is a self-signature of a key that has -+// expired. -+func (sig *Signature) KeyExpired(currentTime time.Time) bool { -+ if sig.KeyLifetimeSecs == nil { -+ return false -+ } -+ expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) -+ return currentTime.After(expiry) -+} -+ -+// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. -+func (sig *Signature) buildHashSuffix() (err error) { -+ hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) -+ -+ var ok bool -+ l := 6 + hashedSubpacketsLen -+ sig.HashSuffix = make([]byte, l+6) -+ sig.HashSuffix[0] = 4 -+ sig.HashSuffix[1] = uint8(sig.SigType) -+ sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) -+ sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) -+ if !ok { -+ sig.HashSuffix = nil -+ return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) -+ } -+ sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) -+ sig.HashSuffix[5] = byte(hashedSubpacketsLen) -+ serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) -+ trailer := sig.HashSuffix[l:] -+ trailer[0] = 4 -+ trailer[1] = 0xff -+ trailer[2] = byte(l >> 24) -+ trailer[3] = byte(l >> 16) -+ trailer[4] = byte(l >> 8) -+ trailer[5] = byte(l) -+ return -+} -+ -+func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { -+ err = sig.buildHashSuffix() -+ if err != nil { -+ return -+ } -+ -+ h.Write(sig.HashSuffix) -+ digest = h.Sum(nil) -+ copy(sig.HashTag[:], digest) -+ return -+} -+ -+// Sign signs a message with a private key. The hash, h, must contain -+// the hash of the message to be signed and will be mutated by this function. -+// On success, the signature is stored in sig. Call Serialize to write it out. -+// If config is nil, sensible defaults will be used. -+func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { -+ sig.outSubpackets = sig.buildSubpackets() -+ digest, err := sig.signPrepareHash(h) -+ if err != nil { -+ return -+ } -+ -+ switch priv.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ // supports both *rsa.PrivateKey and crypto.Signer -+ sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) -+ sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) -+ case PubKeyAlgoDSA: -+ dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) -+ -+ // Need to truncate hashBytes to match FIPS 186-3 section 4.6. -+ subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 -+ if len(digest) > subgroupSize { -+ digest = digest[:subgroupSize] -+ } -+ r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) -+ if err == nil { -+ sig.DSASigR.bytes = r.Bytes() -+ sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) -+ sig.DSASigS.bytes = s.Bytes() -+ sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) -+ } -+ case PubKeyAlgoECDSA: -+ var r, s *big.Int -+ if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { -+ // direct support, avoid asn1 wrapping/unwrapping -+ r, s, err = ecdsa.Sign(config.Random(), pk, digest) -+ } else { -+ var b []byte -+ b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) -+ if err == nil { -+ r, s, err = unwrapECDSASig(b) -+ } -+ } -+ if err == nil { -+ sig.ECDSASigR = fromBig(r) -+ sig.ECDSASigS = fromBig(s) -+ } -+ default: -+ err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) -+ } -+ -+ return -+} -+ -+// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA -+// signature. -+func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { -+ var ecsdaSig struct { -+ R, S *big.Int -+ } -+ _, err = asn1.Unmarshal(b, &ecsdaSig) -+ if err != nil { -+ return -+ } -+ return ecsdaSig.R, ecsdaSig.S, nil -+} -+ -+// SignUserId computes a signature from priv, asserting that pub is a valid -+// key for the identity id. On success, the signature is stored in sig. Call -+// Serialize to write it out. -+// If config is nil, sensible defaults will be used. -+func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { -+ h, err := userIdSignatureHash(id, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return sig.Sign(h, priv, config) -+} -+ -+// SignKey computes a signature from priv, asserting that pub is a subkey. On -+// success, the signature is stored in sig. Call Serialize to write it out. -+// If config is nil, sensible defaults will be used. -+func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { -+ h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) -+ if err != nil { -+ return err -+ } -+ return sig.Sign(h, priv, config) -+} -+ -+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -+// called first. -+func (sig *Signature) Serialize(w io.Writer) (err error) { -+ if len(sig.outSubpackets) == 0 { -+ sig.outSubpackets = sig.rawSubpackets -+ } -+ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { -+ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") -+ } -+ -+ sigLength := 0 -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ sigLength = 2 + len(sig.RSASignature.bytes) -+ case PubKeyAlgoDSA: -+ sigLength = 2 + len(sig.DSASigR.bytes) -+ sigLength += 2 + len(sig.DSASigS.bytes) -+ case PubKeyAlgoECDSA: -+ sigLength = 2 + len(sig.ECDSASigR.bytes) -+ sigLength += 2 + len(sig.ECDSASigS.bytes) -+ default: -+ panic("impossible") -+ } -+ -+ unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) -+ length := len(sig.HashSuffix) - 6 /* trailer not included */ + -+ 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + -+ 2 /* hash tag */ + sigLength -+ err = serializeHeader(w, packetTypeSignature, length) -+ if err != nil { -+ return -+ } -+ -+ _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) -+ if err != nil { -+ return -+ } -+ -+ unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) -+ unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) -+ unhashedSubpackets[1] = byte(unhashedSubpacketsLen) -+ serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) -+ -+ _, err = w.Write(unhashedSubpackets) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(sig.HashTag[:]) -+ if err != nil { -+ return -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ err = writeMPIs(w, sig.RSASignature) -+ case PubKeyAlgoDSA: -+ err = writeMPIs(w, sig.DSASigR, sig.DSASigS) -+ case PubKeyAlgoECDSA: -+ err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) -+ default: -+ panic("impossible") -+ } -+ return -+} -+ -+// outputSubpacket represents a subpacket to be marshaled. -+type outputSubpacket struct { -+ hashed bool // true if this subpacket is in the hashed area. -+ subpacketType signatureSubpacketType -+ isCritical bool -+ contents []byte -+} -+ -+func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { -+ creationTime := make([]byte, 4) -+ binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) -+ subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) -+ -+ if sig.IssuerKeyId != nil { -+ keyId := make([]byte, 8) -+ binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) -+ subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) -+ } -+ -+ if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { -+ sigLifetime := make([]byte, 4) -+ binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) -+ subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) -+ } -+ -+ // Key flags may only appear in self-signatures or certification signatures. -+ -+ if sig.FlagsValid { -+ var flags byte -+ if sig.FlagCertify { -+ flags |= KeyFlagCertify -+ } -+ if sig.FlagSign { -+ flags |= KeyFlagSign -+ } -+ if sig.FlagEncryptCommunications { -+ flags |= KeyFlagEncryptCommunications -+ } -+ if sig.FlagEncryptStorage { -+ flags |= KeyFlagEncryptStorage -+ } -+ subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) -+ } -+ -+ // The following subpackets may only appear in self-signatures -+ -+ if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { -+ keyLifetime := make([]byte, 4) -+ binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) -+ subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) -+ } -+ -+ if sig.IsPrimaryId != nil && *sig.IsPrimaryId { -+ subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) -+ } -+ -+ if len(sig.PreferredSymmetric) > 0 { -+ subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) -+ } -+ -+ if len(sig.PreferredHash) > 0 { -+ subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) -+ } -+ -+ if len(sig.PreferredCompression) > 0 { -+ subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) -+ } -+ -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go -new file mode 100644 -index 00000000000000..56e761179d0cf8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_test.go -@@ -0,0 +1,78 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "encoding/hex" -+ "testing" -+) -+ -+func TestSignatureRead(t *testing.T) { -+ packet, err := Read(readerFromHex(signatureDataHex)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ sig, ok := packet.(*Signature) -+ if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 { -+ t.Errorf("failed to parse, got: %#v", packet) -+ } -+} -+ -+func TestSignatureReserialize(t *testing.T) { -+ packet, _ := Read(readerFromHex(signatureDataHex)) -+ sig := packet.(*Signature) -+ out := new(bytes.Buffer) -+ err := sig.Serialize(out) -+ if err != nil { -+ t.Errorf("error reserializing: %s", err) -+ return -+ } -+ -+ expected, _ := hex.DecodeString(signatureDataHex) -+ if !bytes.Equal(expected, out.Bytes()) { -+ t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) -+ } -+} -+ -+func TestSignUserId(t *testing.T) { -+ sig := &Signature{ -+ SigType: SigTypeGenericCert, -+ PubKeyAlgo: PubKeyAlgoRSA, -+ Hash: 0, // invalid hash function -+ } -+ -+ packet, err := Read(readerFromHex(rsaPkDataHex)) -+ if err != nil { -+ t.Fatalf("failed to deserialize public key: %v", err) -+ } -+ pubKey := packet.(*PublicKey) -+ -+ packet, err = Read(readerFromHex(privKeyRSAHex)) -+ if err != nil { -+ t.Fatalf("failed to deserialize private key: %v", err) -+ } -+ privKey := packet.(*PrivateKey) -+ -+ err = sig.SignUserId("", pubKey, privKey, nil) -+ if err == nil { -+ t.Errorf("did not receive an error when expected") -+ } -+ -+ sig.Hash = crypto.SHA256 -+ err = privKey.Decrypt([]byte("testing")) -+ if err != nil { -+ t.Fatalf("failed to decrypt private key: %v", err) -+ } -+ -+ err = sig.SignUserId("", pubKey, privKey, nil) -+ if err != nil { -+ t.Errorf("failed to sign user id: %v", err) -+ } -+} -+ -+const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e" -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go -new file mode 100644 -index 00000000000000..6edff889349b3f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3.go -@@ -0,0 +1,146 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "crypto" -+ "encoding/binary" -+ "fmt" -+ "io" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// SignatureV3 represents older version 3 signatures. These signatures are less secure -+// than version 4 and should not be used to create new signatures. They are included -+// here for backwards compatibility to read and validate with older key material. -+// See RFC 4880, section 5.2.2. -+type SignatureV3 struct { -+ SigType SignatureType -+ CreationTime time.Time -+ IssuerKeyId uint64 -+ PubKeyAlgo PublicKeyAlgorithm -+ Hash crypto.Hash -+ HashTag [2]byte -+ -+ RSASignature parsedMPI -+ DSASigR, DSASigS parsedMPI -+} -+ -+func (sig *SignatureV3) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.2.2 -+ var buf [8]byte -+ if _, err = readFull(r, buf[:1]); err != nil { -+ return -+ } -+ if buf[0] < 2 || buf[0] > 3 { -+ err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) -+ return -+ } -+ if _, err = readFull(r, buf[:1]); err != nil { -+ return -+ } -+ if buf[0] != 5 { -+ err = errors.UnsupportedError( -+ "invalid hashed material length " + strconv.Itoa(int(buf[0]))) -+ return -+ } -+ -+ // Read hashed material: signature type + creation time -+ if _, err = readFull(r, buf[:5]); err != nil { -+ return -+ } -+ sig.SigType = SignatureType(buf[0]) -+ t := binary.BigEndian.Uint32(buf[1:5]) -+ sig.CreationTime = time.Unix(int64(t), 0) -+ -+ // Eight-octet Key ID of signer. -+ if _, err = readFull(r, buf[:8]); err != nil { -+ return -+ } -+ sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) -+ -+ // Public-key and hash algorithm -+ if _, err = readFull(r, buf[:2]); err != nil { -+ return -+ } -+ sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: -+ default: -+ err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) -+ return -+ } -+ var ok bool -+ if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { -+ return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) -+ } -+ -+ // Two-octet field holding left 16 bits of signed hash value. -+ if _, err = readFull(r, sig.HashTag[:2]); err != nil { -+ return -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) -+ case PubKeyAlgoDSA: -+ if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { -+ return -+ } -+ sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) -+ default: -+ panic("unreachable") -+ } -+ return -+} -+ -+// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -+// called first. -+func (sig *SignatureV3) Serialize(w io.Writer) (err error) { -+ buf := make([]byte, 8) -+ -+ // Write the sig type and creation time -+ buf[0] = byte(sig.SigType) -+ binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) -+ if _, err = w.Write(buf[:5]); err != nil { -+ return -+ } -+ -+ // Write the issuer long key ID -+ binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) -+ if _, err = w.Write(buf[:8]); err != nil { -+ return -+ } -+ -+ // Write public key algorithm, hash ID, and hash value -+ buf[0] = byte(sig.PubKeyAlgo) -+ hashId, ok := s2k.HashToHashId(sig.Hash) -+ if !ok { -+ return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) -+ } -+ buf[1] = hashId -+ copy(buf[2:4], sig.HashTag[:]) -+ if _, err = w.Write(buf[:4]); err != nil { -+ return -+ } -+ -+ if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { -+ return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") -+ } -+ -+ switch sig.PubKeyAlgo { -+ case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: -+ err = writeMPIs(w, sig.RSASignature) -+ case PubKeyAlgoDSA: -+ err = writeMPIs(w, sig.DSASigR, sig.DSASigS) -+ default: -+ panic("impossible") -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go -new file mode 100644 -index 00000000000000..abb2d8c14496f8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/signature_v3_test.go -@@ -0,0 +1,96 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto" -+ "encoding/hex" -+ "io" -+ "testing" -+ -+ "golang.org/x/crypto/openpgp/armor" -+) -+ -+func TestSignatureV3Read(t *testing.T) { -+ r := v3KeyReader(t) -+ Read(r) // Skip public key -+ Read(r) // Skip uid -+ packet, err := Read(r) // Signature -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ sig, ok := packet.(*SignatureV3) -+ if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 { -+ t.Errorf("failed to parse, got: %#v", packet) -+ } -+} -+ -+func TestSignatureV3Reserialize(t *testing.T) { -+ r := v3KeyReader(t) -+ Read(r) // Skip public key -+ Read(r) // Skip uid -+ packet, err := Read(r) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ sig := packet.(*SignatureV3) -+ out := new(bytes.Buffer) -+ if err = sig.Serialize(out); err != nil { -+ t.Errorf("error reserializing: %s", err) -+ return -+ } -+ expected, err := io.ReadAll(v3KeyReader(t)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts -+ if !bytes.Equal(expected, out.Bytes()) { -+ t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) -+ } -+} -+ -+func v3KeyReader(t *testing.T) io.Reader { -+ armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor)) -+ if err != nil { -+ t.Fatalf("armor Decode failed: %v", err) -+ } -+ return armorBlock.Body -+} -+ -+// keySigV3Armor is some V3 public key I found in an SKS dump. -+// Old: Public Key Packet(tag 6)(141 bytes) -+// -+// Ver 4 - new -+// Public key creation time - Fri Sep 16 17:13:54 CDT 1994 -+// Pub alg - unknown(pub 0) -+// Unknown public key(pub 0) -+// -+// Old: User ID Packet(tag 13)(39 bytes) -+// -+// User ID - Armin M. Warda -+// -+// Old: Signature Packet(tag 2)(149 bytes) -+// -+// Ver 4 - new -+// Sig type - unknown(05) -+// Pub alg - ElGamal Encrypt-Only(pub 16) -+// Hash alg - unknown(hash 46) -+// Hashed Sub: unknown(sub 81, critical)(1988 bytes) -+const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+Version: SKS 1.0.10 -+ -+mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV -+5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi -+ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3 -+YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4 -+gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx -+524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF -+YFCbq4EjXRoOrYM= -+=LPjs -+-----END PGP PUBLIC KEY BLOCK-----` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go -new file mode 100644 -index 00000000000000..744c2d2c42dc5e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go -@@ -0,0 +1,155 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto/cipher" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// This is the largest session key that we'll support. Since no 512-bit cipher -+// has even been seriously used, this is comfortably large. -+const maxSessionKeySizeInBytes = 64 -+ -+// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC -+// 4880, section 5.3. -+type SymmetricKeyEncrypted struct { -+ CipherFunc CipherFunction -+ s2k func(out, in []byte) -+ encryptedKey []byte -+} -+ -+const symmetricKeyEncryptedVersion = 4 -+ -+func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { -+ // RFC 4880, section 5.3. -+ var buf [2]byte -+ if _, err := readFull(r, buf[:]); err != nil { -+ return err -+ } -+ if buf[0] != symmetricKeyEncryptedVersion { -+ return errors.UnsupportedError("SymmetricKeyEncrypted version") -+ } -+ ske.CipherFunc = CipherFunction(buf[1]) -+ -+ if ske.CipherFunc.KeySize() == 0 { -+ return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) -+ } -+ -+ var err error -+ ske.s2k, err = s2k.Parse(r) -+ if err != nil { -+ return err -+ } -+ -+ encryptedKey := make([]byte, maxSessionKeySizeInBytes) -+ // The session key may follow. We just have to try and read to find -+ // out. If it exists then we limit it to maxSessionKeySizeInBytes. -+ n, err := readFull(r, encryptedKey) -+ if err != nil && err != io.ErrUnexpectedEOF { -+ return err -+ } -+ -+ if n != 0 { -+ if n == maxSessionKeySizeInBytes { -+ return errors.UnsupportedError("oversized encrypted session key") -+ } -+ ske.encryptedKey = encryptedKey[:n] -+ } -+ -+ return nil -+} -+ -+// Decrypt attempts to decrypt an encrypted session key and returns the key and -+// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data -+// packet. -+func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { -+ key := make([]byte, ske.CipherFunc.KeySize()) -+ ske.s2k(key, passphrase) -+ -+ if len(ske.encryptedKey) == 0 { -+ return key, ske.CipherFunc, nil -+ } -+ -+ // the IV is all zeros -+ iv := make([]byte, ske.CipherFunc.blockSize()) -+ c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) -+ plaintextKey := make([]byte, len(ske.encryptedKey)) -+ c.XORKeyStream(plaintextKey, ske.encryptedKey) -+ cipherFunc := CipherFunction(plaintextKey[0]) -+ if cipherFunc.blockSize() == 0 { -+ return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) -+ } -+ plaintextKey = plaintextKey[1:] -+ if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() { -+ return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " + -+ "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")") -+ } -+ return plaintextKey, cipherFunc, nil -+} -+ -+// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The -+// packet contains a random session key, encrypted by a key derived from the -+// given passphrase. The session key is returned and must be passed to -+// SerializeSymmetricallyEncrypted. -+// If config is nil, sensible defaults will be used. -+func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { -+ cipherFunc := config.Cipher() -+ keySize := cipherFunc.KeySize() -+ if keySize == 0 { -+ return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) -+ } -+ -+ s2kBuf := new(bytes.Buffer) -+ keyEncryptingKey := make([]byte, keySize) -+ // s2k.Serialize salts and stretches the passphrase, and writes the -+ // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. -+ err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) -+ if err != nil { -+ return -+ } -+ s2kBytes := s2kBuf.Bytes() -+ -+ packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize -+ err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) -+ if err != nil { -+ return -+ } -+ -+ var buf [2]byte -+ buf[0] = symmetricKeyEncryptedVersion -+ buf[1] = byte(cipherFunc) -+ _, err = w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ _, err = w.Write(s2kBytes) -+ if err != nil { -+ return -+ } -+ -+ sessionKey := make([]byte, keySize) -+ _, err = io.ReadFull(config.Random(), sessionKey) -+ if err != nil { -+ return -+ } -+ iv := make([]byte, cipherFunc.blockSize()) -+ c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) -+ encryptedCipherAndKey := make([]byte, keySize+1) -+ c.XORKeyStream(encryptedCipherAndKey, buf[1:]) -+ c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) -+ _, err = w.Write(encryptedCipherAndKey) -+ if err != nil { -+ return -+ } -+ -+ key = sessionKey -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go -new file mode 100644 -index 00000000000000..5471d77706dd28 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go -@@ -0,0 +1,116 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "io" -+ "testing" -+) -+ -+func TestSymmetricKeyEncrypted(t *testing.T) { -+ buf := readerFromHex(symmetricallyEncryptedHex) -+ packet, err := Read(buf) -+ if err != nil { -+ t.Errorf("failed to read SymmetricKeyEncrypted: %s", err) -+ return -+ } -+ ske, ok := packet.(*SymmetricKeyEncrypted) -+ if !ok { -+ t.Error("didn't find SymmetricKeyEncrypted packet") -+ return -+ } -+ key, cipherFunc, err := ske.Decrypt([]byte("password")) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ -+ packet, err = Read(buf) -+ if err != nil { -+ t.Errorf("failed to read SymmetricallyEncrypted: %s", err) -+ return -+ } -+ se, ok := packet.(*SymmetricallyEncrypted) -+ if !ok { -+ t.Error("didn't find SymmetricallyEncrypted packet") -+ return -+ } -+ r, err := se.Decrypt(cipherFunc, key) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ -+ contents, err := io.ReadAll(r) -+ if err != nil && err != io.EOF { -+ t.Error(err) -+ return -+ } -+ -+ expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex) -+ if !bytes.Equal(expectedContents, contents) { -+ t.Errorf("bad contents got:%x want:%x", contents, expectedContents) -+ } -+} -+ -+const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf" -+const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a" -+ -+func TestSerializeSymmetricKeyEncryptedCiphers(t *testing.T) { -+ tests := [...]struct { -+ cipherFunc CipherFunction -+ name string -+ }{ -+ {Cipher3DES, "Cipher3DES"}, -+ {CipherCAST5, "CipherCAST5"}, -+ {CipherAES128, "CipherAES128"}, -+ {CipherAES192, "CipherAES192"}, -+ {CipherAES256, "CipherAES256"}, -+ } -+ -+ for _, test := range tests { -+ var buf bytes.Buffer -+ passphrase := []byte("testing") -+ config := &Config{ -+ DefaultCipher: test.cipherFunc, -+ } -+ -+ key, err := SerializeSymmetricKeyEncrypted(&buf, passphrase, config) -+ if err != nil { -+ t.Errorf("cipher(%s) failed to serialize: %s", test.name, err) -+ continue -+ } -+ -+ p, err := Read(&buf) -+ if err != nil { -+ t.Errorf("cipher(%s) failed to reparse: %s", test.name, err) -+ continue -+ } -+ -+ ske, ok := p.(*SymmetricKeyEncrypted) -+ if !ok { -+ t.Errorf("cipher(%s) parsed a different packet type: %#v", test.name, p) -+ continue -+ } -+ -+ if ske.CipherFunc != config.DefaultCipher { -+ t.Errorf("cipher(%s) SKE cipher function is %d (expected %d)", test.name, ske.CipherFunc, config.DefaultCipher) -+ } -+ parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase) -+ if err != nil { -+ t.Errorf("cipher(%s) failed to decrypt reparsed SKE: %s", test.name, err) -+ continue -+ } -+ if !bytes.Equal(key, parsedKey) { -+ t.Errorf("cipher(%s) keys don't match after Decrypt: %x (original) vs %x (parsed)", test.name, key, parsedKey) -+ } -+ if parsedCipherFunc != test.cipherFunc { -+ t.Errorf("cipher(%s) cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)", -+ test.name, test.cipherFunc, parsedCipherFunc) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go -new file mode 100644 -index 00000000000000..1a1a62964fc952 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go -@@ -0,0 +1,290 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "crypto/cipher" -+ "crypto/sha1" -+ "crypto/subtle" -+ "golang.org/x/crypto/openpgp/errors" -+ "hash" -+ "io" -+ "strconv" -+) -+ -+// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The -+// encrypted contents will consist of more OpenPGP packets. See RFC 4880, -+// sections 5.7 and 5.13. -+type SymmetricallyEncrypted struct { -+ MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. -+ contents io.Reader -+ prefix []byte -+} -+ -+const symmetricallyEncryptedVersion = 1 -+ -+func (se *SymmetricallyEncrypted) parse(r io.Reader) error { -+ if se.MDC { -+ // See RFC 4880, section 5.13. -+ var buf [1]byte -+ _, err := readFull(r, buf[:]) -+ if err != nil { -+ return err -+ } -+ if buf[0] != symmetricallyEncryptedVersion { -+ return errors.UnsupportedError("unknown SymmetricallyEncrypted version") -+ } -+ } -+ se.contents = r -+ return nil -+} -+ -+// Decrypt returns a ReadCloser, from which the decrypted contents of the -+// packet can be read. An incorrect key can, with high probability, be detected -+// immediately and this will result in a KeyIncorrect error being returned. -+func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { -+ keySize := c.KeySize() -+ if keySize == 0 { -+ return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) -+ } -+ if len(key) != keySize { -+ return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") -+ } -+ -+ if se.prefix == nil { -+ se.prefix = make([]byte, c.blockSize()+2) -+ _, err := readFull(se.contents, se.prefix) -+ if err != nil { -+ return nil, err -+ } -+ } else if len(se.prefix) != c.blockSize()+2 { -+ return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") -+ } -+ -+ ocfbResync := OCFBResync -+ if se.MDC { -+ // MDC packets use a different form of OCFB mode. -+ ocfbResync = OCFBNoResync -+ } -+ -+ s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) -+ if s == nil { -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ plaintext := cipher.StreamReader{S: s, R: se.contents} -+ -+ if se.MDC { -+ // MDC packets have an embedded hash that we need to check. -+ h := sha1.New() -+ h.Write(se.prefix) -+ return &seMDCReader{in: plaintext, h: h}, nil -+ } -+ -+ // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. -+ return seReader{plaintext}, nil -+} -+ -+// seReader wraps an io.Reader with a no-op Close method. -+type seReader struct { -+ in io.Reader -+} -+ -+func (ser seReader) Read(buf []byte) (int, error) { -+ return ser.in.Read(buf) -+} -+ -+func (ser seReader) Close() error { -+ return nil -+} -+ -+const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size -+ -+// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold -+// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an -+// MDC packet containing a hash of the previous contents which is checked -+// against the running hash. See RFC 4880, section 5.13. -+type seMDCReader struct { -+ in io.Reader -+ h hash.Hash -+ trailer [mdcTrailerSize]byte -+ scratch [mdcTrailerSize]byte -+ trailerUsed int -+ error bool -+ eof bool -+} -+ -+func (ser *seMDCReader) Read(buf []byte) (n int, err error) { -+ if ser.error { -+ err = io.ErrUnexpectedEOF -+ return -+ } -+ if ser.eof { -+ err = io.EOF -+ return -+ } -+ -+ // If we haven't yet filled the trailer buffer then we must do that -+ // first. -+ for ser.trailerUsed < mdcTrailerSize { -+ n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) -+ ser.trailerUsed += n -+ if err == io.EOF { -+ if ser.trailerUsed != mdcTrailerSize { -+ n = 0 -+ err = io.ErrUnexpectedEOF -+ ser.error = true -+ return -+ } -+ ser.eof = true -+ n = 0 -+ return -+ } -+ -+ if err != nil { -+ n = 0 -+ return -+ } -+ } -+ -+ // If it's a short read then we read into a temporary buffer and shift -+ // the data into the caller's buffer. -+ if len(buf) <= mdcTrailerSize { -+ n, err = readFull(ser.in, ser.scratch[:len(buf)]) -+ copy(buf, ser.trailer[:n]) -+ ser.h.Write(buf[:n]) -+ copy(ser.trailer[:], ser.trailer[n:]) -+ copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) -+ if n < len(buf) { -+ ser.eof = true -+ err = io.EOF -+ } -+ return -+ } -+ -+ n, err = ser.in.Read(buf[mdcTrailerSize:]) -+ copy(buf, ser.trailer[:]) -+ ser.h.Write(buf[:n]) -+ copy(ser.trailer[:], buf[n:]) -+ -+ if err == io.EOF { -+ ser.eof = true -+ } -+ return -+} -+ -+// This is a new-format packet tag byte for a type 19 (MDC) packet. -+const mdcPacketTagByte = byte(0x80) | 0x40 | 19 -+ -+func (ser *seMDCReader) Close() error { -+ if ser.error { -+ return errors.SignatureError("error during reading") -+ } -+ -+ for !ser.eof { -+ // We haven't seen EOF so we need to read to the end -+ var buf [1024]byte -+ _, err := ser.Read(buf[:]) -+ if err == io.EOF { -+ break -+ } -+ if err != nil { -+ return errors.SignatureError("error during reading") -+ } -+ } -+ -+ if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { -+ return errors.SignatureError("MDC packet not found") -+ } -+ ser.h.Write(ser.trailer[:2]) -+ -+ final := ser.h.Sum(nil) -+ if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { -+ return errors.SignatureError("hash mismatch") -+ } -+ return nil -+} -+ -+// An seMDCWriter writes through to an io.WriteCloser while maintains a running -+// hash of the data written. On close, it emits an MDC packet containing the -+// running hash. -+type seMDCWriter struct { -+ w io.WriteCloser -+ h hash.Hash -+} -+ -+func (w *seMDCWriter) Write(buf []byte) (n int, err error) { -+ w.h.Write(buf) -+ return w.w.Write(buf) -+} -+ -+func (w *seMDCWriter) Close() (err error) { -+ var buf [mdcTrailerSize]byte -+ -+ buf[0] = mdcPacketTagByte -+ buf[1] = sha1.Size -+ w.h.Write(buf[:2]) -+ digest := w.h.Sum(nil) -+ copy(buf[2:], digest) -+ -+ _, err = w.w.Write(buf[:]) -+ if err != nil { -+ return -+ } -+ return w.w.Close() -+} -+ -+// noOpCloser is like an io.NopCloser, but for an io.Writer. -+type noOpCloser struct { -+ w io.Writer -+} -+ -+func (c noOpCloser) Write(data []byte) (n int, err error) { -+ return c.w.Write(data) -+} -+ -+func (c noOpCloser) Close() error { -+ return nil -+} -+ -+// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet -+// to w and returns a WriteCloser to which the to-be-encrypted packets can be -+// written. -+// If config is nil, sensible defaults will be used. -+func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { -+ if c.KeySize() != len(key) { -+ return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") -+ } -+ writeCloser := noOpCloser{w} -+ ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) -+ if err != nil { -+ return -+ } -+ -+ _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) -+ if err != nil { -+ return -+ } -+ -+ block := c.new(key) -+ blockSize := block.BlockSize() -+ iv := make([]byte, blockSize) -+ _, err = config.Random().Read(iv) -+ if err != nil { -+ return -+ } -+ s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) -+ _, err = ciphertext.Write(prefix) -+ if err != nil { -+ return -+ } -+ plaintext := cipher.StreamWriter{S: s, W: ciphertext} -+ -+ h := sha1.New() -+ h.Write(iv) -+ h.Write(iv[blockSize-2:]) -+ contents = &seMDCWriter{w: plaintext, h: h} -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go -new file mode 100644 -index 00000000000000..4c47c7b145a0f2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go -@@ -0,0 +1,122 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "crypto/sha1" -+ "encoding/hex" -+ "golang.org/x/crypto/openpgp/errors" -+ "io" -+ "testing" -+) -+ -+// TestReader wraps a []byte and returns reads of a specific length. -+type testReader struct { -+ data []byte -+ stride int -+} -+ -+func (t *testReader) Read(buf []byte) (n int, err error) { -+ n = t.stride -+ if n > len(t.data) { -+ n = len(t.data) -+ } -+ if n > len(buf) { -+ n = len(buf) -+ } -+ copy(buf, t.data) -+ t.data = t.data[n:] -+ if len(t.data) == 0 { -+ err = io.EOF -+ } -+ return -+} -+ -+func testMDCReader(t *testing.T) { -+ mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex) -+ -+ for stride := 1; stride < len(mdcPlaintext)/2; stride++ { -+ r := &testReader{data: mdcPlaintext, stride: stride} -+ mdcReader := &seMDCReader{in: r, h: sha1.New()} -+ body, err := io.ReadAll(mdcReader) -+ if err != nil { -+ t.Errorf("stride: %d, error: %s", stride, err) -+ continue -+ } -+ if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) { -+ t.Errorf("stride: %d: bad contents %x", stride, body) -+ continue -+ } -+ -+ err = mdcReader.Close() -+ if err != nil { -+ t.Errorf("stride: %d, error on Close: %s", stride, err) -+ } -+ } -+ -+ mdcPlaintext[15] ^= 80 -+ -+ r := &testReader{data: mdcPlaintext, stride: 2} -+ mdcReader := &seMDCReader{in: r, h: sha1.New()} -+ _, err := io.ReadAll(mdcReader) -+ if err != nil { -+ t.Errorf("corruption test, error: %s", err) -+ return -+ } -+ err = mdcReader.Close() -+ if err == nil { -+ t.Error("corruption: no error") -+ } else if _, ok := err.(*errors.SignatureError); !ok { -+ t.Errorf("corruption: expected SignatureError, got: %s", err) -+ } -+} -+ -+const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980" -+ -+func TestSerialize(t *testing.T) { -+ buf := bytes.NewBuffer(nil) -+ c := CipherAES128 -+ key := make([]byte, c.KeySize()) -+ -+ w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil) -+ if err != nil { -+ t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err) -+ return -+ } -+ -+ contents := []byte("hello world\n") -+ -+ w.Write(contents) -+ w.Close() -+ -+ p, err := Read(buf) -+ if err != nil { -+ t.Errorf("error from Read: %s", err) -+ return -+ } -+ -+ se, ok := p.(*SymmetricallyEncrypted) -+ if !ok { -+ t.Errorf("didn't read a *SymmetricallyEncrypted") -+ return -+ } -+ -+ r, err := se.Decrypt(c, key) -+ if err != nil { -+ t.Errorf("error from Decrypt: %s", err) -+ return -+ } -+ -+ contentsCopy := bytes.NewBuffer(nil) -+ _, err = io.Copy(contentsCopy, r) -+ if err != nil { -+ t.Errorf("error from io.Copy: %s", err) -+ return -+ } -+ if !bytes.Equal(contentsCopy.Bytes(), contents) { -+ t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go -new file mode 100644 -index 00000000000000..ff7ef5307557ea ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute.go -@@ -0,0 +1,90 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "image" -+ "image/jpeg" -+ "io" -+) -+ -+const UserAttrImageSubpacket = 1 -+ -+// UserAttribute is capable of storing other types of data about a user -+// beyond name, email and a text comment. In practice, user attributes are typically used -+// to store a signed thumbnail photo JPEG image of the user. -+// See RFC 4880, section 5.12. -+type UserAttribute struct { -+ Contents []*OpaqueSubpacket -+} -+ -+// NewUserAttributePhoto creates a user attribute packet -+// containing the given images. -+func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { -+ uat = new(UserAttribute) -+ for _, photo := range photos { -+ var buf bytes.Buffer -+ // RFC 4880, Section 5.12.1. -+ data := []byte{ -+ 0x10, 0x00, // Little-endian image header length (16 bytes) -+ 0x01, // Image header version 1 -+ 0x01, // JPEG -+ 0, 0, 0, 0, // 12 reserved octets, must be all zero. -+ 0, 0, 0, 0, -+ 0, 0, 0, 0} -+ if _, err = buf.Write(data); err != nil { -+ return -+ } -+ if err = jpeg.Encode(&buf, photo, nil); err != nil { -+ return -+ } -+ uat.Contents = append(uat.Contents, &OpaqueSubpacket{ -+ SubType: UserAttrImageSubpacket, -+ Contents: buf.Bytes()}) -+ } -+ return -+} -+ -+// NewUserAttribute creates a new user attribute packet containing the given subpackets. -+func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { -+ return &UserAttribute{Contents: contents} -+} -+ -+func (uat *UserAttribute) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.13 -+ b, err := io.ReadAll(r) -+ if err != nil { -+ return -+ } -+ uat.Contents, err = OpaqueSubpackets(b) -+ return -+} -+ -+// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including -+// header. -+func (uat *UserAttribute) Serialize(w io.Writer) (err error) { -+ var buf bytes.Buffer -+ for _, sp := range uat.Contents { -+ sp.Serialize(&buf) -+ } -+ if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { -+ return err -+ } -+ _, err = w.Write(buf.Bytes()) -+ return -+} -+ -+// ImageData returns zero or more byte slices, each containing -+// JPEG File Interchange Format (JFIF), for each photo in the -+// user attribute packet. -+func (uat *UserAttribute) ImageData() (imageData [][]byte) { -+ for _, sp := range uat.Contents { -+ if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { -+ imageData = append(imageData, sp.Contents[16:]) -+ } -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go -new file mode 100644 -index 00000000000000..13ca5143cee62c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userattribute_test.go -@@ -0,0 +1,109 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "bytes" -+ "encoding/base64" -+ "image/color" -+ "image/jpeg" -+ "testing" -+) -+ -+func TestParseUserAttribute(t *testing.T) { -+ r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket)) -+ for i := 0; i < 2; i++ { -+ p, err := Read(r) -+ if err != nil { -+ t.Fatal(err) -+ } -+ uat := p.(*UserAttribute) -+ imgs := uat.ImageData() -+ if len(imgs) != 1 { -+ t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs)) -+ } -+ if len(imgs[0]) != 3395 { -+ t.Errorf("Unexpected JPEG image size: %d", len(imgs[0])) -+ } -+ img, err := jpeg.Decode(bytes.NewBuffer(imgs[0])) -+ if err != nil { -+ t.Errorf("Error decoding JPEG image: %v", err) -+ } -+ // A pixel in my right eye. -+ pixel := color.NRGBAModel.Convert(img.At(56, 36)) -+ ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255} -+ if pixel != ref { -+ t.Errorf("Unexpected pixel color: %v", pixel) -+ } -+ w := bytes.NewBuffer(nil) -+ err = uat.Serialize(w) -+ if err != nil { -+ t.Errorf("Error writing user attribute: %v", err) -+ } -+ r = bytes.NewBuffer(w.Bytes()) -+ } -+} -+ -+const userAttributePacket = ` -+0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE -+BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA -+QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e -+Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH -+CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw -+JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6 -+g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk -+5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB -+AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX -+GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT -+lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2 -+9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN -+pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od -+W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova -+ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH -+/eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09 -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` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userid.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userid.go -new file mode 100644 -index 00000000000000..359a462eb8ab64 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userid.go -@@ -0,0 +1,159 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "io" -+ "strings" -+) -+ -+// UserId contains text that is intended to represent the name and email -+// address of the key holder. See RFC 4880, section 5.11. By convention, this -+// takes the form "Full Name (Comment) " -+type UserId struct { -+ Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. -+ -+ Name, Comment, Email string -+} -+ -+func hasInvalidCharacters(s string) bool { -+ for _, c := range s { -+ switch c { -+ case '(', ')', '<', '>', 0: -+ return true -+ } -+ } -+ return false -+} -+ -+// NewUserId returns a UserId or nil if any of the arguments contain invalid -+// characters. The invalid characters are '\x00', '(', ')', '<' and '>' -+func NewUserId(name, comment, email string) *UserId { -+ // RFC 4880 doesn't deal with the structure of userid strings; the -+ // name, comment and email form is just a convention. However, there's -+ // no convention about escaping the metacharacters and GPG just refuses -+ // to create user ids where, say, the name contains a '('. We mirror -+ // this behaviour. -+ -+ if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { -+ return nil -+ } -+ -+ uid := new(UserId) -+ uid.Name, uid.Comment, uid.Email = name, comment, email -+ uid.Id = name -+ if len(comment) > 0 { -+ if len(uid.Id) > 0 { -+ uid.Id += " " -+ } -+ uid.Id += "(" -+ uid.Id += comment -+ uid.Id += ")" -+ } -+ if len(email) > 0 { -+ if len(uid.Id) > 0 { -+ uid.Id += " " -+ } -+ uid.Id += "<" -+ uid.Id += email -+ uid.Id += ">" -+ } -+ return uid -+} -+ -+func (uid *UserId) parse(r io.Reader) (err error) { -+ // RFC 4880, section 5.11 -+ b, err := io.ReadAll(r) -+ if err != nil { -+ return -+ } -+ uid.Id = string(b) -+ uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) -+ return -+} -+ -+// Serialize marshals uid to w in the form of an OpenPGP packet, including -+// header. -+func (uid *UserId) Serialize(w io.Writer) error { -+ err := serializeHeader(w, packetTypeUserId, len(uid.Id)) -+ if err != nil { -+ return err -+ } -+ _, err = w.Write([]byte(uid.Id)) -+ return err -+} -+ -+// parseUserId extracts the name, comment and email from a user id string that -+// is formatted as "Full Name (Comment) ". -+func parseUserId(id string) (name, comment, email string) { -+ var n, c, e struct { -+ start, end int -+ } -+ var state int -+ -+ for offset, rune := range id { -+ switch state { -+ case 0: -+ // Entering name -+ n.start = offset -+ state = 1 -+ fallthrough -+ case 1: -+ // In name -+ if rune == '(' { -+ state = 2 -+ n.end = offset -+ } else if rune == '<' { -+ state = 5 -+ n.end = offset -+ } -+ case 2: -+ // Entering comment -+ c.start = offset -+ state = 3 -+ fallthrough -+ case 3: -+ // In comment -+ if rune == ')' { -+ state = 4 -+ c.end = offset -+ } -+ case 4: -+ // Between comment and email -+ if rune == '<' { -+ state = 5 -+ } -+ case 5: -+ // Entering email -+ e.start = offset -+ state = 6 -+ fallthrough -+ case 6: -+ // In email -+ if rune == '>' { -+ state = 7 -+ e.end = offset -+ } -+ default: -+ // After email -+ } -+ } -+ switch state { -+ case 1: -+ // ended in the name -+ n.end = len(id) -+ case 3: -+ // ended in comment -+ c.end = len(id) -+ case 6: -+ // ended in email -+ e.end = len(id) -+ } -+ -+ name = strings.TrimSpace(id[n.start:n.end]) -+ comment = strings.TrimSpace(id[c.start:c.end]) -+ email = strings.TrimSpace(id[e.start:e.end]) -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go b/ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go -new file mode 100644 -index 00000000000000..29681938938c68 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/packet/userid_test.go -@@ -0,0 +1,87 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package packet -+ -+import ( -+ "testing" -+) -+ -+var userIdTests = []struct { -+ id string -+ name, comment, email string -+}{ -+ {"", "", "", ""}, -+ {"John Smith", "John Smith", "", ""}, -+ {"John Smith ()", "John Smith", "", ""}, -+ {"John Smith () <>", "John Smith", "", ""}, -+ {"(comment", "", "comment", ""}, -+ {"(comment)", "", "comment", ""}, -+ {" sdfk", "", "", "email"}, -+ {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"}, -+ {" John Smith < email > lksdfj", "John Smith", "", "email"}, -+ {"("}, -+ {"foo", "bar", "", "foo (bar)"}, -+ {"foo", "", "baz", "foo "}, -+ {"", "bar", "baz", "(bar) "}, -+ {"foo", "bar", "baz", "foo (bar) "}, -+} -+ -+func TestNewUserId(t *testing.T) { -+ for i, test := range newUserIdTests { -+ uid := NewUserId(test.name, test.comment, test.email) -+ if uid == nil { -+ t.Errorf("#%d: returned nil", i) -+ continue -+ } -+ if uid.Id != test.id { -+ t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id) -+ } -+ } -+} -+ -+var invalidNewUserIdTests = []struct { -+ name, comment, email string -+}{ -+ {"foo(", "", ""}, -+ {"foo<", "", ""}, -+ {"", "bar)", ""}, -+ {"", "bar<", ""}, -+ {"", "", "baz>"}, -+ {"", "", "baz)"}, -+ {"", "", "baz\x00"}, -+} -+ -+func TestNewUserIdWithInvalidInput(t *testing.T) { -+ for i, test := range invalidNewUserIdTests { -+ if uid := NewUserId(test.name, test.comment, test.email); uid != nil { -+ t.Errorf("#%d: returned non-nil value: %#v", i, uid) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/read.go b/ms_mod/golang.org/x/crypto/openpgp/read.go -new file mode 100644 -index 00000000000000..48a893146858ca ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/read.go -@@ -0,0 +1,448 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package openpgp implements high level operations on OpenPGP messages. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package openpgp // import "golang.org/x/crypto/openpgp" -+ -+import ( -+ "crypto" -+ _ "crypto/sha256" -+ "hash" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+// SignatureType is the armor type for a PGP signature. -+var SignatureType = "PGP SIGNATURE" -+ -+// readArmored reads an armored block with the given type. -+func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { -+ block, err := armor.Decode(r) -+ if err != nil { -+ return -+ } -+ -+ if block.Type != expectedType { -+ return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) -+ } -+ -+ return block.Body, nil -+} -+ -+// MessageDetails contains the result of parsing an OpenPGP encrypted and/or -+// signed message. -+type MessageDetails struct { -+ IsEncrypted bool // true if the message was encrypted. -+ EncryptedToKeyIds []uint64 // the list of recipient key ids. -+ IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. -+ DecryptedWith Key // the private key used to decrypt the message, if any. -+ IsSigned bool // true if the message is signed. -+ SignedByKeyId uint64 // the key id of the signer, if any. -+ SignedBy *Key // the key of the signer, if available. -+ LiteralData *packet.LiteralData // the metadata of the contents -+ UnverifiedBody io.Reader // the contents of the message. -+ -+ // If IsSigned is true and SignedBy is non-zero then the signature will -+ // be verified as UnverifiedBody is read. The signature cannot be -+ // checked until the whole of UnverifiedBody is read so UnverifiedBody -+ // must be consumed until EOF before the data can be trusted. Even if a -+ // message isn't signed (or the signer is unknown) the data may contain -+ // an authentication code that is only checked once UnverifiedBody has -+ // been consumed. Once EOF has been seen, the following fields are -+ // valid. (An authentication code failure is reported as a -+ // SignatureError error when reading from UnverifiedBody.) -+ SignatureError error // nil if the signature is good. -+ Signature *packet.Signature // the signature packet itself, if v4 (default) -+ SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature -+ -+ decrypted io.ReadCloser -+} -+ -+// A PromptFunction is used as a callback by functions that may need to decrypt -+// a private key, or prompt for a passphrase. It is called with a list of -+// acceptable, encrypted private keys and a boolean that indicates whether a -+// passphrase is usable. It should either decrypt a private key or return a -+// passphrase to try. If the decrypted private key or given passphrase isn't -+// correct, the function will be called again, forever. Any error returned will -+// be passed up. -+type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) -+ -+// A keyEnvelopePair is used to store a private key with the envelope that -+// contains a symmetric key, encrypted with that key. -+type keyEnvelopePair struct { -+ key Key -+ encryptedKey *packet.EncryptedKey -+} -+ -+// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. -+// The given KeyRing should contain both public keys (for signature -+// verification) and, possibly encrypted, private keys for decrypting. -+// If config is nil, sensible defaults will be used. -+func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { -+ var p packet.Packet -+ -+ var symKeys []*packet.SymmetricKeyEncrypted -+ var pubKeys []keyEnvelopePair -+ var se *packet.SymmetricallyEncrypted -+ -+ packets := packet.NewReader(r) -+ md = new(MessageDetails) -+ md.IsEncrypted = true -+ -+ // The message, if encrypted, starts with a number of packets -+ // containing an encrypted decryption key. The decryption key is either -+ // encrypted to a public key, or with a passphrase. This loop -+ // collects these packets. -+ParsePackets: -+ for { -+ p, err = packets.Next() -+ if err != nil { -+ return nil, err -+ } -+ switch p := p.(type) { -+ case *packet.SymmetricKeyEncrypted: -+ // This packet contains the decryption key encrypted with a passphrase. -+ md.IsSymmetricallyEncrypted = true -+ symKeys = append(symKeys, p) -+ case *packet.EncryptedKey: -+ // This packet contains the decryption key encrypted to a public key. -+ md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) -+ switch p.Algo { -+ case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: -+ break -+ default: -+ continue -+ } -+ var keys []Key -+ if p.KeyId == 0 { -+ keys = keyring.DecryptionKeys() -+ } else { -+ keys = keyring.KeysById(p.KeyId) -+ } -+ for _, k := range keys { -+ pubKeys = append(pubKeys, keyEnvelopePair{k, p}) -+ } -+ case *packet.SymmetricallyEncrypted: -+ se = p -+ break ParsePackets -+ case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: -+ // This message isn't encrypted. -+ if len(symKeys) != 0 || len(pubKeys) != 0 { -+ return nil, errors.StructuralError("key material not followed by encrypted message") -+ } -+ packets.Unread(p) -+ return readSignedMessage(packets, nil, keyring) -+ } -+ } -+ -+ var candidates []Key -+ var decrypted io.ReadCloser -+ -+ // Now that we have the list of encrypted keys we need to decrypt at -+ // least one of them or, if we cannot, we need to call the prompt -+ // function so that it can decrypt a key or give us a passphrase. -+FindKey: -+ for { -+ // See if any of the keys already have a private key available -+ candidates = candidates[:0] -+ candidateFingerprints := make(map[string]bool) -+ -+ for _, pk := range pubKeys { -+ if pk.key.PrivateKey == nil { -+ continue -+ } -+ if !pk.key.PrivateKey.Encrypted { -+ if len(pk.encryptedKey.Key) == 0 { -+ pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) -+ } -+ if len(pk.encryptedKey.Key) == 0 { -+ continue -+ } -+ decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) -+ if err != nil && err != errors.ErrKeyIncorrect { -+ return nil, err -+ } -+ if decrypted != nil { -+ md.DecryptedWith = pk.key -+ break FindKey -+ } -+ } else { -+ fpr := string(pk.key.PublicKey.Fingerprint[:]) -+ if v := candidateFingerprints[fpr]; v { -+ continue -+ } -+ candidates = append(candidates, pk.key) -+ candidateFingerprints[fpr] = true -+ } -+ } -+ -+ if len(candidates) == 0 && len(symKeys) == 0 { -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ if prompt == nil { -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ passphrase, err := prompt(candidates, len(symKeys) != 0) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Try the symmetric passphrase first -+ if len(symKeys) != 0 && passphrase != nil { -+ for _, s := range symKeys { -+ key, cipherFunc, err := s.Decrypt(passphrase) -+ if err == nil { -+ decrypted, err = se.Decrypt(cipherFunc, key) -+ if err != nil && err != errors.ErrKeyIncorrect { -+ return nil, err -+ } -+ if decrypted != nil { -+ break FindKey -+ } -+ } -+ -+ } -+ } -+ } -+ -+ md.decrypted = decrypted -+ if err := packets.Push(decrypted); err != nil { -+ return nil, err -+ } -+ return readSignedMessage(packets, md, keyring) -+} -+ -+// readSignedMessage reads a possibly signed message if mdin is non-zero then -+// that structure is updated and returned. Otherwise a fresh MessageDetails is -+// used. -+func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { -+ if mdin == nil { -+ mdin = new(MessageDetails) -+ } -+ md = mdin -+ -+ var p packet.Packet -+ var h hash.Hash -+ var wrappedHash hash.Hash -+FindLiteralData: -+ for { -+ p, err = packets.Next() -+ if err != nil { -+ return nil, err -+ } -+ switch p := p.(type) { -+ case *packet.Compressed: -+ if err := packets.Push(p.Body); err != nil { -+ return nil, err -+ } -+ case *packet.OnePassSignature: -+ if !p.IsLast { -+ return nil, errors.UnsupportedError("nested signatures") -+ } -+ -+ h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) -+ if err != nil { -+ md = nil -+ return -+ } -+ -+ md.IsSigned = true -+ md.SignedByKeyId = p.KeyId -+ keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) -+ if len(keys) > 0 { -+ md.SignedBy = &keys[0] -+ } -+ case *packet.LiteralData: -+ md.LiteralData = p -+ break FindLiteralData -+ } -+ } -+ -+ if md.SignedBy != nil { -+ md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} -+ } else if md.decrypted != nil { -+ md.UnverifiedBody = checkReader{md} -+ } else { -+ md.UnverifiedBody = md.LiteralData.Body -+ } -+ -+ return md, nil -+} -+ -+// hashForSignature returns a pair of hashes that can be used to verify a -+// signature. The signature may specify that the contents of the signed message -+// should be preprocessed (i.e. to normalize line endings). Thus this function -+// returns two hashes. The second should be used to hash the message itself and -+// performs any needed preprocessing. -+func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { -+ if !hashId.Available() { -+ return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) -+ } -+ h := hashId.New() -+ -+ switch sigType { -+ case packet.SigTypeBinary: -+ return h, h, nil -+ case packet.SigTypeText: -+ return h, NewCanonicalTextHash(h), nil -+ } -+ -+ return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) -+} -+ -+// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF -+// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger -+// MDC checks. -+type checkReader struct { -+ md *MessageDetails -+} -+ -+func (cr checkReader) Read(buf []byte) (n int, err error) { -+ n, err = cr.md.LiteralData.Body.Read(buf) -+ if err == io.EOF { -+ mdcErr := cr.md.decrypted.Close() -+ if mdcErr != nil { -+ err = mdcErr -+ } -+ } -+ return -+} -+ -+// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes -+// the data as it is read. When it sees an EOF from the underlying io.Reader -+// it parses and checks a trailing Signature packet and triggers any MDC checks. -+type signatureCheckReader struct { -+ packets *packet.Reader -+ h, wrappedHash hash.Hash -+ md *MessageDetails -+} -+ -+func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { -+ n, err = scr.md.LiteralData.Body.Read(buf) -+ scr.wrappedHash.Write(buf[:n]) -+ if err == io.EOF { -+ var p packet.Packet -+ p, scr.md.SignatureError = scr.packets.Next() -+ if scr.md.SignatureError != nil { -+ return -+ } -+ -+ var ok bool -+ if scr.md.Signature, ok = p.(*packet.Signature); ok { -+ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) -+ } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { -+ scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) -+ } else { -+ scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") -+ return -+ } -+ -+ // The SymmetricallyEncrypted packet, if any, might have an -+ // unsigned hash of its own. In order to check this we need to -+ // close that Reader. -+ if scr.md.decrypted != nil { -+ mdcErr := scr.md.decrypted.Close() -+ if mdcErr != nil { -+ err = mdcErr -+ } -+ } -+ } -+ return -+} -+ -+// CheckDetachedSignature takes a signed file and a detached signature and -+// returns the signer if the signature is valid. If the signer isn't known, -+// ErrUnknownIssuer is returned. -+func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { -+ var issuerKeyId uint64 -+ var hashFunc crypto.Hash -+ var sigType packet.SignatureType -+ var keys []Key -+ var p packet.Packet -+ -+ packets := packet.NewReader(signature) -+ for { -+ p, err = packets.Next() -+ if err == io.EOF { -+ return nil, errors.ErrUnknownIssuer -+ } -+ if err != nil { -+ return nil, err -+ } -+ -+ switch sig := p.(type) { -+ case *packet.Signature: -+ if sig.IssuerKeyId == nil { -+ return nil, errors.StructuralError("signature doesn't have an issuer") -+ } -+ issuerKeyId = *sig.IssuerKeyId -+ hashFunc = sig.Hash -+ sigType = sig.SigType -+ case *packet.SignatureV3: -+ issuerKeyId = sig.IssuerKeyId -+ hashFunc = sig.Hash -+ sigType = sig.SigType -+ default: -+ return nil, errors.StructuralError("non signature packet found") -+ } -+ -+ keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) -+ if len(keys) > 0 { -+ break -+ } -+ } -+ -+ if len(keys) == 0 { -+ panic("unreachable") -+ } -+ -+ h, wrappedHash, err := hashForSignature(hashFunc, sigType) -+ if err != nil { -+ return nil, err -+ } -+ -+ if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { -+ return nil, err -+ } -+ -+ for _, key := range keys { -+ switch sig := p.(type) { -+ case *packet.Signature: -+ err = key.PublicKey.VerifySignature(h, sig) -+ case *packet.SignatureV3: -+ err = key.PublicKey.VerifySignatureV3(h, sig) -+ default: -+ panic("unreachable") -+ } -+ -+ if err == nil { -+ return key.Entity, nil -+ } -+ } -+ -+ return nil, err -+} -+ -+// CheckArmoredDetachedSignature performs the same actions as -+// CheckDetachedSignature but expects the signature to be armored. -+func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { -+ body, err := readArmored(signature, SignatureType) -+ if err != nil { -+ return -+ } -+ -+ return CheckDetachedSignature(keyring, signed, body) -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/read_test.go b/ms_mod/golang.org/x/crypto/openpgp/read_test.go -new file mode 100644 -index 00000000000000..6bbfaf1afb4894 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/read_test.go -@@ -0,0 +1,612 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package openpgp -+ -+import ( -+ "bytes" -+ _ "crypto/sha512" -+ "encoding/hex" -+ "io" -+ "strings" -+ "testing" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+func readerFromHex(s string) io.Reader { -+ data, err := hex.DecodeString(s) -+ if err != nil { -+ panic("readerFromHex: bad input") -+ } -+ return bytes.NewBuffer(data) -+} -+ -+func TestReadKeyRing(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B { -+ t.Errorf("bad keyring: %#v", kring) -+ } -+} -+ -+func TestRereadKeyRing(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ if err != nil { -+ t.Errorf("error in initial parse: %s", err) -+ return -+ } -+ out := new(bytes.Buffer) -+ err = kring[0].Serialize(out) -+ if err != nil { -+ t.Errorf("error in serialization: %s", err) -+ return -+ } -+ kring, err = ReadKeyRing(out) -+ if err != nil { -+ t.Errorf("error in second parse: %s", err) -+ return -+ } -+ -+ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB { -+ t.Errorf("bad keyring: %#v", kring) -+ } -+} -+ -+func TestReadPrivateKeyRing(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil { -+ t.Errorf("bad keyring: %#v", kring) -+ } -+} -+ -+func TestReadDSAKey(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 { -+ t.Errorf("bad parse: %#v", kring) -+ } -+} -+ -+func TestReadP256Key(t *testing.T) { -+ kring, err := ReadKeyRing(readerFromHex(p256TestKeyHex)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x5918513E { -+ t.Errorf("bad parse: %#v", kring) -+ } -+} -+ -+func TestDSAHashTruncatation(t *testing.T) { -+ // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo -+ // SHA512 in order to require DSA hash truncation to verify correctly. -+ _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512)) -+ if err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestGetKeyById(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ -+ keys := kring.KeysById(0xa34d7e18c20c31bb) -+ if len(keys) != 1 || keys[0].Entity != kring[0] { -+ t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) -+ } -+ -+ keys = kring.KeysById(0xfd94408d4543314f) -+ if len(keys) != 1 || keys[0].Entity != kring[0] { -+ t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) -+ } -+} -+ -+func checkSignedMessage(t *testing.T, signedHex, expected string) { -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ -+ md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ -+ if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.DecryptedWith != (Key{}) { -+ t.Errorf("bad MessageDetails: %#v", md) -+ } -+ -+ contents, err := io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("error reading UnverifiedBody: %s", err) -+ } -+ if string(contents) != expected { -+ t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) -+ } -+ if md.SignatureError != nil || md.Signature == nil { -+ t.Errorf("failed to validate: %s", md.SignatureError) -+ } -+} -+ -+func TestSignedMessage(t *testing.T) { -+ checkSignedMessage(t, signedMessageHex, signedInput) -+} -+ -+func TestTextSignedMessage(t *testing.T) { -+ checkSignedMessage(t, signedTextMessageHex, signedTextInput) -+} -+ -+// The reader should detect "compressed quines", which are compressed -+// packets that expand into themselves and cause an infinite recursive -+// parsing loop. -+// The packet in this test case comes from Taylor R. Campbell at -+// http://mumble.net/~campbell/misc/pgp-quine/ -+func TestCampbellQuine(t *testing.T) { -+ md, err := ReadMessage(readerFromHex(campbellQuine), nil, nil, nil) -+ if md != nil { -+ t.Errorf("Reading a compressed quine should not return any data: %#v", md) -+ } -+ structural, ok := err.(errors.StructuralError) -+ if !ok { -+ t.Fatalf("Unexpected class of error: %T", err) -+ } -+ if !strings.Contains(string(structural), "too many layers of packets") { -+ t.Fatalf("Unexpected error: %s", err) -+ } -+} -+ -+var signedEncryptedMessageTests = []struct { -+ keyRingHex string -+ messageHex string -+ signedByKeyId uint64 -+ encryptedToKeyId uint64 -+}{ -+ { -+ testKeys1And2PrivateHex, -+ signedEncryptedMessageHex, -+ 0xa34d7e18c20c31bb, -+ 0x2a67d68660df41c7, -+ }, -+ { -+ dsaElGamalTestKeysHex, -+ signedEncryptedMessage2Hex, -+ 0x33af447ccd759b09, -+ 0xcf6a7abcd43e3673, -+ }, -+} -+ -+func TestSignedEncryptedMessage(t *testing.T) { -+ for i, test := range signedEncryptedMessageTests { -+ expected := "Signed and encrypted message\n" -+ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) -+ prompt := func(keys []Key, symmetric bool) ([]byte, error) { -+ if symmetric { -+ t.Errorf("prompt: message was marked as symmetrically encrypted") -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ if len(keys) == 0 { -+ t.Error("prompt: no keys requested") -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ err := keys[0].PrivateKey.Decrypt([]byte("passphrase")) -+ if err != nil { -+ t.Errorf("prompt: error decrypting key: %s", err) -+ return nil, errors.ErrKeyIncorrect -+ } -+ -+ return nil, nil -+ } -+ -+ md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil) -+ if err != nil { -+ t.Errorf("#%d: error reading message: %s", i, err) -+ return -+ } -+ -+ if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId { -+ t.Errorf("#%d: bad MessageDetails: %#v", i, md) -+ } -+ -+ contents, err := io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("#%d: error reading UnverifiedBody: %s", i, err) -+ } -+ if string(contents) != expected { -+ t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected) -+ } -+ -+ if md.SignatureError != nil || md.Signature == nil { -+ t.Errorf("#%d: failed to validate: %s", i, md.SignatureError) -+ } -+ } -+} -+ -+func TestUnspecifiedRecipient(t *testing.T) { -+ expected := "Recipient unspecified\n" -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) -+ -+ md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil) -+ if err != nil { -+ t.Errorf("error reading message: %s", err) -+ return -+ } -+ -+ contents, err := io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("error reading UnverifiedBody: %s", err) -+ } -+ if string(contents) != expected { -+ t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) -+ } -+} -+ -+func TestSymmetricallyEncrypted(t *testing.T) { -+ firstTimeCalled := true -+ -+ prompt := func(keys []Key, symmetric bool) ([]byte, error) { -+ if len(keys) != 0 { -+ t.Errorf("prompt: len(keys) = %d (want 0)", len(keys)) -+ } -+ -+ if !symmetric { -+ t.Errorf("symmetric is not set") -+ } -+ -+ if firstTimeCalled { -+ firstTimeCalled = false -+ return []byte("wrongpassword"), nil -+ } -+ -+ return []byte("password"), nil -+ } -+ -+ md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil) -+ if err != nil { -+ t.Errorf("ReadMessage: %s", err) -+ return -+ } -+ -+ contents, err := io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("ReadAll: %s", err) -+ } -+ -+ expectedCreationTime := uint32(1295992998) -+ if md.LiteralData.Time != expectedCreationTime { -+ t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime) -+ } -+ -+ const expected = "Symmetrically encrypted.\n" -+ if string(contents) != expected { -+ t.Errorf("contents got: %s want: %s", string(contents), expected) -+ } -+} -+ -+func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) { -+ signed := bytes.NewBufferString(sigInput) -+ signer, err := CheckDetachedSignature(kring, signed, signature) -+ if err != nil { -+ t.Errorf("%s: signature error: %s", tag, err) -+ return -+ } -+ if signer == nil { -+ t.Errorf("%s: signer is nil", tag) -+ return -+ } -+ if signer.PrimaryKey.KeyId != expectedSignerKeyId { -+ t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId) -+ } -+} -+ -+func TestDetachedSignature(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId) -+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId) -+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId) -+ -+ incorrectSignedInput := signedInput + "X" -+ _, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex)) -+ if err == nil { -+ t.Fatal("CheckDetachedSignature returned without error for bad signature") -+ } -+ if err == errors.ErrUnknownIssuer { -+ t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid") -+ } -+} -+ -+func TestDetachedSignatureDSA(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) -+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) -+} -+ -+func TestMultipleSignaturePacketsDSA(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) -+ testDetachedSignature(t, kring, readerFromHex(missingHashFunctionHex+detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) -+} -+ -+func TestDetachedSignatureP256(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(p256TestKeyHex)) -+ testDetachedSignature(t, kring, readerFromHex(detachedSignatureP256Hex), signedInput, "binary", testKeyP256KeyId) -+} -+ -+func testHashFunctionError(t *testing.T, signatureHex string) { -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ _, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex)) -+ if err == nil { -+ t.Fatal("Packet with bad hash type was correctly parsed") -+ } -+ unsupported, ok := err.(errors.UnsupportedError) -+ if !ok { -+ t.Fatalf("Unexpected class of error: %s", err) -+ } -+ if !strings.Contains(string(unsupported), "hash ") { -+ t.Fatalf("Unexpected error: %s", err) -+ } -+} -+ -+func TestUnknownHashFunction(t *testing.T) { -+ // unknownHashFunctionHex contains a signature packet with hash -+ // function type 153 (which isn't a real hash function id). -+ testHashFunctionError(t, unknownHashFunctionHex) -+} -+ -+func TestMissingHashFunction(t *testing.T) { -+ // missingHashFunctionHex contains a signature packet that uses -+ // RIPEMD160, which isn't compiled in. Since that's the only signature -+ // packet we don't find any suitable packets and end up with ErrUnknownIssuer -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) -+ _, err := CheckDetachedSignature(kring, nil, readerFromHex(missingHashFunctionHex)) -+ if err == nil { -+ t.Fatal("Packet with missing hash type was correctly parsed") -+ } -+ if err != errors.ErrUnknownIssuer { -+ t.Fatalf("Unexpected class of error: %s", err) -+ } -+} -+ -+func TestReadingArmoredPrivateKey(t *testing.T) { -+ el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock)) -+ if err != nil { -+ t.Error(err) -+ } -+ if len(el) != 1 { -+ t.Errorf("got %d entities, wanted 1\n", len(el)) -+ } -+} -+ -+func TestReadingArmoredPublicKey(t *testing.T) { -+ el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey)) -+ if err != nil { -+ t.Error(err) -+ } -+ if len(el) != 1 { -+ t.Errorf("didn't get a valid entity") -+ } -+} -+ -+func TestNoArmoredData(t *testing.T) { -+ _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo")) -+ if _, ok := err.(errors.InvalidArgumentError); !ok { -+ t.Errorf("error was not an InvalidArgumentError: %s", err) -+ } -+} -+ -+func testReadMessageError(t *testing.T, messageHex string) { -+ buf, err := hex.DecodeString(messageHex) -+ if err != nil { -+ t.Errorf("hex.DecodeString(): %v", err) -+ } -+ -+ kr, err := ReadKeyRing(new(bytes.Buffer)) -+ if err != nil { -+ t.Errorf("ReadKeyring(): %v", err) -+ } -+ -+ _, err = ReadMessage(bytes.NewBuffer(buf), kr, -+ func([]Key, bool) ([]byte, error) { -+ return []byte("insecure"), nil -+ }, nil) -+ -+ if err == nil { -+ t.Errorf("ReadMessage(): Unexpected nil error") -+ } -+} -+ -+func TestIssue11503(t *testing.T) { -+ testReadMessageError(t, "8c040402000aa430aa8228b9248b01fc899a91197130303030") -+} -+ -+func TestIssue11504(t *testing.T) { -+ testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130") -+} -+ -+// TestSignatureV3Message tests the verification of V3 signature, generated -+// with a modern V4-style key. Some people have their clients set to generate -+// V3 signatures, so it's useful to be able to verify them. -+func TestSignatureV3Message(t *testing.T) { -+ sig, err := armor.Decode(strings.NewReader(signedMessageV3)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3)) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ md, err := ReadMessage(sig.Body, key, nil, nil) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ -+ _, err = io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ -+ // We'll see a sig error here after reading in the UnverifiedBody above, -+ // if there was one to see. -+ if err = md.SignatureError; err != nil { -+ t.Error(err) -+ return -+ } -+ -+ if md.SignatureV3 == nil { -+ t.Errorf("No available signature after checking signature") -+ return -+ } -+ if md.Signature != nil { -+ t.Errorf("Did not expect a signature V4 back") -+ return -+ } -+ return -+} -+ -+const testKey1KeyId = 0xA34D7E18C20C31BB -+const testKey3KeyId = 0x338934250CCC0360 -+const testKeyP256KeyId = 0xd44a2c495918513e -+ -+const signedInput = "Signed message\nline 2\nline 3\n" -+const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" -+ -+const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" -+ -+const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" -+ -+const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" -+ -+const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24" -+ -+const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" -+ -+const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817" -+ -+const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" -+ -+const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" -+ -+const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" -+ -+const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" -+ -+const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" -+ -+const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d" -+ -+const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" -+ -+const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6" -+ -+const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" -+ -+const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" -+ -+const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" -+ -+const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" -+ -+const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- -+Version: GnuPG v1.4.10 (GNU/Linux) -+ -+lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp -+idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn -+vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB -+AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X -+0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL -+IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk -+VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn -+gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 -+TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx -+q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz -+dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA -+CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 -+ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ -+eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid -+AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV -+bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK -+/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA -+A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX -+TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc -+lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 -+rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN -+oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 -+QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU -+nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC -+AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp -+BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad -+AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL -+VrM0m72/jnpKo04= -+=zNCn -+-----END PGP PRIVATE KEY BLOCK-----` -+ -+const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+Charset: UTF-8 -+ -+xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 -+sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk -+Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ -+AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD -+24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX -++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 -+B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX -+fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA -+FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 -+ex7En5r7rHR5xwX82Msc+Rq9dSyO -+=7MrZ -+-----END PGP PUBLIC KEY BLOCK-----` -+ -+const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` -+ -+const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` -+ -+const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` -+ -+const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` -+ -+const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -+Comment: GPGTools - https://gpgtools.org -+ -+mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY -+BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z -+tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 -+JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV -+/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ -+K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H -+JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx -+YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 -+b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi -+UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M -+pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM -+AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz -+786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd -+EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB -+=RZia -+-----END PGP PUBLIC KEY BLOCK----- -+` -+ -+const signedMessageV3 = `-----BEGIN PGP MESSAGE----- -+Comment: GPGTools - https://gpgtools.org -+ -+owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP -+q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka -+uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka -+DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d -+iT57d/OhWwA= -+=hG7R -+-----END PGP MESSAGE----- -+` -diff --git a/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go -new file mode 100644 -index 00000000000000..f53244a1c7b538 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k.go -@@ -0,0 +1,279 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package s2k implements the various OpenPGP string-to-key transforms as -+// specified in RFC 4800 section 3.7.1. -+// -+// Deprecated: this package is unmaintained except for security fixes. New -+// applications should consider a more focused, modern alternative to OpenPGP -+// for their specific task. If you are required to interoperate with OpenPGP -+// systems and need a maintained package, consider a community fork. -+// See https://golang.org/issue/44226. -+package s2k // import "golang.org/x/crypto/openpgp/s2k" -+ -+import ( -+ "crypto" -+ "hash" -+ "io" -+ "strconv" -+ -+ "golang.org/x/crypto/openpgp/errors" -+) -+ -+// Config collects configuration parameters for s2k key-stretching -+// transformatioms. A nil *Config is valid and results in all default -+// values. Currently, Config is used only by the Serialize function in -+// this package. -+type Config struct { -+ // Hash is the default hash function to be used. If -+ // nil, SHA1 is used. -+ Hash crypto.Hash -+ // S2KCount is only used for symmetric encryption. It -+ // determines the strength of the passphrase stretching when -+ // the said passphrase is hashed to produce a key. S2KCount -+ // should be between 1024 and 65011712, inclusive. If Config -+ // is nil or S2KCount is 0, the value 65536 used. Not all -+ // values in the above range can be represented. S2KCount will -+ // be rounded up to the next representable value if it cannot -+ // be encoded exactly. When set, it is strongly encrouraged to -+ // use a value that is at least 65536. See RFC 4880 Section -+ // 3.7.1.3. -+ S2KCount int -+} -+ -+func (c *Config) hash() crypto.Hash { -+ if c == nil || uint(c.Hash) == 0 { -+ // SHA1 is the historical default in this package. -+ return crypto.SHA1 -+ } -+ -+ return c.Hash -+} -+ -+func (c *Config) encodedCount() uint8 { -+ if c == nil || c.S2KCount == 0 { -+ return 96 // The common case. Correspoding to 65536 -+ } -+ -+ i := c.S2KCount -+ switch { -+ // Behave like GPG. Should we make 65536 the lowest value used? -+ case i < 1024: -+ i = 1024 -+ case i > 65011712: -+ i = 65011712 -+ } -+ -+ return encodeCount(i) -+} -+ -+// encodeCount converts an iterative "count" in the range 1024 to -+// 65011712, inclusive, to an encoded count. The return value is the -+// octet that is actually stored in the GPG file. encodeCount panics -+// if i is not in the above range (encodedCount above takes care to -+// pass i in the correct range). See RFC 4880 Section 3.7.7.1. -+func encodeCount(i int) uint8 { -+ if i < 1024 || i > 65011712 { -+ panic("count arg i outside the required range") -+ } -+ -+ for encoded := 0; encoded < 256; encoded++ { -+ count := decodeCount(uint8(encoded)) -+ if count >= i { -+ return uint8(encoded) -+ } -+ } -+ -+ return 255 -+} -+ -+// decodeCount returns the s2k mode 3 iterative "count" corresponding to -+// the encoded octet c. -+func decodeCount(c uint8) int { -+ return (16 + int(c&15)) << (uint32(c>>4) + 6) -+} -+ -+// Simple writes to out the result of computing the Simple S2K function (RFC -+// 4880, section 3.7.1.1) using the given hash and input passphrase. -+func Simple(out []byte, h hash.Hash, in []byte) { -+ Salted(out, h, in, nil) -+} -+ -+var zero [1]byte -+ -+// Salted writes to out the result of computing the Salted S2K function (RFC -+// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. -+func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { -+ done := 0 -+ var digest []byte -+ -+ for i := 0; done < len(out); i++ { -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(zero[:]) -+ } -+ h.Write(salt) -+ h.Write(in) -+ digest = h.Sum(digest[:0]) -+ n := copy(out[done:], digest) -+ done += n -+ } -+} -+ -+// Iterated writes to out the result of computing the Iterated and Salted S2K -+// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, -+// salt and iteration count. -+func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { -+ combined := make([]byte, len(in)+len(salt)) -+ copy(combined, salt) -+ copy(combined[len(salt):], in) -+ -+ if count < len(combined) { -+ count = len(combined) -+ } -+ -+ done := 0 -+ var digest []byte -+ for i := 0; done < len(out); i++ { -+ h.Reset() -+ for j := 0; j < i; j++ { -+ h.Write(zero[:]) -+ } -+ written := 0 -+ for written < count { -+ if written+len(combined) > count { -+ todo := count - written -+ h.Write(combined[:todo]) -+ written = count -+ } else { -+ h.Write(combined) -+ written += len(combined) -+ } -+ } -+ digest = h.Sum(digest[:0]) -+ n := copy(out[done:], digest) -+ done += n -+ } -+} -+ -+// Parse reads a binary specification for a string-to-key transformation from r -+// and returns a function which performs that transform. -+func Parse(r io.Reader) (f func(out, in []byte), err error) { -+ var buf [9]byte -+ -+ _, err = io.ReadFull(r, buf[:2]) -+ if err != nil { -+ return -+ } -+ -+ hash, ok := HashIdToHash(buf[1]) -+ if !ok { -+ return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) -+ } -+ if !hash.Available() { -+ return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) -+ } -+ h := hash.New() -+ -+ switch buf[0] { -+ case 0: -+ f := func(out, in []byte) { -+ Simple(out, h, in) -+ } -+ return f, nil -+ case 1: -+ _, err = io.ReadFull(r, buf[:8]) -+ if err != nil { -+ return -+ } -+ f := func(out, in []byte) { -+ Salted(out, h, in, buf[:8]) -+ } -+ return f, nil -+ case 3: -+ _, err = io.ReadFull(r, buf[:9]) -+ if err != nil { -+ return -+ } -+ count := decodeCount(buf[8]) -+ f := func(out, in []byte) { -+ Iterated(out, h, in, buf[:8], count) -+ } -+ return f, nil -+ } -+ -+ return nil, errors.UnsupportedError("S2K function") -+} -+ -+// Serialize salts and stretches the given passphrase and writes the -+// resulting key into key. It also serializes an S2K descriptor to -+// w. The key stretching can be configured with c, which may be -+// nil. In that case, sensible defaults will be used. -+func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { -+ var buf [11]byte -+ buf[0] = 3 /* iterated and salted */ -+ buf[1], _ = HashToHashId(c.hash()) -+ salt := buf[2:10] -+ if _, err := io.ReadFull(rand, salt); err != nil { -+ return err -+ } -+ encodedCount := c.encodedCount() -+ count := decodeCount(encodedCount) -+ buf[10] = encodedCount -+ if _, err := w.Write(buf[:]); err != nil { -+ return err -+ } -+ -+ Iterated(key, c.hash().New(), passphrase, salt, count) -+ return nil -+} -+ -+// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with -+// Go's crypto.Hash type. See RFC 4880, section 9.4. -+var hashToHashIdMapping = []struct { -+ id byte -+ hash crypto.Hash -+ name string -+}{ -+ {1, crypto.MD5, "MD5"}, -+ {2, crypto.SHA1, "SHA1"}, -+ {3, crypto.RIPEMD160, "RIPEMD160"}, -+ {8, crypto.SHA256, "SHA256"}, -+ {9, crypto.SHA384, "SHA384"}, -+ {10, crypto.SHA512, "SHA512"}, -+ {11, crypto.SHA224, "SHA224"}, -+} -+ -+// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP -+// hash id. -+func HashIdToHash(id byte) (h crypto.Hash, ok bool) { -+ for _, m := range hashToHashIdMapping { -+ if m.id == id { -+ return m.hash, true -+ } -+ } -+ return 0, false -+} -+ -+// HashIdToString returns the name of the hash function corresponding to the -+// given OpenPGP hash id. -+func HashIdToString(id byte) (name string, ok bool) { -+ for _, m := range hashToHashIdMapping { -+ if m.id == id { -+ return m.name, true -+ } -+ } -+ -+ return "", false -+} -+ -+// HashToHashId returns an OpenPGP hash id which corresponds the given Hash. -+func HashToHashId(h crypto.Hash) (id byte, ok bool) { -+ for _, m := range hashToHashIdMapping { -+ if m.hash == h { -+ return m.id, true -+ } -+ } -+ return 0, false -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go -new file mode 100644 -index 00000000000000..183d26056b11e4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/s2k/s2k_test.go -@@ -0,0 +1,137 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package s2k -+ -+import ( -+ "bytes" -+ "crypto" -+ _ "crypto/md5" -+ "crypto/rand" -+ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+ "encoding/hex" -+ "testing" -+ -+ _ "golang.org/x/crypto/ripemd160" -+) -+ -+var saltedTests = []struct { -+ in, out string -+}{ -+ {"hello", "10295ac1"}, -+ {"world", "ac587a5e"}, -+ {"foo", "4dda8077"}, -+ {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"}, -+ {"x", "f1d3f289"}, -+ {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"}, -+} -+ -+func TestSalted(t *testing.T) { -+ h := sha1.New() -+ salt := [4]byte{1, 2, 3, 4} -+ -+ for i, test := range saltedTests { -+ expected, _ := hex.DecodeString(test.out) -+ out := make([]byte, len(expected)) -+ Salted(out, h, []byte(test.in), salt[:]) -+ if !bytes.Equal(expected, out) { -+ t.Errorf("#%d, got: %x want: %x", i, out, expected) -+ } -+ } -+} -+ -+var iteratedTests = []struct { -+ in, out string -+}{ -+ {"hello", "83126105"}, -+ {"world", "6fa317f9"}, -+ {"foo", "8fbc35b9"}, -+ {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"}, -+ {"x", "5a684dfe"}, -+ {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"}, -+} -+ -+func TestIterated(t *testing.T) { -+ h := sha1.New() -+ salt := [4]byte{4, 3, 2, 1} -+ -+ for i, test := range iteratedTests { -+ expected, _ := hex.DecodeString(test.out) -+ out := make([]byte, len(expected)) -+ Iterated(out, h, []byte(test.in), salt[:], 31) -+ if !bytes.Equal(expected, out) { -+ t.Errorf("#%d, got: %x want: %x", i, out, expected) -+ } -+ } -+} -+ -+var parseTests = []struct { -+ spec, in, out string -+}{ -+ /* Simple with SHA1 */ -+ {"0002", "hello", "aaf4c61d"}, -+ /* Salted with SHA1 */ -+ {"01020102030405060708", "hello", "f4f7d67e"}, -+ /* Iterated with SHA1 */ -+ {"03020102030405060708f1", "hello", "f2a57b7c"}, -+} -+ -+func TestParse(t *testing.T) { -+ for i, test := range parseTests { -+ spec, _ := hex.DecodeString(test.spec) -+ buf := bytes.NewBuffer(spec) -+ f, err := Parse(buf) -+ if err != nil { -+ t.Errorf("%d: Parse returned error: %s", i, err) -+ continue -+ } -+ -+ expected, _ := hex.DecodeString(test.out) -+ out := make([]byte, len(expected)) -+ f(out, []byte(test.in)) -+ if !bytes.Equal(out, expected) { -+ t.Errorf("%d: output got: %x want: %x", i, out, expected) -+ } -+ if testing.Short() { -+ break -+ } -+ } -+} -+ -+func TestSerialize(t *testing.T) { -+ hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160, -+ crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224} -+ testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712} -+ for _, h := range hashes { -+ for _, c := range testCounts { -+ testSerializeConfig(t, &Config{Hash: h, S2KCount: c}) -+ } -+ } -+} -+ -+func testSerializeConfig(t *testing.T, c *Config) { -+ t.Logf("Running testSerializeConfig() with config: %+v", c) -+ -+ buf := bytes.NewBuffer(nil) -+ key := make([]byte, 16) -+ passphrase := []byte("testing") -+ err := Serialize(buf, key, rand.Reader, passphrase, c) -+ if err != nil { -+ t.Errorf("failed to serialize: %s", err) -+ return -+ } -+ -+ f, err := Parse(buf) -+ if err != nil { -+ t.Errorf("failed to reparse: %s", err) -+ return -+ } -+ key2 := make([]byte, len(key)) -+ f(key2, passphrase) -+ if !bytes.Equal(key2, key) { -+ t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/write.go b/ms_mod/golang.org/x/crypto/openpgp/write.go -new file mode 100644 -index 00000000000000..b89d48b81d7370 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/write.go -@@ -0,0 +1,418 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package openpgp -+ -+import ( -+ "crypto" -+ "hash" -+ "io" -+ "strconv" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/armor" -+ "golang.org/x/crypto/openpgp/errors" -+ "golang.org/x/crypto/openpgp/packet" -+ "golang.org/x/crypto/openpgp/s2k" -+) -+ -+// DetachSign signs message with the private key from signer (which must -+// already have been decrypted) and writes the signature to w. -+// If config is nil, sensible defaults will be used. -+func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { -+ return detachSign(w, signer, message, packet.SigTypeBinary, config) -+} -+ -+// ArmoredDetachSign signs message with the private key from signer (which -+// must already have been decrypted) and writes an armored signature to w. -+// If config is nil, sensible defaults will be used. -+func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { -+ return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) -+} -+ -+// DetachSignText signs message (after canonicalising the line endings) with -+// the private key from signer (which must already have been decrypted) and -+// writes the signature to w. -+// If config is nil, sensible defaults will be used. -+func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { -+ return detachSign(w, signer, message, packet.SigTypeText, config) -+} -+ -+// ArmoredDetachSignText signs message (after canonicalising the line endings) -+// with the private key from signer (which must already have been decrypted) -+// and writes an armored signature to w. -+// If config is nil, sensible defaults will be used. -+func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { -+ return armoredDetachSign(w, signer, message, packet.SigTypeText, config) -+} -+ -+func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { -+ out, err := armor.Encode(w, SignatureType, nil) -+ if err != nil { -+ return -+ } -+ err = detachSign(out, signer, message, sigType, config) -+ if err != nil { -+ return -+ } -+ return out.Close() -+} -+ -+func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { -+ if signer.PrivateKey == nil { -+ return errors.InvalidArgumentError("signing key doesn't have a private key") -+ } -+ if signer.PrivateKey.Encrypted { -+ return errors.InvalidArgumentError("signing key is encrypted") -+ } -+ -+ sig := new(packet.Signature) -+ sig.SigType = sigType -+ sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo -+ sig.Hash = config.Hash() -+ sig.CreationTime = config.Now() -+ sig.IssuerKeyId = &signer.PrivateKey.KeyId -+ -+ h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) -+ if err != nil { -+ return -+ } -+ io.Copy(wrappedHash, message) -+ -+ err = sig.Sign(h, signer.PrivateKey, config) -+ if err != nil { -+ return -+ } -+ -+ return sig.Serialize(w) -+} -+ -+// FileHints contains metadata about encrypted files. This metadata is, itself, -+// encrypted. -+type FileHints struct { -+ // IsBinary can be set to hint that the contents are binary data. -+ IsBinary bool -+ // FileName hints at the name of the file that should be written. It's -+ // truncated to 255 bytes if longer. It may be empty to suggest that the -+ // file should not be written to disk. It may be equal to "_CONSOLE" to -+ // suggest the data should not be written to disk. -+ FileName string -+ // ModTime contains the modification time of the file, or the zero time if not applicable. -+ ModTime time.Time -+} -+ -+// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. -+// The resulting WriteCloser must be closed after the contents of the file have -+// been written. -+// If config is nil, sensible defaults will be used. -+func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ if hints == nil { -+ hints = &FileHints{} -+ } -+ -+ key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) -+ if err != nil { -+ return -+ } -+ w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) -+ if err != nil { -+ return -+ } -+ -+ literaldata := w -+ if algo := config.Compression(); algo != packet.CompressionNone { -+ var compConfig *packet.CompressionConfig -+ if config != nil { -+ compConfig = config.CompressionConfig -+ } -+ literaldata, err = packet.SerializeCompressed(w, algo, compConfig) -+ if err != nil { -+ return -+ } -+ } -+ -+ var epochSeconds uint32 -+ if !hints.ModTime.IsZero() { -+ epochSeconds = uint32(hints.ModTime.Unix()) -+ } -+ return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) -+} -+ -+// intersectPreferences mutates and returns a prefix of a that contains only -+// the values in the intersection of a and b. The order of a is preserved. -+func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { -+ var j int -+ for _, v := range a { -+ for _, v2 := range b { -+ if v == v2 { -+ a[j] = v -+ j++ -+ break -+ } -+ } -+ } -+ -+ return a[:j] -+} -+ -+func hashToHashId(h crypto.Hash) uint8 { -+ v, ok := s2k.HashToHashId(h) -+ if !ok { -+ panic("tried to convert unknown hash") -+ } -+ return v -+} -+ -+// writeAndSign writes the data as a payload package and, optionally, signs -+// it. hints contains optional information, that is also encrypted, -+// that aids the recipients in processing the message. The resulting -+// WriteCloser must be closed after the contents of the file have been -+// written. If config is nil, sensible defaults will be used. -+func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ var signer *packet.PrivateKey -+ if signed != nil { -+ signKey, ok := signed.signingKey(config.Now()) -+ if !ok { -+ return nil, errors.InvalidArgumentError("no valid signing keys") -+ } -+ signer = signKey.PrivateKey -+ if signer == nil { -+ return nil, errors.InvalidArgumentError("no private key in signing key") -+ } -+ if signer.Encrypted { -+ return nil, errors.InvalidArgumentError("signing key must be decrypted") -+ } -+ } -+ -+ var hash crypto.Hash -+ for _, hashId := range candidateHashes { -+ if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { -+ hash = h -+ break -+ } -+ } -+ -+ // If the hash specified by config is a candidate, we'll use that. -+ if configuredHash := config.Hash(); configuredHash.Available() { -+ for _, hashId := range candidateHashes { -+ if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { -+ hash = h -+ break -+ } -+ } -+ } -+ -+ if hash == 0 { -+ hashId := candidateHashes[0] -+ name, ok := s2k.HashIdToString(hashId) -+ if !ok { -+ name = "#" + strconv.Itoa(int(hashId)) -+ } -+ return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") -+ } -+ -+ if signer != nil { -+ ops := &packet.OnePassSignature{ -+ SigType: packet.SigTypeBinary, -+ Hash: hash, -+ PubKeyAlgo: signer.PubKeyAlgo, -+ KeyId: signer.KeyId, -+ IsLast: true, -+ } -+ if err := ops.Serialize(payload); err != nil { -+ return nil, err -+ } -+ } -+ -+ if hints == nil { -+ hints = &FileHints{} -+ } -+ -+ w := payload -+ if signer != nil { -+ // If we need to write a signature packet after the literal -+ // data then we need to stop literalData from closing -+ // encryptedData. -+ w = noOpCloser{w} -+ -+ } -+ var epochSeconds uint32 -+ if !hints.ModTime.IsZero() { -+ epochSeconds = uint32(hints.ModTime.Unix()) -+ } -+ literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) -+ if err != nil { -+ return nil, err -+ } -+ -+ if signer != nil { -+ return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil -+ } -+ return literalData, nil -+} -+ -+// Encrypt encrypts a message to a number of recipients and, optionally, signs -+// it. hints contains optional information, that is also encrypted, that aids -+// the recipients in processing the message. The resulting WriteCloser must -+// be closed after the contents of the file have been written. -+// If config is nil, sensible defaults will be used. -+func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { -+ if len(to) == 0 { -+ return nil, errors.InvalidArgumentError("no encryption recipient provided") -+ } -+ -+ // These are the possible ciphers that we'll use for the message. -+ candidateCiphers := []uint8{ -+ uint8(packet.CipherAES128), -+ uint8(packet.CipherAES256), -+ uint8(packet.CipherCAST5), -+ } -+ // These are the possible hash functions that we'll use for the signature. -+ candidateHashes := []uint8{ -+ hashToHashId(crypto.SHA256), -+ hashToHashId(crypto.SHA384), -+ hashToHashId(crypto.SHA512), -+ hashToHashId(crypto.SHA1), -+ hashToHashId(crypto.RIPEMD160), -+ } -+ // In the event that a recipient doesn't specify any supported ciphers -+ // or hash functions, these are the ones that we assume that every -+ // implementation supports. -+ defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] -+ defaultHashes := candidateHashes[len(candidateHashes)-1:] -+ -+ encryptKeys := make([]Key, len(to)) -+ for i := range to { -+ var ok bool -+ encryptKeys[i], ok = to[i].encryptionKey(config.Now()) -+ if !ok { -+ return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") -+ } -+ -+ sig := to[i].primaryIdentity().SelfSignature -+ -+ preferredSymmetric := sig.PreferredSymmetric -+ if len(preferredSymmetric) == 0 { -+ preferredSymmetric = defaultCiphers -+ } -+ preferredHashes := sig.PreferredHash -+ if len(preferredHashes) == 0 { -+ preferredHashes = defaultHashes -+ } -+ candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) -+ candidateHashes = intersectPreferences(candidateHashes, preferredHashes) -+ } -+ -+ if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { -+ return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") -+ } -+ -+ cipher := packet.CipherFunction(candidateCiphers[0]) -+ // If the cipher specified by config is a candidate, we'll use that. -+ configuredCipher := config.Cipher() -+ for _, c := range candidateCiphers { -+ cipherFunc := packet.CipherFunction(c) -+ if cipherFunc == configuredCipher { -+ cipher = cipherFunc -+ break -+ } -+ } -+ -+ symKey := make([]byte, cipher.KeySize()) -+ if _, err := io.ReadFull(config.Random(), symKey); err != nil { -+ return nil, err -+ } -+ -+ for _, key := range encryptKeys { -+ if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { -+ return nil, err -+ } -+ } -+ -+ payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) -+ if err != nil { -+ return -+ } -+ -+ return writeAndSign(payload, candidateHashes, signed, hints, config) -+} -+ -+// Sign signs a message. The resulting WriteCloser must be closed after the -+// contents of the file have been written. hints contains optional information -+// that aids the recipients in processing the message. -+// If config is nil, sensible defaults will be used. -+func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { -+ if signed == nil { -+ return nil, errors.InvalidArgumentError("no signer provided") -+ } -+ -+ // These are the possible hash functions that we'll use for the signature. -+ candidateHashes := []uint8{ -+ hashToHashId(crypto.SHA256), -+ hashToHashId(crypto.SHA384), -+ hashToHashId(crypto.SHA512), -+ hashToHashId(crypto.SHA1), -+ hashToHashId(crypto.RIPEMD160), -+ } -+ defaultHashes := candidateHashes[len(candidateHashes)-1:] -+ preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash -+ if len(preferredHashes) == 0 { -+ preferredHashes = defaultHashes -+ } -+ candidateHashes = intersectPreferences(candidateHashes, preferredHashes) -+ return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) -+} -+ -+// signatureWriter hashes the contents of a message while passing it along to -+// literalData. When closed, it closes literalData, writes a signature packet -+// to encryptedData and then also closes encryptedData. -+type signatureWriter struct { -+ encryptedData io.WriteCloser -+ literalData io.WriteCloser -+ hashType crypto.Hash -+ h hash.Hash -+ signer *packet.PrivateKey -+ config *packet.Config -+} -+ -+func (s signatureWriter) Write(data []byte) (int, error) { -+ s.h.Write(data) -+ return s.literalData.Write(data) -+} -+ -+func (s signatureWriter) Close() error { -+ sig := &packet.Signature{ -+ SigType: packet.SigTypeBinary, -+ PubKeyAlgo: s.signer.PubKeyAlgo, -+ Hash: s.hashType, -+ CreationTime: s.config.Now(), -+ IssuerKeyId: &s.signer.KeyId, -+ } -+ -+ if err := sig.Sign(s.h, s.signer, s.config); err != nil { -+ return err -+ } -+ if err := s.literalData.Close(); err != nil { -+ return err -+ } -+ if err := sig.Serialize(s.encryptedData); err != nil { -+ return err -+ } -+ return s.encryptedData.Close() -+} -+ -+// noOpCloser is like an io.NopCloser, but for an io.Writer. -+// TODO: we have two of these in OpenPGP packages alone. This probably needs -+// to be promoted somewhere more common. -+type noOpCloser struct { -+ w io.Writer -+} -+ -+func (c noOpCloser) Write(data []byte) (n int, err error) { -+ return c.w.Write(data) -+} -+ -+func (c noOpCloser) Close() error { -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/openpgp/write_test.go b/ms_mod/golang.org/x/crypto/openpgp/write_test.go -new file mode 100644 -index 00000000000000..8b686789ee5f34 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/openpgp/write_test.go -@@ -0,0 +1,361 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package openpgp -+ -+import ( -+ "bytes" -+ "io" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/openpgp/packet" -+) -+ -+func TestSignDetached(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) -+ out := bytes.NewBuffer(nil) -+ message := bytes.NewBufferString(signedInput) -+ err := DetachSign(out, kring[0], message, nil) -+ if err != nil { -+ t.Error(err) -+ } -+ -+ testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) -+} -+ -+func TestSignTextDetached(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) -+ out := bytes.NewBuffer(nil) -+ message := bytes.NewBufferString(signedInput) -+ err := DetachSignText(out, kring[0], message, nil) -+ if err != nil { -+ t.Error(err) -+ } -+ -+ testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) -+} -+ -+func TestSignDetachedDSA(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex)) -+ out := bytes.NewBuffer(nil) -+ message := bytes.NewBufferString(signedInput) -+ err := DetachSign(out, kring[0], message, nil) -+ if err != nil { -+ t.Error(err) -+ } -+ -+ testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId) -+} -+ -+func TestSignDetachedP256(t *testing.T) { -+ kring, _ := ReadKeyRing(readerFromHex(p256TestKeyPrivateHex)) -+ kring[0].PrivateKey.Decrypt([]byte("passphrase")) -+ -+ out := bytes.NewBuffer(nil) -+ message := bytes.NewBufferString(signedInput) -+ err := DetachSign(out, kring[0], message, nil) -+ if err != nil { -+ t.Error(err) -+ } -+ -+ testDetachedSignature(t, kring, out, signedInput, "check", testKeyP256KeyId) -+} -+ -+func TestNewEntity(t *testing.T) { -+ if testing.Short() { -+ return -+ } -+ -+ // Check bit-length with no config. -+ e, err := NewEntity("Test User", "test", "test@example.com", nil) -+ if err != nil { -+ t.Errorf("failed to create entity: %s", err) -+ return -+ } -+ bl, err := e.PrimaryKey.BitLength() -+ if err != nil { -+ t.Errorf("failed to find bit length: %s", err) -+ } -+ if int(bl) != defaultRSAKeyBits { -+ t.Errorf("BitLength %v, expected %v", int(bl), defaultRSAKeyBits) -+ } -+ -+ // Check bit-length with a config. -+ cfg := &packet.Config{RSABits: 1024} -+ e, err = NewEntity("Test User", "test", "test@example.com", cfg) -+ if err != nil { -+ t.Errorf("failed to create entity: %s", err) -+ return -+ } -+ bl, err = e.PrimaryKey.BitLength() -+ if err != nil { -+ t.Errorf("failed to find bit length: %s", err) -+ } -+ if int(bl) != cfg.RSABits { -+ t.Errorf("BitLength %v, expected %v", bl, cfg.RSABits) -+ } -+ -+ w := bytes.NewBuffer(nil) -+ if err := e.SerializePrivate(w, nil); err != nil { -+ t.Errorf("failed to serialize entity: %s", err) -+ return -+ } -+ serialized := w.Bytes() -+ -+ el, err := ReadKeyRing(w) -+ if err != nil { -+ t.Errorf("failed to reparse entity: %s", err) -+ return -+ } -+ -+ if len(el) != 1 { -+ t.Errorf("wrong number of entities found, got %d, want 1", len(el)) -+ } -+ -+ w = bytes.NewBuffer(nil) -+ if err := e.SerializePrivate(w, nil); err != nil { -+ t.Errorf("failed to serialize entity second time: %s", err) -+ return -+ } -+ -+ if !bytes.Equal(w.Bytes(), serialized) { -+ t.Errorf("results differed") -+ } -+} -+ -+func TestSymmetricEncryption(t *testing.T) { -+ buf := new(bytes.Buffer) -+ plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil) -+ if err != nil { -+ t.Errorf("error writing headers: %s", err) -+ return -+ } -+ message := []byte("hello world\n") -+ _, err = plaintext.Write(message) -+ if err != nil { -+ t.Errorf("error writing to plaintext writer: %s", err) -+ } -+ err = plaintext.Close() -+ if err != nil { -+ t.Errorf("error closing plaintext writer: %s", err) -+ } -+ -+ md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) { -+ return []byte("testing"), nil -+ }, nil) -+ if err != nil { -+ t.Errorf("error rereading message: %s", err) -+ } -+ messageBuf := bytes.NewBuffer(nil) -+ _, err = io.Copy(messageBuf, md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("error rereading message: %s", err) -+ } -+ if !bytes.Equal(message, messageBuf.Bytes()) { -+ t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message) -+ } -+} -+ -+var testEncryptionTests = []struct { -+ keyRingHex string -+ isSigned bool -+}{ -+ { -+ testKeys1And2PrivateHex, -+ false, -+ }, -+ { -+ testKeys1And2PrivateHex, -+ true, -+ }, -+ { -+ dsaElGamalTestKeysHex, -+ false, -+ }, -+ { -+ dsaElGamalTestKeysHex, -+ true, -+ }, -+} -+ -+func TestEncryption(t *testing.T) { -+ for i, test := range testEncryptionTests { -+ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) -+ -+ passphrase := []byte("passphrase") -+ for _, entity := range kring { -+ if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { -+ err := entity.PrivateKey.Decrypt(passphrase) -+ if err != nil { -+ t.Errorf("#%d: failed to decrypt key", i) -+ } -+ } -+ for _, subkey := range entity.Subkeys { -+ if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { -+ err := subkey.PrivateKey.Decrypt(passphrase) -+ if err != nil { -+ t.Errorf("#%d: failed to decrypt subkey", i) -+ } -+ } -+ } -+ } -+ -+ var signed *Entity -+ if test.isSigned { -+ signed = kring[0] -+ } -+ -+ buf := new(bytes.Buffer) -+ w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil) -+ if err != nil { -+ t.Errorf("#%d: error in Encrypt: %s", i, err) -+ continue -+ } -+ -+ const message = "testing" -+ _, err = w.Write([]byte(message)) -+ if err != nil { -+ t.Errorf("#%d: error writing plaintext: %s", i, err) -+ continue -+ } -+ err = w.Close() -+ if err != nil { -+ t.Errorf("#%d: error closing WriteCloser: %s", i, err) -+ continue -+ } -+ -+ md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) -+ if err != nil { -+ t.Errorf("#%d: error reading message: %s", i, err) -+ continue -+ } -+ -+ testTime, _ := time.Parse("2006-01-02", "2013-07-01") -+ if test.isSigned { -+ signKey, _ := kring[0].signingKey(testTime) -+ expectedKeyId := signKey.PublicKey.KeyId -+ if md.SignedByKeyId != expectedKeyId { -+ t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId) -+ } -+ if md.SignedBy == nil { -+ t.Errorf("#%d: failed to find the signing Entity", i) -+ } -+ } -+ -+ plaintext, err := io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("#%d: error reading encrypted contents: %s", i, err) -+ continue -+ } -+ -+ encryptKey, _ := kring[0].encryptionKey(testTime) -+ expectedKeyId := encryptKey.PublicKey.KeyId -+ if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId { -+ t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds) -+ } -+ -+ if string(plaintext) != message { -+ t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message) -+ } -+ -+ if test.isSigned { -+ if md.SignatureError != nil { -+ t.Errorf("#%d: signature error: %s", i, md.SignatureError) -+ } -+ if md.Signature == nil { -+ t.Error("signature missing") -+ } -+ } -+ } -+} -+ -+var testSigningTests = []struct { -+ keyRingHex string -+}{ -+ { -+ testKeys1And2PrivateHex, -+ }, -+ { -+ dsaElGamalTestKeysHex, -+ }, -+} -+ -+func TestSigning(t *testing.T) { -+ for i, test := range testSigningTests { -+ kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) -+ -+ passphrase := []byte("passphrase") -+ for _, entity := range kring { -+ if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { -+ err := entity.PrivateKey.Decrypt(passphrase) -+ if err != nil { -+ t.Errorf("#%d: failed to decrypt key", i) -+ } -+ } -+ for _, subkey := range entity.Subkeys { -+ if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { -+ err := subkey.PrivateKey.Decrypt(passphrase) -+ if err != nil { -+ t.Errorf("#%d: failed to decrypt subkey", i) -+ } -+ } -+ } -+ } -+ -+ signed := kring[0] -+ -+ buf := new(bytes.Buffer) -+ w, err := Sign(buf, signed, nil /* no hints */, nil) -+ if err != nil { -+ t.Errorf("#%d: error in Sign: %s", i, err) -+ continue -+ } -+ -+ const message = "testing" -+ _, err = w.Write([]byte(message)) -+ if err != nil { -+ t.Errorf("#%d: error writing plaintext: %s", i, err) -+ continue -+ } -+ err = w.Close() -+ if err != nil { -+ t.Errorf("#%d: error closing WriteCloser: %s", i, err) -+ continue -+ } -+ -+ md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) -+ if err != nil { -+ t.Errorf("#%d: error reading message: %s", i, err) -+ continue -+ } -+ -+ testTime, _ := time.Parse("2006-01-02", "2013-07-01") -+ signKey, _ := kring[0].signingKey(testTime) -+ expectedKeyId := signKey.PublicKey.KeyId -+ if md.SignedByKeyId != expectedKeyId { -+ t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId) -+ } -+ if md.SignedBy == nil { -+ t.Errorf("#%d: failed to find the signing Entity", i) -+ } -+ -+ plaintext, err := io.ReadAll(md.UnverifiedBody) -+ if err != nil { -+ t.Errorf("#%d: error reading contents: %v", i, err) -+ continue -+ } -+ -+ if string(plaintext) != message { -+ t.Errorf("#%d: got: %q, want: %q", i, plaintext, message) -+ } -+ -+ if md.SignatureError != nil { -+ t.Errorf("#%d: signature error: %q", i, md.SignatureError) -+ } -+ if md.Signature == nil { -+ t.Error("signature missing") -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c b/ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c -new file mode 100644 -index 00000000000000..b3ca072d480924 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/otr/libotr_test_helper.c -@@ -0,0 +1,197 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This code can be compiled and used to test the otr package against libotr. -+// See otr_test.go. -+ -+// +build ignore -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static int g_session_established = 0; -+ -+OtrlPolicy policy(void *opdata, ConnContext *context) { -+ return OTRL_POLICY_ALWAYS; -+} -+ -+int is_logged_in(void *opdata, const char *accountname, const char *protocol, -+ const char *recipient) { -+ return 1; -+} -+ -+void inject_message(void *opdata, const char *accountname, const char *protocol, -+ const char *recipient, const char *message) { -+ printf("%s\n", message); -+ fflush(stdout); -+ fprintf(stderr, "libotr helper sent: %s\n", message); -+} -+ -+void update_context_list(void *opdata) {} -+ -+void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, -+ const char *protocol, const char *username, -+ unsigned char fingerprint[20]) { -+ fprintf(stderr, "NEW FINGERPRINT\n"); -+ g_session_established = 1; -+} -+ -+void write_fingerprints(void *opdata) {} -+ -+void gone_secure(void *opdata, ConnContext *context) {} -+ -+void gone_insecure(void *opdata, ConnContext *context) {} -+ -+void still_secure(void *opdata, ConnContext *context, int is_reply) {} -+ -+int max_message_size(void *opdata, ConnContext *context) { return 99999; } -+ -+const char *account_name(void *opdata, const char *account, -+ const char *protocol) { -+ return "ACCOUNT"; -+} -+ -+void account_name_free(void *opdata, const char *account_name) {} -+ -+const char *error_message(void *opdata, ConnContext *context, -+ OtrlErrorCode err_code) { -+ return "ERR"; -+} -+ -+void error_message_free(void *opdata, const char *msg) {} -+ -+void resent_msg_prefix_free(void *opdata, const char *prefix) {} -+ -+void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, -+ ConnContext *context, unsigned short progress_event, -+ char *question) {} -+ -+void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, -+ ConnContext *context, const char *message, -+ gcry_error_t err) { -+ fprintf(stderr, "msg event: %d %s\n", msg_event, message); -+} -+ -+OtrlMessageAppOps uiops = { -+ policy, -+ NULL, -+ is_logged_in, -+ inject_message, -+ update_context_list, -+ new_fingerprint, -+ write_fingerprints, -+ gone_secure, -+ gone_insecure, -+ still_secure, -+ max_message_size, -+ account_name, -+ account_name_free, -+ NULL, /* received_symkey */ -+ error_message, -+ error_message_free, -+ NULL, /* resent_msg_prefix */ -+ resent_msg_prefix_free, -+ handle_smp_event, -+ handle_msg_event, -+ NULL /* create_instag */, -+ NULL /* convert_msg */, -+ NULL /* convert_free */, -+ NULL /* timer_control */, -+}; -+ -+static const char kPrivateKeyData[] = -+ "(privkeys (account (name \"account\") (protocol proto) (private-key (dsa " -+ "(p " -+ "#00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F" -+ "30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E" -+ "5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB" -+ "8C031D3561FECEE72EBB4A090D450A9B7A857#) (q " -+ "#00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g " -+ "#535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F" -+ "1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F" -+ "6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57" -+ "597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y " -+ "#0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF" -+ "2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93" -+ "454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A" -+ "3C0FF501E3DC673B76D7BABF349009B6ECF#) (x " -+ "#14D0345A3562C480A039E3C72764F72D79043216#)))))\n"; -+ -+int main() { -+ OTRL_INIT; -+ -+ // We have to write the private key information to a file because the libotr -+ // API demands a filename to read from. -+ const char *tmpdir = "/tmp"; -+ if (getenv("TMP")) { -+ tmpdir = getenv("TMP"); -+ } -+ -+ char private_key_file[256]; -+ snprintf(private_key_file, sizeof(private_key_file), -+ "%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir); -+ int fd = mkstemp(private_key_file); -+ if (fd == -1) { -+ perror("creating temp file"); -+ } -+ write(fd, kPrivateKeyData, sizeof(kPrivateKeyData) - 1); -+ close(fd); -+ -+ OtrlUserState userstate = otrl_userstate_create(); -+ otrl_privkey_read(userstate, private_key_file); -+ unlink(private_key_file); -+ -+ fprintf(stderr, "libotr helper started\n"); -+ -+ char buf[4096]; -+ -+ for (;;) { -+ char *message = fgets(buf, sizeof(buf), stdin); -+ if (strlen(message) == 0) { -+ break; -+ } -+ message[strlen(message) - 1] = 0; -+ fprintf(stderr, "libotr helper got: %s\n", message); -+ -+ char *newmessage = NULL; -+ OtrlTLV *tlvs; -+ int ignore_message = otrl_message_receiving( -+ userstate, &uiops, NULL, "account", "proto", "peer", message, -+ &newmessage, &tlvs, NULL, NULL, NULL); -+ if (tlvs) { -+ otrl_tlv_free(tlvs); -+ } -+ -+ if (newmessage != NULL) { -+ fprintf(stderr, "libotr got: %s\n", newmessage); -+ otrl_message_free(newmessage); -+ -+ gcry_error_t err; -+ char *newmessage = NULL; -+ -+ err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto", -+ "peer", 0, "test message", NULL, &newmessage, -+ OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL); -+ if (newmessage == NULL) { -+ fprintf(stderr, "libotr didn't encrypt message\n"); -+ return 1; -+ } -+ write(1, newmessage, strlen(newmessage)); -+ write(1, "\n", 1); -+ fprintf(stderr, "libotr sent: %s\n", newmessage); -+ otrl_message_free(newmessage); -+ -+ g_session_established = 0; -+ write(1, "?OTRv2?\n", 8); -+ fprintf(stderr, "libotr sent: ?OTRv2\n"); -+ } -+ } -+ -+ return 0; -+} -diff --git a/ms_mod/golang.org/x/crypto/otr/otr.go b/ms_mod/golang.org/x/crypto/otr/otr.go -new file mode 100644 -index 00000000000000..29121e9bb653ac ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/otr/otr.go -@@ -0,0 +1,1419 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package otr implements the Off The Record protocol as specified in -+// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html -+// -+// The version of OTR implemented by this package has been deprecated -+// (https://bugs.otr.im/lib/libotr/issues/140). An implementation of OTRv3 is -+// available at https://github.com/coyim/otr3. -+package otr // import "golang.org/x/crypto/otr" -+ -+import ( -+ "bytes" -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/dsa" -+ "crypto/hmac" -+ "crypto/rand" -+ "crypto/sha1" -+ "crypto/sha256" -+ "crypto/subtle" -+ "encoding/base64" -+ "encoding/hex" -+ "errors" -+ "hash" -+ "io" -+ "math/big" -+ "strconv" -+) -+ -+// SecurityChange describes a change in the security state of a Conversation. -+type SecurityChange int -+ -+const ( -+ NoChange SecurityChange = iota -+ // NewKeys indicates that a key exchange has completed. This occurs -+ // when a conversation first becomes encrypted, and when the keys are -+ // renegotiated within an encrypted conversation. -+ NewKeys -+ // SMPSecretNeeded indicates that the peer has started an -+ // authentication and that we need to supply a secret. Call SMPQuestion -+ // to get the optional, human readable challenge and then Authenticate -+ // to supply the matching secret. -+ SMPSecretNeeded -+ // SMPComplete indicates that an authentication completed. The identity -+ // of the peer has now been confirmed. -+ SMPComplete -+ // SMPFailed indicates that an authentication failed. -+ SMPFailed -+ // ConversationEnded indicates that the peer ended the secure -+ // conversation. -+ ConversationEnded -+) -+ -+// QueryMessage can be sent to a peer to start an OTR conversation. -+var QueryMessage = "?OTRv2?" -+ -+// ErrorPrefix can be used to make an OTR error by appending an error message -+// to it. -+var ErrorPrefix = "?OTR Error:" -+ -+var ( -+ fragmentPartSeparator = []byte(",") -+ fragmentPrefix = []byte("?OTR,") -+ msgPrefix = []byte("?OTR:") -+ queryMarker = []byte("?OTR") -+) -+ -+// isQuery attempts to parse an OTR query from msg and returns the greatest -+// common version, or 0 if msg is not an OTR query. -+func isQuery(msg []byte) (greatestCommonVersion int) { -+ pos := bytes.Index(msg, queryMarker) -+ if pos == -1 { -+ return 0 -+ } -+ for i, c := range msg[pos+len(queryMarker):] { -+ if i == 0 { -+ if c == '?' { -+ // Indicates support for version 1, but we don't -+ // implement that. -+ continue -+ } -+ -+ if c != 'v' { -+ // Invalid message -+ return 0 -+ } -+ -+ continue -+ } -+ -+ if c == '?' { -+ // End of message -+ return -+ } -+ -+ if c == ' ' || c == '\t' { -+ // Probably an invalid message -+ return 0 -+ } -+ -+ if c == '2' { -+ greatestCommonVersion = 2 -+ } -+ } -+ -+ return 0 -+} -+ -+const ( -+ statePlaintext = iota -+ stateEncrypted -+ stateFinished -+) -+ -+const ( -+ authStateNone = iota -+ authStateAwaitingDHKey -+ authStateAwaitingRevealSig -+ authStateAwaitingSig -+) -+ -+const ( -+ msgTypeDHCommit = 2 -+ msgTypeData = 3 -+ msgTypeDHKey = 10 -+ msgTypeRevealSig = 17 -+ msgTypeSig = 18 -+) -+ -+const ( -+ // If the requested fragment size is less than this, it will be ignored. -+ minFragmentSize = 18 -+ // Messages are padded to a multiple of this number of bytes. -+ paddingGranularity = 256 -+ // The number of bytes in a Diffie-Hellman private value (320-bits). -+ dhPrivateBytes = 40 -+ // The number of bytes needed to represent an element of the DSA -+ // subgroup (160-bits). -+ dsaSubgroupBytes = 20 -+ // The number of bytes of the MAC that are sent on the wire (160-bits). -+ macPrefixBytes = 20 -+) -+ -+// These are the global, common group parameters for OTR. -+var ( -+ p *big.Int // group prime -+ g *big.Int // group generator -+ q *big.Int // group order -+ pMinus2 *big.Int -+) -+ -+func init() { -+ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16) -+ q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16) -+ g = new(big.Int).SetInt64(2) -+ pMinus2 = new(big.Int).Sub(p, g) -+} -+ -+// Conversation represents a relation with a peer. The zero value is a valid -+// Conversation, although PrivateKey must be set. -+// -+// When communicating with a peer, all inbound messages should be passed to -+// Conversation.Receive and all outbound messages to Conversation.Send. The -+// Conversation will take care of maintaining the encryption state and -+// negotiating encryption as needed. -+type Conversation struct { -+ // PrivateKey contains the private key to use to sign key exchanges. -+ PrivateKey *PrivateKey -+ -+ // Rand can be set to override the entropy source. Otherwise, -+ // crypto/rand will be used. -+ Rand io.Reader -+ // If FragmentSize is set, all messages produced by Receive and Send -+ // will be fragmented into messages of, at most, this number of bytes. -+ FragmentSize int -+ -+ // Once Receive has returned NewKeys once, the following fields are -+ // valid. -+ SSID [8]byte -+ TheirPublicKey PublicKey -+ -+ state, authState int -+ -+ r [16]byte -+ x, y *big.Int -+ gx, gy *big.Int -+ gxBytes []byte -+ digest [sha256.Size]byte -+ -+ revealKeys, sigKeys akeKeys -+ -+ myKeyId uint32 -+ myCurrentDHPub *big.Int -+ myCurrentDHPriv *big.Int -+ myLastDHPub *big.Int -+ myLastDHPriv *big.Int -+ -+ theirKeyId uint32 -+ theirCurrentDHPub *big.Int -+ theirLastDHPub *big.Int -+ -+ keySlots [4]keySlot -+ -+ myCounter [8]byte -+ theirLastCtr [8]byte -+ oldMACs []byte -+ -+ k, n int // fragment state -+ frag []byte -+ -+ smp smpState -+} -+ -+// A keySlot contains key material for a specific (their keyid, my keyid) pair. -+type keySlot struct { -+ // used is true if this slot is valid. If false, it's free for reuse. -+ used bool -+ theirKeyId uint32 -+ myKeyId uint32 -+ sendAESKey, recvAESKey []byte -+ sendMACKey, recvMACKey []byte -+ theirLastCtr [8]byte -+} -+ -+// akeKeys are generated during key exchange. There's one set for the reveal -+// signature message and another for the signature message. In the protocol -+// spec the latter are indicated with a prime mark. -+type akeKeys struct { -+ c [16]byte -+ m1, m2 [32]byte -+} -+ -+func (c *Conversation) rand() io.Reader { -+ if c.Rand != nil { -+ return c.Rand -+ } -+ return rand.Reader -+} -+ -+func (c *Conversation) randMPI(buf []byte) *big.Int { -+ _, err := io.ReadFull(c.rand(), buf) -+ if err != nil { -+ panic("otr: short read from random source") -+ } -+ -+ return new(big.Int).SetBytes(buf) -+} -+ -+// tlv represents the type-length value from the protocol. -+type tlv struct { -+ typ, length uint16 -+ data []byte -+} -+ -+const ( -+ tlvTypePadding = 0 -+ tlvTypeDisconnected = 1 -+ tlvTypeSMP1 = 2 -+ tlvTypeSMP2 = 3 -+ tlvTypeSMP3 = 4 -+ tlvTypeSMP4 = 5 -+ tlvTypeSMPAbort = 6 -+ tlvTypeSMP1WithQuestion = 7 -+) -+ -+// Receive handles a message from a peer. It returns a human readable message, -+// an indicator of whether that message was encrypted, a hint about the -+// encryption state and zero or more messages to send back to the peer. -+// These messages do not need to be passed to Send before transmission. -+func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) { -+ if bytes.HasPrefix(in, fragmentPrefix) { -+ in, err = c.processFragment(in) -+ if in == nil || err != nil { -+ return -+ } -+ } -+ -+ if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' { -+ in = in[len(msgPrefix) : len(in)-1] -+ } else if version := isQuery(in); version > 0 { -+ c.authState = authStateAwaitingDHKey -+ c.reset() -+ toSend = c.encode(c.generateDHCommit()) -+ return -+ } else { -+ // plaintext message -+ out = in -+ return -+ } -+ -+ msg := make([]byte, base64.StdEncoding.DecodedLen(len(in))) -+ msgLen, err := base64.StdEncoding.Decode(msg, in) -+ if err != nil { -+ err = errors.New("otr: invalid base64 encoding in message") -+ return -+ } -+ msg = msg[:msgLen] -+ -+ // The first two bytes are the protocol version (2) -+ if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 { -+ err = errors.New("otr: invalid OTR message") -+ return -+ } -+ -+ msgType := int(msg[2]) -+ msg = msg[3:] -+ -+ switch msgType { -+ case msgTypeDHCommit: -+ switch c.authState { -+ case authStateNone: -+ c.authState = authStateAwaitingRevealSig -+ if err = c.processDHCommit(msg); err != nil { -+ return -+ } -+ c.reset() -+ toSend = c.encode(c.generateDHKey()) -+ return -+ case authStateAwaitingDHKey: -+ // This is a 'SYN-crossing'. The greater digest wins. -+ var cmp int -+ if cmp, err = c.compareToDHCommit(msg); err != nil { -+ return -+ } -+ if cmp > 0 { -+ // We win. Retransmit DH commit. -+ toSend = c.encode(c.serializeDHCommit()) -+ return -+ } else { -+ // They win. We forget about our DH commit. -+ c.authState = authStateAwaitingRevealSig -+ if err = c.processDHCommit(msg); err != nil { -+ return -+ } -+ c.reset() -+ toSend = c.encode(c.generateDHKey()) -+ return -+ } -+ case authStateAwaitingRevealSig: -+ if err = c.processDHCommit(msg); err != nil { -+ return -+ } -+ toSend = c.encode(c.serializeDHKey()) -+ case authStateAwaitingSig: -+ if err = c.processDHCommit(msg); err != nil { -+ return -+ } -+ c.reset() -+ toSend = c.encode(c.generateDHKey()) -+ c.authState = authStateAwaitingRevealSig -+ default: -+ panic("bad state") -+ } -+ case msgTypeDHKey: -+ switch c.authState { -+ case authStateAwaitingDHKey: -+ var isSame bool -+ if isSame, err = c.processDHKey(msg); err != nil { -+ return -+ } -+ if isSame { -+ err = errors.New("otr: unexpected duplicate DH key") -+ return -+ } -+ toSend = c.encode(c.generateRevealSig()) -+ c.authState = authStateAwaitingSig -+ case authStateAwaitingSig: -+ var isSame bool -+ if isSame, err = c.processDHKey(msg); err != nil { -+ return -+ } -+ if isSame { -+ toSend = c.encode(c.serializeDHKey()) -+ } -+ } -+ case msgTypeRevealSig: -+ if c.authState != authStateAwaitingRevealSig { -+ return -+ } -+ if err = c.processRevealSig(msg); err != nil { -+ return -+ } -+ toSend = c.encode(c.generateSig()) -+ c.authState = authStateNone -+ c.state = stateEncrypted -+ change = NewKeys -+ case msgTypeSig: -+ if c.authState != authStateAwaitingSig { -+ return -+ } -+ if err = c.processSig(msg); err != nil { -+ return -+ } -+ c.authState = authStateNone -+ c.state = stateEncrypted -+ change = NewKeys -+ case msgTypeData: -+ if c.state != stateEncrypted { -+ err = errors.New("otr: encrypted message received without encrypted session established") -+ return -+ } -+ var tlvs []tlv -+ out, tlvs, err = c.processData(msg) -+ encrypted = true -+ -+ EachTLV: -+ for _, inTLV := range tlvs { -+ switch inTLV.typ { -+ case tlvTypeDisconnected: -+ change = ConversationEnded -+ c.state = stateFinished -+ break EachTLV -+ case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion: -+ var reply tlv -+ var complete bool -+ reply, complete, err = c.processSMP(inTLV) -+ if err == smpSecretMissingError { -+ err = nil -+ change = SMPSecretNeeded -+ c.smp.saved = &inTLV -+ return -+ } -+ if err == smpFailureError { -+ err = nil -+ change = SMPFailed -+ } else if complete { -+ change = SMPComplete -+ } -+ if reply.typ != 0 { -+ toSend = c.encode(c.generateData(nil, &reply)) -+ } -+ break EachTLV -+ default: -+ // skip unknown TLVs -+ } -+ } -+ default: -+ err = errors.New("otr: unknown message type " + strconv.Itoa(msgType)) -+ } -+ -+ return -+} -+ -+// Send takes a human readable message from the local user, possibly encrypts -+// it and returns zero one or more messages to send to the peer. -+func (c *Conversation) Send(msg []byte) ([][]byte, error) { -+ switch c.state { -+ case statePlaintext: -+ return [][]byte{msg}, nil -+ case stateEncrypted: -+ return c.encode(c.generateData(msg, nil)), nil -+ case stateFinished: -+ return nil, errors.New("otr: cannot send message because secure conversation has finished") -+ } -+ -+ return nil, errors.New("otr: cannot send message in current state") -+} -+ -+// SMPQuestion returns the human readable challenge question from the peer. -+// It's only valid after Receive has returned SMPSecretNeeded. -+func (c *Conversation) SMPQuestion() string { -+ return c.smp.question -+} -+ -+// Authenticate begins an authentication with the peer. Authentication involves -+// an optional challenge message and a shared secret. The authentication -+// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which -+// indicates that a new authentication is happening and thus this one was -+// aborted) or SMPFailed. -+func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) { -+ if c.state != stateEncrypted { -+ err = errors.New("otr: can't authenticate a peer without a secure conversation established") -+ return -+ } -+ -+ if c.smp.saved != nil { -+ c.calcSMPSecret(mutualSecret, false /* they started it */) -+ -+ var out tlv -+ var complete bool -+ out, complete, err = c.processSMP(*c.smp.saved) -+ if complete { -+ panic("SMP completed on the first message") -+ } -+ c.smp.saved = nil -+ if out.typ != 0 { -+ toSend = c.encode(c.generateData(nil, &out)) -+ } -+ return -+ } -+ -+ c.calcSMPSecret(mutualSecret, true /* we started it */) -+ outs := c.startSMP(question) -+ for _, out := range outs { -+ toSend = append(toSend, c.encode(c.generateData(nil, &out))...) -+ } -+ return -+} -+ -+// End ends a secure conversation by generating a termination message for -+// the peer and switches to unencrypted communication. -+func (c *Conversation) End() (toSend [][]byte) { -+ switch c.state { -+ case statePlaintext: -+ return nil -+ case stateEncrypted: -+ c.state = statePlaintext -+ return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected})) -+ case stateFinished: -+ c.state = statePlaintext -+ return nil -+ } -+ panic("unreachable") -+} -+ -+// IsEncrypted returns true if a message passed to Send would be encrypted -+// before transmission. This result remains valid until the next call to -+// Receive or End, which may change the state of the Conversation. -+func (c *Conversation) IsEncrypted() bool { -+ return c.state == stateEncrypted -+} -+ -+var fragmentError = errors.New("otr: invalid OTR fragment") -+ -+// processFragment processes a fragmented OTR message and possibly returns a -+// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is -+// the fragment number (starting from 1), n is the number of fragments in this -+// message and msg is a substring of the base64 encoded message. -+func (c *Conversation) processFragment(in []byte) (out []byte, err error) { -+ in = in[len(fragmentPrefix):] // remove "?OTR," -+ parts := bytes.Split(in, fragmentPartSeparator) -+ if len(parts) != 4 || len(parts[3]) != 0 { -+ return nil, fragmentError -+ } -+ -+ k, err := strconv.Atoi(string(parts[0])) -+ if err != nil { -+ return nil, fragmentError -+ } -+ -+ n, err := strconv.Atoi(string(parts[1])) -+ if err != nil { -+ return nil, fragmentError -+ } -+ -+ if k < 1 || n < 1 || k > n { -+ return nil, fragmentError -+ } -+ -+ if k == 1 { -+ c.frag = append(c.frag[:0], parts[2]...) -+ c.k, c.n = k, n -+ } else if n == c.n && k == c.k+1 { -+ c.frag = append(c.frag, parts[2]...) -+ c.k++ -+ } else { -+ c.frag = c.frag[:0] -+ c.n, c.k = 0, 0 -+ } -+ -+ if c.n > 0 && c.k == c.n { -+ c.n, c.k = 0, 0 -+ return c.frag, nil -+ } -+ -+ return nil, nil -+} -+ -+func (c *Conversation) generateDHCommit() []byte { -+ _, err := io.ReadFull(c.rand(), c.r[:]) -+ if err != nil { -+ panic("otr: short read from random source") -+ } -+ -+ var xBytes [dhPrivateBytes]byte -+ c.x = c.randMPI(xBytes[:]) -+ c.gx = new(big.Int).Exp(g, c.x, p) -+ c.gy = nil -+ c.gxBytes = appendMPI(nil, c.gx) -+ -+ h := sha256.New() -+ h.Write(c.gxBytes) -+ h.Sum(c.digest[:0]) -+ -+ aesCipher, err := aes.NewCipher(c.r[:]) -+ if err != nil { -+ panic(err.Error()) -+ } -+ -+ var iv [aes.BlockSize]byte -+ ctr := cipher.NewCTR(aesCipher, iv[:]) -+ ctr.XORKeyStream(c.gxBytes, c.gxBytes) -+ -+ return c.serializeDHCommit() -+} -+ -+func (c *Conversation) serializeDHCommit() []byte { -+ var ret []byte -+ ret = appendU16(ret, 2) // protocol version -+ ret = append(ret, msgTypeDHCommit) -+ ret = appendData(ret, c.gxBytes) -+ ret = appendData(ret, c.digest[:]) -+ return ret -+} -+ -+func (c *Conversation) processDHCommit(in []byte) error { -+ var ok1, ok2 bool -+ c.gxBytes, in, ok1 = getData(in) -+ digest, in, ok2 := getData(in) -+ if !ok1 || !ok2 || len(in) > 0 { -+ return errors.New("otr: corrupt DH commit message") -+ } -+ copy(c.digest[:], digest) -+ return nil -+} -+ -+func (c *Conversation) compareToDHCommit(in []byte) (int, error) { -+ _, in, ok1 := getData(in) -+ digest, in, ok2 := getData(in) -+ if !ok1 || !ok2 || len(in) > 0 { -+ return 0, errors.New("otr: corrupt DH commit message") -+ } -+ return bytes.Compare(c.digest[:], digest), nil -+} -+ -+func (c *Conversation) generateDHKey() []byte { -+ var yBytes [dhPrivateBytes]byte -+ c.y = c.randMPI(yBytes[:]) -+ c.gy = new(big.Int).Exp(g, c.y, p) -+ return c.serializeDHKey() -+} -+ -+func (c *Conversation) serializeDHKey() []byte { -+ var ret []byte -+ ret = appendU16(ret, 2) // protocol version -+ ret = append(ret, msgTypeDHKey) -+ ret = appendMPI(ret, c.gy) -+ return ret -+} -+ -+func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) { -+ gy, _, ok := getMPI(in) -+ if !ok { -+ err = errors.New("otr: corrupt DH key message") -+ return -+ } -+ if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 { -+ err = errors.New("otr: DH value out of range") -+ return -+ } -+ if c.gy != nil { -+ isSame = c.gy.Cmp(gy) == 0 -+ return -+ } -+ c.gy = gy -+ return -+} -+ -+func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) { -+ var xb []byte -+ xb = c.PrivateKey.PublicKey.Serialize(xb) -+ -+ var verifyData []byte -+ if xFirst { -+ verifyData = appendMPI(verifyData, c.gx) -+ verifyData = appendMPI(verifyData, c.gy) -+ } else { -+ verifyData = appendMPI(verifyData, c.gy) -+ verifyData = appendMPI(verifyData, c.gx) -+ } -+ verifyData = append(verifyData, xb...) -+ verifyData = appendU32(verifyData, c.myKeyId) -+ -+ mac := hmac.New(sha256.New, keys.m1[:]) -+ mac.Write(verifyData) -+ mb := mac.Sum(nil) -+ -+ xb = appendU32(xb, c.myKeyId) -+ xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...) -+ -+ aesCipher, err := aes.NewCipher(keys.c[:]) -+ if err != nil { -+ panic(err.Error()) -+ } -+ var iv [aes.BlockSize]byte -+ ctr := cipher.NewCTR(aesCipher, iv[:]) -+ ctr.XORKeyStream(xb, xb) -+ -+ mac = hmac.New(sha256.New, keys.m2[:]) -+ encryptedSig := appendData(nil, xb) -+ mac.Write(encryptedSig) -+ -+ return encryptedSig, mac.Sum(nil) -+} -+ -+func (c *Conversation) generateRevealSig() []byte { -+ s := new(big.Int).Exp(c.gy, c.x, p) -+ c.calcAKEKeys(s) -+ c.myKeyId++ -+ -+ encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */) -+ -+ c.myCurrentDHPub = c.gx -+ c.myCurrentDHPriv = c.x -+ c.rotateDHKeys() -+ incCounter(&c.myCounter) -+ -+ var ret []byte -+ ret = appendU16(ret, 2) -+ ret = append(ret, msgTypeRevealSig) -+ ret = appendData(ret, c.r[:]) -+ ret = append(ret, encryptedSig...) -+ ret = append(ret, mac[:20]...) -+ return ret -+} -+ -+func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error { -+ mac := hmac.New(sha256.New, keys.m2[:]) -+ mac.Write(appendData(nil, encryptedSig)) -+ myMAC := mac.Sum(nil)[:20] -+ -+ if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { -+ return errors.New("bad signature MAC in encrypted signature") -+ } -+ -+ aesCipher, err := aes.NewCipher(keys.c[:]) -+ if err != nil { -+ panic(err.Error()) -+ } -+ var iv [aes.BlockSize]byte -+ ctr := cipher.NewCTR(aesCipher, iv[:]) -+ ctr.XORKeyStream(encryptedSig, encryptedSig) -+ -+ sig := encryptedSig -+ sig, ok1 := c.TheirPublicKey.Parse(sig) -+ keyId, sig, ok2 := getU32(sig) -+ if !ok1 || !ok2 { -+ return errors.New("otr: corrupt encrypted signature") -+ } -+ -+ var verifyData []byte -+ if xFirst { -+ verifyData = appendMPI(verifyData, c.gx) -+ verifyData = appendMPI(verifyData, c.gy) -+ } else { -+ verifyData = appendMPI(verifyData, c.gy) -+ verifyData = appendMPI(verifyData, c.gx) -+ } -+ verifyData = c.TheirPublicKey.Serialize(verifyData) -+ verifyData = appendU32(verifyData, keyId) -+ -+ mac = hmac.New(sha256.New, keys.m1[:]) -+ mac.Write(verifyData) -+ mb := mac.Sum(nil) -+ -+ sig, ok1 = c.TheirPublicKey.Verify(mb, sig) -+ if !ok1 { -+ return errors.New("bad signature in encrypted signature") -+ } -+ if len(sig) > 0 { -+ return errors.New("corrupt encrypted signature") -+ } -+ -+ c.theirKeyId = keyId -+ zero(c.theirLastCtr[:]) -+ return nil -+} -+ -+func (c *Conversation) processRevealSig(in []byte) error { -+ r, in, ok1 := getData(in) -+ encryptedSig, in, ok2 := getData(in) -+ theirMAC := in -+ if !ok1 || !ok2 || len(theirMAC) != 20 { -+ return errors.New("otr: corrupt reveal signature message") -+ } -+ -+ aesCipher, err := aes.NewCipher(r) -+ if err != nil { -+ return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error()) -+ } -+ var iv [aes.BlockSize]byte -+ ctr := cipher.NewCTR(aesCipher, iv[:]) -+ ctr.XORKeyStream(c.gxBytes, c.gxBytes) -+ h := sha256.New() -+ h.Write(c.gxBytes) -+ digest := h.Sum(nil) -+ if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 { -+ return errors.New("otr: bad commit MAC in reveal signature message") -+ } -+ var rest []byte -+ c.gx, rest, ok1 = getMPI(c.gxBytes) -+ if !ok1 || len(rest) > 0 { -+ return errors.New("otr: gx corrupt after decryption") -+ } -+ if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 { -+ return errors.New("otr: DH value out of range") -+ } -+ s := new(big.Int).Exp(c.gx, c.y, p) -+ c.calcAKEKeys(s) -+ -+ if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil { -+ return errors.New("otr: in reveal signature message: " + err.Error()) -+ } -+ -+ c.theirCurrentDHPub = c.gx -+ c.theirLastDHPub = nil -+ -+ return nil -+} -+ -+func (c *Conversation) generateSig() []byte { -+ c.myKeyId++ -+ -+ encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */) -+ -+ c.myCurrentDHPub = c.gy -+ c.myCurrentDHPriv = c.y -+ c.rotateDHKeys() -+ incCounter(&c.myCounter) -+ -+ var ret []byte -+ ret = appendU16(ret, 2) -+ ret = append(ret, msgTypeSig) -+ ret = append(ret, encryptedSig...) -+ ret = append(ret, mac[:macPrefixBytes]...) -+ return ret -+} -+ -+func (c *Conversation) processSig(in []byte) error { -+ encryptedSig, in, ok1 := getData(in) -+ theirMAC := in -+ if !ok1 || len(theirMAC) != macPrefixBytes { -+ return errors.New("otr: corrupt signature message") -+ } -+ -+ if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil { -+ return errors.New("otr: in signature message: " + err.Error()) -+ } -+ -+ c.theirCurrentDHPub = c.gy -+ c.theirLastDHPub = nil -+ -+ return nil -+} -+ -+func (c *Conversation) rotateDHKeys() { -+ // evict slots using our retired key id -+ for i := range c.keySlots { -+ slot := &c.keySlots[i] -+ if slot.used && slot.myKeyId == c.myKeyId-1 { -+ slot.used = false -+ c.oldMACs = append(c.oldMACs, slot.recvMACKey...) -+ } -+ } -+ -+ c.myLastDHPriv = c.myCurrentDHPriv -+ c.myLastDHPub = c.myCurrentDHPub -+ -+ var xBytes [dhPrivateBytes]byte -+ c.myCurrentDHPriv = c.randMPI(xBytes[:]) -+ c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p) -+ c.myKeyId++ -+} -+ -+func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) { -+ origIn := in -+ flags, in, ok1 := getU8(in) -+ theirKeyId, in, ok2 := getU32(in) -+ myKeyId, in, ok3 := getU32(in) -+ y, in, ok4 := getMPI(in) -+ counter, in, ok5 := getNBytes(in, 8) -+ encrypted, in, ok6 := getData(in) -+ macedData := origIn[:len(origIn)-len(in)] -+ theirMAC, in, ok7 := getNBytes(in, macPrefixBytes) -+ _, in, ok8 := getData(in) -+ if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 { -+ err = errors.New("otr: corrupt data message") -+ return -+ } -+ -+ ignoreErrors := flags&1 != 0 -+ -+ slot, err := c.calcDataKeys(myKeyId, theirKeyId) -+ if err != nil { -+ if ignoreErrors { -+ err = nil -+ } -+ return -+ } -+ -+ mac := hmac.New(sha1.New, slot.recvMACKey) -+ mac.Write([]byte{0, 2, 3}) -+ mac.Write(macedData) -+ myMAC := mac.Sum(nil) -+ if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { -+ if !ignoreErrors { -+ err = errors.New("otr: bad MAC on data message") -+ } -+ return -+ } -+ -+ if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 { -+ err = errors.New("otr: counter regressed") -+ return -+ } -+ copy(slot.theirLastCtr[:], counter) -+ -+ var iv [aes.BlockSize]byte -+ copy(iv[:], counter) -+ aesCipher, err := aes.NewCipher(slot.recvAESKey) -+ if err != nil { -+ panic(err.Error()) -+ } -+ ctr := cipher.NewCTR(aesCipher, iv[:]) -+ ctr.XORKeyStream(encrypted, encrypted) -+ decrypted := encrypted -+ -+ if myKeyId == c.myKeyId { -+ c.rotateDHKeys() -+ } -+ if theirKeyId == c.theirKeyId { -+ // evict slots using their retired key id -+ for i := range c.keySlots { -+ slot := &c.keySlots[i] -+ if slot.used && slot.theirKeyId == theirKeyId-1 { -+ slot.used = false -+ c.oldMACs = append(c.oldMACs, slot.recvMACKey...) -+ } -+ } -+ -+ c.theirLastDHPub = c.theirCurrentDHPub -+ c.theirKeyId++ -+ c.theirCurrentDHPub = y -+ } -+ -+ if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 { -+ out = decrypted[:nulPos] -+ tlvData := decrypted[nulPos+1:] -+ for len(tlvData) > 0 { -+ var t tlv -+ var ok1, ok2, ok3 bool -+ -+ t.typ, tlvData, ok1 = getU16(tlvData) -+ t.length, tlvData, ok2 = getU16(tlvData) -+ t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length)) -+ if !ok1 || !ok2 || !ok3 { -+ err = errors.New("otr: corrupt tlv data") -+ return -+ } -+ tlvs = append(tlvs, t) -+ } -+ } else { -+ out = decrypted -+ } -+ -+ return -+} -+ -+func (c *Conversation) generateData(msg []byte, extra *tlv) []byte { -+ slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId) -+ if err != nil { -+ panic("otr: failed to generate sending keys: " + err.Error()) -+ } -+ -+ var plaintext []byte -+ plaintext = append(plaintext, msg...) -+ plaintext = append(plaintext, 0) -+ -+ padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity) -+ plaintext = appendU16(plaintext, tlvTypePadding) -+ plaintext = appendU16(plaintext, uint16(padding)) -+ for i := 0; i < padding; i++ { -+ plaintext = append(plaintext, 0) -+ } -+ -+ if extra != nil { -+ plaintext = appendU16(plaintext, extra.typ) -+ plaintext = appendU16(plaintext, uint16(len(extra.data))) -+ plaintext = append(plaintext, extra.data...) -+ } -+ -+ encrypted := make([]byte, len(plaintext)) -+ -+ var iv [aes.BlockSize]byte -+ copy(iv[:], c.myCounter[:]) -+ aesCipher, err := aes.NewCipher(slot.sendAESKey) -+ if err != nil { -+ panic(err.Error()) -+ } -+ ctr := cipher.NewCTR(aesCipher, iv[:]) -+ ctr.XORKeyStream(encrypted, plaintext) -+ -+ var ret []byte -+ ret = appendU16(ret, 2) -+ ret = append(ret, msgTypeData) -+ ret = append(ret, 0 /* flags */) -+ ret = appendU32(ret, c.myKeyId-1) -+ ret = appendU32(ret, c.theirKeyId) -+ ret = appendMPI(ret, c.myCurrentDHPub) -+ ret = append(ret, c.myCounter[:]...) -+ ret = appendData(ret, encrypted) -+ -+ mac := hmac.New(sha1.New, slot.sendMACKey) -+ mac.Write(ret) -+ ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...) -+ ret = appendData(ret, c.oldMACs) -+ c.oldMACs = nil -+ incCounter(&c.myCounter) -+ -+ return ret -+} -+ -+func incCounter(counter *[8]byte) { -+ for i := 7; i >= 0; i-- { -+ counter[i]++ -+ if counter[i] > 0 { -+ break -+ } -+ } -+} -+ -+// calcDataKeys computes the keys used to encrypt a data message given the key -+// IDs. -+func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) { -+ // Check for a cache hit. -+ for i := range c.keySlots { -+ slot = &c.keySlots[i] -+ if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId { -+ return -+ } -+ } -+ -+ // Find an empty slot to write into. -+ slot = nil -+ for i := range c.keySlots { -+ if !c.keySlots[i].used { -+ slot = &c.keySlots[i] -+ break -+ } -+ } -+ if slot == nil { -+ return nil, errors.New("otr: internal error: no more key slots") -+ } -+ -+ var myPriv, myPub, theirPub *big.Int -+ -+ if myKeyId == c.myKeyId { -+ myPriv = c.myCurrentDHPriv -+ myPub = c.myCurrentDHPub -+ } else if myKeyId == c.myKeyId-1 { -+ myPriv = c.myLastDHPriv -+ myPub = c.myLastDHPub -+ } else { -+ err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10)) -+ return -+ } -+ -+ if theirKeyId == c.theirKeyId { -+ theirPub = c.theirCurrentDHPub -+ } else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil { -+ theirPub = c.theirLastDHPub -+ } else { -+ err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10)) -+ return -+ } -+ -+ var sendPrefixByte, recvPrefixByte [1]byte -+ -+ if myPub.Cmp(theirPub) > 0 { -+ // we're the high end -+ sendPrefixByte[0], recvPrefixByte[0] = 1, 2 -+ } else { -+ // we're the low end -+ sendPrefixByte[0], recvPrefixByte[0] = 2, 1 -+ } -+ -+ s := new(big.Int).Exp(theirPub, myPriv, p) -+ sBytes := appendMPI(nil, s) -+ -+ h := sha1.New() -+ h.Write(sendPrefixByte[:]) -+ h.Write(sBytes) -+ slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16] -+ -+ h.Reset() -+ h.Write(slot.sendAESKey) -+ slot.sendMACKey = h.Sum(slot.sendMACKey[:0]) -+ -+ h.Reset() -+ h.Write(recvPrefixByte[:]) -+ h.Write(sBytes) -+ slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16] -+ -+ h.Reset() -+ h.Write(slot.recvAESKey) -+ slot.recvMACKey = h.Sum(slot.recvMACKey[:0]) -+ -+ slot.theirKeyId = theirKeyId -+ slot.myKeyId = myKeyId -+ slot.used = true -+ -+ zero(slot.theirLastCtr[:]) -+ return -+} -+ -+func (c *Conversation) calcAKEKeys(s *big.Int) { -+ mpi := appendMPI(nil, s) -+ h := sha256.New() -+ -+ var cBytes [32]byte -+ hashWithPrefix(c.SSID[:], 0, mpi, h) -+ -+ hashWithPrefix(cBytes[:], 1, mpi, h) -+ copy(c.revealKeys.c[:], cBytes[:16]) -+ copy(c.sigKeys.c[:], cBytes[16:]) -+ -+ hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h) -+ hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h) -+ hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h) -+ hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h) -+} -+ -+func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) { -+ h.Reset() -+ var p [1]byte -+ p[0] = prefix -+ h.Write(p[:]) -+ h.Write(in) -+ if len(out) == h.Size() { -+ h.Sum(out[:0]) -+ } else { -+ digest := h.Sum(nil) -+ copy(out, digest) -+ } -+} -+ -+func (c *Conversation) encode(msg []byte) [][]byte { -+ b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1) -+ base64.StdEncoding.Encode(b64[len(msgPrefix):], msg) -+ copy(b64, msgPrefix) -+ b64[len(b64)-1] = '.' -+ -+ if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize { -+ // We can encode this in a single fragment. -+ return [][]byte{b64} -+ } -+ -+ // We have to fragment this message. -+ var ret [][]byte -+ bytesPerFragment := c.FragmentSize - minFragmentSize -+ numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment -+ -+ for i := 0; i < numFragments; i++ { -+ frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",") -+ todo := bytesPerFragment -+ if todo > len(b64) { -+ todo = len(b64) -+ } -+ frag = append(frag, b64[:todo]...) -+ b64 = b64[todo:] -+ frag = append(frag, ',') -+ ret = append(ret, frag) -+ } -+ -+ return ret -+} -+ -+func (c *Conversation) reset() { -+ c.myKeyId = 0 -+ -+ for i := range c.keySlots { -+ c.keySlots[i].used = false -+ } -+} -+ -+type PublicKey struct { -+ dsa.PublicKey -+} -+ -+func (pk *PublicKey) Parse(in []byte) ([]byte, bool) { -+ var ok bool -+ var pubKeyType uint16 -+ -+ if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 { -+ return nil, false -+ } -+ if pk.P, in, ok = getMPI(in); !ok { -+ return nil, false -+ } -+ if pk.Q, in, ok = getMPI(in); !ok { -+ return nil, false -+ } -+ if pk.G, in, ok = getMPI(in); !ok { -+ return nil, false -+ } -+ if pk.Y, in, ok = getMPI(in); !ok { -+ return nil, false -+ } -+ -+ return in, true -+} -+ -+func (pk *PublicKey) Serialize(in []byte) []byte { -+ in = appendU16(in, 0) -+ in = appendMPI(in, pk.P) -+ in = appendMPI(in, pk.Q) -+ in = appendMPI(in, pk.G) -+ in = appendMPI(in, pk.Y) -+ return in -+} -+ -+// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey. -+func (pk *PublicKey) Fingerprint() []byte { -+ b := pk.Serialize(nil) -+ h := sha1.New() -+ h.Write(b[2:]) -+ return h.Sum(nil) -+} -+ -+func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) { -+ if len(sig) != 2*dsaSubgroupBytes { -+ return nil, false -+ } -+ r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes]) -+ s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:]) -+ ok := dsa.Verify(&pk.PublicKey, hashed, r, s) -+ return sig[dsaSubgroupBytes*2:], ok -+} -+ -+type PrivateKey struct { -+ PublicKey -+ dsa.PrivateKey -+} -+ -+func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte { -+ r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed) -+ if err != nil { -+ panic(err.Error()) -+ } -+ rBytes := r.Bytes() -+ sBytes := s.Bytes() -+ if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes { -+ panic("DSA signature too large") -+ } -+ -+ out := make([]byte, 2*dsaSubgroupBytes) -+ copy(out[dsaSubgroupBytes-len(rBytes):], rBytes) -+ copy(out[len(out)-len(sBytes):], sBytes) -+ return out -+} -+ -+func (priv *PrivateKey) Serialize(in []byte) []byte { -+ in = priv.PublicKey.Serialize(in) -+ in = appendMPI(in, priv.PrivateKey.X) -+ return in -+} -+ -+func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) { -+ in, ok := priv.PublicKey.Parse(in) -+ if !ok { -+ return in, ok -+ } -+ priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey -+ priv.PrivateKey.X, in, ok = getMPI(in) -+ return in, ok -+} -+ -+func (priv *PrivateKey) Generate(rand io.Reader) { -+ if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil { -+ panic(err.Error()) -+ } -+ if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil { -+ panic(err.Error()) -+ } -+ priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey -+} -+ -+func notHex(r rune) bool { -+ if r >= '0' && r <= '9' || -+ r >= 'a' && r <= 'f' || -+ r >= 'A' && r <= 'F' { -+ return false -+ } -+ -+ return true -+} -+ -+// Import parses the contents of a libotr private key file. -+func (priv *PrivateKey) Import(in []byte) bool { -+ mpiStart := []byte(" #") -+ -+ mpis := make([]*big.Int, 5) -+ -+ for i := 0; i < len(mpis); i++ { -+ start := bytes.Index(in, mpiStart) -+ if start == -1 { -+ return false -+ } -+ in = in[start+len(mpiStart):] -+ end := bytes.IndexFunc(in, notHex) -+ if end == -1 { -+ return false -+ } -+ hexBytes := in[:end] -+ in = in[end:] -+ -+ if len(hexBytes)&1 != 0 { -+ return false -+ } -+ -+ mpiBytes := make([]byte, len(hexBytes)/2) -+ if _, err := hex.Decode(mpiBytes, hexBytes); err != nil { -+ return false -+ } -+ -+ mpis[i] = new(big.Int).SetBytes(mpiBytes) -+ } -+ -+ for _, mpi := range mpis { -+ if mpi.Sign() <= 0 { -+ return false -+ } -+ } -+ -+ priv.PrivateKey.P = mpis[0] -+ priv.PrivateKey.Q = mpis[1] -+ priv.PrivateKey.G = mpis[2] -+ priv.PrivateKey.Y = mpis[3] -+ priv.PrivateKey.X = mpis[4] -+ priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey -+ -+ a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P) -+ return a.Cmp(priv.PrivateKey.Y) == 0 -+} -+ -+func getU8(in []byte) (uint8, []byte, bool) { -+ if len(in) < 1 { -+ return 0, in, false -+ } -+ return in[0], in[1:], true -+} -+ -+func getU16(in []byte) (uint16, []byte, bool) { -+ if len(in) < 2 { -+ return 0, in, false -+ } -+ r := uint16(in[0])<<8 | uint16(in[1]) -+ return r, in[2:], true -+} -+ -+func getU32(in []byte) (uint32, []byte, bool) { -+ if len(in) < 4 { -+ return 0, in, false -+ } -+ r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3]) -+ return r, in[4:], true -+} -+ -+func getMPI(in []byte) (*big.Int, []byte, bool) { -+ l, in, ok := getU32(in) -+ if !ok || uint32(len(in)) < l { -+ return nil, in, false -+ } -+ r := new(big.Int).SetBytes(in[:l]) -+ return r, in[l:], true -+} -+ -+func getData(in []byte) ([]byte, []byte, bool) { -+ l, in, ok := getU32(in) -+ if !ok || uint32(len(in)) < l { -+ return nil, in, false -+ } -+ return in[:l], in[l:], true -+} -+ -+func getNBytes(in []byte, n int) ([]byte, []byte, bool) { -+ if len(in) < n { -+ return nil, in, false -+ } -+ return in[:n], in[n:], true -+} -+ -+func appendU16(out []byte, v uint16) []byte { -+ out = append(out, byte(v>>8), byte(v)) -+ return out -+} -+ -+func appendU32(out []byte, v uint32) []byte { -+ out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) -+ return out -+} -+ -+func appendData(out, v []byte) []byte { -+ out = appendU32(out, uint32(len(v))) -+ out = append(out, v...) -+ return out -+} -+ -+func appendMPI(out []byte, v *big.Int) []byte { -+ vBytes := v.Bytes() -+ out = appendU32(out, uint32(len(vBytes))) -+ out = append(out, vBytes...) -+ return out -+} -+ -+func appendMPIs(out []byte, mpis ...*big.Int) []byte { -+ for _, mpi := range mpis { -+ out = appendMPI(out, mpi) -+ } -+ return out -+} -+ -+func zero(b []byte) { -+ for i := range b { -+ b[i] = 0 -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/otr/otr_test.go b/ms_mod/golang.org/x/crypto/otr/otr_test.go -new file mode 100644 -index 00000000000000..cfcd062b274507 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/otr/otr_test.go -@@ -0,0 +1,470 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package otr -+ -+import ( -+ "bufio" -+ "bytes" -+ "crypto/rand" -+ "encoding/hex" -+ "math/big" -+ "os" -+ "os/exec" -+ "testing" -+) -+ -+var isQueryTests = []struct { -+ msg string -+ expectedVersion int -+}{ -+ {"foo", 0}, -+ {"?OtR", 0}, -+ {"?OtR?", 0}, -+ {"?OTR?", 0}, -+ {"?OTRv?", 0}, -+ {"?OTRv1?", 0}, -+ {"?OTR?v1?", 0}, -+ {"?OTR?v?", 0}, -+ {"?OTR?v2?", 2}, -+ {"?OTRv2?", 2}, -+ {"?OTRv23?", 2}, -+ {"?OTRv23 ?", 0}, -+} -+ -+func TestIsQuery(t *testing.T) { -+ for i, test := range isQueryTests { -+ version := isQuery([]byte(test.msg)) -+ if version != test.expectedVersion { -+ t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion) -+ } -+ } -+} -+ -+var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57" -+ -+var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f" -+ -+var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48" -+ -+func TestKeySerialization(t *testing.T) { -+ var priv PrivateKey -+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) -+ rest, ok := priv.Parse(alicePrivateKey) -+ if !ok { -+ t.Error("failed to parse private key") -+ } -+ if len(rest) > 0 { -+ t.Error("data remaining after parsing private key") -+ } -+ -+ out := priv.Serialize(nil) -+ if !bytes.Equal(alicePrivateKey, out) { -+ t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey) -+ } -+ -+ aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex) -+ fingerprint := priv.PublicKey.Fingerprint() -+ if !bytes.Equal(aliceFingerprint, fingerprint) { -+ t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint) -+ } -+} -+ -+const libOTRPrivateKey = `(privkeys -+ (account -+(name "foo@example.com") -+(protocol prpl-jabber) -+(private-key -+ (dsa -+ (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) -+ (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) -+ (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) -+ (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#) -+ (x #14D0345A3562C480A039E3C72764F72D79043216#) -+ ) -+ ) -+ ) -+)` -+ -+func TestParseLibOTRPrivateKey(t *testing.T) { -+ var priv PrivateKey -+ -+ if !priv.Import([]byte(libOTRPrivateKey)) { -+ t.Fatalf("Failed to import sample private key") -+ } -+} -+ -+func TestSignVerify(t *testing.T) { -+ var priv PrivateKey -+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) -+ _, ok := priv.Parse(alicePrivateKey) -+ if !ok { -+ t.Error("failed to parse private key") -+ } -+ -+ var msg [32]byte -+ rand.Reader.Read(msg[:]) -+ -+ sig := priv.Sign(rand.Reader, msg[:]) -+ rest, ok := priv.PublicKey.Verify(msg[:], sig) -+ if !ok { -+ t.Errorf("signature (%x) of %x failed to verify", sig, msg[:]) -+ } else if len(rest) > 0 { -+ t.Error("signature data remains after verification") -+ } -+ -+ sig[10] ^= 80 -+ _, ok = priv.PublicKey.Verify(msg[:], sig) -+ if ok { -+ t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:]) -+ } -+} -+ -+func setupConversation(t *testing.T) (alice, bob *Conversation) { -+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) -+ bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex) -+ -+ alice, bob = new(Conversation), new(Conversation) -+ -+ alice.PrivateKey = new(PrivateKey) -+ bob.PrivateKey = new(PrivateKey) -+ alice.PrivateKey.Parse(alicePrivateKey) -+ bob.PrivateKey.Parse(bobPrivateKey) -+ alice.FragmentSize = 100 -+ bob.FragmentSize = 100 -+ -+ if alice.IsEncrypted() { -+ t.Error("Alice believes that the conversation is secure before we've started") -+ } -+ if bob.IsEncrypted() { -+ t.Error("Bob believes that the conversation is secure before we've started") -+ } -+ -+ performHandshake(t, alice, bob) -+ return alice, bob -+} -+ -+func performHandshake(t *testing.T, alice, bob *Conversation) { -+ var alicesMessage, bobsMessage [][]byte -+ var out []byte -+ var aliceChange, bobChange SecurityChange -+ var err error -+ alicesMessage = append(alicesMessage, []byte(QueryMessage)) -+ -+ for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ { -+ bobsMessage = nil -+ for i, msg := range alicesMessage { -+ out, _, bobChange, bobsMessage, err = bob.Receive(msg) -+ if len(out) > 0 { -+ t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i) -+ } -+ if err != nil { -+ t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err) -+ } -+ if len(bobsMessage) > 0 && i != len(alicesMessage)-1 { -+ t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i) -+ } -+ } -+ -+ alicesMessage = nil -+ for i, msg := range bobsMessage { -+ out, _, aliceChange, alicesMessage, err = alice.Receive(msg) -+ if len(out) > 0 { -+ t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i) -+ } -+ if err != nil { -+ t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err) -+ } -+ if len(alicesMessage) > 0 && i != len(bobsMessage)-1 { -+ t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i) -+ } -+ } -+ } -+ -+ if aliceChange != NewKeys { -+ t.Errorf("Alice terminated without signaling new keys") -+ } -+ if bobChange != NewKeys { -+ t.Errorf("Bob terminated without signaling new keys") -+ } -+ -+ if !bytes.Equal(alice.SSID[:], bob.SSID[:]) { -+ t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:]) -+ } -+ -+ if !alice.IsEncrypted() { -+ t.Error("Alice doesn't believe that the conversation is secure") -+ } -+ if !bob.IsEncrypted() { -+ t.Error("Bob doesn't believe that the conversation is secure") -+ } -+} -+ -+const ( -+ firstRoundTrip = iota -+ subsequentRoundTrip -+ noMACKeyCheck -+) -+ -+func roundTrip(t *testing.T, alice, bob *Conversation, message []byte, macKeyCheck int) { -+ alicesMessage, err := alice.Send(message) -+ if err != nil { -+ t.Errorf("Error from Alice sending message: %s", err) -+ } -+ -+ if len(alice.oldMACs) != 0 { -+ t.Errorf("Alice has not revealed all MAC keys") -+ } -+ -+ for i, msg := range alicesMessage { -+ out, encrypted, _, _, err := bob.Receive(msg) -+ -+ if err != nil { -+ t.Errorf("Error generated while processing test message: %s", err.Error()) -+ } -+ if len(out) > 0 { -+ if i != len(alicesMessage)-1 { -+ t.Fatal("Bob produced a message while processing a fragment of Alice's") -+ } -+ if !encrypted { -+ t.Errorf("Message was not marked as encrypted") -+ } -+ if !bytes.Equal(out, message) { -+ t.Errorf("Message corrupted: got %x, want %x", out, message) -+ } -+ } -+ } -+ -+ switch macKeyCheck { -+ case firstRoundTrip: -+ if len(bob.oldMACs) != 0 { -+ t.Errorf("Bob should not have MAC keys to reveal") -+ } -+ case subsequentRoundTrip: -+ if len(bob.oldMACs) != 40 { -+ t.Errorf("Bob has %d bytes of MAC keys to reveal, but should have 40", len(bob.oldMACs)) -+ } -+ } -+ -+ bobsMessage, err := bob.Send(message) -+ if err != nil { -+ t.Errorf("Error from Bob sending message: %s", err) -+ } -+ -+ if len(bob.oldMACs) != 0 { -+ t.Errorf("Bob has not revealed all MAC keys") -+ } -+ -+ for i, msg := range bobsMessage { -+ out, encrypted, _, _, err := alice.Receive(msg) -+ -+ if err != nil { -+ t.Errorf("Error generated while processing test message: %s", err.Error()) -+ } -+ if len(out) > 0 { -+ if i != len(bobsMessage)-1 { -+ t.Fatal("Alice produced a message while processing a fragment of Bob's") -+ } -+ if !encrypted { -+ t.Errorf("Message was not marked as encrypted") -+ } -+ if !bytes.Equal(out, message) { -+ t.Errorf("Message corrupted: got %x, want %x", out, message) -+ } -+ } -+ } -+ -+ switch macKeyCheck { -+ case firstRoundTrip: -+ if len(alice.oldMACs) != 20 { -+ t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 20", len(alice.oldMACs)) -+ } -+ case subsequentRoundTrip: -+ if len(alice.oldMACs) != 40 { -+ t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 40", len(alice.oldMACs)) -+ } -+ } -+} -+ -+func TestConversation(t *testing.T) { -+ alice, bob := setupConversation(t) -+ -+ var testMessages = [][]byte{ -+ []byte("hello"), []byte("bye"), -+ } -+ -+ roundTripType := firstRoundTrip -+ -+ for _, testMessage := range testMessages { -+ roundTrip(t, alice, bob, testMessage, roundTripType) -+ roundTripType = subsequentRoundTrip -+ } -+} -+ -+func TestGoodSMP(t *testing.T) { -+ var alice, bob Conversation -+ -+ alice.smp.secret = new(big.Int).SetInt64(42) -+ bob.smp.secret = alice.smp.secret -+ -+ var alicesMessages, bobsMessages []tlv -+ var aliceComplete, bobComplete bool -+ var err error -+ var out tlv -+ -+ alicesMessages = alice.startSMP("") -+ for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { -+ bobsMessages = bobsMessages[:0] -+ for i, msg := range alicesMessages { -+ out, bobComplete, err = bob.processSMP(msg) -+ if err != nil { -+ t.Errorf("Error from Bob in round %d: %s", round, err) -+ } -+ if bobComplete && i != len(alicesMessages)-1 { -+ t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round) -+ } -+ if out.typ != 0 { -+ bobsMessages = append(bobsMessages, out) -+ } -+ } -+ -+ alicesMessages = alicesMessages[:0] -+ for i, msg := range bobsMessages { -+ out, aliceComplete, err = alice.processSMP(msg) -+ if err != nil { -+ t.Errorf("Error from Alice in round %d: %s", round, err) -+ } -+ if aliceComplete && i != len(bobsMessages)-1 { -+ t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round) -+ } -+ if out.typ != 0 { -+ alicesMessages = append(alicesMessages, out) -+ } -+ } -+ } -+ -+ if !aliceComplete || !bobComplete { -+ t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete) -+ } -+} -+ -+func TestBadSMP(t *testing.T) { -+ var alice, bob Conversation -+ -+ alice.smp.secret = new(big.Int).SetInt64(42) -+ bob.smp.secret = new(big.Int).SetInt64(43) -+ -+ var alicesMessages, bobsMessages []tlv -+ -+ alicesMessages = alice.startSMP("") -+ for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { -+ bobsMessages = bobsMessages[:0] -+ for _, msg := range alicesMessages { -+ out, complete, _ := bob.processSMP(msg) -+ if complete { -+ t.Errorf("Bob signaled completion in round %d", round) -+ } -+ if out.typ != 0 { -+ bobsMessages = append(bobsMessages, out) -+ } -+ } -+ -+ alicesMessages = alicesMessages[:0] -+ for _, msg := range bobsMessages { -+ out, complete, _ := alice.processSMP(msg) -+ if complete { -+ t.Errorf("Alice signaled completion in round %d", round) -+ } -+ if out.typ != 0 { -+ alicesMessages = append(alicesMessages, out) -+ } -+ } -+ } -+} -+ -+func TestRehandshaking(t *testing.T) { -+ alice, bob := setupConversation(t) -+ roundTrip(t, alice, bob, []byte("test"), firstRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 2"), subsequentRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 3"), subsequentRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 4"), subsequentRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 5"), subsequentRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 6"), subsequentRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 7"), subsequentRoundTrip) -+ roundTrip(t, alice, bob, []byte("test 8"), subsequentRoundTrip) -+ performHandshake(t, alice, bob) -+ roundTrip(t, alice, bob, []byte("test"), noMACKeyCheck) -+ roundTrip(t, alice, bob, []byte("test 2"), noMACKeyCheck) -+} -+ -+func TestAgainstLibOTR(t *testing.T) { -+ // This test requires otr.c.test to be built as /tmp/a.out. -+ // If enabled, this tests runs forever performing OTR handshakes in a -+ // loop. -+ return -+ -+ alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) -+ var alice Conversation -+ alice.PrivateKey = new(PrivateKey) -+ alice.PrivateKey.Parse(alicePrivateKey) -+ -+ cmd := exec.Command("/tmp/a.out") -+ cmd.Stderr = os.Stderr -+ -+ out, err := cmd.StdinPipe() -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer out.Close() -+ stdout, err := cmd.StdoutPipe() -+ if err != nil { -+ t.Fatal(err) -+ } -+ in := bufio.NewReader(stdout) -+ -+ if err := cmd.Start(); err != nil { -+ t.Fatal(err) -+ } -+ -+ out.Write([]byte(QueryMessage)) -+ out.Write([]byte("\n")) -+ var expectedText = []byte("test message") -+ -+ for { -+ line, isPrefix, err := in.ReadLine() -+ if isPrefix { -+ t.Fatal("line from subprocess too long") -+ } -+ if err != nil { -+ t.Fatal(err) -+ } -+ text, encrypted, change, alicesMessage, err := alice.Receive(line) -+ if err != nil { -+ t.Fatal(err) -+ } -+ for _, msg := range alicesMessage { -+ out.Write(msg) -+ out.Write([]byte("\n")) -+ } -+ if change == NewKeys { -+ alicesMessage, err := alice.Send([]byte("Go -> libotr test message")) -+ if err != nil { -+ t.Fatalf("error sending message: %s", err.Error()) -+ } else { -+ for _, msg := range alicesMessage { -+ out.Write(msg) -+ out.Write([]byte("\n")) -+ } -+ } -+ } -+ if len(text) > 0 { -+ if !bytes.Equal(text, expectedText) { -+ t.Fatalf("expected %x, but got %x", expectedText, text) -+ } -+ if !encrypted { -+ t.Fatal("message wasn't encrypted") -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/otr/smp.go b/ms_mod/golang.org/x/crypto/otr/smp.go -new file mode 100644 -index 00000000000000..dc6de4ee0eb74d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/otr/smp.go -@@ -0,0 +1,572 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This file implements the Socialist Millionaires Protocol as described in -+// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol -+// specification is required in order to understand this code and, where -+// possible, the variable names in the code match up with the spec. -+ -+package otr -+ -+import ( -+ "bytes" -+ "crypto/sha256" -+ "errors" -+ "hash" -+ "math/big" -+) -+ -+type smpFailure string -+ -+func (s smpFailure) Error() string { -+ return string(s) -+} -+ -+var smpFailureError = smpFailure("otr: SMP protocol failed") -+var smpSecretMissingError = smpFailure("otr: mutual secret needed") -+ -+const smpVersion = 1 -+ -+const ( -+ smpState1 = iota -+ smpState2 -+ smpState3 -+ smpState4 -+) -+ -+type smpState struct { -+ state int -+ a2, a3, b2, b3, pb, qb *big.Int -+ g2a, g3a *big.Int -+ g2, g3 *big.Int -+ g3b, papb, qaqb, ra *big.Int -+ saved *tlv -+ secret *big.Int -+ question string -+} -+ -+func (c *Conversation) startSMP(question string) (tlvs []tlv) { -+ if c.smp.state != smpState1 { -+ tlvs = append(tlvs, c.generateSMPAbort()) -+ } -+ tlvs = append(tlvs, c.generateSMP1(question)) -+ c.smp.question = "" -+ c.smp.state = smpState2 -+ return -+} -+ -+func (c *Conversation) resetSMP() { -+ c.smp.state = smpState1 -+ c.smp.secret = nil -+ c.smp.question = "" -+} -+ -+func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) { -+ data := in.data -+ -+ switch in.typ { -+ case tlvTypeSMPAbort: -+ if c.smp.state != smpState1 { -+ err = smpFailureError -+ } -+ c.resetSMP() -+ return -+ case tlvTypeSMP1WithQuestion: -+ // We preprocess this into a SMP1 message. -+ nulPos := bytes.IndexByte(data, 0) -+ if nulPos == -1 { -+ err = errors.New("otr: SMP message with question didn't contain a NUL byte") -+ return -+ } -+ c.smp.question = string(data[:nulPos]) -+ data = data[nulPos+1:] -+ } -+ -+ numMPIs, data, ok := getU32(data) -+ if !ok || numMPIs > 20 { -+ err = errors.New("otr: corrupt SMP message") -+ return -+ } -+ -+ mpis := make([]*big.Int, numMPIs) -+ for i := range mpis { -+ var ok bool -+ mpis[i], data, ok = getMPI(data) -+ if !ok { -+ err = errors.New("otr: corrupt SMP message") -+ return -+ } -+ } -+ -+ switch in.typ { -+ case tlvTypeSMP1, tlvTypeSMP1WithQuestion: -+ if c.smp.state != smpState1 { -+ c.resetSMP() -+ out = c.generateSMPAbort() -+ return -+ } -+ if c.smp.secret == nil { -+ err = smpSecretMissingError -+ return -+ } -+ if err = c.processSMP1(mpis); err != nil { -+ return -+ } -+ c.smp.state = smpState3 -+ out = c.generateSMP2() -+ case tlvTypeSMP2: -+ if c.smp.state != smpState2 { -+ c.resetSMP() -+ out = c.generateSMPAbort() -+ return -+ } -+ if out, err = c.processSMP2(mpis); err != nil { -+ out = c.generateSMPAbort() -+ return -+ } -+ c.smp.state = smpState4 -+ case tlvTypeSMP3: -+ if c.smp.state != smpState3 { -+ c.resetSMP() -+ out = c.generateSMPAbort() -+ return -+ } -+ if out, err = c.processSMP3(mpis); err != nil { -+ return -+ } -+ c.smp.state = smpState1 -+ c.smp.secret = nil -+ complete = true -+ case tlvTypeSMP4: -+ if c.smp.state != smpState4 { -+ c.resetSMP() -+ out = c.generateSMPAbort() -+ return -+ } -+ if err = c.processSMP4(mpis); err != nil { -+ out = c.generateSMPAbort() -+ return -+ } -+ c.smp.state = smpState1 -+ c.smp.secret = nil -+ complete = true -+ default: -+ panic("unknown SMP message") -+ } -+ -+ return -+} -+ -+func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) { -+ h := sha256.New() -+ h.Write([]byte{smpVersion}) -+ if weStarted { -+ h.Write(c.PrivateKey.PublicKey.Fingerprint()) -+ h.Write(c.TheirPublicKey.Fingerprint()) -+ } else { -+ h.Write(c.TheirPublicKey.Fingerprint()) -+ h.Write(c.PrivateKey.PublicKey.Fingerprint()) -+ } -+ h.Write(c.SSID[:]) -+ h.Write(mutualSecret) -+ c.smp.secret = new(big.Int).SetBytes(h.Sum(nil)) -+} -+ -+func (c *Conversation) generateSMP1(question string) tlv { -+ var randBuf [16]byte -+ c.smp.a2 = c.randMPI(randBuf[:]) -+ c.smp.a3 = c.randMPI(randBuf[:]) -+ g2a := new(big.Int).Exp(g, c.smp.a2, p) -+ g3a := new(big.Int).Exp(g, c.smp.a3, p) -+ h := sha256.New() -+ -+ r2 := c.randMPI(randBuf[:]) -+ r := new(big.Int).Exp(g, r2, p) -+ c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r)) -+ d2 := new(big.Int).Mul(c.smp.a2, c2) -+ d2.Sub(r2, d2) -+ d2.Mod(d2, q) -+ if d2.Sign() < 0 { -+ d2.Add(d2, q) -+ } -+ -+ r3 := c.randMPI(randBuf[:]) -+ r.Exp(g, r3, p) -+ c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r)) -+ d3 := new(big.Int).Mul(c.smp.a3, c3) -+ d3.Sub(r3, d3) -+ d3.Mod(d3, q) -+ if d3.Sign() < 0 { -+ d3.Add(d3, q) -+ } -+ -+ var ret tlv -+ if len(question) > 0 { -+ ret.typ = tlvTypeSMP1WithQuestion -+ ret.data = append(ret.data, question...) -+ ret.data = append(ret.data, 0) -+ } else { -+ ret.typ = tlvTypeSMP1 -+ } -+ ret.data = appendU32(ret.data, 6) -+ ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3) -+ return ret -+} -+ -+func (c *Conversation) processSMP1(mpis []*big.Int) error { -+ if len(mpis) != 6 { -+ return errors.New("otr: incorrect number of arguments in SMP1 message") -+ } -+ g2a := mpis[0] -+ c2 := mpis[1] -+ d2 := mpis[2] -+ g3a := mpis[3] -+ c3 := mpis[4] -+ d3 := mpis[5] -+ h := sha256.New() -+ -+ r := new(big.Int).Exp(g, d2, p) -+ s := new(big.Int).Exp(g2a, c2, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ t := new(big.Int).SetBytes(hashMPIs(h, 1, r)) -+ if c2.Cmp(t) != 0 { -+ return errors.New("otr: ZKP c2 incorrect in SMP1 message") -+ } -+ r.Exp(g, d3, p) -+ s.Exp(g3a, c3, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ t.SetBytes(hashMPIs(h, 2, r)) -+ if c3.Cmp(t) != 0 { -+ return errors.New("otr: ZKP c3 incorrect in SMP1 message") -+ } -+ -+ c.smp.g2a = g2a -+ c.smp.g3a = g3a -+ return nil -+} -+ -+func (c *Conversation) generateSMP2() tlv { -+ var randBuf [16]byte -+ b2 := c.randMPI(randBuf[:]) -+ c.smp.b3 = c.randMPI(randBuf[:]) -+ r2 := c.randMPI(randBuf[:]) -+ r3 := c.randMPI(randBuf[:]) -+ r4 := c.randMPI(randBuf[:]) -+ r5 := c.randMPI(randBuf[:]) -+ r6 := c.randMPI(randBuf[:]) -+ -+ g2b := new(big.Int).Exp(g, b2, p) -+ g3b := new(big.Int).Exp(g, c.smp.b3, p) -+ -+ r := new(big.Int).Exp(g, r2, p) -+ h := sha256.New() -+ c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r)) -+ d2 := new(big.Int).Mul(b2, c2) -+ d2.Sub(r2, d2) -+ d2.Mod(d2, q) -+ if d2.Sign() < 0 { -+ d2.Add(d2, q) -+ } -+ -+ r.Exp(g, r3, p) -+ c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r)) -+ d3 := new(big.Int).Mul(c.smp.b3, c3) -+ d3.Sub(r3, d3) -+ d3.Mod(d3, q) -+ if d3.Sign() < 0 { -+ d3.Add(d3, q) -+ } -+ -+ c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p) -+ c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p) -+ c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p) -+ c.smp.qb = new(big.Int).Exp(g, r4, p) -+ r.Exp(c.smp.g2, c.smp.secret, p) -+ c.smp.qb.Mul(c.smp.qb, r) -+ c.smp.qb.Mod(c.smp.qb, p) -+ -+ s := new(big.Int) -+ s.Exp(c.smp.g2, r6, p) -+ r.Exp(g, r5, p) -+ s.Mul(r, s) -+ s.Mod(s, p) -+ r.Exp(c.smp.g3, r5, p) -+ cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s)) -+ -+ // D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q -+ -+ s.Mul(r4, cp) -+ r.Sub(r5, s) -+ d5 := new(big.Int).Mod(r, q) -+ if d5.Sign() < 0 { -+ d5.Add(d5, q) -+ } -+ -+ s.Mul(c.smp.secret, cp) -+ r.Sub(r6, s) -+ d6 := new(big.Int).Mod(r, q) -+ if d6.Sign() < 0 { -+ d6.Add(d6, q) -+ } -+ -+ var ret tlv -+ ret.typ = tlvTypeSMP2 -+ ret.data = appendU32(ret.data, 11) -+ ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6) -+ return ret -+} -+ -+func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) { -+ if len(mpis) != 11 { -+ err = errors.New("otr: incorrect number of arguments in SMP2 message") -+ return -+ } -+ g2b := mpis[0] -+ c2 := mpis[1] -+ d2 := mpis[2] -+ g3b := mpis[3] -+ c3 := mpis[4] -+ d3 := mpis[5] -+ pb := mpis[6] -+ qb := mpis[7] -+ cp := mpis[8] -+ d5 := mpis[9] -+ d6 := mpis[10] -+ h := sha256.New() -+ -+ r := new(big.Int).Exp(g, d2, p) -+ s := new(big.Int).Exp(g2b, c2, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ s.SetBytes(hashMPIs(h, 3, r)) -+ if c2.Cmp(s) != 0 { -+ err = errors.New("otr: ZKP c2 failed in SMP2 message") -+ return -+ } -+ -+ r.Exp(g, d3, p) -+ s.Exp(g3b, c3, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ s.SetBytes(hashMPIs(h, 4, r)) -+ if c3.Cmp(s) != 0 { -+ err = errors.New("otr: ZKP c3 failed in SMP2 message") -+ return -+ } -+ -+ c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p) -+ c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p) -+ -+ r.Exp(g, d5, p) -+ s.Exp(c.smp.g2, d6, p) -+ r.Mul(r, s) -+ s.Exp(qb, cp, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ -+ s.Exp(c.smp.g3, d5, p) -+ t := new(big.Int).Exp(pb, cp, p) -+ s.Mul(s, t) -+ s.Mod(s, p) -+ t.SetBytes(hashMPIs(h, 5, s, r)) -+ if cp.Cmp(t) != 0 { -+ err = errors.New("otr: ZKP cP failed in SMP2 message") -+ return -+ } -+ -+ var randBuf [16]byte -+ r4 := c.randMPI(randBuf[:]) -+ r5 := c.randMPI(randBuf[:]) -+ r6 := c.randMPI(randBuf[:]) -+ r7 := c.randMPI(randBuf[:]) -+ -+ pa := new(big.Int).Exp(c.smp.g3, r4, p) -+ r.Exp(c.smp.g2, c.smp.secret, p) -+ qa := new(big.Int).Exp(g, r4, p) -+ qa.Mul(qa, r) -+ qa.Mod(qa, p) -+ -+ r.Exp(g, r5, p) -+ s.Exp(c.smp.g2, r6, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ -+ s.Exp(c.smp.g3, r5, p) -+ cp.SetBytes(hashMPIs(h, 6, s, r)) -+ -+ r.Mul(r4, cp) -+ d5 = new(big.Int).Sub(r5, r) -+ d5.Mod(d5, q) -+ if d5.Sign() < 0 { -+ d5.Add(d5, q) -+ } -+ -+ r.Mul(c.smp.secret, cp) -+ d6 = new(big.Int).Sub(r6, r) -+ d6.Mod(d6, q) -+ if d6.Sign() < 0 { -+ d6.Add(d6, q) -+ } -+ -+ r.ModInverse(qb, p) -+ qaqb := new(big.Int).Mul(qa, r) -+ qaqb.Mod(qaqb, p) -+ -+ ra := new(big.Int).Exp(qaqb, c.smp.a3, p) -+ r.Exp(qaqb, r7, p) -+ s.Exp(g, r7, p) -+ cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r)) -+ -+ r.Mul(c.smp.a3, cr) -+ d7 := new(big.Int).Sub(r7, r) -+ d7.Mod(d7, q) -+ if d7.Sign() < 0 { -+ d7.Add(d7, q) -+ } -+ -+ c.smp.g3b = g3b -+ c.smp.qaqb = qaqb -+ -+ r.ModInverse(pb, p) -+ c.smp.papb = new(big.Int).Mul(pa, r) -+ c.smp.papb.Mod(c.smp.papb, p) -+ c.smp.ra = ra -+ -+ out.typ = tlvTypeSMP3 -+ out.data = appendU32(out.data, 8) -+ out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7) -+ return -+} -+ -+func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) { -+ if len(mpis) != 8 { -+ err = errors.New("otr: incorrect number of arguments in SMP3 message") -+ return -+ } -+ pa := mpis[0] -+ qa := mpis[1] -+ cp := mpis[2] -+ d5 := mpis[3] -+ d6 := mpis[4] -+ ra := mpis[5] -+ cr := mpis[6] -+ d7 := mpis[7] -+ h := sha256.New() -+ -+ r := new(big.Int).Exp(g, d5, p) -+ s := new(big.Int).Exp(c.smp.g2, d6, p) -+ r.Mul(r, s) -+ s.Exp(qa, cp, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ -+ s.Exp(c.smp.g3, d5, p) -+ t := new(big.Int).Exp(pa, cp, p) -+ s.Mul(s, t) -+ s.Mod(s, p) -+ t.SetBytes(hashMPIs(h, 6, s, r)) -+ if t.Cmp(cp) != 0 { -+ err = errors.New("otr: ZKP cP failed in SMP3 message") -+ return -+ } -+ -+ r.ModInverse(c.smp.qb, p) -+ qaqb := new(big.Int).Mul(qa, r) -+ qaqb.Mod(qaqb, p) -+ -+ r.Exp(qaqb, d7, p) -+ s.Exp(ra, cr, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ -+ s.Exp(g, d7, p) -+ t.Exp(c.smp.g3a, cr, p) -+ s.Mul(s, t) -+ s.Mod(s, p) -+ t.SetBytes(hashMPIs(h, 7, s, r)) -+ if t.Cmp(cr) != 0 { -+ err = errors.New("otr: ZKP cR failed in SMP3 message") -+ return -+ } -+ -+ var randBuf [16]byte -+ r7 := c.randMPI(randBuf[:]) -+ rb := new(big.Int).Exp(qaqb, c.smp.b3, p) -+ -+ r.Exp(qaqb, r7, p) -+ s.Exp(g, r7, p) -+ cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r)) -+ -+ r.Mul(c.smp.b3, cr) -+ d7 = new(big.Int).Sub(r7, r) -+ d7.Mod(d7, q) -+ if d7.Sign() < 0 { -+ d7.Add(d7, q) -+ } -+ -+ out.typ = tlvTypeSMP4 -+ out.data = appendU32(out.data, 3) -+ out.data = appendMPIs(out.data, rb, cr, d7) -+ -+ r.ModInverse(c.smp.pb, p) -+ r.Mul(pa, r) -+ r.Mod(r, p) -+ s.Exp(ra, c.smp.b3, p) -+ if r.Cmp(s) != 0 { -+ err = smpFailureError -+ } -+ -+ return -+} -+ -+func (c *Conversation) processSMP4(mpis []*big.Int) error { -+ if len(mpis) != 3 { -+ return errors.New("otr: incorrect number of arguments in SMP4 message") -+ } -+ rb := mpis[0] -+ cr := mpis[1] -+ d7 := mpis[2] -+ h := sha256.New() -+ -+ r := new(big.Int).Exp(c.smp.qaqb, d7, p) -+ s := new(big.Int).Exp(rb, cr, p) -+ r.Mul(r, s) -+ r.Mod(r, p) -+ -+ s.Exp(g, d7, p) -+ t := new(big.Int).Exp(c.smp.g3b, cr, p) -+ s.Mul(s, t) -+ s.Mod(s, p) -+ t.SetBytes(hashMPIs(h, 8, s, r)) -+ if t.Cmp(cr) != 0 { -+ return errors.New("otr: ZKP cR failed in SMP4 message") -+ } -+ -+ r.Exp(rb, c.smp.a3, p) -+ if r.Cmp(c.smp.papb) != 0 { -+ return smpFailureError -+ } -+ -+ return nil -+} -+ -+func (c *Conversation) generateSMPAbort() tlv { -+ return tlv{typ: tlvTypeSMPAbort} -+} -+ -+func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte { -+ if h != nil { -+ h.Reset() -+ } else { -+ h = sha256.New() -+ } -+ -+ h.Write([]byte{magic}) -+ for _, mpi := range mpis { -+ h.Write(appendMPI(nil, mpi)) -+ } -+ return h.Sum(nil) -+} -diff --git a/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go -new file mode 100644 -index 00000000000000..904b57e01d7a50 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2.go -@@ -0,0 +1,77 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC -+2898 / PKCS #5 v2.0. -+ -+A key derivation function is useful when encrypting data based on a password -+or any other not-fully-random data. It uses a pseudorandom function to derive -+a secure encryption key based on the password. -+ -+While v2.0 of the standard defines only one pseudorandom function to use, -+HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved -+Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To -+choose, you can pass the `New` functions from the different SHA packages to -+pbkdf2.Key. -+*/ -+package pbkdf2 // import "golang.org/x/crypto/pbkdf2" -+ -+import ( -+ "crypto/hmac" -+ "hash" -+) -+ -+// Key derives a key from the password, salt and iteration count, returning a -+// []byte of length keylen that can be used as cryptographic key. The key is -+// derived based on the method described as PBKDF2 with the HMAC variant using -+// the supplied hash function. -+// -+// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you -+// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by -+// doing: -+// -+// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) -+// -+// Remember to get a good random salt. At least 8 bytes is recommended by the -+// RFC. -+// -+// Using a higher iteration count will increase the cost of an exhaustive -+// search but will also make derivation proportionally slower. -+func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { -+ prf := hmac.New(h, password) -+ hashLen := prf.Size() -+ numBlocks := (keyLen + hashLen - 1) / hashLen -+ -+ var buf [4]byte -+ dk := make([]byte, 0, numBlocks*hashLen) -+ U := make([]byte, hashLen) -+ for block := 1; block <= numBlocks; block++ { -+ // N.B.: || means concatenation, ^ means XOR -+ // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter -+ // U_1 = PRF(password, salt || uint(i)) -+ prf.Reset() -+ prf.Write(salt) -+ buf[0] = byte(block >> 24) -+ buf[1] = byte(block >> 16) -+ buf[2] = byte(block >> 8) -+ buf[3] = byte(block) -+ prf.Write(buf[:4]) -+ dk = prf.Sum(dk) -+ T := dk[len(dk)-hashLen:] -+ copy(U, T) -+ -+ // U_n = PRF(password, U_(n-1)) -+ for n := 2; n <= iter; n++ { -+ prf.Reset() -+ prf.Write(U) -+ U = U[:0] -+ U = prf.Sum(U) -+ for x := range U { -+ T[x] ^= U[x] -+ } -+ } -+ } -+ return dk[:keyLen] -+} -diff --git a/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go -new file mode 100644 -index 00000000000000..f83cb69227371a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pbkdf2/pbkdf2_test.go -@@ -0,0 +1,176 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pbkdf2 -+ -+import ( -+ "bytes" -+ "crypto/sha1" -+ "crypto/sha256" -+ "hash" -+ "testing" -+) -+ -+type testVector struct { -+ password string -+ salt string -+ iter int -+ output []byte -+} -+ -+// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070 -+var sha1TestVectors = []testVector{ -+ { -+ "password", -+ "salt", -+ 1, -+ []byte{ -+ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, -+ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, -+ 0x2f, 0xe0, 0x37, 0xa6, -+ }, -+ }, -+ { -+ "password", -+ "salt", -+ 2, -+ []byte{ -+ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, -+ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, -+ 0xd8, 0xde, 0x89, 0x57, -+ }, -+ }, -+ { -+ "password", -+ "salt", -+ 4096, -+ []byte{ -+ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, -+ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, -+ 0x65, 0xa4, 0x29, 0xc1, -+ }, -+ }, -+ // // This one takes too long -+ // { -+ // "password", -+ // "salt", -+ // 16777216, -+ // []byte{ -+ // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, -+ // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, -+ // 0x26, 0x34, 0xe9, 0x84, -+ // }, -+ // }, -+ { -+ "passwordPASSWORDpassword", -+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", -+ 4096, -+ []byte{ -+ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, -+ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, -+ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, -+ 0x38, -+ }, -+ }, -+ { -+ "pass\000word", -+ "sa\000lt", -+ 4096, -+ []byte{ -+ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, -+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, -+ }, -+ }, -+} -+ -+// Test vectors from -+// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors -+var sha256TestVectors = []testVector{ -+ { -+ "password", -+ "salt", -+ 1, -+ []byte{ -+ 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, -+ 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, -+ 0xa8, 0x65, 0x48, 0xc9, -+ }, -+ }, -+ { -+ "password", -+ "salt", -+ 2, -+ []byte{ -+ 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, -+ 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, -+ 0x2a, 0x30, 0x3f, 0x8e, -+ }, -+ }, -+ { -+ "password", -+ "salt", -+ 4096, -+ []byte{ -+ 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, -+ 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, -+ 0x96, 0x28, 0x93, 0xa0, -+ }, -+ }, -+ { -+ "passwordPASSWORDpassword", -+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", -+ 4096, -+ []byte{ -+ 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, -+ 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, -+ 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, -+ 0x1c, -+ }, -+ }, -+ { -+ "pass\000word", -+ "sa\000lt", -+ 4096, -+ []byte{ -+ 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, -+ 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87, -+ }, -+ }, -+} -+ -+func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) { -+ for i, v := range vectors { -+ o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h) -+ if !bytes.Equal(o, v.output) { -+ t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o) -+ } -+ } -+} -+ -+func TestWithHMACSHA1(t *testing.T) { -+ testHash(t, sha1.New, "SHA1", sha1TestVectors) -+} -+ -+func TestWithHMACSHA256(t *testing.T) { -+ testHash(t, sha256.New, "SHA256", sha256TestVectors) -+} -+ -+var sink uint8 -+ -+func benchmark(b *testing.B, h func() hash.Hash) { -+ password := make([]byte, h().Size()) -+ salt := make([]byte, 8) -+ for i := 0; i < b.N; i++ { -+ password = Key(password, salt, 4096, len(password), h) -+ } -+ sink += password[0] -+} -+ -+func BenchmarkHMACSHA1(b *testing.B) { -+ benchmark(b, sha1.New) -+} -+ -+func BenchmarkHMACSHA256(b *testing.B) { -+ benchmark(b, sha256.New) -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go -new file mode 100644 -index 00000000000000..233b8b62cc2708 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string.go -@@ -0,0 +1,50 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "errors" -+ "unicode/utf16" -+) -+ -+// bmpString returns s encoded in UCS-2 with a zero terminator. -+func bmpString(s string) ([]byte, error) { -+ // References: -+ // https://tools.ietf.org/html/rfc7292#appendix-B.1 -+ // https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane -+ // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes -+ // EncodeRune returns 0xfffd if the rune does not need special encoding -+ // - the above RFC provides the info that BMPStrings are NULL terminated. -+ -+ ret := make([]byte, 0, 2*len(s)+2) -+ -+ for _, r := range s { -+ if t, _ := utf16.EncodeRune(r); t != 0xfffd { -+ return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2") -+ } -+ ret = append(ret, byte(r/256), byte(r%256)) -+ } -+ -+ return append(ret, 0, 0), nil -+} -+ -+func decodeBMPString(bmpString []byte) (string, error) { -+ if len(bmpString)%2 != 0 { -+ return "", errors.New("pkcs12: odd-length BMP string") -+ } -+ -+ // strip terminator if present -+ if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { -+ bmpString = bmpString[:l-2] -+ } -+ -+ s := make([]uint16, 0, len(bmpString)/2) -+ for len(bmpString) > 0 { -+ s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) -+ bmpString = bmpString[2:] -+ } -+ -+ return string(utf16.Decode(s)), nil -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go -new file mode 100644 -index 00000000000000..7fca55f4e8b3a9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/bmp-string_test.go -@@ -0,0 +1,63 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "testing" -+) -+ -+var bmpStringTests = []struct { -+ in string -+ expectedHex string -+ shouldFail bool -+}{ -+ {"", "0000", false}, -+ // Example from https://tools.ietf.org/html/rfc7292#appendix-B. -+ {"Beavis", "0042006500610076006900730000", false}, -+ // Some characters from the "Letterlike Symbols Unicode block". -+ {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false}, -+ // any character outside the BMP should trigger an error. -+ {"\U0001f000 East wind (Mahjong)", "", true}, -+} -+ -+func TestBMPString(t *testing.T) { -+ for i, test := range bmpStringTests { -+ expected, err := hex.DecodeString(test.expectedHex) -+ if err != nil { -+ t.Fatalf("#%d: failed to decode expectation", i) -+ } -+ -+ out, err := bmpString(test.in) -+ if err == nil && test.shouldFail { -+ t.Errorf("#%d: expected to fail, but produced %x", i, out) -+ continue -+ } -+ -+ if err != nil && !test.shouldFail { -+ t.Errorf("#%d: failed unexpectedly: %s", i, err) -+ continue -+ } -+ -+ if !test.shouldFail { -+ if !bytes.Equal(out, expected) { -+ t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out) -+ continue -+ } -+ -+ roundTrip, err := decodeBMPString(out) -+ if err != nil { -+ t.Errorf("#%d: decoding output gave an error: %s", i, err) -+ continue -+ } -+ -+ if roundTrip != test.in { -+ t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in) -+ continue -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/crypto.go b/ms_mod/golang.org/x/crypto/pkcs12/crypto.go -new file mode 100644 -index 00000000000000..96f4a1a56ecacd ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/crypto.go -@@ -0,0 +1,131 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "bytes" -+ "crypto/cipher" -+ "crypto/des" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "errors" -+ -+ "golang.org/x/crypto/pkcs12/internal/rc2" -+) -+ -+var ( -+ oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) -+ oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6}) -+) -+ -+// pbeCipher is an abstraction of a PKCS#12 cipher. -+type pbeCipher interface { -+ // create returns a cipher.Block given a key. -+ create(key []byte) (cipher.Block, error) -+ // deriveKey returns a key derived from the given password and salt. -+ deriveKey(salt, password []byte, iterations int) []byte -+ // deriveKey returns an IV derived from the given password and salt. -+ deriveIV(salt, password []byte, iterations int) []byte -+} -+ -+type shaWithTripleDESCBC struct{} -+ -+func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) { -+ return des.NewTripleDESCipher(key) -+} -+ -+func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte { -+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24) -+} -+ -+func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte { -+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) -+} -+ -+type shaWith40BitRC2CBC struct{} -+ -+func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) { -+ return rc2.New(key, len(key)*8) -+} -+ -+func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { -+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5) -+} -+ -+func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { -+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) -+} -+ -+type pbeParams struct { -+ Salt []byte -+ Iterations int -+} -+ -+func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { -+ var cipherType pbeCipher -+ -+ switch { -+ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): -+ cipherType = shaWithTripleDESCBC{} -+ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): -+ cipherType = shaWith40BitRC2CBC{} -+ default: -+ return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported") -+ } -+ -+ var params pbeParams -+ if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { -+ return nil, 0, err -+ } -+ -+ key := cipherType.deriveKey(params.Salt, password, params.Iterations) -+ iv := cipherType.deriveIV(params.Salt, password, params.Iterations) -+ -+ block, err := cipherType.create(key) -+ if err != nil { -+ return nil, 0, err -+ } -+ -+ return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil -+} -+ -+func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) { -+ cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password) -+ if err != nil { -+ return nil, err -+ } -+ -+ encrypted := info.Data() -+ if len(encrypted) == 0 { -+ return nil, errors.New("pkcs12: empty encrypted data") -+ } -+ if len(encrypted)%blockSize != 0 { -+ return nil, errors.New("pkcs12: input is not a multiple of the block size") -+ } -+ decrypted = make([]byte, len(encrypted)) -+ cbc.CryptBlocks(decrypted, encrypted) -+ -+ psLen := int(decrypted[len(decrypted)-1]) -+ if psLen == 0 || psLen > blockSize { -+ return nil, ErrDecryption -+ } -+ -+ if len(decrypted) < psLen { -+ return nil, ErrDecryption -+ } -+ ps := decrypted[len(decrypted)-psLen:] -+ decrypted = decrypted[:len(decrypted)-psLen] -+ if !bytes.Equal(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) { -+ return nil, ErrDecryption -+ } -+ -+ return -+} -+ -+// decryptable abstracts an object that contains ciphertext. -+type decryptable interface { -+ Algorithm() pkix.AlgorithmIdentifier -+ Data() []byte -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go b/ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go -new file mode 100644 -index 00000000000000..eb4dae8fceba54 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/crypto_test.go -@@ -0,0 +1,125 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "bytes" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "testing" -+) -+ -+var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) -+ -+func TestPbDecrypterFor(t *testing.T) { -+ params, _ := asn1.Marshal(pbeParams{ -+ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, -+ Iterations: 2048, -+ }) -+ alg := pkix.AlgorithmIdentifier{ -+ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), -+ Parameters: asn1.RawValue{ -+ FullBytes: params, -+ }, -+ } -+ -+ pass, _ := bmpString("Sesame open") -+ -+ _, _, err := pbDecrypterFor(alg, pass) -+ if _, ok := err.(NotImplementedError); !ok { -+ t.Errorf("expected not implemented error, got: %T %s", err, err) -+ } -+ -+ alg.Algorithm = sha1WithTripleDES -+ cbc, blockSize, err := pbDecrypterFor(alg, pass) -+ if err != nil { -+ t.Errorf("unexpected error from pbDecrypterFor %v", err) -+ } -+ if blockSize != 8 { -+ t.Errorf("unexpected block size %d, wanted 8", blockSize) -+ } -+ -+ plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8} -+ expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247} -+ ciphertext := make([]byte, len(plaintext)) -+ cbc.CryptBlocks(ciphertext, plaintext) -+ -+ if bytes.Compare(ciphertext, expectedCiphertext) != 0 { -+ t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext) -+ } -+} -+ -+var pbDecryptTests = []struct { -+ in []byte -+ expected []byte -+ expectedError error -+}{ -+ { -+ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes -+ []byte("A secret!"), -+ nil, -+ }, -+ { -+ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes -+ []byte("A secret"), -+ nil, -+ }, -+ { -+ []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect -+ nil, -+ ErrDecryption, -+ }, -+ { -+ []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ] -+ nil, -+ ErrDecryption, -+ }, -+} -+ -+func TestPbDecrypt(t *testing.T) { -+ for i, test := range pbDecryptTests { -+ decryptable := testDecryptable{ -+ data: test.in, -+ algorithm: pkix.AlgorithmIdentifier{ -+ Algorithm: sha1WithTripleDES, -+ Parameters: pbeParams{ -+ Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"), -+ Iterations: 4096, -+ }.RawASN1(), -+ }, -+ } -+ password, _ := bmpString("sesame") -+ -+ plaintext, err := pbDecrypt(decryptable, password) -+ if err != test.expectedError { -+ t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError) -+ continue -+ } -+ -+ if !bytes.Equal(plaintext, test.expected) { -+ t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected) -+ } -+ } -+} -+ -+type testDecryptable struct { -+ data []byte -+ algorithm pkix.AlgorithmIdentifier -+} -+ -+func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm } -+func (d testDecryptable) Data() []byte { return d.data } -+ -+func (params pbeParams) RawASN1() (raw asn1.RawValue) { -+ asn1Bytes, err := asn1.Marshal(params) -+ if err != nil { -+ panic(err) -+ } -+ _, err = asn1.Unmarshal(asn1Bytes, &raw) -+ if err != nil { -+ panic(err) -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/errors.go b/ms_mod/golang.org/x/crypto/pkcs12/errors.go -new file mode 100644 -index 00000000000000..7377ce6fb2b814 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/errors.go -@@ -0,0 +1,23 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import "errors" -+ -+var ( -+ // ErrDecryption represents a failure to decrypt the input. -+ ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding") -+ -+ // ErrIncorrectPassword is returned when an incorrect password is detected. -+ // Usually, P12/PFX data is signed to be able to verify the password. -+ ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect") -+) -+ -+// NotImplementedError indicates that the input is not currently supported. -+type NotImplementedError string -+ -+func (e NotImplementedError) Error() string { -+ return "pkcs12: " + string(e) -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go -new file mode 100644 -index 00000000000000..3347f338c18607 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go -@@ -0,0 +1,27 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package rc2 -+ -+import ( -+ "testing" -+) -+ -+func BenchmarkEncrypt(b *testing.B) { -+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) -+ b.ResetTimer() -+ var src [8]byte -+ for i := 0; i < b.N; i++ { -+ r.Encrypt(src[:], src[:]) -+ } -+} -+ -+func BenchmarkDecrypt(b *testing.B) { -+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) -+ b.ResetTimer() -+ var src [8]byte -+ for i := 0; i < b.N; i++ { -+ r.Decrypt(src[:], src[:]) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go -new file mode 100644 -index 00000000000000..05de9cc2cdcc59 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go -@@ -0,0 +1,268 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package rc2 implements the RC2 cipher -+/* -+https://www.ietf.org/rfc/rfc2268.txt -+http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf -+ -+This code is licensed under the MIT license. -+*/ -+package rc2 -+ -+import ( -+ "crypto/cipher" -+ "encoding/binary" -+ "math/bits" -+) -+ -+// The rc2 block size in bytes -+const BlockSize = 8 -+ -+type rc2Cipher struct { -+ k [64]uint16 -+} -+ -+// New returns a new rc2 cipher with the given key and effective key length t1 -+func New(key []byte, t1 int) (cipher.Block, error) { -+ // TODO(dgryski): error checking for key length -+ return &rc2Cipher{ -+ k: expandKey(key, t1), -+ }, nil -+} -+ -+func (*rc2Cipher) BlockSize() int { return BlockSize } -+ -+var piTable = [256]byte{ -+ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, -+ 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, -+ 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, -+ 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, -+ 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, -+ 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, -+ 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, -+ 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, -+ 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, -+ 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, -+ 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, -+ 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, -+ 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, -+ 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, -+ 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, -+ 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, -+} -+ -+func expandKey(key []byte, t1 int) [64]uint16 { -+ -+ l := make([]byte, 128) -+ copy(l, key) -+ -+ var t = len(key) -+ var t8 = (t1 + 7) / 8 -+ var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8)))) -+ -+ for i := len(key); i < 128; i++ { -+ l[i] = piTable[l[i-1]+l[uint8(i-t)]] -+ } -+ -+ l[128-t8] = piTable[l[128-t8]&tm] -+ -+ for i := 127 - t8; i >= 0; i-- { -+ l[i] = piTable[l[i+1]^l[i+t8]] -+ } -+ -+ var k [64]uint16 -+ -+ for i := range k { -+ k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256 -+ } -+ -+ return k -+} -+ -+func (c *rc2Cipher) Encrypt(dst, src []byte) { -+ -+ r0 := binary.LittleEndian.Uint16(src[0:]) -+ r1 := binary.LittleEndian.Uint16(src[2:]) -+ r2 := binary.LittleEndian.Uint16(src[4:]) -+ r3 := binary.LittleEndian.Uint16(src[6:]) -+ -+ var j int -+ -+ for j <= 16 { -+ // mix r0 -+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) -+ r0 = bits.RotateLeft16(r0, 1) -+ j++ -+ -+ // mix r1 -+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) -+ r1 = bits.RotateLeft16(r1, 2) -+ j++ -+ -+ // mix r2 -+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) -+ r2 = bits.RotateLeft16(r2, 3) -+ j++ -+ -+ // mix r3 -+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) -+ r3 = bits.RotateLeft16(r3, 5) -+ j++ -+ -+ } -+ -+ r0 = r0 + c.k[r3&63] -+ r1 = r1 + c.k[r0&63] -+ r2 = r2 + c.k[r1&63] -+ r3 = r3 + c.k[r2&63] -+ -+ for j <= 40 { -+ // mix r0 -+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) -+ r0 = bits.RotateLeft16(r0, 1) -+ j++ -+ -+ // mix r1 -+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) -+ r1 = bits.RotateLeft16(r1, 2) -+ j++ -+ -+ // mix r2 -+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) -+ r2 = bits.RotateLeft16(r2, 3) -+ j++ -+ -+ // mix r3 -+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) -+ r3 = bits.RotateLeft16(r3, 5) -+ j++ -+ -+ } -+ -+ r0 = r0 + c.k[r3&63] -+ r1 = r1 + c.k[r0&63] -+ r2 = r2 + c.k[r1&63] -+ r3 = r3 + c.k[r2&63] -+ -+ for j <= 60 { -+ // mix r0 -+ r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) -+ r0 = bits.RotateLeft16(r0, 1) -+ j++ -+ -+ // mix r1 -+ r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) -+ r1 = bits.RotateLeft16(r1, 2) -+ j++ -+ -+ // mix r2 -+ r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) -+ r2 = bits.RotateLeft16(r2, 3) -+ j++ -+ -+ // mix r3 -+ r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) -+ r3 = bits.RotateLeft16(r3, 5) -+ j++ -+ } -+ -+ binary.LittleEndian.PutUint16(dst[0:], r0) -+ binary.LittleEndian.PutUint16(dst[2:], r1) -+ binary.LittleEndian.PutUint16(dst[4:], r2) -+ binary.LittleEndian.PutUint16(dst[6:], r3) -+} -+ -+func (c *rc2Cipher) Decrypt(dst, src []byte) { -+ -+ r0 := binary.LittleEndian.Uint16(src[0:]) -+ r1 := binary.LittleEndian.Uint16(src[2:]) -+ r2 := binary.LittleEndian.Uint16(src[4:]) -+ r3 := binary.LittleEndian.Uint16(src[6:]) -+ -+ j := 63 -+ -+ for j >= 44 { -+ // unmix r3 -+ r3 = bits.RotateLeft16(r3, 16-5) -+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) -+ j-- -+ -+ // unmix r2 -+ r2 = bits.RotateLeft16(r2, 16-3) -+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) -+ j-- -+ -+ // unmix r1 -+ r1 = bits.RotateLeft16(r1, 16-2) -+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) -+ j-- -+ -+ // unmix r0 -+ r0 = bits.RotateLeft16(r0, 16-1) -+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) -+ j-- -+ } -+ -+ r3 = r3 - c.k[r2&63] -+ r2 = r2 - c.k[r1&63] -+ r1 = r1 - c.k[r0&63] -+ r0 = r0 - c.k[r3&63] -+ -+ for j >= 20 { -+ // unmix r3 -+ r3 = bits.RotateLeft16(r3, 16-5) -+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) -+ j-- -+ -+ // unmix r2 -+ r2 = bits.RotateLeft16(r2, 16-3) -+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) -+ j-- -+ -+ // unmix r1 -+ r1 = bits.RotateLeft16(r1, 16-2) -+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) -+ j-- -+ -+ // unmix r0 -+ r0 = bits.RotateLeft16(r0, 16-1) -+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) -+ j-- -+ -+ } -+ -+ r3 = r3 - c.k[r2&63] -+ r2 = r2 - c.k[r1&63] -+ r1 = r1 - c.k[r0&63] -+ r0 = r0 - c.k[r3&63] -+ -+ for j >= 0 { -+ // unmix r3 -+ r3 = bits.RotateLeft16(r3, 16-5) -+ r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) -+ j-- -+ -+ // unmix r2 -+ r2 = bits.RotateLeft16(r2, 16-3) -+ r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) -+ j-- -+ -+ // unmix r1 -+ r1 = bits.RotateLeft16(r1, 16-2) -+ r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) -+ j-- -+ -+ // unmix r0 -+ r0 = bits.RotateLeft16(r0, 16-1) -+ r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) -+ j-- -+ -+ } -+ -+ binary.LittleEndian.PutUint16(dst[0:], r0) -+ binary.LittleEndian.PutUint16(dst[2:], r1) -+ binary.LittleEndian.PutUint16(dst[4:], r2) -+ binary.LittleEndian.PutUint16(dst[6:], r3) -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go -new file mode 100644 -index 00000000000000..51a7efe506289f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go -@@ -0,0 +1,92 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package rc2 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "testing" -+) -+ -+func TestEncryptDecrypt(t *testing.T) { -+ // TODO(dgryski): add the rest of the test vectors from the RFC -+ var tests = []struct { -+ key string -+ plain string -+ cipher string -+ t1 int -+ }{ -+ { -+ "0000000000000000", -+ "0000000000000000", -+ "ebb773f993278eff", -+ 63, -+ }, -+ { -+ "ffffffffffffffff", -+ "ffffffffffffffff", -+ "278b27e42e2f0d49", -+ 64, -+ }, -+ { -+ "3000000000000000", -+ "1000000000000001", -+ "30649edf9be7d2c2", -+ 64, -+ }, -+ { -+ "88", -+ "0000000000000000", -+ "61a8a244adacccf0", -+ 64, -+ }, -+ { -+ "88bca90e90875a", -+ "0000000000000000", -+ "6ccf4308974c267f", -+ 64, -+ }, -+ { -+ "88bca90e90875a7f0f79c384627bafb2", -+ "0000000000000000", -+ "1a807d272bbe5db1", -+ 64, -+ }, -+ { -+ "88bca90e90875a7f0f79c384627bafb2", -+ "0000000000000000", -+ "2269552ab0f85ca6", -+ 128, -+ }, -+ { -+ "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", -+ "0000000000000000", -+ "5b78d3a43dfff1f1", -+ 129, -+ }, -+ } -+ -+ for _, tt := range tests { -+ k, _ := hex.DecodeString(tt.key) -+ p, _ := hex.DecodeString(tt.plain) -+ c, _ := hex.DecodeString(tt.cipher) -+ -+ b, _ := New(k, tt.t1) -+ -+ var dst [8]byte -+ -+ b.Encrypt(dst[:], p) -+ -+ if !bytes.Equal(dst[:], c) { -+ t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c) -+ } -+ -+ b.Decrypt(dst[:], c) -+ -+ if !bytes.Equal(dst[:], p) { -+ t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/mac.go b/ms_mod/golang.org/x/crypto/pkcs12/mac.go -new file mode 100644 -index 00000000000000..5f38aa7de83ce0 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/mac.go -@@ -0,0 +1,45 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "crypto/hmac" -+ "crypto/sha1" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+) -+ -+type macData struct { -+ Mac digestInfo -+ MacSalt []byte -+ Iterations int `asn1:"optional,default:1"` -+} -+ -+// from PKCS#7: -+type digestInfo struct { -+ Algorithm pkix.AlgorithmIdentifier -+ Digest []byte -+} -+ -+var ( -+ oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) -+) -+ -+func verifyMac(macData *macData, message, password []byte) error { -+ if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) { -+ return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String()) -+ } -+ -+ key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20) -+ -+ mac := hmac.New(sha1.New, key) -+ mac.Write(message) -+ expectedMAC := mac.Sum(nil) -+ -+ if !hmac.Equal(macData.Mac.Digest, expectedMAC) { -+ return ErrIncorrectPassword -+ } -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/mac_test.go b/ms_mod/golang.org/x/crypto/pkcs12/mac_test.go -new file mode 100644 -index 00000000000000..1ed4ff21e14b39 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/mac_test.go -@@ -0,0 +1,42 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "encoding/asn1" -+ "testing" -+) -+ -+func TestVerifyMac(t *testing.T) { -+ td := macData{ -+ Mac: digestInfo{ -+ Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93}, -+ }, -+ MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, -+ Iterations: 2048, -+ } -+ -+ message := []byte{11, 12, 13, 14, 15} -+ password, _ := bmpString("") -+ -+ td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3}) -+ err := verifyMac(&td, message, password) -+ if _, ok := err.(NotImplementedError); !ok { -+ t.Errorf("err: %v", err) -+ } -+ -+ td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) -+ err = verifyMac(&td, message, password) -+ if err != ErrIncorrectPassword { -+ t.Errorf("Expected incorrect password, got err: %v", err) -+ } -+ -+ password, _ = bmpString("Sesame open") -+ err = verifyMac(&td, message, password) -+ if err != nil { -+ t.Errorf("err: %v", err) -+ } -+ -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go -new file mode 100644 -index 00000000000000..5c419d41e32c2a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf.go -@@ -0,0 +1,170 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "bytes" -+ "crypto/sha1" -+ "math/big" -+) -+ -+var ( -+ one = big.NewInt(1) -+) -+ -+// sha1Sum returns the SHA-1 hash of in. -+func sha1Sum(in []byte) []byte { -+ sum := sha1.Sum(in) -+ return sum[:] -+} -+ -+// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of -+// repeats of pattern. -+func fillWithRepeats(pattern []byte, v int) []byte { -+ if len(pattern) == 0 { -+ return nil -+ } -+ outputLen := v * ((len(pattern) + v - 1) / v) -+ return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen] -+} -+ -+func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) { -+ // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments -+ -+ // Let H be a hash function built around a compression function f: -+ -+ // Z_2^u x Z_2^v -> Z_2^u -+ -+ // (that is, H has a chaining variable and output of length u bits, and -+ // the message input to the compression function of H is v bits). The -+ // values for u and v are as follows: -+ -+ // HASH FUNCTION VALUE u VALUE v -+ // MD2, MD5 128 512 -+ // SHA-1 160 512 -+ // SHA-224 224 512 -+ // SHA-256 256 512 -+ // SHA-384 384 1024 -+ // SHA-512 512 1024 -+ // SHA-512/224 224 1024 -+ // SHA-512/256 256 1024 -+ -+ // Furthermore, let r be the iteration count. -+ -+ // We assume here that u and v are both multiples of 8, as are the -+ // lengths of the password and salt strings (which we denote by p and s, -+ // respectively) and the number n of pseudorandom bits required. In -+ // addition, u and v are of course non-zero. -+ -+ // For information on security considerations for MD5 [19], see [25] and -+ // [1], and on those for MD2, see [18]. -+ -+ // The following procedure can be used to produce pseudorandom bits for -+ // a particular "purpose" that is identified by a byte called "ID". -+ // This standard specifies 3 different values for the ID byte: -+ -+ // 1. If ID=1, then the pseudorandom bits being produced are to be used -+ // as key material for performing encryption or decryption. -+ -+ // 2. If ID=2, then the pseudorandom bits being produced are to be used -+ // as an IV (Initial Value) for encryption or decryption. -+ -+ // 3. If ID=3, then the pseudorandom bits being produced are to be used -+ // as an integrity key for MACing. -+ -+ // 1. Construct a string, D (the "diversifier"), by concatenating v/8 -+ // copies of ID. -+ var D []byte -+ for i := 0; i < v; i++ { -+ D = append(D, ID) -+ } -+ -+ // 2. Concatenate copies of the salt together to create a string S of -+ // length v(ceiling(s/v)) bits (the final copy of the salt may be -+ // truncated to create S). Note that if the salt is the empty -+ // string, then so is S. -+ -+ S := fillWithRepeats(salt, v) -+ -+ // 3. Concatenate copies of the password together to create a string P -+ // of length v(ceiling(p/v)) bits (the final copy of the password -+ // may be truncated to create P). Note that if the password is the -+ // empty string, then so is P. -+ -+ P := fillWithRepeats(password, v) -+ -+ // 4. Set I=S||P to be the concatenation of S and P. -+ I := append(S, P...) -+ -+ // 5. Set c=ceiling(n/u). -+ c := (size + u - 1) / u -+ -+ // 6. For i=1, 2, ..., c, do the following: -+ A := make([]byte, c*20) -+ var IjBuf []byte -+ for i := 0; i < c; i++ { -+ // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1, -+ // H(H(H(... H(D||I)))) -+ Ai := hash(append(D, I...)) -+ for j := 1; j < r; j++ { -+ Ai = hash(Ai) -+ } -+ copy(A[i*20:], Ai[:]) -+ -+ if i < c-1 { // skip on last iteration -+ // B. Concatenate copies of Ai to create a string B of length v -+ // bits (the final copy of Ai may be truncated to create B). -+ var B []byte -+ for len(B) < v { -+ B = append(B, Ai[:]...) -+ } -+ B = B[:v] -+ -+ // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit -+ // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by -+ // setting I_j=(I_j+B+1) mod 2^v for each j. -+ { -+ Bbi := new(big.Int).SetBytes(B) -+ Ij := new(big.Int) -+ -+ for j := 0; j < len(I)/v; j++ { -+ Ij.SetBytes(I[j*v : (j+1)*v]) -+ Ij.Add(Ij, Bbi) -+ Ij.Add(Ij, one) -+ Ijb := Ij.Bytes() -+ // We expect Ijb to be exactly v bytes, -+ // if it is longer or shorter we must -+ // adjust it accordingly. -+ if len(Ijb) > v { -+ Ijb = Ijb[len(Ijb)-v:] -+ } -+ if len(Ijb) < v { -+ if IjBuf == nil { -+ IjBuf = make([]byte, v) -+ } -+ bytesShort := v - len(Ijb) -+ for i := 0; i < bytesShort; i++ { -+ IjBuf[i] = 0 -+ } -+ copy(IjBuf[bytesShort:], Ijb) -+ Ijb = IjBuf -+ } -+ copy(I[j*v:(j+1)*v], Ijb) -+ } -+ } -+ } -+ } -+ // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom -+ // bit string, A. -+ -+ // 8. Use the first n bits of A as the output of this entire process. -+ return A[:size] -+ -+ // If the above process is being used to generate a DES key, the process -+ // should be used to create 64 random bits, and the key's parity bits -+ // should be set after the 64 bits have been produced. Similar concerns -+ // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any -+ // similar keys with parity bits "built into them". -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go -new file mode 100644 -index 00000000000000..262037d7ebaac9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/pbkdf_test.go -@@ -0,0 +1,34 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) { -+ cipherInfo := shaWithTripleDESCBC{} -+ -+ salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff") -+ password, _ := bmpString("sesame") -+ key := cipherInfo.deriveKey(salt, password, 2048) -+ -+ if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 { -+ t.Fatalf("expected key '%x', but found '%x'", expected, key) -+ } -+} -+ -+func TestThatPBKDFHandlesLeadingZeros(t *testing.T) { -+ // This test triggers a case where I_j (in step 6C) ends up with leading zero -+ // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int). -+ // This was previously causing bug whereby certain inputs would break the -+ // derivation and produce the wrong output. -+ key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24) -+ expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1") -+ if bytes.Compare(key, expected) != 0 { -+ t.Fatalf("expected key '%x', but found '%x'", expected, key) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go -new file mode 100644 -index 00000000000000..3a89bdb3e393bb ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12.go -@@ -0,0 +1,360 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package pkcs12 implements some of PKCS#12. -+// -+// This implementation is distilled from https://tools.ietf.org/html/rfc7292 -+// and referenced documents. It is intended for decoding P12/PFX-stored -+// certificates and keys for use with the crypto/tls package. -+// -+// This package is frozen. If it's missing functionality you need, consider -+// an alternative like software.sslmate.com/src/go-pkcs12. -+package pkcs12 -+ -+import ( -+ "crypto/ecdsa" -+ "crypto/rsa" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/hex" -+ "encoding/pem" -+ "errors" -+) -+ -+var ( -+ oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1}) -+ oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6}) -+ -+ oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) -+ oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) -+ oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) -+ -+ errUnknownAttributeOID = errors.New("pkcs12: unknown attribute OID") -+) -+ -+type pfxPdu struct { -+ Version int -+ AuthSafe contentInfo -+ MacData macData `asn1:"optional"` -+} -+ -+type contentInfo struct { -+ ContentType asn1.ObjectIdentifier -+ Content asn1.RawValue `asn1:"tag:0,explicit,optional"` -+} -+ -+type encryptedData struct { -+ Version int -+ EncryptedContentInfo encryptedContentInfo -+} -+ -+type encryptedContentInfo struct { -+ ContentType asn1.ObjectIdentifier -+ ContentEncryptionAlgorithm pkix.AlgorithmIdentifier -+ EncryptedContent []byte `asn1:"tag:0,optional"` -+} -+ -+func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier { -+ return i.ContentEncryptionAlgorithm -+} -+ -+func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent } -+ -+type safeBag struct { -+ Id asn1.ObjectIdentifier -+ Value asn1.RawValue `asn1:"tag:0,explicit"` -+ Attributes []pkcs12Attribute `asn1:"set,optional"` -+} -+ -+type pkcs12Attribute struct { -+ Id asn1.ObjectIdentifier -+ Value asn1.RawValue `asn1:"set"` -+} -+ -+type encryptedPrivateKeyInfo struct { -+ AlgorithmIdentifier pkix.AlgorithmIdentifier -+ EncryptedData []byte -+} -+ -+func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier { -+ return i.AlgorithmIdentifier -+} -+ -+func (i encryptedPrivateKeyInfo) Data() []byte { -+ return i.EncryptedData -+} -+ -+// PEM block types -+const ( -+ certificateType = "CERTIFICATE" -+ privateKeyType = "PRIVATE KEY" -+) -+ -+// unmarshal calls asn1.Unmarshal, but also returns an error if there is any -+// trailing data after unmarshaling. -+func unmarshal(in []byte, out interface{}) error { -+ trailing, err := asn1.Unmarshal(in, out) -+ if err != nil { -+ return err -+ } -+ if len(trailing) != 0 { -+ return errors.New("pkcs12: trailing data found") -+ } -+ return nil -+} -+ -+// ToPEM converts all "safe bags" contained in pfxData to PEM blocks. -+// Unknown attributes are discarded. -+// -+// Note that although the returned PEM blocks for private keys have type -+// "PRIVATE KEY", the bytes are not encoded according to PKCS #8, but according -+// to PKCS #1 for RSA keys and SEC 1 for ECDSA keys. -+func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { -+ encodedPassword, err := bmpString(password) -+ if err != nil { -+ return nil, ErrIncorrectPassword -+ } -+ -+ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) -+ -+ if err != nil { -+ return nil, err -+ } -+ -+ blocks := make([]*pem.Block, 0, len(bags)) -+ for _, bag := range bags { -+ block, err := convertBag(&bag, encodedPassword) -+ if err != nil { -+ return nil, err -+ } -+ blocks = append(blocks, block) -+ } -+ -+ return blocks, nil -+} -+ -+func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { -+ block := &pem.Block{ -+ Headers: make(map[string]string), -+ } -+ -+ for _, attribute := range bag.Attributes { -+ k, v, err := convertAttribute(&attribute) -+ if err == errUnknownAttributeOID { -+ continue -+ } -+ if err != nil { -+ return nil, err -+ } -+ block.Headers[k] = v -+ } -+ -+ switch { -+ case bag.Id.Equal(oidCertBag): -+ block.Type = certificateType -+ certsData, err := decodeCertBag(bag.Value.Bytes) -+ if err != nil { -+ return nil, err -+ } -+ block.Bytes = certsData -+ case bag.Id.Equal(oidPKCS8ShroundedKeyBag): -+ block.Type = privateKeyType -+ -+ key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password) -+ if err != nil { -+ return nil, err -+ } -+ -+ switch key := key.(type) { -+ case *rsa.PrivateKey: -+ block.Bytes = x509.MarshalPKCS1PrivateKey(key) -+ case *ecdsa.PrivateKey: -+ block.Bytes, err = x509.MarshalECPrivateKey(key) -+ if err != nil { -+ return nil, err -+ } -+ default: -+ return nil, errors.New("found unknown private key type in PKCS#8 wrapping") -+ } -+ default: -+ return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String()) -+ } -+ return block, nil -+} -+ -+func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) { -+ isString := false -+ -+ switch { -+ case attribute.Id.Equal(oidFriendlyName): -+ key = "friendlyName" -+ isString = true -+ case attribute.Id.Equal(oidLocalKeyID): -+ key = "localKeyId" -+ case attribute.Id.Equal(oidMicrosoftCSPName): -+ // This key is chosen to match OpenSSL. -+ key = "Microsoft CSP Name" -+ isString = true -+ default: -+ return "", "", errUnknownAttributeOID -+ } -+ -+ if isString { -+ if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil { -+ return "", "", err -+ } -+ if value, err = decodeBMPString(attribute.Value.Bytes); err != nil { -+ return "", "", err -+ } -+ } else { -+ var id []byte -+ if err := unmarshal(attribute.Value.Bytes, &id); err != nil { -+ return "", "", err -+ } -+ value = hex.EncodeToString(id) -+ } -+ -+ return key, value, nil -+} -+ -+// Decode extracts a certificate and private key from pfxData. This function -+// assumes that there is only one certificate and only one private key in the -+// pfxData; if there are more use ToPEM instead. -+func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) { -+ encodedPassword, err := bmpString(password) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ if len(bags) != 2 { -+ err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU") -+ return -+ } -+ -+ for _, bag := range bags { -+ switch { -+ case bag.Id.Equal(oidCertBag): -+ if certificate != nil { -+ err = errors.New("pkcs12: expected exactly one certificate bag") -+ } -+ -+ certsData, err := decodeCertBag(bag.Value.Bytes) -+ if err != nil { -+ return nil, nil, err -+ } -+ certs, err := x509.ParseCertificates(certsData) -+ if err != nil { -+ return nil, nil, err -+ } -+ if len(certs) != 1 { -+ err = errors.New("pkcs12: expected exactly one certificate in the certBag") -+ return nil, nil, err -+ } -+ certificate = certs[0] -+ -+ case bag.Id.Equal(oidPKCS8ShroundedKeyBag): -+ if privateKey != nil { -+ err = errors.New("pkcs12: expected exactly one key bag") -+ return nil, nil, err -+ } -+ -+ if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { -+ return nil, nil, err -+ } -+ } -+ } -+ -+ if certificate == nil { -+ return nil, nil, errors.New("pkcs12: certificate missing") -+ } -+ if privateKey == nil { -+ return nil, nil, errors.New("pkcs12: private key missing") -+ } -+ -+ return -+} -+ -+func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) { -+ pfx := new(pfxPdu) -+ if err := unmarshal(p12Data, pfx); err != nil { -+ return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error()) -+ } -+ -+ if pfx.Version != 3 { -+ return nil, nil, NotImplementedError("can only decode v3 PFX PDU's") -+ } -+ -+ if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) { -+ return nil, nil, NotImplementedError("only password-protected PFX is implemented") -+ } -+ -+ // unmarshal the explicit bytes in the content for type 'data' -+ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil { -+ return nil, nil, err -+ } -+ -+ if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 { -+ return nil, nil, errors.New("pkcs12: no MAC in data") -+ } -+ -+ if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil { -+ if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 { -+ // some implementations use an empty byte array -+ // for the empty string password try one more -+ // time with empty-empty password -+ password = nil -+ err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password) -+ } -+ if err != nil { -+ return nil, nil, err -+ } -+ } -+ -+ var authenticatedSafe []contentInfo -+ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil { -+ return nil, nil, err -+ } -+ -+ if len(authenticatedSafe) != 2 { -+ return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe") -+ } -+ -+ for _, ci := range authenticatedSafe { -+ var data []byte -+ -+ switch { -+ case ci.ContentType.Equal(oidDataContentType): -+ if err := unmarshal(ci.Content.Bytes, &data); err != nil { -+ return nil, nil, err -+ } -+ case ci.ContentType.Equal(oidEncryptedDataContentType): -+ var encryptedData encryptedData -+ if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil { -+ return nil, nil, err -+ } -+ if encryptedData.Version != 0 { -+ return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported") -+ } -+ if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil { -+ return nil, nil, err -+ } -+ default: -+ return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe") -+ } -+ -+ var safeContents []safeBag -+ if err := unmarshal(data, &safeContents); err != nil { -+ return nil, nil, err -+ } -+ bags = append(bags, safeContents...) -+ } -+ -+ return bags, password, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go -new file mode 100644 -index 00000000000000..68476a822fbc7a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/pkcs12_test.go -@@ -0,0 +1,141 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "crypto/rsa" -+ "crypto/tls" -+ "encoding/base64" -+ "encoding/pem" -+ "testing" -+) -+ -+func TestPfx(t *testing.T) { -+ for commonName, base64P12 := range testdata { -+ p12, _ := base64.StdEncoding.DecodeString(base64P12) -+ -+ priv, cert, err := Decode(p12, "") -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if err := priv.(*rsa.PrivateKey).Validate(); err != nil { -+ t.Errorf("error while validating private key: %v", err) -+ } -+ -+ if cert.Subject.CommonName != commonName { -+ t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName) -+ } -+ } -+} -+ -+func TestPEM(t *testing.T) { -+ for commonName, base64P12 := range testdata { -+ p12, _ := base64.StdEncoding.DecodeString(base64P12) -+ -+ blocks, err := ToPEM(p12, "") -+ if err != nil { -+ t.Fatalf("error while converting to PEM: %s", err) -+ } -+ -+ var pemData []byte -+ for _, b := range blocks { -+ pemData = append(pemData, pem.EncodeToMemory(b)...) -+ } -+ -+ cert, err := tls.X509KeyPair(pemData, pemData) -+ if err != nil { -+ t.Errorf("err while converting to key pair: %v", err) -+ } -+ config := tls.Config{ -+ Certificates: []tls.Certificate{cert}, -+ } -+ config.BuildNameToCertificate() -+ -+ if _, exists := config.NameToCertificate[commonName]; !exists { -+ t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate) -+ } -+ } -+} -+ -+func ExampleToPEM() { -+ p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`) -+ -+ blocks, err := ToPEM(p12, "password") -+ if err != nil { -+ panic(err) -+ } -+ -+ var pemData []byte -+ for _, b := range blocks { -+ pemData = append(pemData, pem.EncodeToMemory(b)...) -+ } -+ -+ // then use PEM data for tls to construct tls certificate: -+ cert, err := tls.X509KeyPair(pemData, pemData) -+ if err != nil { -+ panic(err) -+ } -+ -+ config := &tls.Config{ -+ Certificates: []tls.Certificate{cert}, -+ } -+ -+ _ = config -+} -+ -+var testdata = map[string]string{ -+ // 'null' password test case -+ "Windows Azure Tools": `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`, -+ // Windows IAS PEAP & LDAPS certificates test case -+ // Unknown OID 1.3.6.1.4.1.311.17.2 should be dropped -+ "Windows IAS PEAP & LDAPS certificates": `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`, -+ // empty string password test case -+ "testing@example.com": `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 -+HQ8CAggA`, -+} -diff --git a/ms_mod/golang.org/x/crypto/pkcs12/safebags.go b/ms_mod/golang.org/x/crypto/pkcs12/safebags.go -new file mode 100644 -index 00000000000000..def1f7b98d7de4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/pkcs12/safebags.go -@@ -0,0 +1,57 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pkcs12 -+ -+import ( -+ "crypto/x509" -+ "encoding/asn1" -+ "errors" -+) -+ -+var ( -+ // see https://tools.ietf.org/html/rfc7292#appendix-D -+ oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1}) -+ oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2}) -+ oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3}) -+) -+ -+type certBag struct { -+ Id asn1.ObjectIdentifier -+ Data []byte `asn1:"tag:0,explicit"` -+} -+ -+func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) { -+ pkinfo := new(encryptedPrivateKeyInfo) -+ if err = unmarshal(asn1Data, pkinfo); err != nil { -+ return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error()) -+ } -+ -+ pkData, err := pbDecrypt(pkinfo, password) -+ if err != nil { -+ return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error()) -+ } -+ -+ ret := new(asn1.RawValue) -+ if err = unmarshal(pkData, ret); err != nil { -+ return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error()) -+ } -+ -+ if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil { -+ return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()) -+ } -+ -+ return privateKey, nil -+} -+ -+func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) { -+ bag := new(certBag) -+ if err := unmarshal(asn1Data, bag); err != nil { -+ return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error()) -+ } -+ if !bag.Id.Equal(oidCertTypeX509Certificate) { -+ return nil, NotImplementedError("only X509 certificates are supported") -+ } -+ return bag.Data, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go b/ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go -new file mode 100644 -index 00000000000000..dd975a32c988a1 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/poly1305/poly1305_compat.go -@@ -0,0 +1,91 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package poly1305 implements Poly1305 one-time message authentication code as -+// specified in https://cr.yp.to/mac/poly1305-20050329.pdf. -+// -+// Poly1305 is a fast, one-time authentication function. It is infeasible for an -+// attacker to generate an authenticator for a message without the key. However, a -+// key must only be used for a single message. Authenticating two different -+// messages with the same key allows an attacker to forge authenticators for other -+// messages with the same key. -+// -+// Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was -+// used with a fixed key in order to generate one-time keys from an nonce. -+// However, in this package AES isn't used and the one-time key is specified -+// directly. -+// -+// Deprecated: Poly1305 as implemented by this package is a cryptographic -+// building block that is not safe for general purpose use. -+// For encryption, use the full ChaCha20-Poly1305 construction implemented by -+// golang.org/x/crypto/chacha20poly1305. For authentication, use a general -+// purpose MAC such as HMAC implemented by crypto/hmac. -+package poly1305 // import "golang.org/x/crypto/poly1305" -+ -+import "golang.org/x/crypto/internal/poly1305" -+ -+// TagSize is the size, in bytes, of a poly1305 authenticator. -+// -+// For use with golang.org/x/crypto/chacha20poly1305, chacha20poly1305.Overhead -+// can be used instead. -+const TagSize = 16 -+ -+// Sum generates an authenticator for msg using a one-time key and puts the -+// 16-byte result into out. Authenticating two different messages with the same -+// key allows an attacker to forge messages at will. -+func Sum(out *[16]byte, m []byte, key *[32]byte) { -+ poly1305.Sum(out, m, key) -+} -+ -+// Verify returns true if mac is a valid authenticator for m with the given key. -+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { -+ return poly1305.Verify(mac, m, key) -+} -+ -+// New returns a new MAC computing an authentication -+// tag of all data written to it with the given key. -+// This allows writing the message progressively instead -+// of passing it as a single slice. Common users should use -+// the Sum function instead. -+// -+// The key must be unique for each message, as authenticating -+// two different messages with the same key allows an attacker -+// to forge messages at will. -+func New(key *[32]byte) *MAC { -+ return &MAC{mac: poly1305.New(key)} -+} -+ -+// MAC is an io.Writer computing an authentication tag -+// of the data written to it. -+// -+// MAC cannot be used like common hash.Hash implementations, -+// because using a poly1305 key twice breaks its security. -+// Therefore writing data to a running MAC after calling -+// Sum or Verify causes it to panic. -+type MAC struct { -+ mac *poly1305.MAC -+} -+ -+// Size returns the number of bytes Sum will return. -+func (h *MAC) Size() int { return TagSize } -+ -+// Write adds more data to the running message authentication code. -+// It never returns an error. -+// -+// It must not be called after the first call of Sum or Verify. -+func (h *MAC) Write(p []byte) (n int, err error) { -+ return h.mac.Write(p) -+} -+ -+// Sum computes the authenticator of all data written to the -+// message authentication code. -+func (h *MAC) Sum(b []byte) []byte { -+ return h.mac.Sum(b) -+} -+ -+// Verify returns whether the authenticator of all data written to -+// the message authentication code matches the expected value. -+func (h *MAC) Verify(expected []byte) bool { -+ return h.mac.Verify(expected) -+} -diff --git a/ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go -new file mode 100644 -index 00000000000000..cf3eeb158a9c60 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160.go -@@ -0,0 +1,124 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package ripemd160 implements the RIPEMD-160 hash algorithm. -+// -+// Deprecated: RIPEMD-160 is a legacy hash and should not be used for new -+// applications. Also, this package does not and will not provide an optimized -+// implementation. Instead, use a modern hash like SHA-256 (from crypto/sha256). -+package ripemd160 // import "golang.org/x/crypto/ripemd160" -+ -+// RIPEMD-160 is designed by Hans Dobbertin, Antoon Bosselaers, and Bart -+// Preneel with specifications available at: -+// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. -+ -+import ( -+ "crypto" -+ "hash" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.RIPEMD160, New) -+} -+ -+// The size of the checksum in bytes. -+const Size = 20 -+ -+// The block size of the hash algorithm in bytes. -+const BlockSize = 64 -+ -+const ( -+ _s0 = 0x67452301 -+ _s1 = 0xefcdab89 -+ _s2 = 0x98badcfe -+ _s3 = 0x10325476 -+ _s4 = 0xc3d2e1f0 -+) -+ -+// digest represents the partial evaluation of a checksum. -+type digest struct { -+ s [5]uint32 // running context -+ x [BlockSize]byte // temporary buffer -+ nx int // index into x -+ tc uint64 // total count of bytes processed -+} -+ -+func (d *digest) Reset() { -+ d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 -+ d.nx = 0 -+ d.tc = 0 -+} -+ -+// New returns a new hash.Hash computing the checksum. -+func New() hash.Hash { -+ result := new(digest) -+ result.Reset() -+ return result -+} -+ -+func (d *digest) Size() int { return Size } -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Write(p []byte) (nn int, err error) { -+ nn = len(p) -+ d.tc += uint64(nn) -+ if d.nx > 0 { -+ n := len(p) -+ if n > BlockSize-d.nx { -+ n = BlockSize - d.nx -+ } -+ for i := 0; i < n; i++ { -+ d.x[d.nx+i] = p[i] -+ } -+ d.nx += n -+ if d.nx == BlockSize { -+ _Block(d, d.x[0:]) -+ d.nx = 0 -+ } -+ p = p[n:] -+ } -+ n := _Block(d, p) -+ p = p[n:] -+ if len(p) > 0 { -+ d.nx = copy(d.x[:], p) -+ } -+ return -+} -+ -+func (d0 *digest) Sum(in []byte) []byte { -+ // Make a copy of d0 so that caller can keep writing and summing. -+ d := *d0 -+ -+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. -+ tc := d.tc -+ var tmp [64]byte -+ tmp[0] = 0x80 -+ if tc%64 < 56 { -+ d.Write(tmp[0 : 56-tc%64]) -+ } else { -+ d.Write(tmp[0 : 64+56-tc%64]) -+ } -+ -+ // Length in bits. -+ tc <<= 3 -+ for i := uint(0); i < 8; i++ { -+ tmp[i] = byte(tc >> (8 * i)) -+ } -+ d.Write(tmp[0:8]) -+ -+ if d.nx != 0 { -+ panic("d.nx != 0") -+ } -+ -+ var digest [Size]byte -+ for i, s := range d.s { -+ digest[i*4] = byte(s) -+ digest[i*4+1] = byte(s >> 8) -+ digest[i*4+2] = byte(s >> 16) -+ digest[i*4+3] = byte(s >> 24) -+ } -+ -+ return append(in, digest[:]...) -+} -diff --git a/ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go -new file mode 100644 -index 00000000000000..a1fbffdd5fcb5d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160_test.go -@@ -0,0 +1,72 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ripemd160 -+ -+// Test vectors are from: -+// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html -+ -+import ( -+ "fmt" -+ "io" -+ "testing" -+) -+ -+type mdTest struct { -+ out string -+ in string -+} -+ -+var vectors = [...]mdTest{ -+ {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""}, -+ {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"}, -+ {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"}, -+ {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"}, -+ {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"}, -+ {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, -+ {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, -+ {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}, -+} -+ -+func TestVectors(t *testing.T) { -+ for i := 0; i < len(vectors); i++ { -+ tv := vectors[i] -+ md := New() -+ for j := 0; j < 3; j++ { -+ if j < 2 { -+ io.WriteString(md, tv.in) -+ } else { -+ io.WriteString(md, tv.in[0:len(tv.in)/2]) -+ md.Sum(nil) -+ io.WriteString(md, tv.in[len(tv.in)/2:]) -+ } -+ s := fmt.Sprintf("%x", md.Sum(nil)) -+ if s != tv.out { -+ t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out) -+ } -+ md.Reset() -+ } -+ } -+} -+ -+func millionA() string { -+ md := New() -+ for i := 0; i < 100000; i++ { -+ io.WriteString(md, "aaaaaaaaaa") -+ } -+ return fmt.Sprintf("%x", md.Sum(nil)) -+} -+ -+func TestMillionA(t *testing.T) { -+ const out = "52783243c1697bdbe16d37f97f68f08325dc1528" -+ if s := millionA(); s != out { -+ t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out) -+ } -+} -+ -+func BenchmarkMillionA(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ millionA() -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go -new file mode 100644 -index 00000000000000..e0edc02f0f30f3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ripemd160/ripemd160block.go -@@ -0,0 +1,165 @@ -+// Copyright 2010 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// RIPEMD-160 block step. -+// In its own file so that a faster assembly or C version -+// can be substituted easily. -+ -+package ripemd160 -+ -+import ( -+ "math/bits" -+) -+ -+// work buffer indices and roll amounts for one line -+var _n = [80]uint{ -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, -+ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, -+ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, -+ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, -+} -+ -+var _r = [80]uint{ -+ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, -+ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, -+ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, -+ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, -+ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, -+} -+ -+// same for the other parallel one -+var n_ = [80]uint{ -+ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, -+ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, -+ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, -+ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, -+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, -+} -+ -+var r_ = [80]uint{ -+ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, -+ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, -+ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, -+ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, -+ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, -+} -+ -+func _Block(md *digest, p []byte) int { -+ n := 0 -+ var x [16]uint32 -+ var alpha, beta uint32 -+ for len(p) >= BlockSize { -+ a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4] -+ aa, bb, cc, dd, ee := a, b, c, d, e -+ j := 0 -+ for i := 0; i < 16; i++ { -+ x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 -+ j += 4 -+ } -+ -+ // round 1 -+ i := 0 -+ for i < 16 { -+ alpha = a + (b ^ c ^ d) + x[_n[i]] -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 2 -+ for i < 32 { -+ alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 3 -+ for i < 48 { -+ alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 4 -+ for i < 64 { -+ alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // round 5 -+ for i < 80 { -+ alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e -+ s := int(_r[i]) -+ alpha = bits.RotateLeft32(alpha, s) + e -+ beta = bits.RotateLeft32(c, 10) -+ a, b, c, d, e = e, alpha, b, beta, d -+ -+ // parallel line -+ alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] -+ s = int(r_[i]) -+ alpha = bits.RotateLeft32(alpha, s) + ee -+ beta = bits.RotateLeft32(cc, 10) -+ aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd -+ -+ i++ -+ } -+ -+ // combine results -+ dd += c + md.s[1] -+ md.s[1] = md.s[2] + d + ee -+ md.s[2] = md.s[3] + e + aa -+ md.s[3] = md.s[4] + a + bb -+ md.s[4] = md.s[0] + b + cc -+ md.s[0] = dd -+ -+ p = p[BlockSize:] -+ n += BlockSize -+ } -+ return n -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go -new file mode 100644 -index 00000000000000..3fd05b27516987 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/hsalsa20.go -@@ -0,0 +1,146 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package salsa provides low-level access to functions in the Salsa family. -+package salsa // import "golang.org/x/crypto/salsa20/salsa" -+ -+import "math/bits" -+ -+// Sigma is the Salsa20 constant for 256-bit keys. -+var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} -+ -+// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte -+// key k, and 16-byte constant c, and puts the result into the 32-byte array -+// out. -+func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { -+ x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 -+ x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 -+ x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 -+ x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 -+ x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 -+ x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 -+ x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 -+ x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 -+ x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 -+ x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 -+ x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 -+ x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 -+ x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 -+ x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 -+ x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 -+ x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 -+ -+ for i := 0; i < 20; i += 2 { -+ u := x0 + x12 -+ x4 ^= bits.RotateLeft32(u, 7) -+ u = x4 + x0 -+ x8 ^= bits.RotateLeft32(u, 9) -+ u = x8 + x4 -+ x12 ^= bits.RotateLeft32(u, 13) -+ u = x12 + x8 -+ x0 ^= bits.RotateLeft32(u, 18) -+ -+ u = x5 + x1 -+ x9 ^= bits.RotateLeft32(u, 7) -+ u = x9 + x5 -+ x13 ^= bits.RotateLeft32(u, 9) -+ u = x13 + x9 -+ x1 ^= bits.RotateLeft32(u, 13) -+ u = x1 + x13 -+ x5 ^= bits.RotateLeft32(u, 18) -+ -+ u = x10 + x6 -+ x14 ^= bits.RotateLeft32(u, 7) -+ u = x14 + x10 -+ x2 ^= bits.RotateLeft32(u, 9) -+ u = x2 + x14 -+ x6 ^= bits.RotateLeft32(u, 13) -+ u = x6 + x2 -+ x10 ^= bits.RotateLeft32(u, 18) -+ -+ u = x15 + x11 -+ x3 ^= bits.RotateLeft32(u, 7) -+ u = x3 + x15 -+ x7 ^= bits.RotateLeft32(u, 9) -+ u = x7 + x3 -+ x11 ^= bits.RotateLeft32(u, 13) -+ u = x11 + x7 -+ x15 ^= bits.RotateLeft32(u, 18) -+ -+ u = x0 + x3 -+ x1 ^= bits.RotateLeft32(u, 7) -+ u = x1 + x0 -+ x2 ^= bits.RotateLeft32(u, 9) -+ u = x2 + x1 -+ x3 ^= bits.RotateLeft32(u, 13) -+ u = x3 + x2 -+ x0 ^= bits.RotateLeft32(u, 18) -+ -+ u = x5 + x4 -+ x6 ^= bits.RotateLeft32(u, 7) -+ u = x6 + x5 -+ x7 ^= bits.RotateLeft32(u, 9) -+ u = x7 + x6 -+ x4 ^= bits.RotateLeft32(u, 13) -+ u = x4 + x7 -+ x5 ^= bits.RotateLeft32(u, 18) -+ -+ u = x10 + x9 -+ x11 ^= bits.RotateLeft32(u, 7) -+ u = x11 + x10 -+ x8 ^= bits.RotateLeft32(u, 9) -+ u = x8 + x11 -+ x9 ^= bits.RotateLeft32(u, 13) -+ u = x9 + x8 -+ x10 ^= bits.RotateLeft32(u, 18) -+ -+ u = x15 + x14 -+ x12 ^= bits.RotateLeft32(u, 7) -+ u = x12 + x15 -+ x13 ^= bits.RotateLeft32(u, 9) -+ u = x13 + x12 -+ x14 ^= bits.RotateLeft32(u, 13) -+ u = x14 + x13 -+ x15 ^= bits.RotateLeft32(u, 18) -+ } -+ out[0] = byte(x0) -+ out[1] = byte(x0 >> 8) -+ out[2] = byte(x0 >> 16) -+ out[3] = byte(x0 >> 24) -+ -+ out[4] = byte(x5) -+ out[5] = byte(x5 >> 8) -+ out[6] = byte(x5 >> 16) -+ out[7] = byte(x5 >> 24) -+ -+ out[8] = byte(x10) -+ out[9] = byte(x10 >> 8) -+ out[10] = byte(x10 >> 16) -+ out[11] = byte(x10 >> 24) -+ -+ out[12] = byte(x15) -+ out[13] = byte(x15 >> 8) -+ out[14] = byte(x15 >> 16) -+ out[15] = byte(x15 >> 24) -+ -+ out[16] = byte(x6) -+ out[17] = byte(x6 >> 8) -+ out[18] = byte(x6 >> 16) -+ out[19] = byte(x6 >> 24) -+ -+ out[20] = byte(x7) -+ out[21] = byte(x7 >> 8) -+ out[22] = byte(x7 >> 16) -+ out[23] = byte(x7 >> 24) -+ -+ out[24] = byte(x8) -+ out[25] = byte(x8 >> 8) -+ out[26] = byte(x8 >> 16) -+ out[27] = byte(x8 >> 24) -+ -+ out[28] = byte(x9) -+ out[29] = byte(x9 >> 8) -+ out[30] = byte(x9 >> 16) -+ out[31] = byte(x9 >> 24) -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go -new file mode 100644 -index 00000000000000..7ec7bb39bc0494 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa208.go -@@ -0,0 +1,201 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package salsa -+ -+import "math/bits" -+ -+// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts -+// the result into the 64-byte array out. The input and output may be the same array. -+func Core208(out *[64]byte, in *[64]byte) { -+ j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 -+ j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 -+ j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 -+ j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 -+ j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 -+ j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 -+ j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 -+ j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 -+ j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 -+ j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 -+ j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 -+ j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 -+ j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 -+ j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 -+ j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 -+ j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 -+ -+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 -+ x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 -+ -+ for i := 0; i < 8; i += 2 { -+ u := x0 + x12 -+ x4 ^= bits.RotateLeft32(u, 7) -+ u = x4 + x0 -+ x8 ^= bits.RotateLeft32(u, 9) -+ u = x8 + x4 -+ x12 ^= bits.RotateLeft32(u, 13) -+ u = x12 + x8 -+ x0 ^= bits.RotateLeft32(u, 18) -+ -+ u = x5 + x1 -+ x9 ^= bits.RotateLeft32(u, 7) -+ u = x9 + x5 -+ x13 ^= bits.RotateLeft32(u, 9) -+ u = x13 + x9 -+ x1 ^= bits.RotateLeft32(u, 13) -+ u = x1 + x13 -+ x5 ^= bits.RotateLeft32(u, 18) -+ -+ u = x10 + x6 -+ x14 ^= bits.RotateLeft32(u, 7) -+ u = x14 + x10 -+ x2 ^= bits.RotateLeft32(u, 9) -+ u = x2 + x14 -+ x6 ^= bits.RotateLeft32(u, 13) -+ u = x6 + x2 -+ x10 ^= bits.RotateLeft32(u, 18) -+ -+ u = x15 + x11 -+ x3 ^= bits.RotateLeft32(u, 7) -+ u = x3 + x15 -+ x7 ^= bits.RotateLeft32(u, 9) -+ u = x7 + x3 -+ x11 ^= bits.RotateLeft32(u, 13) -+ u = x11 + x7 -+ x15 ^= bits.RotateLeft32(u, 18) -+ -+ u = x0 + x3 -+ x1 ^= bits.RotateLeft32(u, 7) -+ u = x1 + x0 -+ x2 ^= bits.RotateLeft32(u, 9) -+ u = x2 + x1 -+ x3 ^= bits.RotateLeft32(u, 13) -+ u = x3 + x2 -+ x0 ^= bits.RotateLeft32(u, 18) -+ -+ u = x5 + x4 -+ x6 ^= bits.RotateLeft32(u, 7) -+ u = x6 + x5 -+ x7 ^= bits.RotateLeft32(u, 9) -+ u = x7 + x6 -+ x4 ^= bits.RotateLeft32(u, 13) -+ u = x4 + x7 -+ x5 ^= bits.RotateLeft32(u, 18) -+ -+ u = x10 + x9 -+ x11 ^= bits.RotateLeft32(u, 7) -+ u = x11 + x10 -+ x8 ^= bits.RotateLeft32(u, 9) -+ u = x8 + x11 -+ x9 ^= bits.RotateLeft32(u, 13) -+ u = x9 + x8 -+ x10 ^= bits.RotateLeft32(u, 18) -+ -+ u = x15 + x14 -+ x12 ^= bits.RotateLeft32(u, 7) -+ u = x12 + x15 -+ x13 ^= bits.RotateLeft32(u, 9) -+ u = x13 + x12 -+ x14 ^= bits.RotateLeft32(u, 13) -+ u = x14 + x13 -+ x15 ^= bits.RotateLeft32(u, 18) -+ } -+ x0 += j0 -+ x1 += j1 -+ x2 += j2 -+ x3 += j3 -+ x4 += j4 -+ x5 += j5 -+ x6 += j6 -+ x7 += j7 -+ x8 += j8 -+ x9 += j9 -+ x10 += j10 -+ x11 += j11 -+ x12 += j12 -+ x13 += j13 -+ x14 += j14 -+ x15 += j15 -+ -+ out[0] = byte(x0) -+ out[1] = byte(x0 >> 8) -+ out[2] = byte(x0 >> 16) -+ out[3] = byte(x0 >> 24) -+ -+ out[4] = byte(x1) -+ out[5] = byte(x1 >> 8) -+ out[6] = byte(x1 >> 16) -+ out[7] = byte(x1 >> 24) -+ -+ out[8] = byte(x2) -+ out[9] = byte(x2 >> 8) -+ out[10] = byte(x2 >> 16) -+ out[11] = byte(x2 >> 24) -+ -+ out[12] = byte(x3) -+ out[13] = byte(x3 >> 8) -+ out[14] = byte(x3 >> 16) -+ out[15] = byte(x3 >> 24) -+ -+ out[16] = byte(x4) -+ out[17] = byte(x4 >> 8) -+ out[18] = byte(x4 >> 16) -+ out[19] = byte(x4 >> 24) -+ -+ out[20] = byte(x5) -+ out[21] = byte(x5 >> 8) -+ out[22] = byte(x5 >> 16) -+ out[23] = byte(x5 >> 24) -+ -+ out[24] = byte(x6) -+ out[25] = byte(x6 >> 8) -+ out[26] = byte(x6 >> 16) -+ out[27] = byte(x6 >> 24) -+ -+ out[28] = byte(x7) -+ out[29] = byte(x7 >> 8) -+ out[30] = byte(x7 >> 16) -+ out[31] = byte(x7 >> 24) -+ -+ out[32] = byte(x8) -+ out[33] = byte(x8 >> 8) -+ out[34] = byte(x8 >> 16) -+ out[35] = byte(x8 >> 24) -+ -+ out[36] = byte(x9) -+ out[37] = byte(x9 >> 8) -+ out[38] = byte(x9 >> 16) -+ out[39] = byte(x9 >> 24) -+ -+ out[40] = byte(x10) -+ out[41] = byte(x10 >> 8) -+ out[42] = byte(x10 >> 16) -+ out[43] = byte(x10 >> 24) -+ -+ out[44] = byte(x11) -+ out[45] = byte(x11 >> 8) -+ out[46] = byte(x11 >> 16) -+ out[47] = byte(x11 >> 24) -+ -+ out[48] = byte(x12) -+ out[49] = byte(x12 >> 8) -+ out[50] = byte(x12 >> 16) -+ out[51] = byte(x12 >> 24) -+ -+ out[52] = byte(x13) -+ out[53] = byte(x13 >> 8) -+ out[54] = byte(x13 >> 16) -+ out[55] = byte(x13 >> 24) -+ -+ out[56] = byte(x14) -+ out[57] = byte(x14 >> 8) -+ out[58] = byte(x14 >> 16) -+ out[59] = byte(x14 >> 24) -+ -+ out[60] = byte(x15) -+ out[61] = byte(x15 >> 8) -+ out[62] = byte(x15 >> 16) -+ out[63] = byte(x15 >> 24) -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go -new file mode 100644 -index 00000000000000..c400dfcf7bce5c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go -@@ -0,0 +1,24 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+package salsa -+ -+//go:noescape -+ -+// salsa2020XORKeyStream is implemented in salsa20_amd64.s. -+func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) -+ -+// XORKeyStream crypts bytes from in to out using the given key and counters. -+// In and out must overlap entirely or not at all. Counter -+// contains the raw salsa20 counter bytes (both nonce and block counter). -+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { -+ if len(in) == 0 { -+ return -+ } -+ _ = out[len(in)-1] -+ salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s -new file mode 100644 -index 00000000000000..c0892772045a25 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s -@@ -0,0 +1,881 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+// This code was translated into a form compatible with 6a from the public -+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html -+ -+// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) -+// This needs up to 64 bytes at 360(R12); hence the non-obvious frame size. -+TEXT Β·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment -+ MOVQ out+0(FP),DI -+ MOVQ in+8(FP),SI -+ MOVQ n+16(FP),DX -+ MOVQ nonce+24(FP),CX -+ MOVQ key+32(FP),R8 -+ -+ MOVQ SP,R12 -+ ADDQ $31, R12 -+ ANDQ $~31, R12 -+ -+ MOVQ DX,R9 -+ MOVQ CX,DX -+ MOVQ R8,R10 -+ CMPQ R9,$0 -+ JBE DONE -+ START: -+ MOVL 20(R10),CX -+ MOVL 0(R10),R8 -+ MOVL 0(DX),AX -+ MOVL 16(R10),R11 -+ MOVL CX,0(R12) -+ MOVL R8, 4 (R12) -+ MOVL AX, 8 (R12) -+ MOVL R11, 12 (R12) -+ MOVL 8(DX),CX -+ MOVL 24(R10),R8 -+ MOVL 4(R10),AX -+ MOVL 4(DX),R11 -+ MOVL CX,16(R12) -+ MOVL R8, 20 (R12) -+ MOVL AX, 24 (R12) -+ MOVL R11, 28 (R12) -+ MOVL 12(DX),CX -+ MOVL 12(R10),DX -+ MOVL 28(R10),R8 -+ MOVL 8(R10),AX -+ MOVL DX,32(R12) -+ MOVL CX, 36 (R12) -+ MOVL R8, 40 (R12) -+ MOVL AX, 44 (R12) -+ MOVQ $1634760805,DX -+ MOVQ $857760878,CX -+ MOVQ $2036477234,R8 -+ MOVQ $1797285236,AX -+ MOVL DX,48(R12) -+ MOVL CX, 52 (R12) -+ MOVL R8, 56 (R12) -+ MOVL AX, 60 (R12) -+ CMPQ R9,$256 -+ JB BYTESBETWEEN1AND255 -+ MOVOA 48(R12),X0 -+ PSHUFL $0X55,X0,X1 -+ PSHUFL $0XAA,X0,X2 -+ PSHUFL $0XFF,X0,X3 -+ PSHUFL $0X00,X0,X0 -+ MOVOA X1,64(R12) -+ MOVOA X2,80(R12) -+ MOVOA X3,96(R12) -+ MOVOA X0,112(R12) -+ MOVOA 0(R12),X0 -+ PSHUFL $0XAA,X0,X1 -+ PSHUFL $0XFF,X0,X2 -+ PSHUFL $0X00,X0,X3 -+ PSHUFL $0X55,X0,X0 -+ MOVOA X1,128(R12) -+ MOVOA X2,144(R12) -+ MOVOA X3,160(R12) -+ MOVOA X0,176(R12) -+ MOVOA 16(R12),X0 -+ PSHUFL $0XFF,X0,X1 -+ PSHUFL $0X55,X0,X2 -+ PSHUFL $0XAA,X0,X0 -+ MOVOA X1,192(R12) -+ MOVOA X2,208(R12) -+ MOVOA X0,224(R12) -+ MOVOA 32(R12),X0 -+ PSHUFL $0X00,X0,X1 -+ PSHUFL $0XAA,X0,X2 -+ PSHUFL $0XFF,X0,X0 -+ MOVOA X1,240(R12) -+ MOVOA X2,256(R12) -+ MOVOA X0,272(R12) -+ BYTESATLEAST256: -+ MOVL 16(R12),DX -+ MOVL 36 (R12),CX -+ MOVL DX,288(R12) -+ MOVL CX,304(R12) -+ SHLQ $32,CX -+ ADDQ CX,DX -+ ADDQ $1,DX -+ MOVQ DX,CX -+ SHRQ $32,CX -+ MOVL DX, 292 (R12) -+ MOVL CX, 308 (R12) -+ ADDQ $1,DX -+ MOVQ DX,CX -+ SHRQ $32,CX -+ MOVL DX, 296 (R12) -+ MOVL CX, 312 (R12) -+ ADDQ $1,DX -+ MOVQ DX,CX -+ SHRQ $32,CX -+ MOVL DX, 300 (R12) -+ MOVL CX, 316 (R12) -+ ADDQ $1,DX -+ MOVQ DX,CX -+ SHRQ $32,CX -+ MOVL DX,16(R12) -+ MOVL CX, 36 (R12) -+ MOVQ R9,352(R12) -+ MOVQ $20,DX -+ MOVOA 64(R12),X0 -+ MOVOA 80(R12),X1 -+ MOVOA 96(R12),X2 -+ MOVOA 256(R12),X3 -+ MOVOA 272(R12),X4 -+ MOVOA 128(R12),X5 -+ MOVOA 144(R12),X6 -+ MOVOA 176(R12),X7 -+ MOVOA 192(R12),X8 -+ MOVOA 208(R12),X9 -+ MOVOA 224(R12),X10 -+ MOVOA 304(R12),X11 -+ MOVOA 112(R12),X12 -+ MOVOA 160(R12),X13 -+ MOVOA 240(R12),X14 -+ MOVOA 288(R12),X15 -+ MAINLOOP1: -+ MOVOA X1,320(R12) -+ MOVOA X2,336(R12) -+ MOVOA X13,X1 -+ PADDL X12,X1 -+ MOVOA X1,X2 -+ PSLLL $7,X1 -+ PXOR X1,X14 -+ PSRLL $25,X2 -+ PXOR X2,X14 -+ MOVOA X7,X1 -+ PADDL X0,X1 -+ MOVOA X1,X2 -+ PSLLL $7,X1 -+ PXOR X1,X11 -+ PSRLL $25,X2 -+ PXOR X2,X11 -+ MOVOA X12,X1 -+ PADDL X14,X1 -+ MOVOA X1,X2 -+ PSLLL $9,X1 -+ PXOR X1,X15 -+ PSRLL $23,X2 -+ PXOR X2,X15 -+ MOVOA X0,X1 -+ PADDL X11,X1 -+ MOVOA X1,X2 -+ PSLLL $9,X1 -+ PXOR X1,X9 -+ PSRLL $23,X2 -+ PXOR X2,X9 -+ MOVOA X14,X1 -+ PADDL X15,X1 -+ MOVOA X1,X2 -+ PSLLL $13,X1 -+ PXOR X1,X13 -+ PSRLL $19,X2 -+ PXOR X2,X13 -+ MOVOA X11,X1 -+ PADDL X9,X1 -+ MOVOA X1,X2 -+ PSLLL $13,X1 -+ PXOR X1,X7 -+ PSRLL $19,X2 -+ PXOR X2,X7 -+ MOVOA X15,X1 -+ PADDL X13,X1 -+ MOVOA X1,X2 -+ PSLLL $18,X1 -+ PXOR X1,X12 -+ PSRLL $14,X2 -+ PXOR X2,X12 -+ MOVOA 320(R12),X1 -+ MOVOA X12,320(R12) -+ MOVOA X9,X2 -+ PADDL X7,X2 -+ MOVOA X2,X12 -+ PSLLL $18,X2 -+ PXOR X2,X0 -+ PSRLL $14,X12 -+ PXOR X12,X0 -+ MOVOA X5,X2 -+ PADDL X1,X2 -+ MOVOA X2,X12 -+ PSLLL $7,X2 -+ PXOR X2,X3 -+ PSRLL $25,X12 -+ PXOR X12,X3 -+ MOVOA 336(R12),X2 -+ MOVOA X0,336(R12) -+ MOVOA X6,X0 -+ PADDL X2,X0 -+ MOVOA X0,X12 -+ PSLLL $7,X0 -+ PXOR X0,X4 -+ PSRLL $25,X12 -+ PXOR X12,X4 -+ MOVOA X1,X0 -+ PADDL X3,X0 -+ MOVOA X0,X12 -+ PSLLL $9,X0 -+ PXOR X0,X10 -+ PSRLL $23,X12 -+ PXOR X12,X10 -+ MOVOA X2,X0 -+ PADDL X4,X0 -+ MOVOA X0,X12 -+ PSLLL $9,X0 -+ PXOR X0,X8 -+ PSRLL $23,X12 -+ PXOR X12,X8 -+ MOVOA X3,X0 -+ PADDL X10,X0 -+ MOVOA X0,X12 -+ PSLLL $13,X0 -+ PXOR X0,X5 -+ PSRLL $19,X12 -+ PXOR X12,X5 -+ MOVOA X4,X0 -+ PADDL X8,X0 -+ MOVOA X0,X12 -+ PSLLL $13,X0 -+ PXOR X0,X6 -+ PSRLL $19,X12 -+ PXOR X12,X6 -+ MOVOA X10,X0 -+ PADDL X5,X0 -+ MOVOA X0,X12 -+ PSLLL $18,X0 -+ PXOR X0,X1 -+ PSRLL $14,X12 -+ PXOR X12,X1 -+ MOVOA 320(R12),X0 -+ MOVOA X1,320(R12) -+ MOVOA X4,X1 -+ PADDL X0,X1 -+ MOVOA X1,X12 -+ PSLLL $7,X1 -+ PXOR X1,X7 -+ PSRLL $25,X12 -+ PXOR X12,X7 -+ MOVOA X8,X1 -+ PADDL X6,X1 -+ MOVOA X1,X12 -+ PSLLL $18,X1 -+ PXOR X1,X2 -+ PSRLL $14,X12 -+ PXOR X12,X2 -+ MOVOA 336(R12),X12 -+ MOVOA X2,336(R12) -+ MOVOA X14,X1 -+ PADDL X12,X1 -+ MOVOA X1,X2 -+ PSLLL $7,X1 -+ PXOR X1,X5 -+ PSRLL $25,X2 -+ PXOR X2,X5 -+ MOVOA X0,X1 -+ PADDL X7,X1 -+ MOVOA X1,X2 -+ PSLLL $9,X1 -+ PXOR X1,X10 -+ PSRLL $23,X2 -+ PXOR X2,X10 -+ MOVOA X12,X1 -+ PADDL X5,X1 -+ MOVOA X1,X2 -+ PSLLL $9,X1 -+ PXOR X1,X8 -+ PSRLL $23,X2 -+ PXOR X2,X8 -+ MOVOA X7,X1 -+ PADDL X10,X1 -+ MOVOA X1,X2 -+ PSLLL $13,X1 -+ PXOR X1,X4 -+ PSRLL $19,X2 -+ PXOR X2,X4 -+ MOVOA X5,X1 -+ PADDL X8,X1 -+ MOVOA X1,X2 -+ PSLLL $13,X1 -+ PXOR X1,X14 -+ PSRLL $19,X2 -+ PXOR X2,X14 -+ MOVOA X10,X1 -+ PADDL X4,X1 -+ MOVOA X1,X2 -+ PSLLL $18,X1 -+ PXOR X1,X0 -+ PSRLL $14,X2 -+ PXOR X2,X0 -+ MOVOA 320(R12),X1 -+ MOVOA X0,320(R12) -+ MOVOA X8,X0 -+ PADDL X14,X0 -+ MOVOA X0,X2 -+ PSLLL $18,X0 -+ PXOR X0,X12 -+ PSRLL $14,X2 -+ PXOR X2,X12 -+ MOVOA X11,X0 -+ PADDL X1,X0 -+ MOVOA X0,X2 -+ PSLLL $7,X0 -+ PXOR X0,X6 -+ PSRLL $25,X2 -+ PXOR X2,X6 -+ MOVOA 336(R12),X2 -+ MOVOA X12,336(R12) -+ MOVOA X3,X0 -+ PADDL X2,X0 -+ MOVOA X0,X12 -+ PSLLL $7,X0 -+ PXOR X0,X13 -+ PSRLL $25,X12 -+ PXOR X12,X13 -+ MOVOA X1,X0 -+ PADDL X6,X0 -+ MOVOA X0,X12 -+ PSLLL $9,X0 -+ PXOR X0,X15 -+ PSRLL $23,X12 -+ PXOR X12,X15 -+ MOVOA X2,X0 -+ PADDL X13,X0 -+ MOVOA X0,X12 -+ PSLLL $9,X0 -+ PXOR X0,X9 -+ PSRLL $23,X12 -+ PXOR X12,X9 -+ MOVOA X6,X0 -+ PADDL X15,X0 -+ MOVOA X0,X12 -+ PSLLL $13,X0 -+ PXOR X0,X11 -+ PSRLL $19,X12 -+ PXOR X12,X11 -+ MOVOA X13,X0 -+ PADDL X9,X0 -+ MOVOA X0,X12 -+ PSLLL $13,X0 -+ PXOR X0,X3 -+ PSRLL $19,X12 -+ PXOR X12,X3 -+ MOVOA X15,X0 -+ PADDL X11,X0 -+ MOVOA X0,X12 -+ PSLLL $18,X0 -+ PXOR X0,X1 -+ PSRLL $14,X12 -+ PXOR X12,X1 -+ MOVOA X9,X0 -+ PADDL X3,X0 -+ MOVOA X0,X12 -+ PSLLL $18,X0 -+ PXOR X0,X2 -+ PSRLL $14,X12 -+ PXOR X12,X2 -+ MOVOA 320(R12),X12 -+ MOVOA 336(R12),X0 -+ SUBQ $2,DX -+ JA MAINLOOP1 -+ PADDL 112(R12),X12 -+ PADDL 176(R12),X7 -+ PADDL 224(R12),X10 -+ PADDL 272(R12),X4 -+ MOVD X12,DX -+ MOVD X7,CX -+ MOVD X10,R8 -+ MOVD X4,R9 -+ PSHUFL $0X39,X12,X12 -+ PSHUFL $0X39,X7,X7 -+ PSHUFL $0X39,X10,X10 -+ PSHUFL $0X39,X4,X4 -+ XORL 0(SI),DX -+ XORL 4(SI),CX -+ XORL 8(SI),R8 -+ XORL 12(SI),R9 -+ MOVL DX,0(DI) -+ MOVL CX,4(DI) -+ MOVL R8,8(DI) -+ MOVL R9,12(DI) -+ MOVD X12,DX -+ MOVD X7,CX -+ MOVD X10,R8 -+ MOVD X4,R9 -+ PSHUFL $0X39,X12,X12 -+ PSHUFL $0X39,X7,X7 -+ PSHUFL $0X39,X10,X10 -+ PSHUFL $0X39,X4,X4 -+ XORL 64(SI),DX -+ XORL 68(SI),CX -+ XORL 72(SI),R8 -+ XORL 76(SI),R9 -+ MOVL DX,64(DI) -+ MOVL CX,68(DI) -+ MOVL R8,72(DI) -+ MOVL R9,76(DI) -+ MOVD X12,DX -+ MOVD X7,CX -+ MOVD X10,R8 -+ MOVD X4,R9 -+ PSHUFL $0X39,X12,X12 -+ PSHUFL $0X39,X7,X7 -+ PSHUFL $0X39,X10,X10 -+ PSHUFL $0X39,X4,X4 -+ XORL 128(SI),DX -+ XORL 132(SI),CX -+ XORL 136(SI),R8 -+ XORL 140(SI),R9 -+ MOVL DX,128(DI) -+ MOVL CX,132(DI) -+ MOVL R8,136(DI) -+ MOVL R9,140(DI) -+ MOVD X12,DX -+ MOVD X7,CX -+ MOVD X10,R8 -+ MOVD X4,R9 -+ XORL 192(SI),DX -+ XORL 196(SI),CX -+ XORL 200(SI),R8 -+ XORL 204(SI),R9 -+ MOVL DX,192(DI) -+ MOVL CX,196(DI) -+ MOVL R8,200(DI) -+ MOVL R9,204(DI) -+ PADDL 240(R12),X14 -+ PADDL 64(R12),X0 -+ PADDL 128(R12),X5 -+ PADDL 192(R12),X8 -+ MOVD X14,DX -+ MOVD X0,CX -+ MOVD X5,R8 -+ MOVD X8,R9 -+ PSHUFL $0X39,X14,X14 -+ PSHUFL $0X39,X0,X0 -+ PSHUFL $0X39,X5,X5 -+ PSHUFL $0X39,X8,X8 -+ XORL 16(SI),DX -+ XORL 20(SI),CX -+ XORL 24(SI),R8 -+ XORL 28(SI),R9 -+ MOVL DX,16(DI) -+ MOVL CX,20(DI) -+ MOVL R8,24(DI) -+ MOVL R9,28(DI) -+ MOVD X14,DX -+ MOVD X0,CX -+ MOVD X5,R8 -+ MOVD X8,R9 -+ PSHUFL $0X39,X14,X14 -+ PSHUFL $0X39,X0,X0 -+ PSHUFL $0X39,X5,X5 -+ PSHUFL $0X39,X8,X8 -+ XORL 80(SI),DX -+ XORL 84(SI),CX -+ XORL 88(SI),R8 -+ XORL 92(SI),R9 -+ MOVL DX,80(DI) -+ MOVL CX,84(DI) -+ MOVL R8,88(DI) -+ MOVL R9,92(DI) -+ MOVD X14,DX -+ MOVD X0,CX -+ MOVD X5,R8 -+ MOVD X8,R9 -+ PSHUFL $0X39,X14,X14 -+ PSHUFL $0X39,X0,X0 -+ PSHUFL $0X39,X5,X5 -+ PSHUFL $0X39,X8,X8 -+ XORL 144(SI),DX -+ XORL 148(SI),CX -+ XORL 152(SI),R8 -+ XORL 156(SI),R9 -+ MOVL DX,144(DI) -+ MOVL CX,148(DI) -+ MOVL R8,152(DI) -+ MOVL R9,156(DI) -+ MOVD X14,DX -+ MOVD X0,CX -+ MOVD X5,R8 -+ MOVD X8,R9 -+ XORL 208(SI),DX -+ XORL 212(SI),CX -+ XORL 216(SI),R8 -+ XORL 220(SI),R9 -+ MOVL DX,208(DI) -+ MOVL CX,212(DI) -+ MOVL R8,216(DI) -+ MOVL R9,220(DI) -+ PADDL 288(R12),X15 -+ PADDL 304(R12),X11 -+ PADDL 80(R12),X1 -+ PADDL 144(R12),X6 -+ MOVD X15,DX -+ MOVD X11,CX -+ MOVD X1,R8 -+ MOVD X6,R9 -+ PSHUFL $0X39,X15,X15 -+ PSHUFL $0X39,X11,X11 -+ PSHUFL $0X39,X1,X1 -+ PSHUFL $0X39,X6,X6 -+ XORL 32(SI),DX -+ XORL 36(SI),CX -+ XORL 40(SI),R8 -+ XORL 44(SI),R9 -+ MOVL DX,32(DI) -+ MOVL CX,36(DI) -+ MOVL R8,40(DI) -+ MOVL R9,44(DI) -+ MOVD X15,DX -+ MOVD X11,CX -+ MOVD X1,R8 -+ MOVD X6,R9 -+ PSHUFL $0X39,X15,X15 -+ PSHUFL $0X39,X11,X11 -+ PSHUFL $0X39,X1,X1 -+ PSHUFL $0X39,X6,X6 -+ XORL 96(SI),DX -+ XORL 100(SI),CX -+ XORL 104(SI),R8 -+ XORL 108(SI),R9 -+ MOVL DX,96(DI) -+ MOVL CX,100(DI) -+ MOVL R8,104(DI) -+ MOVL R9,108(DI) -+ MOVD X15,DX -+ MOVD X11,CX -+ MOVD X1,R8 -+ MOVD X6,R9 -+ PSHUFL $0X39,X15,X15 -+ PSHUFL $0X39,X11,X11 -+ PSHUFL $0X39,X1,X1 -+ PSHUFL $0X39,X6,X6 -+ XORL 160(SI),DX -+ XORL 164(SI),CX -+ XORL 168(SI),R8 -+ XORL 172(SI),R9 -+ MOVL DX,160(DI) -+ MOVL CX,164(DI) -+ MOVL R8,168(DI) -+ MOVL R9,172(DI) -+ MOVD X15,DX -+ MOVD X11,CX -+ MOVD X1,R8 -+ MOVD X6,R9 -+ XORL 224(SI),DX -+ XORL 228(SI),CX -+ XORL 232(SI),R8 -+ XORL 236(SI),R9 -+ MOVL DX,224(DI) -+ MOVL CX,228(DI) -+ MOVL R8,232(DI) -+ MOVL R9,236(DI) -+ PADDL 160(R12),X13 -+ PADDL 208(R12),X9 -+ PADDL 256(R12),X3 -+ PADDL 96(R12),X2 -+ MOVD X13,DX -+ MOVD X9,CX -+ MOVD X3,R8 -+ MOVD X2,R9 -+ PSHUFL $0X39,X13,X13 -+ PSHUFL $0X39,X9,X9 -+ PSHUFL $0X39,X3,X3 -+ PSHUFL $0X39,X2,X2 -+ XORL 48(SI),DX -+ XORL 52(SI),CX -+ XORL 56(SI),R8 -+ XORL 60(SI),R9 -+ MOVL DX,48(DI) -+ MOVL CX,52(DI) -+ MOVL R8,56(DI) -+ MOVL R9,60(DI) -+ MOVD X13,DX -+ MOVD X9,CX -+ MOVD X3,R8 -+ MOVD X2,R9 -+ PSHUFL $0X39,X13,X13 -+ PSHUFL $0X39,X9,X9 -+ PSHUFL $0X39,X3,X3 -+ PSHUFL $0X39,X2,X2 -+ XORL 112(SI),DX -+ XORL 116(SI),CX -+ XORL 120(SI),R8 -+ XORL 124(SI),R9 -+ MOVL DX,112(DI) -+ MOVL CX,116(DI) -+ MOVL R8,120(DI) -+ MOVL R9,124(DI) -+ MOVD X13,DX -+ MOVD X9,CX -+ MOVD X3,R8 -+ MOVD X2,R9 -+ PSHUFL $0X39,X13,X13 -+ PSHUFL $0X39,X9,X9 -+ PSHUFL $0X39,X3,X3 -+ PSHUFL $0X39,X2,X2 -+ XORL 176(SI),DX -+ XORL 180(SI),CX -+ XORL 184(SI),R8 -+ XORL 188(SI),R9 -+ MOVL DX,176(DI) -+ MOVL CX,180(DI) -+ MOVL R8,184(DI) -+ MOVL R9,188(DI) -+ MOVD X13,DX -+ MOVD X9,CX -+ MOVD X3,R8 -+ MOVD X2,R9 -+ XORL 240(SI),DX -+ XORL 244(SI),CX -+ XORL 248(SI),R8 -+ XORL 252(SI),R9 -+ MOVL DX,240(DI) -+ MOVL CX,244(DI) -+ MOVL R8,248(DI) -+ MOVL R9,252(DI) -+ MOVQ 352(R12),R9 -+ SUBQ $256,R9 -+ ADDQ $256,SI -+ ADDQ $256,DI -+ CMPQ R9,$256 -+ JAE BYTESATLEAST256 -+ CMPQ R9,$0 -+ JBE DONE -+ BYTESBETWEEN1AND255: -+ CMPQ R9,$64 -+ JAE NOCOPY -+ MOVQ DI,DX -+ LEAQ 360(R12),DI -+ MOVQ R9,CX -+ REP; MOVSB -+ LEAQ 360(R12),DI -+ LEAQ 360(R12),SI -+ NOCOPY: -+ MOVQ R9,352(R12) -+ MOVOA 48(R12),X0 -+ MOVOA 0(R12),X1 -+ MOVOA 16(R12),X2 -+ MOVOA 32(R12),X3 -+ MOVOA X1,X4 -+ MOVQ $20,CX -+ MAINLOOP2: -+ PADDL X0,X4 -+ MOVOA X0,X5 -+ MOVOA X4,X6 -+ PSLLL $7,X4 -+ PSRLL $25,X6 -+ PXOR X4,X3 -+ PXOR X6,X3 -+ PADDL X3,X5 -+ MOVOA X3,X4 -+ MOVOA X5,X6 -+ PSLLL $9,X5 -+ PSRLL $23,X6 -+ PXOR X5,X2 -+ PSHUFL $0X93,X3,X3 -+ PXOR X6,X2 -+ PADDL X2,X4 -+ MOVOA X2,X5 -+ MOVOA X4,X6 -+ PSLLL $13,X4 -+ PSRLL $19,X6 -+ PXOR X4,X1 -+ PSHUFL $0X4E,X2,X2 -+ PXOR X6,X1 -+ PADDL X1,X5 -+ MOVOA X3,X4 -+ MOVOA X5,X6 -+ PSLLL $18,X5 -+ PSRLL $14,X6 -+ PXOR X5,X0 -+ PSHUFL $0X39,X1,X1 -+ PXOR X6,X0 -+ PADDL X0,X4 -+ MOVOA X0,X5 -+ MOVOA X4,X6 -+ PSLLL $7,X4 -+ PSRLL $25,X6 -+ PXOR X4,X1 -+ PXOR X6,X1 -+ PADDL X1,X5 -+ MOVOA X1,X4 -+ MOVOA X5,X6 -+ PSLLL $9,X5 -+ PSRLL $23,X6 -+ PXOR X5,X2 -+ PSHUFL $0X93,X1,X1 -+ PXOR X6,X2 -+ PADDL X2,X4 -+ MOVOA X2,X5 -+ MOVOA X4,X6 -+ PSLLL $13,X4 -+ PSRLL $19,X6 -+ PXOR X4,X3 -+ PSHUFL $0X4E,X2,X2 -+ PXOR X6,X3 -+ PADDL X3,X5 -+ MOVOA X1,X4 -+ MOVOA X5,X6 -+ PSLLL $18,X5 -+ PSRLL $14,X6 -+ PXOR X5,X0 -+ PSHUFL $0X39,X3,X3 -+ PXOR X6,X0 -+ PADDL X0,X4 -+ MOVOA X0,X5 -+ MOVOA X4,X6 -+ PSLLL $7,X4 -+ PSRLL $25,X6 -+ PXOR X4,X3 -+ PXOR X6,X3 -+ PADDL X3,X5 -+ MOVOA X3,X4 -+ MOVOA X5,X6 -+ PSLLL $9,X5 -+ PSRLL $23,X6 -+ PXOR X5,X2 -+ PSHUFL $0X93,X3,X3 -+ PXOR X6,X2 -+ PADDL X2,X4 -+ MOVOA X2,X5 -+ MOVOA X4,X6 -+ PSLLL $13,X4 -+ PSRLL $19,X6 -+ PXOR X4,X1 -+ PSHUFL $0X4E,X2,X2 -+ PXOR X6,X1 -+ PADDL X1,X5 -+ MOVOA X3,X4 -+ MOVOA X5,X6 -+ PSLLL $18,X5 -+ PSRLL $14,X6 -+ PXOR X5,X0 -+ PSHUFL $0X39,X1,X1 -+ PXOR X6,X0 -+ PADDL X0,X4 -+ MOVOA X0,X5 -+ MOVOA X4,X6 -+ PSLLL $7,X4 -+ PSRLL $25,X6 -+ PXOR X4,X1 -+ PXOR X6,X1 -+ PADDL X1,X5 -+ MOVOA X1,X4 -+ MOVOA X5,X6 -+ PSLLL $9,X5 -+ PSRLL $23,X6 -+ PXOR X5,X2 -+ PSHUFL $0X93,X1,X1 -+ PXOR X6,X2 -+ PADDL X2,X4 -+ MOVOA X2,X5 -+ MOVOA X4,X6 -+ PSLLL $13,X4 -+ PSRLL $19,X6 -+ PXOR X4,X3 -+ PSHUFL $0X4E,X2,X2 -+ PXOR X6,X3 -+ SUBQ $4,CX -+ PADDL X3,X5 -+ MOVOA X1,X4 -+ MOVOA X5,X6 -+ PSLLL $18,X5 -+ PXOR X7,X7 -+ PSRLL $14,X6 -+ PXOR X5,X0 -+ PSHUFL $0X39,X3,X3 -+ PXOR X6,X0 -+ JA MAINLOOP2 -+ PADDL 48(R12),X0 -+ PADDL 0(R12),X1 -+ PADDL 16(R12),X2 -+ PADDL 32(R12),X3 -+ MOVD X0,CX -+ MOVD X1,R8 -+ MOVD X2,R9 -+ MOVD X3,AX -+ PSHUFL $0X39,X0,X0 -+ PSHUFL $0X39,X1,X1 -+ PSHUFL $0X39,X2,X2 -+ PSHUFL $0X39,X3,X3 -+ XORL 0(SI),CX -+ XORL 48(SI),R8 -+ XORL 32(SI),R9 -+ XORL 16(SI),AX -+ MOVL CX,0(DI) -+ MOVL R8,48(DI) -+ MOVL R9,32(DI) -+ MOVL AX,16(DI) -+ MOVD X0,CX -+ MOVD X1,R8 -+ MOVD X2,R9 -+ MOVD X3,AX -+ PSHUFL $0X39,X0,X0 -+ PSHUFL $0X39,X1,X1 -+ PSHUFL $0X39,X2,X2 -+ PSHUFL $0X39,X3,X3 -+ XORL 20(SI),CX -+ XORL 4(SI),R8 -+ XORL 52(SI),R9 -+ XORL 36(SI),AX -+ MOVL CX,20(DI) -+ MOVL R8,4(DI) -+ MOVL R9,52(DI) -+ MOVL AX,36(DI) -+ MOVD X0,CX -+ MOVD X1,R8 -+ MOVD X2,R9 -+ MOVD X3,AX -+ PSHUFL $0X39,X0,X0 -+ PSHUFL $0X39,X1,X1 -+ PSHUFL $0X39,X2,X2 -+ PSHUFL $0X39,X3,X3 -+ XORL 40(SI),CX -+ XORL 24(SI),R8 -+ XORL 8(SI),R9 -+ XORL 56(SI),AX -+ MOVL CX,40(DI) -+ MOVL R8,24(DI) -+ MOVL R9,8(DI) -+ MOVL AX,56(DI) -+ MOVD X0,CX -+ MOVD X1,R8 -+ MOVD X2,R9 -+ MOVD X3,AX -+ XORL 60(SI),CX -+ XORL 44(SI),R8 -+ XORL 28(SI),R9 -+ XORL 12(SI),AX -+ MOVL CX,60(DI) -+ MOVL R8,44(DI) -+ MOVL R9,28(DI) -+ MOVL AX,12(DI) -+ MOVQ 352(R12),R9 -+ MOVL 16(R12),CX -+ MOVL 36 (R12),R8 -+ ADDQ $1,CX -+ SHLQ $32,R8 -+ ADDQ R8,CX -+ MOVQ CX,R8 -+ SHRQ $32,R8 -+ MOVL CX,16(R12) -+ MOVL R8, 36 (R12) -+ CMPQ R9,$64 -+ JA BYTESATLEAST65 -+ JAE BYTESATLEAST64 -+ MOVQ DI,SI -+ MOVQ DX,DI -+ MOVQ R9,CX -+ REP; MOVSB -+ BYTESATLEAST64: -+ DONE: -+ RET -+ BYTESATLEAST65: -+ SUBQ $64,R9 -+ ADDQ $64,DI -+ ADDQ $64,SI -+ JMP BYTESBETWEEN1AND255 -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go -new file mode 100644 -index 00000000000000..fc781f76f96107 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_amd64_test.go -@@ -0,0 +1,32 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+package salsa -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+func TestCounterOverflow(t *testing.T) { -+ in := make([]byte, 4096) -+ key := &[32]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, -+ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2} -+ for n, counter := range []*[16]byte{ -+ &[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // zero counter -+ &[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}, // counter about to overflow 32 bits -+ &[16]byte{0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff}, // counter above 32 bits -+ } { -+ out := make([]byte, 4096) -+ XORKeyStream(out, in, counter, key) -+ outGeneric := make([]byte, 4096) -+ genericXORKeyStream(outGeneric, in, counter, key) -+ if !bytes.Equal(out, outGeneric) { -+ t.Errorf("%d: assembly and go implementations disagree", n) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go -new file mode 100644 -index 00000000000000..4392cc1ac74024 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go -@@ -0,0 +1,15 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package salsa -+ -+// XORKeyStream crypts bytes from in to out using the given key and counters. -+// In and out must overlap entirely or not at all. Counter -+// contains the raw salsa20 counter bytes (both nonce and block counter). -+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { -+ genericXORKeyStream(out, in, counter, key) -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go -new file mode 100644 -index 00000000000000..e5cdb9a25bee76 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go -@@ -0,0 +1,233 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package salsa -+ -+import "math/bits" -+ -+const rounds = 20 -+ -+// core applies the Salsa20 core function to 16-byte input in, 32-byte key k, -+// and 16-byte constant c, and puts the result into 64-byte array out. -+func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { -+ j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 -+ j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 -+ j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 -+ j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 -+ j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 -+ j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 -+ j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 -+ j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 -+ j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 -+ j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 -+ j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 -+ j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 -+ j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 -+ j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 -+ j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 -+ j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 -+ -+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 -+ x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 -+ -+ for i := 0; i < rounds; i += 2 { -+ u := x0 + x12 -+ x4 ^= bits.RotateLeft32(u, 7) -+ u = x4 + x0 -+ x8 ^= bits.RotateLeft32(u, 9) -+ u = x8 + x4 -+ x12 ^= bits.RotateLeft32(u, 13) -+ u = x12 + x8 -+ x0 ^= bits.RotateLeft32(u, 18) -+ -+ u = x5 + x1 -+ x9 ^= bits.RotateLeft32(u, 7) -+ u = x9 + x5 -+ x13 ^= bits.RotateLeft32(u, 9) -+ u = x13 + x9 -+ x1 ^= bits.RotateLeft32(u, 13) -+ u = x1 + x13 -+ x5 ^= bits.RotateLeft32(u, 18) -+ -+ u = x10 + x6 -+ x14 ^= bits.RotateLeft32(u, 7) -+ u = x14 + x10 -+ x2 ^= bits.RotateLeft32(u, 9) -+ u = x2 + x14 -+ x6 ^= bits.RotateLeft32(u, 13) -+ u = x6 + x2 -+ x10 ^= bits.RotateLeft32(u, 18) -+ -+ u = x15 + x11 -+ x3 ^= bits.RotateLeft32(u, 7) -+ u = x3 + x15 -+ x7 ^= bits.RotateLeft32(u, 9) -+ u = x7 + x3 -+ x11 ^= bits.RotateLeft32(u, 13) -+ u = x11 + x7 -+ x15 ^= bits.RotateLeft32(u, 18) -+ -+ u = x0 + x3 -+ x1 ^= bits.RotateLeft32(u, 7) -+ u = x1 + x0 -+ x2 ^= bits.RotateLeft32(u, 9) -+ u = x2 + x1 -+ x3 ^= bits.RotateLeft32(u, 13) -+ u = x3 + x2 -+ x0 ^= bits.RotateLeft32(u, 18) -+ -+ u = x5 + x4 -+ x6 ^= bits.RotateLeft32(u, 7) -+ u = x6 + x5 -+ x7 ^= bits.RotateLeft32(u, 9) -+ u = x7 + x6 -+ x4 ^= bits.RotateLeft32(u, 13) -+ u = x4 + x7 -+ x5 ^= bits.RotateLeft32(u, 18) -+ -+ u = x10 + x9 -+ x11 ^= bits.RotateLeft32(u, 7) -+ u = x11 + x10 -+ x8 ^= bits.RotateLeft32(u, 9) -+ u = x8 + x11 -+ x9 ^= bits.RotateLeft32(u, 13) -+ u = x9 + x8 -+ x10 ^= bits.RotateLeft32(u, 18) -+ -+ u = x15 + x14 -+ x12 ^= bits.RotateLeft32(u, 7) -+ u = x12 + x15 -+ x13 ^= bits.RotateLeft32(u, 9) -+ u = x13 + x12 -+ x14 ^= bits.RotateLeft32(u, 13) -+ u = x14 + x13 -+ x15 ^= bits.RotateLeft32(u, 18) -+ } -+ x0 += j0 -+ x1 += j1 -+ x2 += j2 -+ x3 += j3 -+ x4 += j4 -+ x5 += j5 -+ x6 += j6 -+ x7 += j7 -+ x8 += j8 -+ x9 += j9 -+ x10 += j10 -+ x11 += j11 -+ x12 += j12 -+ x13 += j13 -+ x14 += j14 -+ x15 += j15 -+ -+ out[0] = byte(x0) -+ out[1] = byte(x0 >> 8) -+ out[2] = byte(x0 >> 16) -+ out[3] = byte(x0 >> 24) -+ -+ out[4] = byte(x1) -+ out[5] = byte(x1 >> 8) -+ out[6] = byte(x1 >> 16) -+ out[7] = byte(x1 >> 24) -+ -+ out[8] = byte(x2) -+ out[9] = byte(x2 >> 8) -+ out[10] = byte(x2 >> 16) -+ out[11] = byte(x2 >> 24) -+ -+ out[12] = byte(x3) -+ out[13] = byte(x3 >> 8) -+ out[14] = byte(x3 >> 16) -+ out[15] = byte(x3 >> 24) -+ -+ out[16] = byte(x4) -+ out[17] = byte(x4 >> 8) -+ out[18] = byte(x4 >> 16) -+ out[19] = byte(x4 >> 24) -+ -+ out[20] = byte(x5) -+ out[21] = byte(x5 >> 8) -+ out[22] = byte(x5 >> 16) -+ out[23] = byte(x5 >> 24) -+ -+ out[24] = byte(x6) -+ out[25] = byte(x6 >> 8) -+ out[26] = byte(x6 >> 16) -+ out[27] = byte(x6 >> 24) -+ -+ out[28] = byte(x7) -+ out[29] = byte(x7 >> 8) -+ out[30] = byte(x7 >> 16) -+ out[31] = byte(x7 >> 24) -+ -+ out[32] = byte(x8) -+ out[33] = byte(x8 >> 8) -+ out[34] = byte(x8 >> 16) -+ out[35] = byte(x8 >> 24) -+ -+ out[36] = byte(x9) -+ out[37] = byte(x9 >> 8) -+ out[38] = byte(x9 >> 16) -+ out[39] = byte(x9 >> 24) -+ -+ out[40] = byte(x10) -+ out[41] = byte(x10 >> 8) -+ out[42] = byte(x10 >> 16) -+ out[43] = byte(x10 >> 24) -+ -+ out[44] = byte(x11) -+ out[45] = byte(x11 >> 8) -+ out[46] = byte(x11 >> 16) -+ out[47] = byte(x11 >> 24) -+ -+ out[48] = byte(x12) -+ out[49] = byte(x12 >> 8) -+ out[50] = byte(x12 >> 16) -+ out[51] = byte(x12 >> 24) -+ -+ out[52] = byte(x13) -+ out[53] = byte(x13 >> 8) -+ out[54] = byte(x13 >> 16) -+ out[55] = byte(x13 >> 24) -+ -+ out[56] = byte(x14) -+ out[57] = byte(x14 >> 8) -+ out[58] = byte(x14 >> 16) -+ out[59] = byte(x14 >> 24) -+ -+ out[60] = byte(x15) -+ out[61] = byte(x15 >> 8) -+ out[62] = byte(x15 >> 16) -+ out[63] = byte(x15 >> 24) -+} -+ -+// genericXORKeyStream is the generic implementation of XORKeyStream to be used -+// when no assembly implementation is available. -+func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { -+ var block [64]byte -+ var counterCopy [16]byte -+ copy(counterCopy[:], counter[:]) -+ -+ for len(in) >= 64 { -+ core(&block, &counterCopy, key, &Sigma) -+ for i, x := range block { -+ out[i] = in[i] ^ x -+ } -+ u := uint32(1) -+ for i := 8; i < 16; i++ { -+ u += uint32(counterCopy[i]) -+ counterCopy[i] = byte(u) -+ u >>= 8 -+ } -+ in = in[64:] -+ out = out[64:] -+ } -+ -+ if len(in) > 0 { -+ core(&block, &counterCopy, key, &Sigma) -+ for i, v := range in { -+ out[i] = v ^ block[i] -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go -new file mode 100644 -index 00000000000000..f67e94eba41793 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa/salsa_test.go -@@ -0,0 +1,54 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package salsa -+ -+import "testing" -+ -+func TestCore208(t *testing.T) { -+ in := [64]byte{ -+ 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, -+ 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, -+ 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, -+ 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, -+ 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, -+ 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, -+ 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, -+ 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e} -+ -+ out := [64]byte{ -+ 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, -+ 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, -+ 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, -+ 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, -+ 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, -+ 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, -+ 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, -+ 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, -+ } -+ -+ Core208(&in, &in) -+ if in != out { -+ t.Errorf("expected %x, got %x", out, in) -+ } -+} -+ -+func TestOutOfBoundsWrite(t *testing.T) { -+ // encrypted "0123456789" -+ cipherText := []byte{170, 166, 196, 104, 175, 121, 68, 44, 174, 51} -+ var counter [16]byte -+ var key [32]byte -+ want := "abcdefghij" -+ plainText := []byte(want) -+ defer func() { -+ err := recover() -+ if err == nil { -+ t.Error("XORKeyStream expected to panic on len(dst) < len(src), but didn't") -+ } -+ if plainText[3] == '3' { -+ t.Errorf("XORKeyStream did out of bounds write, want %v, got %v", want, string(plainText)) -+ } -+ }() -+ XORKeyStream(plainText[:3], cipherText, &counter, &key) -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa20.go b/ms_mod/golang.org/x/crypto/salsa20/salsa20.go -new file mode 100644 -index 00000000000000..8f4f896c70d3f0 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa20.go -@@ -0,0 +1,58 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+Package salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf. -+ -+Salsa20 differs from many other stream ciphers in that it is message orientated -+rather than byte orientated. Keystream blocks are not preserved between calls, -+therefore each side must encrypt/decrypt data with the same segmentation. -+ -+Another aspect of this difference is that part of the counter is exposed as -+a nonce in each call. Encrypting two different messages with the same (key, -+nonce) pair leads to trivial plaintext recovery. This is analogous to -+encrypting two different messages with the same key with a traditional stream -+cipher. -+ -+This package also implements XSalsa20: a version of Salsa20 with a 24-byte -+nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply -+passing a 24-byte slice as the nonce triggers XSalsa20. -+*/ -+package salsa20 // import "golang.org/x/crypto/salsa20" -+ -+// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. -+ -+import ( -+ "golang.org/x/crypto/internal/alias" -+ "golang.org/x/crypto/salsa20/salsa" -+) -+ -+// XORKeyStream crypts bytes from in to out using the given key and nonce. -+// In and out must overlap entirely or not at all. Nonce must -+// be either 8 or 24 bytes long. -+func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { -+ if len(out) < len(in) { -+ panic("salsa20: output smaller than input") -+ } -+ if alias.InexactOverlap(out[:len(in)], in) { -+ panic("salsa20: invalid buffer overlap") -+ } -+ -+ var subNonce [16]byte -+ -+ if len(nonce) == 24 { -+ var subKey [32]byte -+ var hNonce [16]byte -+ copy(hNonce[:], nonce[:16]) -+ salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma) -+ copy(subNonce[:], nonce[16:]) -+ key = &subKey -+ } else if len(nonce) == 8 { -+ copy(subNonce[:], nonce[:]) -+ } else { -+ panic("salsa20: nonce must be 8 or 24 bytes") -+ } -+ -+ salsa.XORKeyStream(out, in, &subNonce, key) -+} -diff --git a/ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go b/ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go -new file mode 100644 -index 00000000000000..0ef3328eb0a8dc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/salsa20/salsa20_test.go -@@ -0,0 +1,139 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package salsa20 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "testing" -+) -+ -+func fromHex(s string) []byte { -+ ret, err := hex.DecodeString(s) -+ if err != nil { -+ panic(err) -+ } -+ return ret -+} -+ -+// testVectors was taken from set 6 of the ECRYPT test vectors: -+// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup -+var testVectors = []struct { -+ key []byte -+ iv []byte -+ numBytes int -+ xor []byte -+}{ -+ { -+ fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"), -+ fromHex("0D74DB42A91077DE"), -+ 131072, -+ fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"), -+ }, -+ { -+ fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"), -+ fromHex("167DE44BB21980E7"), -+ 131072, -+ fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"), -+ }, -+ { -+ fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"), -+ fromHex("1F86ED54BB2289F0"), -+ 131072, -+ fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"), -+ }, -+ { -+ fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"), -+ fromHex("288FF65DC42B92F9"), -+ 131072, -+ fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"), -+ }, -+} -+ -+func TestSalsa20(t *testing.T) { -+ var inBuf, outBuf []byte -+ var key [32]byte -+ -+ for i, test := range testVectors { -+ if test.numBytes%64 != 0 { -+ t.Errorf("#%d: numBytes is not a multiple of 64", i) -+ continue -+ } -+ -+ if test.numBytes > len(inBuf) { -+ inBuf = make([]byte, test.numBytes) -+ outBuf = make([]byte, test.numBytes) -+ } -+ in := inBuf[:test.numBytes] -+ out := outBuf[:test.numBytes] -+ copy(key[:], test.key) -+ XORKeyStream(out, in, test.iv, &key) -+ -+ var xor [64]byte -+ for len(out) > 0 { -+ for i := 0; i < 64; i++ { -+ xor[i] ^= out[i] -+ } -+ out = out[64:] -+ } -+ -+ if !bytes.Equal(xor[:], test.xor) { -+ t.Errorf("#%d: bad result", i) -+ } -+ } -+} -+ -+var xSalsa20TestData = []struct { -+ in, nonce, key, out []byte -+}{ -+ { -+ []byte("Hello world!"), -+ []byte("24-byte nonce for xsalsa"), -+ []byte("this is 32-byte key for xsalsa20"), -+ []byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41}, -+ }, -+ { -+ make([]byte, 64), -+ []byte("24-byte nonce for xsalsa"), -+ []byte("this is 32-byte key for xsalsa20"), -+ []byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6, -+ 0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70, -+ 0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf, -+ 0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26, -+ 0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40, -+ 0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f, -+ 0x3a, 0x58, 0xe4, 0x76, 0x48}, -+ }, -+} -+ -+func TestXSalsa20(t *testing.T) { -+ var key [32]byte -+ -+ for i, test := range xSalsa20TestData { -+ out := make([]byte, len(test.in)) -+ copy(key[:], test.key) -+ XORKeyStream(out, test.in, test.nonce, &key) -+ if !bytes.Equal(out, test.out) { -+ t.Errorf("%d: expected %x, got %x", i, test.out, out) -+ } -+ } -+} -+ -+var ( -+ keyArray [32]byte -+ key = &keyArray -+ nonce [8]byte -+ msg = make([]byte, 1<<10) -+) -+ -+func BenchmarkXOR1K(b *testing.B) { -+ b.StopTimer() -+ out := make([]byte, 1024) -+ b.StartTimer() -+ for i := 0; i < b.N; i++ { -+ XORKeyStream(out, msg[:1024], nonce[:], key) -+ } -+ b.SetBytes(1024) -+} -diff --git a/ms_mod/golang.org/x/crypto/scrypt/example_test.go b/ms_mod/golang.org/x/crypto/scrypt/example_test.go -new file mode 100644 -index 00000000000000..6736479b196153 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/scrypt/example_test.go -@@ -0,0 +1,26 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package scrypt_test -+ -+import ( -+ "encoding/base64" -+ "fmt" -+ "log" -+ -+ "golang.org/x/crypto/scrypt" -+) -+ -+func Example() { -+ // DO NOT use this salt value; generate your own random salt. 8 bytes is -+ // a good length. -+ salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b} -+ -+ dk, err := scrypt.Key([]byte("some password"), salt, 1<<15, 8, 1, 32) -+ if err != nil { -+ log.Fatal(err) -+ } -+ fmt.Println(base64.StdEncoding.EncodeToString(dk)) -+ // Output: lGnMz8io0AUkfzn6Pls1qX20Vs7PGN6sbYQ2TQgY12M= -+} -diff --git a/ms_mod/golang.org/x/crypto/scrypt/scrypt.go b/ms_mod/golang.org/x/crypto/scrypt/scrypt.go -new file mode 100644 -index 00000000000000..c971a99fa67982 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/scrypt/scrypt.go -@@ -0,0 +1,212 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package scrypt implements the scrypt key derivation function as defined in -+// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard -+// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf). -+package scrypt // import "golang.org/x/crypto/scrypt" -+ -+import ( -+ "crypto/sha256" -+ "encoding/binary" -+ "errors" -+ "math/bits" -+ -+ "golang.org/x/crypto/pbkdf2" -+) -+ -+const maxInt = int(^uint(0) >> 1) -+ -+// blockCopy copies n numbers from src into dst. -+func blockCopy(dst, src []uint32, n int) { -+ copy(dst, src[:n]) -+} -+ -+// blockXOR XORs numbers from dst with n numbers from src. -+func blockXOR(dst, src []uint32, n int) { -+ for i, v := range src[:n] { -+ dst[i] ^= v -+ } -+} -+ -+// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in, -+// and puts the result into both tmp and out. -+func salsaXOR(tmp *[16]uint32, in, out []uint32) { -+ w0 := tmp[0] ^ in[0] -+ w1 := tmp[1] ^ in[1] -+ w2 := tmp[2] ^ in[2] -+ w3 := tmp[3] ^ in[3] -+ w4 := tmp[4] ^ in[4] -+ w5 := tmp[5] ^ in[5] -+ w6 := tmp[6] ^ in[6] -+ w7 := tmp[7] ^ in[7] -+ w8 := tmp[8] ^ in[8] -+ w9 := tmp[9] ^ in[9] -+ w10 := tmp[10] ^ in[10] -+ w11 := tmp[11] ^ in[11] -+ w12 := tmp[12] ^ in[12] -+ w13 := tmp[13] ^ in[13] -+ w14 := tmp[14] ^ in[14] -+ w15 := tmp[15] ^ in[15] -+ -+ x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8 -+ x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 -+ -+ for i := 0; i < 8; i += 2 { -+ x4 ^= bits.RotateLeft32(x0+x12, 7) -+ x8 ^= bits.RotateLeft32(x4+x0, 9) -+ x12 ^= bits.RotateLeft32(x8+x4, 13) -+ x0 ^= bits.RotateLeft32(x12+x8, 18) -+ -+ x9 ^= bits.RotateLeft32(x5+x1, 7) -+ x13 ^= bits.RotateLeft32(x9+x5, 9) -+ x1 ^= bits.RotateLeft32(x13+x9, 13) -+ x5 ^= bits.RotateLeft32(x1+x13, 18) -+ -+ x14 ^= bits.RotateLeft32(x10+x6, 7) -+ x2 ^= bits.RotateLeft32(x14+x10, 9) -+ x6 ^= bits.RotateLeft32(x2+x14, 13) -+ x10 ^= bits.RotateLeft32(x6+x2, 18) -+ -+ x3 ^= bits.RotateLeft32(x15+x11, 7) -+ x7 ^= bits.RotateLeft32(x3+x15, 9) -+ x11 ^= bits.RotateLeft32(x7+x3, 13) -+ x15 ^= bits.RotateLeft32(x11+x7, 18) -+ -+ x1 ^= bits.RotateLeft32(x0+x3, 7) -+ x2 ^= bits.RotateLeft32(x1+x0, 9) -+ x3 ^= bits.RotateLeft32(x2+x1, 13) -+ x0 ^= bits.RotateLeft32(x3+x2, 18) -+ -+ x6 ^= bits.RotateLeft32(x5+x4, 7) -+ x7 ^= bits.RotateLeft32(x6+x5, 9) -+ x4 ^= bits.RotateLeft32(x7+x6, 13) -+ x5 ^= bits.RotateLeft32(x4+x7, 18) -+ -+ x11 ^= bits.RotateLeft32(x10+x9, 7) -+ x8 ^= bits.RotateLeft32(x11+x10, 9) -+ x9 ^= bits.RotateLeft32(x8+x11, 13) -+ x10 ^= bits.RotateLeft32(x9+x8, 18) -+ -+ x12 ^= bits.RotateLeft32(x15+x14, 7) -+ x13 ^= bits.RotateLeft32(x12+x15, 9) -+ x14 ^= bits.RotateLeft32(x13+x12, 13) -+ x15 ^= bits.RotateLeft32(x14+x13, 18) -+ } -+ x0 += w0 -+ x1 += w1 -+ x2 += w2 -+ x3 += w3 -+ x4 += w4 -+ x5 += w5 -+ x6 += w6 -+ x7 += w7 -+ x8 += w8 -+ x9 += w9 -+ x10 += w10 -+ x11 += w11 -+ x12 += w12 -+ x13 += w13 -+ x14 += w14 -+ x15 += w15 -+ -+ out[0], tmp[0] = x0, x0 -+ out[1], tmp[1] = x1, x1 -+ out[2], tmp[2] = x2, x2 -+ out[3], tmp[3] = x3, x3 -+ out[4], tmp[4] = x4, x4 -+ out[5], tmp[5] = x5, x5 -+ out[6], tmp[6] = x6, x6 -+ out[7], tmp[7] = x7, x7 -+ out[8], tmp[8] = x8, x8 -+ out[9], tmp[9] = x9, x9 -+ out[10], tmp[10] = x10, x10 -+ out[11], tmp[11] = x11, x11 -+ out[12], tmp[12] = x12, x12 -+ out[13], tmp[13] = x13, x13 -+ out[14], tmp[14] = x14, x14 -+ out[15], tmp[15] = x15, x15 -+} -+ -+func blockMix(tmp *[16]uint32, in, out []uint32, r int) { -+ blockCopy(tmp[:], in[(2*r-1)*16:], 16) -+ for i := 0; i < 2*r; i += 2 { -+ salsaXOR(tmp, in[i*16:], out[i*8:]) -+ salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:]) -+ } -+} -+ -+func integer(b []uint32, r int) uint64 { -+ j := (2*r - 1) * 16 -+ return uint64(b[j]) | uint64(b[j+1])<<32 -+} -+ -+func smix(b []byte, r, N int, v, xy []uint32) { -+ var tmp [16]uint32 -+ R := 32 * r -+ x := xy -+ y := xy[R:] -+ -+ j := 0 -+ for i := 0; i < R; i++ { -+ x[i] = binary.LittleEndian.Uint32(b[j:]) -+ j += 4 -+ } -+ for i := 0; i < N; i += 2 { -+ blockCopy(v[i*R:], x, R) -+ blockMix(&tmp, x, y, r) -+ -+ blockCopy(v[(i+1)*R:], y, R) -+ blockMix(&tmp, y, x, r) -+ } -+ for i := 0; i < N; i += 2 { -+ j := int(integer(x, r) & uint64(N-1)) -+ blockXOR(x, v[j*R:], R) -+ blockMix(&tmp, x, y, r) -+ -+ j = int(integer(y, r) & uint64(N-1)) -+ blockXOR(y, v[j*R:], R) -+ blockMix(&tmp, y, x, r) -+ } -+ j = 0 -+ for _, v := range x[:R] { -+ binary.LittleEndian.PutUint32(b[j:], v) -+ j += 4 -+ } -+} -+ -+// Key derives a key from the password, salt, and cost parameters, returning -+// a byte slice of length keyLen that can be used as cryptographic key. -+// -+// N is a CPU/memory cost parameter, which must be a power of two greater than 1. -+// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the -+// limits, the function returns a nil byte slice and an error. -+// -+// For example, you can get a derived key for e.g. AES-256 (which needs a -+// 32-byte key) by doing: -+// -+// dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) -+// -+// The recommended parameters for interactive logins as of 2017 are N=32768, r=8 -+// and p=1. The parameters N, r, and p should be increased as memory latency and -+// CPU parallelism increases; consider setting N to the highest power of 2 you -+// can derive within 100 milliseconds. Remember to get a good random salt. -+func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { -+ if N <= 1 || N&(N-1) != 0 { -+ return nil, errors.New("scrypt: N must be > 1 and a power of 2") -+ } -+ if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { -+ return nil, errors.New("scrypt: parameters are too large") -+ } -+ -+ xy := make([]uint32, 64*r) -+ v := make([]uint32, 32*N*r) -+ b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) -+ -+ for i := 0; i < p; i++ { -+ smix(b[i*128*r:], r, N, v, xy) -+ } -+ -+ return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil -+} -diff --git a/ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go b/ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go -new file mode 100644 -index 00000000000000..766ed8d9050250 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/scrypt/scrypt_test.go -@@ -0,0 +1,162 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package scrypt -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+type testVector struct { -+ password string -+ salt string -+ N, r, p int -+ output []byte -+} -+ -+var good = []testVector{ -+ { -+ "password", -+ "salt", -+ 2, 10, 10, -+ []byte{ -+ 0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f, -+ 0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb, -+ 0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a, -+ 0xc5, 0xe5, 0xa, 0xa1, 0x5f, -+ }, -+ }, -+ { -+ "password", -+ "salt", -+ 16, 100, 100, -+ []byte{ -+ 0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18, -+ 0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e, -+ 0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5, -+ 0x7f, 0x91, 0x96, 0x3c, 0x37, -+ }, -+ }, -+ { -+ "this is a long \000 password", -+ "and this is a long \000 salt", -+ 16384, 8, 1, -+ []byte{ -+ 0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70, -+ 0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09, -+ 0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f, -+ 0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98, -+ 0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50, -+ 0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa, -+ 0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11, -+ 0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40, -+ 0x18, 0x79, 0xe6, 0x41, 0xae, -+ }, -+ }, -+ { -+ "p", -+ "s", -+ 2, 1, 1, -+ []byte{ -+ 0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98, -+ 0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52, -+ }, -+ }, -+ -+ { -+ "", -+ "", -+ 16, 1, 1, -+ []byte{ -+ 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b, -+ 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b, -+ 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa, -+ 0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d, -+ 0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f, -+ 0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, -+ 0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, -+ 0x06, -+ }, -+ }, -+ { -+ "password", -+ "NaCl", -+ 1024, 8, 16, -+ []byte{ -+ 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78, -+ 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a, -+ 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76, -+ 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9, -+ 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d, -+ 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, -+ 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, -+ 0x40, -+ }, -+ }, -+ { -+ "pleaseletmein", "SodiumChloride", -+ 16384, 8, 1, -+ []byte{ -+ 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46, -+ 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8, -+ 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43, -+ 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55, -+ 0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24, -+ 0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, -+ 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, -+ 0x87, -+ }, -+ }, -+ /* -+ // Disabled: needs 1 GiB RAM and takes too long for a simple test. -+ { -+ "pleaseletmein", "SodiumChloride", -+ 1048576, 8, 1, -+ []byte{ -+ 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad, -+ 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56, -+ 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee, -+ 0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f, -+ 0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c, -+ 0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, -+ 0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, -+ 0xa4, -+ }, -+ }, -+ */ -+} -+ -+var bad = []testVector{ -+ {"p", "s", 0, 1, 1, nil}, // N == 0 -+ {"p", "s", 1, 1, 1, nil}, // N == 1 -+ {"p", "s", 7, 8, 1, nil}, // N is not power of 2 -+ {"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large -+} -+ -+func TestKey(t *testing.T) { -+ for i, v := range good { -+ k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output)) -+ if err != nil { -+ t.Errorf("%d: got unexpected error: %s", i, err) -+ } -+ if !bytes.Equal(k, v.output) { -+ t.Errorf("%d: expected %x, got %x", i, v.output, k) -+ } -+ } -+ for i, v := range bad { -+ _, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32) -+ if err == nil { -+ t.Errorf("%d: expected error, got nil", i) -+ } -+ } -+} -+ -+var sink []byte -+ -+func BenchmarkKey(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ sink, _ = Key([]byte("password"), []byte("salt"), 1<<15, 8, 1, 64) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/doc.go b/ms_mod/golang.org/x/crypto/sha3/doc.go -new file mode 100644 -index 00000000000000..decd8cf9bf7491 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/doc.go -@@ -0,0 +1,62 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package sha3 implements the SHA-3 fixed-output-length hash functions and -+// the SHAKE variable-output-length hash functions defined by FIPS-202. -+// -+// Both types of hash function use the "sponge" construction and the Keccak -+// permutation. For a detailed specification see http://keccak.noekeon.org/ -+// -+// # Guidance -+// -+// If you aren't sure what function you need, use SHAKE256 with at least 64 -+// bytes of output. The SHAKE instances are faster than the SHA3 instances; -+// the latter have to allocate memory to conform to the hash.Hash interface. -+// -+// If you need a secret-key MAC (message authentication code), prepend the -+// secret key to the input, hash with SHAKE256 and read at least 32 bytes of -+// output. -+// -+// # Security strengths -+// -+// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security -+// strength against preimage attacks of x bits. Since they only produce "x" -+// bits of output, their collision-resistance is only "x/2" bits. -+// -+// The SHAKE-256 and -128 functions have a generic security strength of 256 and -+// 128 bits against all attacks, provided that at least 2x bits of their output -+// is used. Requesting more than 64 or 32 bytes of output, respectively, does -+// not increase the collision-resistance of the SHAKE functions. -+// -+// # The sponge construction -+// -+// A sponge builds a pseudo-random function from a public pseudo-random -+// permutation, by applying the permutation to a state of "rate + capacity" -+// bytes, but hiding "capacity" of the bytes. -+// -+// A sponge starts out with a zero state. To hash an input using a sponge, up -+// to "rate" bytes of the input are XORed into the sponge's state. The sponge -+// is then "full" and the permutation is applied to "empty" it. This process is -+// repeated until all the input has been "absorbed". The input is then padded. -+// The digest is "squeezed" from the sponge in the same way, except that output -+// is copied out instead of input being XORed in. -+// -+// A sponge is parameterized by its generic security strength, which is equal -+// to half its capacity; capacity + rate is equal to the permutation's width. -+// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means -+// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. -+// -+// # Recommendations -+// -+// The SHAKE functions are recommended for most new uses. They can produce -+// output of arbitrary length. SHAKE256, with an output length of at least -+// 64 bytes, provides 256-bit security against all attacks. The Keccak team -+// recommends it for most applications upgrading from SHA2-512. (NIST chose a -+// much stronger, but much slower, sponge instance for SHA3-512.) -+// -+// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. -+// They produce output of the same length, with the same security strengths -+// against all attacks. This means, in particular, that SHA3-256 only has -+// 128-bit collision resistance, because its output length is 32 bytes. -+package sha3 // import "golang.org/x/crypto/sha3" -diff --git a/ms_mod/golang.org/x/crypto/sha3/hashes.go b/ms_mod/golang.org/x/crypto/sha3/hashes.go -new file mode 100644 -index 00000000000000..28b94b633dc67e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/hashes.go -@@ -0,0 +1,116 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// This file provides functions for creating instances of the SHA-3 -+// and SHAKE hash functions, as well as utility functions for hashing -+// bytes. -+ -+import ( -+ "crypto" -+ "hash" -+ -+ "golang.org/x/crypto/internal/backend" -+) -+ -+// New224 creates a new SHA3-224 hash. -+// Its generic security strength is 224 bits against preimage attacks, -+// and 112 bits against collision attacks. -+func New224() hash.Hash { -+ if h := new224Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 144, outputLen: 28, dsbyte: 0x06} -+} -+ -+// New256 creates a new SHA3-256 hash. -+// Its generic security strength is 256 bits against preimage attacks, -+// and 128 bits against collision attacks. -+func New256() hash.Hash { -+ if backend.Enabled { -+ if backend.SupportsHash(crypto.SHA3_256) { -+ println("using backend sha3_256") -+ return backend.NewSHA3_256() -+ } else { -+ println("backend doesn't support sha3_256") -+ } -+ } -+ if h := new256Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 136, outputLen: 32, dsbyte: 0x06} -+} -+ -+// New384 creates a new SHA3-384 hash. -+// Its generic security strength is 384 bits against preimage attacks, -+// and 192 bits against collision attacks. -+func New384() hash.Hash { -+ if h := new384Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 104, outputLen: 48, dsbyte: 0x06} -+} -+ -+// New512 creates a new SHA3-512 hash. -+// Its generic security strength is 512 bits against preimage attacks, -+// and 256 bits against collision attacks. -+func New512() hash.Hash { -+ if h := new512Asm(); h != nil { -+ return h -+ } -+ return &state{rate: 72, outputLen: 64, dsbyte: 0x06} -+} -+ -+// NewLegacyKeccak256 creates a new Keccak-256 hash. -+// -+// Only use this function if you require compatibility with an existing cryptosystem -+// that uses non-standard padding. All other users should use New256 instead. -+func NewLegacyKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } -+ -+// NewLegacyKeccak512 creates a new Keccak-512 hash. -+// -+// Only use this function if you require compatibility with an existing cryptosystem -+// that uses non-standard padding. All other users should use New512 instead. -+func NewLegacyKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } -+ -+// Sum224 returns the SHA3-224 digest of the data. -+func Sum224(data []byte) (digest [28]byte) { -+ h := New224() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -+ -+// Sum256 returns the SHA3-256 digest of the data. -+func Sum256(data []byte) (digest [32]byte) { -+ if backend.Enabled { -+ if backend.SupportsHash(crypto.SHA3_256) { -+ println("using backend sha3_256") -+ return backend.SHA3_256(data) -+ } else { -+ println("backend doesn't support sha3_256") -+ } -+ } -+ h := New256() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -+ -+// Sum384 returns the SHA3-384 digest of the data. -+func Sum384(data []byte) (digest [48]byte) { -+ h := New384() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -+ -+// Sum512 returns the SHA3-512 digest of the data. -+func Sum512(data []byte) (digest [64]byte) { -+ h := New512() -+ h.Write(data) -+ h.Sum(digest[:0]) -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/hashes_generic.go b/ms_mod/golang.org/x/crypto/sha3/hashes_generic.go -new file mode 100644 -index 00000000000000..c74fc20fcb33b7 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/hashes_generic.go -@@ -0,0 +1,28 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !gc || purego || !s390x -+// +build !gc purego !s390x -+ -+package sha3 -+ -+import ( -+ "hash" -+) -+ -+// new224Asm returns an assembly implementation of SHA3-224 if available, -+// otherwise it returns nil. -+func new224Asm() hash.Hash { return nil } -+ -+// new256Asm returns an assembly implementation of SHA3-256 if available, -+// otherwise it returns nil. -+func new256Asm() hash.Hash { return nil } -+ -+// new384Asm returns an assembly implementation of SHA3-384 if available, -+// otherwise it returns nil. -+func new384Asm() hash.Hash { return nil } -+ -+// new512Asm returns an assembly implementation of SHA3-512 if available, -+// otherwise it returns nil. -+func new512Asm() hash.Hash { return nil } -diff --git a/ms_mod/golang.org/x/crypto/sha3/keccakf.go b/ms_mod/golang.org/x/crypto/sha3/keccakf.go -new file mode 100644 -index 00000000000000..e5faa375c04e87 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/keccakf.go -@@ -0,0 +1,415 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !amd64 || purego || !gc -+// +build !amd64 purego !gc -+ -+package sha3 -+ -+import "math/bits" -+ -+// rc stores the round constants for use in the ΞΉ step. -+var rc = [24]uint64{ -+ 0x0000000000000001, -+ 0x0000000000008082, -+ 0x800000000000808A, -+ 0x8000000080008000, -+ 0x000000000000808B, -+ 0x0000000080000001, -+ 0x8000000080008081, -+ 0x8000000000008009, -+ 0x000000000000008A, -+ 0x0000000000000088, -+ 0x0000000080008009, -+ 0x000000008000000A, -+ 0x000000008000808B, -+ 0x800000000000008B, -+ 0x8000000000008089, -+ 0x8000000000008003, -+ 0x8000000000008002, -+ 0x8000000000000080, -+ 0x000000000000800A, -+ 0x800000008000000A, -+ 0x8000000080008081, -+ 0x8000000000008080, -+ 0x0000000080000001, -+ 0x8000000080008008, -+} -+ -+// keccakF1600 applies the Keccak permutation to a 1600b-wide -+// state represented as a slice of 25 uint64s. -+func keccakF1600(a *[25]uint64) { -+ // Implementation translated from Keccak-inplace.c -+ // in the keccak reference code. -+ var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 -+ -+ for i := 0; i < 24; i += 4 { -+ // Combines the 5 steps in each round into 2 steps. -+ // Unrolls 4 rounds per loop and spreads some steps across rounds. -+ -+ // Round 1 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[6] ^ d1 -+ bc1 = bits.RotateLeft64(t, 44) -+ t = a[12] ^ d2 -+ bc2 = bits.RotateLeft64(t, 43) -+ t = a[18] ^ d3 -+ bc3 = bits.RotateLeft64(t, 21) -+ t = a[24] ^ d4 -+ bc4 = bits.RotateLeft64(t, 14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc2 = bits.RotateLeft64(t, 3) -+ t = a[16] ^ d1 -+ bc3 = bits.RotateLeft64(t, 45) -+ t = a[22] ^ d2 -+ bc4 = bits.RotateLeft64(t, 61) -+ t = a[3] ^ d3 -+ bc0 = bits.RotateLeft64(t, 28) -+ t = a[9] ^ d4 -+ bc1 = bits.RotateLeft64(t, 20) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc4 = bits.RotateLeft64(t, 18) -+ t = a[1] ^ d1 -+ bc0 = bits.RotateLeft64(t, 1) -+ t = a[7] ^ d2 -+ bc1 = bits.RotateLeft64(t, 6) -+ t = a[13] ^ d3 -+ bc2 = bits.RotateLeft64(t, 25) -+ t = a[19] ^ d4 -+ bc3 = bits.RotateLeft64(t, 8) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc1 = bits.RotateLeft64(t, 36) -+ t = a[11] ^ d1 -+ bc2 = bits.RotateLeft64(t, 10) -+ t = a[17] ^ d2 -+ bc3 = bits.RotateLeft64(t, 15) -+ t = a[23] ^ d3 -+ bc4 = bits.RotateLeft64(t, 56) -+ t = a[4] ^ d4 -+ bc0 = bits.RotateLeft64(t, 27) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc3 = bits.RotateLeft64(t, 41) -+ t = a[21] ^ d1 -+ bc4 = bits.RotateLeft64(t, 2) -+ t = a[2] ^ d2 -+ bc0 = bits.RotateLeft64(t, 62) -+ t = a[8] ^ d3 -+ bc1 = bits.RotateLeft64(t, 55) -+ t = a[14] ^ d4 -+ bc2 = bits.RotateLeft64(t, 39) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ // Round 2 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[16] ^ d1 -+ bc1 = bits.RotateLeft64(t, 44) -+ t = a[7] ^ d2 -+ bc2 = bits.RotateLeft64(t, 43) -+ t = a[23] ^ d3 -+ bc3 = bits.RotateLeft64(t, 21) -+ t = a[14] ^ d4 -+ bc4 = bits.RotateLeft64(t, 14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc2 = bits.RotateLeft64(t, 3) -+ t = a[11] ^ d1 -+ bc3 = bits.RotateLeft64(t, 45) -+ t = a[2] ^ d2 -+ bc4 = bits.RotateLeft64(t, 61) -+ t = a[18] ^ d3 -+ bc0 = bits.RotateLeft64(t, 28) -+ t = a[9] ^ d4 -+ bc1 = bits.RotateLeft64(t, 20) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc4 = bits.RotateLeft64(t, 18) -+ t = a[6] ^ d1 -+ bc0 = bits.RotateLeft64(t, 1) -+ t = a[22] ^ d2 -+ bc1 = bits.RotateLeft64(t, 6) -+ t = a[13] ^ d3 -+ bc2 = bits.RotateLeft64(t, 25) -+ t = a[4] ^ d4 -+ bc3 = bits.RotateLeft64(t, 8) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc1 = bits.RotateLeft64(t, 36) -+ t = a[1] ^ d1 -+ bc2 = bits.RotateLeft64(t, 10) -+ t = a[17] ^ d2 -+ bc3 = bits.RotateLeft64(t, 15) -+ t = a[8] ^ d3 -+ bc4 = bits.RotateLeft64(t, 56) -+ t = a[24] ^ d4 -+ bc0 = bits.RotateLeft64(t, 27) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc3 = bits.RotateLeft64(t, 41) -+ t = a[21] ^ d1 -+ bc4 = bits.RotateLeft64(t, 2) -+ t = a[12] ^ d2 -+ bc0 = bits.RotateLeft64(t, 62) -+ t = a[3] ^ d3 -+ bc1 = bits.RotateLeft64(t, 55) -+ t = a[19] ^ d4 -+ bc2 = bits.RotateLeft64(t, 39) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ // Round 3 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[11] ^ d1 -+ bc1 = bits.RotateLeft64(t, 44) -+ t = a[22] ^ d2 -+ bc2 = bits.RotateLeft64(t, 43) -+ t = a[8] ^ d3 -+ bc3 = bits.RotateLeft64(t, 21) -+ t = a[19] ^ d4 -+ bc4 = bits.RotateLeft64(t, 14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc2 = bits.RotateLeft64(t, 3) -+ t = a[1] ^ d1 -+ bc3 = bits.RotateLeft64(t, 45) -+ t = a[12] ^ d2 -+ bc4 = bits.RotateLeft64(t, 61) -+ t = a[23] ^ d3 -+ bc0 = bits.RotateLeft64(t, 28) -+ t = a[9] ^ d4 -+ bc1 = bits.RotateLeft64(t, 20) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc4 = bits.RotateLeft64(t, 18) -+ t = a[16] ^ d1 -+ bc0 = bits.RotateLeft64(t, 1) -+ t = a[2] ^ d2 -+ bc1 = bits.RotateLeft64(t, 6) -+ t = a[13] ^ d3 -+ bc2 = bits.RotateLeft64(t, 25) -+ t = a[24] ^ d4 -+ bc3 = bits.RotateLeft64(t, 8) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc1 = bits.RotateLeft64(t, 36) -+ t = a[6] ^ d1 -+ bc2 = bits.RotateLeft64(t, 10) -+ t = a[17] ^ d2 -+ bc3 = bits.RotateLeft64(t, 15) -+ t = a[3] ^ d3 -+ bc4 = bits.RotateLeft64(t, 56) -+ t = a[14] ^ d4 -+ bc0 = bits.RotateLeft64(t, 27) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc3 = bits.RotateLeft64(t, 41) -+ t = a[21] ^ d1 -+ bc4 = bits.RotateLeft64(t, 2) -+ t = a[7] ^ d2 -+ bc0 = bits.RotateLeft64(t, 62) -+ t = a[18] ^ d3 -+ bc1 = bits.RotateLeft64(t, 55) -+ t = a[4] ^ d4 -+ bc2 = bits.RotateLeft64(t, 39) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ // Round 4 -+ bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] -+ bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] -+ bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] -+ bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] -+ bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] -+ d0 = bc4 ^ (bc1<<1 | bc1>>63) -+ d1 = bc0 ^ (bc2<<1 | bc2>>63) -+ d2 = bc1 ^ (bc3<<1 | bc3>>63) -+ d3 = bc2 ^ (bc4<<1 | bc4>>63) -+ d4 = bc3 ^ (bc0<<1 | bc0>>63) -+ -+ bc0 = a[0] ^ d0 -+ t = a[1] ^ d1 -+ bc1 = bits.RotateLeft64(t, 44) -+ t = a[2] ^ d2 -+ bc2 = bits.RotateLeft64(t, 43) -+ t = a[3] ^ d3 -+ bc3 = bits.RotateLeft64(t, 21) -+ t = a[4] ^ d4 -+ bc4 = bits.RotateLeft64(t, 14) -+ a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] -+ a[1] = bc1 ^ (bc3 &^ bc2) -+ a[2] = bc2 ^ (bc4 &^ bc3) -+ a[3] = bc3 ^ (bc0 &^ bc4) -+ a[4] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[5] ^ d0 -+ bc2 = bits.RotateLeft64(t, 3) -+ t = a[6] ^ d1 -+ bc3 = bits.RotateLeft64(t, 45) -+ t = a[7] ^ d2 -+ bc4 = bits.RotateLeft64(t, 61) -+ t = a[8] ^ d3 -+ bc0 = bits.RotateLeft64(t, 28) -+ t = a[9] ^ d4 -+ bc1 = bits.RotateLeft64(t, 20) -+ a[5] = bc0 ^ (bc2 &^ bc1) -+ a[6] = bc1 ^ (bc3 &^ bc2) -+ a[7] = bc2 ^ (bc4 &^ bc3) -+ a[8] = bc3 ^ (bc0 &^ bc4) -+ a[9] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[10] ^ d0 -+ bc4 = bits.RotateLeft64(t, 18) -+ t = a[11] ^ d1 -+ bc0 = bits.RotateLeft64(t, 1) -+ t = a[12] ^ d2 -+ bc1 = bits.RotateLeft64(t, 6) -+ t = a[13] ^ d3 -+ bc2 = bits.RotateLeft64(t, 25) -+ t = a[14] ^ d4 -+ bc3 = bits.RotateLeft64(t, 8) -+ a[10] = bc0 ^ (bc2 &^ bc1) -+ a[11] = bc1 ^ (bc3 &^ bc2) -+ a[12] = bc2 ^ (bc4 &^ bc3) -+ a[13] = bc3 ^ (bc0 &^ bc4) -+ a[14] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[15] ^ d0 -+ bc1 = bits.RotateLeft64(t, 36) -+ t = a[16] ^ d1 -+ bc2 = bits.RotateLeft64(t, 10) -+ t = a[17] ^ d2 -+ bc3 = bits.RotateLeft64(t, 15) -+ t = a[18] ^ d3 -+ bc4 = bits.RotateLeft64(t, 56) -+ t = a[19] ^ d4 -+ bc0 = bits.RotateLeft64(t, 27) -+ a[15] = bc0 ^ (bc2 &^ bc1) -+ a[16] = bc1 ^ (bc3 &^ bc2) -+ a[17] = bc2 ^ (bc4 &^ bc3) -+ a[18] = bc3 ^ (bc0 &^ bc4) -+ a[19] = bc4 ^ (bc1 &^ bc0) -+ -+ t = a[20] ^ d0 -+ bc3 = bits.RotateLeft64(t, 41) -+ t = a[21] ^ d1 -+ bc4 = bits.RotateLeft64(t, 2) -+ t = a[22] ^ d2 -+ bc0 = bits.RotateLeft64(t, 62) -+ t = a[23] ^ d3 -+ bc1 = bits.RotateLeft64(t, 55) -+ t = a[24] ^ d4 -+ bc2 = bits.RotateLeft64(t, 39) -+ a[20] = bc0 ^ (bc2 &^ bc1) -+ a[21] = bc1 ^ (bc3 &^ bc2) -+ a[22] = bc2 ^ (bc4 &^ bc3) -+ a[23] = bc3 ^ (bc0 &^ bc4) -+ a[24] = bc4 ^ (bc1 &^ bc0) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go -new file mode 100644 -index 00000000000000..248a38241ff9cf ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.go -@@ -0,0 +1,14 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+package sha3 -+ -+// This function is implemented in keccakf_amd64.s. -+ -+//go:noescape -+ -+func keccakF1600(a *[25]uint64) -diff --git a/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s -new file mode 100644 -index 00000000000000..4cfa54383bfa83 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/keccakf_amd64.s -@@ -0,0 +1,391 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build amd64 && !purego && gc -+// +build amd64,!purego,gc -+ -+// This code was translated into a form compatible with 6a from the public -+// domain sources at https://github.com/gvanas/KeccakCodePackage -+ -+// Offsets in state -+#define _ba (0*8) -+#define _be (1*8) -+#define _bi (2*8) -+#define _bo (3*8) -+#define _bu (4*8) -+#define _ga (5*8) -+#define _ge (6*8) -+#define _gi (7*8) -+#define _go (8*8) -+#define _gu (9*8) -+#define _ka (10*8) -+#define _ke (11*8) -+#define _ki (12*8) -+#define _ko (13*8) -+#define _ku (14*8) -+#define _ma (15*8) -+#define _me (16*8) -+#define _mi (17*8) -+#define _mo (18*8) -+#define _mu (19*8) -+#define _sa (20*8) -+#define _se (21*8) -+#define _si (22*8) -+#define _so (23*8) -+#define _su (24*8) -+ -+// Temporary registers -+#define rT1 AX -+ -+// Round vars -+#define rpState DI -+#define rpStack SP -+ -+#define rDa BX -+#define rDe CX -+#define rDi DX -+#define rDo R8 -+#define rDu R9 -+ -+#define rBa R10 -+#define rBe R11 -+#define rBi R12 -+#define rBo R13 -+#define rBu R14 -+ -+#define rCa SI -+#define rCe BP -+#define rCi rBi -+#define rCo rBo -+#define rCu R15 -+ -+#define MOVQ_RBI_RCE MOVQ rBi, rCe -+#define XORQ_RT1_RCA XORQ rT1, rCa -+#define XORQ_RT1_RCE XORQ rT1, rCe -+#define XORQ_RBA_RCU XORQ rBa, rCu -+#define XORQ_RBE_RCU XORQ rBe, rCu -+#define XORQ_RDU_RCU XORQ rDu, rCu -+#define XORQ_RDA_RCA XORQ rDa, rCa -+#define XORQ_RDE_RCE XORQ rDe, rCe -+ -+#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ -+ /* Prepare round */ \ -+ MOVQ rCe, rDa; \ -+ ROLQ $1, rDa; \ -+ \ -+ MOVQ _bi(iState), rCi; \ -+ XORQ _gi(iState), rDi; \ -+ XORQ rCu, rDa; \ -+ XORQ _ki(iState), rCi; \ -+ XORQ _mi(iState), rDi; \ -+ XORQ rDi, rCi; \ -+ \ -+ MOVQ rCi, rDe; \ -+ ROLQ $1, rDe; \ -+ \ -+ MOVQ _bo(iState), rCo; \ -+ XORQ _go(iState), rDo; \ -+ XORQ rCa, rDe; \ -+ XORQ _ko(iState), rCo; \ -+ XORQ _mo(iState), rDo; \ -+ XORQ rDo, rCo; \ -+ \ -+ MOVQ rCo, rDi; \ -+ ROLQ $1, rDi; \ -+ \ -+ MOVQ rCu, rDo; \ -+ XORQ rCe, rDi; \ -+ ROLQ $1, rDo; \ -+ \ -+ MOVQ rCa, rDu; \ -+ XORQ rCi, rDo; \ -+ ROLQ $1, rDu; \ -+ \ -+ /* Result b */ \ -+ MOVQ _ba(iState), rBa; \ -+ MOVQ _ge(iState), rBe; \ -+ XORQ rCo, rDu; \ -+ MOVQ _ki(iState), rBi; \ -+ MOVQ _mo(iState), rBo; \ -+ MOVQ _su(iState), rBu; \ -+ XORQ rDe, rBe; \ -+ ROLQ $44, rBe; \ -+ XORQ rDi, rBi; \ -+ XORQ rDa, rBa; \ -+ ROLQ $43, rBi; \ -+ \ -+ MOVQ rBe, rCa; \ -+ MOVQ rc, rT1; \ -+ ORQ rBi, rCa; \ -+ XORQ rBa, rT1; \ -+ XORQ rT1, rCa; \ -+ MOVQ rCa, _ba(oState); \ -+ \ -+ XORQ rDu, rBu; \ -+ ROLQ $14, rBu; \ -+ MOVQ rBa, rCu; \ -+ ANDQ rBe, rCu; \ -+ XORQ rBu, rCu; \ -+ MOVQ rCu, _bu(oState); \ -+ \ -+ XORQ rDo, rBo; \ -+ ROLQ $21, rBo; \ -+ MOVQ rBo, rT1; \ -+ ANDQ rBu, rT1; \ -+ XORQ rBi, rT1; \ -+ MOVQ rT1, _bi(oState); \ -+ \ -+ NOTQ rBi; \ -+ ORQ rBa, rBu; \ -+ ORQ rBo, rBi; \ -+ XORQ rBo, rBu; \ -+ XORQ rBe, rBi; \ -+ MOVQ rBu, _bo(oState); \ -+ MOVQ rBi, _be(oState); \ -+ B_RBI_RCE; \ -+ \ -+ /* Result g */ \ -+ MOVQ _gu(iState), rBe; \ -+ XORQ rDu, rBe; \ -+ MOVQ _ka(iState), rBi; \ -+ ROLQ $20, rBe; \ -+ XORQ rDa, rBi; \ -+ ROLQ $3, rBi; \ -+ MOVQ _bo(iState), rBa; \ -+ MOVQ rBe, rT1; \ -+ ORQ rBi, rT1; \ -+ XORQ rDo, rBa; \ -+ MOVQ _me(iState), rBo; \ -+ MOVQ _si(iState), rBu; \ -+ ROLQ $28, rBa; \ -+ XORQ rBa, rT1; \ -+ MOVQ rT1, _ga(oState); \ -+ G_RT1_RCA; \ -+ \ -+ XORQ rDe, rBo; \ -+ ROLQ $45, rBo; \ -+ MOVQ rBi, rT1; \ -+ ANDQ rBo, rT1; \ -+ XORQ rBe, rT1; \ -+ MOVQ rT1, _ge(oState); \ -+ G_RT1_RCE; \ -+ \ -+ XORQ rDi, rBu; \ -+ ROLQ $61, rBu; \ -+ MOVQ rBu, rT1; \ -+ ORQ rBa, rT1; \ -+ XORQ rBo, rT1; \ -+ MOVQ rT1, _go(oState); \ -+ \ -+ ANDQ rBe, rBa; \ -+ XORQ rBu, rBa; \ -+ MOVQ rBa, _gu(oState); \ -+ NOTQ rBu; \ -+ G_RBA_RCU; \ -+ \ -+ ORQ rBu, rBo; \ -+ XORQ rBi, rBo; \ -+ MOVQ rBo, _gi(oState); \ -+ \ -+ /* Result k */ \ -+ MOVQ _be(iState), rBa; \ -+ MOVQ _gi(iState), rBe; \ -+ MOVQ _ko(iState), rBi; \ -+ MOVQ _mu(iState), rBo; \ -+ MOVQ _sa(iState), rBu; \ -+ XORQ rDi, rBe; \ -+ ROLQ $6, rBe; \ -+ XORQ rDo, rBi; \ -+ ROLQ $25, rBi; \ -+ MOVQ rBe, rT1; \ -+ ORQ rBi, rT1; \ -+ XORQ rDe, rBa; \ -+ ROLQ $1, rBa; \ -+ XORQ rBa, rT1; \ -+ MOVQ rT1, _ka(oState); \ -+ K_RT1_RCA; \ -+ \ -+ XORQ rDu, rBo; \ -+ ROLQ $8, rBo; \ -+ MOVQ rBi, rT1; \ -+ ANDQ rBo, rT1; \ -+ XORQ rBe, rT1; \ -+ MOVQ rT1, _ke(oState); \ -+ K_RT1_RCE; \ -+ \ -+ XORQ rDa, rBu; \ -+ ROLQ $18, rBu; \ -+ NOTQ rBo; \ -+ MOVQ rBo, rT1; \ -+ ANDQ rBu, rT1; \ -+ XORQ rBi, rT1; \ -+ MOVQ rT1, _ki(oState); \ -+ \ -+ MOVQ rBu, rT1; \ -+ ORQ rBa, rT1; \ -+ XORQ rBo, rT1; \ -+ MOVQ rT1, _ko(oState); \ -+ \ -+ ANDQ rBe, rBa; \ -+ XORQ rBu, rBa; \ -+ MOVQ rBa, _ku(oState); \ -+ K_RBA_RCU; \ -+ \ -+ /* Result m */ \ -+ MOVQ _ga(iState), rBe; \ -+ XORQ rDa, rBe; \ -+ MOVQ _ke(iState), rBi; \ -+ ROLQ $36, rBe; \ -+ XORQ rDe, rBi; \ -+ MOVQ _bu(iState), rBa; \ -+ ROLQ $10, rBi; \ -+ MOVQ rBe, rT1; \ -+ MOVQ _mi(iState), rBo; \ -+ ANDQ rBi, rT1; \ -+ XORQ rDu, rBa; \ -+ MOVQ _so(iState), rBu; \ -+ ROLQ $27, rBa; \ -+ XORQ rBa, rT1; \ -+ MOVQ rT1, _ma(oState); \ -+ M_RT1_RCA; \ -+ \ -+ XORQ rDi, rBo; \ -+ ROLQ $15, rBo; \ -+ MOVQ rBi, rT1; \ -+ ORQ rBo, rT1; \ -+ XORQ rBe, rT1; \ -+ MOVQ rT1, _me(oState); \ -+ M_RT1_RCE; \ -+ \ -+ XORQ rDo, rBu; \ -+ ROLQ $56, rBu; \ -+ NOTQ rBo; \ -+ MOVQ rBo, rT1; \ -+ ORQ rBu, rT1; \ -+ XORQ rBi, rT1; \ -+ MOVQ rT1, _mi(oState); \ -+ \ -+ ORQ rBa, rBe; \ -+ XORQ rBu, rBe; \ -+ MOVQ rBe, _mu(oState); \ -+ \ -+ ANDQ rBa, rBu; \ -+ XORQ rBo, rBu; \ -+ MOVQ rBu, _mo(oState); \ -+ M_RBE_RCU; \ -+ \ -+ /* Result s */ \ -+ MOVQ _bi(iState), rBa; \ -+ MOVQ _go(iState), rBe; \ -+ MOVQ _ku(iState), rBi; \ -+ XORQ rDi, rBa; \ -+ MOVQ _ma(iState), rBo; \ -+ ROLQ $62, rBa; \ -+ XORQ rDo, rBe; \ -+ MOVQ _se(iState), rBu; \ -+ ROLQ $55, rBe; \ -+ \ -+ XORQ rDu, rBi; \ -+ MOVQ rBa, rDu; \ -+ XORQ rDe, rBu; \ -+ ROLQ $2, rBu; \ -+ ANDQ rBe, rDu; \ -+ XORQ rBu, rDu; \ -+ MOVQ rDu, _su(oState); \ -+ \ -+ ROLQ $39, rBi; \ -+ S_RDU_RCU; \ -+ NOTQ rBe; \ -+ XORQ rDa, rBo; \ -+ MOVQ rBe, rDa; \ -+ ANDQ rBi, rDa; \ -+ XORQ rBa, rDa; \ -+ MOVQ rDa, _sa(oState); \ -+ S_RDA_RCA; \ -+ \ -+ ROLQ $41, rBo; \ -+ MOVQ rBi, rDe; \ -+ ORQ rBo, rDe; \ -+ XORQ rBe, rDe; \ -+ MOVQ rDe, _se(oState); \ -+ S_RDE_RCE; \ -+ \ -+ MOVQ rBo, rDi; \ -+ MOVQ rBu, rDo; \ -+ ANDQ rBu, rDi; \ -+ ORQ rBa, rDo; \ -+ XORQ rBi, rDi; \ -+ XORQ rBo, rDo; \ -+ MOVQ rDi, _si(oState); \ -+ MOVQ rDo, _so(oState) \ -+ -+// func keccakF1600(state *[25]uint64) -+TEXT Β·keccakF1600(SB), 0, $200-8 -+ MOVQ state+0(FP), rpState -+ -+ // Convert the user state into an internal state -+ NOTQ _be(rpState) -+ NOTQ _bi(rpState) -+ NOTQ _go(rpState) -+ NOTQ _ki(rpState) -+ NOTQ _mi(rpState) -+ NOTQ _sa(rpState) -+ -+ // Execute the KeccakF permutation -+ MOVQ _ba(rpState), rCa -+ MOVQ _be(rpState), rCe -+ MOVQ _bu(rpState), rCu -+ -+ XORQ _ga(rpState), rCa -+ XORQ _ge(rpState), rCe -+ XORQ _gu(rpState), rCu -+ -+ XORQ _ka(rpState), rCa -+ XORQ _ke(rpState), rCe -+ XORQ _ku(rpState), rCu -+ -+ XORQ _ma(rpState), rCa -+ XORQ _me(rpState), rCe -+ XORQ _mu(rpState), rCu -+ -+ XORQ _sa(rpState), rCa -+ XORQ _se(rpState), rCe -+ MOVQ _si(rpState), rDi -+ MOVQ _so(rpState), rDo -+ XORQ _su(rpState), rCu -+ -+ mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) -+ mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) -+ -+ // Revert the internal state to the user state -+ NOTQ _be(rpState) -+ NOTQ _bi(rpState) -+ NOTQ _go(rpState) -+ NOTQ _ki(rpState) -+ NOTQ _mi(rpState) -+ NOTQ _sa(rpState) -+ -+ RET -diff --git a/ms_mod/golang.org/x/crypto/sha3/register.go b/ms_mod/golang.org/x/crypto/sha3/register.go -new file mode 100644 -index 00000000000000..8b4453aac3c332 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/register.go -@@ -0,0 +1,19 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.4 -+// +build go1.4 -+ -+package sha3 -+ -+import ( -+ "crypto" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.SHA3_224, New224) -+ crypto.RegisterHash(crypto.SHA3_256, New256) -+ crypto.RegisterHash(crypto.SHA3_384, New384) -+ crypto.RegisterHash(crypto.SHA3_512, New512) -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3.go b/ms_mod/golang.org/x/crypto/sha3/sha3.go -new file mode 100644 -index 00000000000000..fa182beb40b509 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/sha3.go -@@ -0,0 +1,193 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// spongeDirection indicates the direction bytes are flowing through the sponge. -+type spongeDirection int -+ -+const ( -+ // spongeAbsorbing indicates that the sponge is absorbing input. -+ spongeAbsorbing spongeDirection = iota -+ // spongeSqueezing indicates that the sponge is being squeezed. -+ spongeSqueezing -+) -+ -+const ( -+ // maxRate is the maximum size of the internal buffer. SHAKE-256 -+ // currently needs the largest buffer. -+ maxRate = 168 -+) -+ -+type state struct { -+ // Generic sponge components. -+ a [25]uint64 // main state of the hash -+ buf []byte // points into storage -+ rate int // the number of bytes of state to use -+ -+ // dsbyte contains the "domain separation" bits and the first bit of -+ // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the -+ // SHA-3 and SHAKE functions by appending bitstrings to the message. -+ // Using a little-endian bit-ordering convention, these are "01" for SHA-3 -+ // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the -+ // padding rule from section 5.1 is applied to pad the message to a multiple -+ // of the rate, which involves adding a "1" bit, zero or more "0" bits, and -+ // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, -+ // giving 00000110b (0x06) and 00011111b (0x1f). -+ // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf -+ // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and -+ // Extendable-Output Functions (May 2014)" -+ dsbyte byte -+ -+ storage storageBuf -+ -+ // Specific to SHA-3 and SHAKE. -+ outputLen int // the default output size in bytes -+ state spongeDirection // whether the sponge is absorbing or squeezing -+} -+ -+// BlockSize returns the rate of sponge underlying this hash function. -+func (d *state) BlockSize() int { return d.rate } -+ -+// Size returns the output size of the hash function in bytes. -+func (d *state) Size() int { return d.outputLen } -+ -+// Reset clears the internal state by zeroing the sponge state and -+// the byte buffer, and setting Sponge.state to absorbing. -+func (d *state) Reset() { -+ // Zero the permutation's state. -+ for i := range d.a { -+ d.a[i] = 0 -+ } -+ d.state = spongeAbsorbing -+ d.buf = d.storage.asBytes()[:0] -+} -+ -+func (d *state) clone() *state { -+ ret := *d -+ if ret.state == spongeAbsorbing { -+ ret.buf = ret.storage.asBytes()[:len(ret.buf)] -+ } else { -+ ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate] -+ } -+ -+ return &ret -+} -+ -+// permute applies the KeccakF-1600 permutation. It handles -+// any input-output buffering. -+func (d *state) permute() { -+ switch d.state { -+ case spongeAbsorbing: -+ // If we're absorbing, we need to xor the input into the state -+ // before applying the permutation. -+ xorIn(d, d.buf) -+ d.buf = d.storage.asBytes()[:0] -+ keccakF1600(&d.a) -+ case spongeSqueezing: -+ // If we're squeezing, we need to apply the permutation before -+ // copying more output. -+ keccakF1600(&d.a) -+ d.buf = d.storage.asBytes()[:d.rate] -+ copyOut(d, d.buf) -+ } -+} -+ -+// pads appends the domain separation bits in dsbyte, applies -+// the multi-bitrate 10..1 padding rule, and permutes the state. -+func (d *state) padAndPermute(dsbyte byte) { -+ if d.buf == nil { -+ d.buf = d.storage.asBytes()[:0] -+ } -+ // Pad with this instance's domain-separator bits. We know that there's -+ // at least one byte of space in d.buf because, if it were full, -+ // permute would have been called to empty it. dsbyte also contains the -+ // first one bit for the padding. See the comment in the state struct. -+ d.buf = append(d.buf, dsbyte) -+ zerosStart := len(d.buf) -+ d.buf = d.storage.asBytes()[:d.rate] -+ for i := zerosStart; i < d.rate; i++ { -+ d.buf[i] = 0 -+ } -+ // This adds the final one bit for the padding. Because of the way that -+ // bits are numbered from the LSB upwards, the final bit is the MSB of -+ // the last byte. -+ d.buf[d.rate-1] ^= 0x80 -+ // Apply the permutation -+ d.permute() -+ d.state = spongeSqueezing -+ d.buf = d.storage.asBytes()[:d.rate] -+ copyOut(d, d.buf) -+} -+ -+// Write absorbs more data into the hash's state. It produces an error -+// if more data is written to the ShakeHash after writing -+func (d *state) Write(p []byte) (written int, err error) { -+ if d.state != spongeAbsorbing { -+ panic("sha3: write to sponge after read") -+ } -+ if d.buf == nil { -+ d.buf = d.storage.asBytes()[:0] -+ } -+ written = len(p) -+ -+ for len(p) > 0 { -+ if len(d.buf) == 0 && len(p) >= d.rate { -+ // The fast path; absorb a full "rate" bytes of input and apply the permutation. -+ xorIn(d, p[:d.rate]) -+ p = p[d.rate:] -+ keccakF1600(&d.a) -+ } else { -+ // The slow path; buffer the input until we can fill the sponge, and then xor it in. -+ todo := d.rate - len(d.buf) -+ if todo > len(p) { -+ todo = len(p) -+ } -+ d.buf = append(d.buf, p[:todo]...) -+ p = p[todo:] -+ -+ // If the sponge is full, apply the permutation. -+ if len(d.buf) == d.rate { -+ d.permute() -+ } -+ } -+ } -+ -+ return -+} -+ -+// Read squeezes an arbitrary number of bytes from the sponge. -+func (d *state) Read(out []byte) (n int, err error) { -+ // If we're still absorbing, pad and apply the permutation. -+ if d.state == spongeAbsorbing { -+ d.padAndPermute(d.dsbyte) -+ } -+ -+ n = len(out) -+ -+ // Now, do the squeezing. -+ for len(out) > 0 { -+ n := copy(out, d.buf) -+ d.buf = d.buf[n:] -+ out = out[n:] -+ -+ // Apply the permutation if we've squeezed the sponge dry. -+ if len(d.buf) == 0 { -+ d.permute() -+ } -+ } -+ -+ return -+} -+ -+// Sum applies padding to the hash state and then squeezes out the desired -+// number of output bytes. -+func (d *state) Sum(in []byte) []byte { -+ // Make a copy of the original hash so that caller can keep writing -+ // and summing. -+ dup := d.clone() -+ hash := make([]byte, dup.outputLen) -+ dup.Read(hash) -+ return append(in, hash...) -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go -new file mode 100644 -index 00000000000000..63a3edb4cea70b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.go -@@ -0,0 +1,287 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+package sha3 -+ -+// This file contains code for using the 'compute intermediate -+// message digest' (KIMD) and 'compute last message digest' (KLMD) -+// instructions to compute SHA-3 and SHAKE hashes on IBM Z. -+ -+import ( -+ "hash" -+ -+ "golang.org/x/sys/cpu" -+) -+ -+// codes represent 7-bit KIMD/KLMD function codes as defined in -+// the Principles of Operation. -+type code uint64 -+ -+const ( -+ // function codes for KIMD/KLMD -+ sha3_224 code = 32 -+ sha3_256 = 33 -+ sha3_384 = 34 -+ sha3_512 = 35 -+ shake_128 = 36 -+ shake_256 = 37 -+ nopad = 0x100 -+) -+ -+// kimd is a wrapper for the 'compute intermediate message digest' instruction. -+// src must be a multiple of the rate for the given function code. -+// -+//go:noescape -+func kimd(function code, chain *[200]byte, src []byte) -+ -+// klmd is a wrapper for the 'compute last message digest' instruction. -+// src padding is handled by the instruction. -+// -+//go:noescape -+func klmd(function code, chain *[200]byte, dst, src []byte) -+ -+type asmState struct { -+ a [200]byte // 1600 bit state -+ buf []byte // care must be taken to ensure cap(buf) is a multiple of rate -+ rate int // equivalent to block size -+ storage [3072]byte // underlying storage for buf -+ outputLen int // output length if fixed, 0 if not -+ function code // KIMD/KLMD function code -+ state spongeDirection // whether the sponge is absorbing or squeezing -+} -+ -+func newAsmState(function code) *asmState { -+ var s asmState -+ s.function = function -+ switch function { -+ case sha3_224: -+ s.rate = 144 -+ s.outputLen = 28 -+ case sha3_256: -+ s.rate = 136 -+ s.outputLen = 32 -+ case sha3_384: -+ s.rate = 104 -+ s.outputLen = 48 -+ case sha3_512: -+ s.rate = 72 -+ s.outputLen = 64 -+ case shake_128: -+ s.rate = 168 -+ case shake_256: -+ s.rate = 136 -+ default: -+ panic("sha3: unrecognized function code") -+ } -+ -+ // limit s.buf size to a multiple of s.rate -+ s.resetBuf() -+ return &s -+} -+ -+func (s *asmState) clone() *asmState { -+ c := *s -+ c.buf = c.storage[:len(s.buf):cap(s.buf)] -+ return &c -+} -+ -+// copyIntoBuf copies b into buf. It will panic if there is not enough space to -+// store all of b. -+func (s *asmState) copyIntoBuf(b []byte) { -+ bufLen := len(s.buf) -+ s.buf = s.buf[:len(s.buf)+len(b)] -+ copy(s.buf[bufLen:], b) -+} -+ -+// resetBuf points buf at storage, sets the length to 0 and sets cap to be a -+// multiple of the rate. -+func (s *asmState) resetBuf() { -+ max := (cap(s.storage) / s.rate) * s.rate -+ s.buf = s.storage[:0:max] -+} -+ -+// Write (via the embedded io.Writer interface) adds more data to the running hash. -+// It never returns an error. -+func (s *asmState) Write(b []byte) (int, error) { -+ if s.state != spongeAbsorbing { -+ panic("sha3: write to sponge after read") -+ } -+ length := len(b) -+ for len(b) > 0 { -+ if len(s.buf) == 0 && len(b) >= cap(s.buf) { -+ // Hash the data directly and push any remaining bytes -+ // into the buffer. -+ remainder := len(b) % s.rate -+ kimd(s.function, &s.a, b[:len(b)-remainder]) -+ if remainder != 0 { -+ s.copyIntoBuf(b[len(b)-remainder:]) -+ } -+ return length, nil -+ } -+ -+ if len(s.buf) == cap(s.buf) { -+ // flush the buffer -+ kimd(s.function, &s.a, s.buf) -+ s.buf = s.buf[:0] -+ } -+ -+ // copy as much as we can into the buffer -+ n := len(b) -+ if len(b) > cap(s.buf)-len(s.buf) { -+ n = cap(s.buf) - len(s.buf) -+ } -+ s.copyIntoBuf(b[:n]) -+ b = b[n:] -+ } -+ return length, nil -+} -+ -+// Read squeezes an arbitrary number of bytes from the sponge. -+func (s *asmState) Read(out []byte) (n int, err error) { -+ n = len(out) -+ -+ // need to pad if we were absorbing -+ if s.state == spongeAbsorbing { -+ s.state = spongeSqueezing -+ -+ // write hash directly into out if possible -+ if len(out)%s.rate == 0 { -+ klmd(s.function, &s.a, out, s.buf) // len(out) may be 0 -+ s.buf = s.buf[:0] -+ return -+ } -+ -+ // write hash into buffer -+ max := cap(s.buf) -+ if max > len(out) { -+ max = (len(out)/s.rate)*s.rate + s.rate -+ } -+ klmd(s.function, &s.a, s.buf[:max], s.buf) -+ s.buf = s.buf[:max] -+ } -+ -+ for len(out) > 0 { -+ // flush the buffer -+ if len(s.buf) != 0 { -+ c := copy(out, s.buf) -+ out = out[c:] -+ s.buf = s.buf[c:] -+ continue -+ } -+ -+ // write hash directly into out if possible -+ if len(out)%s.rate == 0 { -+ klmd(s.function|nopad, &s.a, out, nil) -+ return -+ } -+ -+ // write hash into buffer -+ s.resetBuf() -+ if cap(s.buf) > len(out) { -+ s.buf = s.buf[:(len(out)/s.rate)*s.rate+s.rate] -+ } -+ klmd(s.function|nopad, &s.a, s.buf, nil) -+ } -+ return -+} -+ -+// Sum appends the current hash to b and returns the resulting slice. -+// It does not change the underlying hash state. -+func (s *asmState) Sum(b []byte) []byte { -+ if s.outputLen == 0 { -+ panic("sha3: cannot call Sum on SHAKE functions") -+ } -+ -+ // Copy the state to preserve the original. -+ a := s.a -+ -+ // Hash the buffer. Note that we don't clear it because we -+ // aren't updating the state. -+ klmd(s.function, &a, nil, s.buf) -+ return append(b, a[:s.outputLen]...) -+} -+ -+// Reset resets the Hash to its initial state. -+func (s *asmState) Reset() { -+ for i := range s.a { -+ s.a[i] = 0 -+ } -+ s.resetBuf() -+ s.state = spongeAbsorbing -+} -+ -+// Size returns the number of bytes Sum will return. -+func (s *asmState) Size() int { -+ return s.outputLen -+} -+ -+// BlockSize returns the hash's underlying block size. -+// The Write method must be able to accept any amount -+// of data, but it may operate more efficiently if all writes -+// are a multiple of the block size. -+func (s *asmState) BlockSize() int { -+ return s.rate -+} -+ -+// Clone returns a copy of the ShakeHash in its current state. -+func (s *asmState) Clone() ShakeHash { -+ return s.clone() -+} -+ -+// new224Asm returns an assembly implementation of SHA3-224 if available, -+// otherwise it returns nil. -+func new224Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_224) -+ } -+ return nil -+} -+ -+// new256Asm returns an assembly implementation of SHA3-256 if available, -+// otherwise it returns nil. -+func new256Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_256) -+ } -+ return nil -+} -+ -+// new384Asm returns an assembly implementation of SHA3-384 if available, -+// otherwise it returns nil. -+func new384Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_384) -+ } -+ return nil -+} -+ -+// new512Asm returns an assembly implementation of SHA3-512 if available, -+// otherwise it returns nil. -+func new512Asm() hash.Hash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(sha3_512) -+ } -+ return nil -+} -+ -+// newShake128Asm returns an assembly implementation of SHAKE-128 if available, -+// otherwise it returns nil. -+func newShake128Asm() ShakeHash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(shake_128) -+ } -+ return nil -+} -+ -+// newShake256Asm returns an assembly implementation of SHAKE-256 if available, -+// otherwise it returns nil. -+func newShake256Asm() ShakeHash { -+ if cpu.S390X.HasSHA3 { -+ return newAsmState(shake_256) -+ } -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s -new file mode 100644 -index 00000000000000..a0e051b0451e59 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/sha3_s390x.s -@@ -0,0 +1,34 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build gc && !purego -+// +build gc,!purego -+ -+#include "textflag.h" -+ -+// func kimd(function code, chain *[200]byte, src []byte) -+TEXT Β·kimd(SB), NOFRAME|NOSPLIT, $0-40 -+ MOVD function+0(FP), R0 -+ MOVD chain+8(FP), R1 -+ LMG src+16(FP), R2, R3 // R2=base, R3=len -+ -+continue: -+ WORD $0xB93E0002 // KIMD --, R2 -+ BVS continue // continue if interrupted -+ MOVD $0, R0 // reset R0 for pre-go1.8 compilers -+ RET -+ -+// func klmd(function code, chain *[200]byte, dst, src []byte) -+TEXT Β·klmd(SB), NOFRAME|NOSPLIT, $0-64 -+ // TODO: SHAKE support -+ MOVD function+0(FP), R0 -+ MOVD chain+8(FP), R1 -+ LMG dst+16(FP), R2, R3 // R2=base, R3=len -+ LMG src+40(FP), R4, R5 // R4=base, R5=len -+ -+continue: -+ WORD $0xB93F0024 // KLMD R2, R4 -+ BVS continue // continue if interrupted -+ MOVD $0, R0 // reset R0 for pre-go1.8 compilers -+ RET -diff --git a/ms_mod/golang.org/x/crypto/sha3/sha3_test.go b/ms_mod/golang.org/x/crypto/sha3/sha3_test.go -new file mode 100644 -index 00000000000000..83bd6195d6cd13 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/sha3_test.go -@@ -0,0 +1,490 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// Tests include all the ShortMsgKATs provided by the Keccak team at -+// https://github.com/gvanas/KeccakCodePackage -+// -+// They only include the zero-bit case of the bitwise testvectors -+// published by NIST in the draft of FIPS-202. -+ -+import ( -+ "bytes" -+ "compress/flate" -+ "encoding/hex" -+ "encoding/json" -+ "fmt" -+ "hash" -+ "math/rand" -+ "os" -+ "strings" -+ "testing" -+) -+ -+const ( -+ testString = "brekeccakkeccak koax koax" -+ katFilename = "testdata/keccakKats.json.deflate" -+) -+ -+// testDigests contains functions returning hash.Hash instances -+// with output-length equal to the KAT length for SHA-3, Keccak -+// and SHAKE instances. -+var testDigests = map[string]func() hash.Hash{ -+ "SHA3-224": New224, -+ "SHA3-256": New256, -+ "SHA3-384": New384, -+ "SHA3-512": New512, -+ "Keccak-256": NewLegacyKeccak256, -+ "Keccak-512": NewLegacyKeccak512, -+} -+ -+// testShakes contains functions that return sha3.ShakeHash instances for -+// with output-length equal to the KAT length. -+var testShakes = map[string]struct { -+ constructor func(N []byte, S []byte) ShakeHash -+ defAlgoName string -+ defCustomStr string -+}{ -+ // NewCShake without customization produces same result as SHAKE -+ "SHAKE128": {NewCShake128, "", ""}, -+ "SHAKE256": {NewCShake256, "", ""}, -+ "cSHAKE128": {NewCShake128, "CSHAKE128", "CustomStrign"}, -+ "cSHAKE256": {NewCShake256, "CSHAKE256", "CustomStrign"}, -+} -+ -+// decodeHex converts a hex-encoded string into a raw byte string. -+func decodeHex(s string) []byte { -+ b, err := hex.DecodeString(s) -+ if err != nil { -+ panic(err) -+ } -+ return b -+} -+ -+// structs used to marshal JSON test-cases. -+type KeccakKats struct { -+ Kats map[string][]struct { -+ Digest string `json:"digest"` -+ Length int64 `json:"length"` -+ Message string `json:"message"` -+ -+ // Defined only for cSHAKE -+ N string `json:"N"` -+ S string `json:"S"` -+ } -+} -+ -+func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { -+ xorInOrig, copyOutOrig := xorIn, copyOut -+ xorIn, copyOut = xorInGeneric, copyOutGeneric -+ testf("generic") -+ if xorImplementationUnaligned != "generic" { -+ xorIn, copyOut = xorInUnaligned, copyOutUnaligned -+ testf("unaligned") -+ } -+ xorIn, copyOut = xorInOrig, copyOutOrig -+} -+ -+// TestKeccakKats tests the SHA-3 and Shake implementations against all the -+// ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage -+// (The testvectors are stored in keccakKats.json.deflate due to their length.) -+func TestKeccakKats(t *testing.T) { -+ testUnalignedAndGeneric(t, func(impl string) { -+ // Read the KATs. -+ deflated, err := os.Open(katFilename) -+ if err != nil { -+ t.Errorf("error opening %s: %s", katFilename, err) -+ } -+ file := flate.NewReader(deflated) -+ dec := json.NewDecoder(file) -+ var katSet KeccakKats -+ err = dec.Decode(&katSet) -+ if err != nil { -+ t.Errorf("error decoding KATs: %s", err) -+ } -+ -+ for algo, function := range testDigests { -+ d := function() -+ for _, kat := range katSet.Kats[algo] { -+ d.Reset() -+ in, err := hex.DecodeString(kat.Message) -+ if err != nil { -+ t.Errorf("error decoding KAT: %s", err) -+ } -+ d.Write(in[:kat.Length/8]) -+ got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) -+ if got != kat.Digest { -+ t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", -+ algo, impl, kat.Length, kat.Message, got, kat.Digest) -+ t.Logf("wanted %+v", kat) -+ t.FailNow() -+ } -+ continue -+ } -+ } -+ -+ for algo, v := range testShakes { -+ for _, kat := range katSet.Kats[algo] { -+ N, err := hex.DecodeString(kat.N) -+ if err != nil { -+ t.Errorf("error decoding KAT: %s", err) -+ } -+ -+ S, err := hex.DecodeString(kat.S) -+ if err != nil { -+ t.Errorf("error decoding KAT: %s", err) -+ } -+ d := v.constructor(N, S) -+ in, err := hex.DecodeString(kat.Message) -+ if err != nil { -+ t.Errorf("error decoding KAT: %s", err) -+ } -+ -+ d.Write(in[:kat.Length/8]) -+ out := make([]byte, len(kat.Digest)/2) -+ d.Read(out) -+ got := strings.ToUpper(hex.EncodeToString(out)) -+ if got != kat.Digest { -+ t.Errorf("function=%s, implementation=%s, length=%d N:%s\n S:%s\nmessage:\n %s \ngot:\n %s\nwanted:\n %s", -+ algo, impl, kat.Length, kat.N, kat.S, kat.Message, got, kat.Digest) -+ t.Logf("wanted %+v", kat) -+ t.FailNow() -+ } -+ continue -+ } -+ } -+ }) -+} -+ -+// TestKeccak does a basic test of the non-standardized Keccak hash functions. -+func TestKeccak(t *testing.T) { -+ tests := []struct { -+ fn func() hash.Hash -+ data []byte -+ want string -+ }{ -+ { -+ NewLegacyKeccak256, -+ []byte("abc"), -+ "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", -+ }, -+ { -+ NewLegacyKeccak512, -+ []byte("abc"), -+ "18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96", -+ }, -+ } -+ -+ for _, u := range tests { -+ h := u.fn() -+ h.Write(u.data) -+ got := h.Sum(nil) -+ want := decodeHex(u.want) -+ if !bytes.Equal(got, want) { -+ t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want) -+ } -+ } -+} -+ -+// TestUnalignedWrite tests that writing data in an arbitrary pattern with -+// small input buffers. -+func TestUnalignedWrite(t *testing.T) { -+ testUnalignedAndGeneric(t, func(impl string) { -+ buf := sequentialBytes(0x10000) -+ for alg, df := range testDigests { -+ d := df() -+ d.Reset() -+ d.Write(buf) -+ want := d.Sum(nil) -+ d.Reset() -+ for i := 0; i < len(buf); { -+ // Cycle through offsets which make a 137 byte sequence. -+ // Because 137 is prime this sequence should exercise all corner cases. -+ offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} -+ for _, j := range offsets { -+ if v := len(buf) - i; v < j { -+ j = v -+ } -+ d.Write(buf[i : i+j]) -+ i += j -+ } -+ } -+ got := d.Sum(nil) -+ if !bytes.Equal(got, want) { -+ t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) -+ } -+ } -+ -+ // Same for SHAKE -+ for alg, df := range testShakes { -+ want := make([]byte, 16) -+ got := make([]byte, 16) -+ d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr)) -+ -+ d.Reset() -+ d.Write(buf) -+ d.Read(want) -+ d.Reset() -+ for i := 0; i < len(buf); { -+ // Cycle through offsets which make a 137 byte sequence. -+ // Because 137 is prime this sequence should exercise all corner cases. -+ offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} -+ for _, j := range offsets { -+ if v := len(buf) - i; v < j { -+ j = v -+ } -+ d.Write(buf[i : i+j]) -+ i += j -+ } -+ } -+ d.Read(got) -+ if !bytes.Equal(got, want) { -+ t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) -+ } -+ } -+ }) -+} -+ -+// TestAppend checks that appending works when reallocation is necessary. -+func TestAppend(t *testing.T) { -+ testUnalignedAndGeneric(t, func(impl string) { -+ d := New224() -+ -+ for capacity := 2; capacity <= 66; capacity += 64 { -+ // The first time around the loop, Sum will have to reallocate. -+ // The second time, it will not. -+ buf := make([]byte, 2, capacity) -+ d.Reset() -+ d.Write([]byte{0xcc}) -+ buf = d.Sum(buf) -+ expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" -+ if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { -+ t.Errorf("got %s, want %s", got, expected) -+ } -+ } -+ }) -+} -+ -+// TestAppendNoRealloc tests that appending works when no reallocation is necessary. -+func TestAppendNoRealloc(t *testing.T) { -+ testUnalignedAndGeneric(t, func(impl string) { -+ buf := make([]byte, 1, 200) -+ d := New224() -+ d.Write([]byte{0xcc}) -+ buf = d.Sum(buf) -+ expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" -+ if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { -+ t.Errorf("%s: got %s, want %s", impl, got, expected) -+ } -+ }) -+} -+ -+// TestSqueezing checks that squeezing the full output a single time produces -+// the same output as repeatedly squeezing the instance. -+func TestSqueezing(t *testing.T) { -+ testUnalignedAndGeneric(t, func(impl string) { -+ for algo, v := range testShakes { -+ d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) -+ d0.Write([]byte(testString)) -+ ref := make([]byte, 32) -+ d0.Read(ref) -+ -+ d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr)) -+ d1.Write([]byte(testString)) -+ var multiple []byte -+ for range ref { -+ one := make([]byte, 1) -+ d1.Read(one) -+ multiple = append(multiple, one...) -+ } -+ if !bytes.Equal(ref, multiple) { -+ t.Errorf("%s (%s): squeezing %d bytes one at a time failed", algo, impl, len(ref)) -+ } -+ } -+ }) -+} -+ -+// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. -+// -+// The alignment of each slice is intentionally randomized to detect alignment -+// issues in the implementation. See https://golang.org/issue/37644. -+// Ideally, the compiler should fuzz the alignment itself. -+// (See https://golang.org/issue/35128.) -+func sequentialBytes(size int) []byte { -+ alignmentOffset := rand.Intn(8) -+ result := make([]byte, size+alignmentOffset)[alignmentOffset:] -+ for i := range result { -+ result[i] = byte(i) -+ } -+ return result -+} -+ -+func TestReset(t *testing.T) { -+ out1 := make([]byte, 32) -+ out2 := make([]byte, 32) -+ -+ for _, v := range testShakes { -+ // Calculate hash for the first time -+ c := v.constructor(nil, []byte{0x99, 0x98}) -+ c.Write(sequentialBytes(0x100)) -+ c.Read(out1) -+ -+ // Calculate hash again -+ c.Reset() -+ c.Write(sequentialBytes(0x100)) -+ c.Read(out2) -+ -+ if !bytes.Equal(out1, out2) { -+ t.Error("\nExpected:\n", out1, "\ngot:\n", out2) -+ } -+ } -+} -+ -+func TestClone(t *testing.T) { -+ out1 := make([]byte, 16) -+ out2 := make([]byte, 16) -+ -+ // Test for sizes smaller and larger than block size. -+ for _, size := range []int{0x1, 0x100} { -+ in := sequentialBytes(size) -+ for _, v := range testShakes { -+ h1 := v.constructor(nil, []byte{0x01}) -+ h1.Write([]byte{0x01}) -+ -+ h2 := h1.Clone() -+ -+ h1.Write(in) -+ h1.Read(out1) -+ -+ h2.Write(in) -+ h2.Read(out2) -+ -+ if !bytes.Equal(out1, out2) { -+ t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2)) -+ } -+ } -+ } -+} -+ -+// BenchmarkPermutationFunction measures the speed of the permutation function -+// with no input data. -+func BenchmarkPermutationFunction(b *testing.B) { -+ b.SetBytes(int64(200)) -+ var lanes [25]uint64 -+ for i := 0; i < b.N; i++ { -+ keccakF1600(&lanes) -+ } -+} -+ -+// benchmarkHash tests the speed to hash num buffers of buflen each. -+func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { -+ b.StopTimer() -+ h.Reset() -+ data := sequentialBytes(size) -+ b.SetBytes(int64(size * num)) -+ b.StartTimer() -+ -+ var state []byte -+ for i := 0; i < b.N; i++ { -+ for j := 0; j < num; j++ { -+ h.Write(data) -+ } -+ state = h.Sum(state[:0]) -+ } -+ b.StopTimer() -+ h.Reset() -+} -+ -+// benchmarkShake is specialized to the Shake instances, which don't -+// require a copy on reading output. -+func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { -+ b.StopTimer() -+ h.Reset() -+ data := sequentialBytes(size) -+ d := make([]byte, 32) -+ -+ b.SetBytes(int64(size * num)) -+ b.StartTimer() -+ -+ for i := 0; i < b.N; i++ { -+ h.Reset() -+ for j := 0; j < num; j++ { -+ h.Write(data) -+ } -+ h.Read(d) -+ } -+} -+ -+func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } -+func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } -+func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } -+func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } -+ -+func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } -+func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } -+func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } -+func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } -+ -+func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } -+ -+func Example_sum() { -+ buf := []byte("some data to hash") -+ // A hash needs to be 64 bytes long to have 256-bit collision resistance. -+ h := make([]byte, 64) -+ // Compute a 64-byte hash of buf and put it in h. -+ ShakeSum256(h, buf) -+ fmt.Printf("%x\n", h) -+ // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d -+} -+ -+func Example_mac() { -+ k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") -+ buf := []byte("and this is some data to authenticate") -+ // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key. -+ h := make([]byte, 32) -+ d := NewShake256() -+ // Write the key into the hash. -+ d.Write(k) -+ // Now write the data. -+ d.Write(buf) -+ // Read 32 bytes of output from the hash into h. -+ d.Read(h) -+ fmt.Printf("%x\n", h) -+ // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff -+} -+ -+func ExampleNewCShake256() { -+ out := make([]byte, 32) -+ msg := []byte("The quick brown fox jumps over the lazy dog") -+ -+ // Example 1: Simple cshake -+ c1 := NewCShake256([]byte("NAME"), []byte("Partition1")) -+ c1.Write(msg) -+ c1.Read(out) -+ fmt.Println(hex.EncodeToString(out)) -+ -+ // Example 2: Different customization string produces different digest -+ c1 = NewCShake256([]byte("NAME"), []byte("Partition2")) -+ c1.Write(msg) -+ c1.Read(out) -+ fmt.Println(hex.EncodeToString(out)) -+ -+ // Example 3: Longer output length produces longer digest -+ out = make([]byte, 64) -+ c1 = NewCShake256([]byte("NAME"), []byte("Partition1")) -+ c1.Write(msg) -+ c1.Read(out) -+ fmt.Println(hex.EncodeToString(out)) -+ -+ // Example 4: Next read produces different result -+ c1.Read(out) -+ fmt.Println(hex.EncodeToString(out)) -+ -+ // Output: -+ //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b -+ //a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0 -+ //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8 -+ //85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109 -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/shake.go b/ms_mod/golang.org/x/crypto/sha3/shake.go -new file mode 100644 -index 00000000000000..d7be2954ab26a8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/shake.go -@@ -0,0 +1,173 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+// This file defines the ShakeHash interface, and provides -+// functions for creating SHAKE and cSHAKE instances, as well as utility -+// functions for hashing bytes to arbitrary-length output. -+// -+// -+// SHAKE implementation is based on FIPS PUB 202 [1] -+// cSHAKE implementations is based on NIST SP 800-185 [2] -+// -+// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf -+// [2] https://doi.org/10.6028/NIST.SP.800-185 -+ -+import ( -+ "encoding/binary" -+ "io" -+) -+ -+// ShakeHash defines the interface to hash functions that -+// support arbitrary-length output. -+type ShakeHash interface { -+ // Write absorbs more data into the hash's state. It panics if input is -+ // written to it after output has been read from it. -+ io.Writer -+ -+ // Read reads more output from the hash; reading affects the hash's -+ // state. (ShakeHash.Read is thus very different from Hash.Sum) -+ // It never returns an error. -+ io.Reader -+ -+ // Clone returns a copy of the ShakeHash in its current state. -+ Clone() ShakeHash -+ -+ // Reset resets the ShakeHash to its initial state. -+ Reset() -+} -+ -+// cSHAKE specific context -+type cshakeState struct { -+ *state // SHA-3 state context and Read/Write operations -+ -+ // initBlock is the cSHAKE specific initialization set of bytes. It is initialized -+ // by newCShake function and stores concatenation of N followed by S, encoded -+ // by the method specified in 3.3 of [1]. -+ // It is stored here in order for Reset() to be able to put context into -+ // initial state. -+ initBlock []byte -+} -+ -+// Consts for configuring initial SHA-3 state -+const ( -+ dsbyteShake = 0x1f -+ dsbyteCShake = 0x04 -+ rate128 = 168 -+ rate256 = 136 -+) -+ -+func bytepad(input []byte, w int) []byte { -+ // leftEncode always returns max 9 bytes -+ buf := make([]byte, 0, 9+len(input)+w) -+ buf = append(buf, leftEncode(uint64(w))...) -+ buf = append(buf, input...) -+ padlen := w - (len(buf) % w) -+ return append(buf, make([]byte, padlen)...) -+} -+ -+func leftEncode(value uint64) []byte { -+ var b [9]byte -+ binary.BigEndian.PutUint64(b[1:], value) -+ // Trim all but last leading zero bytes -+ i := byte(1) -+ for i < 8 && b[i] == 0 { -+ i++ -+ } -+ // Prepend number of encoded bytes -+ b[i-1] = 9 - i -+ return b[i-1:] -+} -+ -+func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash { -+ c := cshakeState{state: &state{rate: rate, dsbyte: dsbyte}} -+ -+ // leftEncode returns max 9 bytes -+ c.initBlock = make([]byte, 0, 9*2+len(N)+len(S)) -+ c.initBlock = append(c.initBlock, leftEncode(uint64(len(N)*8))...) -+ c.initBlock = append(c.initBlock, N...) -+ c.initBlock = append(c.initBlock, leftEncode(uint64(len(S)*8))...) -+ c.initBlock = append(c.initBlock, S...) -+ c.Write(bytepad(c.initBlock, c.rate)) -+ return &c -+} -+ -+// Reset resets the hash to initial state. -+func (c *cshakeState) Reset() { -+ c.state.Reset() -+ c.Write(bytepad(c.initBlock, c.rate)) -+} -+ -+// Clone returns copy of a cSHAKE context within its current state. -+func (c *cshakeState) Clone() ShakeHash { -+ b := make([]byte, len(c.initBlock)) -+ copy(b, c.initBlock) -+ return &cshakeState{state: c.clone(), initBlock: b} -+} -+ -+// Clone returns copy of SHAKE context within its current state. -+func (c *state) Clone() ShakeHash { -+ return c.clone() -+} -+ -+// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. -+// Its generic security strength is 128 bits against all attacks if at -+// least 32 bytes of its output are used. -+func NewShake128() ShakeHash { -+ if h := newShake128Asm(); h != nil { -+ return h -+ } -+ return &state{rate: rate128, dsbyte: dsbyteShake} -+} -+ -+// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. -+// Its generic security strength is 256 bits against all attacks if -+// at least 64 bytes of its output are used. -+func NewShake256() ShakeHash { -+ if h := newShake256Asm(); h != nil { -+ return h -+ } -+ return &state{rate: rate256, dsbyte: dsbyteShake} -+} -+ -+// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash, -+// a customizable variant of SHAKE128. -+// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is -+// desired. S is a customization byte string used for domain separation - two cSHAKE -+// computations on same input with different S yield unrelated outputs. -+// When N and S are both empty, this is equivalent to NewShake128. -+func NewCShake128(N, S []byte) ShakeHash { -+ if len(N) == 0 && len(S) == 0 { -+ return NewShake128() -+ } -+ return newCShake(N, S, rate128, dsbyteCShake) -+} -+ -+// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash, -+// a customizable variant of SHAKE256. -+// N is used to define functions based on cSHAKE, it can be empty when plain cSHAKE is -+// desired. S is a customization byte string used for domain separation - two cSHAKE -+// computations on same input with different S yield unrelated outputs. -+// When N and S are both empty, this is equivalent to NewShake256. -+func NewCShake256(N, S []byte) ShakeHash { -+ if len(N) == 0 && len(S) == 0 { -+ return NewShake256() -+ } -+ return newCShake(N, S, rate256, dsbyteCShake) -+} -+ -+// ShakeSum128 writes an arbitrary-length digest of data into hash. -+func ShakeSum128(hash, data []byte) { -+ h := NewShake128() -+ h.Write(data) -+ h.Read(hash) -+} -+ -+// ShakeSum256 writes an arbitrary-length digest of data into hash. -+func ShakeSum256(hash, data []byte) { -+ h := NewShake256() -+ h.Write(data) -+ h.Read(hash) -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/shake_generic.go b/ms_mod/golang.org/x/crypto/sha3/shake_generic.go -new file mode 100644 -index 00000000000000..5c0710ef98ff88 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/shake_generic.go -@@ -0,0 +1,20 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !gc || purego || !s390x -+// +build !gc purego !s390x -+ -+package sha3 -+ -+// newShake128Asm returns an assembly implementation of SHAKE-128 if available, -+// otherwise it returns nil. -+func newShake128Asm() ShakeHash { -+ return nil -+} -+ -+// newShake256Asm returns an assembly implementation of SHAKE-256 if available, -+// otherwise it returns nil. -+func newShake256Asm() ShakeHash { -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate b/ms_mod/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate -new file mode 100644 -index 0000000000000000000000000000000000000000..7a94c2f8bce62c70664cda859a30845cab713c24 -GIT binary patch -literal 540828 -zcmV(+K;6HL{JXAoOO7>&`TZ1$v|B*%8f1CALcUB{4XE%-(8a0WYv|pDSP8W?6T3cR -zuXFY}-&~BC|M_44{EvV9@Bhm`{_)TM%l|p(|Aff@{EvV9U;meX -z{No?L-@ZTp{J;G_{>Oj**Z=(IfBfU0nmmUXN%eN-rPKjo;XRWO*(`q71M*xOT1g4b -zy8rxN|NqbWfBonG=YRaq|NB4x;~(e$_|^aWKmY5${$R|hx@TP+Ts2$!oSCMCvA10((sNL)Vn5#o;pgjssqOvK5IFO` -zgAm-s71W6!nyI!H4l1vKs2sY7&q0f$$zmUd@TX@YED%S@{mYac!J<D)t{}(ue3|m?qPlW2FAw@(##l1Du~**Wd$q)=M{HXPhY%};Ky!}8 -zl_NI}Oly1?BcIL+;1{UMXlC{=a}JPcb>AcANlEMsvjdtY=fZe~v%z&oJj|~Q -z(NDMK;KhS%EP#Ug=l-Y*^)clGUIyC~c7)^xC~jX3ptzN*yQh`pfb{t?=;C)AsYWuG -zOnWL_`OBmc-NKL%yT=bf@4>)fjdoclF&exqN=Nv#wcovmz7X!ym1p`gBH~q`)D@~f -z{RsLR72P5X%nK=pvm%acos&wwurYV6AMR5Y`yPfbqduK_Vy2~fx6ONMSY+WZvxMso -z=Tco7aEu;A>YXrM?88y(LJD{ZTx{+AjqDGz{L{T9hpGH5q8}XIv1x4j%dmS#pe8yn -z0xEM|qS_G7v6MT`y4U$2QiAU(p;7$uD>$E?9+wp_AsQeq85AY!@ZX!})8f-0GJZjL -zj^2&45z5oi~)9GJQxKOR&r5;KteCBZh{L}pnl18+4W^5eD -znsNs@^H%jXr<^`%6#y}}IZwHMT8E$hzkz6%v+AhX^|4uiP~USA|4jcN7jjx~glCrS -zZTH@r!&$0^#YA=&b3LjYd-d3U+V>d>f}zJE5vsZ^nB|7t>A8k*|HQOoho$yfBUy|3 -z#f36C44lP>x3nt()_xAzhqx3zcaT1#!te##@L}q%2AoQ-2=iwYV^5__ -zK%xY8#3T}jwdrh -z%$=0(32HotyjZ=N0}6E%4Ji_>N)B8Jx5v^y(<?!ks~vq9(846)UORlO=zd!I89i-Xwmq9&^Y&o4GIp*p -z-;8-!L<$GvZ*m*w0kh!TYP?80hyyJbd=RKTr~^9Phj4bc&$52mdcU*FJtoh;fe|zk -z4z>~8Je5Qi*R*Aeu(xxl|xK;XH&%ZPu2&cPI7vN#crlp33lz!3{M6ND>=_!A@6A -zPhB+XFRa6FB_A*FXv}3-;^eR)^Em?61`N1%WkZf24C)qdm%g-^OXXU)q|_TF7@C~bUZdzeVQk03FBlmWpL} -zM17YSd~vI8`RO@+TGMXzed5ImCbSX(z_zfZ$M;dDPK|=`fAf<%i;F$o -zzeqX!XKug7CHCHx^nx; -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 -z_j%i*ha^J*rDAm7!rz&Uuemq*?lfe`6LAx -zM%9jDc;w03hZ?_wE{ -z+0)L3$EdK%h`jGqJijrMk{J0_wL9(H9F#ow9HRGZr0kZ2rU$M%;K%FWziI>tNulLC -zjokNKcKv%ovM!fTCeC`eA%-GaHh^hYF#}|YPdQmH-Vx4YpGQ{pyPJ`@?L-aRH&>ja -z?lKA9+Xc6+B_wUQf!eik^`SgOW($Ob#l&UEsmktzd$T5vAk$=@L$y6Ic5hX1hqIpN -zoa*4y>;_iZYAc(A#AR4aRk#2iRv&(@U!{GE+7+Ys1D=k>Inz2#A27}8noVsK;gHY7jv -zxQ7S4@Da9N;=63kp{<7wP$4b6><%q1lTmd48|P^sRN?QK8d3L+5TS_&ZlmIL6Zs4b -zT9zuFV=Vnyuh8#~i836S3R4o0!ZWuvBTk$&JAPO}dFgViLv^;wLx9Kv17D9aPQi>V -z$g^`_Mkx_aJyr+G{BWsy+hZXbziBcqwW%TGDGB!7PVssL9_Iwya0uL@VWIziI)I{V(iQh=_)^b}M_vQ>8Jwg89PI4QNE(1iJxFv4Ke6V!D+Ab0&SpkOqFm?E{M<8; -zV1@pq_IO|5Zt+!t6-=|FbF9RSNrde&l)x=6H~?Vfu!JIt$RT`sboTkw%VM*zc@8n` -z(&XH>xet*d7t!jV978pgY;R%PPOi5(>ID@}UyFsJA7V1&v*foco&< -zTNOjyo1^y7QCk8g?3fJ3c(v3Xcd%PmwYrCeDwhmI1IV5}9jU8g -zPl#@^#XX+n{1mw9=MH^$e*7fw&T_Ndta}08^5P;A)MMDI`Pizi<(hcg6-)ED)ueFb -zy?3%c+F_K@vZ|B;5VE=oi=^AK_9TXk`GV1lzfzEtQ@7M$9=C+!yO$kOsu0n&{_Y?M -zQ#_h*r?-sa;U6rv$Zw#r)5PeoqP@rWxi`r^Ps!?cuV^k>&ri{ssGL*$Q*metSZ#-w -zPSL_?(oF;}sW=gIE@~wB8ChDqKIanky>n4-!6Q8PX}zZkf*Xb&9dN~~WS!AZY+>CB -zI)v)ezy~<-Y4i6Mc%n??Pu@d%?Kk=3Vr|b)QM%28hx}3i&`5*A=?#(OO_umnl=|IW -zQes;~pPSGRs_&_Lg?R*2=NOor4Ja)$Q1854SBLSX5Zb83tI-;#VdJKprlHiWzWx~5 -z<$D}Y+{kIZjb^)MG{_YQb=MAPI%Rskt+wp+d#LdtZz|}Y8I8g2PE0>(N-amiHLUfh -zTA0DbdD7WfAUMx~3xS -zxnOG^JHmkXHwScJjv0$Mr(U3=aZu_vrjoi&d4gOJyX;=3nliESIa<41rJPr= -zTrS!jiL;LZ9VyRU^G4eCgH6bF-48uZSZQm^FHg~Mce0TW?2DbcSZlW`oEV!MQOzFMWO)(k+jHXuJ -zkl@;T=<~9V@1B=h*_yE@;2E7$?&=|?8Y>QA=;^rh6k%`>xVqc`wqggeM_~8m6nN=L -zrYFb$byEXOS>_|UUR$Bp`WQ_3llfPgyz>!nYrf)mY78x%=OQvJaz7Tvnj{!!{=}-) -zMSGDiPa2oE%h986&knzTAU{<-$YSwCOCHmlPu}$1B};2jzUab3uqixfTXC7z9!o4@ -zbEp*M=Xb~U<^?6~M-jLJrhf(HEh!p4hrPxPGsEi6xrYwDJpIzOx{UW+O@YIUo5eyh -z^*dESl!bTk<;A!3J9d!rY^JU#)!+MN+L%D5dGHzg`)p}Bc;3r=M)0XT?KD|MNf=+4 -zb-(*+r{!0hkPTyE96dEVLy!k2i=m5}Y@b#4``w9yD>B&llIjy>Aj+aCj -zIoP%O;Gj&uq5oDAN&{hKC;_bwR7DMS5wUASJK_XB-b -zPQXqNgu?qXbHz9V>#g93TeVz{x_91NH=zazI8eG0I8t_?Z<}oCW)4yeX}4j -zh!)B%cMt~fkrdF-rwK0~d-$^pH@Ep -zp63LP4}kd2k#jG|T~`AV=74)x9e8~JK-WVJhqfQQ3-g@a7XxwU{VxW5I(ij9U0wp -zIid0Ti|k`_6K@RdLLM&avq`f$;t>>Us(L=L?cdxdqcgQG8iLBccCVlTYY$N`vOiID -z2Epj8%J|u{C>7o+e71*=9zr_v=!BjH`1MawttSItx+j^>m*`SRYJ38{^;vp1^4(qLPR4<+(JxEem*v4uP7*5So)YniwpVZEqD?pczBPzr^u55@oYO**tj8r*mbI5i~i57X@ -z#}2sJK$b+U`0q}->mfHBPIl-ydd4JWpX|C<_XxU@w^t2k|9yYJ&gPiA47!H*4EG}h -zz%6kHh!2aBhbCMt>`OYInD^c1R9}zGP!WGg0Xn(sIZsBud|_LM!ATF^_kVClpwb~~ -z@nax%^LXa4_eu8hC+rZ7PvWk$mw?Fnm9@osd+MjIG!BOyK0D;Alo^|RsC|B;{%Jag -zhn&Ofhpm!LWwPOW>Y9W8JzG=f;3ZsLvPdICbA*+xqm3;1P|fvD#IGDv -zZp?n)J}1GG8j=@o_|Fsbfpv5aj#PXJm=aTDMP3m%x-z0_#DD{`t@Q!{f>&m -ztwEtNe>}6OE}$VY))Uf+$GockzSeTKiz)(f=HW>yVRNan)X*;OvIGi~LK(yrZ -z3eeA-!bBx>2nZDUAqcdo1sy}-D`S1K={)9(2zJPAxq=xf-4Hl6C!!F_?EIXT*2*cH -z@#*4v0#Ivu36Wb~Rx0#s%*>1UL~&#pHi<)O{)U=Hsz>El1-V7{^WM_$4sY0{IilOh^O_N{kq5*&zkeEGRl(d(aZ9vz@L4YMC7bm -zsW9!$pb5G-i0W5P3Lzh#I8UfzbBdA7*O^HB?g^ix4mXw8yLzFq?UseYeJfuTyP!69 -zHp0#tw(ydBrP`+u+=s -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 -z!*$qQN%*AzZkGovMX4jykx5 -z`v4yI-SBis`9m@X2CiV~+p<|VBW9;B)oS{5LVErk=~rQ{$JaE6JPGPxIH&%2RJ -zRlN_bw44(wXW)UKxv~kEr0exV%!7pY9#hicvR$U1#rz2 -zVGYKp$v4S~3jLHOjUP*kxTXQ>%BiZjF^75K?uD4LJ)#ju4hl5ygNRJ;q+c9mRFmUZ -zg5NJ-5f&};z(t&+`$~oLxq5>p>TM-JxF=hrnd7GTywgNYdFF`mNhp{{N|53d5w#W} -zibD6m0*S=_dFxlB2jHOlIv($=baGfDfR)1sJQTNSH5#cGdiUf{(`)z-^D`68>?r#h -zA$M}kYtKuxE}9dk_~4F>k55p!P;@@Jd&_(iuEo*--0nSM$Y!>R7N?}pE~j2E9uB7F -zM*hY&PFJNKD!5BZSER-)aNCYRb>iRw3c7pD0Z08U>{oBQW2~G3Z;QHBaqC4@e5@hW -z?sXTB2L*f}d&`?M=1#BzU*-7o!fM*nvt?{3$mZQ&Kh<+VIsBz^gkXdx23x^}@%e+)|HP -z`E3+*ORh_W``rv(y1Q>bbRW7dY<#~EiR|{h_KihZ4N1gtO!JCuhh*;Is|U5`>zO4J -zIjLxehbsnEb|n@u`k)962#-G=_XvbGp7-^uRy)D|cB9J^GuJG{lIP)2-0lNlBbgz$ -z>vB=kCTR5aGW9Fy8iXiZO -z$iA%64!JQVYK!4#eRztNUm5`DK8@YYS{?eSlCyTKq2kQg=3;df*DP>tBFxajGJKW(P9r7fQ=RR-a#d2m~Fs1$pc&H+_Z_*2@k=i~lf -z-U|uj-lnB@j)TCwKi#bh_xMFg3rK(b`R4}w*2+-ZX`g){T(|e(bO@kS!Vt1PRX%nq -z>l}iJWSVntSK*)_WzXkpe%W$gyeEZ*#-Z;8r5=>?IV;*Lc@5+bQoq_u1yf6|#4?kU -z5B(4JLyC48WG)!J0w8L7wIA%j!*6^02%JlS8OzS3fGzRh>p2R1$d0WgzY@M6`t~

*MP~@|g&eKE{jR5*iq?f6HMmz2&am{(;1ohr`PJV8|e~fj2(+b%% -zXR6BvjB1(tn_+52xs9>>Kt^|+`r6IOADrzu#KI^72&O5KFXra!t{|nrzJ8WWH3HJC -zh#mC8C)^&oI#YRR2!%H7d^aD)?OpiO)n~ym(ubs2n2RQ>~ -zUieTuF(CH=W(v`ezL(t8!?9s5c*QrI=Uwgts4F1Xc!w|5HQLf2~JXU#cioz)5xd65?DxSe(ic|0GCAwC1 -z!6@ej9e8{TXylzuoo)tvWCy{pal1xtoGgB5hfZ5#fY1W&+ywM8DOhz8-|;)WudaOW -zL#_+(E)nrjI_xcdg+3aMe5{4k^L;QC)Kn`(xe*LbQ|#Bw&2UGM4fpRUj!ekjm*%`A -zb`N(2jFOUtGqhb74FhbYwAyA;{OP=f@E-#zBB~)Q5?|FUWu0w;H5so?AOGG9#bpm; -z&PcBp&YZxgl2hS;W-IRg4#MpPv=*T_kDlBRodqw45A-TELHish9h;gs( -z;xRqFl!yJN=REw!Aor}L?{Mv-!d@9!w<(yU1nv~+`3ylWUa?vZ-fJgBP{UuL1{q%N -z8?k|mvxcH``xD5d;f63Z0o~HNypYF8Z`BFX9?VnO`d~O5pz8AiU^H6$@Lh$M6#&Wj -zGN^Fi*B6P@L%eiO%XP#9;T5(Iit%S+#l}TvGp!>LNEgL{4dP*}nafj;#`op-o+3@!DcZ0aK))$E{v9Zq+SMyCqlco`|%T59ndGFrn5- -z^KqmmS$zcsOo{111|%2AL;J$j`ca_c_Lch1I4Pe&#pC7`pmhJX=rTDTf$k`GLCNWG -zfbKVIQ6Gnr1hzSI6jJV^V3AP2H{@plZ>E#l&{=h;BGAs-0XulZ0760g#77Vm?|!QMy6wTU5oL5}y$KsF)|7-#%^+~mG2()KDk -zU&ref=Lq^$0txEF1+Q)sQOjmS5>#3Bx~!bi?6w=aFGe>CuV0!1IJZm1XlM@gJsWLu`@wG*2)>An(O-l3 -z0q*#0H+Sa|7sfsS9&M=RVW&P}_b@}o=!kcl*O;6}LDRaXEutbP;Nuln!jH1^_)Sk5 -z%G|WD_SGOM_**Fz9rzgOISXVL<)jW^raO>KF7jzFoqyfjc}EhDqoGN6 -z%^3%S6G4W01W`C@3)F@M=G=7mi2JbTL5z30fGkvRGC7FT!Fw<|*Ef*57Qq+JJ?mi1 -zfbDo~?#dGBRC5zkg4UzcDHmdwBC#upj^yyE`_R+%`5L39%})?b+AC^eeWEBYIv_jW -zhAb>w9!HJ;!zbvtf8$zYs;&G{Qp~v%@L;Bz9bw=lK$wj4He1ntZp&|R)h*j^!fcs6 -zvP=Z=k}qZ{)6h?(q@H#gx!{O5ZD!*mSwfX-NCej=?L3{-2A&Cba{{K1VO7MSO7LD{g?3 -zn9N7H35wyw(p=`7KgV|<{?=n5e>z`NXoqC-VNxxT**Fuw##2mdpXUV(y%4QbX?gi|#LI1Heza?B~et{4l -zCL|Evgv2uOsndH>4Y8E)E}U<^3&us8fT*T)C)JEvN{fJcrvkh@cz^Zi(a -z0_x4``^jNz#oph1#8h9(U!Av+U)$_WeYkt<3h1M%GIXP&&*+roxMc5%S?Q99^zY{F -z8)aVqN{{Nm3RUXCrKBm9+wu3R -zc}WcqauoVL_DVE*SS9gmyVCu+Ilon3DebqQ2S;R6vhld#!`v-SFuf1s`+O)>Aiuf# -zuU0Qd?#w6Nv{(U?a~;kNwh})uj?8SWK+&wpa9+jthgBYp%x|`h2)bz3%bX1;vwN?W -zV3*FY@z1G+lrdR{_}1>Wmxyp+Rn{9i&mk47$Bm1w`iXkQa0M}fipH#K_LZepF> -z9w==a=9uodW}1hEii9oZ{;kP_d%hM>P?uxZkbxe+y)X6LJ9o=NACarL=A#KhKd~A9 -z7K&{NZ1D6q{Fa0U-Kjg- -z%XevZb06~_!PBw#_zB~=2sZ@o8pfkaANZTncerkT!&a_+U3(CKg_JTUj<4Cdb^pGQ -zJc=v?|J(#*N&@B;ZxTs&c2a89bg$J4`&`5!@^^Cktu1>;PTN-${Fc98y;*}bqD~} -zd6`vtmFKiEsFLCF$)@J)^CDrG^d06teLjEU6QOo`cJa|6dS5#+BopIs*uR)$ -zV$YQ?>wrh@CE)8F7$rZiWbn5fE!di+6;=E@qjyETWMTMn$0bOFn#ke@uT>`v4jnzz -zP7jmL1E7__%7h)}z$J(eoQv7fC{4FCrz(Rw8r~s+XCD|>r9u;RPmff<9p$3}osVYX -zWoqbyq1qrTA#wA@+|BJ1iP)R!f#sUV>!g#EBhcwpH+O3vW9s4ju81F9_a(CT(V8iP -zr<+^H!?6&rDmy&#A)|k8lHVIeQH=yH2vmD{Z^uh#A#Lcy&O}9h{Xx2y`tJPRq~CMv -z#yzAYk;<#J4jVyz6LaceA)mwZ02f=G$;)R_uHv4ngiUC;7a=ZTK~aXPXW+m)7i+Ue -zw9oZ;DfGUi@P2a#o?~L5VQI3bUSjOiz2kb1C+RC4eu_FCMs0}Hh+A-D&~{8R8f8?^ -z?7p1YT#3grRt_gu$Hvw`klv`Xy}Oupt{}lT;143 -z&>ndZ+K)@)J_IU#aUkzn;VtA(BVf0-_E=G2Dijj_eV!=W-V;vHl}zv$XJhE%AoA`5 -zu@{Suc?;=)#@YLOqkik;woQ@m7&gP)E`3$VH{hlm6pe(0xp)E^&!x41h%;~LQnL$= -z1|JRma!)nX4$OU=D1>!eX-|I9HtY52J3J@7_T?qkjTwBW4(x5xT){BYc{F!lVr=nS -zGIc$!?3&u$A@;kn+g-N^Y~N|^1G`e|`2H`OuF6e3Rp;W}zQ=)y1COz_GoNXG=;t=d -z64$+WE%xx~xvrC)Ire|d08E~Ri6gAa07pLOG0jBEv*kjtkALOMui7h2jnu!lD*ppQ -zq`WA*dd`XnnI0LC^Cfz`?-a}QHKJ3O1@EGD+KX2kc`M)shvhzc*x#J4qhA@KcuOj0 -z7MLtIfCj|s>=HSzOaj{ajl)ZD^Hhk=3Yn%zA|kX=-x -z7h6LQ@aU@tH7RWGbcG%1!#O@3z`lo@%o}`I%*aIYz>GGWLvxAn`pU3Kmh|Rl#Y0Ee -zyziwXX7zLSmCBxfiY6{D^`^N=@s@U*+}y_I2B<{>$eofSxMf2JN<4DhK(BWP$2k$) -zT!+_yeBHI@l2HT-1>|RJcvD}=gVZf#Sm;cS(#LE^$rP^UpS_S6xWs_hC`&ELvD*dC -zJ41*2kk&MMZq|dF834IQes9-LSn(c1r<3NErx|@0FUiN!3Vh}=Rn?iBFAv}}$|EUpP<_2W{rbVav4OZ(VXb?*oSDu8UsVLcqMWPK+7D?aYHvp&W=2Ox*uu^B -z3fPy~vHSp%!_9L4Tc1`#0Y!+DQIDeD>2}OZ3d^fyT{OuR%<1-kHHz;~i6H%!2--+P -zfj`{Ft4{2`@c>%Om5+`O$ZV?;JyNU+kDF6o2PY>YvzNX{BFZge;8<3vJsx-2 -z|2$_yA(IS`bhRDInJSM*3`Vf)e2!jNC7UUMWxI6c=e-5}78NSCpMGSA?%fvhN}Rc? -z^b(c8Tfz1vakV3F4UVdT0Ysl6KWGAw%n5c+UWUE*9EkuRIuMBZC{10yZF7_#J8r+N -z&BZ;v;=One7m>%*M(I6!}9Uum? -zsSkcbtIKQk42U)bpMpmWrt1XHAX8E?>SeU)tTd^Ra+dJf`V<4(^57N33K1+szYEvbu! -zC$z-q1gt0sY~mF(9dH@p&m)ur7_nk{kLFCQj3~x__nq_D8&35#>wAN@nk(SzNB{ZPz(4RB{8Dfgx8(dBO2it>Tmc8r;p3D$8&w#BHZjF$Q?#D$qU-%#`3(|W$! -zYAdIxHnR)9pl$~vCttR{O>m|pYv^#kl;a%wxAa$RPmz7^mpf6S1=;{*TuUGxAv#A~ -z;KDhYSX0XVQ$s|*rH)f>-#89Utw6URLkF;sFjo~nym1wV2wz>k2{y1ktI#3__-L4e -zs8?=yuIK$QqeYBEu{aw}h(FqWtV$`_wr;FOVSi>kI1aJ|D0bLB`D`fno;;hqcT+8E -zqH2r1^0p&qVLi;CEPm$h13wchDvddfQyQ2sZi~ -zPyWXoHMb5uV=jb1dQ3JM-h&=TYVW#!8vq^c0-b;JkYH#cX!x;Te6-3MUueSKxE_1s -z&=pg7Y4sbl&DZ6Deg7V8CTBIo5N;y{iO4d%)ChL1WvfKN`m-y3GBP=1W9 -zU`Rhn(jJWm(@Z45?t2uOU1g)#?^?5s8=5&b8JDrchon(#?0|rQs`>0*{U#(od_<2o -z=8^I6E7QgEIeye6-u!zaQ#ivA=3<^a?9*PxCFdN~S5>Eh*xq7%lHJcaB>Sh#n10JC -zNjoM7n6|9vIP<*|j&ZxG6u4w7zEGNDf~?wyA~Tp6`0<^nd00BN?25#z4&hld=Rs!-ORVJa0~Lqk5#vX#@YJ@%$k0Wd -zx!QRY;s!Gh)7eKTvE{SDBf}2Wd1ZA5KaWxvm7{>8j|qdXwY~^OG>BN`)DU47ld+sMEizzEul*cm4CvUBd)tX+6 -zk0|LYi>s~rxVv7`UfO`l_%wrlQS|QgHXji$9$B#=RFWChImhTKVRcePms3Z2rj2Ab -zIb%k9vHQ}ZgWPtB)IeS^*9*ri)})#4YL09bT7-x -zt?Fpl`*O)W*e%Hq5pY3V230;lJ+zKxIO) -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 -zgxP8ne3;pXZgbl;&k;Rt -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 -zIk$pn|6o21SnJG(ZVAy^T9$L$$Yg#0ljaP -z!9E6Yql+can4!jd8zZlDi}rC5J6Mm)B2|4R1ZeA0r>$^b7DdJ+`rCFASc(M!$?;VR -zT__&;JiHzg{wz8{fbF{bnSGC$ejb3z@8Q^6eHrRu6H7I$FL*Y9FK$}w-?fPk$-@S?#dFw4I2wxM>v(a=mPG+M#JV(h87gUw+Z8-u%^mO)GmsaoBFHfr~b^lU|_=P3^sjOH|qpmXzq*Z&FMcI6zg -z)-;YAvxYYhT3Q@b$m>ybkAy!)5WX^xG3hx=lWHVc!WSSN(J#|EFGSrxf!HdHG@i0;%mp^635ZTrK-j -z#f!AEEV0{XPYwxoW(F)*GM%0Xduh=+fa?5g;Ftes;5Qc!olmC8^p!{hqRZ#&{1|j{ -zRa`usS_Gm;%}q;03*+{uOK2^4W|q3x;W`cs!eaq;q9^xKCL>VFG1rZA1m#XMq+CC% -zwt^<|zy(|j{$wm_umh9jwuX+@ryI4n3G>g3d9IrRj$cv`H`+dW8DjWzS1Tnvv{4WP -zumNkO{^GX`ClXnsJLL{uGG-m`dwedOyq}x$D;W`!3msICghFe-C$oKGhi}r0bl^~& -znEcewn|mL#xjoC&{Ot+k1LiNOyoBp|68=7O(;1$axPV$OIn~_j4rzN#VCRv`rGy8l -z`{+<`&VMX{|7iLDgaaOT__oW%E}2WPK$CgU^@wz@ojqU7Yz54nORJYs3V73#)d;9; -ztj_EtMY)_)E89-$korwfO%%LmM>hDi+S@lZ)+r846fo>Z>+h*xC-`BQu@(u)%{Fen0yr@o$*3D2~wO -zA%()$yWj^G+6egeI=@05w?seJn;HEl`l+TdgP-Km0N(0)wAblfYFB2_)#0OiD#kGF==SHsl9ujD{InjGC5}Ld2 -znxz$sa0$#?%4>Aeyv}{)AY@HN$NV@wS|d=#@6}u5TkAxyOd@S(mCzrqyF%T4@l^M) -z(%HOaeHy#+MS43nZ@!S!I`PnXHiU(`#C{gN=v%k0I74;k@w2PdNGD40S|s0dw<^P@ -zr%&Ju4d9tm#C!7PxTy1S^j9Hr%xCge`$Lp|VykwMxV7??A)j2a>QiFAc(S8-eb1n+ -z%FrAhN$Sa(do* -zcR>ARw20z5?SwBfF+<+x{@mV`|IqUO&LgwL!$gl9xPuv^JD-(h4*}{(B)&zbkM;8^ -zt=&U#?$oE_3ilqH#r|Ai6JJV71)$s;dQZk3uYqEFHTsjhseQ$>+4ytXTFEp5p>OEG -z=9O|9y=xgdb^i$f!ddZ6&h$Ko2@GGF&;|5QVe8&yKH_sg=YfS=ISdakza>$3;?vVU -zhb-ZsyBT**5x8d_i7w}HkpLk=@cK3!rq9SCAbz8y%conk82LPUOqxo=fIDY{^$_4` -zty5QBaTlIx`oC1&TM0UQdN$c*WcQGgNhxnYU5=vqqxb<~nKY;{TM -zJ2=QS1I|UZIMDpESjnS?kGH(?MPGYX=p?k-;@A6?{BnpIM?}Ua93Ho~q4#cp2mmpR -zqDD;{R6n59{1JWb~ -zXkWX#M}zV`p_(j+Aq8es)HkZ^&V`Hj>J$Ty2ON$t$0HQ@ehb2tFp-RE+gLlqA>Ez| -zcUj{YSRK#28H*Sp=V9sO3cRo)su$e6F*e)my==8;K#RThIP1|q3tLJh70QRjAF(EM -zOf(p$tVz9)J&FiLA)?1drXKpl>aGamsYOzxs^bnMpW@!1gz+c?-7Am4Sdbiq2kDI+ -zPO@9AvLPKgmk%<%lurTmGs)(xKFp@f#C>(H)oV6WmC<yBCX;9TJ7QF(d-PtUttQASDBWI@`~c{IdmcJ -zQM^FF3>jZE(B^n-$Ky${5Tl?-_NR^BR(-lG_ZZ>Io{gQpWDwh;J3u6xn@3VNVb4)% -z`n_%Zdpts!#XuVn6@WO7RCcHWc6h&OT0{2Nu7cm?Oe18Pp6<^p`S))vw~=g05wfeI^9w-Ly? -z#)hp#+7y}kxkK#OJqjEi-`NEW;5p)UPxl~4n$jooo0n_#-LHh6Rpjb@7-Q)3kNZSb -zFFclo@jhu;;@jxI2iabonyYu9T4gVZ#KRF2uk;9X8BqIs2obzzp?&Q`{Lx-o*Ck$6 -zqxYgE>*S+zlHW|^->@IV#Yvif=_nD&X -z?SY$G`4Uc{UE#$TH~99`|iqy(H|nG?v_4rBl2{E~WzJ1@G^P0{4iD -zhV4{+)2XCGg>onlJ|1zEU`!tDFmkG^JpwmP=&&K@CXftKE@Dz3rT?QE^&VuT3Ap78 -z(!{K0;eOu^R#8c~eepsOd>tnx??HzK2A3~Qr9lmeNb{a(zPJ0aZ3{o--g*v$yA~x1 -z@q=XY61&G$fJjJ(zTu4sm-&;$a;3_?CNp}Oa$DcJ4_uA$O0>_P=a|Cn2T5_H;IVze -zZ))#`pD_StdR(y5_Vgoyuk^hX!+Up%?x}kh1^0dfgyr{d9hlUCEp9TR>Bqp}ewzI& -z|7*{5^kLmfYH#Qi>~-I{SjMj~uT|+NRxgP;79DJ*$TAfiw_3KEm95<_zQKU@VE) -z2a1cxe8Ib~XRnJ*4%!d|?+&IcSeP0?ZR&CP4mLkgLxfJn417W9iCsu9nRK{NsiWwH -zoll(Y8y^TJ8Np=aP(|7sNTQ?+qCs43DEOETN* -znxA;${vPwFZ&N2<7K%Kf4*M3qjb#d&oQwB=xc+hU_)NGA38-I)!v@hliuqsz3ERsy -z7IVv{?nV)^)SZ_C;BMf4dg1qOe2N&TXkv@~Iewnvgi%!^nnu&j-VzFJR|bMqQw3ZT-WY>Y*9{+e*V?0B^_3CP!bFz4Zf#!A_mOHHx -zoqhNKayTEJI2I5m_-~{68C<7NxPaT$x+$P?Euo`W$&Q|@Y4#`*J{*>Qe(p!y--99i -zO_1$Ian^*Ovd%Wl=enab{9bg9gOpjo?g+Z)$#cX=gKy&E39qDjsW5z~Q+#5kuIJYC|exmm0E%dyGpQW9<6(L-L%jh<+u}zSX -zS-UCD4{4ZT=*(uBY{FxOs0`bAWXq@PUDJdPFJ#mlP#$ -zCtTx2Iw#!HzcD&#)LlIs`_P{apnkL7^KJYwkcR{V5NtzVqFbo=Rx#`Di&nB++;cFt;w34d9ps?ELf1$Ir7_wnXcQ8`q7a#M+~elXZ`TE1hF)V8woqw)Y?!k6y5aw3s$h+tNA=d}gC_UYf?EwI8tw1lHQe^?ZDf96kr>zP -zrfE`l*9e!Hp3O(FUopRe2kAHN_z!;rbT^lOQvzR;H30NV4V`e8Om!T*C(n?EB(yW` -z*NFqcQMmUuJ6dZrsV?^s;mYL_q(;~;d8_wb&KJ5}=?N;D^pz*3~^HCXLSBZ^x -ztLeD{l1=BlMMKTMmx%rcH2wTL(A-loNN$EmF86-(inlu7jZU&^HW+dEdQ=wiiAT>A -zeQ{miPh2=TXBT815xOm%43|0GzMW;@vvqj|BM$9ByJd0tTs`M%7|#Lqx8@I%bwVax -z=-C-1(1XAzYliP@cpGM0b<2d(z=Y*3(RiiVSpAL|mEO5K%H>fgrV;#@*qR+)+(|LI -zRh$(0{xe1oQTuFW#od<>87IYO>C_8{$b#F7o&8YZMLMkI=H_eGz!Q5g6ajPKPGKK) -zgNSf<_U<*GYCl92s*lxxn}uQIYUwN3__tBwBM0VrIZvt6d7xk=Q4F`$OQZdSSow?D -z_1qAt-~P+@_Ylq3{bkYPNp?z&=K-Og11t0=+mLxW6Y0Yf?WOl0ZgoR%XJg|z#)P>&^KuF0kkf16Sa05EVCAK+job=1da -zL$K?ZC&_jT(tG}!nzt<`TP{_=#uX~5gV5V|#qrEtuzZv!r*dC0J7_>e(+@np;(h%Wd!FIi{RSY>u=qm4{^Ul3w(DK1~8#}30Y36_%1qu$NI^eM7) -zwUirs)kX2C@G}_d^GH!f9nH^@LpK<&-hjT>M9&=ZOQtDVFNViHW;*?V3^1U^ -zx9`&ZJ*Y!z<65#?*f;oWXpiovH+q&5u$<3mB!dvbpwC>#-Y9j?bG+O?r$arqH4lqf -zNs-KB>i3(Kn=URs$xT4_VSkV8_HS6#8{nfsN7(PqjaqapE(}<`$%o>B*dq6iHA%kF -zFZEsI2N?SrT@}rqkE{A==|_lf0ojctRM*&>i2~z^Z96JltZbNybCR4V^3z`iy!%L3 -zXkVFhYVnoik|;i_MM*lkbe$KS@r6gMeGWG(UhSO=FU-!%So#@xs8#gmwEgH*YtL}# -z5sw^qFjQbSO8;hVTURcV_-)?5t;*H9Eocdky^z|6d(!%Lk_-?9++mF%{Q$wI`}q5e -zR)3H75ED-kB%Ci}?o6G2G}C$PtY&yufX^O%6g$s*tr!ov-r%e+dNSSx2AJbF!M&f( -zRlOo>Ao57aJT{Vr*a&QLr)9%Qxv0)dv~M*ZtU~aszE=X|-Yq4#%T@GfNPulJvv1tk -zfE(0_S&V?QE97;x7L2bQ!z(0WUiyH!Qts9;LB4g%j-!{_QC;qd2(n4+0uBUhMOt?b -z*neW|+zl)OH9T4uAu&Sk;ec}vIDxlu6GA1oFMp?3$1_EOd6Dv^ -z*%pBtP}j668D?=a*Q@^d@%>4NQ;wi2Kpobe)svvLcs|30c~AvjNf%TpRO2E))Iat4 -z_4hE4mby?Ilrpm6x0+sGcE_^^yYP#sBCGu -zF~I41?zJ3HF7tlqG?-!p7w8+I@-pM?i$V9nmU@_E&mu7MN?k=XP( -zyyZyl32!@PBs6y=K8be%8LmyvDCt;rc-ZWA5TLyh(4$jiTXjn}eJI||R2%+Oz_ -z7Oer^YiuPCwn#+Z14AT$DJAQ=6!A@~Jj@ecmSCZXugy|0CJGo;dpA)6fp?Q-T+G%k -zr0dl>x`W*1L$^EnZsq6W*7pvir4Nd%;~G-?#Ezb~q??=QI$|})I)6%&==+YK3>Z)P -z1_f`!TkTZJ+0`M$Q5TR=?$Pa1b2llzjswCE?8WhJ%|kCda0=BhvD{M|6bXnzUL8eF -zJ2xS({OuoMdNW2{db95XX6*iRVsDl=X;U -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 -zGf(n&;vHKKbic!N! -z77hXmc8;5L!i8485|_I{;6C;0b^x&e{SfBfqr~r}J37C5|3rK}0T4Q8?Qw^^=L;_0 -zc;yNN$Idl-R1IsTD?UfMr}H1RM7*oPR8`r`>v6PJ9M6R>s|%I6F$MXFb&lfm6l-lC -zDi^_5jsj&wrSbrY_ -zEk7R?R&o1i={~8`Q{oMN1#W_gwhZlw#GBMhCjm4fWtZH$Xh}b;7bb99alUPInARC<9bWd8l;%S8UN1`{u)^5kq%_F1?`sEcx -zmv0Q8E``oyQa}4j`aD*5NFQ2k3cZ@6wiFlrRwm`@^r=1cErTzI0xbab>|8lw8Mo4| -zsoj*|ppJ91>>OW#DSjF`I30lO7~YY1Km`%kUHeNqIJfe&$I4#Ip(VVx$yO2P=6P(N -z8oVzNJ5A8V*`n3lzP^3A35^uaeirUW%Q39~tW%ump$sd0-=4&aPGWIdpl1Ux0ltp} -za)FaPn<)GT!DB+-1TTYo+(fAPVOol_r*t&%DNB}MPV?!``&w303{&!knGyxEpL3H -zRv+xUec%6ED=&!wX+gkjj^DYmM5XT)N#q^OYwQp7+}Unw;``-V5k9Y$D$Ii1G{=W; -z6^FZv2%aFn9+~o`;{vP`Jw%G69R-$uiMlnYyCkH2^{^WW(4%ATDY$2SE@%^}E8Ea` -z$68E21L{;Q$b}-PcF+YMP!!dGcFgODW`4gmFS>N1LIJ+c$~(a$V8gF$=iP|VQ-1#Z -z{zT$Z?H%u}YY5d$NWoj5J8e(6f?}y>{Ts?T-;wUmW%YYZu>E`Wp)02IMV$bOEPv5t -zo41{pH6svlT1>r{`q4*1!eL^u%CmB&C&(5(mfohxu+4rO7gp+E|BK+T9Rd{nnzhPG -zYvacIA<$~dE0^mEQrI^N{unLQ2@1Hoc-@9>FWpn$U{%gQ)b*`Rb>~rPVtdRF;XJ&& -z2)NjOm36pbdYnBQ^m(7oy#{tyR4qmf-Y_oVn -z_AF58`DRSzuq*Q92@~i&G!yV$21;gRRqX0vI^7eURRsug2CKDB-Tvl6^PEfk)PjA< -zMW8{azliKMcblU(VEn%N4S73en(*(w>(8a)iib3a>%CHPxX602R5Muc3;DL?o5%a> -zYnk5*>nBm?L|PZ{I&hh;ofA}#`94zIcjpB9x#nw(7R!w1GuUS~EzhgYEBV=Q@ToS6 -z0(#^YfL7#I`}p1{nTwNJHD5~G*kKg>Qn!!1as(_J&3(VG8D+J27&2DH2I@@463myg -z?V94~m^cI(x~QM-rALIS*YZhjroEnNAm`rW{yDiNzEz`g_3{iBXAfgg?jewqo`G0C -z4;<80`e+9)j$IilbL1P80y@I(y4=SAtAd+S9kUVQ`jLRA`W18iRe+eU6z%8O+#t9aVf4FZ{T@X`SDf#=?WSa-{d3`;9Psm562OMN -zYW}J~?>L`&%;sVanA)K`F{CC)_pLDf7j`ST@a|KyHcsBj&kLFjF3UGqWPWtZ&vIV7 -z^xlIMZS80GNp}PZnX7ER;2Z$4`dp(<7xT5-6&e{ais&IK|6hQGeq4Y;TtEPh_OSH -zA~Jc*DtV&Lxwi%UvdJM<#N42HK>Wluihcfaf*A7|I2t~x96Mh#OKj2^xykc%6r3** -z)XVYvR(Dk&i+kl=mvOiE>!G-D86#Sw5`7V8>J&#S$gr -zXCPht9$o}**zMueIkPGXKB-1?oZ%_3!)@qx@6*D2;^5tjJaS~YzTthDsT!)saH)># -z&2^Fcboh#2oHI|+cKT2&cj%yO`*{pu#nobYxrRcIJ(ORplJbtRsTak97v7 -z95k>#7QknWQ?ngDE8K7h%?0yC4rag;-1>OE;X1p}j42YHbjyfbbxU)1LmdHflQoryo*m0%*fy-1g`u -zAF_k`nao{e>m#zn2!=OrU4O3`CCmNszJncFR-SusK&p;@{VzxAJEne^JEqVhe`>>! -z`-t4VqC)Sd4BvVDD~Z3rFB}KOEx=*-`gq*Z&vB&qJ?_}%lvPG4^_BpcSPf9~9I4SE -zh-h5^cw6Us%Hb!0TBk0Er0pv((Crg-`M9u7-^`&wdf+mTLO-O!;zyV6c`E$U!Jct~ -zZE?jg5$dnac~W4{k^Fqf-edFR7%JKY>F(*Z2gE(ANKJFv@e_dw_XZq6-N?ha`sA&! -z3!0};jNm?!h6f$|ixp}sg`1bO>hm;0k9W7Mv*vI}uN<2=X$8KYufyJx>?E(qpOpvA -zfV#BhwSp?sNZ+SR!(q)6X{>Kq#boka=K~sr^~Kh{$5H$ikzAmw2P)RozX{?9p{JVf -z-nP)4b4m0D8l&r_FJosJjg{kcC0{nQ}udrgOjR|^EREsIbGFC%iCwd>Ij -zB?xW<+@Crzeh)~>-f@ITmd{b)KsXPgfBuX9u<0`&Cx<2RyI+&HTRjj7n8SDrqw>`} -z<4U;l#8Dvsn-DpD8;aGuG7l}YENz02S^^y?zJ{I>hl=Z=)n@oZ9FoMNI^LEFY~Sfv -z)dJ_HoZI$6Rex8oqa~X|#ytJW`Fp?mNt7H&%51;1f -zdc~a?WMbt4M~92XuvwX;LDt)u*h?DadA@18166?~X0OyWU;Y-`*#xafyF=$bj-2lr -z{vJK}bcP(3b{&j*glHNDuZ=S7ICTfL8JszI94JwLFR`E0UeRbV3{&SJnW8~%Wrwuv -z+=$wLAuMXAE?T!aAS%i{%{{uJN$&^NJ_0L -ziqHrKGlBPdC+pz)!PH1gb$T>#oHY(MVaMANxfd5Iln3wE${9RJCozS4@rv6q7;(of -zIh}(A?FSaFZ!{L1`>-YPvo>t+$NhjIl{gbc*^4_O=^lXH$8zX9xXg8LDz<%VTlHdo -z&n3y5o89w%MugU~uoiP3q>HdF -zdGOpiWr=xTiS`v}i;r{};~5iJYoN^(ul+kG4)4m@SK4vAr1V6UA_|h?)9Om*waYCW -za#t3Seg_4{?;%W4^|>9Jv|$D=;u#HNTamB}weQZ~VlcHq -z|2%+vI4&vaBj`gx(EKXj!UQP3;;MH?%7&>FV2|{2W^x46*Q~iArLgISlthMmb2$+2 -zSP5eN+3QdWWJHbiFrnhgL$0@}2=;5>Nx>=IkogQQs0WmP_Fu*Cu}$DslH<;Do)Q^e -zH%ayBz02n-A(}pz^$@4!%5lw5r%zIXn3D%M6{S81n$NDm>u?1OWZzd!uI9sKx$ZtO -zw+V9+Z{*jn&EDH+Usz)s_In8@2;AE47lyue)J5ovE4_tT$M7-e8Lr7!N4wr0p=h3( -zJ@sJHP40tpQx4Tmn3^ZR2C!%a3Sgr9+`OrMi}5tTqYG;|Nl&Gi!VLjK=sIbzLHIR< -z9ar4w`xf({yFMb`aF6%;L;5vh9Lp-02#j3)B~^lCt}8P5}vE(mj|(Ckn_0h^8WX!(i^Kzg38$7$}2c7ZbpMK^|`31HuU -zk;$2_3gNMVG=22g;GXdF)Gc$&XC6>2qs~vzl0mQS$F^S{Xeu==uFZXWjhcj=pZJyMJ~fPC-cFWbW9^ZD;DzM`p57q8rk -zAkGd0@wuR80QcI_i)3Gt3jZCgu2KeKXM_3R#d}ZQ;Fc)Ivj6){pNZg(Yc-^I}F%xuGFg;t#MMT&%L0t()o3P*V&}h -zBNF%3c@7H(uxJvvf^`>Qs8CbyiO-ab3o?7#ff&j3-I~J@|3-{F9tH^$~vtUFHL -zx7z6*M(5*+yeIHXks(UrH|vkuwjC$rTo$I;yzem;kRWhTKXJMb5R&tiB(%0*QWy8X -z8*<9G7@dyPfkQ-82lPuEU6f8OkF)d%XWkgnHA0i$i|wZvpwLIQ8cj~XQs$RpD1fJH -zmPTF94O#zE1)z5PLXG#3ockTgK5U=U6IcC4_MVtC6ZPfUKzxVED-CY!#~;#LRcL*! -zUY~1oDpQFNyw@6;msfGEj@(c!lf{l;+&v?q?%BHNR!jgWnQ+4+x4}EiXBNP -zP|%Z}-l8KsKir)*65uc`T#z3qL+@Nx*_Ae5OSADU5cc0^U*)ym}DaT(m);5JvN~ -zh*>#hcy4*z8UKbaby^%#WUJ;$5+6!@cGmJ*l9rA5!8cAjY&1)B~F3Bseh1+%=| -z#qdhUpVAYLKa*bPVPk6D&c}n}e13^TGvc6A+9=h(Iz2Wpv -zpN056u&U(>&0*iit2*IThDYqwY5tC7?Z7eh)pPZDp$QfX=SNj9T~6}JfY@F*#9!Ju -zCeSF)rN>mhGhX6S*HdNiShZbCT%Q~Lo~roC)PCwQzwoDa#yW2$M4nE8VCpm5Y2R9& -zgA5)pD4H|+x$?$%911I4h>zq1k-NfdoIC_Nz4|%m39}# -zgT!s;OTCk=D`u``^9o)l(hb($3*2P0Rb$uHcu_&C<+I;qe_PD5K5h3HtIHHp;C{~a -zV`%(8e8QC+7wSsZ@)plH-Ey~`kKn;wdHlPq%~9`JBcb}45fHyeTr~lmA(!3bZEt5f -zr{|V{R|Ar8%lnV4^P~XM$*n!~bvVtVBxj;TsmQ${=@pQDB>E(D=hqi(s3QsBbeY3( -z71$oE$-rZTI7{Tb<@LZa1J9L?b5P0Bi2muBBQzvwlM3GYYTn`C1S4s*P;TJ!HH(qR -z7gL?+mqHPbFbXor2}axtw!lbR=C3pv^Ldb!>Bj$NQ9?94LZ=AXWQyv{3ST@2kidHC -z$fI>W(j94c!^R&A;CXxR)X_j%=W||F-n)LOQWxG%+*jKMlu9YZ8%%Ytc0KL+4N$tm -z`5a5zjlP4|0H3;W&=kLuL3=`7?<32`J9#_{u!h9Pw~dm=W|o1V1+kh<&Ma)MQ*8 -zhflJH$1#_G!!@BoebTrcQttcT=LvG0$M&=FvZJg3`^4;F%Di&a|JO4OY~KosrPbECdK2cospfIv>X+iyS9}_Og$Klcj{5^XXH#(eZ1UB|avEm?rWyirz7{~a -zeG}^}M25xn-b<73n=)a%?}LGPL0W)BRX}9#y<`0&!8LPbtrmlv_iFHutV( -zfr&>%W)q$Ut3La{PL0p@oFhBOjvE -zy*5`j7@lIRm749gt6%c_HzmbYWqr;vDs@m~k&SNL+2&ifD*&+3^v?>5t -z$z(4D?aY?35ZKgH%TkTzeAa3c2K5$UWS?C599}2+)v`?0FLm$niM^1Z-*@e)y2Eto -zJjs0QGsn2&Ky#fg-V=4P<{rQBcHpJdtIN|oQg*PB4;zFS*cFvQXitLjOK{Y8L-6d~ -zM;YkEZKu97;un%~g}o>+-G(`!?VHO=u;VACc^?d1Uz9uWRM5!!dsj~-ltil?2!~A2 -zo1XAsTnwqs?U4q4vLMT2A?NS!aR&DwyK={#PcXWr3)4X@gw)64y*cq56`!10nEtu& -zeh=QJP5ZGE_g>L@^`KG=F`6v;AeCphx*8#tEbFSv2`{4(C6<-quys?lcZ*J#PCfn{C-AoG!(RGa12Ii(>rI_h=u -zq#dbKeeYC%Q|9Ce3Vi(mg6K5|-K74-Sc2Fo$DFQy;Pbs(5%(wS4z~5Pv)E -zGYqablRORuuZg&C&}Yo;-KV)%vq`N%m9U@r5>oloC5CGQX+@5hH4=N$IB*f3q!&Y}72_Nxi_ed&??uEXu- -z)<=E6`G9+AFD4KPzi=vua!Oc7nTh)rwXuA<`J0zU0vq>i9ub!0IiyzC9@_=H=Q5Y4 -z5kyn7`9-4*=FRJE9;8J@rW`pF^)m9UGyKpdzJ&b^l)~dSaG__wBu;U;6cpWB#*zUj!0Y|1|NkfkMA2XK-o3{ExKzdmWg99=0p?*`D{w4{t8O9RG?}yocpbBw9lq -zdt~vOYNj)`-^y94CK9olNt5dfo!7DWQgr5)aNeN$+@u|eG)_R`5r`uszC`*SV~($? -zmWfe|)FUf?3h!vu_9#t|EJUxkOFhU&FGgYFa5wU!vuW>AC_T_JYy95X*AHkG;|a(N -z2KL*goR4@$bgAZHPY$TQg8y1bEpF!%#N*?7A*6fZAZtK5d~4_c-}`V8{~0a?huC@xWtMI1*U*oi*){wBkt{ -za5*n4qdQoA>oez}5h8OT^S0ZC`Y5U7XeJED#h1A<=KtUD|G)j8|MUNOhvWbHfBip$ -z{_iOIfBirH&;R>BwR~*1bUpV>n?7cC*hB*!9#Gs*mV|qllJAD&r6j|4}P9Z -zfWNMXntf67RMTfYNKGyaWEu2j9l=biISvVs@(o&j(z?;Mzi81yyEzma)p`${* -z)wg0A6>!^a^`xTkil48RqBB$6cGx#?4CA*!)K9gw^EYD3LL`>qY+Ab*#GgV$6qw&V -zb?d&fhaqtC+&-yb3Wmf1DaoYk)-3+XLs#N`6Jw2-$$)6$l -zO(m1Rb!gMqz3JRDc*0N;AJGWFilz-Kme1JOIWN}+IWFDL3tWDM1pf~!?zXS5ZF(qm -zh5mN=y^kkX)3RsY6MkR9hVidFcyvSpryp&bL0)sa8?*CE2=VtCmE(-cU;6|DTEVpJ_Z#XybY8Nbl+RP*%yM(02KtF6bzIGb#7w@DpN;>>U+9$25L# -z1#BR?aaMu4+Z~@hC-g2D{wZIEWn+~jx?Sp1kMRuO+ZdYhZ+Fp;-E+(FPQLVuk}+RR -z=VyQa_h`9bD0t+zx!)elFY4O#nBy`1dqFHe&o;fEiOV@qMK?-8j~ZB1(tZ+wm82&x -zi`i@m-U`&8N;JRclO5+=90sQD>hqaS;nmx)4mR`Wq&{EzP;mj9{mbfm;9Uf$5&SQ$fzu$&Yaq4#f5NIg|T)QWCz!yI}#6(X$cD=$72xXAf3f8~OXp -zp3yVXEC{q{>ADZIheJjZpNsu|a=IerL4a?Q^VCDG`P+~AcMd{5m#*Ii74;o;9}{7S -z2~cC}yDop50yhjTUQ+|Lxp@23Ja+hq#QI{~oV+++NokUftRj#~Tx9<3`ucn6|C76z -z&91r4JX{$&=FFBcFNS@pz<&;yVe+K(AdD**S7eIhhEhm*Y0S6kPk^AuS@PB*(HyG_ -zzn$}c5B`XO%eKv7JQ{fb+v!+BC6R}@wrml${|V_d2DrWsiptru$_3GSjp$xTKE_s; -z)?dKzLzyU5%|o;9luWF}*feM>p{HY?Q|fs?eX0X#7b)8TPJ7mPiMy -zW>ME!zfKa$@S+*^7`5`WDr=mkRJ9y~_&r04ziojl6VT-DXN09&33`>vKC|X_N=e!c -z-9z`b;R%GB?%u=oGKGqk@J2pT;jlihMyx4|Dm9|{@MN3_HF%)%#T%V -zp2rAo3Ntidujc1@jIA(K6|!OL$=%axsMUwk)5jxei@J~S&p!v;VHhq -zH}mj!MIzn>rSU7f67T>p@~6A$?S~KU2Z#j(&!CRWL|rK0zbnIADAF%8pIgwu2{&HcmK@Siy@E{FoJGmc%|;+aV8b__R#kgtD{=41gmhD-n7} -ze>U-c7i1Lo2v2=pS^w&Iz*2U-Jl*1va}{Y|KVgl1H^uu>OqZIb{Eansx9P4G%Q5%) -ztZSF?PC!^el*2tL78U6GDTB3`$#`*{U+e^b*KiWMcJA)^BnPO*I`H$3Y#N!e(sM98 -z5M%19Nx17bD9t0e8O?u2VST`9s*iqp_BR6`(E=39V`%#_`8~nRmtN|UoTz*^jD&uc -zh4FXUhiyf#MS0O-xCJksp%Gi?`6kW~_>>aWKJ@A8Dj}u==p@shfEfNgouzzpw;m`! -z%Zu*g9kPO(k*L636897*q+7FDXInC)#!pQ3AC;nmp^X!J7l__x -z`Bl9CU0b?FwV2$skQ;88e9q<_ehP0na`uxu&Ht%Vm+nWQ|+x2b5SmHxTq~k`W;&g-1(KK=y#0_&M@tez}9>P|N4Lr2#uz+=)m=>1Kpqd*Uljy -z1#&!q2Ia&xI?;uhFXrgqmEU_T1}}7G97Dh1p*B)Do(G${2j*p*`$&n$F{NGpY$$$l -zd-`2fBQn7EU%{UGA{@y-1kAIT>uoRJe2VapkqVqnw{UbM8;>x24vgO{>JZ!qP5xe0 -z_Awd5eeVoyrIh?4zuz3=mya@bDY&9VJ{nr|BR5o>u~B9g<-F9c^PM8CtyLe -zJIjGe^4Mm6f6&>w=d(bg*(puJ6rcQ@fiN`hA-NiVn)l$z>S)?o8cCO13HM;&y=OL5 -zPe%JeV|zL26UzwSDoviB!%+0Qa<_8z^!5u)5AOtj!we6`)ltcvj`SMH5fo?XN$=7F -zz-gW2@BV?TbZtJ$84t;5{T(@5w{MBugyhTqcsSWT3eE-K7)Jw4Bq0F&9Jo5yXxNkL -z_cQ*EF9G^*Y`$hbcdHr%v18b-w~gXlIiu8KsE3@>p(cgpj9G%#!lRQDFT7o_nNw(! -z@psMmGZ(dpZarg<1h-?hLKyU;*;;qoZs)eE-f!DK*DjpuU$qDNT^&5e6lVCs{Y6F- -z_%}uaLRd{jv^S;d6SCrQac&OTyZLRR*ZSu>YpA50H}^{9`*}D2%}UY>r}6Wcd3&dNh7+$noZH*$Af-jmNNT98$P -z*NP~3X84{VbZeReS`Fu5Fh=nK;~R^&M}~eD}apZ7CUChvGIGi{A7HvKuX&T?V7xRdony{ -z&AmFMmKC&aowC&v)AD#~|1Ca$JCol#g3|zZ3_}&FnsFW`6$iQT)GDkudAH$zejB! -zjj;qslVT*0S~@+4`}$ts$78iiEK~P#p<{*Dp)QvG)w$r`b>F4t?~C%vz(%d_e9t -z>Se}vkI_pjfGiPbqP~Sxzg&>3isvpC_}qs1I>bGKe^)U;;M+==S*|VXt9$@6+^if3 -zA;|2qUz*3mugVk(TQ&a_c;Vl*S9r(b_{-uI^tn8}0~VCaxOMk^cZ_oDp>7i3exYQ? -zIZxPbBUG||9rGG|l-o7)<~#tKr}SECYtY{l8d)c+3|7gnc;^AoSh571Y`?-&a+9Jm -z`rt%OXG!9j3%}3>|E|{dplb#r=y<}z72noLp6Y$4eC}zy>#RV-L0`LDUH9H#tvl|J -zS4)f?MI6WdK|LLL2Yk0w?7o}9_-9{lEqjn|G`K}rM-F2ZHx*xU2tciV|H3w6A7c9k -ziEl6m|BPY3>${I+*KrU-!OEq*1qOQ_i$6r7EzMcyMq%(dQ=gUZSjeZVjWDr#wxNgu -z_7VSU-Dwur7J`ouTc>JP{Q2aw&Jyo;#X{Jn1CAecbQlPNeJ^(`s)vP6B;xv%-9Zig -zdCuiOCPFo(y6(=)7EStz%;nZW2mxVxs6X7dTYcMk=r$$1S0Q|@Nt3B^EL}o_>eJBd -zZ)cou(TtoIbn9Oo`A@!}oe$H&86Yk-PbF=J3{vaBC0jKx|9Y_dDLcNyFUQz_f9t<% -z$WpSgs!KSqPUjTic!#5N@U(*86B0H8n|MW&DkHwOk5-T=E6n2$kNusk_gRjYvHd_XSAa~e!Qb7<&gQR`rgX02IjmA=i}2qsXdgb4C8HVLr+uw>;ldjFPn7bz>TE}C -z&H(0|u!=_>+*Nh`p?scMx@c#qP(y01WF5E~E*w0TM9`mHCy?FSt8MHDX8K!U -zD~`N(Nr5%~)*O+tyRD-e?$Zn}+rGb=GwmRJJ#zAVRu6PiTDcF?Z4vzW?f&clmtP85od;$g$y!*W7D=}+ygdwQooVT@&)^O*EYYn-=IEe(#{DtvhI -zQN|R#S8vUcliq)i=3j?K9~}MS9CDys3iP8E=aZRf(EXgjnyrF&jv1~e_0L=IyB1#d -z;@#!5e0qU7@S=t9iX#JAupRUS5++`+4ZAjXmD(Fm#SnpW+a`oi03j=H7%~{Z08@ -zJzufX@3TJAqQ@`JVX1eUPa^BXwbWs^@3f$z%kAp$q8Bqk5~#29o=6TPK*mT-^CtB! -zdBkqCiLbX1*?B+->NNjdcR&keKJz$1vJTd_n-V(-#KLUmu8#F-j@LTn8$sHXqF-lozgRO>O73n8_UUEJz_WL -zQ9_u_S&?_J>QpkkpyecC$b%d6XSJ|66V%8F06Up0%;+A^G(Nzo@R?H2!350_Ei_n9 -zCONpjx_I)tLVq3rr1rh;b2H)7^SZjIXnwx_Lk)-E)qJzEeU3Ws!#zSl@y@a -z0a(f-s1qT-_X~d4^tTv!CeiA6obv)X-Os1m(>xp`-8g1lVw-^7W(EVzzma7(?{W%( -z2rhf<4HJTRUz(pgeL~WR!1<-C;nVT1Vv;faFi3e -zuG?Ha06Rd$zi`lFxJNzeO0NvzEmE*!`SQi0raxZhe6hmna$%i0v+tC1XQ~uNk(~SK -zSJP?GGK)Xwpe)LpGljO8xZCYu$BScZ{J@p);p3yL$2voh+UepXnEtGx$bX1<@>+em -z!@~GzO$$}M>yy-U1j;kKWZhvRy-{}hkX?#va3+Tk1nzrvj{_jirPKG;^$zZ}F^Ksl -ze$#8WFOp+>n3=+ZPg}g%hW`WahB*>SNEnz7kVyH!GKswx(c1?v&DkAVGt`UGLyUIh -zXO{Wh%{Y{ee$MJNrtUwA`|jUNTh4k{^QY@|?4C!!IbaCaR$>Ae-a -z_Yxw2P>|xKsCVOk&MwM-^gm|$R>rX#053jFiGZ8YdoE$KigRqVMenGld~$VJ$_}Rn -zC7h98hDL2MNe|sT@F`38xfiFq=l$dyI|5zT_oHisWV2#<4_%A!_!F1Bz%)3)8F(KK -zzu2?IX<#N?tjgIB{Huo?fc!*N%L*`2epRUCcgG|{9>0(&3fhgqdf&Al)4*Aig6a!o -z`1#k|N&~oY0SXc-Ebywul^Au@8xP?*tCpoYbDYQeKb7gVhb2MChmbm7fLG=;Pi*#{ -z6W|elJ2-@DPV2+LbvX859jEHE3WpEx%i -zwXUd0SGa`JdT>>C`KH6hjZtBh5n-%U1e4D(Ax6Gxe5Zrupd=Uo(fip**)4gRUJ%wf -z7w-E86`?s#QfS@%guM-nul_xWii@Yg+VX%p<&CmXn!8m7wRhdE@`CKmT_Hk|gYJp$ -z@^g+$|3eWiw=YqjZOfI*QMOEiW?jeHTSC%@`_W5nT;(x4k=b%W!ehet(4y)dC&uvej7b}~bKUc;}b^g}u0t8$*V~3%WKjCut7tc1f -zSA)HRs7bNR-%TIyy!Gv`$j|rlyBYvse((KfS(5%q5Q1ub;w|F$kjlcANgebTJ>56t -zY~Pm|+VfDsX}K~PMSm}d -zCw_8Deu3?=Vf$>|7a@tk!up&$9L;ogKzGkB#sOW7r1+Js^mpe+`G8D?E6I^U7^}?) -z2uOFhzDR=<^`wTLzL=me<()do5uTQ -zO=}2wN`mihr`$N%8h9}R{+?OSn>SNk3i+)6^95h%jBi)Nz$CgYgFym!cPv^GX#h|C -zVh8%WSJbS+Iq!nrrL=Pj8}J?X$CRqX*iMT&1iTL~#A{?&c4{KhP~sa2-&$_(N7igB -z=u;}&mtplx)jM#yhp(TP6Q(s%lKJ|a)p9JY7~MMTEJ^i0_}%+^=cE<^bhN+G&ZTo( -z5XaAQcs33mc=(L)pf1PDHozIb>J0k3yL7NGU3PZ@iMl$EKIFoj{KPct!p?0w-2G3# -za0Syn3BXI-nMBwh!U^2sI&jYMx@TX2R74J8=+W7C#$MK&J(~c;XXTUrtM_s=J5f$j -zcC?6A|2?UC=Zkolh_~A0>cJ4f)2L$ -ztKasW&LJ`6`uV1Qcd#xb@6K|wSeDs2?=iy==~UpOxcSiUr@i8GKY`x#8&*wvK;AhZ -z|7R{q87-?y8RvxT<3Ed}+p_+si;UkrPVZip9!Y_+Qa|%B>Vdm!d{0UhB3>=|TNE|Y -zWYNRW`5O%&nmR-W`lJg~tsoY8>p)4z5qa=Z34F%TjJ7Iayi+@8(=7DZcOK -zT={vjes{@~*cb7R<>?pF4eEh<9yzK5eq3PVl$QI^+i6^;!#H`JHY(9HS_ArQSPC@F -zgSgdp@6+ilA=Rw;Z=`o@>>QHDGNJ-H~DawQP -zBpX;?$BGFQSCPKC$3I(?5k6?&d=#7kca|4Z)eeCMpwta1N!?2cL01sF+>FU`II@BhN{tkrY#p=1VuMo(1dEsYaIRpwK`h!Y4e}B -z>USp&ob`PB@Vi{4oF-UT4BbWo_JI_TdIZ34BW+*6CgievfgZN3^!4SJ*J!vq*-0)n -z$^rnn>h+cAv5n}5F=e~nQABf@kkfqM^<&8h>N2oFWOc89dU>Ab{5?7N*_#vA+}L_w -zX$|K)SIZBARQ6st+MI>Noa0SbgYUUTKiSOh-ko~+y7SG0Fgj3=KZdw!tlSfhH!m(x -z^$iX>SFczc_TqcU=M1it>3Qi)rYGlKd8zeG`O8(7x3)sf8~jY%PZ(T2Ys3fSz1id< -z)Hr%x9>a$&k^7-I)+E7z`7@TS;2gja!%J>n=!>@}+3X@A@32THZW!}kn-fvENfEpZI@*ucaL&?FTKm;!J-9?=2}Be(b&G -zI%bBK4Hys*578lKy)w7QH01y&D0g8`g>d7Z-jfE -zv`3UDSWodwR>O|>pe)O`z0?z({+Veh3vxlkEoDgSgIH|8>~ -zsp`AKU3eH=4)`+gL~8r8UT+XoZ|s3^g0PUv|r -zalf!|ew{e`-BCOyGT1oM=aIf6%A)y+bJ8v!)o-asua6r5cCCK674u!FMdiNHa!>Es -zp0VVUI0=AGB{7-A=MYk=;Y1vkl7n*m->HLr^c^?>2_L|nP*I>IzRUfuiG|(7daM3^ -zcV!$gxWo|1$GkG$0SB&(6H(On9HJrsJ2K%|=c^GHi0Dt9s^1lxLYRBl&%Dhl*4Ijm#!=58pnal4KnWnY;#uvML40O$r1N+yP^$+ -zmWCS1UbeJr7u7>LAI=%@xKmarcFkX4-#UBG-<480V#OKEdc3F4nd<I(YYr%KtMf!(9PbtB>yM~s2Ht!98WT5Jtu8?B{Vgr0E -zeaGVcw9pTp%HN*ek9>5-0gH%AXT(-jTQzg1yM9&Hhsz&bmxIn#_Z;;{)PK$9+kb33 -z8Eyd*!|c81NWOEi7YojC!6R>S@9IlKQb`Uo>RKt2aPBy0t1xU2g90JJJQ$*|=Y0KORPV_^P*6HEasTc7ywgnEB8HoTSL{wT -zdlrSa7EW?#q7J?PDVyIAGBC$XutE5~ko&hF-e;XEc&vi+h`Py{#o=n=(|3w!jw(Rz -zV;fky=aE+D#$SCy``t^m=z>(eG7c&!uzoJYFQClE6qWi$AC@dk}~K -z<2D>Y;``ZC9w6htE4Ot_`u4?$xbu-{+&?e^)sE-!ZY~q;DxZes -z2j{#H`C4ezx$A8)_8r$>H7NVt;U$j)L4p+$(;GhLma@6E&ni~F6-g!~pa(x5Ucy$ut?@Do>u -z8_^dRmqgzmqX8ATewP2-Ewc$fM@N~sPDKD;(A$}PQ(yS(diSn1+%GXTC90qU -zf%*Q-Gymb~)?PaNxvG#7?>S<83)$;f^(+$vSL|I -z9lV_bkhf-`$oMwR+~!l3EdcRybakopbUt*F?h^9y1z|uzgPWruoFO1|43IiAo6Q(9uV{;cJt45I72( -zj5lNxJOqt+9O(LT1v64!$HS>P5rwDR;XA~%UYD{NAMdV5EVZVW5V_@Lufl82%)E$? -zu82g43u6ktvs_IrEvpwScI=e2u_7V|?d>~4V*}3G^{q|*iOd5Y#%htO$^n_ON7aq; -z=(ic17eG~IrczP?sd0i{*c0KOZ}evt3O5=kwF;&C-AjEy$k!s2kejbv5qJ=G;9uG1 -zQ4tG*JZyoy^jQT!7`7c^pB{r#i+yYmg^KvSM|xDJvu1JK?tV%hr`QS7?jiHKa3&39 -zLh2aO(b87XfmrM1UR%@Q3)KXP8NDnII{cZB5dBIkMJNz#`6As<^V2^`s|SYj7=+y& -z%VH#j8i7Gc`&Fm#-@R=By~k2{Z&&YWY`5~zWA6>DirY~ihmCMp$9CSYZ9no2K7X=A -zHHu3&bdya7&Zpaf4{zPmqj+AJ9u?pccrP*HC2hD`zGZq@<$xSgX`Z=YaNtbcR0r3^ -z315$VE$`H -zTE95B|L%tGp}K}8SV>hJ+>2h<7JJXB0l(=-ST)Dp-{GZ6I$jw4IN-6$1E2M$To*nM -zrC!UM=Ut*eI{ql8ai3m1#<7Rp`S8uSiOc*B<9&P!YKTPcz4EwYIk;)x0GD`I{eor5 -z)sqOh?^#2$A` -z|9t4v(avl4#zSZ(B+cEaPPIg{q-IA5t(J>J{F|uzG>lwV^{&J5+rkeVD{p)rvyZ9@ -zPZ^#}ipVQnk2Si6#>OQ_?Yu~GY%coyWwaSC&@8Gj>o0DbMpbNJ-0K!7oQJG*4nyG4 -zd**;%KIHtTh6Xg{RNgtsF=vm|ow;s=$#!+_C%bT8m}z^oUOke&A=oqfYah^mcifey -zzTTp^44mE3rjz-ej?3<6DA|vw`BCa*H?!iT6L! -z3s%3S9N!<_INWVXRRn=dGJ(8{Wxwty{P(T?73y9fo -zoCMxsTD{Dwdhchfm!}x{0boO0kS*!p=ceD*!uq);PxQ)_vTznHnt<-P6_iZ&m*)UjKxeUc`%p)Ywp- -zE(rrPF2}3ThRyJ$s|Nkf9s8&H&423vF5`Ng8w*M}!Z<|94z)6oHKI4Sg}dgxn8#Te -zHXo5b=fFzgpd7IplKV}~yBTOVkFRO~YS*J|_kQyJBV?zzj*B>$VC&; -zUay&!MSsw!=&E}H=g}(i{>>Erqa#;*lkcXnzmO^@ul-n3)jmQNY&?(f_ZY@!4Jo%H -za6HuX&MY?5-^HY1SCum7%yA;x9p~PJV8y*W$q66AnlUcFhe^uWg+>p)#>h0rP6c -zt(KDn_{fp^cQsF!zk95o@A$XY;Jgz2%~d;b{HO$d^J(E+xF4mRVPbKfHa|DQGq?vk -zPwQSkb8yKqe~bzL9R!j0a)b$gNK-+2z7u8W3x@$|J)+dF;a -zK$>*xQDINS^t}^f@7pPUzvbT@a~hDyly$VocW&yjAm`C@&a&YneSzS4Cz@qyh-IO) -z^qV}n53-rasR5v)aF~n!9c1CU`im_4UeF5=+LLu(F1km+<)Ll(GM^NcyVxdU$)@h< -zzDbwU_A>h;rDNk?lXiwSP9;GCQF3 -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 -zKjNqEB~vjsEa(fCe&U||ABr{Z3wr=m* -z`4E09i-P&g>O&azwLQF&gQ;)(>DhB0OT9OaKnuiN09|i67S64LondZ)CYhDc!m&;R -zkGBE!aR`&HV!%h55EKiyvd{I2s0o(^k#=!t;9H#ox>Edtiur7PxxgtF9?5y+yEk+OophzI!UaY_81V -zVfn(F0~qB*ryHQ^9y5CzQe+&_%Pm-VO~9E@9kael$1k;So{n -zas+!IaOckj$&0b!K5R>3HhJ#hqii1EI>>uRx4UZ)dZ-m|&3C(xPQStIZ~f98j0H^R -zE!}p6@7{;H{MJpnT@h5mFGZFeA0j;$2!<;Zx^VOnOpHK*hFan-lKiJogneTb>gL -zkXskfr-N>39@s-+20wlE;Xe!lBA1}_+CFM+86J6yoay9&+etE?LCwW`G?$(C>i9V* -zZm*!jXHx*q}=&TEv{_|}PsD{A_|;EUgIrtaLkYIMyaC_8@__5V;w*{;K>xJ;j^ -z7b{tK85JZJ4O8IsmcODI$|BC6QiqGlMNt^9gGE`SZiIt@pn$6$pgWDG4dP+T5~*F7 -zmj6F^d+UTfsAVg;*Wl&34jp7JGN(X0X!{+pNy%af-ecoCwr38I+zp?0t7udr#aF?3 -z5GYn3{GwUIa9|hf6auxL$(#@md9?-9`){BA#Ms@SDuS@m^PPuFn1$z~=^JHjtmPn) -zbw|x2n2b7IwM%5vLT{cc -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 -zf=VvzZ4Ww^RYvV|hL5G%{#3!C19fPCB2{ylIg -z>#U>!KR9aFb4g)@yI>6h&-Drp&&u?J*BtEPF@>Y8=l)!{-@-*d)Gf{eN8Yp3*mt3~ -zjINwt^L~paR4RS4^5jc*koK)JOxq`Nr%0HFbo+*qzD)PH0#313%oJ06{&J@>_hrh~ -zH3D3GU-%%aE>hI!|+zl -zXQsPi;H#QIm=t}bOX?xhK&dTH#0W1hcU`zqmJa(eKBf&I8Qe&-zx8#F=$HD@+>0bI -zbw2M-=X(xak7A0^y7pKt-r*!N?_5v0 -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 -z>t+Yep9~L;{khctVG4aJbB@iG -zxaRZ#bDskJ*N+O<#XKdYa`qvexm-R%t7>G(YPvnzv_42FkBUY(fRFR%J%B12a%=*+_gcsvfp)oYDVi_}f+ -zH6!PUmW>7q?im>32yu!WJqHWVJgSCo;~EYP@hR4uA#E)Pw9)JHpoE_UBN -zJ}0Bu(%bgbEdY^kd`mKm+de_~L3V?i(57RhZ`W2;*XK2BXp%DLQgk~()O-3Ct=bp@ -zvvG5~hsE$X9C(0hs=|xCFx>eC^x;h9i!5sZ+Yl@GKZ?uM@c_R<{B4Lf-g1;ec_5wn?IsCu3<8K$Ikl-HgTG!6}E2Vq$vcU*xK7u -zT|92~Aot3{mW>cfN(_y7378}t;YtT%Pvj9h5kgB)E}!#kVX3QpDTbA@n@zs9Ogwfe -zhT6{}9(l`yR(~#dBDko<$!5kJ;kr9G6hPx;B1Kts$>J85d_Nw#YA@J-Tu{jGhH-r{ -z=WdU@-px;?F)mrNn%O<)z?|@x1^W72hKI>pL&EuUjagIw-1Z^DdG`)MeA+EL8BubT -zZUdajOI#ZBP5ZTqOo`#N;l=5d!-v_~N%o@Jxyf_fA38Wr351HHGk~KADU9WQH1=V^ -zJWH#$@-))zcvZl@{xjb=bvk$tFy7nLm=&pF$LT#=pL*eYR1pdJVw-0baq2gRN}mOg -z=U%I;G%nrbF?-=g#>;ehfs=f5i#g4JtM5I88i>Syk5(N-xX#`inkc7N<`idVS%`f| -zKM#>l_NUAVNU>6{3JTocOa9w%+|Dd3K{KR<_`T^5l?>}0(Ngpq-3TzkIYKvpHu=@8 -zuT!gG?Djq9bF?t3rdyvZZQ`YG1jb4e8I@k8J+C;a%!6Xp$PTwCb!+bR={jog0tn^a -z&aq9C7OS>>fFzLUN-?dDSsZRJLlj5J(l&@Ia+63~e_tx9SCC1+{W5>Z$2YmS0 -zs+Yp6^M{0_Yq8;{T%r7KW9LC-g?8&RnOYuwZ_E3b^{FN}T;{UyJ?WXb5QmMtW+UE{ -z(;+U%*30O85h=tE^XAuQD+4CC+(Izvgs1owRlbd{sD>n+D~Go6-rT7cWfRl0s^4Yz -zT!PC{_ljc7CdJ-urao=^aI&q13bewtf_o;5lfwvAum_9-tAM_i{7uZu^!_uE&_8Lg -zD{k>1-#J8q9HVmT+NY;>QV;t#M)b0(KVo+=&(YHmNk+|wYr-54@7mFNa3T_oJ+DCH -zshGd-r};LGQfOel_b301*jUfdrxX0i5h8rojJVL=c0&s6_ysf0~IX3(S5=cf@%1~>=cXiVx4&WC{J^>zxD60#WdipSK -zh1Pgd^&EO2u+hxEoACqu?KZp8U25uEtsDKQ=%1}beOMl%w0!Z`i4V-aXI2XDh(b*B -z`>37uVP)V`NxVnMf4Ahy?^bzl>fwdtw|=hg@%TDu;!BdYaIqT70v-cJ6<9i<@%f*< -zSY^ySQg&Epn(?e6qtETnud57#A_F8)oIi0=)=%D@Jk4Iv;CMXzBvzi@C!pab2{z|k -ze!LN?9=x~94G@ajMfXyrZJA(41sV!t$GugbZIs_dxHbM2GfeiY7^g_?Y -zanV})TL+!sLdU=sy%@?{z}=6*_$2N&*BX@SUhlJfUo!RVc%L7C$Nlf-`jR7=9ZjaC -z(AC#Dk3MFDH}8I$w_{ii_9~ZTQeDC>#?5Lk-4gZVF?ZHAPu+CRjF+~YhybULtDmW_ -zb8M4bEwnMH;eKT;WLS!jK+p!3^t#Oer1NvaQv+uU3Yx%$$05;*{~}<=6;d=;fYFK -za^mG2RqWg45hr9?@chR1zuWP@So2H|Q)Aj8BS($nfe$lA@ZRxn -zj<(}NN=K9g9p7eQG6z!2%^NdyVjsOBA9brJcn=VCl~Zr@aabu5O&b1`A@#m0{OLV$ -zC;K2zC*9P76_7o#;{{V}3=&1)3zwG~uK_lGNWXJSx(P5PM3@ -zKNHy~9!UTD9R8KtqE82pDbDc+__ZGoQ9~-=Pw;BB>epBOVi&C{0~pK -z;Y)JM$H#z7Ae`dEDW)x)p#NMyKve| -z>mNJ~2fhHk4(O=BF74V*$h1fdaH1&YYxV*PVB0yd*+-|sO5~b#bC=1A=NSvkZLNBE -zmt>@s=2EtZs*8_Y@`Q=G@QhVM*a0ahuw=0A!!<@hUuW -zX{6C32NPM<{i;g1^Ql{_oNez>jjdJDWhO9^S9!YO+9`4U+iL8luA@`)rbI>_9;**B -z5BSj-Z@bx2iW2P?t#w{Coc5n1wN-^BF{5W(~ -zU;XTU^okq?{RF@50%M=4h`YzMkr3yy-W;cM?qlPR>xQ@AZuX+GgWU~NP;=*+UK6Id -zfjKd7sJabb0^XJ*h&SiXxs4D1*|ycd&?EFvU!bfQ>QIIF>|IgmBH+3Yp&#WmGH_Pp -z_1W|@a!ZjjO&^^EeVGs!3pDf96hpdwsvP$*juTy?3FA%{&ak7ew5v5-RR^lafr+a= -z(+KjtTF_p!FRPMJGXKf<_c-A79{S{D;Q=bR+s;UROzH+HbP#2HtY`#$&r-qTI6n)4 -z{vHwlyKu^luB9J)?@%AT-_NVeX^9e5Vk`Gkz+t?L3F^|X@<5R#Kg5G+D@Y}a=_C$g -z5SLgJ=~aKY5E{&A8k9-i{@$i(%?|UL1FzSR-D8h13r<;=F#IkV$Onp|uYDTx -zXOGb#*?OA`YjbLVU=G|zqQ9_dFVTb%EvT& -zh=J1Smd?cSsn3-#jD!58PV|n@Lz#$ -zW7PwGCJeF|fv8W&K2C7^;g%s_D7=hV^=d0QlKn?6_&rvj?sFwCs6-Z_-`;c6Ggw$K -z&8l0;$Na!(&sK!pgt{S0(UMLP3@0Dh{h#n~SANbHmM(E(*6AdWrw5Q>o*TsnH11;% -zaaZRtEdyAdG-u6HIf!|Q?hyufNo#gYE)E~FqM96VqPcpi@yIKpRL4t#n7+xVJE$0f -zC*>Y~_`#e9*!QHg)?GwcH#|yZapZ>O_xY>pEHxNCtOHzyA3{52=Nn{(w@QhPc>G?@ -z_m^Au1RhnwW5%MMQ$`8Hw_e#sLN?!tl(F;YJsu&R14l|J)xB`aCQdJ2c)_GMqvhTd -zgJtlblV|vC!X5pOjqo3X2!8d3%_no^_DZND^AY$uQHCyGGg^X9D@HXiziy>!MREGm -zee_m>ndL6IcrFbN;bRRB(UW^PQwTW~{MrV9lAZ@+Q_qDpUnN(4-~*3`d@>(3)IlkF -z+QP=_)7@Iy#QEplJ?FY1%{^?W*LfT42*$|grdP%Uyipi~xPj|s_r-HLO(cm$cj_5B -z>>@U|58OEjd7xeaK6)Z17dyBfdBwJVZ)O`}M^5sKe3USnnEX`fTY4W8Iz21g@|`Ip -ztNBYZF9BbJ#J}(OKymP1IC5mlwu>K{9nP9PERQJYbWUhI4jLqBYj2Mpzw`5sPyb_d -zAt{JuMZe>C^}~KOM6ua#@VOCrZ|y96F|-vpXAZ9&PA!zpwIzL5ccJot9%#bpj0xnOnVb0g^>p1MxP2+45Z`h#N<<_ijRs8dr# -z6ZOtpkgj-Xi6z~Lh0}!|Ws9xtZ~>j^%!eHw47umC<bstQ@RY6Ft?ZQN*7_LYtX7Xz?){;3X0Kf0|_4lwt#TcviRuHQ -z^S1UnL;5W^uS|rlo7(t=%a0Bzmdo1$-t_i9Gp?{|JFGF?hyRXpcOQc49x;Z^Q{K?j -zl`r!9Qp@HGQ7edt=Cd(8>}u?1;Y@ey)X^(g-3b?Vt(q93l#WNrfwNT^cX}FL25mr@ -zfnr(6m-C|FPv`L?RsD`|m`_2Xv8m6pG4iaX_{txJgaPOw;W6D5&yQp5NYv`XAcr-#uuS-f%Tgz%!IFw)0t<_Aru-Mw02{M9nN~yncWY -z&J?RMyt3xA)So+WlH@=dBIlm410TGt!4iKp{F4Z(eZ{rK<#SS7&2&cPZ+ODzm3kgK -z>lrq6{s}80tlmw@ya^zTPA_fPBHd4+?3@(=y#r|Tz{IH>K|lAttx;zJupQTRhS4P?`bKA0pj)kk1RkwsOXCrw9oP^9MuN72I(Chw -ziTS~;WPl(#pklPa!5RLyAb7Sr!A)fV^l<$Y37D{L#8nY1P?68U#qGfjI4cME(`5R+ -zA^f)vr(YbUffhwaCWNn(nKk(aaGbO-MoXg45b;rh-neo~K8hHXnco4ypt>yci=HyN -zE;fOJO4)}kxnU{UQ?fPpmR&4$heM7C96XU3)1zaEqkQLtC)LumT2?GDPucLbWv%aG -zBG(-ym&60Uz9@hB9CaSgd1Z~iwz05DZ1bhBCoSdW6myA)j8Dk@VY9~Gvw`m|v)~x% -zG>zL{H~#c#^1LsM5ji{V^NvLR -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 -zN6_Xk{rrMVj}>9Lc|pUGZ-=Kc;quV~`r -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 -zF%dtJFcsY=7{!O&$ayq3@?Sr?5YO4TQkna -z@!ivgLh-K_wuk*|LMX*2-j~11)>^SU75ev)pq0i0Kl$2S&JzU>Ntlch_kJ@52r`^V -zk3J+6~TkAHzMW+p -zw1R2n?h9@itzgmUuN}PvmsFWSwEf1e6>}s`=dPHVK(r6aaCgw##hv;3#mn--pEY=2M;b&XW -zx4kIhbGG8AJmnFOZw7Apv6=G!eyhhw+Kfpa-&e_pn=nEwl#AiPVLFol+P4 -zUg1wTs~t037OopC#|SUD)UgCEx_pgEmQ9-<1nibGJ*`j&>9-d9-Ik_RZRBdh-(cPx -z6sxXBArf4U7HT%n4MoKY%trK6xNDle_RVyMouN2+_$577v=;?aK7}}sLO4_%!>H=44zA!C5)92Fx(>knUdZebSml -zl;qxX9>J!%tGxi0CvSKm9=nP;7fZmX5KeHgbHw^x4b3PHv6URj{8x3#M_!h1A=H$u -z?SmYAQn)L)=dPmOJ&S+W`|+H6%<|{}x;6G30D72BLPz84{^928Edv)N9^Seu@%Y%! -zK>FRtCf-44Rj}RqQmEO|4Laxtyk7ob@|(72f-lc?=C_02SM~f(^?OAj=&^j#J28R; -zdcNz;)x(1O>1DC3we4lhe;_`xm -z&>NLe$7-XdhgqAQTxa&DMvMPyecQz~->ZBeBhn`E>#OLA2n@7ys#(IQ+g_5e%k%xs -zeQ>usGWC>$2IQXEG&46CyJ~n;iK7X00={a5JNGWT3_9ynDKm=qRvI*&bERZS6 -z`m?!yQqz1H&mnWn+o2>nPc(F-*P*GeNG!4PyC==@MK>!E^v6IH0q}6_@uZYGFJYa> -zhfL=|?ITgcU1(VsG%EOO;6eY&n|K57Md#iFNiHUvJuiven{upfwLcDVFPD+uzk|s) -zLH6FSYnSv?)8(V&65)~dFk#N#$4JTN+7lBjglyjDKZ5CZ9dexkPsg*HoynQsxHX(O -zFHy;3Un)_d19E{~QA&di7m}@RVn+K7jybnv{pCra?B=!4C3{YinqD@ygGaBuy*w}4!m5bx3=c%&V!DW1 -zl7ISoi!2SXCjGk_OEsXDoyLsi9lkBtf(j<|wx#HO3Q^y#(>YOu2~ydQd=1>)YWMf= -zzF6kQGzGu8%%@mQ=ug_sB+33&`!2rhgX(}Txxntt6j+-_yVZ1TsXre9rnX*?pR_xE -zx7QKZk((uS?5^l}7J=ZUiokjd -z_|%>ZsHWpUYI3MA>Rvh0`5=FrNMc~%G+m1D9eGRw=SkO!^pwYy_GrLv(vv%>XQ@hP -zj>hBYr?s+=x@qUw%&Ny%frYv;lcZHhy&nU)20`AE(CxE4Q?^tne4;n4`XulKk7jw| -zr7;SWitK=ZdYA)hah9Y4>KdZw-jEBsH2@re9;dAgec11g$~l1PP*Q^5i964n`!s!b -zNwuGZ8a3r_q>QaRYMVPtID=k>#~1+r_Ls?!Lt||_U+b|{jVkUzYl{u- -zwR0q(@Ef^N4^~VKN6hJGL0SB6$OCkG$VwD+awOvMHP*N+Nn~*PCVn5V4_@9|cBJ7x -zqTixRLUk_WqS78CmWzFFRCS!uZ=!VA#W`JhKn48JrcTAg;(=O^d+AP4ae3YYr@%oST5CASF-0@94k6(aVDy -ziC+6s{5>^q%YC#8aqme+Igj(bCo^aW6Hv(_I!%0>vA)J_QmP>Gf+33>IR=0RW*)Ph -z^k+$H;!DGOXwK26O-p^~dI{bnn!_~eRJUjCg?`83x;}(Fb)>RL^}zK<5ok8A#<)#reFnMq;5jwO`htu+ -zlA!vKQy(Mj4wB|4{Pwn9?}owLgg@(x(&rR{LWyY`+{D|L>{8aW7KIgP(0%*+<>F4j -zRH5WG{C(~nznlJC{2VOJz1x*id0hMR5NDX92T#L!n?BiaG9)C`W^|tZUBi$ki+Jkf -zeyvi2r|vo1Yl)f1&ZU;eF^gA*O5e6G<^pi_m9L^tXB(7Wrmyt6U=}5h;dQE;U0R!w -zIQ$?@a1$4#-~q)ghouqEBBSrI$KzHt7dPPNLFm_GFlW|bQiwgH9*U#iKB}CwX8`x* -zfTvN-IOO-9>2Gyc0dpF_rSvc`&Yw_%0aQ -z&pLtl4?i!tXmjUtPfnn&T4wsEYlsc7XG~U|w+g$R02AZ0BW=70s5o`QbqWrQ@zFdy -z0}AJ<-f#iL1`HvrJz~V~;|B&m9C+ftpHN7*7E*Hn`~= -zk3xQ-Sn@Cy0wJ~H((%>BI!D6OS)co~*EfHLO~XIhx=#|#ZH<9A -z3a7x;MlY@8V0n%6g@xwf)`f&RYee5A^U*}+D-{wK6u%i!w*rrC|5-y2!zFq8aj4Eb -z*$ed5!gmAu$(kh<&tVneO2;ee;nz9N{mrj_w<7up)Wae7URa8_=aQe7b*UaJWF&9! -zJOIufeRS~J(VN!>kF)yIk^Pl%Vjans4XD*}M4aBY7U=GXpj4x$GtK770vbn4d(bBr -zQ`PU|Q!@8TJV{2B0J_PwLr2Od3}q1BkK}BDub)Y=Em1Oln{S44IyNuMw82y{S;zu7 -z-N*Wb?4ih((#t{SOL;I(S5d9qkzS!M96sL<^aM27`!)Dgo-RLbeoB**CgoJSNbFY# -z^fYyH1pv7?o~!u)3^GrI&F3f~r%NVsb&uDjB|K-y*AVY1d8&X0Vh#}p-K2weo7QUQ -z#5XdU(8)md8;vj4f$8&S06jp$zuwwzEvUxg{!BmAYWlMZ#@m?>j31+9PzK~fuy^MX -zkk)hNXB~I^ZeF~Uqc8enzWxoLyzj9^P2=9r$c2jbc*4pW#N?S4DaZ%DDIIaYK5^Mu -zJ(41{$eoBs^(%+S$4B)^pG+kWDN;->&Cf9m#FQ1D$P0<>o~^)!wB|MR`~w7SC!@ER)f2sr#$fCUZ?O( -z(_7KHC$dUEcVmDJqK8yjwAX<3pCfW#v|UoNIVK!V3iRmOTZM?~Z#vw~veg|JJl98E -zzd_z*)=&#g&=X(_aluf{5+<-tAiBr-%FO7HWTydqm7eD&Uj@JX(s-TCOp^}z^Zd%1 -z=Nx}LL{Epl-E|yWKz07rslNTaPowc|-~yrhZBjiae&?>=?T!;)2&ApL-OpkMP<8pU -zjN3XBylj<;hM3ufZZzIEM3(h~w6W>dKYG2V< -zds}awe7^+7+;|@aIEs}1wYop%OD#zWXBSWSr87%M`fCiUdm;P8_LfEPH5y`n%n(5y -zjvfSDoH)jIdEm|sjvCNI;9tqo*0_mMdcOU;l(luwoxx+=F>GhqLsT9&FfSK8{ytG# -z^QNvWP@8-`vnm{hd`r?5W`*ue_#OkbDyutpO_*fn=2SmW0+owB*3xH=Cqs!G;-@P7 -zbB+Q_lKCvp$0PiTorD|b<#VVrdG8SZ?W;IAU9qSkb>0X5rqPq$gItF~;3Wt%Nz-a0 -z`;LsCveAkAn|J+gkmN$zP>2>dOvgo%`Z453p6Be9#E|2$&gi+!D4&4=vs*_!HL+TX -zi^|gDlnwMqFaWLU>4_VAvftC+vhMr2=Uo>@#m_}u^ra_Y-5j3tor1LYqA*mhsb6Th -zl}m6x-}JE3z`(*wP-%-svElTHQqOulsm`<~svK0#k%(`?UEzx!(_@G4#pasJm{cnS -zDixK89rs|6h3SY*^5XTQm)ZmQB$a|)J>} -zZe0lZMlZmozbyZ?qh&UggbtA7jK-D*vFSk4m<;ylQq@aV=uI~F7-N{KQawwX;qVVW?#oAV? -zg=ayjp1qmZg>I?p{VcSLZ??!eqY#H(h1d{llkNlPC(cp*o4coodHZp0$9Xuo_bZ~w -zEt0FJ_&&V_LPAdo1%79J$Lz7Zm+oyDcW1wvjgv?J46?Td!c?k)hm1ImZRXZAH9bkO -zrzRGpM-F$E8NsPWGP}Qh-}849Cd9z*TrRtE*VG_xnbVbEc#7=>FNUA)Dm`TL-joUz8VLwT;{~7xHQI-c2Rdi9)q}g=qu=MfEs(cbG&M& -z>SV*3ab2rwQNhuY_AgI+5j~5C~T6;&W;05g#`|55) -z`@0T*SbW`JuKsO9rdkCrqcjpqTvpeok1!TNlNHfEHMhybLJQS<3W4rZ(m%uOciZN8 -zP<1<%_6r4a^}ayESG2EPg3Pf6fVY)SlnOt|Gz!{$e)jy&~#NO0~Af*lRRbXA(K4EvVCifDav+1~O+ab9ZL1)Z5Y>kpvkt|1Lw -znZS>a7MznHindw8wf5w&awvL~QeMS;7gsVdQ&Tw!0o6WJkqs -zN_j)={qnD~HrhqBDja`dmPthhK2fE~!t96PrM$BQc?|Vg+6Mmi|u&&>M_Pfzj_uN3pV*MsZ2xRa@jBie5Jk0ur -zxl_QB#@Vk3J-i>dBwS%UjoA;`$+-)TJ~5TZ|2kS^&Oozybd}ID>(Uk|nHP{i^Kp#Q -z6l(5=Vp|yxiAW2@?8bN*uz$C2-3we>DrfwI%ze9`^cK`6&;qKd=QRpOiFW6Twtj~>zjEw -za}T4_+-MubNyTUS@(=XXGgWg;{z&ROedD*>P%c1)1P@E;pj*_oiP@p@p -z)%~Tu;lp3h$re~=`MD(Lap-!_@VB)h9Q|sjnJBpgsW@-q7;Bar^IWfg{aYL{y%gcfuO}xRDfBjwp2c=)!tlc~Gy)YR!$MmexSL -zoYnvQ;o?bApk(XwIY@VMpF};MIapzj7nGo!miEFrFJ;FnjORznoKdbTtPjvuY4rYi -zfrQ8Yh3Eq+_rb?GkFbwM!pUGQWcaG*;rc=kzc?E`y2q%x^fz6awTvw>UPI^EUz^?_Xg -zS2}XJ0TRcZ`>Y(47IvTFySqWsc={z?GvZqCYfslVIie^lfA9<0@NENI&9! -zyLgEY9>MdFb>Ln&h;l9cA(G|;s(o+%g2K%&#y9&YF6SfS_K5tYBp7~~aN#BxzGQ1> -zueM*NHh>kK<*MRLrseY4)Hc`(M=B!6J++*O=Xxt*|5;lhQSj0)NgY*<6)ewHdc3g{ -zgX-yR5FKHUyqd`4eFX&K{LXE^+fRYVNF{<*o^rXo;aV1V_AJYnQmo=)^+Tf3qY_qW -zL7xN#^`J-yYASosbic6_(ZZc@q2|2oa;zR+>xqb)_Y7fuql)UQC+CynZ&u~2t=G{2Wrr`E{g6#q} -ztwICboRL$fY)&)E06ZG8j<@Kk88%!dJ^>H7tuOmm*Iy1=ZzSbqtm6kPMxquB+vyK}w~3 -zB- -zaL-si5a}lwF!Y$>@J%N>mN4wj -z_X*EXge%nOF4WM#?$_s9$Esd{ijwKadCt8y4Z)z4Gnj_1fOGy?U01!VgyI*6?4k?zIE}KT#W_z)ouN|-C*>`teYIY4`H6G> -z*SP@RpGVFq;i!L)zO^T^)QJ-)_B>v*qug;nKZC`WMD6M5)zg{8HR+&n512c^IWBgP -z{Bx}N^9qWpa-eXsvn{cu!vwFzXTL#{hvi)1(pH^$iWMB~(Mdb|a|C?;ZgEX$in1!) -ztIUbor{f0Ru~TObLK?My$m6mhdT)oNy8)ba=&uFmvZtZEx09DB&kdpCD1CJBCNN-e -z&pGUlh?0wZUo*sFY4(CW3a@d -zOOhzJ$q}{in_+-9zLSzFhn4AWowrO4qzK$JPt5KEh~jczK_5>h3yt`@5a=l?%Zv3j -zb)AD1=}#m#Hr2oP>T~66x9K-U_rgGo&Esfb$AWeTlAz^yDm;9cd(tvDtjAl0wqm9y?h{CPUbICkyD4CPqr!6$o?Jhd>Zq@d -zQ~Kt~d@HbP(GJ6$kF3DwtfA2Ev`ojQqK3{Td`Ulbq9L~M-WorjnH9K0I`C11R@kp> -z;tFqEXNe6z989I+cj+5ZomqY7tX^DpdL$x=c>(_J#XgS@VB^I*4yA(37JxCGM$vGg -zMU92{fMV(6Aa9S&g#$m!8uND>trOb&OH$D=WUmi+Q<*H__8RRVVWFD -z!G_b-(+X2@ixe3}(d2No^;~I%=|LQ*uYIf!|3_O+vBVhP%8x -z%@ErxG^@8YNlJp$_P8+$7I_592^t$?33XS|aHz`_eEf4U1}ap6Zv@HLLzr(MVjBZC!mzLr0`qu@-E!O0iM58M<>vwV6b?9(W+)Buu1tI?2 -z>al>X@jdjI%y*Ye+!iL?4v&5N@xqOJ9-nwjN2+X|+N{rXYl0uUsGcmDQb?weyHozf -z^c7@?go|o*uYE2DHnpj4LPV9Hi)+)}y(Kw1plL7J8DKRJbr$6pB!K|)UQICLu>0N?5;ZG5MH94+%xA{ff -zS-6p;;d?*#LES#;9@c(e0!%|X$u@g{hx~5$^%Lg2Xkb11jVtDOTg|IK4fq&s=xwCL -z{Tu+Uqx1i86s+I$u`Q|lfN01JY)tqOp4MY_pMsB=AKrF9zaqaeg9J}Pck4$ZLiQ*VRav6k(;eXO%Ve{FQM!s+fp!7U%j%U -zT`hp1!<>O@!2aM)FFeMGcZq_xqaTP?q8yzRK_f3G`lowD>5`V;vPUdl4iruKc?jR+J!(Bt77p1q>>SoBEcO&=3x;b)FZm{)HkuB+bT=g3O -zH97Pty0+>43cG%6vJQa?d=*E1#9r!wX~mr=456EezKjg~0Jf{1!fUbmXWa8sw|Q-@ -zz4CKPMDHPjIaJ~PV9+8K6tRNZ+4S4yWjn5L^h~mPc9ivl) -zdTLGBPRRNCxiY6?86X&vA9%f!Z<8tFy3dskj}D2u=;<4~x*5bO=II6T67>xj{?q}L -zOXGx4!iQuqkmVf6J-sw9k8QE9FqAhNPszQMdDTmDGOmk^*-MCqD#zfn8xR|fX_)mh -z*~d?eeU+!`3P{@H;pz`T)rBBy3&!fqD@C15x*wsLyKa1@`>}x_5vU{wSP*VX!P(1c -z+9zBZdsiZlvblRiU!XpkO$&%2inKjMyhBO~kmB(r>6?GgZ@PtZ?Xagml9}#>(gk=4 -zoa*?x?u$DV=eEBznH2~o`O|Oap5NoZhVhk_y(*dT?BqO>Z{U0y&r*sk8QGQC8KuVz -zj=qyI@L8s?p5!W>l65?fVdiqqc56w7jDLfUU~v;En``}Qq>&6-(8+9rmx~^HL4yMl -z%AX8WFLH~Vb2NFP_xjzLO+~&(Cm*}!Y*0g5&5bi4l@~mkV);|Toxm5{B1As-!-q4r -zP8|8($0xG}Z(Vv6oAeX^sIhaW>=qPx7UUFJop%%KhLkK$<8UfL0}|?S)}!@liJrE& -zC#~)wv0Z1Nt$k49l2_a9`usjl+*n4->ky`c=%@9YBa5SC6x_HkEtD;A&3SBTcbe;&Z!1H_@zMoL~)EcxO?1}lK~Rd0fu7H(qp_`%sD`cABmDZK*| -zN)qxt*U=S}BB3pqmwTd$Z^5TsLE<-s@c8t;W3&+IaHnvr-%2+w^nD2umh~O;lt=k+ -z%tOL#2k``)jhZW(ySasf$4}|Dhw)*7MZsw02{RbIL~G|0>^ir3Rs(`Y-(J*)oyQiI -zsUhFaj-ZaXQ2LzR22KH&&rBh&p0`M(mw}9tY{(5TY0{_R-ml~_LHxbHhF|X$Xs)w3 -zssr1FEGcM)A!ocY{e8wc_2_SBlen;(;fkLU)%!@r3TQqi4+1SKZglz1z#aKY87GP_ -z!kqFf;hcN1t+$eYiW4zUQM-{7!loZ>hq5Fo{ir -zDC`zDHlW7AiibBv%68>%6YEIZ&Y`Yx)9b|N6FOqIL4#D>^3Xe9SV=0cvZaxA8pKfF%J<@W|AYX#n -z<#N6^kNOL)uA-mtILHnW42uAqlncNJHC1b0muuNDK%b+=^T?o0dqD9!OqcfKO??M| -zto-(wE>{2?OiixFLvQmV`&|p~rj|#Qzdi(aT)%k`nO=D1dl`yJMu?Ew3tNdl|A9@% -z;kbPlHi4NqX#hpb^|9k~9h|5v6;CuasrgmhAlh_mwLmE>RH4Y3sF$g|VCbRI`x5!r -z*m@oZI(~ZQCjl%{hohTkOngoN8Mms=<=F7iAM#uw`6G5kH& -zjDZjP71?ah`vRcNJ!ina$1hqS28_Jgr$8UM{JO0XM)w<)OOd>YB&ytK@T{nXl%C(PfF`jyq*B*Y0=C1-qkYm_9OlarVlhaSmReu^@ -zz{}rqysNIC*=>zF;oKDW*afyTEZKZI`{kc|ginr!od5;ruNwxnw%24BN`+qT8#uoQ -z(to0Jg8$-?nD#M5c~N$nBq+e`(CM(FKI%hc9r1Z19NwgQwBKa*h62ON-8s&=#vqeN -zRQKP56wR-0l;1cG_92l!%|!fWwj9bAAkxj8kF7CV0?vcJ9Oa+%I1zNLCqqkQ0qyoN -zgADGj;J~FjOZ9oXaf>bs3^U -zVvrH`oAn2w_@4PLC*Aus)3ifl((E#q) -zSUZpE&amrME03H*nwycEmavt|gr8QpuL5D8v(yobo`4pKKgIKY%PEvBpG>8>f149| -zJqY@6Q9qibq4%5n{aP8n<_J-!TWLF%p4Y<36a -zETOI_In0`C{SZ%JNxge&x^A}6jNQll@zG)` -z*Mq2t>gVW0F8l4<7eMAXb|H4XY%b*UYrTJu7{iK0(r2{qDX4#%x86^7<+4L_p_Sn^1v(jxX49so`shY -zZ#QkPy?7Al -za^7yRyvs`t`*^gq9<^m-IB>a+P@G>62fxSeIES$O?7e>O(2h;tzlY}^IZP|%;$}Ld -zEtmY-HP{SG>yyCtxX_a=O_58s*{kOydY!gT`rjIi5nn%2m)5tMwJ|l5M&J6H -z+QiA~vGf`JfZ|o2GD0Yhrlg_a7}20Cvpzp};`cPlzErG~RY%O!$7TUSe2?Bg<@xs0 -zvs%Q%TITraTQS<{)tid`xY8Uj+oB&^UFQZnroVrKfg+78d#Gko1J8Hfd -zd|l@ey^uOMTYG!I)^pfK$+=>MKRcU$_tD!O@H=z}yQ|?deY-B+XYJ_B-(u6JN0W)J -z@Fxu<9}m?fBex~yv0OOJ!nhZ%(?o0EF}FOQRm6Nc9$lA}i{5|iL_DM-KfmR7leY4w -zQJ2gDbc*j~!b}-IZh0a8i;?+5@Hu5D`g!AjcL1Mn0Ck8D@(66a@MoIzlEK2Q7m4`4(3Dq(85!k> -zTP(!52vP?;JG3fAH^t}tA0Ich41ohjh@^^dbTmeTn -z?;|X>BW9z_bYkL&lD0o$^yl4?qR`c`j2DWr*jXh<&RsK}3prXyiBX3uimu#@Xp6vg -z&h{&30rwd5sX>G(Rm@Pf`t1t+TU6tdmzmA3@g^Foj2$&1&6pRXKQ-^a8!iDnXbT<> -zyN`2EYD^+CImm5~{j3}OhMCyt8ao9SIJK9p1mUSfleD(WRnn0(ok}-;yOjJEW;@2) -zIzSgB63%Ty(0qS6TBu3$7T&f$A$vIN0X@VoX5~9roF}`^?mODnihzCfa@$y^DQA7s -z_kcifh1r*QOhygx>&~Fvb3c;*TVCfk0ys>Edbu-M#dRKO+_>JeQIBo0oc{cY4{FxtyjcT$eX&=F*rpwx -z-LhhC6361W6-jy`z3Z%7Tq7Z`uTOg-_rK0kFs*O -zPmx{q&>;44+x1UvFG%?y;n!ZrZ1g9a5Q5NHz%=uQI13RtG_-3~><5c6F~KNGWHdc8@Nca -zsimIwx5x$Do0cYUa0d%)_Zq0hWr@mDk;Y(%*0(ZV5W{6TQ~OCHolEKZfrA$TZoG{y -z-hVQq^YaUTzu3hKAUNi{%W-nZE`2({*7oA^n(_u8zA#tDc%uB&p+6Bka$J9qQ_s=4 -zRwI1l+Z9|C_G0*aDJ{Z>5RXA)uR>A)3@+wyEZ(_wtS`n%qIXA5_Rnwp{m6GPz{D)! -zRGsNHjNTJQb}U@M(D22;Q&O}qU_5y4QMdknHVJk~B5AH_+v8W`4yu1fq~|lUxwQ|` -zKPY$oR7N$_JI4Bnei@x@K(~QAV}eor&9vq3ul(KiM4JrBpuJKYRmpwsUE6CN$6tQO -z+jQ|he2TYo>V*N$zh4qFVl-l!zAn-A2P<`K_1>9066}_IeBl!h*=!Dja_o1sRskN; -z@nfWkmn@}Mr6Ow{_4xIjzn>C)?^bE~={bH{(zIIV?c*mFRe1rxwr;{GXZyCgPn(5bzcQuLGO`PeUeTZYKdLcj2u2?j_j+(0pTc -z^Zwk?->;87wvf2-lGLFyP5f?a+OXSY1hwyxzE7|63y*hiPxp6|5B-S&6p3&GEzAy} -zbDej=DyN!WR=F*Mhl+{LhVQsA1fkV|6DkT1kmTGW1`7lt0;43ulRrC_@9zgoxeH8F -zpGRSqvi2b^bt_BLIA@M9_aTEv)Y>0XX~&o@QAz$A%gNYXdfERh_N_vUU=P&A%QJld -zap!t?C0z@wds#mV2`TQleVT;0$N?Y4jYF=^O>?7vjRxG`Z=89%c6=8;$rY^8j{AB2 -zHV#i|3BV1Ddt=H)`Eh}7(1V6^Gn)R)GWR;jH%9w7-c8gAV>Qc!8oN$C?Gt@Pki7+Z -zv8C5-2AHQ0MnW*OT!$nOJ8=#(Ubo4g-)p~}qn5=r$_jyw*Lm^yDw2l4*ExF+K?!0l -zEUbwM2dm7vhCKZVG5-B(#BFFjy+@-k_$B8H55QHhA7a<{eV?U=ZpXVP7+b6}dzz4D -z{8kItyLk7-xX1=;HT|iOasR_hD%_BM`A>8z?+%&dj$e`EjG;_MyYv#yRNPOKa=N++ -z(M$5q&@lb^%}o$^AIL+`tgWvGotKaD2>{Sx&CjFZR&iJ8r!1VVH`*spCYBCLdKzt= -zF}R-M)oAqV4&(2)S68gPNnLw#!}KNrIMwI0O#`BG0*p=@zI+dME~|j+)Vm4siB;Ls -ze^H^;(~rfk>b%Tkd;{`RuMv^2m4z;c$lkAV!k%0a_Q`~HnwOP6s`S$ST`k1VlvP$X -z5P#(({QX*MCug$y4z7h0Lle2XK)E8sh-h_PnmG5=VEPN_StoSW2TwQ>iFQ!_8N_PMo)_kD?UG!qU61x+{1~17PiJeKR&}Nk;DyqoXL`QE}!MZ%*le3v~hhv*BIDTw+dc!%@EPKv*ByqZ5y9fgn#a3$Ic6^2V(X7us2J@a3%@8ydSduDENcovZy)#*$)==t$47N}^qMIo!}lr~+w@4?BE0DHS#;v;lqB9{oBW*WZb&{Dg1oV=bl%_ -zbHCPrLfl5=URNm_NHr)s$DAiy?;x$qe2>ladBntwUH*vr`~8G%2bV@>#VmfkTH^25 -zb5O!iy)T{lrK^1YwNW0%w+-*d`KJxP%0Odm)D*nF`6-;#+ULivS5PQD*E#b2eV%{f -zpMa}7Tiut=s@$r<<%Q3}Ob4nbOPx!eYT*ok-KaBR%TYN25R-OT4p(xpHlVUrPk5~)<-BJi~3O^^BM-Z -z_a{4_=D-3R+MY1if^(@ndo>hu`xy$T6) -zdT;hG%#Xic=yP0*a`Ye_lY@%oMRqe7bj*FrAmf8gT+*snUHK&p$grGMv+CsfXlnTj -zQ7aJB?CaWpJ7fecHUuEJfzvjBgws&j3u5o`L5o?1>L7mlZk=CFTntvoy -zpigtMSBTNizPjJ&aDe;fH_TKaXXR6Th(y)?XJ45hJt+bC0>Psoa}V7$Z&Z`{Oy3V< -zsj6{=kN91?ut1^vclEHrcfK2kSxtuhLf~4Zpx9BD+jL?*_-Gex(7-m?2^rf*|9Jyn -zph$g0e}-5JguZHA|6Glq5!2&>=MXAjHme=r@$C?)^P(?4tSFeO66uS!IJ7!@uUFC| -zOSBpELED?14`_^|!@1W@7|Qs~S0b#L_2d4ZS%neGbeJva|n -zXWt%3{O5ZDI6JB>e!_KZb$|fm -z49I@!&?xK&TypHZ&-NF9XF>?pGXXqtx_7n>R1cKhzRTCr?oVb-ziShxix>Y0QM`eYa>F`uaRDO=>7Ab)&FR)!rZxMVgWc26lg1E#!qW4EYfGzdFmGnVBJQ5&dOo?l`j(G97&n?1BBd -z&M(B};5@mdxTuoWFV;0S#WmDG^xoK-%@osCk6=dOYYANwiUM!%~v -z`uHNuxj7J8@yMN-h^$?Vp_xU$3X63mxK?ZCa8?+Cz!B-Xb3qgF^e5AOP~Cf_l?={I -zf1~9^k?xCfNdC;)3H|QjVXbPtCYo?_&v_UZ*0dinIvWxl9ZQ)It$y~%R3swR+qnFPkB{qyNO6?k5h(i#6bkVe02MWrtu -zJHZn49-_E@^?Tyyq$JV8&(m^`n?+p4zE07dou2|&ou+#%;j}xuUEEV=k0OcDIWK_v -z>Tx$cE4lp8UD)5NRMs$(!(_Y#4|*XkK(L+29P@mz>K$UP1cHH<&jDO^E*IXFPgmVk;fabL%n^PuUupA>afRk?+Z%@ -z+l>|?DK4H%Hy*XKMzJn_#C)WY+?o*;9*{f*O@F^j(ZvivYRpO=q7$E&>@A({42;3- -zUU(Rm4;Og#T#{&&xOw{MMGvNdK8{qLZQI{#}n6zY-4_#>y~)O6P8U@2zGf -z*(#3`dt-xI_(P1d7y$?+F!(?%-G?TZlDc|WJ@8TbGn=!_?_d^G(joLV -z9^J#6;#mfb{(dT!b77_^e8TTP*Xm~+-=a%1d9}a-;3c9@wvO9UE$ncbbw1X6gYGoX -ztuv*lpE&6ymbNo#JOGcg1g<@Jn|`FRKwYSkmPaM87pQQ5cNTI`|DGz13(4HmwqK>^ -zCOB@8AG#+j-^3YWi|Y`yvhC -z+lWWo?&uv-Gh_FRzxzlDa#&R3@Jv6xcELrw#ZKmeaU#^>)$ -z-t(X!re3At9MXUF=wIvgAL?qdzVA})t$5*A(bI`qW*0knGJ|!ry$IOtMa&_zvsf=k -zsXsDF)(3cZeoaxqkB~$Jt@o -zbiR3OOv9<(tw&N|-%siMUO3oIT~t>%HRhYpt_t&_lZ-&95x?G7`FABQvP@O5VxYn; -z+ltd}J$ghh_gs@T9TzxoErxo;qMUnq@Oq&f1J%~N$=hXeg`zKl -z`*k;%bJR?0&RSQ~r-usakOfY0){fjG4|!nvHK?2T5Nhc4nsW@myYYyOqgqr~@d>xE -zJNGD>os&}CIlSZY0I&4l{V{YMtT%JeUX_#}Fxm$yB~- -zu^xm^*`?rJ({pep8;-{PIr07<>Vq@wmGK$loEM*_n2)LA`)(%H3IH8x79Wx1PX;(k -z$PUz8ejh^*fm~@;P7B%mx*2dA{87B_d4F?`0zY(Q`_XBNnF}{;>)VKc`NfinmXq;T$7&#p5AhBazY+BMN9a -z_PKzpKFE0(ZSZ2}OF%-DYI&Qi2jW=#iT=d{Gf|fBr0^*jyL3Ab3p*>u8bCmBrytvQ -z282hc@#;(E{Fq~(ZqGit?}+x{GbB5%Kat1p8swRcE1$Uvf@oJ%q{++D(*k#eU)D}L -z8~%a}2@mt5yK;~6=YSQ%U$yCzBF?#-=kYdtfA@Vfh96sgNkRtvc%A$HbW=iNNcn!o -zEP9k&{+<-*i@tXQL^&W1!rYayU~HMYsC^8o^P%ahiBZ|Dm0Q}#2H9gTlvsoZo)ZH% -z^%BD+KEF<${0HUQ+;+r$ -zK{adQ@Fkq=bFj82##F0KE#-o1FS?s;Fl?mLdRotFc@*1ym!;a-Kx0!Il3sMvLjzv-0pngI -zU9zT-mh;b;9~U0#foA8)DEwPMM}cx=?>f?)lx^`rzwI7XZv4<5@Q?)v>Xp0xPynC% -zDf^HbX8NK+shq-joM@sq`}9xIc==r!6@tT4VS)@?_l(wN#EFw;#}5ezEh@G6yA%E5 -zZ$xB)fv-myCEssGFVBv?3|h>Ta;y%N`Js9s-yVvS__~p)#HI!>O>vO#cD~b+Eph!u -zod2TRJO~m%Noe&U7Q17BpG0Ez#hr5+z|X^b;CnU6PwMq#$qeri@^`V_Eakz4gC+t4 -zg+FJ*<##Q$Ntkl3+1rv-fVzF|yH1a(RBbQd>_1 -z>sH{WRJ#b*1*Ym9SXp?i{N=1^iR2`58(1m3B^4uEKt`Ncf7`LB>LWEm(%0-d=;xHe -zOA!xdhEP0KgGbz{TDbIu-kwLI89-|&)jQ^&9^a^cuHtZ^q|` -zYtO>wIY_Xa55Cr0Jju?>keD6KEY*MFXRc{XMKQM9Ej_tI&=R|CFFTl1GJGBQQI&DL -z*f~+=;$!cTlo5G`!J$p&z7=q3x$_?+gns4}Q;5?VyeNeo&|AYA)fQ=FT36}oDv&Hd -zoov}9VM``0=-S8^H6KG{TjW`IpFxqMUk~vL+m+QEF-T5n4w$fGJU7Oxx%Rk&sRaTg -z(*s2kd-43Og$8HVBh%U~p@atjL%@Oaj5uNzdj~?=3IF%~|j=wtKO1a7q*T0Hf*Qlo5M@ZyRSfk&@If}i2Vz3Oumu~kQ}Xn}q#;67du -z9@H@SV3NyKLFP6?725A!KP$#?@t&Y#Z}ahm_Q=57Zj6)fa^x}7`JHioSCIwD_Ff-N=$CTzlqwSq -zgUB2M^=zLAg4DQ5Lw6q(|HB -zR!m$rVQ$X_`|JRR39f$qmj~vU5wlZ%<1Z5Da(QrZ$~xu=biTLCR0%bQKl$a#$A4=y -zQk2y3VS>UF6Y=-t!uAd=?Q&2e9&7OO=`sIb?ySfhpi|(SH9Z=SaPbS3;?L%UQ4KaGZSz@^E?Xnm@GGes1HX(zlfl -zdso`p(#y*@)SYC=j(vI0`JkHHa`fm%^uyr1UGFGgHJ)H-@^`(7GXlHx=-f+UR{wOL -zE#bd#f^Cr?5RPEt`*5pywnv;ZFEYvE?d_sgc>!IR4Iib62oSm>xir0(_TX8bnLWBe -zXZdHpul%lUi8Ho^ -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 -zbN;(q^*9Ra>)AY(h&bTYCnxc*Q*-$ -z)uI^TcmU(=--kL&pOJ!b -z9^_HL()O{mS?LQ0!_xVh8{Z4!4lX8LbP@2IHpeQ^!k_Q{x0_4|SC%04Js-O&nYa{+ -z4)Dk!DRGV|xqz04?8E6!qI8J+ve2#MBs?&C7F7n(4<;GB{Sl8h3CaMl8#lBb!V@6dgc+bddC&up9h5Hy4 -zHCiURr>p<1r!V1A4^`FWCag1aSOn)>MYTYnqiR@X_pnckywc`Co~(Y8VK1jQ5`9+h -zk0;_Q!JJLMx?BBspUgeDUVLLg2}ceNQ67g{naCQ^o7-}_=DoO^MF%$3@BwjHDI663 -z1Z_XL`@HkPAFj`A3i3WKXLtkC_0F5p1WzsUq}{|*M2OsY9FDEV`p@A -zdJN;U{FmDiI38;Ha=1w}B?JHk(k<|XhjdKuXJM0D-q%0PoW3Uq14zzXMY?8%7g`SO -zsqZJhT!q)K3Lt7of?J-K2X>S`R0M^=wpIPX4FAhHl@#(&D -ze1JFT^Ctj)!SOlZ&Y>fIrp@_Ac*g0$PHx@nJdD$hP0esWahY9xxJIo`O(lSQeh~3e -zmx={?AE!0LIR_z-sN1Vxapg4c89c?OmpKfsEHqd=j$`vygQLg96kY-;lwvmVSl5RD -zwQ!^N@4j3X%>fMXMYm4sjkV;-9XEeOFCL`~rV8Msi7karKMlr@Qaww)~W`8 -zSb@(e`gahC>*_Bu?R$YR7POpoU#`0>;PTi8j0?LImAlyH!IDi~?!HO)r0qS&0aVAv -z!{Sc1;^Y2jY~6J>`4P^1brWO-^l#SNq&3+ryqNRAXuv=Vy>t?xs)(g(2avn6lX&Po -zx1RlcA0kfWnMb}o%wPj(fW7 -z?yGS^X)TKfZKULd=#j0okyKcguUB(3tB+i1DoD6=Ea+g!IYj-pNZU={~Qn -z+SrXpE$(+u9O0uEK6${0=fqEpN?HO3hTe%IdH3GgQn6~kq4hQ6{+f@C-yK4=H%p99 -z=-BmA16g{H?nRC51XaX)E?4eZe?b0i&1;AEb0!$gPgj0tjxf-9w0WJx1$MdRA;7SZ -ztUKr2b711mCxot4ReDl4U1m{gKUul!L%>NMq9C!PhaTcpoLjIe)nM74C~@3J`jFWY -z89kOL_sU91?%yY#;L^7I6&?m0m -zQkIADT!2$QrM#cYLh&D}@+*$~58TA4E1N4(FAKD>lR}3KR`MyoQ4(2SpIIDspR~hz -z_A+32@!Jgr1qR;@;=kSvy%*!tfljzg<#}Tb6ED8)Mip=U{pCH2 -zAUcH~OF5Vb(xnL$m4>S;t~M?y!V%cV=bnze{(;~~)6bU{`{k;9%LM)4C*HC|8l>F6 -z^)-4J>d39HJ%|UC@fyB0vR0G_(LPaE&s>OmMBFUloKtd8pd9CDOB1u!m26h}hi6uP -z-j&Diz9rh17~))UxxAxSue(ZBE|J41eZeyI39lq7t3Oe1{# -zFhm~$$wWn&Vg|9P2&Bh`x|o#sRZ-!;^(YFNnHWIAK05%>LAY{it%?DtnU%Pi*P|mU -z1c@HSF};`E8OViBEG^%}C;VS{27j{wnWGe2dS?Q>vMdax>e)E`y(8{tCa -zlzy|nI$NE#=bs#$0U%1G*tT~km1&!S9ciiVR*Ol^;#HnN8F;i%xX+zLETLcBeet_D -zifJQ~u0!s^0w7r=@i*;=3pj_9xiB38jWizbk$^sM4-#zo0g2BY$%9j}Lt;7&dx`KR -zra)!lb%`Mx^WgJ!_ZYo=?R_5l%G=w0h>AUvK#JmV*l}?c%F3=0_v))%{i--TfH_KZ -z;}g43N0RTbxgyg`{Q@9AE${EQ6H -zZFaQY=OgBcHQMAQJa-|5KB)-*b>9&3AMV~!{F22h0-fu7oX+){Vlul2%b0s<3k@E( -znAW-XJl=UZZh6un=sq>q7m_w9a!$&FO{g-2k@NKhq6x`a8f1UOO79HNQlB}=B|Hjy -zlI>&J7I<1T~1oj*%2aK8YM8>C|(inHeBC^3JWF*7v`4 -zb#Ya=%(_q>oHq-@RGu3vbGS+KbdI)NtphM8W(xxWf;BKF6GCda@;jdh$S`GcJu)Js -z_iV6Uo40m6)!(%IsvKrSw{*Ob)9;B}E(upVi58&v6;?abjdbYh2Kv@*ZNXl(&3$=y -z;)?Ay*WEx^)W~aIXO?~N*j)ZBpZ`2HB$S44RqMFtLyfBNUT|dy@>vBRl+J5R7W&HM -z&CiEjL>00k3$M!Y4-DP2=}~JVc<;}Z`Q5Qades{}HS!ammdI$@#Z? -z<=^v0GvUG|tPn}mHk8I~+y|u3K8Rjkd`Zv!Y~eN!kcZ=Ljkfp6qed>Jf$h8Ubv;_o -zCw3FIIMIYkP~ZJzjm&zG+-o@7daFT|I7^Fg4~65I4H$foXKr~UIui8v9gfKS?eY&x -zmX+f|BB@GfMpQPuaHuZD)#H^LDiv{k^L_&zcpoN&Pjlq4tt<=|B3})gef&!1{^TjY -zd%RRI_15Xn;=@|K6%f^A6@s@!v##7eAa;oN@q9BU0mU1aY%PQJoUBKuCEm`~kXieJoo#F-9bYS^IH}uAbh2vbc#r+Ph|TISWhRv{Y~tiRPHp*=)Td -z(-oSXTyWA4*Dc=28}7YbmvSYnDSScfQ% -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 -zy>9jXTVGWS=2cI_j%7c(2C0|Wy( -zCjOnz|6a!54WXM1>!%C7P7+h&Tbu5IGMAHlV)C1gjlQkZ#}ng92V~bZ&AqYtIm6#m -z!h3CwZdvbRLLCo(G~#E;UmK_4EWu~>d!!-D@e|iB{1kEY-gEsk8kyF_-7&rb{37aA -ztAO_wB;BZD&t2->SZ%dtobtV6<9hlcTxYne=#OfCV7F7=X1(!=on8H=ufYKmDY(bS -zR&_q>{y&Aa0*OtidpO&O^I<7D1)s?BrKvGBiu<6ovKMZQnPc2TOKG#PDD(|;4$Z4E=9sTET*tyjvZ`n|Q1#Q?D-()ZC4!HrXON?z5% -zM7$!$;E^(J`ExOs_XrgZO}OQ;_Jc}s7h1DoUq(B!3@?J^GM}6l&d|N5<2$(3?#r69 -z*D;zEjt0IQ;=c*U?@rZjdu5jcDJ@HKjuPajY?lxFS19_9yVcBq_I~Od?-znBSJI2`mIShcLO#rf -z_a-VW!fK%Q=4V{{b2)!Ew|?pkta$GwgChRu#9)4&Y81@5DI4In#d%^Yv`YF^=7n|j -zb|Ia^z&98kC;A#vv*q4;ObbJ-gw8%R#W;58^a0v5@Z&}^@@Ru-a6XcCK6jt;`25Os -zI~9TZp$C7g*6S`>K*%9CE8Q1U`6iWqlVxs`*h18{@)#h@0zTL)_K> -zF?JP -z`}3r96zw5PULx7E%I0@pENvZEBPqvRVo&Bw47G16;9al#Gz$oo7bYq_h8HTbxf%1b -zSmOMyhn*BYv?V7AYBTs{Ngadr+vl=5IMkjt$kU4>24-DviJd(InvI%`Kg^4Sn1b4; -zDeV$ZGERHs&8*Sj$Px8&jd^%TJXUqyE(UoYv-Tbn;bN_v2grGK<5sNN-Wg$e^pJGt -z&Sb_0g3R0f*)Vfs^t}J_#O1qwI->XNfOtlf_+M%KSdLkbGk#9Bvt -zpI{PIR7z?MSj++LR@}a4LJAw=s(Govchz8I-DZ>&O(TFhs+_ebXm&0d_&3mfonJ}@ -z=ZQlwknUu`-?$(~VOaJ*d)oJQ7$nLjkE{;&&eel9GvM6!>4%!l(I-AOTsNGNtHgBQ(x7+OG94j86!n4 -z52sv~3QQdK=nP|V;VWT>L3B$)4afz(uV3rKI-1ai(kIu(4w7c15*|9Z9dVoS=)LP^ -zowB`f`Gw+k1-z -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 -z5LC;73)wsmG9}SXXj1n8O?Jq+bt -zffh-qzqTeS8lbdg6X~bkcE+0^c91z7 -zU5?SCD?Dq%_o67n#A4N*M+~zYNdGyA3l(O&n!o&f30w}@swh6XNaxOO?^|WMsDm9U -zex3xs=0xv(aq=smsmCYbZX#P0ZyNSf<91Y|WUsQo(cS&Kk4ROe^Q>4-F!uKNlDxi8&MKG7X -z$%6cZz2*b#_*#BoR$s^)hd*ANKpY_Q%|N{C=-DpzZ_?{iXTedAu0hu13$8wp;1+ER -z(4GQME)>PNu~MphPTLuZFuT`HigH5sihsvlFGo9?ST!#nxlgdD+b&$Z&i5PplfBaq -z;*%T_wCOW@{?2WmGRtikvm4NzqW(meR`ryS-G`}{FM6NzQfeb{=ux}~_|~~z44>tN -zxHfh#cLv)?C6>*fcVI?)@5OUw=z#+4uMqU9ZR3ufg$`{OjQ~e|>*lvk4Yk(kOm4J9FFk -zI4x5$$fNw{Ngpnz5HU%%c@*$?u%-(Vo#}Bq*FT;@=UCYBj@v2<5-(Kp&grLm6Q)sO -z<@8~gua1eG`=UrdwyyBW|8K_Gqh5i=m*Hs#9J|N++V*CD#?*f{pB-X5?EmWgpdh`K -zzA^o=9hcB7OA$y9{JN -zW2NrCcRKU4R0F$v5znP?!tU<68b=dSU)t3r4fh7MubK8Ub8hqxg6p`3Vs7Na)jAlk -zb=7oR;b?2f(F>0^e~zc>NBkkoBifn$G<2ommQqCBm+s!~U(BYfy7G8=e#Nkh4T -z=a%e*-c;a|h*F9O?o*GN#T87Wl-TYI;CStG4A*^JW;nohv@I{wBN%5gLo{0%ak2U7!&#CMe9EqUnZc%IE9KH{(YHOGl4i0J -z;s_`LrGBcq=dOMB^5tKrjz({~-Wi0K5%=pG`P2T`OrM|- -z#;8^7D%<8mG~Bo14yj0_o7Rd<48Qe(LB_^y40B*)I3h?h;tzBk46PLPx1Rr9z@G<- -zpLQGSif(D;Ueks+Y%ofPC_J?RDxIg!i_NQmN=P}%hb_63ED1HHVcz*-gr)qdC!YO-oNX^16+xf1Oh>%ILuB^6o1|3&o3MjnuzC5OvE>Y)+QY+?E94-QQOpdOk1N)CFl9yh?tM8_dpJs*?uy1eIC1>IM!z`t -z=_5eDn*?&Q@1C%`^&S(O+`R{{EBpGmU( -z4hGV%(zUp3FROJ)woLKWJa5wsC$i>{gdV(eK%kDo{#_5J`a~S0pCz2nA>9h;GYw-q -z3;EE-zoy3~K{Q}Yif=lBJT~0NTM@2F(C&4OD@tkiLH5sU+55Y#fTMyXfZ~wa%`QUo -z{ziwZzrDxbh}+M1%CQroBkm$dGoURVT2U+F19Q$?cpSxbq^&q(t;ko(SGiw~Dz -zD3Kk_;8DRU(QBiR^O|A+Pe8E0x!qQz@=VHebkbbt7!yD|gb(5Bxz3NFU8#GG?QyxP -zeEU}l^K#9)P!plw&T$3Fx8D)>q}HwG064W%$Y(Q-jUv|PP?hIF@v*!sdoA2jZc>46 -zJ=OKSSijF0sorD1qW@RJw@M>Kq`MnPD{wH2kbfLm|j_qgFkCN7>A -z8b&~KuNq(Q`&m}=r31qSFTFU`?DFlm8hM3~+6kf)w2rcS5+?&M_`KMwVE@LiE8^FC -zyPpSz4}OQuvwg&bi%xP;^Es4naUj2*2H42%fVbP3z9MObC-Wg+hJkVc(}%aR(VWy| -zpW{$e2&84 -z*Vfd@G>knyU%XjB1*^8z2M|fdu|=$+md7xx1)WOKWlFt-!B5p{N}`7OP~XEXC%^;das>ELMPnhZ7EX0 -zVHmcKD}9!S$Mmx69xkJUx)1~xf0t$6-|Z3J{!L)6=96zDvEnu~n4KXYhu%~J_tP=j -z-=KLpZ=v1It1}T!>#wf2oicrO?hwJ -z5v)!d#+SibYwRK;e0#f&E%?3IY6QGv94|}ysJx#by@u1cm$ds(;?#kQv9;b)T{Ncp -zB*WgvefvN#G7|JTjzDgx|@_=npwAU3lwSYn}Slh`S2vSv$CC4r;(Fbf_W0 -z=`7cKpX`jE=ZW`sLj}J*Yo<@U`@a4CxshoTtE!6#jD$TDX}58Lrzx7_hS4{*?Q49e -z+YAv#yFLi4q5?v${qVWQN~xr@V#40z3nf| -z=inhft(H|t$zLBj;*`9wb}eTdyWMCp>)?^`kTM-8(Kfe;QWdD$UGQ+6gY>t5^{nJs -ze1d+mE{n0*2x_Bsvv{zDJw+_KHqdD%@$4#Tu#zD189U^~+#7`>8 -zDzo2>HbH7!b5DD$X^4F;7a#NJJ^*tm=b{JTCcT{bRSGtYdb`Ls@ky~7y*}IWJdR%r -znil7w!}v12*kqBM)oNX0LrOfDz`3*>>YsBh -z;@xghXd>Rq1G3zXMSf-PeSuyXgP$uRKb||H>`R2Hl4BkpJjB7`YfoGT&39(h*GZP< -z2mdzOa%WY-(SFFp43AdKNCPp& -zykAq&@>sHp0N&a?PlIpS#@A-5=zPb9qae{yxNOyUlz!_A{*R01#l!fSp%H7D-uLmk -zRY#2+xv5n?Uycn-z8F|UOMUtr?ZaMsmDcbjKbD=jl -z8w$V~phsoo{j9dyihWGiWG^n*u=Bzc9wo)}rxB`z@WIs!uA$Gx?+JRKjE=+C8i9*0 -zMZrr-VM6%%&r-g>wS-TJPuL_OpFgjm-C8M$nO`^n+dh(VF1Pu{)Rj64?m>KK$>;{c -zx!CzY8phsca;s6l=d+o(y;}7+>C=lp!{T?F2hCw(Xw#O-V_HuT_YW^gTVnJh{Q#l!dXfKr?)z^`Rx -z^Q05L|ICBOK5Iq4rtv7L2x1(H;Vb1D*$>%S$i6l{I2iVXtDh8MX^2F{CZW$d{Rr)< -za6LK`d6X>uLLaG^zsJiv_gsg)^n%mG$#F9L2;3;O>Oy0hJHl -zQ-mXD!{zqd?=n@}|A8038$*h$<-2s$N@mQt;1|9b65z9xkn99n=kk$9paM|=9nk=q -z?Q@$Eda;Z;!&eJVzNb_lbK8PpfwdT2IXQcurtZ{B7p1V#qjIM?VipC2R -zJjw+3O2|T-oAKR_p|o?hpyp>P0g4Tn0-dm}^Odo(6%J(J_fIeM_!+xgtA7@+nmw*N -za3M!-BgKrh&bT0=y{A#5^UWjN99-lDRrCcYEIB$UuDqW;`q6H_Fg96V#kl_tj^BQB -zS8irUqjE8HwHu}IQ*Ou8ca7tWo-)vvId3MG)NXYYmb63XlM&)C9q1PT4{nvJ-QzRZX1>XHoJ3`hlL)_c(_)>YD!GimCy?W9kO~0|@ce~2BS0DO>vJ&om -z#Vp(d)y_QCUYoN*`05myQOt_AjtO?2iR}es|PKHixDYJ-J{n+?CH1#bE12Wgxz%!_D-1>iD!0 -zy`*Iq8gG_zf}}l>*WWJ`zPI^6tkiu1!H}Y8ApdS~K{#JUZk$@badDq!-pW*@UB9;a -zc}zpll6w^2j>pvB%9D=_x_TWcQ#O%$V%~0rF7{9H%D)?2B;lBz2ck=2qZiMfET~%k -zZ0C<%vMX8EPb-(_YWr8YbM49ZT%#A6_txETx&*Px)yEu3oRWvN$XhpK?SPTIJ=d#^(0PD{_{`VWf?F4uHwi!e}8A967~@vO+vbLHeAW;18L -zVV{9vEz{=#ysV^ON&B6N6G_W7-QX&9jsNzi{XDOT?NZ-m8`X-On<0XEH?oe>dzOuL -z#+hk_eGI83+;&9&H5E#nCt-_o`nD$={aruFzguF;`6;5S=Vsp=(lQI`IAAy(@45Q$ -zE&2w$eP;+&?fi|)W4~9P=nC{z2RbcN5x%0_2hSNN_8dbI5A}LlKdjBW$qGy5bT>>v -zjgKq4Uc&J>IWZtu-FhCtZ(q6Rc#e;FpT|#iTWetOfIKOj5V=DsdQTTS0X<#g*lIby0|VEg5}bL*S?^C%MN -z^+nhqUZ#M8>^OU%PaFt9kIZDq-&%%$x81PW_)Q1Ck%h;+S3E6)F5Q!=)y-(5CNSKy -zFBCnWc)E^PWk@lmP;IA#v`h9 -z*>XxTVaUrD>);`^oya>Xe;4gbQrU?hw=z2(TX)g0H*4_jJ&uV?P$(K|q}0gtO&IK| -zyI(0QqqETV#UR?o%Ey=Z_fTX0k47DH_R#rk{!CvAw?iZszDlM+Cs)Nq=+vUa3Xei- -zF>7H+f4;lcj4-p*b^VCroWb){k3sb03T0kAlnmy&0l>&IeNVDDtlBaf^CLe;EbeDB -zRD&Ium!&myv_9X##mzJ0kowY(>A`U!J?uu?pmI;l{iflT5&~`1i8*KEtd;u1gEE{* -zyc*rfGALyC>UazI$bl570eh(`VscLh)f4BZwcpBYL+o5hddP8ZC{9d%Q&0N#J|!nT -z`-sJNrjo>J52PM|yF#A7?`T7E`C8=hU4fQ(*uNpTU7qYnYL}Ee_AzZmqG{5bwF&`8 -z4~pw8>=T5DZSCK#W(ee;E&2Q(tv!i>bocUi9l|DL&T;uPnFonSqEzvLCZ$|$OzgE-uH{A+%@Z9S1S@W;>zALln>M-o^{9EOGCXU3y -zpLJgu+Fw6{_`PLy^iU$9*#QA*VCXOeJU6mvu6!f6`QY$vn#Y2Ks#-!G14gN7!H-hO -zemDEd?`ELJn-jfoBC)yau31{K2$$fzt+7Us<^}iBP{^8!jy*a4?4Dp5za?UQ-rga? -zWfEzFRXYCk=@shkd!V|9m0?Er{nvvN0^wCHCBXGHL796=$sO -z1czO%J_J#6u0`^NyHy!JJq>YE8jxq8h!^rHI&$+|LiDUUzlU7GBm&=Nj+I}L4*CavGvsrO?ISHifL-wBBGBn18pjBv%|Uh -z&;Aj%3UPcI89VP|8qLvCU1R*FTqD6@Bh^5!J{wehW{NF|w01!2IPAF&(d?uC&0<_1 -z`Pn}r|B=n{-E(J&$5TZDc;{q{?tGEwJ%mR`BF}f6M@_`5w040I?i7g-;Jsk8r~A(J -zJe&imh?ILnFJ#>D8Z5S_A-)l3wU6AJjlU$*l}sZP`kISup46bx`(?{c-G75?5mtPY -zGd%&A(9VM$-Dd^fqPcgOL42MId}8KS4x?T7w{+@G0G2NRSt1;FGwz%sbk78dF6VKP -zKp{Hl^&Qwu!^j>y=WBgmhHlZ~!_aO`no7fXc3^`Q2oJOt)K%9reZJn1Ndky-E(q&; -zt3es|XR`q(8GC}`?dSRvP3{+sYsJW=a{9cNbxwlND1x{3Sq_KsuE750@! -zwSA|nZGJBp`#lHQ97oPTv!Edzgs)PcB*_CPZfYo@<~d)W@v}6&;e3lf3mlc1-vP;> -z7%$P=eWk~ZbpjdXWM9&xhCNA^oGrOt>R4h1_ZT8j&_rfTkBs7%*f%#UPwjE7{bKRe -zk~eI1N$R^8$~8mIJ!}EkZ_7Qtz<;xM9&OTBmKZvTt+wZ@c}#woq{b1E@dbgz?QQJ6 -z8z_QEjH5@U&zP>8(l;L~@B51}jFb6ie)ae+)JPJ@3 -zk3IBZa>E?Tr)#k_5Us^a=jLUnu)B7jad@)**w?P&(WrdkK`qNUA%$jC)HkZ^&c%D~ -z)p;9gJPDAGWlieE?9p?uC`1%&Wa_EtQ{5F| -zJhg}PP!+f%$u|M^Pb013R|Rla4QGqWTU=4StSV-n;B9}P9ycVX1@WsJ?|)~H7OZ<} -zVj*ry>N#(pv@BNVZ({o0)T9s$xjF0SJQ|E>J$q9hj;o?;@nkcdd#!fr=`8oC$}0%> -zX@y;sTaZVI?zOiH^SxxR?e>n<=mSh--Co?thzvv_b&g~s?miDouB4Ueg5G;*>k2=Xk}tyS7|^|q=U*MuRi>q)yrO3qfG)-bJr@a? -zG2`1cv^gHz@qA${#wh9`>%U{;j7&2uXwvL`i{t}$gz>FdG0|@xIMp!rQ+bpvUvlA4 -z6UXR4eRroAnr(eV;8Y|d|89Gb-)&IJBzKs7IoB@pswVPsU#+~^Uih`ei{67RX~++R -zPF|^d#iU}-uw$~x@c<0sKIb;mb@3-q-v2|(H6Qu}vS@YG9k8Z7-?8W%fD6#~WPj%| -z%VxcHgIQs|+6K62XP6Bf!0mqHCk=|JwJ*ohGaHHy%Kpt&OL~Z0MrwA}?0kPD7J5MO -z+#sGjrG}<+CO~H`ZDx;lnE;%k_w5%$AZKnoP4*NPsw@%St8c%!5r1K7adDpXzD7Yl -zLxq{q~m#q9~*s -zObFiJ@kJf&bIY-kc{o`CPJiXa8Q;0<&qC9Bn$G{T*y^6m+oB2(~26C#?Ryr?hU?C)aSeUN@lk&SN--$EoZo6 -z;bY7C)w}FXql&2Yn9Yl5xwWgqoU_+SC%elW?HYONpCigS%Con96}17y&A~GGZS42r -zR?G0vDk602c78L!XKqCuz_8R~LB?}0**6ETx4Gvzz59FV*zb{va&wiSc#T|41h<06sQ@6;?vo+%5V_*yVrw-pg+A2WWLuPZsL{C2;x<1C>;7)e%8SJ7 -zMdR3Q0H6#F59A)qG8kgZd&t5!TsbSznwT%2jF4(^pjhJ;o01Gv0&JOreVe>Nz$=rs -zX?Gp4b1pVH$A&O?cTUQpg{cwN -zrh?0N5&jL?JzvRj#(A6E^K>10;MCzlrG7*&?tH^NzxJPCl97{qI8+bqjYFcOjG{qY -zZAT7$V~_*$(6MuCb}*YpVYg6%aI_vgAN1A*V7kY-5zW7AH`gq+2%)$6&)4eSYlSm^ -zUQ2qZdb{Cz>eC9lb}i>^PTlZcJv|~|h=*VCm&2t{<%*#TL=o3rA++h#2@D -z{!LrI+qvpHJWH?hCH1M}zKvvKnQ~0vp8G!^lT#F5D5)Jn>IWIPLA1|$KUqV<_Rz~> -zZrRk`C^{^4=RpeIjkAKqc<;tHVd&^Fu|54IxkE9y>0W*)z^1Y6)l%e+H6}K3;;W{< -zaV3Zu*{?W}D@7fCX2yra@j`0#bn)5agAk5>P)(i*c)nsFiTwd)*Y15TS|CZaFSv;N -zp$0dujtc;GJRNW3HNV&Cf#5;+q&jD{O9UWL(vBD(7(%Yc=LG;+{M0PX?Y2|yv_=Fg -zbsKXypWXor3<&LW7zRhvsjeb$>U2F}u(1Mse1J9Q}Sb&X)$LH2fAsj-!-W;O@wAPe=eU(%_qC -z4}@1zJqQjTD!Cj-9|F~lMt{qLfbIjR9SqyLZ>QHmlX7KWk;cbY# -zcD^WJcPl!02`?YF!HsRgjLa`R*|{9etnPWb+}q*P7G%@*bvE7hd+=!X)Hmry5qJ@@}yep8{2wjo0W0fxk>R2^Ded4QZI -z5Ngg;x^%ZlL2lQcj86ZG(KR>xdO^g`CG@*xZ01Xi?+xy_2NkyA>e0RaKGGWP1$|iIz8i)`sl6# -z$37KngGav^7IR0I7|BC|5ec`kFVU@|=dE^9Fj!zLMPmG{SBgL-$AP%rdBf&Q9XyE- -zPzXx?jahsiO_QCozry>FXFB6;JVJ5EJ;iXp$wDo*4mVE2pT=Erq#IPEo=rRt#bWyI -zKYzlzM(gWSgEVkdYV>r;??v=`kk#d-;i$)6jMi6n -z>SRfOCkNdu249fNP(tss#s06f5pGYcoW2>4+it~osJteJo*1|4IZ0mS9Krkr+v=RK -zp_TA22=WQ;#%t!AU#mJez2&%K`$ID$!tmQq=QI`(X@jHo4+|+e2y;4I}ojpBe@VB10$mtf<0!HAXmGObk#HpdYeOsc -z3)HNfnd2HoH6-x)B&xJ@3Q-fRFNScqqQXsOtYM^&1Dmqv* -z({7GF*h0-5QQPI`A(=br!hACit^yv1(fd_LpS!RITo$}XQ74K=dwfsrQf7(7qanQo -z4aejHow(Hq(Z~L7dOZk}g(CNPi=z{JA!LUJ4UweeON|-YJs5i$I49EMJfpUI=?t~1 -z+Irju0xpbNy5d3gb0PglUeR$kmw#P8j9lMk?Me+nxJ#z`nR6jwNJA3a`Rq8LVsO;i -zdz<}OYc#1YH;8cMa>=1SxF2b#_g&5h1zqWhD%OMQpA2q&u1E+8hT86D7k3zXwk-$-Ty~@vFsJ!>+Tu-o~>%}alo*?T)1IJSD!vK -zLAuD0E6qunN$r>Ww4vPf{km(K9zhx-g#ErUz4{*#`^)z_=AL?j7Bcy -zTpo4AG=iV=Tr=Q3J1IuDijyMW{}~?-QKLa^ardQj_)Ln=64cu^k%hPQbasO4Jp`=f -z=H_eG$P)`E^x(-{< -zk8^P1xI@{kR4UH?0(p-Vl2zQBCj*RGh2c4K)86g~YO+}73Y*Mn<^DP6?f!0-`>Gx- -zdOXRX)OeoYPQ5f9aX|Jm0m0Qte3s6sSNi$8l{f>C`gJTCSnuI|Z|=Nrkwf2H$K25rZF*ovS<83;R -z3ZMB(@!+Z=lQ;y=F4TKs=#cOr9^>EPA0r|T!k#CH*h&59^Z6mC3(S*byX6ok)TZWb -zi^-Nt6}WMQN(v74_FeGERDtrVSI{g>20)EX;lT?Q%EhDgb!C=aP53gW?3C -z>+K*(&GPpt_%}BFZm)|$@udx-iw^KeBCEzKvs?Sv$h7xGAr_b7@_qUYPIxBaQW9Y0 -zHV4y}h{DxUZtPX}h);#XoKT-<0y7FUzbG!<;B)l`_Pr(w1LT)XQ?ec=jD3!M`Ux#` -zEQz0qu$LcP;dpGq4t$q_JpI9)-mj@;>uV&w!H-(G -z0GDWiOm+RJa*lm9M%*og1z#OY5O*E6I1BUVd6MThPRzP$4nNu_0yiRTiubDQV2snb -zqeoRDhPd&)L81Pp)?adv+P)zCq#U1QVSump_~(N9-H=CV<65#?r*AN9Xpe5qmcvrw -zDQ6gsWE46$$7ime-Y9iX05A8h?o_a?d79Enie%=b-LJ=Xy0{pU`|X|Qbv&}$zovO_ -z#LxDDu-}~T6`tBB#Pm?4<{X6y3UVY&f7-+ -zj{aa)yxKb#-*$wDfcgbfv8cMlf$KKTKetL8>akCii+_2~wW5wO$wkbY0|`!|LJ1Nra)fV|PNmyhqyD-!+P -z!beOzMVJU5QtwPbKl|-G2CEs~73i~|vN{Rx^`CeO{Ki+2-FP1zqX(LwZ{oy$^9t*U -z07H>yy5_mBtaJJxo80-Tr%1V|-~s$w^>C^V`c>a6fpYJb65i!1%70NUo6PJRH#YDF -zb)L7S@XW4|*VS4yz6N%#kcfHdGZ;#_Tf>C;);IeZz0`ix}$47wR!Gi?z9?A#X -zErK_&u4z*;&YsO&ulkoe{O3VI!IR=NIw39y+?)jg)|F)f{46wd+tg2W{vFwQ>OeEU8hhsvd%A$-r1nabihu6`ok<%Zi= -zX>sp2{V_#g#s!W*Z(hfV%9fTJgPg8#ujQa}nfFuK!4xBBk&w?NFEif0C+G|Jt*4n5 -z_Hcal=~;Pn4lXO{M&47Z6J%N6BU#4%H*2Vnc5)Qu%&g3^hZ`^Y)l&2@I$51>9s>A5$78Tg+1+WbjAV@mTS -zDD_u)cvb!6F`j$$PZ3j{Dbb_PADTNu1=ke`UymKAu2$Z|??*BhYS; -zjEU-MLD;REe0PvKZBBK2*JgZkJD>P~(6B*~HC)BhHokNDE&ZlGrwlQhe2svK@|^E{ -z%m)38naM=T$S6ua#>+p2Ar%tj&3>i42^06$8^OZo|a` -z=eRsvMhfK$h?2kO=TuDc+VSu&qK5IVR-)=Om%AQJ6O0sZIj-Nhq1)%}{JC(J2_aGL -z;q}(s(A_wAz -zDsCDURd_b#dxb8Tkl#K0kvPtijbL=m4DOE116$N>9ty?=DD$zc<)G)Qrt=vz5gTf` -z4|?DvwY^_pclv1R1)^un2|K<}>3@Bz6A_wESd<;eeC9a?Z}(-Gn36c!Alq93OOg~q -zcoLYHTryL$5PbllrB6+-;YgylzqUv;b;%WXR2 -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 -zK?(R}(&?E#{%evrTNqc-L4?F()X -z;JRb2^~;T9QeH59U-MW$OaY)LF;}h#U3m)hL;EkXntM^>oHOq!lzK@dBEEH~XTM0H -zJ6Kg((?Uvj%kGmOJ~cTv*TBx$-|@ar@JwvOob}RW9)np}=@hmL;W~@;HH_-%Ll1sj6aOx|*P;B`wm>#-eqU{h*pP{ZG -zv!i|KS%>CLI*&mFfb%5HxnLN!3s!ymB-q+$>i8Evh0|YR9X8-GIj7EA?#hktBG9k% -zIW&xFrP;CC6VUizZ1Fwx7KfqHN`HYO;;nk;YqL}}Wv3JMWWyh5T -z{T{`^@f)BhKHK9H?YG&u^Pk3rask)+3jZ<6sH(lz{xVZyL`Y=B9FX-_{(#RYmFlCC -zU(R9r=NRfNnk#Wmt@y>vjJ|ixNpjf^6?_?;NAB$td@dh=>v`!Z^xP&)V=Fv{T5lEb -zo(9j8pu$~haURlC(8F*rI9buXag+t0?hw+6`Z~uc?d!YNYYqb1AkCoh`Ac14(~maq -zlWaZ7)?md@0m{-mxa568qxB9fg?q4h3 -z+SvzcN^y@q{_>ufYQe{}8S!Jk -zM|HLAa9yLBfkm^aL9JKSF&=BZ2Q@*x0Q9P5ai5Xm@sU2Im-Xr3%w~fVMgFP@CW|+b -z;#&&@nQ3O|EckS?NI%(vtw&rQw9*`B)_Hu6dgjUdLx>K*>o>NsD6~xu^?~vO47pd&7d(E=#WW1WQZP-=tm)iBXTuVa-F7%S71OZY99FSqHa -z!x7pkCf4xE&{EL~_UqVA6{&CkGfZ9@55HjmsHCTc{Q)GnmzngJ_(PRJZN9vvF}QfD -z8g=EIsi3D?u)(?zui-e>nN3`Y?XvBB{w>cYS+by!*fYp+hC06)#?lxFk!G|={PkrUybn|@9)n+b_OzRc&CPwWbk -z*`7z@QajIy!}3bKbyrm_!(j)%guJVJDy>f+Bx(4XJqS!&G74D%CBb1f#%hWeG39+q -z_NX~gdhLO&+0~D}y#G6w`O>S+0<*vsYUklgq@f&kKixeA7JhAnr~QtN8mEF -zK6XDxc9BuKgsv$v;G>K0Eto}q?vvvo%ln|MMw^wtpo0)eh=oMRHjo7yki#MlZ70gk -zQMLNo46%?rT>!pL;TpfgpmQG#M6J6ErIG&K7G6Y%sC%HuFE?SK9|F2Z)Ew&0oF!)I -zYmK0yV+0se)cUD$giEM0{z}#X?2$`@Z*Tlue!s_o+rA~@vaB*+gcuy=y_>y~;F*h;HG`IEdi*_-`QqDz;kwbU5WsTM>3@+`x`S|7zNW&|lw2== -zf5|KDa+m97@j=(mYT_|-OmcLn-BYH6)r&>>4MxTcc$RH$h}j*%#;cE+9-xQQb>Qp( -zNkF#0X)C!hw_$qhS~PGW=-0Bg(JJ({;7|H{fY_Lt?o)Ep`bzCpBc{haL__J6YCJZa -zcb)gaQwn`E=S;~kj^2bkt$OHx*s`h_4WyifJ$ -zmmCPX=a$A}F8TI#k-@!W -zj?Qjg#NAjQeQst;$x@TZgM3z5gc5$&zuyDIHx8~bSQ6C5QX=xzOm -zoD3E-FV^;@j%B&GXe6tDFTvj<$H%_z(0L4sqmTYenVA?c`m9l4T_1|Ps?s}lDIfEy -z6Z1+lVT})p^1*s5QT~PXb1b~~A(878HSuK*T!p&)4g9H*Y#Qy2`T{v9IdOA8duOcS -zgXi8%ol`Unz?z@C9(CSZTAeN)?t}JSzb=14zhD0676W*DqFd)U;&oOG71W3Vj2zoL -zH%TuY-78Iv4BSUjS#=+yEN`bkg}~k+h9@V&RyLf))B}RKcHBn^CzyGHR5R{)5>+*W -z)m0|Ea!#z{JOaR7cvwGQPd>*dgS_19LjKIUc9BFg(^NZ3s7v -zP);L2>!DXn9vyyUijI8do^`G^F)!W&dMYZ*WPlDwnmt}hr(M2~rG4v!GfBR_D&qXw -z6&}`)3iR-wT6p-2Y$k%>nE?#5pnu?kx)dZ!4As(|wY!WwL-dbYH=O -zZX3_KWPD}1A_nK+1GRZl;34G6`{-PeG(+JR^=t^+Y;s(gvA;2Z35F%&_$SK( -zn79kv-P5a&0Q9UJY#eGkpXd#!db|9{deDuPC+GPZAGP2|bw}EjSH}Zo&r^|&r!ggQRmzKtu8xM$Wngv9+Sc^h5AV%b*9M< -zI|cLp+@C&0@Yrqm!H$qNm@eVt$?#OM6U%jK&3<4{5?j7?+HXLz%fsz;#zUwV9r|M4 -ziP@F)|1g;2zXzdtYwUo><nqSc}tH4J7L~@D7oSGkPbNxiHx;|z}4^e -zGjrj_22-_uki4&YT%O?o?ieh@zOLEMa`_cxvJhQ|IjJ{dtM3|~qYFnwSid590633z -z$X+`AX}VyWLawDE3%NLk1oXgut80b6}S) -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 -z5F& -zLXKo^huzBzyqVArNp%eR1m4T}Mcd91vGsK!)b~#e^FE3NJDA<*_lbftBXm46l8My} -z8aj6orcK$F3SmdtXY;-lSqo#1Y`XKM)AHt1wkE0b3aHD$@+-Xsw^3&^N6SR-9s$Yb -z&u;zN+lm_bY1GH4jVBNK*)Jhw^yvNjsJtvZkVt6p?c^sJ5gwSIu#cj3J<{=jx@%LU -z@%TQ<@YOeQELKc;WXCQAflPffAaQ7a-e3FgQFaM9b|Lnf`70N8k*KGV!Ls2X-{$vU -zBI!w*gA|)f_;uLLqf9iOEcmEzL*Oe&`@{eRbjQ~ZuSbRhz_9LhJ1cPY!6^?s#(HKE -z?QU8=kPbgo+)i`^H5BomE+fW44xJFNmRCdR`VCOzKI(ECE`804$V{&+$FV|}bBOQZ -zbAie4Ia{C$_u!`5D|LD=J*bQ@z5iyqoW;#uCh=V5NlcpMTZae^g7zfwqn$R~?V+`< -zV~>5@d3%(S#1F1rqF3d&)(SIZAHeZ`IWr)bg2C3HB3sh=wDvauZ36T;O1CL~7wZl- -zSwKhSd^fsk%qaE9yxyIt8$y_QefgpCBlxZgbv<drxR1wdL4bVs2a{QIv5+ABahSfKH3m3kSf|LdPEL^(yq#JY -zQnGjY4yV%TbLlELD`>Is9B2!Kv_c@UUFSnv`=|<%R~vTCu+@{o%hwY9gz4Pt(E80m -z1}GT?_uU68WqY^=o|+q8d*AA*on&uO0yl^Nsjz@YA6O42RS!2@9LGrWg_u9jGiw`o -zz`&heG1r*Iwvr)w`)eGQ1Md-)fsKL2v`0+8>}e1^$OfNn+~Rho0vWQ0t=#VMf;f2TTr1SA>VN&p)Qq?PqN;zN2kqp?u9t8QG=qnn_G7- -zIFxRC7z4}MD>qts!t9J9(HeY)eSpog8YgJ20q)DGXh@Y^XAdcoa;pn|`nhW-h>YVMmEGgIQhQN4b`g;t3 -zdh)%qNnF^??utW+Dn8M(ay08cvUyro+z1(G4vu_RK@i1w&p>&Wa1P>a>uslE_#zfg -ztZz%f-_po7P`WvozUD%>`V`F+*WCGLMDz|E&D&u#Fck6|RkTulDPL6FPz7B^mC69~H;Q=e%)MO+C|LU+WX -zw7jtm&~XGV+lA>g|I)$Vx&T-#yjzfm-{*oh-hAu`itZ_SG9-|bPsN`8^Z`Tan&;+) -z$NFKPz^L8Zay_yLne&?1em%~1hV%Dwe+TGB9rU@Pn@ecPs&K3y5K8s9?;CxVXLi( -zH^?eqN!6Z;IFn`X%c|V@CRN1h? -zX%K~Bao;{y18&9RyCP+~f9F)&-ImiIO;VgCxVc{MDOA1_VWxG!B3I`=wG6T_gK|eR -zUj0?fF4Cut&xRf+WL@m-__;`b5AoY8*1LQasBXmZ@h2_e@^xh|lKzrFg7GOHk2WE& -z6u+0l)`AvT|&gF4uGJ+|=ai3-lI8WWR0W-PH1={?{kse%CSK -zUZz)`8Ieyh$q3P<_PVXaUp~tdp2LBSdo~X*l{_biYy16iK|7M3wuRyi)A;_SlWi++s?PTYc?*#!eC^ -zAn`E7;mfx7O2dsgwjxr>dYieP=(1DjBURfYcjEGXjRt01k5b-O^DuF!8|lgS)VF!$ -z9)+4!Qnzn_x0+aK0y2Yu%v*)>3GMgJMe>j(1ynoZzpKAy)AJdJ(lK!e?p`=Z5>N)8 -zEd{{$KI}d~tL>nJk05_1j^vN{Oka?FDp95GCe#^Z5j~HG?^CH1jLS*aS8)ib=kwEf -zYTab1XwqU*_Hv0dpoD}V{=E@*aYo#HU2uN`nj?J{&e5) -z>s#;lf31E8nXu!YuuH>Tb!Bh{Rv4oc2T+hUa5#FVO1r;%bAzX?spVW#kS!Slc1`{) -z1@J-w2%aiTM0cMr`0~e-{M3x~KL`{8M-vVLacV!x)LAO;Cjfpm7*S01u{7sOODg;7 -z;*M2|10zd>Cisq{GR=hs|K{SZnyE}UEP^TOq)x}ftn)2zft?wFi; -z4g8#Q#4NvjZL&In3k?ERH(2?|RXz)V{kYa+Pb+%tQX)2jv7g#+y-n@VE%H}L`R2v9 -zRrl#;_LE7w@5B{AKK_} -z3^amcGSf_lqqX+Bcs|_0j&CYmC31(!bA;7OmJVGx8novZXZg)o>P&6#pAW=FPwg9x -zsSBv&o}-TlruP|Km!PECbM`00s0sD@_O1|U5_XWGWg_mE_kfsSNd<28oO_w9Z?((h6r%aExw_;<=Z -zfSvN2t9PoHg7+=|twU=WGoAC9_5nt@Q9anSYi=glAe50$^Hs``Ng9}M_#N}h&}ja= -z(Ho2N8`vCxk-hHUmHqyBsNYr`=eV9*W%sGYKgknAt7*Sqq!SFWhJx@uP5u<-;)Rr*5ND!hoA5pV?%lB0&3a(jLx`61#$~xIcF)2TXZ98qn -z7CtU>i6@A34RRzgHnIX7kb)}Q-KOLZxEgnGAWcz-F)T`B}F}JNP -zv!rE*%>xj5^0Y+g=S6VnKzaDrjD}U+5l1i99W>QVZoK%GKK=^hw*O$&`e3Abx6ONM -zh~E%1u&yXBQjq)U=vXy7GJsdb%TFIaz*pDn_*Rd=7lQ1l -zZrIJsuCPjP%VGk-ie9p~*Qw~|;Kc8-TF!^<4vXl3LpwH&f17g{#JNYO_|o)up<(9^ -zWChd=JhbM(FV+e#NchF+VzTtGJ+=!+`M|? -zYi<8Uo_^14hLYfCMR^eS+Nql)Lw|onrb4B<-HXzOv|mPDUh)tCbAY#pa1aoYxH2uf -zpz*UIe2mx@@c7xt`XYTDO^-32Q@$*IF3w2zP+b=hOUh)3*}A{5;QSs4y!C0Wmg6NJ -za+3)rIRyVKGXN_3DyLpX=96eQY-*|0QE9EHCYW#J!$Cc@h@ZpDBhL+3W>5S&E}jdl -zm!OP;?^C9@Z;=;3$*lxttFJ4hrHw{^=WhOjoCYtPtc@khWME>}zxA>cp)1BBU9*MQ>pLY;gQN -zCu2B|$P&=)u0CIAD!O>XKFT-!cURnXce)OWwiJG?SMwsg?Qr$&HY2_ZyQh0RFukq? -zYQV~u?jZ2_@WJ~H2@7(U*D|#doIO8-L1gcM#bVtcfMjsvpAJ^PhcJ{s57A_nLr{$P -zWw6UQxFw$WA6SCKiU$d!*3t9W+rPu$3^bqaJ~P#E?(jW#NJMSY0Ay6I8^1E6&^t-( -z@c9by`P{Y#xkC0hCwK)1SGflDXRubvtoHNE{_gOHZ$N&C;qu7Yh@}VX)YfMYR=Cce -zwdwe&*;5h$;CUiLlyWfdLI)k&ULOgaTFfDg$I~Cr1-I{%n5;3HYKD~ -zBy7J~HGFtaDaT-r>Vf@2qLzjyEDJNNg}{A>FwFv;=iqj1B++SAED8^8bxQnqj6H#R -zSWf_5;6?uFD*n4Sx$U#}n$529CK{@Y9W^4&n1?}M+Qgp?*Wg>xt`oOXQn%!=K@YfC -z<9+Klb@c3GQ5G2(;Z4zL%&qcodE>cORp0e8S3o*GRw_7;^~cfHTYbONJ~UR4(ybG} -zlL&vaB?aScokMse@&LBoqY0JwTBu3$*2T8Jz4g9bkzi2k!K+N533dW*&(eM@;{;~f -z#j$#-J_pJzZ%y7+F8>+>vl-;+>7%Px322t&VEVUh$DbmV>hK=K&(09tc6)k}U-+E$rla?4Sa=R~_AC=sjK>2&7_~&zfUe2iO`vvF9 -zR)VEc9Zk&zPfqqPh1u>soVK4Sf6W~dW=J(``CcSAnth@O_b*}&Dm0wd-YPQ -z3)->pz3GxycT{N$rRQsGHGWIcyt(@sc3JK^M%P;|_FZP9Kh+|hb8+jO6(ETI9A;1f_1{z_x*g%CuQf-F1^rOU?Guj2?NPIA7rhZm -zzE^jtWllasjDzy!2j$nyLj(6rt`y<0h59d4!~c+6u$HfS*S5Dmz$uUEz8iTe2lexGQ^D{yzrd6xrn$dEoCd}}*&a7}rG -zf$ni2|@QMT4wJ;TIa2U -z&#bT#&pEb*%{{(P+H^|P8L#svBWeuiM}}apm#v0LQMaI+P%kIg%6o3sW<2t97L!# -zs}^a)Zut0zjp?u@#Ecc!)n$NqpO9U(tmlX6K -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 -zTdLK$f2)06Iy=}E)w+!KQ`as -zCS0$Yrr3K8dy&Q$bW3~X-VIXoe-?c`ibJ#HWH+O9DA%e-S=Mg -zy?%z{a=i~ka>6ca9qt+{m()ju>!#mN%k4z-j9`^+|La5kd1HfDuH0)EL(8q+IrpXe -z&WFbRoIxOUyvMK}t|od=&|rGW_&w#2i?ppgXb0~sB6l0Y2?LCi*7mJ(31eKV`i$(L -zM1QfQ^ScKrEt{*lOb>%IVl$23bn=sD?nB#{k~RWc6r#mlnHJlsoosp(=J9Wo1Gr7) -zg5G)rXwhvFPi=<)n}ori^F7y*jzQ5ymeRp$XqVfdLbb8lv@v7w>Vc}EV|T22RNLL? -zj)(#`R9DZb2ttFFz^g?UNO;tZ?*i>jvOi -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 -zMpIrpN1@d6+x!1me1zb6RATM$DY -zw6TYy=$w12ej<(EGZSOvcfK1e7nN66zuOjaMe6HtmZ5nOF6$Oyv~)rygOO%oz{v8F -z#U~DR&BjQr@d0MLg!ZjSS?6>k}{L`sP1}2TUcmPk)a_@VaXR=-7@0%Y| -zuck8;9CUA@n*Cd2U_^{K$LXR~UThS|c9+FV(G0F)t+Ds4^+@Q;Fxy>0aI*{GLeDGS -zIuozP>gggF4Z4BXf1m8%Qx?j{mng;x?<x-2gj4#J?rF@mUPigBWMi_S^Q+!x!h; -zv9#bY<@tbE5jIx{r~vl8y3LD;Db* -z*bS%7NfK9)8@1@49r(yWvTwc{aKQbD#3?mo&;*i>l$O#BE=Ud`y6t9%twuh3k*;Nc -z9?McY7W^ODB4^jkb-)I}UV=xXVq!AVcK= -z{46fKhbRcBtg7{Zd~Pbd`_4rcVp1*>n-O+&|J?l2-;*5RM{xnPcTcyTGNBGJavMq5 -zhoIpx{0Dq4@!kNsOs6dZ_;HgiU*Gd^1%CD-6nj}{9h%%8bD&$#Tm9;ZfV{V113igDKqN5~*U -zgli&8R65B$2l)8Eq~ -z;o*HJ`~>zVw)y@Dj9QgV^&JVAZ!~^CX;z=?y!EVhD=xO;bO4nQ(*Wo -zjl;eCYc9fm&zHbMl>N^k{_vqu=-C;@!hDe776dI4-EDP-0Q-C-_l2#mn7hP-wWnw6 -zq>)b?WjaAtYSQ=YdHjC$+~S+P;{uKMqT4xbr>FbI&bdu^zy-ngz?m$)zDKC!9Ln?e -zj9C_KOXT4sRqY^nc^F@nAeYe(HbUzn;zopsj-%kflwYKJcrnt(ir23$`>PM3W-@uu -z*5vGp&|qbg;iE(TDfg8B;`8=QzqD(x}f+XnwPCYEY6LSiP=@Fz!6$M^C -zvFH99LZEy3XmtPi>_0{KTtDyEVzhGj{Bw8Mi-g?Bz`tGGs1TjUl(Rqfxn}JsuP{Xf -z!&p9W*kUDN4E8O5os1Im^XbSMQnERm_vYwa|EY8T`^FU=?qDju|IPdhJnHu(K*IZq -zooustr_hBjN+MwEO1=-`fY+|e?GSQJbU5t>Rj~kj&+P)vbS5Vg6nBiM6G#P95-!X=@S-b8gRV+`zv(HTYiBk)u3SH<;QO=6j%x;F+$UR*{;^g7oQe -zSRQAfb(^j3!YqI9?*aP0a$GLE2vCGPv^6w~Sl@{lV7)dE{hsCc`SgEp+AfQ8*WG)% -z8V!^S$8JCY?JK%81F{j10MVIuD1%;tJ~kj=hGHA)$Z}4i!O_6;l4j}orqQ_9^2E-o -zlzIBSJcgHhjI12DBGMlj?MA$vg2o^=aNfz?v3%bx^@g;F{5jdr`%-wIq&W?D>*J7> -zgz-3L(xbb5Z5d(_UYs!dsc-Tr^3#I7H{=_yZVSZ$t(|f7hr3%!mZ{Yqd8d3N@@%s2 -zr>XR-n`8f>wqUdk#0O?0@O{W@v_TCxry;mPB366*NEbWIybo0}1sLO?Sy5MHlus5y -zrc#D{Qgmw6m*?IRkG8v1YTK8YV)d&l=iqd@C3E|V+&rH?lJwHc6jnarT*a8Qd8bY2 -z?`b4KD$>fS1(aU0~F0&?dQvyF*QhF~U2F~IkWWRBcA5Dj& -zDzoP_2q2b*48&Q%Fy&n+Z7{y~BL>pRX;z5IV!Z_q(tp -zopDtT?41J&Oy8Qjn!+M}^GKwAr;u8;IwM -zz8A_(Htu5&pWXvEQ>embal)gGaGRW669p -z&PhqS&H&-~fF#j6N4B2BZnfC~t||cj>87-}?0ZNRubk6WNvaR+H5+{EqjD8KPaWJC -zs`tB1U@%7EDQ^*#f;5t3uE-S_}D -zVrhnab(gs#yIu6^MeA^+2b$1a0Qx>GQ4--7UXtx^--5$ua60U6;Ai8%ovwP!75%54 -zfc=Li`8%8$PTDCF3M2g7}^TC!Ij#WVQ0Q3gWYQ~-tXmv^Of&2&NjnO#Nqoca?H -zwY&hoCXRZ~L;AJ&*vnBHc=#y7&&7Y%wDB1^O!M^47GP34orKjRCNHv-uYCGF=9Jq- -zMNRlmiu1H+gs%lCDeE@=d=I}_Z){{$sz|)zi?`10cbF^d)n(s?gTV@9?<>yDBxPW} -z65uFq1yMC8F4Tz*C%Hs^py;vpXhD$;ll7&3?1jxdolS>zO7Ejzt2KWSfu#8@=L!0kDN`bBs -zbzcci;!)waJO@M42B{MxhbrIk<%qS6D{zZ}P$!I+>em#j{hknFPlRNlPRY5OJ{bK% -z%Raj?PLunRrK_FVEQ)&nqES-${#*0WzL+|C=?J~7A8M0%J@Rz;IbrX872~7MQihiC -zMMgn=i_2xuRb76KiqhyafrZGtK?~;$l;opI9bKpiowSa7;_tbaEO>_m^r{Z07~##68$nR{-*1 -zq`s|k=hj1)0xf$oPf243B{kp#z8S={$$H!U<1lO=c6eJA6UJ>m6M8P(e^P)=Nfr -zndn@3)xRms&pBs_9$gm66qiFK^kS(mU%9dxFMEt(%eA9Kbdoo2jPTfiAH7|5dj9tQ -z@RNrh&*v_pEr~UEcriW1!+E*j9tM&Jj_f`{^fI^bD5$Q(9@C)nXf-Gu{xoU~sl{4{ -z$z&b@sg}T7dYfRRzE;`KH}bQJryCEnekxM&D<+w_}nqT{#Fi#NVxgD_rQ;8-|AUfx7ah~j(wb=ERfAR0H=&(@>7pz -z)Yhw@1G#n|ow7BZ6VR8TsPgWS2i^YmpkaU$wkqHf{dI&b+@-G^w$#(jp)X(G?ok<3 -zL`BWmFbr4@WT+G-h*MYT=y~j;gedG2*(8gi4p(S+to9wd$msj4p8N0FC;$z#((_sR -zEMB^9?Wy?LAFj%`Q9b_Xj>9@#Kl_c1jeLt|pDc5a(sHD39n%5)bTjGU<-j{ic>ejs -z!fAo`5;7lXg3$JD(>N*!f~<1SOn?Ex1M#H}u1k}?o@M2Tlm5B+U+GU5R3VSqpSf!Y -zg!~~|B;x<~u5M(Z^Sx+zpQx^ibEWfKGR9tg8P>>@jLHMk6#Gu=_52i8na4FJZY1$h -zr|Pj3c2r`~pi8|@zwoaAo~Byl4x<+8;_j1=+IxpB-9_vHk8+fwTI237czBA@oAMUs -zLF+;|$nX5Q9DFP#tfH_>Dv8nSL9cW1K0JAH@wgv6Q5i*h&I^Wkd>?w4MIu71eA>ZH -zzeyg+m#PBnWd_9}sFl@D@hdlrJ#YQ3z^rK(=9OR>S;*=_eWd&xOdyrZBY?5@{t5X;AeO|WCB!P%4886O*dzI?f-Jt)TzZw>Empgu^{F|u%G?-miHP!(=uDnoXJ)8beQ~s00X(O!S%nG?Z -zb<#C8H-nwNlF5QLLH>RiZ>0;|BdRbT;&IdL&dpCX*plQF@=M})APF^a5Ht?5pFcGu -z4?1tCNsKip`O>yy{IfMYgot^#uG}hCmny=4l3E3G`J$dXz2wOmfyKas*B)u2LX%Hg -z>qxqMULC>ci&UtPIOqP1nBNmydZvM}LtF-Mcl0t=y{B{9qBMf9k(#6Otz##S|emu^;>Lw=n|Hh3&Eg1~yK@8yhl!ay%ZpT!;KIfawc -zjPk+t!7&DYlIlV+7m9wmG5YTrF9|u7 -zB}lzYc2!GmEQO*2JaSD+C$A~Fz{i#5@f0UfVmiG?Xx}F#WVpkFDi_filMG&bh4p*_ -z4V0lPaP86Vho6$vd&4K->Ip4KRg9GMeh1-YaZo;YTid36G8*7P9CacLUb{jf-;uG5f|z -z;JHkr%dD!q;y^b~JJ#)i3**{wa_^bjFJaWdgAW-?>4GUoVZ`Y$zLAmJ!#6IgxV{5? -z!Ug$JWz|bcF^uPior9`Y0Cw<pbdnGJ4b%J32XEbV*n@pizo -z4sx`4-cljt3|e?@Bb@{Ui<_F1iHdN12kcZGGMEDFfmMLC-gp=({Sv -zQSsF-)rABO(u{<3%}QbxHPfP1p>y -z&EumQfZBDuarax#JVJJg>lj-MKpytPkJ$mHh~TF~g(Qz%XZGRi`uKl6WIAmL4sdH{ -z;84&6+Y&Z_EZRXl#&G^NfDTTGK#312TbUHPUm@E*x5(`gq`mi6N`6hv)BFBg%Qt{l -zeeeMhPII3e6v|1UQ+@g~9on|?d=OJ#a#MkXQ-Y2^)zADt6oJGic_)qi9qD>7eLj|6 -z^-?MZ8($s0eGNk<-DNuhuZNnx8e$Sn2?0QXv;{u!kecb9K>ZXudff``rO~_?K*Dzw -zY0U~3T9}6G`_3;H;`$>Xh#K-BP_oRNnUP^W%^KHdfmq-0!RQu8yw57udaL6$iui(ZA;q=d^y@9o^?>H-Y({N@4 -zN0NJ;?DKz&ok@~rDXxXLqy}|Eb?kphW!#wlXdZI8U3O8{rw;gPo^!uRmou?by@@E}xRx)u+qU -zifbwXgj%k|ON}ZP=*>=RhQo{yNYw3Bu(-l~mIt{G_ns35SN4Hi4CUCo)jE$H#T5Ff -zLXZeCMWqtuZ`$ -z&RI5W{pS66-icr*Fs+m!o3qRe`{Xd*&{E3pNw;1kpik`kvGe|#=0Kf>l`@ZrQn>}7C$)?sT -zm9};ePKQgjXnA+!BQ?ESb9!DvFJvgVmzbj4M-jL1Og5<}-B@Mrh*{D2EYx#g&k5S&TPtx{~U3rCY`bLdS_UAvO8Z3OrFAv$E4c~oa&#rE|o$Tqqrq#vo -z4!YW#C3ZM;?0TtzEWJZZ#qN^S0@ULS&!pT8VPEGg4d^onx}R;3y&+Y=@D -z75!#1TOy-J(Q>b>l;rmRF%jA#U)d3;zy&p|vJ2XrZ#gXtH%OVUZd(!2_eO1w)G0|ihjb$PGnP>O*-st+;o7s}c>amA81?VMnyB{( -zv>hjf4jHV++mpk_QC-Ngr8EO^#<-&Z+2+a|Vw=9tcDfjRBOJ~pYi9Pt1>*RSr -zJ>PrueN}t{nXvDGKQ -z>+73>_vd>3)E2Za@dRISxo1bOUiUA1@3GVX&+V~36#J0x1?}QMC!q690!-+_Z+KWe -z0nxB}uPRu62e2Er5UZcqVmNnA?(Lb;mZqgVJ?~fM4y6GEJpvCc@&!?4K)KDMrRv{2N*m$Meds)1>&_J9y}!Al*lI3*Ycm -zi=^|t_QnMqK6y@IIszJL5H?6aGh9Z3EoYFpOtKy)CHqBKr(rJT`}cI3%Zv2A9ve47l{*mgd3TRU(Aik>70#P9=@9scLcU=QXdp;9inhX6 -zbSpn!b3H5@{^&ZlLS_4e=pFuwEs{SGr~2#kJbrf@az~w)j9wAyTwiwL&pz#t*<~y{ -zr@zh%gU43WI`^{XwR_^0Cow@c*IZvn+N8+glqdU8We6kZ>$^o05?&fS9vh{12Ix`G -zaGsJg3d?!yJEgEdZqX1nPu2Gy7=8UDd0&>i!S^VdZe2L1kNG)jZ2-q$prH=5C%Ctx -zIR5RRo6O)fGP7T2gYmmRad1^mnRR_<`~AocQ_tL389q&#+&S8IwHRPH -zW(xxW;%Hz_CWL&33*Y%qK!)idSC$c>7sPS&+Pt+rQ~gaVSrtA9(JdWsDHq0{PoOqve0eOA>9p68;e^1S6Wy>aeA -z_liULG;x%CZOOU6SMGO5Bk5Id{H!ch0#G8OkJbW@go=h=nrxmmi}LS#L?6P1OIRV2 -zsBI{X+qe%DcuS9zzo=Ed3aYTlKpu{}HQL^stVS-Sf$h8UbroCBH!Lk|aiR&8poF!i -zMrJ)o?lqiky`Lp6oh&WFWeP{04H#T8np+-;js*Sv3{OMQpSt9j)7;KdfwlC>jRb@) -z0Ga_du3N)M$8Lt}cL{Cx-k}j|7P$m+x@hm#kruZnM9w{0Kw{y19=TvVDCRRLDDRK1 -z>Yw*n@w*371ygTve->-j>aBpNCaVxv(%mH@X@oF)>@ -z`9wgr-jV4F&CXN6>3r(e*~lC2y0p$GjWEYq&Z&}f -zxEI^QRs`SI%u9rsp^nNv3zCb)M8W=Iv-cqpm)Q2y%h^gsBr#~=v&gjpi?DZ_2JHBm -zD8ghnSo$7?XurRM20Hp40&qx&44hrmKhGZBn1&8ttOwXP0OlSBm8i&yo%oDab6C0v -z{CqdokJhA)5poV8f6Yz@LQhMQS`+KQvcKIya?SjueYSZTnbX}5lJ8H2`Mb|j_y+nN -zfTu;UM&Kdwddq1OIfDm^ -z_n`sP%U~B<7)8(6Jr4{icWY+8pCQUq -zzd`1yYKOY*nOG5XYY*oiCoda2cjRWL#cb+n6v9~~sC{Ch-179%796I-}hQEFKxA7V3~GW1!SgjBAG{UxXzzK-Cmh6-$;2 -z?d6Kx)`Ilu))$^xFHMb7Hl+4b>?-rf&=AWsmhbFSs|Qf;y-wLjZ~8?G8~)ycXldy3 -zY>F@(j(iC%k2IxVH9yTKq5^-mCZ3yh#6jyQIjA4;l7XZ-brG=qzX6u&Zg3b -zuhEkja;;8F2}=eFGE|{|_vTqjL=JdX&Rh$4T7omD)|O*2elFzio>6*4YP}EQWNRPi -zfdhpQ`XQ~!wARVU83OlU>bbWvvGE{9bBrPL|(8y25e%^E5^-JdKNwdZ8~g6R@7r98aKvP$h~iQqu`FxG+Np -z*AdRV-#2XcZbC(8Jx!M9m{fSKM#I(09Zin(FEC9(7q_vGJVXV_l?LE22HtCS|CrQG-5EeAeS#j=MNKuWQegpRYD8;PwqbOFgf0d|nJ~w`*VB{qA+I9pGIedg5Z(>eM~-9Sb3k -z*7I}1;4fHe+(>i&jMEu -zeCi~HrT3c=ciOVT+P-^ozih6|;bHl<7Y8uPiB2~_)jekRHs-Ab)H;WJJnT_4=?jT< -zR8nNSXt{l_Vi`^C(lkLRx&BKuM+t8wMjwI$Ep3-Q8>|j2tjSjYW926dT}I{ig8uG*y@RoU -z>Aa=ej!<#LsmpKOq}vriC9HmK+3_LLbAe#ELZJ&s%bSlkm7I**n?}r!Ju@TeJgx`m -z!%x*25G$rXqHywZVf{=(Xg?DIx(g~|sO<4I1@6tG+D|VYKAg^R&_IkMQaL#&YVk=} -zkcV%)GB6NocLU&PXo@P|^S(D)0BBNgnaH6r8U6DufE_o~GY8!5wGsoglk%zHWTZ%Yim$(eZQDX!m4`HhwuLZhiA#^<|qq=l$TDa8(B}=jW3C -zhrwm!5|mzBsHfw@BX5y2ork-fB=Z?$U%W?i*?F&ypM&D|1QDF(<+|?c$k?lRq;Gu< -zo}svY_%mm_DS3GzMoDhwI7v0eWR$cv!2o5=3#5MHv4-yoSlt)y%9lY7JAU&?kgAE7 -zX6jr+9B@n5ebSjl_{-JwSIFO&i3+mL*cVFf9wzUVPLEds5d{a<9S5(;Yg<{0%$^wC}<@P*_S9OYj~W -z-?4q$hU9Mev|B}^5-C0f#DhSw`s6Ro8ioVASf>!E^-Si3c*v`*px*uG4VH;X;;nN# -z(r+{z)f)LugmkdWTtm$`2`S|&4bb3O{*E1k(rqix0h@95U?F4116Dfu{YV7gbL!(! -zYIcHq<@2JA-|6>vV{Vz@Nbke*Jea|QqKC)OaVTjoq_3ZO988yBhwy&6<{DF7PKCYa -zeJeITLK))ev+!fC(dU`e0MY*gl_%G -zqqG!{FM()|M`*9_{rXqWeq*xYB%XeeB-w*7uqCgsP;|~se$_VrjlD=hVOVjR{$4~8voGqT-``iE=kHq -z64&_&h-P=#D`4=-Eq#tG4S7MJ`^iCB5h-GDTR3BN!;zK99NHK;G34Br9ZR2b;%j(K -zedeHDAvjJoobdD!5!Km^sR5L8teEBP0fEa|hmN((KP&f9N}ugbz~ypludmz{cx|z% -zo!0BiPgR}2yR?1rl$zMREBw-=+{aOoR@w)S9XL4aJSP?ONIL0Qentwod%LXclv1ar -z;CUNT!$w@{Zf`GAFjg(jd3mX>71XN2{#@GM?Z0pi!ZLzWo^Lwc0lgqE@up_2ojsEh -zReD|a?V0t&YnM6!=2psiaMeR~XT9{?A{>JT=Zg=t>Ki~cz~$K4vfB@Q8EXK{OHtHZ -zCwX+dnIXKTk5#E<>zTrXDtT4v964tkJ}$k-ZG?^6Zdg!L#D=<-tvKOYKglZ2DD^6> -zsM!SRWQ!GFqDePy1q9TD`P(eRR?jYslY;S_`{?GPxPDX1zn-y0_PJ9k<>mFD+9sC) -zHg%a=={!6qYqfK?2t!RIj%2;S?2Xv0K=CvY^lY*|{PSEFe|HRfIc`+WERbG26ViYY -zW#PgJ3f@t%Bo*QQ7ejjrTqQBh^q%LxU -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 -zk?Jc;ecaPDykRslMX@$6+n@VB>WEt3f -zSLh|+18*hDmX3+edEatG6coT~`ay*rfM5>LJ8}61=FD*iAR2H)c}Sd>Z)uOP8fDon -zDNe4gJywf%IEl>r^WVIq*m#()4ZpN5GoLGg9qpXX$FmF8JIb40-2(3Em9|E~ZIC*YIpYk1iJD3m -z+U9a(=6RKrde8j49;N@V_GgLsLQ@pi>2VO|F=E$hy7%m@Ige-`x6%7ZFK?f5Fa!!m -zxUx^j`$bd19`kyPhQIp~#GM2?C_=?U>KR;gGD1Wf!W!&)h35U!sH~Mb4A( -zfUqmaxf_{+l2Klce*05eUj>0cJSy>L@;|&Wu<0wL>r8yc>KmPN&P#oTluOy|;B>?F -zZ3^{^fTCiD0no^e{r!MoX(Xg{=;+!o^};oBT7W(xbQK+5uuH(w{tkfOm#4K+S4cbN -zvo#i#8N|KH6&3^PDo+dpX@l41$%~5Pl1FJA_6Qu8}Rz-GT#PqHmiEiK1 -zN6^>bYW1Uke6m-y?seWQPKWOWBrrUs6aw>=6msq0#O?K<*jI*HmaBBr(;9B+C^Ib+ -ztYP=rI!Z~Yv{ZM&FLdX8CUUh?GT*I|rjci<>IGX6)4_*nuL|8Fn9dW~G#oDl8oT`c -zBKzeb)BB&*$lP%YT0lWD`k3($UmO(E!wstBD*NUcUlOgirt6fN%a> -zuRxunfDhvhj#$RJ#ai4?YGlrumDU-xsw=XVYRuz&Kf!>6) -z?=73nB3ift(f}(>?=_RAyLcogwI;E+<&4pnM!7(J?vl}Ref=4j`?6Z-H=Xxq5d6nn -zZPRj@Ry%}1GI}-`-Uk~)DyzJ9>*XcX3pD@c$U?tBrDlY^_^@0H-&TRW{^;cT&^;>f -z%Ef0$#@Eh+Je#j)x#Q(5&-)z|v`4?ZOYHdFSUYovf2JRX5A4W@_v^Sh>B5ir6Pn~} -zVcii=>bKt<^uAx^^scay?{{rb$_2&j8;r|XZcV4~XzRcM1rfF0y%GxZ=}_uA8gts* -z?&(VI&&f7B@W$VhY^zkpjf -zoBoZyNkmihcudOQM`kIJN14QZI&eo-uQZX#6PDjwy -z!s)2=Z*DKRMRt#*7P*_nVV_W+#Ktm3tUnx -z7wIQEx{)N=q2-JKwhY&Rt(Lrekpo&q{={>J7B%i7+B8+V7>t07a<5-__{D~h1u2B)tj>TRHKAtg;)APG#_2U~- -z!XD;)^~(Jo_Wlfn-wzSKDV0rW-DQ^ZnRVFFR(;4@FKHh-0hRIfynhxF_e`JW74hPcBQ}IeGNU@X57iS^CslNP -z4oIG9kFhs7V@7-9bzn`?G3Ja4ZNa-AUSY7V$~QEpX7!@0Yw -zcd=WNAM)aYc&u4@U;3Qs?m*=|;vknE{qH^Jf?$fp0o_$p^_g#;v(hl3d*-pdGxrjX -zS?`tj#9)N{A#y>u5f6`+_6*YyTo8}$tn@;%`&LUu@d3L>8N^VMVL@d=v1S2t{%+8E -z+t|*55pPoL?2zTD -z#oKFnQgEgAam_6nZNi@0H{(dTS5sZQe7BgGFFaHm_u;ZXxdX<92B&&36QXQf2u>vS -zVNd-87`yl&xlNE=tn-lS#cw7k>R@sD+y$3MB9`Pj0$jxaxG3@%(v>TrW$JjSzbP%l -zpDM!0zsDm^LWtKfPrp4M@UXR`5d-DI>!hzrltSBj66>QmlybGpR0@^NIu15PY{*sg -zAb}uH*K*??(eVc12NYFvuSkS~9)KLq5E#2x4k#ISEnoyyb?1!^DMo@fe%>9LyAM$clZ17 -zlXmtFxzwo9g1C$Uix+szks&?tXFyPB7NhCqnAY4QiPQAB35&gSN*zEnawr7J!NuGj0rLe5Tw=4W= -ztDJQ_a+hm#!2Ivl?WDk7;Kzzp^e7Wn;){j2!HcH=$DPB*QIq;11YQmR(V7_nSDr${cXq6A+$1bIXw`=(;v8pW1~vma_%}N?k0Qiqa}FpcToI3cdR*#)eS|5$vj1tuIoY7uL+=?RmQ$oim#wQfJc0% -z7}}X}vzg~}`!)ZPL)G~veH;wVz3Fkp#rnedVVE@pfnGf?C0kR5@oB#Zd_J>m8KL~9 -zQQAr-2!$Bbq(Idl9tS$mFN+a7CMjJP)-_o|IESk4=!>lczV&%RTa3b8{q8=JY_AvS -z;S!qrn5Npj`8X;!u+5FejEsS4mIqy7kcKuoTUD!K-cQW@#^zq};J$;yF85Ob -z>jtR)eILQU$2?$TA?xLsi-4S#bM*M>&%?av{iRzU#_>mV@lfwW?++gcLmF~iH>U?@8Rgu&cTACm{Lq$LqP3Dl -zGQa1g(_aJDJiH5Xn>1?lcF<}p1iIJQ6;}iFd+*;O!!2@#_HE#WGs4y2-(B94DC=dW -zs3jh~aYy*7diJ7iNOwUrF*mdxl0($jrfAPSHHFrl@lTBOlASXT@Tb&0Vjy#W9!&A? -z!H{A4I`Ho_!ZigcR(yc|KC<^EoYZ2!%dAN4bbv<4dgN -z=p+P$i#spI@#=+=I4`kpm&UPanmB*nVLGGbg+BDEvmSYYcEwCx`KaE9(8W%}O5l5& -z@%f&1qHN1PVB&*R}%#D -z3`@>q91?)}z{k8gpx@l?&bbXycWlX0ytn&qC?;R!R(>XRU=waFMC|-WpTguctm^J1uErl|}63$KOs`ks8tNVa3 -zf?kT9`#-d~3grx%kn%t(hgl%&*Cu+m$8#$V-abj^m1;Z9VC0%_AHGD_!q@9nC-(bt -zeb1e|1ruPD$sa0m9~?gmciakfFSz~=kKg)rvN#y&1r=s<)WlfZg+AYtw7xWcO<>n! -z{ZLJr9c;rfp>B9wS=s87h!4b*eWm=p-Sf8YO>eQ%3+E~pI2JW0#$L2WCB>}6?soIy -z+4|RA=RW-T#hO68W#ESyL{=ZxVE~{P+O;fz56L~kyeKXmhIFZ0;kH%ut4drd>$`_y -zR!dY-`v%o -z#RVQ)x|L8^bQd^FuuVb*&{&SEhrsz}%v*}sj3qTN>E3>fe{T^f-@!9Y_@V&VAfp}S -z7+vp6ZRy&0Qg2nh@=oRa^KzVj54beK=;Nk`cWT$xb#M4Wp#~ghWUg#qfa%mTm{(OC -z$eFm0D{3_24QM+kG*%wU7-5?r-VjF>kLxiqJf82b&DMdW*JpDs6K(eKRljY9V0q~k -zUhj6zS;v;MUM)DdLUvlqW@+)303$w%o}_(RXzNV$az=3{AQ&1}*uc@8*w?`9zEqHNsSfLCHhrf##( -z7~FTwta1GBwkj!`6s*jLK+|z4StE1=aH9q%vvP2GN$K3~O;eWs(GLvO^?}5k= -zL3gAMxDP^^)@3_uR#DYd9|ytt)+$wv03mohv7;ijYKv@=Bho(-NN%4eQi=vn_s79Wh0Erm336 -z0aj@7G)I32Bc0+bQKIpx=8pB+85M7Qo9bwjdLOoOBsmE7>Ob7S`!SpClv=m-4cNrb -z{Z?-XWF2eY@Xrx5Q2Ud>kQr;hM`sL8JSx_e36P+KLJz*d3c67n^VVMREI -zc=Kfd9K6w1)1S~Waut2&+oPysuPAb$cjG(It)(#H^Rq8CT -z-~%3?tpB9i-mK+48^kHm9+D%MQDIUa|AlWf`%$>FZr6@*-}4>X+inIE{-y9F;>D1So$-z=j-zX}GE2H|{B?bd4Za(s$uvy*+Su3~PJQITJPNUJ8D -z;e5dTJ%xfH4y+bK!2216eKD+hg;Gr;`hBR`lt_oA40i+j)8R=m33ZF5=FS@JXH7W! -zH~^apKCCumj*kk2sdnTQi6(BOSgw882@3m_X@HX|g`aAKqQ9y&CBwd-ffgKSr^Ad7 -z#{HDqkl&*{VAFlfPfDc+J;Jg!pk7$okRcu|Ez{>dqP77y92akW(8CsJwZb2e`*%@rpQGCBrn2qAC#_t!mk -zub;;Fj|M>bJq&bllwz(sXSg`{%EsG&pB|PwTJC{X$B4be+_V#=&5ye3wou}3UW;R0 -z%ighmZE^razVT`49$x3B|ZuIg#Z$z+I``)qK!NmD#rntS5{$ZuQ#8aI}W9r=YINV{VGVW -z=cjJwo)TPG0KF+Qcu-O$b?Vxz_!#j+Tf;%0v#}PevWIzmoxJn5sxvducPyALMiJpF -zLZ#>C&#^)IJwBA1m+Q-W*l#1MKR&+@frlR^+S?wGiCf3Fxy23NLO8~;o1e$}Q6aJ+orcP^T8 -z%hrKh5l#}A_v>oEmE_Cn?rCOltm0*%%{a;MIMHfJ1%Ixo*EN!5 -z6{>>o%|lS1_TD{RHIhoX0CqZwN9%mk`l}*m#9t1@#Isk7jX5|-Zlbzn^RbABjx4Bw -zQ1R$FfJYHp7$@S<%7>-fE?v!O+wWlERWTo1>bPZNTYL=|GnW>7s#V;A-m|UEOCP3+ -zNXUun(KE!YpAH4l8GB)$KB;sN^iKT`2KWPUVv=BD3S6y2F}BbQB|N7Xcp3K0;YQxB1oVuTyp5 -zcy5|~j)+dPl=InIG$wr`pg!7<+R;NA7PnhJKk74!9FRk;cTT=^Jf;qB1EXYaAHVJL -za_{(Hkvs}F}CbIr?4?batA -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 -z=dj^1I0ks`)mU71vJ;~zC7Hf -zPDcRPune3G8AY(`+f{t~t@GC7we?Bfp%cgc$@P@hcl~}D8GFjxQ9f#!d)3YEJ{SsL -zM9BJ*~auD9jnNy+oaw|QI7Dyd)t5l8k_xaQBF+mqr -zJ0f}IkxG&4-Y8ez=WFZD!B5sg-3V7ZP+k(FHXSn!ow{@+u_ctU0E=JH+X`E1K7jQ8 -zgH?+>`~i6N+3#FGmM?wB%7*|9V2yge^QbEkd&5e^;e5R-U>I~n0ums@KKb3plzDwk -z>fxzdjtMUL={`1>RZp--(2bz)k1WbB(L6Sb)HEI#e&`hVxzTaXCEp1JpyBuQ7fYef -zv3i*BAv|=w%xLCsKV`6dW}szw9yPGw;yj0m;njCICGu*b2x1+blL-t;akE+;6u5sL -zB2?5lLghZ$#^F2ZjNhEP=4NkrEEviIrC^_+nXKKAW${C-;br5a#*|HaBSvi;0nRGc -z9BsYsv8M7d>YTc30~z-xuCm{Qg)!_IN3q93g4UURxw`#xLA)mn9Hp|>SrrcwfMyu% -z9+K*C{>)L@WUjyWrsZ&*WcEG`cKGwh|I8l@AG@Y{Kk16rcadg560iOqb2~WedW}`< -z;jB}yr0SRj&R-5Bvsr9Ngzktym=ttwVKkbAoQot)M2s6axS=L5J -zE{m0(*bT*@P|uG6U2R%NuhSvU2nVm#zngaYt{z(?L+hH_Qv2lN?NNE+ihuo1*E)Er -z=4PGSh8TUn`5Tc(|C9an?nGi(aJK(#A<=0#(rv(cymyNZ7PsA;Ra$(7(hNjKDoHK5 -zPsJl-3u464eOit$Hy9joiU2_Y=U2@W>pP8mMblc=2O34y -zBS+@_IC^In(~gp2Gk%qGeclU8OG@cjzFm%e`J6MdkRz%y(g>ab9A9&mV1zXn9hQ@! -z=OwI2HN-5ez|o8$LKXSO!G>|ysGoaHg=@#&`bk>L8(rj|FD|&D&ZGWxPvcwVOkY>N -zX25ks5$?gSF%{;b#Y^cA@?>>yvqGyb9a{Yc1a#=18w?ExPw6QYDBk@y%!2aBO8eI1 -ztq^5fVx+1Ugohg-FJE{H_3;+z`!2jrSxLi{hpT)sNddhk?=)YsiG~qrzBsM~__IJo -ze>X3dBFjee4V-ZRFo6Mx_diMkj`)DG@Q7xZR2TZNhzeEa={W(M4|0#+K9y(;IOjI( -z1BrnH@ubTR?{1*cU~n$1IlTuv$o%x9$Ov4xLaan~if8~^n%QG9W;ALxj^DcE_pyoH -zOLZ1K-JG$v4B~u+4BwD)!YQLldLZ#KKodW3n~cM4LB|yLe#4Ew_O}#1_fQE*nh~!i -z@iG4VeUqif=@5V29f?IuPTF_xW5U;9xA7$7wSMqU7-I_{tQ0bc9^bKNShacPVPy~c -zMp4Xq=+1~xp1MEwm~ -zRDJ>}AA<`x_nR251IC~&CobXRGFS8a!k^*wyWO$B&BcnQ&xzIo_bo)fUUkS1DCz%n -zSl#CQOud~Lc^>58CiAvYJX*y^{Gp%c)%M%E*-Ua;?}H@NP1=JksJi)0C?g|3zBCGK -z1}zY7tMX7p+;ZiieRDjH>BnzUe%1b(dXhy@LQgPLYxypJYVhNqym6bRG?<5hidQxQNoDgCR&?52Of@; -z({UlVjM9%UGyqh~J%W67#;GHCof-DD4%U@=d<#4=A?44_2V^y3KH$eLupRwQ*g*~^ -z`87mE46<@$eK*JVs7)*SE^9FY7+Z%qRF@L^zm0Jj&@xAh@K6Z*MN)uZ%*>%~{v?t~U-0;^+mi1PKv*nN~-*Zf?j -zbPy5Fqq$Hr`?&kD`%QR8KQs5b_&3xT=H7c%Gnt#NP8KV@V28J0N}WEd{RnR+R7MpF -zzqq->SXtG(bwWDO-CODDhL`}`DdBI-#-SLUP(s={C+pIeq3iB^EmnTusm@^Rxj7Pg -zORuB@AJ1-c6&n!#J4LP;awZTa$f2`#(1bCv#`7$9AIBAHzes~;)NiWL8RflyBU4zb@YmG^d)?`+DX5*j?MVPvaeVBe?~r7hL=kwl*)6u|pL^%K5@v}|-rr%+v%7$Czd5;4Ap -zja>uDeJtBAl6^C3uHLgO$dM-nk#Pq{nYGF2tp+x5SP*PO7W|}RodaEx1gSHn=@%$s -zsqg_3L!W7{4$>#!8euT7)vX?a!B$44x79+TfFoc>N5NKQqZ@OhW|uowO!`ZdeRK8VF$KCEM_kt;q_op{q^%k16*q};bB`=oFt<-Ol|$o+bM_wZSrt0xB#e$H~$-));iUEkgWFmK#I -zj>AX}&d%Mk(2wL_x7+Fh@YU*S@ur4L_VJ0&8_j3#$uI`+arBl@u!*@uF4rCx!1BD~ -zY_#=0XpWroNEZ?8*ZugwP8bk1qQb_6KYv=xyL_IkFFDg47x~G!Z#3_{7?5&ziaT%F -zaxlLqy2@G8c8@)Aj)rX)b4Vdy4l#d(c95-JhO7fw9o-jZm$P$Htg2k=+Jil`s(Z|L -z|Ubw26BI!JrUlA+yfxi&YJ9!09^a}w>EX~O{dQD92#LC7Kh -zyQ%!!Ss0P?ouQwx;m+`5(UlqBY_frlb1j%ko~}k)0$b1Iz@ybdhpnJ30M8SS+%)P< -zEqqyNHU=K!K?_5r&*MgewSU&F>woy&QH00&*X1TC-H14Q`Z8q1sj{F;3I&%fPvL~n -z-T*XA$);5u3G%TVHd`4uN4i$}5D(#gNy%b#r5=<_R}|Xu;jdJhNobe5^v>1fug&R9 -zakb!uam9LKQ0MkHI4N`>9{|h|nngPo>*6uoI+Ry+>5&lHN4N6Zg6_(eGzrSbd-&cb -zm5=25GE#9-9y2>|`ECsxTu<+8Jdep^yiZTAlo}Y*YcFs2x-buOo)~gl?+zlC2l$2{ -zScmko$K8S}P@3q)nXAXI(;a+l>}6`=lIB}v&6~Gf{~z`3yRa|@onYE2(tJ3%)w~Jf -zw8tt&)#3YZ%f$WCqTB;pjiPCF2>B>$ELO}>JMwXivQdc1z4^&{;Azva4AjpDZ_ur44((p$K(h7tejd -zRp(3zsz`-@CoU+kt+IzQffvZNJyk#rKrLPFTRWs_Ana3E#fo$HUSl*M6gulp@9#+G -zaaFTzKU|J}xj<=zR2TI&4Olp4W<*HLtj8nbz|3j( -zR49gfI%Tc3Jt9K!|1eN^i8|xKSxZpSCYTT6@pUBeS%1iz{m4QNr?xUbYzDX`jzhs# -z_ufd;cDd8Dk1&MY>1*H%<_Co+?YwY#gs?G?`u9Hn?`G1ks@8LE6o00pa-Se5)6Wo+ -z;H(M*gW4^8k~Dbs%+sfPk}g2m*YWG%vn2c8ENPe3{U^R?6ArXKFoKsY

r46_VrdCQ_>b^q8k=CXV-{AK%%}5RO9u(dzXPu -zBUfuF=6fnrIBcV)SK_K2xiQ-x|LJoVx$;=MoI&}zn@?U{P(yiF4BRXvhPKkQwL0!^ -z73*W^_H8Ym5`klyzr*eK7{ZGumN%Id1K=g0>b~ApGdAS++=)>0Vw -z&Lesl_~@z~u~lSap!d$_=5(FI%0tXeA_7ZoJXHr{zirx+9!huTtkR(d0b2~1y_;iT -z%WVKQ8s83+i$|W)`U<+Q#fIKvkfwny8hLe$v3H~;j2?hmT3}CTDX7jr#(n_W^vYiIb_Y2@G$KehU1qH -zPB|aD+jzm_I488ghjqEKW7KPZ1aj7Ab8|M477+QZf -ztaAC28fW*h!W7uFxwd_`1C|S^L*QDLyc@tvajyo=W?Mu7L`O`|)C1kVkMnw;=5sHV -z>(|46r=U8K;wM|-Na$Y8UJ7byN?g+t;Cy1CIbw4ClxWU_VkLRR -zeAHR(Sk3+RC<5k;0A6im*DNLr%hf76c%x{1uN`SIaVnz=#UVHA^NB&yeIhw+^xO)b -z6MIVfWDBe{7u&UE4Ot4Ix6JbCy>BRe^u*NSTdwdB)IMWJ^UlGMfAV*1?v*q+k#!@` -z$xy<%qGLqH_Ned)9oawk*K%_S@I^f{YGYbC!XiQMhG3O`E?>%@7qc)6@Hitsu!pa@ -z&CJ8|eia78bx5v0o=kodMaUm4C?Xcp!~d>3XtpCi`J4T2ab;n-%~%LuCfIu$X0#^c -zI;>U3bYk2EJ8QS#g$LzR2%1v;t>#K_j6@ImCdTYHPqiNjaXjaV#{1M`HPH}?AH8!n -zgH4(nUIKZm0;roX)ME7{9@TAQ)Rk_2vN6%OL?rgD%tTF|q9?47?(X4ewO({lhp)l! -z9FMjqfQ)OmuQ1k&e+jy#JV6#mAv4);(KJdD(irhZNaFr8v62~-bFi;mYb7koJPMKs -z09fCSh=(P4f@sa?$ANv_}znfyMEe?-k`w;jJc9=Sj_&#C_z;bl1g4ih+Ft{r& -z*34Wc$4=qCUru!W4AD<=xw7odO_oX{@2zWisP?J%tdr(@SagKDO|VPXsH{93 -zmefnVRw-+?@R;QxVc&P{CmyzS$5}8Wa#3jO^X=?OKIA^`_od1HbDn2mAHM4PSs>S0 -zUie(EPb*Pjx(1U{L}O*APb3Zzvt!;hpTWd(y))L)|Jmr^qCZ@OYn>#$+7t+!n4y@xE()f+N -zDsO2Ff3>5CH5}^ymAYC9@$iDCA`l}W7;mm@#d;3nX#LfdB3pz+AoPH<6uF3brf`x -zLT(L$v${Lz-g9m7;=}yQDL4S_aeaFw`RT$t^#ta5w>(E5bOF_4B315shpbHD-M1s- -zWWg!<*Y|xh(<<@Yc7m!;)E(3r6}Wl(B-y~(*-ltK#d#PBUuM=v_Q{@<`4Vq^D~d(K -z&eTi$QQuba%Do6GkABjm>fGCTSiYIp@{;UVeSOGlhv^37N>5Y;__6>}9V)3Wk9xP~ -zQ{9yX4+Q;Y4bsJg#HNb|_s{w@#c!qzeNzmFkG -z(z|T&uGtNyCd=j696v1x%6RIq>EUS}vm1C2V1;mspT4Z0Tfz3bRhPzvOqd5+acM$( -zuR|~1V4}ye0$I<6ng|Zoxn>pTDE8gIHyQ?RI|_AldKc-g7Y~UP9Q;?5FE5QS17*Ws^MF -zLkfaM!n~HAkEdv-BqfsJ?R~sttnPU%+0O(a#5c%tTTg`jJ4V5F2)U5FcZWi;xnD@@I5aIp(f8fPUm$#8;7gl7hP6{GmG$Em*S07AzrBH#`yF}Nr? -zNF`rRyYVD5?dCmA`|Y^rNp5;ffYz|a5Qn~@p3#(3j70#zM;ve5ds=dqvZ7)0KoQ3a -zj6csN&ST7e)Xe0n3dlB7Spr^crL*l!?}I;Ye(T`J43)h=8p6b%K8d4xl1~x(;9(TR -z<;?T0%&wmC^9^wH$2NvLh63Pcd8Pes2YwIPG)t7f{$97fTt0FSLNhVkqX8GFxPgq40p@0)Y~*K+H3fRy&mQ>fW%$;y!v@gohUir&w0w0EZ@AAEN}V_ymOFy2}A!nwK`;8mlkyHJdL7 -zcAm>E_beYZ@+TPNV`A1GFzHq8@+8bIiEzlkh{usIH$7Jpz7eo%u+#}oYMk^g$9<~r -zB9a;Tc#p@+G$$Un0qXm2D8HW1+8^cC6}8RtE!UBdr)AZ~BxCk8+}1q|T}$^W_IDWY -zR5Q8C?4ILnro}kxZM$8HLjJFozlQB=0?UK+^>luf`MIKZ($C*p%1shH`iT0bmKX)| -zovSkV8HKGGE1y+ul_U4q6$?K3wCt&nBR+YWHEOaAMemV)%ZYc?q%YI@#KD7YUCo#4 -zp?_WY?Ky70TaImKbNWNi${~Kl)W6XKJ&AeOjuAaIW^{+g&h8T)lkkKosa_(vj?^4$ -z;e6$s&%rrysqXULI$8;V1b0m-&|X>zcC`>cVtH@40t~{qJ+=?}ZI?aSsSo9Am1S-1 -z1i<5;t_5ZVwO%HWP9j!{6|wg|irnXxsy_g^4DJgx1AWw;1>Xy5W+IyRs9;4nrIvTqoV5R~F*(qr+NC-rQG%p&zfZLDS5M0#!thHo -z5cCF8XzzgdI-Xex2lq@2@5HHF7)9?Ry1rVYtqh!(nekAR*El`#omg2%Q}PkH -z5ecPP2pyjnNlzEvWqer07hy5i5feY#u)1YQ?w>O+KjklmrJsjFT5HY%ULt_vF&g*e -zyu%34?(|3k-fcDw(1kh<(;jERVJD9Xez)+a9C<8dGV0y&k<hHVma#ThHhAXumTC!(`eG5eum-iw&s&r -zN_KSkGlqyk(X4zFD!`;q;(0f6{o!spMj=`!?&=9!{XCIiXUIF6AL#NyeNi-NlZf*q -zNaTzelzQp~$9^c6&;U{ZH9*S0d##6@YlZW;PX_LRD6+ShzeBL6ewOcr#XTxwY(WBf -zvT)06r&FRBo)oEc{dZei@mSSk8K?c>)dK0w^Q5a*V15#B23apY;5|{7PE7bcE;!%$ -zxdJncyi9$s)nY=D$RWA6KkpsNyQdaFqvN_IV(UE^b1?;!5}}=)josJo9zWs9F1ivU -z5&x>@x#eY<62cR*xz)(d9m18)HFpo5yS?~#y|J?$O7{*tBN$AfMrUsKfsTeVbVjQt -z@~O7FpyYac?+wMd@t($1A;V+l!qiml5ex*ra^OM&k?NDHAUverMRILhexHB*ZiE&q -zC)7;Xs`FBS>e6*;vxw{+^~s!TnF$Q`|0o$Kuu2eB<*ggWom+a+w9Q=-b -z`^gscD0JTf}R$h$^BA#a&=#qVJJ-G`AqU}4z1 -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 -z9=$!5(vWeF$A!3<$#YrfxSo)C8Cs4) -zY(_gb@05G)-_S`>$~xMu2It7(VYrW5v!qF$(9`&K!NBw$i_+8vN4V~o^JE|e`*E?D -zJr?K6Z4s6OpTozDpDOD>nX^VG#6v^uKAJp+;&l3+_II>m>nx-T&Z)1o-Eq#PIKkL^ -zicLvj*z9aFbv!2DMzBz}-Y0?T<;*yr^>tf6ZVU(^7b6Y}T4KA$EdtnmEbxAX0kLL% -z6LsGi5vdd3y2Q1{MzbhlNZ00t)hDOvC^NDo<_Q*;go}$F`8QwM`boI!C|R!fjp5Jo -z^TZAN#L3oxphK0E8Yk+d3|od)|46Cgp;3m_hWiq%<^J;lRI*w}3)#2ZF<9R3bKQEZ -zfaLgt#38~cE1#EI`2cUmURBj&J)m^ytsCNQ69&TxVscPbHx39mzTh90&Qg9`;2G@zd4oSX$)Kosup -z>wX^$vqc&vGPyG&{p;f$0OeaWm;ioS6|a -zWBkHWY3HOMXDQQ0W!n=zlYx7&PSL5y3>s#j&Y=-k)Ma)p$bH}Z1(k}P|e$-*~=RjwzOm`Z;%?`q6E(n)V3m>kn&qnQy9J -zOH|_$X(3olrC30pK2|^9p8U6c0bt8zGDD`P90%8wLu`6$kv>S1usM-0lQtLAHzvXE -zcLe~fcFnzs)4S -zVA@(;?Y2r{%=fB`R-Q=G^OVXA=ETGG&Ue8NDeSyH74F*!^ -z;*A`1b1qOh*L-8!4{2m1T$Z!=G*8XrDtPBmg_&0D`T36TzYP!WbX~i<=`VMkW8Lr$ -zFkqgi^aUMwu(EG6Ottt+g83xZc}Ip%Ki++%#Gz3Y=Lvt~14B2DD&2$xR2}V+v}GQE -zu%OPz`D#Ww!4UX*_cunD;dGsGWRG~Lct{6A<;f6*A~&joPZQ2(4wT3vhOx$1!BG?* -zoMBtQmiEg#l_8nuCa>^(^)Xz*E#+h_@-;IfS@vHTftCHZ#m_w^`t?zI{4SQ1)ATC$qGV?zmL9OgAbYehJ+j;#OQy|4Qg~dj&;Rqy1^0Sp%;Q -zAM5ITQZzrCprf-vs2+uFCsr2E_KYq?+e<30~!+L+NXF -zChDD?7^+K0TOF?$ -zoBg|xPmnGpIEe4Vr*B9F7;r>`ZnF$Rrkx|nq!Q!sjY*s`DokP&3!hBgny?o3#|bVU -ziW}?!GBO|u+Fuo%uCnCTF`N6}1np1JbzL4A?W0T%PZNIA@fi+v&fXDYD(AIt+8E@H -z735gYWvZ`q0#Eu-kC#|^^pX$Fcz*Lc!M~!95^ZmDU`jOj5nDtyzuad -z!j-d{#N{HXyr$eSq-Xp|<7({VP -zEsw*ciK%5{<;aV5^*9(}T`}b@SZIbMi3u+xY`YWM54j$PPyi-=EUaTwVj)Qo5Flb=zyuQG%)0Wk)UQ)O}pV1o8~oR-^8?+tww!k7trq3_PM$z4KOI( -zNtUAgGmDxt-(`Cqd^r~fiJ=;A`zI5gc8%<0=&*^)2M_TPDvXqT%!p4BS>L7vd-PO; -zz3w$`7TO~nG|eNR)Bf`1JtVscv$)uaV4Fy{mnYdT1=(fUQo%zfu9_VxyDcq9#;Q#G -zSmR(AmR^MK1@17xXW{iV(Sr{nhY81x0VmIUhE~ZoE%+>vGR!>~w*NG4;C%X!iR9`= -z^n_iz94y{}7|O*RQgy`rN)IqgDC%dz0UA$a7IuOHEw|`a7FEiPD55(LnMLE)5hK~t -zjQzE!o8I{8i|)UT8zfDj(e=ChOmfTAL#&k4_?1s60jbyum5}98K8cL+NrJkCac#oE -zw-@Llq7a;bJAza9F}bf6<6?>lWhy-NqNQ=xro7+ouu+8cQ~U7^&27Vz^dicGIv5;p -z(`<)+XJY6en8O@?8ArY;Thg)4Ds=A+KgaY5lidmO<_30oU@OP7uY?@Q+zvxz2Hs3) -zhom|Ned2rX{zjkA5wZ1kp{wsFhIzj}wEf(xt|LGFHY0TWX%8k=Gid1Cy)bRcwp15( -zlzlewMQkmM`DN3cZ+baz7OR@1&I4eVbIVbB3$U-wW{$qy$2|g)&EL2Pw0BfB^3%|d -z(Hl>m>u0|SQlm%l-%kmS5J@+Dc{#tbwR`KGgG*`wumpwq^uK9K>ooLNz_0{cnYTn( -zWa3IR1Ra%^Y~#`0p!1bFo>dg>cbG9xUUE2gX~TbCdHuF}kbq+dv1sNGZVWF`PbGt8 -z!?}#j?;nx$B-gnVn@jhru$)KP=;aN$dCeN)K0wA`v& -z`^<$7F&;h$OpfPlfiB>=n`#d#6_H*ljxfc)oRV^f}tM -z>HP{D9Bi`Sg~a(@%+;8$)DshmJ5d-yHxqps`S24Mt}o?Zi`9SPF4zTh!eYAzzBd-}e9+CKACRrD#e!^?m+K1=v=2NxFY7(o>()S9qC2z>RNnbWa+PVh;Vhk%nWNGRgE -z&y^034vD+y=^MMc8N@2)>2=}}jT>k9b0=0V4G5t;y>=1xVR^Ih -zl-x_1SN-YTjO!v}_7b|G3fTF^Rf&zp^qF;-Y;cIN@8z_*;v_A2xO!P{-4kR_V`FvZ -zm7;z!XFowWcikAK`>ClQkyA;2&K}{W6r8=B_C1eEWA92ND4V-S^gYy|*|Y~SM3J_K -zh<8Xy&q?w4NXGqV_{ODf2?j*mYftlXHBBAk4tJ12t7{sF-bFndPZZ{zz#Fm>^ODPx -zTwC@I>KMqr9~d}32h*5Qs&O{rh9|qzRt%}x@9_O8(+uM)&G4#ZLfFYE(6HkSjj)s= -zOGb7jc1GzbE6^8NbH0&*tdLx#Q?icmzHKh&Y`2zV$oSXjek^VxWpk}xjWl}e5CoZR -z=jGDJ-p~#l3FXhmu@|{T06>!`davJ|*;M2UI=Sz!XCF1B)!cwNQhAR@Q!Iaz1Sard -zYlO%*J^k^dEeMeBePuFh@YW?re;lb1w8r30*{xILStqB+3f@Vs8&a}3jl-#Q`XHf# -zvx0t;eh+-*qiJ=4#CDwzZSA8%m%Q3;*9==h+*n4->nBVH(V_M0;|)+U3U1t&mdf^U -z4Lr3uy!Q6$sj*~lQ35xJ0I9HmM^9MKO{yMlz&m~;%@<<+d7oQ-=5djg4Q%4C>ij@T -zUOjipOD4ZAYDH=@K4+Sg9eB>gX_*zdwD-bygv`IvLSHXFB5_sktcoSW_;uJkO)6(9 -zq<#nRZv%?ZX(J`CDwcfsl)-wA_f>B?H!a-6?CC355PcEvV@faJLPsq>kQY5r> -z=H$g*ld-}cvf0nbLp4B)(qi-*3!{Di{W$KeJGDc8GTqu2D -zw-2Wrmv0zXUWK1(X`y};Yjn) -zk;I;x8NkzaXI-^?CDRxFr=<|ZX!HY0{a9|?P3dhd}CWV(Zsgst;QMBr&}WFyZ$Rh -z?&UsRC;AD)*`hX-G^U#Ir{^62P@V|V9cZK2UHqGq1y=Whl-wdEL}hR~V5VA%X_}Ww -zc7P`iYR;2d4{KcRgGUc&X6mrFx%Xm_RX#}8o{Bh=W%)F-;QSeKTb(?qhwD_kPxaTm -zgO(sbZjb0hJCZ(qEWL}jRL_1ik4=Lp>=rlnK@Gr)$G1hwcK>;Cc60Q6D>JvVwh3GM -zdxC$s@O_!GxG#S7G;Ev(AV*a6`S$!pjHv4X)uSVv`_!q>o__eka78bR?gi?BQGDq1 -z&D83jLHyg~!tjXhGV1$75y!`$GzMgJWiOI$0zbj`DKd{XA+QujWH%o|y$R|M++9V#!7)d6h|aLcdD-cn!+2_{*1jtHvf=ZVM2+W(ahvuy#V;5y -z?Wa5Y&N*b|w_&Iq$Z8{Fe?Yn35FcT-uLD6#ks`0NMCn`%th{h&0zls|~n{KTZD20V86gd<1n1Kkz3cZ%@$*z*a>$5AB^o_T%hp$t^i!f*E3BY^bF-6b3 -z303uU%FC`xG2fMSl4JqMzstnO(z1_pcC&z($6h4MF8yqa`a!FuKiP54_!sxCSGI%L -z&%Qiy-w#E_e$TfVU*cOIg&PWHa>3w;)ZLY@1R_6U>-#f|f7@bU;N!kUHrw-7;Lzp* -z%(3tCllBlFjJ(=VN1wR=x<&Ae?$_#^B6$%>RJqaQ<2ZJU9HTS0n9>8Q(eN`~lQ;qS -z6?z^XGZJ -zu#2GG{y1a@rxs1>fbn^3n>-;C -zwIMQl1uM@?xVZ1o2yX2RQ&VjP5Q=i>!V(_^z -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 -zqXc_zS=N&D)Ali{Tdg6Z{z`Ibd -zH*(;W3UgtJ@%~406rY!h_^W;$wk46okXZyW4;+FkRJK%vg13$$hFS4trD~{lomyi* -zYiB{n87ep4P3^vHHnj_2mIhA4qEp4+3e=njzOD7s*81ZRB%DNXNe>nj7~a$Go}JIU -zU}|BfDA6vQ-fscrNZ-8Ddfa)su`aD#zg7BB62pQPmm@Q8Y8(UZn+uPF7Tu8s0}3`C^fw9TxA(x@XxH)yS;fF4!x` -zhH-=vTL_OAcE3jQ*la|jm%S&e35;zJ-wVuPgTtnU!FQumFXiU~g|A~7zFf}ETDwpH -zzR4u0c_(6_;Vi<)gGPvGgPt)8``FTSDe76%NMXVUJ?X+d_4*hdBRaF_HR0FRqI%=t -z4f_I@7GOR*b%b16IUAGa3fFipC@40gk(4(*mb9M`ci&X4*_5mHYggj8O~_{%e2^~- -zpy0o^_Fse^7S1_jef@0C%YYgwN6g;5Xx~kGK?qqlDaM6`gkE2-lk|En&7Zd1S>0^z -z{zQKk_PlS1>OFi@?q5Ka4L-)X!ocE4@?3rJ__5&{ERwH5dg@698`+EA(^zUF}K@5T~QNb`xy`neK}L${b1 -z={!d4r~A?kTsUKBGqQ5qSUuVHm8Ne)H}1uAi`kjZ@fZudhg!t+ghq3gjw{p)Wc$p@ -z`&fsP9e;$7aPZrnIdHGOs+UF;d~aSp-*&F_!|VExukd;>%!ZR5XjJ-klHOw?viSr7 -z0#d&9y{7lIsb2Z1tX>)mcE0B|%=fE*9n}7|c!5=oWVkZzsbuoc`IM6Wj5JGL$LV@l -zcUFyQN(v?J2_xlMLlwShegC_y3K9{YixiS!)51D)?TI$x%~nII?!E -z{Ya(4S86!lkCkIMkH0W7;A2)=*SY%D)c439k9n~t)Ot{OdHhR52~vYZV%1MJ3_1G) -zZ~U6|Yqcs5kyG!dlR`Ir+ZGV(zNWh;^vX2!jr!wF}>nQ>k?@9uw1!dNA+4azP}{iQkpIlIyQF!AGT8fQ0si -zM!b(o&_s)JPPHXJ?efVnJZQd_I@SQ^0)+<8BO>LG@dZrhQKEq2RquhzxlABk{+_JR -z7UBdvq7t$qd`tSXwO+WIe2VQ-L~!;%+2*38R33xZ3icBQWs -z^&X8QNn|wl3Tpe@*pBTxYSeH|4PX~nZ)9{@MYFK%>0RZ_@LN~g81XxH*!Nq$^)}o+ -z3ihgwCik5D3{f^PKgGom!}rK1D**JMBW0h~#7FuJ4orWmPR;l1U8BM1y$Fek;;mgm -z65-rb(FSsRfqw~1{6nl#IFZcj(Q;7l1WWIKM#~`_$ZD -zi;L*0PMRy*lkMkF!DqzX``Tl**BIM%>QaEo7gcBR8*@i?xdUalK!okQ9(i9|S#`x} -zJ6n5ktGd@WH})K)4cM{Q7UhPt`sinLJrDVbFg*g9;o5xYP{|?Qvbe7y12$iAzi~x7 -z#qhz_yr02Ly`dfyt5_YeMG0C;pseMnR9iVT|9vY_K&2NbD_Rd4Pc-cKZ -z`z9T`jV-))h2zTXX)`c6AuS*P{GA6!KIWqvP-`~VjmFJ#3a(DG?B`*_GCtsP@H-lM -z(0u6uoQ -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 -z -z+~=%W#6ttE6|LWNiPh&=XjLYAsrhE_x6PmY+pGMy6{O(z{xlJ)x^FOxh1m4i>zV(Y -ziJ?~fW}F>!KeLeL3pM>sfMb7hD^q8j8`gd4&*~&$McOSofEvjV4!4rC4ozCgY5PXB -zBTkFanMZXpE4BLJ|5^U526*Ig-wx+H{Q0-07kjeCgEf^c6pm7N@`J*>Ei|>n58c{9 -z1=6{-OLg3-0OnZB6)z?Ua;bs0SWt^$UUT1cWbNmGm -z?1=iXykEH8n52j)>45cO6~Ebt@l#gB_zlWjX(Q&YrMcdZdoJNQ2TJe=PxP50ORgl* -z`rNAT?R~Uf=^`PV3Np3G1X85(j0w+?sl1(eo4VZU-qrk*HF^vo&KVCj-HvvO4qxSl -zZ(yTr2g(4ok(kb_QD>d^Bz}OYWs}#`Z&ylPfA=E}_2>4{!bAG%zr4(Q3Cev8IAVRk -z_VY42?sqjlqH)IW74vO>h(P(9D}_|6xwF4MvC$0py6f~c1hMb)-`^Yfp~)>q-(lJbO;3_b+XtoOh-Wr(8I^BNX0r2?)? -zmxvIboUtO5jqUaWm-uN!2ps^s&A3I~-9U)d1TO;K)h!rb)UzzHbVDrS_NUyR -zo#h?{-0(Q^_@@E_rKON|;-@p>Zy(S5$Q=$JrtW&=uU632`|Le7^G}D}K8kf05bi?1 -zi>r{reGh^z+tM1>BR4^Xr3Eqsnp(a|8dlKZg>s4d)q@wwwY*nw$VKuS?9}C|qD{{! -z<@e~MFWW98Cy)~5=8)<+z{RdCfv?FO%55j?Yo3UDa=9K?o_U#;U0w%AkCS1; -z7V;-{No?YdfmVWrXJIeG;+5Qn_Zid9Jaau<9~M_0W;d9V8Zq^vzOUZ$H83eFr15*A -zW8>->^)ng3X|Oi)`O@eC%b<;|xvqFuzr)rA%!$+GgoryEM#RLyW_QoxN}Ud5@{$rW -zVo7l`h;J%dbh4uSy29A(jiGl*?L5Jr4TdHFfd}wSV7 -zk*?kz6M2|K7HTe4li_H54;+O1|Hz9lTl$^Fn|WSh(VVkds(*!9kIs&LgH3 -z_O5Fm{ZhS%XdL-6Ls51mZarlVdTC;U~+_8A$o30T>$-eXG -zTu*Y&!qp{HrI<^J)o5rMf2!(dKF0_1d)N~MhQ9%a1gi(l)&U=otd^*6Y`yj{`ul&m -zLWEpYLZ1EE8}TLwWu1FWS8zTVm&XNw9`o+n9KNP<*mjxq^5KiGaq$&5UVaVw3aijn -zzY~9}uJTKK7k-Dg?qmHCiJJE`~RL$|{dk$^)?#kyLXdXtL`dHPvrK*q1(9z;tn>n&QRFzPl3nq(oF5LSpqcn -z4w3-eGj!yj@S)9%iX#1qeZ-#mM36DojuBZ`zj6}i?i?Dge%(m|1ZT;%`8uKM7Yioc -zcn8bi;hA&Y`!(2J>4{fl00>BrKja&kk0h|i-8v7BRRg6SvUSfsZ5S^;^d25yo%`s8 -zM_;B3)KMwAecSzb`1QJmL6x9i=9BCYL` -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 -zJPP|Ny-_fUE=|GL`VWow$D5IK>H&a`yI>N -zwifKTboGpwerF=25(qY#L5yXC`X1SCbqH^?{Tb{e^tI!Xx>!t65sYmfY-C6nj3Azm%@fE6k$iQMz~c6K|d_N}18*;jvVck;$1a@)s;JQI0_ -zx8wTX8uP#&sd~M|UYe$Omu3Yiwa-2Ly@D`R&hb|Y4^qB}%(BzPvLIpSw#2Ddt(O(* -zqO@GQY<%&uA@;(%B?^ZcE%55Cqdi-5_q@snM&T1y-j)IJ?nUqoJKxLpIY;{BoYIxv -zd)>Y_pOC_8+}&`4&Oud-@1+er$hcm|^yE1=?vXKi-Kz#~4!---TfryylZ-V5$(zR$ -zmD9tE<~{VYFMw0<?_m$aKPhT-6zGI);=Tgz&r(*W1&}Yx;_rhr2P3VLK -z;5OFrQ={vvbvzy(V$GL*G`}71e^#E@E=Q(*JnguO+#o$wXm$H4?#VIgl({!T{`n?L -z4jil`-_7>BujlRxIq-LeHq3k~ZfYx}`C~Nv7%NlX5khC{qakxRbn1?{_@^*^?%lZW -zp_~LdXPSH10_UF77ciqk=ne^d$B^Chok*{W6~`=dSRROZ7WA=oqnZCWkO$>SQQrVy*S8oX&l0Ju4?AK0*rO|AxY+4VtIw7kP9g0JR&m8*nOa`fcdEJLoT+1gR!vE -zkU}aup!FC_$UYn$nr+}nC`bm4bQ(|34b!;riOumtMs_~eko;)UdzQUd{0IbXZNn`c -z+R}3*9^2LPI?RNf&&>FqTv||k;6SavwesrEnf&wio852eRWPm0^1j>ETbc5SfbQ|r -zw>kVeH6liu33@b?`Q=iNpKMq2oaK;+X>i8e(to%1((VY -z$#*|puQh@X=MlQ>k9>1ecHh2vq7&<&IjPx|ha8h#FHjqH^Ji>5;-9-fOb+DdptCQH -zk{`FwD3u&=J0n+Uua#I%;q`Hsjqu$CjmR?+} -zL#Ch5I1lXKFUhTS552U;nAb|AAiVtGo>!9>Kh-*vYAkm}UlSV$xf4uHVcLUgwgG)Q;$D2IGw%F=uJxJ)|3}!FBuSFnQ1nWe2m(ut -z_dk-1UcC%iE~J*)va%xRB=9~Rz&AhYiI>JNvMKCs-Fcm5w~*OIpJ@_x2|JsWOzjHg*sbI%R)i$<=Cp9EmW -zGem@zHl$-nl5xL!o7y=mbUQX2=GtdgjPgL~JQZj&qsQ~eOS~8s0Y-*NZJ)EMz&miE -zhIM635?3Eq@wDeblSY`-C#tW#M;As?yfBDQA4}AtQ~A~F=wAcW+&i>}fqCY1KNcPE -zo}=`=?Z1$PKs+#==75u4wQ0z#I;+rAOD|BoxbXD4@q~af+c%!NU5d}12IzA?LvrX% -zJ_p23-qS>U1mH<5HTi}nQPEzcN5FE=H*_UsSs6=TysU88uUhxW4R`cgOq(y@!shK+ -zr5CxJGhu_(33EolL;Kc)GmT8LJ4sIPP4ybrlil-nB!u9>_xOQ*o|2fw;O>q}Vi75#!-jhTDYxy|H4h?+$0q5340ovC>i%03~QC&DM -zJS9rD-DWr%wsG2hlu(%>BIgpLdBWK3di26g9x@!YG~sx{o&=k|91Aa4pOCSH_x11;Mr*GP&Gb(k@ -zGz6diJU%X6Yg9M!2h+QNN8y17XrUTiZP$o!oUAP^wXa0csCu!!F5pZJE^t`BQK4|g -z=f2SKlYV~N!@UPVZCl%qool!7zRitzFL)mAr_(9;A>=+D^R)A4`q)knc4=~AxTBVT9R9#E)+MXYN&eoZ8R -zvLj#i;*ImxEGxQwx|e$10b@_teKMBnX$D@^I^SipJawIC`NF=n=KS8z(C75bF7h<^ -zVSSPU0NKBRYdZCg!8dTn;=Db5JsC8Ftc%VQ6FN9(p8>L8RFNmzR=zUaE*}BchODZ}Slp>m_^PVuSB(;p6{H -z%})c!{pNI@Bh}7m?_dSPV=SG4b3^9bs!DYWdE6z4%h-quD)eB`K$YgHHMceUx?c{x -z^y48_wj3ZsykFbO3s_wD8?xrk*Qk#r-8BG#ZWp;H>;y{Ibt+BMPxT$INTw_DO$HZp -z2zHt=dEw`6b8>XgJNa8PSgTGZLe#>oo<8>;I}h!6CC}wh)uP7XQp8@D@;c~U!-!DK -z6Y6&h{d{jQ9bW){`teLYp~W2HgU63gGKkl0(o?By**n}SbcUd7^r0vXY_X^lh0wi) -zl^8w8&Gap_E;PUu=R5YzFcQiWh*%|2t!KZ+BG3y@FJnRZ3|E|QMB}}}jf^v!?+>$z -zCS&--=Y`AAKO@j@N4aq2;xRwF=bOX&jXHya)`o(#cF)FvL-+y3nJ9+>`ICa`0#MM@ -zG;5*<_eD`z(>SCJOW{;;b%);r21R|Dk4_QsH@X0)IP>Jw0T2iM*foEF+_r*#)CyT_aS`->hxoLt;74ldJ-<>IS$p5Vk);H -zT14bPU?>dM6DD>=Pf>h>kWS)3(W^JLYvKXaq~*mc2s0UpFZ>B^X5i|PxX79pE}qMb -znjCjd)|!)7q3GG|Ij8r^+k2okiG8IYkpwLdfanIH->*@l8qeJ33-lE81M=G5e{WiZ -znR2x9Wx)*_r3T=3AYs1vC{F8mGp?=kscBevpI&ur#6)bAlGDvgB8+ -zw05jVzVY$fv6Se7jA?R?hg)oa+aU2jhabQZlz770R$FX@zP8W+{jy30Rvaw{c7f0I -z(M-sR3cqW#y#UacV7dh&hG7{XvPL#e@Z-`K?D*ckSMUAC3_%AQGuYc-!o&H_(Z5lV -zEklZv$W($rFB6jVH3Yy%4v2K=<$!}X03Ta|-@ZqPxs99Y$>GP3%S&|RmN4PV@=uf- -zzx?_l`#mb{LVfS5Oo+jK`GP)M>9-D6pGlFwq;RTz6pF}4uAZ_icLuRAoRs#si;FuV -z9$AG|Cr|AG=ogq?uGfd3r37|JJobhH-LHropHjmE@}dH#%u@n_QpdJ1(63Lr^8=UC -zNRIWJ9=EJq`m6uOpB}kC@1KDKP0bRa3Z~aMdLc{TicB -zin=@AiH>sfvrI8PTzL-QY{FNk5>`dAN0sK~=O#+TX -zl5oHLnGpcj6&RYX(E=)u9VQEi0QD0FbIVHui!t#*z0&9tA}i*GsS+$VWm7}yBJ -z<(~VvQKAF{B<@ORDWaaoX9#(7g9QOsXxcB -z_l$2pG%v9CuN{v(*j?Fe9fGO60E1?8h?AXR_>{RrY&40~L`ij07b}E|15#n4?yKQ?nidG?6T8cBY|6S4J)Bgvv@^WD!fP}ud++Fr^>3yFd -z<$OFJHWyB^sWg`C07;-vpUp=nodLyPL77n-lWO~8wo&X(gxfX{dG2RBwR7x##m5&P -z0+4|14G$ti*E)5h6s6Lw>WMAfGu78wZV0wtR(Kykj~d2P=yR>^UXSi-d4R1wx2HL= -zcX8j6fW`o?xK>=iddcc%6#97+ZL)bV58mFV@T&4O5UnlQX9tf!OfAF&`;{H$RI%~N -zzn$*3dZLY%y?Sfby)YwFuY4BMBvHpjMT665^6A^&?1O5;i)Y=i%^I5ur-jb#x68JFm}{tlb-Bi3r0AnJ`40X&hk_R<>fy0HLj7sc>&c#8auigZu99qZ3ib~ztR1` -zX@KWJKiwyT`y1%;*kP|}v+U6WJC}#mAuPV$NH|W1yE!t?#;qf@I`^udCJ8CY)ooV0Uuk*i! -z&GsvNKe%6G$5Zi#eRvmzmtFGYm40A+#x-tm1KBpp>f>^pd?BFgD^n+t8{Zprim~bZ -z-iv3pJxwiY@947~xQ8LXBCg=9Dea!DdD7?`iiuWU6qe2!!dR9_xZ$q5o^fgpk(;Jo -zi!J%=k5vmQmM(cKft8#~meergvR`)dA6Ot2y-A;pX+Ejzr{Ble!W^$q1^g(EjuN)7R$t+})w -z8(F&V)A1cl3Ie7V!tnS#G5JXP>k<$GlB?IgYHY#oS|K_182fG59=Hq?FkSSvxvbj9 -zAI6sguXlCR>|S$}m<@3%II#;Hr-C0htRhB{JdN{yPZ=PbODmuclQA<){KdUTZQqPo -zIkF0USHQ6$B#SDvZt`H=u1k8nSL4Fd(%H#hGRqxhe=P$uzeS~F86l(-ZR_LHf@TmNDkc|>vH0{IOx2Ma!ZEn5|zI;uEKQ^!iB1Kn)c -z8;S2RQ$=THg0Ecedu@iKfj~s9MLih`an7WkE3xl;L_VN8YRbb0%*}2o+fikz1!;q$MbMs?XD9Wd||qt!)saw5U_3+$owoR!j#u -z;pVNqogYa>Ui8N)bAiqpoC^9(18(dT!Oy#)-|l!lwwSyTk{9HOhNE1ZHph()SHaP2zc>v9Hg?TLX9MD`301Xo871kW}-m({~Hin(Hca__JKB1KTcdKUe3= -zqp)xgc9tWjZ%P&8VHtZ+(*T>usESV&Fei!o(ZQo9=h7T8o-Um;4qxwk(ttT0Xim-x -zyURou83%d;DTu@hR9?>F3$!IloAmZ{Z0A>>JiYj2!-=^1@E4k~G#OBS*i=b(Krv#)vW04o3ks^D98 -z>N>Vl(c$5PLZ>6Y0j?8(TySQ&RS&=LO0KEy)xk(Z(Tg&@33+T7C<}1pC<~T2P#Jtd(aiqK3s=(pN;T5a&n5UWs -zu$a&mW>2sFR_ -z17JYUX%NG>O)s7tYv-8%IynFC)wsb!wO66_-bi_AChHoLgpH7?4i$=l-4{6?Fraw9 -zvs}gdnWr!S9OHH^g{LA@`Cfb&bx%U);{Xcxcx#CFrIg?s9d!kxz4lV>i(F@qF^A%EH$(C^8- -zFCtvIqv*5I(&uf}unj{CSjm@j{fdyoJzoRB0E)0y&D^`IE_dg}Dm{$({=61=8Rw-@;3X4qtILzNxgiLVJZm&N4${5!zXBzOScriL5AQc2j)oes7;B5$7``-l&W# -z&}Q!3b#JdfH8^!7v|}0N^WXjE`ywpOEEPZgWss#gdbC$X=bWdaaU>}t_$|S;b1R7L -z?m-RcF$GxsyszM#P9(zkDh`H5;;Ci?N`;)!8%K@~3>C}?2%5*h!O@6$n4cOK%~E*U -z&>G3N)OE!c&Vr*ja?8nn4;DmUW<1|S94Q&h`KFd#ee2WqHF+I2{^c@3zdiW!Dd+KB -z^r0lKxgGTQ?KaPuy7d{xS`fvQ>pfwnd~HzX@^q~ -z#wQONGTrOaNrNc>_t8t6hqyHfMMT)<0evEvV&w!@gH)2G>-3sP1mC)~Pt~xqa>P7@ -z87-W{x7OxZ5j@H|Hv-hIKLnf*b=ID34Sic%Bhv>LBo)an!rt>3c2zDYzC0LF^`eWf -z3<4Ox(=NCI8`<OVHwo4}{23Pef|JlvSI$ZaRpj+Q`-&7AHlICMfm& -zyzO7Eu*(O0C&&l}59pMr0Oe5>kQ_?cg0Ndm<>}>VFBxZ_dk!P-!!^e`jX0#+=cb+z>RHZ7xMkLexB4Y% -zK5?&j`c2%219hjlDFWlkkH?Lq%l+luD)hkRCp+`eWWxlSN}X`W3c|WnsN9g6@lD>e -z*}4%gE@f#mpHZ?y(H+TVj1eGRLh>Z*V8t0o>hP&Ld@Rg-;xnJ=&BN9Xuu+eip4cNp -zIZs`cL{JVZ>p9a}RdSoSDgs_Mg)dSLmEKR)mA#aYjTL(X3uuz-L1UtMya+wxkHzp1 -zKka~U5|~k*T6mE4=xp+Q)4&4xc;!o(c|Q*&l+W7|qG@CkDDWB#OQ-41a5giK1v{1pXnNYJ=vxw&eZ|>Mk&yD(eP(PdemoN(-h@$ -zYz=^F@sg{Sbu19b+i=raYj>OREaSvAtjp)6e9zH%oV2&UNgM!vp(XV)u0!8b0bfgS -zk1(`_eD96lgL$D(v$mMOnv)tEw73ulhV%MKdrFPza{4^3vG)9M>c1MjmjLv9jNZ!9FHaQIB-8bJxeUDk9E}cnnc*m0#dh0D>nn$Ud)qARQpU}d$ -zX~po0J%Kis5s{z0XxgLMCqczaMxg)zZ7LO;s_C?u;Ac6JpI=s8sCyk(*Iq2ZJUg&t -z-AySI^8)22l||Z_xq;si$T=qYw*8F{1Uex -zzK%8-rIQxljVgL|!}2$=?JaG`=}EPTui@vdr%uWC;~Dz~7D)0zdLl_A?%q0j4-;Q) -zzZi2s^aXq@d$Q0!)8!Y`CEmJ=#^noq=_``YM@mTZC=hM0E6t+_wpk2SPgPE4tz?pE -z11pZ*p=CcPIn}52$i-83mghXh??7I-$GjT)yj%}hFCN1%vT{;?OW1Bo^|7g0bpC}0sV4A?v=?oYOhTF+;5b|CR+eG@U^ -zb2CxSOPY3wZk&y_+?N*TY65+;TKD!-t=!&hWkyf_>A5@SxW0#T?^CX{E2!}ep_id~ -zLZeQKhsCfRjKtp_IrM*={*XeOoJQ|d(!Mj5`;_fxa~k)E$$q0=ALLNNH=MJ&h1pA! -zW@L{18Iw%8TMi2i#tN<)6|&8|aOBEhiGDfx3e@Cyk-N8`L&B-6{Qlmj=v-(SKek57 -zrMz$!U#j~Ca?ioBm$1%m1HLscT860&qtdU(ID%QDV(QqwwAHfmd76GH5+WHm8sIW( -zo<|YpqkP7xZov}OOUmMzauw&AZV$|Td}g0BEhWD|irRA+=5BAKoF+s~M!pFdnpr16 -z-v2*0>74-43yl5brvZIgcOf{dlUQ2j>-5aNdspTglrH^_gWLz;G^%@B&b(mn5nrFv -z(OA8GgSyqViLqaH^gKg&XC)jlNKy)rqV?jTdf1R_CwF`H8zDfRvG<8=T7b_tA4AIJ -z8(9-&GEeh(le&$n@#O#v8k=5)^}21GA$aEfZnFYI3K8%)GXzg_KJ_-7Cs@te&Nr{7 -z4{F)Hdqga?`m1#56*&O*>Dz+};7WXFi(YD@K_!0_uBxnnD)(WH_=yKpZ;gS=pshbU -z(agMWi#OGQx^8z2fTKW&zR`qlk2N{NIu{Br8Ax|03m?ZC#CLdeTHp(|aLFdmJ?hf3 -zN_poxd_$t)1cSOF91I}z4e_C`CS~k?ZWc9OUh#GKcP#++l0MQE1Ls<>nd4NdP1()Y -zztRV%d>&*f*>N+bywKq456d_Tb;%fc``PrMz#M8+IuL(WMejrVQ#;2(%ZU -zS@_8gpmP=dPCca;D9&vwn}3oLo=oVs7Iyje%b|zI7vRuz9=a5I*VvRl&*8jo6^?!b -z4g&kz97LnL{t?ttj-2C1U(&oF8-ie~0G%Y)fG*NBsqHs&As&r1AS%hZ_OyPE=Rus2 -z_}r=QtOv0SqT;GMLUTdgmq9xv=k0A$2qP>lQUSMFIzn}3rA+PUf+!rj{F`K{nJ+imszOCkT%vGjSx&A(0gOrcxKx6Bp**9!^#ZRFns= -zw!K8Ik{P#My!^^2@(Sju!Bo5H*f~>^sxcW>W7j=dOxo$3K40NxCt$n6#YeTaVRZs+ -zcI6K9w?|W$J^bPfIsr)SIXm3q5 -z5`6_~_V(sugIx=D$6=>O)&;zJ^D*FYVrqcuW5|%nIZk{A%kQ_L}ogvEQU8CUjM>;OgF& -zj3P+71ZxhElPrU!KUS~KaqFAd@`ZA@!jpFXeS -z@0j1C>^5BkZ%616f>UQ-}T6_+c79I%FB#!CEIo<(1xq~I+PE%xL0R*}T8k~O`NK2Q)t@7r#T!-oWC`v}Q< -zuJvpBBLDUuypa(|Qxuow>Xi`@6o`RMJ>Fo0j|!*SS|`ToY`g%bXSsmEhFnC`=5LSp -z&)4tXD+wOHx%nQ+BiBY-$FD&?K{Y4#z=h^(@EJ?kPEJ6)eA=<4E;fZ5uKQW!EH^$} -z;MqCk^5TAxDbsdO$3eJ0o)xEXcKqzstd`?!tm&oF_Vmp(P&8bnPaxvng@nsC@Y2LL -zC9R{Fkksm0%WXT%4%=;undINhWp!3~r^EF@Wy{Vtq!tX-+4`tZ+Ff9g9YOmhqE~>b -zaOeXIr>_|3w)WmYWj+TMu0Anw?^hpks7x;}Z)>?hYxX;?DGzUliTZ_<+kwW8P%Bx@ -zqEh{t`I7NmC%|(!7dU}zM^{YA53lJdMX;>V`{ZJt16+?2eC=izBkavlybb+Ppf -zYOH^qAO}rNa=#fm1ofd~ANuNhvK6ldFnP;o*01Lt@#>nsQ|m?V;|RKNZ1s6$f8UQR -zt2{;SpT$9@?IPtpF1uH4W3~Id9_HDDV=IC>o{PWU#0rMS@6AQTa#ykiJ@+Oziu;Dvzi@3nk39<;QoAJQ0rKFt` -zzuvY-e`b;Kv;g@a(QH@h{ESRLZ@bIh!n@Pe>uIs_@^)p^l5sl7KD~q$b>107H}KWd -z$KbZ;B~F45bBi;Fpl=H|k;?)x>*YRuXAU*j|1Bj(CRs+fHemC3*fbXbG -zoLhC4L66qaP+hXIr$)}(DN95Gi0Bxf|0+Ka#4qZiuv1>i%~G&qbJ63QiZ)ru=hEqM -z#n~H%kq$M2P6#(ng-Jx_wxeft8eMq&;q%RskRlpn2wV_-+Uth=d$p3%u`$fIa63=F -z96rf}7o?7zR;J3l0mA?0K5Et8bB`U(^MvR)1>2>iJk8~DURLL~U~=EKx^8b#&3Np< -zu@iS=2q5I9+HS@iNxa0?52H4yoUgdhAwDK;XHo3J5F21o%YI}`f36SeQ=))?c=e-SFT{&miICx=U4Ia -z@HucI{E&Id%Rlq*>p))4Cwrq&Bj^Nn`)PxK#c$N#H(_tl4)`%gvqsbGbpLu(1cf+b -z9|94=^mn+e)kM^N;Rc({Jh^I}VSsdXwJGAd9{94e6Gy5jK?lwwN0IBW{@KQ8@VTBI -zZ`0$$^{~-lna@-B1hei(nL(hZb%g$J_I?&l9Ya#(S^jCZ4z9xxQKWw<>QLmt8lK -zhT3n;CdX7AbSB-6%)Zl8ts_`5E=bu~Wr -zuC|xb9{OtdrBg`J#FA!r`;pG~9_ql&Ix2g7XdrCI{B6GoK0;4m0X3$tEq?=i%M}J6 -z;>wOnpH)H~6?9*2)g8&E@8%>Q(IlIrio0bGnrzNK_8^=Fvw>6a(rCejhfT -z%JO%#@-8kv%$Y~WZ>jT~=)jkFisFeneKBA(IKyweMT$#w0oCC%qr2Y_<>WQawbN(N -zBT-;!cOH7cqI+KV<9=sKIQ=PTz&6XyohHlw~66$U%ii1)mN_c>Yj4@b8_w(6QM>YTQ<|_VLfAg6{-;%)CRWbuqqrWXV42 -zzj{mfw<{vQ^!NTN#8PQS_=qmvl6gYY9*Q=$_&R)^jgrP*G&(1n@CY<{#&@|q3?A|~ -zJ*n2A!00;;mP_zvvQ+X2>3D^ERT2xlx) -zj2}5&-Eaa~e?ssq9+-%3XUx;)XPyG1Z#fyZ-SNw}vbP?f0t-J93Y$|+w|3CqpIpfn -zIN^;(^H|)262MDsR<2u!y6R_b`$$enw;P^ff|(~XA-NOme)becwjb4BbdR^89rn8B -z&ZS<2do&YaKA*=>hLdU<Oqi^Rs5qoVM;d -zkn#=c^WsLAd!EFLxw?f2=j(pH$ndg>4_l@t6 -zHJ6GsPMNLm;6(^MWj4O -zTS+YY)J0mkQ^QMs7^Gg!&3l;_3^X1d6vO8*8R7TClx7`^1oXaR%ytgBPkz&U57H)) -z_Vr7oVv2|H{gA16G1dq(*k_F9KK-e{vsI_c&l75xGp+Oz4)^<9_bHH3fwUqB{JgG? -zu%|DdRyf=lqDf0nWEzg2OP3&5m;9#tNW6ACs0AOnH+>l{)R`$`v>EeKjE#* -zvs0Q(d2F)SwkR|m`M8Gt{kHCjdk;Xv!IKlBVXlMG-=#hW~ -zYR$I_tNc#y$w$Y{_Y{!flNa30-+3OOh6BgO?&E)s6-o{H_oZb1W?DhR0V|aGjl4<;DnUrd!=Ja?G`*)50D4 -z^IUmsAwxj(U2rn@i%~G)Pbq|58NJI_#lrjvvwJ+SQ#W+`6v{n%*!DrD==;V6seU=` -zaVo0?aBP-~SH{|pJeB!%|JCp}}_69DHifmY%ze1`@wLuJ+EPPWLUPK@2kg1LG3%vjgyMoSdSdgQzCz4LX6 -zU7AjwQ7DU$&$Ok5gqh?8$dvQ}sOsr^>3nv&5q(7s%^>RPNy34b&HWsXn*BtU#+?iA -zu{kQ&*M_vDUzr7WD^CgiHBbn;yBCaDpBZ#A)3p8 -z#(ZpD&F86!ga)s0CvjkYkwx~azIl2*4dAJ*P7}wkKlc0F;3=9>FJOt@+ms{5VFo;G-Zy#gzKT7 -zC-}Nf2W>#n7GCWaJVHC>mOr7Acr#vzk%RKnH1_RP1;ta_)f| -zqynYOoP9YjDjU*l%c0$p>b5zG=&tj<0gGcKbz&qkkH=H30!P{Ph;gb4-^96xADn3< -zW8~YJ$FS<*cwDW$6npzXDKe`!3U=@gN$K$L1nvxk>sf-n -zpHI$)G`)#L+T;ASkB-f;%MGqwA`Sg^oD*u-F%F5Rnf3^OElAM-B-5veXEbYl1&lA7 -z9u(tozFv;N2j<>uk2v&d@_wm-Z)QXnK`#hZSN7ND{5Z0Dg%c4?sFXU+R%m#3?c$`Hzw+Or&I0=OOy%s`<|{xjWi^3A))T%tso -z%lA6zpww)R9sgX#wB|IsHWUFe6FwLPwR;%fE;>O6Tg|L0cwK6|O{wIZ#5pJ#H0slY -zy0^oH$a0<@JMUR5Eqowz$LkpPt_1ki_`6@_v&j5*+dX#ByEu9Ob5dc^ -zkuvBremqcp*bul8;o`L2u2s5kQJ*KHCpFz+?Yp9gOc|xnc2a2nnjC$_ZO`_Xs{B^? -zmorvu*W%<#bb|_kbUsp1c{G{sUypIU`8ZFE(th#8A!*;~-zY;~L)v~?^pVZ?tLf!} -z^R$P9a>L?z5ApsxZgdCY>q5d2-?_f3g$;4HZ*-a{HmJh3sCY4{e#h~7Txft2^Wqoi -z>grhMVO`yaF86fZK1ZVj;lqyeh!id5ZICqGSvzR&55uuW1dlVeijWeEe8#)I@<&fD -z=c0dg -z>TKT2w;2pb9}MxIsXW@zX~47Lsv5Pc#`sE(M}nR2(w!E4J%Cwgq>pA7F!uup#TFBi -zFOZQO%8oJ)++Qg5JKgaWi1?^$izDHyZ?ph(zHFH{59`TQy~;piY}E9yU|;b&S!>j% -zN#DAl^jzo2_j{iI?9cpirEetHrDlxEH=!dT;W(=k -z(e?ty@7`q5;{%_Gzuys)WvnoH1V!37Cwt%&5$XB*=;S^jd)4O${wY&8H;Q5)QTIYs>$O)7o}Rx8uQY_f0@h( -z)apHPh-eqpvJl^T{|d-sLWy5k|BO7bVB=)qDUV4ZAN6wHGclxh1?%`*NpR%M_zKE( -zKEQ_r0&Xi?S_iq|V~u;6k^KSH#TWqcCnw@tAQtbqI_9caYGy``AEeO=+fb1mRUmh8N+qf -z`H}%u4}SMt^h*J`ZoLJcKj+-<8gmSU0b+EqGbWe=ia*VbP{0CDVt&bBSH5$1EwRt( -z>R8Ho+VOn;7X>4v-%UG>C7B>EpQ2qs7$&-(yWgQNnFa3A@*6jxY~xY$lp~maf#S;$ -zA6p|bh%25#cxh_FiKb-pJ{bVWc0jxH>MiCFsyznll|?>xx1jSN@@r?0(bL1iO% -z*Z3jVtf0o#>SMLc^7TO2!d#@*(gjv@o5-TB(YCJ(Q;^;){1d5c)B%ok9PoQzshJc$ -zZ@Zj3pS1$x7yG+7W>3&q?~@guIXh3B26>CQ02=O~KP4FNsXn)Cv?OQ?O1)OQE$G|S -z+T0eUN%uVVL!B4$T(s*@Z{2xcgAr*0`%dIEDn<4J27#$_ofh7XkU@?>GJu0v_yn?l -zaXX}_G*$9HO77}aKu6q($t1<&k3OCj4Q6eO#^?UQl)bj+zj{ -zcgv88w(zLh+xWUSaQ_7|I&)hwv^ -zK88mho8Br{={fkssrOZ%BO2j(w{A%F>1=J-l3Nt@1xS1LeUp<;!B5G%X@P!SN~0Rh -zqErPxJyP!P1j)x!jB@l`Iwt3Vo);NrFz73JTLu|lTPK&aDyl!S-UJzzvuakITuX9Z -z$$`=ph-rTHqW|gn9qngXw|4V$B9KZq6K6O%M6w3&_h_#!t6yI`_PBf}jZl~Fwetvj -ziq)c$+6f8Xy^zqX*9k{KNskhaIpi^#x59~_QCBy{Bn;Kw8at5QWcNh-#*|)r3&|t` -z-Gy)AJSB+tPGH03)8jj_p|WZIt>bvy=`D+UcU?W0- -zNVsP5*qI4kqg(QQUdDR0L*=BmTI=CdOPmIBJL6;C@&(5D=W^(n9)*VT7Cp3+oYOWu -zZ`-qH4An|eT)TYJ&*P#`A)(m=tMhHGslLIKs3^g_Q|IeERo+KWXCvKwmAeiB-nS*M -zyEpK;1eXBc1`-7qk3Q`hV&5H0)=)C&i&>RDQ)l$8ZJHPpW-2WGM#Q# -z#r?h`-oQD^?)Jn#K*)I|USNZ5%BOemcm=qA|HKzOF;>NeqiAKO4jSzJgJPv7Im^)L8&Z%Z*n;_WRF -zKKNcIulpGZbN7cST89n?RiuNdWQv@P8H>7SJAZZ}(C^Gi9pJ|F38e}-``HI<TsM;<$#eK%vX<&y-5bLnq%p!YsJ`-3A_` -zFTd|j9_y!_4Jrf;*txH#eH|JFyk1SGojUp)63=}T_T{dYkQX0F*0^_R@_OjDii$r? -zdDbXv-MAzw(O~FpJf037!&?`|X$gj(;y&Vbp0d1oe2MIc>Q~fED}dgk;(HU#_Sx$m -zcaQCpdt>5J`t)b=<%{X6UoyU=J<^hUMPp6RY00;wwyTII>2O~i4{u%19c0i=&R|3? -z#RsAorFJdP{&qG&)*{HsoGOM0>Ou{f*uwC<$`* -z;UiB0uDIK)+&fkGynnA$jexI#e3mi$D4c`IeXk(WRcbR7!Q)*g!Oz><}INLQPPF`AZ*@?Gu>O#GZUM@N-=7v?rm5PS`ju -z9rudN86Vw#baap8ZGJ$l*|Gf!grev1BxRzEyZ3=o&(`gkTmAS>zWRQ7Z}g>>0Xcl< -zv*bvwY}(4K?_8Of5Mmz_k~ziv*{4vIgZ3LvYuc~nw%^7-u?e@dK1X$##%W>cqRv99;?vv -z=(nnq|3s^wU(`JiJcq8r&E|)uJiZ+w^?1JBiekB`Dv`d|_71JiB6=m!XPlKm2WAuV -z5yGkQ$1FcTWQMYT_IdUh5});yh?h< -zHVMobE;x$_lqxxu3dVfO*8dmsy}XBNYsi0*Saj#0Be-0`7d*^n94 -z3-@C3skn{VNBp}aQDUM`9J*fTDh7JAWPOF)zi4$NO-iKhJ -zkE_kwP&j$%RZwMnh-dn6_3C(+cMz@MCSVc3QCDN%~30H-uKiZ|7WPj%w;8* -zqgQTv<=1=LdG38%VOOyBoaK -zY!;skvqvJV@Wws;_-J%B)R*jd?L79M_wevT6Yu)vzCyoqEz1`3>vBC0AorD?$u7j` -z{Vw1*f6dk_SMl6IyP0)SOzn)CwpgQ8-3RTA`_yrSvEHi5#aA%#pQnK^G2F{Uk3;M3 -zxo#|MYMh*(m1cAI-pL!V^LbgHIa&vlwimj`!yXG$x3_ocF@cNBEQWXoyH9<0VIuOo -zL{m>xkYA~0Wwq;!W{;}%A?@$3jiEUnEh$kv?`Jr8KZ}cq&Ouk4xX2)H8{GOVI=>j< -zaH?%VFw8ej^O>_8kTRxYbQ&i5y$@Tzp&qTLiWzo{pUOw!_--ABKYyy0PQ$?!bXCAyvTq)+S3U^*khS8{gnDRb_K -zb*M=}t$kQ|QH%Q))~M?_>iqr(hn0LO`04!c1E`mH_)M60?`QLbk-$gL{c65vpD$PB -zo?|kG9-BSPNL_G*qWzP{ZFk~5hSpPdwdg{Wpx*M%Mo@3G_D -zO+p!L&56ynejkjf`XuJtQ=od+a5IW-f=zHf%=;Vf_Qu#=frE18zFAi1K=yO5%z!ap -zqrpI_CymDRNX$MCtne7d;8Q`ECm!$2%kiEJ4Y`ciloP*$dZX()7`FlWafA!E;B$7V -zE|IIC5^THjr6QcCY2}tsAOvgxY3!Mr2N&C4P*0kFDzfpjSI$RX$`$VT33_EU>z)U$ -z_i0>9xWn7OzFpDpB+NHG?h5eskp#xkXnWP?I~kN3St2;>+bB--_GzG%)aOEkI1@$Q -z+~!p06*mN5tYhPSK4$~y;eYx`g~in-j;NHQbpyLygYF>Cs{;TNfzYv=_Gp|AVeet> -zE+_Vh!Dy&Mk^MHoeMMb9o9tH+eXdwF_9V}>uY>Q)quTOG0x0lXgxwa<%&Jj=CtvOT -zQb^B2up`Tp6CQCqB(X}-C9H>mYJfoRh<&I|qTi{$O`^9f!&|A8%V3JH6bljzU9h`S -zDhQ^o)+;$Or9MHyaM8=0VO`-Qh-#F57jq54!a-hnq(Dhw~Lw~Ob)ah`_ -zo=Vd6BbSFCL*%%^IBt=GQD#*3eoBsvE%8nBj85RykMaBLqtXb+*kkMHTO9%0hST;q -ze(doh$)o%=MxFOUO;v19F5wY>^ySd)E|U9Y!T;xYW&|}C+MNb=uG;LA8|&)%G(ezH -zgyo|l6#!$_KqYiW4E9a|*=5wSU+c!gp -z%jRv^)pj0cMj7Aed2gBqhve#7>2*5hCz9w5&4k)Li&@7CWisCAB_upibHc%4uSomJ -z9SEujopU?w@|UE_wht`wbH0*m@+HpahIA$mhTzSx{BE+Q29+{@x!h0(@4}9DGk;zB -z8@uOxaYzN^1XmqE9~eH6By7L@9XKSKe|{e34I#H*NjYTss~41hXJ?)+`rLP~R$L52 -z#2t;BOStuavuyU-6~26^<$NsQ)j8d5Je8zP;!=Zvk4R>Iw~Q?kN?cP~;{MY;0qFFG -zn+rx#i>Dm9pRGs_54G@6ofDn|`)Z~dJZ1pU(0Sl~IT%5Bd1b!(nD*u66~zh0>ujD> -z2Sp6D>wfn*h7)hlNj@R%4H+XNv>kY!Fw^yWV@w{6usx?ghYW*hKD`&%$I%4#0m4zWLA{j9la-wGHz1dgE%K4p8lAm#@jg9hg|7PiG=| -z-h%I)cN{eQ#+?>vn0saV_qnSy(fzY@dv(ua;?|Js|53G#$mWQj_ -zl~D38%LOw_8~o{5c$@2$lYV9W5tFQ?oJfT@D6f8DwpEqE%-~xd`}tHTow?%)^DXOm -z6_B3xp+51(E49kJE-OphKD>}IF~KME+UdJ!aL7-D#SCs=BP_u{mbZ;Hj;yIU&FE2F*ds^slq3m>$cToGYb=ifH)H -zODx?lF?B2*eoXz>9UJ8jX!JFbbD#R1tV3e5?m<#- -z3!Zc-Rx)HZ95Z;#_4BLN-4a&cuZ3;@+0}lwSOl9IEiYakdU&bFUd^aTJ}Ojn38ap716GT^#s-2wuvP9j_rr6pH`6)D%B*-ENY9H>~nr^+!RO -z{OY~;@OSrqzBq$wP@j#2ho2f-wQ^KtF1Rq%JbGRtpYw7~NfE~ri`lAjBg64rpzr&% -z&VXMs8YU7bvG<#f*s+d>Hx|y4e3m1N!4)ymXhdG+@O^$Cxqdwk-5cJI%Id*0c2YP} -z6C~;|-g?8`2w~g^q;PR}F`z_lCWsi&e#I2v-;AgT5 -z?64x^L;LTm#8X0g5$fSiJPYP*ws)p;n1;m%M -zQzR??iChtNb=UU|Cmr&nRwULk&6&HOpBho*oP`F2>qrOk(bJte_KNe|OXnj!{K~g? -zg+D$?aq!c2=@;`p`pqDIp18=;3mZXBh_#FlK9F85Ip5{Gn^NaX$Me$FD?ydQ7{T)$ -zJonaM4ZyuPeDTT*t-wvRa|&(Pk2cnu$cI880OYcE*a`f0)p?3*?nHu$2k&=_Kk`wf -z{4!-cjsjC7)V;!8c(Pl|r^4_MAIEtdl#|5-zVBgoFQO@Ax6phQ*I1ROHSWT3eo`m9 -z0yurr7t;hUxoD?}#W4&Z3A(N%eqb`VBm2$6z3pE1WgxCT)GyftWy@O$V{Q@$A1^Ho -zYgvf52SvJX5i|iJ=#d~ps*RGTRK({tup$vUr8jc&s~8E}>yB==ci%3DZ8a60s=kch -z0spP1;g{`*kZaK{WAG<&$3cKY3(x|onM6a -z*%A+3MI>|hd@%JX4m;LD>ct>AQ; -zrVJS&=#si)UXAtdrk@I19)64_746!c_mIR%<+F^VvWr*ZbOe;I^d-z)!+UtE%+?a_W-3znj$W+1H>CM~xkh*M -z^7-ikO20Eext>%I*^6`5Ev(SvG%d#*f*t5jSSk~44)0n>pk -zOk=PT;)4sO6Yxga`8)xyhyVGltE^1uCTvKaM$rE55TNmahd$g*L(IKT7Z%N{*`Gzq -ztymRO%N_xEA#&3Bz(GEYH*3D6fPX#k#jw)QcIxhi_UywFIXd$8?r -z))UH)7M@Lo)iI>mUet@Tx8Fju;AlPO_Vk5U?%w7jI(xW{eb?_}sKHUZ@>Sn5^*uTJ -z)O58bAK|D3FJWHY!k(aRjlTB9g%iXhGcZZ^{s@he;7S3W;{UsxFX$Zr`4qhJv`8S&0+`JC3Eb+**NoUwscDU93eiN -z9og*pP8y;ZPAWeM-AQ~V84>IuP)m9r@4FSCunh;4;>~)IwgU@z*Xbi|ELt>X%6$-| -z$4g&j*M3~Jn;#aUUNbS*Ygl8W%AXkMS8Gn1?p9pOPSGd8?#`+28d_x1PV4PzK7{7; -zMOmJ=))T&bzWn-pt}@{(d$+y_{(Ii4TIE|FS8U%Nf@B~*nK|mTXitq?;JbEr-!`d9zMuHKET&@wIilE6=%xK1iQ}Xtqq9RpN>V^%A>!~>vw9Xg6O~;%z@Af -z@m4btd6*gVs{VC+#i3AwYqe(H{tCNK*o$=GAZXrudJO^2Rrg+LC4)25S8jAsr2F14 -zZt$P@)p4zt5aOeqA&yIKI-me>2Oh04?tCj`GPjRrign@@fBL)nPKkO-KH5Y_ar{hW -zpDzw-i`tm=2Mhl=L`W5VMj -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 -z=zXp8kvTPW)qx -zxpj3>(foY*&ovx^SCj3*GtKOze}O95i|1?M_S8-%(%v;{x|G;reFN~?TD-Spx3+`s -z23_hsQSeXCd02oG4@8|D!Td>o>2W{nb}Sz|KXo2=H_8CNWmr!PoSI8{nbd8_mGTQa -zmPV1_0-U#&`Fh@YEh4^ADDyBzkkf+?BFl_LP$KuZ?~_u=+9}-@NpL~eg3dq!L3cPn -znW;{)4=m@wV&ftq;qNZ#GLY$X-n)eXnV1nbI;Qy6S=pvg;CV144J9YmzFXl>On)}3 -zS5#BTJt1)XC!~_&UImNqquY3;oWx -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 -z$4f4t38gyOsk*U87*e?&>-z4?8$}FfuAQ@8 -z7LP4f!p0kH)1flC@EVbPr>;lmyXAE=Boo^G -zqkqXQ-$b6U;;=9``D5%@>;ju3$@GPso`jYo@U$dr+TppXqH|Uejrfcy$Z4rtf=1A) -z4JN%1cY3C!ecU|G_E0p|RaEer^ORi7YnSXipDg9TyNE%_uTKwtN2W^Dd-vhg2H}kb -z(Rpfg)W#;$Tp!cmQvhKXlkwOWkvnoW``WGYdd+3!roMi;Cr3vgh2uW`lu2w-N!*I=sRFv>%inoc(){8 -zdAP>8b6F)n3&CTW&a4tw7aoVPr52Hct2N89GJekiPyUQx>wuh@Bj?e&C)R}av$Kt+ -z8-yd#+XR5xoT7nzA6^$)!j~JopJn3{hH{*T5c8%v6+e9j&bX>qvY*~l_8ho*(Y}lT -zx(;LO$LY16r<>1?(DHVUyxZ -z7NPeE;LG}`wn%*!WiHqwu;01C#5{h0yfM`GUgws1x`7{s;pmxA21IW|a#PVuUOUoH -za@Lu?m-h3_tGIQ`U>@596S}xpMIE!wV|$-vUcGhw-JFdrl77{f-{z^J&n!)xGZ%dC -zTRU}u4wr~t{~DFHZ@b55mnCpicf{t_0o_nzJ-5!IK1n^V@qrrShJ42^LOIq@;OH1| -zRh?Zp~75I5jBYj9kO9|YWs)7|s_ -z<{Uc$UDx*;Hzy=}tRU~9YY`s*yq9)Bq66SK93?t~?m;3Q6~?INXuVauuAmSnR513V -zp_;)0JW}ds`BDUP=7YFvwcovT`pk{=94sR&)SeM`eR!gBIoCp1Q||SN1E@QRaEG8N -zi9vyBjrlGGSxe~C77$i9xY>Fz -z5lDf&nffZhIA5ld7PM9_MEAO#4Eo|10qzAk%CE%V_w~oH0!{Va&#kCtt7Fgc@b4JF -z?%9Ax)i}P0U%ZF-HGh$Be-EmrIM^Rqof1l-e!2l$R_)Njo_*k=@4J4twNkYGk)nF~ -zX%;w^tIyJSq`7I2Qy+RvW$4Rrx+~yMloClZGS}z2d#UAwwN|tQemC}m^2*Hnze|Zz -z+NpxB9)84kqmAylx7Z$6zQOki6L<{44qqc57xjcmO$$K5*C&M>UHc%$V_KmP#WFJZ -ziWi8XqKqv&S@vFoPQ7uNM#^DiuYa~;kJG=lP2eh!t^;*2pcZ!$(2uhxI=t^H2CeFR%AWr~7! -zW4@@F_G224$4Ei-PLf%201;=Q^vFr8;vwVdPP&XKi)? -zg#79LPFXBv{*n-zz2`km{Cj$UY|m+RGEi>1#E21u6#}1?8T9+Q*XDNbk>p2Bo-%Gs -z7eceN%G2`l82}^hoY&BScHld*hUABS;}%?G3%$#8e=@ws^4bfM~0r -zu-#rLuH)aEJNLxhZ>p<4ckL`R<5T^#U8!`Mo$d#G=!##T=~Hy*eP^UmzH?n~Fr`k# -zCJ^|w2ELC^5m=d;yTIYKuEev&Wg}m3?OX{swl|`QZ|)qp(VkV+e>ozihmK`i8juED -zc>R#WZrB40+(0=Pl8y>+`Ebsoxg2O!6bpLoc*j)d@IHK}I59jYZlVYK>J_5V*_v;! -z0NQ+lj{w-UJU-`AT`w_?*9#imZif;>`{aNvYH%rPTO{oKbsaQxNO{ -z0rQ3E3b#jcKnrT^3mv{zhYCt%+u2T*;51k}Tqvj7&0l_I@;f6JW&<@!)adgpj#pa> -zmvCC2ZjxQT>9BEQR9NM)#?NN_+X^@(G4iFkbvjrMO1?fz^!{$7?3Skn>vHLw3s3I7 -zKi!-sDfDxVM{Wb-tMJbggaBathPq>ynLv?7o^lcu`GUFblP|e`?lr)v?=+kpaBRs4 -zJ*3)V`3O}b(4{B4FWW*{r7hjJzSOpoTrX$6SIeKz$|>gg-0TshniKXEDjSm@skL0P -zOEg{NMR8cj1&0!!kZVDuRx8J_QQX%~kn1L49f;Rav2z2y+@reIQ;Gq?Pk?HrhzM)& -zcd-s6yYVyd-M^CuQ50W^yV*j5rg4;v|HN;LgbZ775uXzWefjgVP1;4sr^Pw1m> -zE=ykDF@vSsiZizltI7k{1F?0`AP*nYd#GD9O>?`aqL00QT4=MR=)895bA82u^w`PV -zTDvs|Tu;5FPE3wS_X_JAfD*zC9Dzdz^_mV~nK^ywY)oZCvW2~?k%#^LRvEb>b>EeG{}QINR&^BYyrw4;}Je>-z*~2_?DbUXfjy8 -z6vKFHeA`Usj8x?1@&OWt?d3ib7PI4c{X1eg9-r_ynXe8kk^CTl3brIpY-#vi2mJzd -zAOGU1d1SGQ#t3hh?{_8S$?XS3m2x_L^+?NQ(fF(;Fn@JHp+n1=%_Gd-IQMUXl -z!n%&Nx4ix{+~TNx!A57n5W~W`rf)^ -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 -zM<3N1Y<;PVsV1Ui!iAOP^Ss+mz7xmsQ -zJ&%Pa%MO7?ru)67PTqZT>DWErL^SfEUs(et-q(woyIdER;LcolQnOx%!Gg47=(qLC -zFaT_Hfq0yA`xa- -zwI$AkgUevdt(MyN%iTQad`u~{H5Tcg9!Ks)_bi)xX9g+xYuUDT>@x9P3O`l1kFnMl -z!~p(r)B1=|9sKghW`j-)!-UCqCGbiI%HD-qmhUl)?jQ@H!<3>>Zk_gS!?`D)Zmz9F -zhSJ&OalDr}XIVk-H;(+Rsb1HxMU_MXzh5F}o2BR8S4YlMn-%B2-y75XjTW)j0W<$@ -zSqiT^_@yl9_1pATrFVchNG-_*`$*X+^fLbv!_Ih@r@aq$~<($is2WP!cT;G{=V -ztL8Q98X7|`dV2F!3>-Mb(Zj`@$NOxJEBd9Um*HHAOPYBGsi5|HZ#17#02|S|AS<2T -zbtpyWXb}q^)}m9_RTbSxQ=TrzM?H6kmHMH@QpX;k{@l`PB?E%{a;dkTR63XZnx5Gc -zu=s=*pTAt@do+U05Y3iHPE&aAJ@++kka+UY>#1DABVz=X{M7ju=f9IPpI}&7TUCAw -zXcw)#y8;opCfJBNu}_>rUoRjCB%qrOayVKY+(9%e~hYWWMR=CNfv$gX@i{2e%U|H8Pq^aVNb@ZPM?*gL -zX#+hE`h*?(o86Gd7melOQ-V#jyWLJtiWOpA<<~84=oh@h-`4V+#ps_%_d9|3Lh|k` -zH;ZMNowHwF7$Thtlvqt11YOT{x$P#Ne#5HigWE(QZ_o~>{M)#vjB`R(SI;8pwyd{M -z$@tyl^mJ{#dJ-rr{jQ`_AGrHC%Sow1#H;ns`Fe!)t?(>HVBFRO3$~};=_o=Sq!GU^_M;1+PWL<5~TkofyFA2_yq6V`dUeOKR`ix!e -z*7|LH@ap&;6kd~D2UNvHm#Z+TYAOmUvQaHyg5IvkMqgsmT!Rt0Pg%RITP(-tgtNG3 -z7~%}P4^2_<1k@?TX_J#rSo;xKjHh3Y%o8Lxc*JFy5zEBZ?`yvRyrIWCR5;%!;nFZY -z{2Bceymp>gT0J+tY7yhiE7}u8hIB7R4_!t^K^G8`4teWopQ7)3{eOgATe4&~3fvO! -z$EQHB|0Oweu0JcHXC}sO`*wAmBaviEKu-I);kUomT)(bbTlw}$-_9AOI;g$ni$Zx& -z_bGMr{jN;po5fQH?ZVxA>^f~V9+6~vl7?=)#|V_C<38`vfj)4#6jG}nIWB7gP#!t- -zC^m5VsYH^08X?#$7+GL&m~vy<#t&yxwB=C{o>*i`mjUX#zE|415Uj+8C?z<#a% -z3NFrWNR*1|?`g#x5CH7z<{XE-u&7DjjD;H%XFux@XLy8;w1$#g^_)Ej(MVV%u6&paryz; -z!{(&-^LOt`!BU|5c8-6iwz~RK^`p+4%0^brn#7$%+wgvlQvA=HHE~pCS++F89c2AN -zvvr -zZ$5pWO4_*schV2HklwdfT4F9s6A-)O+&xd_JsMeFr)=*vq${WFHs=){dq~FMbK)dx -zp6fi2rW2v(CgviIwTU*|&Lr(IU0t4f(B_a(cUOp^3$4BqIzJy9N=nJcEuTU+>wXF_ -zdol7>DWSNZ_ei3h?4foiRGWd1&a^t+16{BhAB;I3)Efl}j*17wy0I{MRM#g2(*PS^ -z@+_sQT}C1DM_aE^tn$Gadl~b|t%iKO!MoH>-8`#_J`LWiwG$VYBc{{+goSS_b{nCo4Bpd4Zs*#8i+j8jE)SP&U(cLQ7l$M`erm4x -zrHI`K9+E!v*h&D}H!M5rL1xsg^e0iu1Iy6{}2$ZbeMo!OV|5>B5+y+S>=60&KR -zFGCS29NxTxIG!n7dCt-A^2OPP^3keIM%01^%J+OX+%rHRxOoY&Y}gXl+nMN;TQ&i4v3|jQ-?UlB^kTU -zp1moSaLDyjO4yX^_;g|S>6S?q-UUqnLBBroLVHU@rTE_R1J!^Pdf-gg-6W@(t$QNy -z(svATZs(#OvR1fba-TB1^fZOP1>S6vNd1zw+9V6{%hJoEW*04n^pOf?L-%A~vHJ+? -z`_8#_XY%W_xg=ka^eu-WuS^=&MRpU-ZPaqx+uU}udF^IOF@O*+>Z3jNB%|p0W(Fzy -zm&zY04koMGIFXNuhrR5fHH^hk=aTha=^OS<#JNH~J)ZHF!XDcSP9$XbtHcNIGvrj( -z{4y)HOkbgOz1&x{s0)!1Jx?y-M)#vR!4@ihPj_Fne82D#Ft0EzAd5zR8BkmEddt*H -zrO-ab!C^4dyTcHN=826sJ@22&p~%?XZ3SNd#Fg*rtMgh~s&)*uZ<(xolLX)TZD#lk -z^@HE?fTx@TUbf-k3^zV)X7L1d&NAHlO!a0h#zvkU6(pCSI^S6R5Y=zqC^Faq -z($0q`Wt;rCLMqYia2NI(Z4$PwWq=+(->G!6Y;QB1$G7dDH7Dj8Z_$N3xEC(Qp%!^C -zqx@8(W4#Z&__?@HEL>BQ!l$QU>p*cL6 -z(%q(L+iOuzQ%dj?Ie1Jt>7r|wO@*_|9U*gu`AV+a6V$<~^!hNHY>HJJFcc%jyijB7 -zR6qpsO-r)2(H=r4BPJf%4!pJdl2V_i)xvMY0##`f$$O!UAZ(9epa7ecH}#_DE;0%B -zTuA)_As;IS3UZ=W}ihQUBZroaMz2`vIxx2+Rnv8K@mTZvm(h|-}8sj=V^;FI|6Q8kYU_Z_bPIDwD -zw3L;zAATMY6N#0}Mh{3hW*Q$U@&hN`i^V`P&tqhhibztQYuZRY=2CDB9(`86tX>+r -z)G5Fjh2L$pk2Bn(YHy3F-H_3S8fqgQ-s7Y%;`Nh3@^oPcIpT4U^B6U@)5=~Nl|Cb` -zjE{@?#l6*rA~vjMhW??c7wOTRxs9Vcdr8GtAQmP+CtW`m#@M!>#6MeyRmt_7zA#jK -z&g8C_E1V(dpt$xmE%<%8bRy{U+e`@^r!;T3$Vhk%Lg=GKmu75A -zANPFR0>82&E$n4}+;9?#m-HNuqL_Wu#7@!Gmm$;boY*Tz4Guku^35z{17xhy#f`m= -zKP!iSJ1Ikm;XZA?E8Q;!lseTZeDuIRZ3x;~`<+Vh-UPZ#(w+%i65ACUPZHwt$h{@O -zntbUo7~n9=SUq=q&$*L^y7$oqCJ&vXcqN~F6|FBbJNOWZMYIV-SrpA=IpLjX(6>Y{{cyT7F^wsY}fotv7qJim+ -z(IdVudBA4yfanzjDW4c6vZJJ6`;Wx?=m37^9a -z?+eT4*}wU8leKX7sB=utJU)A2DeZRM61>HlB-8kQACaPvyOKph9OJ1$66k4Jpmb8= -zj`ln9Xg)tyKv-AUzSUk<-3D>KURN%UU4}WLJbULfrw!Z&UQb&Ghg`%+f{o*L<%Zrv -zrMD?fP6Rzs`cUhu>EAv#RUG=hRS@Q@eTqX!{`P#(;Lcrlx25a8wBHaG-$jIP`Cbwd -zqD4&R``xA8yZ96He%@DDbZmrVA;H){XIdT&vrqG%pqE;gxo;jhjE@`pL5Y?`j=`_; -z(+%_3)wxrXsi$w?bW~+~Wp5w*$}(|I4(a*k_TB;+j4Q55&=VAuGEOA8B)9zQ(`Kau -z^Ut%q1o3zqLQgEW)X41@lxWeWvzPA^pfyP^hOMwGbD1@8)o_4L-cT3Vc6!MF0B_Tb -zlTsf`F+?H>ynYWmnbF&aB~)LBXoPz`o%k?EsV%bj9#>;8r3$RXpgB*@z)-{43zytP -zE<8; -zlH-t~)^&_pxb&q4(QB)shMJ%I(j$E*y$W;X2%cao7=r|R0{1(BI8|SDoV!cB-_gxB -zw)e^o>%h(D*EM -zY09v9Uuq2`D6yRE>KC$nc4(hEheG`3NKHk(4Xhkz&kevX*DFPZIf5IuJJ9+nb6U(q=yhgV%(5A%b~w)}GytW3E3B;ex@Cuk3m-MW>Z -zLt?%+^=NCDvS(T|TzL528NW8c`@Cz>@QVuPvg -zKCTn?P{AME5Mdr7Xx}+&4c87f%2`?j0>YO<&r_aZ$I;`3#NI-uLJG`BQR3RACvzy1 -zZZ79{E4Zj5GB^@@)mbhg>|RXsfs8e0Niqg-xyvjpFPC&a4fBYrr+5k`K3>-JqIZu} -zS)v2oR$UqE;EOHcr-}j>o^C=pI5kGLpbK^(5Bmc=85c956=ku$XW_A@4d5Xu&+aXQ%(&|XN&l}=i$Cv8oj6ZcFafmd!TDd0lb<(qEGfi -zAnepvTSV$9!|58688V+S&CH2Ygra?E$RM1rC_M&z;`0VS@D=U0HJgrq29SPA>JjYx -zM(xA>+(_}T;C3>hKGoeJ=QHIg$1z7PyjdC~iKhHmoYpAgH`J9JH8)$^_e>v<9ei=p -z*m->X0aHANTkxbOd7ZQg)0bFwoQIQb#AkDH4l0JfV8*kGPHzcS;k$gCrsGX5ec9wu -zptnONq5ACBydaunJyyW@^;#;}9$$jv;OB}v?gH8MD!Aq2B0GJJJ?P26d_4OJHs7GJ -zqas$Qsq3?W5YlJPBt9Ly$3PA{7}Bv?v8Q33rtiHgMxjT*uLtW83CFw-r9QB@cm1mj -zK-~w+ZzUA7VmT6s>Vi!czXjS*Syl{`;l3N!g -zPWcSov`6j|(u2n3e4|nlF3?W&`EN&P -zbk+F=wp?s{pKPL5`r?y!11(Qu`e1=Q-H2y5}*|sOi56}un)1y=9dPjFb%9Ebd5+&qH^kO+*Q^_L( -z8U@x-dNwbK$GP~O`LlE70>e{sw|-uqB*?98#bhg(1Eo-e&-qG~bhHFpD~g^Y(nl(!Ob5bGTCWIx|=ptev3+aA$F -z=k``R$PtjUA%t7}B;n3U&ovd)9(bGeq8E(@X;LEUJ$qvE=%c;+UD$HCInaQF%9S`x -zs9A40&#}UClk>#t`m_*t0nB@bYU3jRJaa=S`DDdq~uk#cetv`;Z)%*6B=(+rK#5aoKf+dN%l*YpwF{lE9>}%hY3#Qq;c*kR* -z0^ubcX>!~brH-B_q?YXrQxskZqctr#wYv=?We*MRP{flKEZrpHr_MP;{ITQ2H -z9R1|Ew@!ZbYh^5AceWl}1~BnheYUofH%IvG4IPxZw(z1hsYwt|%sIY)HQy!sR8w&;y~??7{iJWaYg -zJC!u&+H}$RiG9C4qzeP?;4ysvnQyPvp?*jNn$cIkdO`op??U;a9t3P#J@kzz#p^fp -zb}EHEu_YZ2^+F!@%IyL^Czyg42a0Ra9jg9mhybHjaY=#U;y_#!orxPiogWw^*Ms?LAh07^A -z=B(VI(#;{)UML`bcWBsn6oqfTfJ}Mno;SsM$$=X(_$l^t`s}IDHYc4p+2?!{$0N}* -zTMcTh;&Z7rm-k_C=L`{4-9t)aY%NOfncf5I9dyR;bnb!@?6J5-pT*}Bp`(rs@v>|* -z3Hu1TT)b9FIh@i0U*YIU^^^H9?jjy8F{Q`shB7mO*C17hO3q_Y;!Az6FksclQ`nBH -z@y$KA>s@>MC4UlnL~uhd+^?Z@jzNd3=|~(DV_;CT&SAM5L3uRxu(`v8;WZU5h0}I~ -z^HhTou^lk|+#c<*EPt;$eYuC`XhGqPQa6yW(4%~hAA#JqMZ$a7P7~LY!b{&p>b&o} -zXE(2C%?Rgbmzfsh>=ThOv|<|Geb -zjh~xGhy1dK1NMGhMC?K!m%~x?(Ix$fem`$GdRc?J?q2C?bTBR)zX=7jFg9;D>b}J5 -zLo$z)B`NEZHlW~+>YEnGDss?4?CF=BEqki&5chtJeUuIy=?9(+Py0G~1#V@Yc=Wg% -z@%B-42K50!uh{YPKJ5uSZB^ZW&cj3V>LCeJGCKF%ei9Y&q(Oi`+1YmC%6EGGXmiO< -z21c?&Qe8f+gt@TSP0Ns%rhM3r?su0x{KUGs3T)C#oftx!+S3ar(MY2-J_kB&*GV2f -zkoO1Q>qc7daV$*e9$M;-^g_9mskb@4JKLp~|BvyU%C(eFkDu_J&jJP0ZYRS&3eCg9 -z$dPjRzSkXAu)S`K&U&cLxVjv_Igc$xll~d|Q+eWfT)Zl5eG8ZgVPr?+_V{CS@bbd+ -zm-BgN>Ec}~2w7r{{ke2z!hP5S1? -zya(Txe?t!Bbx6hD(EjFtg9%?4pLMWg>Gz(yH>L36)08;ybqF&b?ZJJSnXCO|_X2eE -zPTexvXj2K$*3NG2qo^BsrC -zD5dw-LZt|?!*_HyJB^tHIAP}3a7QY82zgS78I;pt=5V<32!gRwZ%9@H8=l7tZH^?mdrTo60wZe8>FMOW_KKkoT{<+a_nm -zU#5Fdv3?(3NRs9^6L$a}>3=J~dyOTa9-f;wgv?WPV-1g7r)4eJkp7zY>A!ud!D$Mkf`a8_cOM&%LFQ -z?RTln_vuo~weMU}1m^|wVeVMfdt|H5)qabv4revM| -z{3lY*z4mz@7B+T#<~6L+(vLz-j@pTj#zYhmm#+mra#~{NK8{#ln#I9{u9wZB -zIEpzQEjfMo%A9VpuWi7wrFaIFU{1)viby~HzFf{;Q)IXk52hdZ;!00`eoV51eN%+< -znm)1+WvNG(Xj&2IB`T8UsTB%=7AhJR-FWKqZ8F1K^0{g~{NE*sgq)|k?^hZG$b34S -zfjhoK&5$GkD^Vfo3+*Ue{dAPwTUPXR|K1g?w7S^Eyl9OfU;l`nsKvEck -zdiTSKJ0#wh9V^cbh@IZ6z~oQXVN`P;o4b&8=X3erWv4qaH2A)Guj=>&p4NLEy(L#( -zBE}*iW}Nyuk{4l6uUA{%nfzL)m>U01Vikhtn)2m%gx$sUn?yFk3vg)P^;kgoP#T^R}_T-Vrch -zVwgVW28;Ol@sq`!Is^vBICGK;clWVLe(KO^>oH!>kAqk9iEB+$a;(UP-!FA*sUbj~ -zQaR#qVrl80was#07Ew`VH}QjHM#m2_m;&LkOYpV>vS{Ao$Jkc+YtKozXICuEeGKo( -z^T3l{$jiBHemt)5ReWdGYfp`hL(_`RzJXIE#H;_*~BrC;$x3lkg+HKHU{6gck -zE{Ay=`|B)ZHWPZ;t0^_^%;9UZ&9E(_auW9TvD%{(R|Mg5^zhQ@z~4V_ul|fK1=@%W$}I&@QQ6?fS-CA|sWJ(Rn20eufZZk=;C>cW?ne -z-qu?eI2=Y+n -zp8f0+opKa)hX}USA@#Tr~*^d1+C?XN=f -zbP6=Z+Yax;iE$o5jO5u{aOb9rKUy{6_a@lxP7=TG+ZXJccxET!`bZuiZXPGq5J>r?Sb{TZ#uedKa-a>Ep2>k -z^@?{E+;zKLaFp~(R8ADg0xxJp>PK{jCdq1hxA4rvIZ|2+ey|{!bdBo}qA1W^I4tpv -z8eXx-j`CnVvC196w$kS?U^%nhxP9rHa%t44L%%#N{I?gjpW9Go$z#}Lx%A{>iX1(3 -zg8?#d1b}FR^R$U@cs+6qVWt3~O?_KKKU43@`^4WhJ&(H|zs(K;IIGv-UbuvtZ?nOk -zNleCkiYZ#v^pP3v*$VQjiv-MH{T-k_ejG<`A+Z0m?ho_?CZv^?1uG=cA#OO@@y**pz5tx>r{Dy$y?>)ihh&xx-0`b!dTMyO&$#fp%$)k-H~?%lG?{ZzOOJHW -zj%!d#-#(Y&t4LL!+CI=kAYbdrF^^grz4}n)K^D3c8YRissh1>P_CzoWp|{VSRg6XEvbxn{_~6sTo4M@*O!vcxh}RbwA7c$Ml=*=~^UiX73t!nDx{( -zUqNvXxR;=4pwR<|PfT0F@?~27xKNxi`G)E}wf7jvwRofm)q?$AvHMM}(XYZUf;Lhu -zzA+upa|(;2vx -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 -zNYZckOxwImW44&T42A5g& -zoTGkYDj@t7IS9=sl@ItWJ%*RyuC7&T^n)~x?E6o)NHQ!(`$UG**$A+6i_~LJJPtbC -z&KDWZyYuR^dbA0Bq(kw}ETDdi4|vaw3dqKbO!-+}u8`u(j0)|a|8uS77Qjo#8cP^5GO-!mx~l#T5J&~lIBad_*u -z9QrzX+`vG;aHq0r=D1!yHpU#hz*_;wYi#DEA+_?{QYU{Z(M71Dbg5&!%;DAJ9TFVt -z2543@K~Tf)}tYyie19VZW)YzC!bDw)cZ -z6W+_2_h{E#c`C?q^Kg*$J;aJWhvI!1@6AwXQ8Sngz9-xsh1jG#Cp<~zB751OKoZ)) -zL9ippA@MI{tQ#t%iB*=eX&rj_HZXyOxwCJy%W1mp$eKOSp16dzpHZ5Y#M|bdgW8rmJtB07* -zV;mB4bQF5Pz8QTuNs_tfa7$9)VwLjb=d|c?zLO(nqxY1spjYZ}?wKRNHhN-g!Q=>7tfZbmeoD+P -z!24A6^EZ`Q)(qXbmorX$9#w-E<}=iJS_`flP(zxIs5TvU2Qpo!4r+Z0(fQ#yRqngK -z{5&Rks)K~N@7GmpbIah7I6Ae!Dp407^B{xV5LB|(WT)#TN_d4p=agYkII;Ux`%D~4B^^&k -zPDg+5D*6f3e)ZZXo{mb_<((UL-m_e9ieJe1J2Bm43JB|H=m74H^_Oe%^g{W$b`H0b -zd7yD$aXI1%%I0Et8Z`jziFo1FidM)xv9gG4D!-0SXb0fK4%e$x@lso;KmNpdKRfglCR -zrkDoXCtr|RX=SCr!94GmoqI`pM~z&K;w{uOE5_6I=~y{+j|tDY6 -z-a{KtjE{5S7$j>?Qv{i7S^5#|*@ZqVkA&770PXG1I&Cg2M3UE&U1>(|%PsP7(UnBu -zQs?-b=jc6Zh3cHo+1ceYxSV3u`-NP;A9Xg*`Z6g?Wu}uOK~W#}n!#__)A%oSCV}rGK`uf< -zoNPP+^`v&5`xmtw``z`t-i%oc_e@r2{k6%896-CXI$5x>o4d7m>B#YV;bD&Kgtw=NcHbgxjwvGg2>Ca|$Dke_>*tHV1 -zeUiEw&-fFW1fuc?|34>Mp!3{4La5sxj3wK5>mfc9@_|!_6eUAs{K$jSB=$xu@gf0+}-2%VOmOR*^L|gzJ1*>C$YQh=m8ZUJZRZ -zz%en-Wm>^nD2akObXN|!k{@c&VUq2>lj&hS)m$(ncew8MqQQz*hu8WywEkd7%s*$o -zGV07hJOhBR9ij~I^==QIM>NCs+Qdx6T8Xb+afDGfSpgjnHH(|Hae -zuEd(o)$BOTZ$)B_&0SOxm+h&nc?2cylh1NPOLpOFy(C -zp!GgwPx)B2T*HW+orf$E-Y9NFm*+efJdCGn-`?0)O=YL-^pmQc^-vDrbAXU4L1E1R -z?oL}QoPzQ8>T0OjVZ-W@hq!Agj!`r=S6F%^FOt+ODV+q$s -z)2>b&+^@B%>JlOAdDqEsuw3`!n4nV+Kb-Wj6M`JYEICF{md$R9oM=gQj?mZQS4~>9 -z7Ag1e=lL{enxmXTFS&az6NC5HMP8*39Iqb*i&H;OrGKZgKl-tUE|r=(oKy=ZNyyy; -z8_VJ=e1Vu_k0kIk)7Ubb*}m#Uol=2My+Ff+6-aK&bkSB^LBY2?^xA?OpNp?@9p^rI -za_j3qW79AKU^$`4cN5K;jLtAhf1Z41{-~OujPq&VxeGg7O!dWKL}Xa}(+x~-p^hK~ -zX*=Q*{s#@^VCjNI7kR^dwIY2XS2pbF89oI3wT?Ei?beyZqllTpo8;Y8as$X3T<$jn -z=@{~H^XRLuyk^K82Gc#6as`k$a~XrxDsKW7K^^an`KCly?Wv4IUJkm}*NVpE+83Aq -zn0tqL!D{ML_x-u6*+s>6fDu-C8YQ8M20_WrBf5E;Q6e0xnlJ5VK7kF2PnJ>atA+K* -z#Kwg -zG3&&9AAqPU^b$GE=d>?G!FP3D{iG){zJM~}ZUrGEsdp>K$%Nzm(U$`j5FDIP%o#VcY6IUMLHo{hZWi2`2j`qphYMWE~x$vBeo0k|S?d^FH -z7`=~$i~4QSSJy!{5BjFWm_1oq_cPks!od-x2OC$M{n3>aj<09M08>@*8?{4H;L*$y -ze*4}MFVXQSPY8g%I|D+8=3~uR0J`XcD9#}N&IF}6pD`2c>8Ipb_i+qH#_YF4DB$`7 -z%0UaF{@mhVzE)}9lH-GX;5`|LGOM?q+olVyxG3bS4k=uyc!HLu=WGz3hf2bM8_roa -zgz(DVH7UZx)Gj^WAxp2Cp&mcc=FSOc%h|8h;@yF2sB;gn*diV1(RqTnaK+@|$0$)R -z=7~qf+lx}@Vj7qyi^SHRkuMjCHF<>GE;E!6#*v#Zgmo=t}lbyen!DdcM?$d$4LxvVLz|_&dNYS*!qW3Kc>;bO$KvdTT%Z@QNPhH8Tz} -z!Mu;4qaBcUvCyhdbdUmCf3u{RL#BtWmKcm69jmvi=qp%J%1^s;K1x@{qcRI^v5BKz -z29mVGK-Y6YFF{j`I(@m)XYwygzArYdkH*X$dEgmzW#n4xyj`=9B|_KZO0W^ltv)fE -z%Aw>f1>>Y-Un)5+@{kzv9pLm+LxyzmwAZ=Dr=MQW_iH{s>(J9gax@Cija@Vz9DJ|c -zpewIohG1azlN_1yWH&WOFgQ%~qsEUA%++yhghJPW_D4gHc;nvP$R}ltIGDe8(1nL* -zi+h7t^IYq0<#x7Y6>c$(xD=wsQ~=++p`$(>iJ8pbl)RiLMc>wcG^y(t!~L>iwB`%? -zy6T92mYXXTs5<+ib|c04*6pLZiZ9SjS7_A(sI>)WeA(Rl>WE(4XFYMR}lp>I5c)|dE -z{2K-zW8hbWOk2v&7gXfs7JlQiBg2V3Y%=%Ep7R-Z9OHW8bMwsOccG4}yXX4*B8)F< -zNVbZ|eA$V&%~Qz7zn=RUGkP_X**tIJ-P1JVQp|S{LnP<}r@ReSt%K1V~Aub&{{^DZG==>l$6J~#C1aKWqc -z0O%kS&B6mLEtH-;cbslqp(C>_`K~5ZiVp68T+>5-@13+lsYy;*bpWFQk -zrSV8qJ(=6(ROi6@(JHI1S626+yKsI9G51y`)tVqh&ncndc$xt`kFR4j-gs3y7mt`r -z^<^DkyP}oFTB37l+HRkXta}9L&KdP@tbQP`m0qTqdrz2$M-i`(YZqm>3cs&!)FH4O -z#%pjNJdv*tr8<_-XU`>H>|QwP<4k3vKF4#SL?x|70ghOttloS)}2zq8`S%La*elaWp -zzO1j?3f)Ys!CfA*=X@`p8!M%3Hlzi+p13K2eYEz@*i#thmv7$$P%2$LPntiffl(YZ -z?%2!-=kex>dtq>tzs4uzD_kRT999Pk{4{+6EWfw;?dk?acrWS|ag8%!6YX|!PEG%F -zhI${Xbs#`oNj`YI-A-DrF}^j_C!nuGeED&?bzLO?Tnq5_NxWupC6A>Q7wsfZeW6^3 -zkiT6*HjMZl{XM#fgcx=7h-;=T^%esR$JqwM{jzlWvK14kJ{}Hd_UX)w9@%pXv>zMS -zdbP4q)j5{Gi1--3hLOJe3cs}Zo|WFJ2-y)%zcdX -z8(n;g5chP=u{BJ>rW;=*kUu_U%}e)wbB#51%^pS3lX8qwcL4nm+Z`9OIdv{2+~bXS -ztWTcI+56b1wF0pjzMm -z%}m#z4(!{_{>4Q>b1)X*bkse#$&wna7lB+BI3@jw;*!FBs#g>9;!~8k;Dd*419!)l67n19A6h!hvUqU<=!_3izKZ#I -z{}8MdPVT{r@)i^A$Wya)%N*$FtZupItXoUE9t#`O+Dy~=OK0E>+DJW7U9B`wQfHI -z8I5D-o5ymKhWxVVu*Q0>LwDPmpD6kBq-O0vB2!+mOEJA^;)jCUL}b{p-j+v*+&-Tj -zRnx0<*RJhK$)v`(s@w)3F%afUe?~euVey!qe*g#X8b@f|~p9)!?KofaXXx=-XZYo|-wqWOryCS=6SE)e+o; -ztMRbykt=bL@bz$(iUvi=?GdKKe>1Jj`@qq{8|Of{I+ca^$@xxyHZHvtf{&9tI+{R` -zetBO>v@P1Sb5JDC4C1SZ_w?r|9ZHX39U`Wyv4la{7)auD@8WqcGvx7Y+5VnXM`z;db -z#B-=tfbpKFhJ$ASo3*>kIoguHMmzy{Xn1_y4ZJH5M5+-?O^o&(eJ@%n%Iud@?0IyL -z*Hiw<%oR@!o}A6Ww=R;*tIk$lxXw-2N0%?aXMCgDP-3QaN_i_VQhBORL8rUTTs|NI -zuWs;V_I1@N_u$T_`H`<;IYCj7IpQu`pK#)e3s4fuGmV#rHg2@b)MkUfD)AVxX^#Tq -z(%x11PD=Lrt4Dla?V+1UU?ZgZAcyg3lblJw#ba7*l^Z8%eebvXU#;<>>tJkeLrnwh -z*E;h63{Jkgrcd?z*Fa}ya)F-UF0H5f;~mV_GLAHu2-Iu>SvnYf|U;= -zU%A)lC#w#BZ&$bz>_X2@f}e>kY{lc|>T^=QQO^>+aZHb%r1L?>^?B;g?1llICfZc^ -zI--Sv^V&r-04A9|7+;3gq9KtirZ3s`UN&(jCuzBudlT_$AwHqMr<1jXoyrg76IhWvSh$ -zIytw|c5X{`YW78j3%kU0s-g{XE=p&SMbe%z<~pZ``5fO#!BR>u9c1*@tDV!VbJJVX -zU_=`?eKK$H=OJ?;;p;ab#-q$cCI6hc?kCy=j6aJOl%#r6{L*J?71s+*x>9aEB$Y9} -z0lsw7c1k@~#LG|n+AN`o_b+gZ~@zJb9Wyh*qku9xneI~!J2;#g&cJjb? -zR;AZBxQ3H;WwyR<@6HC>F<=-7YkA8-@0{M#*DTp|^?lCzCCzX^1-i{vEqqd{kf>AI -z<6;NXDlj8`XLRi}Jv6UyK5Fxn)a1QQI5Z00BU6&|SQfme$$pf(`m}!%Z5?6b-g*_X -z3bU54=au<79?beQG@Pn!+_lfL^+M; -zY03Jm_L$+E3?zYjh=X25%w;=K@%XB%1OQELP3j}))R)s04C4&%z0#f5d$Eq*LAIx6 -z63OqQp()8>om~9>7bii#58>o-YJ>JCBN>IR)yxb6;VtL^x9^N}YCZAEo9jx;=YFqS -zvm?^`vGE6aYxsFmLJaLS2$c;$LcoBB-s0+wqT{G7L+$7N`Ft;E@VNJWDVmfi#0lC& -z_oM#YIG=qUp@ixkuREt`jF!^T@h+e&FSuuu$mZQssIQ>olUH|AM&e7?fSi`CdjL|= -zwOBC@2Lzot6rdxo=$}eHvShR^?{UiMW)&b-v2TVd6lSCp=}Q6D -zyxYvn41M++q8g)nuW{OBXb6L*vYM^Jxm>Mw*doMh=D)6jG)WZ?2Z(aEi -zIfbq1u8w|9Xa79MF;LSaxenzf#?_^K{Pt7(e%-4aYTs6m1U5@A1~eSPVp`g-ulNfJ -z{30{#JQ0Dwh*LaqlnzH7Z0Bsp0KUWPc@2g#pG3qq+5)FT=V_G-jNPq=Y~6L=?IEqu -z!Fr(mHszlF5+=r^P}9$Yb;Z5&q4{YIyVn&5uYa^8AFGQxWk?xmUUHK9{W$=t(R(U* -zyavHD-2g`pY;(;#cF4z5`wZq$3yyc=__*H3@^nZ_h_x;oenDiO_j=bhQ9c@b?&>_e -zK1-{iNH_9=tUNFj7`xcAdk+D|lN9jTVRtCnqEHFhavZ*PW#x-WH3U7!g6&*xX1*?a -zQqLCy{WWY_u6%LK3UI$Upr-)9B@X1GoHYF`8xSlk(xmvPukaU))qD9tn!wWyk-ZJ` -zh=a?3ucZlwsj+aAjEDj9=S2n@B##!ZRtqhuZOn=C)b)ExYIwEr)aKa9js8^FUJdZ> -zfs)kDLV-iaAL)OBqTW-D{f^3S39jQ3=6W6D$9xn>AOAgVpYPocP2~8&tDxlVPkYx5 -z?{g~;p7EWo%dg^Me(56Q`3Vir@v7l -zAEY?vJZd)MVA~R#9SstvGD;nzmYd!tF-DJ^SNMKmPJbNzyKg{?-cqQ2%;+m{|IiqvRRKP>L8#?vT2Q1m#Bc*Ewj%h^Z&^r19R(ltE0 -z?leVO07Z7jcM+yI?%{Jzcii&JeFf@HIMn@?Go*!3I_>eed2-FYRu)vfxor9lY -ze>^JxZl@fsQL2)2LoXQNTfTQfTn5{kdYU$ySZR$=%xY>Fc7BG~+8esU_Y1@rM8g@R*X7d`BA1;o6w2y0!|^d2^WH4ooNwXI;Mpo2n?b=Sa(<;pE#g*=0MlU>*(CS(DHv$^7V6N$oXof6k6lMzkL)3?~+x}&?X2`o>Pu} -zzbWhPQ@+g8`B<-i0S#4OxbHYi2jc@Qf(C2dIGt4z`bCJz#?$rwy@R{>b!jptg4VSJ -zIyW81-s<-bO;tGui=&t8%*NMbbkdFC&U*lPD<6zP@i~QiJ&`_tuC0GgC>C(){qjHu -zHDK8Tc?{rtoA<@uC?V>B{|LL1WXE+JcqI(Pw8X^wAE|?K$6vjO+P*4VvP1xxB#`Oa -zmf8$%OYB3&m_YTpOMV8Ar)DR3G$dw#>s5w)Ypj!CLtPGh!Z0sW+(bh!PSmK?R|9X7 -z{S=*44UVRQQfBnF)YBDL2lySNxgdU8aPy4z{xx;ux>Yh#;G%7`Ua< -zJ-(bvF0>7-a=P%)P`P}DkHT~YCCDz%3(P|InNn3*aES+dCcaZmNR;bqet}xk3EHBW -zh%cy68Co -z(s@3wAb*emyYaR;iHcH>_VB{q_t!57p2s-1j5|#LPx4-K%!y -zd}b{>iJx!HyvG?0@ChKP1}-a}Uj6JsGauw^|^>-0aZam&$RAq#;&k-tbyum%J(e2axjojO(^_pm(6%_x3Fv&202AH{O`#|o%ZB$jRKfBSz}UEj -zSbcek;oLR3w`WFMnwIkPoVNr!lm-y=2#61>7#=vOLyvX6vU>Q8X@sxyf%wjdGf`2d -z&H=Hh2qea#u0#4?zw$p%!zXu0gY5C}i}Y!QMISqAdA5Wn4i-ElJlX>__bL#U=HdhQ -z^nyu5=^E6!pF@^jIug9lWpE&8%1xD5?#omdL5HQOGJE|o^bcO`&mMi!}9xGWeB1uz5KAh7%HO@Az-AR -zP8y1vVxrQULLA3W`F^f}3kJt);F^?xKT^owaa)HP)>-uvLUSY4aiMMJbK|)JN-%rJ -z37NJXuYhp`ejs9ACKf6Q?a8~^QaV8(!n_w{kS+1W>EeBSHHBqgk+sP-~QX$CdhMxBXEWOJf8>+IAxS}?hJO1u0-g~?aTM2ko=lx@cWrVv96yi4Y -zY2uXNsta=YIwTxRu=Y>>Hse;Pb;T=WgYPj6qySYws=r-hM5fFs9t0^oCN0j@a~`h& -zlzSBJZj@f)g5fG&S}W_f2D5#yy~6w+p>3bWS>G!O(v)~GGzUOGFVg!B_<0&w!_8qI -ze)S_p1w`|FZW||{xL*PW<+1scI_ch`g-L!C5rURr(opLj`Abne{&wP@EPUy<;Mf#A -zNc(c|m_`v@w-iQ1|T-AgrNBmM=7G3MPcL(Khom)nTP<6!x5R8U!xx -zA!V#S+y3d%!g&!p{x!UZ$1A8=fM44KDn1r7Zd}+m+5HX!%3E-coS|4n?LEZb5oUd2 -zCBrZ(Jy?}K`b|;)GiN^JPy(MK59oXv?VJL?I<%?`05Pr)BPSF?JGPw#wn&KxJ^1aG -z&wYriKC!9?fM;wfvBd#XeQ?-<5P!2p6sgA_)&c5-qilIA4jIr3f{m~GR^}N6dJp}Q -zSe1P9qG{1FH-eK-uQa_3Ze -z_18Z8b)NW^&IPum*wJLVEx@sj24^uM?{zly6~E}>J9cnp`kJg4DPdJDo6Jh)fddLd0)+?qZeT)c8=u6U)4$JP)$gmkVXp-9(wXrdWlVT|<1h{&Z3 -zJ#}j@*$~}2L`uYy9oqf9UZ6dWB^d768d2>F~K(?H3J{mT3S1$^GJ^+i~R^#S*dD|Q~PS48r;k{1qs%k7j -zlH2!lAk`r-J=j0{NjPi?7vc&j)vePa*MR4owWUXJqsc_IRBJjUg`~p0_Cd|VlMTIB -z77l)13EtD8z(OG1EuuMxiU@8O?5jAss^bq&!jb$0jPJb<{=`G3L92Rh@i)A=-cW3+ -zZSHoaUFP^*Rj=$dg>Q&|9>Cs{y^kX?cko385NkM(#GV6)*hkH*V5vjqs_M3Virn&0 -zD&KpAcIC5|#W~YtFLVTbUt#q17fQk9dgvRnd@S1%e9WL|Fc!R1joL$;9>Zk#IvRUF -z>4#K)q0I@mE*#g7lZmu`)Q6BusivLE@n#CE>J4noQ%i#Z<9RiZ{Dk5`S{iU$!WX?Ie> -z!A-;qzw<=Dg`4EUz}xru;X>cZt3PW7J7hdNpEuhbUHzKVj%{cryAVrYD8Qb&U&k%g -zyt1LLkYB&v8ZSR^$OhjofgO%ykcv%z*sw$>6~&N_;Nav5NnfA}W6s2DWeZhD$`=?15X`)6gRWBbzK!9=KAB63ayt8)=MAB^EEuP7AqzK8G@(o5kF)gj!S -zf(B&nZ?h#~W)Je65G19A?ht>N<4>gdx7$B=yjLsGaH(^B*@>^$)FHFWSawb?ZJ~jj -znrWSTSzn-?xaCPq(9Jd17n1fH4y=IS{uMI7-*;i?FpY@zc}i@Ps~F; -z-3y@kwqmm7YEOLHGYfs2?6BA=7P>FpKbFff1hq&v?Y-$a4?c9FcK|3fc*_G6#cQBS -zl=NaT2XE=#V3J5FhafrdxM0|Y*ki}^#>7FyqMLWgy5P)i-g~}j;iZ&@Jtwnunm@@> -z_Rx+tpii5vO7Sti{(8Rcvq0NyV2ocs)D4dgV|cvH?h%8_a?VNu@TIT0i$V;9056d2 -z+Gt79i-Jm#xVN0%fBm+QbcE02*Kqr+$em1>SBK2dd>*2p2|uW*3sw3PZh^GwMM@X~qQd8(bAbnku8i;A@-nRNUPw2K$O0;Ti7TqD$c^m;BNTLF7O$Q8i8 -z$G*8<;)@aUpkv@&!?`8;pwO#KuERBG?KOKnEv)(uZ}rG3^^Nz^4sco2ivhTO&rR#E -zRZs0a`k&WjZ6J`(eYmpMS!9>lZeG1`RKbKBGju{i&x+eMx^PqK#fE%?c4u=69c)_F -z>}5w3%1wU6NC~Jt*^LaOd -z!r^RGhE}O7$bRKo5QOa4^1$cP22#@u*|F;8|N8kH-C{D<02hF@j;1so=8uqEKTUR>A_UL8f -zI7-x~K;@^l`I3?0UIRm0Z%ud02_ZiGYS@O>L5kvw9<7XNFGS##DmgHFa#SA9S3Y_B -zGBN^~;n7#09*#6HjjW{_Rp1p8b^4?;sdqMKkS5rpTxaw=esbay@=RsBx^!9`<3%O5 -zqa|mDKb%8zz*`-)#PZZj#&8GQvQONXZL6b+2K6mxP)#);A^CdIJ~gBTxh)pppPVwc -z23Z~D0Q`DDUpd3;b9e=;&qJJcSu2hNZX$mhETj(+R!5Fr>2eH>IM-%g$^;|WnfMBb -z4xx-wKwluTSpX};btn}EoXAE{?XwCq(boO`sKPr23F%N75q#cJlGL1-x7L5xUlO@B1>)={iLh-gQU0Z}-J< -zhk2F3R@m{LBl^%|v07_Xxg845WyV`%qqdCvLg$u-hiu^$l*k -z_e?D9S5v!VMg-{&+xatd{&^atq*uMsQzKOZP$Hv`)&h@&iiTgBY@RiX@-H7nAHs!8 -zSRs;ciJ~-a;}Z4qmL4gub4mFssKO=#c{uLYXnS+Aekw{D*uE<-ZKU-ep+!8B7EP!G -zC9hJ}$gBs+y`STo-s%V6PL>woGJTq{8!)(HH21~fuN&;U2NoIn=eZCW?CROWXQJ=t -zxmhHd>ECgFLu@Hm}7pfN>6`~~=9cA)bX=A$fX>+xRL -z2$JOCq(^AdoveF1w^O_NUCYZPuu!TN>LPrDuhPJ%Hu<7pFSLNAaK8}smi2BPo+ -z@>J%|mp##iWaBh13hb6wvNmU*_0MBs2V^2G1fzE;y?i&n-l4}S-mC4R8VT+y7OtTy -zW}T%V;FAT8H53G}k+H#IVcv~$&!?R0+$WF9H#_p3JOjo^b%Bt;**o<4@(n)7SU{sU -zPj)O016!GtrS!dSK=+YfyVUE)6Do9@uC-E4;SxVa6nPOLU%CVd8^!iV-~q_=wiRa4 -zRjz(?JptOnK*nvBkcH6q(xaBa-`+(;GBwcDNgcDec7u8CS{}6_Ry2Q~wTmnF3g_2D -z{iyZ;ma%Pyv?_ay9F>7aq-N{d6Gw8 -zwXt{QypMMbf}O@VYdtd!rqXuTTJIbT{uXCj_%2CjbC}_fws~78xRgEZ?^j!mY8$2v+xD+^agy^?+EnBi2dw7u>`oK -z;xxTXHYUZJ?}5p5g=Rkl!s&eK*4fA#?!8@?awV)QAT0ikJXI*Q+y>SR0-`FD(C9Ii -zffq_(B{s2rj6*lN^T1A-)}tc}>G!1v{JK0xsbu5RK@^4i?tAE9QeOHD7=db1FQnv4 -z*YYXE^}XNJ%_r6PRg@TxB~q?U -zZRj}}13}s970Cd6jzXgcCVLEMQZ}Q?z8Y}}_zTDq3~IlcNh>#N7R?hLQa$O(lK9rl -zfbU$9d-kAmQ`IZ`Ko8pq7hg~c(!rk+F!?@khAi8Uti(0yb2=uf -z4$XT?j~m4d8`(WWne|rUWBYF@quzF{1TelQZ!+sksUtF(_glym9ELz0!pRZQWKM0#Z(QV-^f6;^ZX7Q=munfzSmBclt* -zxfRoN%zMu#gDgirw6d&)Tuiir^=WBZgVHkjyGgiiyYAd(3J*T|OKw(`#;BagCh{_0 -zei|2>$`R`(HASI1hb)*!b)5RV*PT~;ZuKPVg;2r|6xZ1bPO?46LVK{$>}PGt`vS`M -z&%RCn^MuGVFBsikPnytbgyMc!5Mnp@{bRitOuGnK>71Y1jyJ -zoaLN{uMhWP`+GBjFPr5h!pwN2i+vU(7vG}|_WLbpK{;Gv+f%1Wl^&dmK?|Qnt_@g( -zz1yEgm!FAxkH_tsu!;R#Rx@d!qwgUAhjhrm*+u=gW22!aCt=iRKt;h3=!UxIf+6?O -zJ`H5&T>pSDef;EW4|Gu#=Q%TQdc=5N@iT3_B+jP;hhNIMoD7)z@~ncBzdwEY+ku(^ -zJnf)DJ}gJz$?TfNWUlHBY)zQQ8SpCqB(nC?gsGbYo)(=PStoAD6hP4Ir; -zC$o==ULe1XnmP*38Ty{@me4T`8NWI!*ua{0cxcLw!+f)}M1Jqwyhu@fVPNE%p7Zkk -z^}J@D^C*|_$GTW?y -zX$T4U0j+#M(b5)x4X@~9%>}DqBy_%BC&p-wb8Ne;-+R?VXY4HV7;&y}gci$+$U!GS -zIl=iDUvA5TZvb-~dk(`rMyzK25Yp9syyp>efK{D(7-XtnDuvm{MjqlV^2B|VJdsoB -zQK0G;`#O(V`ID~=Qx4qFV2etw(yALlhL>07=FHTEDyFH}9u>bZNv?d?@9|zrWZ}me -zoJ<=Y;(v%JGbSkTBN6P)`!GTXt*GnrOIUDb#||tUu@@G*aXiXajticNjY*Lw? -zx0Jw9$dk_PGzr-Ul(BPPvWzQQNMtA4&O>6}2Zv7pIsFXR@Y9l}#F7&FW@fI*C8obL -zIwJl&D-yneeg~k?0KZMN`;kcp&hF177rjNlE`+8;n{V&l=0Og>D*nI-hlt>M5A(v^ -z`yF!b9C4pBc%XRCc?3vYezKUI!2LNWlw_d&E5kaH%XU-SlT -z@*3(scC#lN@N`}T-TPL}+=_h+M2;k^@G@m3ZJMV(st~Mk>{>Y55Wr;u;dLAYWF+&h -z2bVb<_WeORqEJIG>9B}9C4${lxp}_x@1Qs?8akqLV%YFAZx~kihSt5LtlIjkLTdgA -zyY-RqQYbBqI%a|OVGJ8IQ>!2+u3r08K2DyoRz7mC@qL--7D<0*NBk(#F);Q_wI0%;t&p?# -zd@de1cSk(Y4(?@^^_*f#aX&(4=U&o+v$+)8n9ZNRE!_vJ@=~7n6GJ>Qoy`Nr46z&X -zn!fahhj#a32b_k!RpeG#Hw4Qc?{ob2(CWn4H+;bYZHn}`CFoGqD{P3#))|?J{V6q_ -zUss@0N}?`wTOCqRxt#YQi+FFegsSQS*joo>fiMGYaOi+u#g)CK`+jD&>3;RfwRJhg -zK+C_~|C)K3aFG;^&JCN4GI!&MvO9eX4-<|jsya7LE6S#~v0tdG@V;JLoB{w@$ap5D_9bK6rL-`Q9&^;$x)p1MbKvrPmyn1nW)Bs!TCCKkwsmfa) -zPsLkDOf$LUq6os&v=G|H9uplavF>k5((>F2L)i7WS6|7e -zm*XG7Fv&sC@iX6%Xz^Y?OlDAzQptn1kH#~~#T^3>>FPdh-qO%>3gh;U9N7f8u(a`s -z*FQ!hv#ldgZ#BI&HjW*cttGq&J_)A}%?Ttq`NGQ&s4t&hx(7&aDfe5WRDlmf(#=En -zTD~8_L{{d4(N`;)>8*jK)K$pShJukL9aE;<`xgq8TJ{ -zjg9G0pYT<}wTrrzSM0LJ!{zv51;s(bXooDMBI$Ctn%3p-9{tW?5?3CH*quE#ZCwGRm^G_Bi89Kb8vboK&&awp$8bpJ@1 -zXxgg*Xd3*gBkl+VUV1S7LFRo6DY5WKt1$swF~c!IxjC~ -z8TZ_LxEfHclh03H8Y84+MxZgL4p53Duk^WAt6D`rr}$6Va;{x)C%sa#Gg!(V&o6>vDl&@Og?Rv8=1acY={H%T~d1q>;S7p@Vqjt^l!ceD4vKilhr40ivREZw -z?yrY94u6 -zh3&yOSLqc|^-o0U0x?diW_j#OX*-{@2!FbAhK;MZ2jUx1Q39&Cp|3o2v+d2aaBg|H -z_g#wVleUywk7ZY!dXU+TX%+Ibxs9Xip;>bluZH<6y-59ScN=xeDZRe8_yCoMJA0Cj -z2f)?f;1wOpnFq=C+upj$uaS#S9aKNd!h;py^hiZC3G>|M?yO(|H-Gy@_k@K0-US{5utW809W(Q9!~^eul9lwbT6~If?Ik>Bvc}o*xSO50 -z&BD8DM9^6W?zz^qFGjKF#dUo4@a~)MN&?Z3cHVvz3vQENQ05Y?tU7|9{OXq=RN|Ca -z;Y%(z!Di0&K9(i-Ru1q3HTeqFr;=hX>Ck%iBMs3LxbDxV4uf_pFA|F4 -zOWvvTiGvGT@ddyKfG$T>_(bN1RY}?7p>C12dbE5@b{5WCsQUmoaFj2Le&(82kJxoS -zCnct41j+9w!BqZrD$o>KxIHA7P-LH#tYGiehjGtaZY;g^ATV)qlo(^_H+x#;pIOT_ -zbc}f%i2VI2_N_WlGry~p4!M`8D;k0z*x#yRNP=7Eu@M?*m_s8lYBx3QYsHEVmsb8< -z&5e`m9t6+}clCWFs2o0w-G)+O%d#9deLE$Hpj?~!XhkdTRxjA(DLtJ-$5IWEuFCOD -z4X)cC=gc+7bHuP~tsLJ&b7u-#qP`t&Ux=A+mRH~ -zMtVNmi*p4nfIZ8g10M9f!mo%P_D@_;WSjj;#bjBY=1PCnF+qYKfR1qVItqZ&77$!G -z`e!1gKhKq@bjo_iRb^{qw!ncx2>p=OWLoQFp -z45QCLNCwX=-6?fQFCZg7AcCKzS1y@+E_l&FuH0BBOZ76GzM%9l*b$ZcHO49qzcgKQ -zU@kd^?*sS(SjQDM9}wiBujMV6{hoy*FHcA1<#DoHb-9J(_|IviQi9&h!?vjDQfrFo -zqMYq8(I*sq2DWbGxp1OF4k~@M&YZt}lCKR3D$mJ>8}ossaenY};&Piyji){ONxXUS -z6=zYC<)mBR*z^H`0Rd2VSEwO_;WFY{L9r;uzGo*+Z#Biqu-dJXbU}Q}gaprU<=xfy -z@N?Q8cs&n4ecBg~YbyvHG}meFevkW1>1QUi(YknB98-|ar=LaAd(ASA0;5)mMFOS$`H-`z4aF>Xz&&wHhGpOv~&EkM~1b>3r>QFWM -zXH0S@_IA+0J45GHfmSmj)avdEYTE29elW53K}^({4*X2AUHR}5oW(R1V~R7Y4@{Ja -zTCjy4xfRCE#&VeW<$j=pf<|MPM-xHe_OLt>j>Sc{&dnukjT}G>46Hn4wxib&j@%xN -zOKPiX(`N|dCduQsl64a_L5zLqVL{q&Ta7w`Q%ZBbZf&?^uSjgizOP1U9tpOLzo>n?Z7NIC25d>#GC5lgn4#1CcZJk$dmS!0c65y3F259;waiM+g -z1Dg(mb|e4}Z?nqH#vinp%sqJdGpoQ=#nYwKXA0#Q3oDPcl_3i}P`8h)*1b4&z#2fY -z8CfbHnI2K66$7vwU8xt9ZqsC&%>!I~xA#ocCkU-C;wK(x=R*T*BVJdnFMFP>^MKEp -zZ=k^TYXQ=%BNuA$Qv|xY?zqag(cqqQ2d*PKT5kF6m8u -z>^|^#l=sb4VsL$w7Cwmr?znesS&whNpO7!_$Hb*kMQb=}mo8{rmz>>)e-U1gMGARq -zz;0krx<9P{D9zqYD#v#-?9k6QKwU47%lW*LmdW)=1y|?^uxPTr90FTv+PQLMrsvCOj^3CwzN>P3u<u2U&%v?w_?sg%F0SJm)of<>8C!! -zUt|Yiys|f3FQ*yqiQ_7a=0yjR>AHR{d@8T1w!gm!H-QdaUE`@wAy8vdzd$**E70lG -zoj_cY+{Yzj=rPOj7U0=>z)PvHFX4khZMa`wSg?9wnhluF3j@!cpEkviYns90!YwEP{rX>xwycvvf=;%=&)oM45Bn9`c>5~r2@Z@L6`RLC3F8VYN -zJ?RjK-M6d`hG=AQFKy##ImdC7&lMfKOml=Yw}^|tT!1j(+d;o_{>RvrB*~Ja&?_+y -zOOW9HM{1L2FT?EDwkm&SggbhJgdQVLBwodP`q%_*DyG-PwR0ITB-`zrJNlg5h5%p8 -zIdAEAU_IA~Y?J|T0bq}wz28X|$`vNrwM&ActfR9m7^?dIZSgtBW%s>YTUm4{zV|Z7 -z#ruH&tg4{Nz`O^jugID?d5z2ao6b?!;w)(`+@~X9guL`AE^xF7y~PvZNv&vTM&RLG@)S -zm38P{UE!mdRTm%`r@lFoq0e*l#7W+Kf1)KB1HWB@SLx4JJT5f?Zv6IU;u%e6`?erX -zEANs`7rPtD!RI#v+AVI~Z^Xf|4AvWm-$$3}1aA{i{;U9{KT&s<<%v*LqHB{(mKjw` -za`E6X>SR-j&#+bY^{=VEd_=ntf)~F&?sE&ZQNr(R -z?>GJ&OUvdq-#s4OLL?4UzV^(1%Sha^gVpyYh9bQm`%cA8}{M#pK+00ixT>6cX*`3)tWEipUH2ZW!Z -z;1qOF=gcxLPRghKM*{TP86LfGAt7Cr*U-F1qg0?s`p(sKJ@4SRwMpzpRVeW(_;WT%8&=r%UuAokJDylO%t -zK>}H|)%3I>H>0~$)KQP#WkSa5C`}u8CvoMrh&=EZ7Q9~ZP{XV6 -zywVx&jhH~jGlrsP`y23{h7-cn1hl2KJdoE&x9SFIAIw|XdhEQVLG=w!6&)^)SKEy-!wyYyw2(Nf#h0Usr-xUtJlW84^KsqQ6Y!I(t&RIV7%yKUu -z$$vKOj}sMSHnsS09Lw)^wF`YJ3r|s!sYRcWC$2XArs#JpX(*3Bbrn6xpYh?{_r4t> -z7`|;rQbelr1(G`>nOfu2hyUktB~(1OSWQG?%*0pM -z!zk(Q4)_@OL4Zpq7#?94j<{gmwv&itsEnFQ=5Gi1}rmSbl=x+l^K|0OdUFv -zv{Cj%Jw1u?-9^5wd}^loXnrOuw;e -z@HeTQn<>;#88^VQJ@=2FgZabfmapNle6(gAI7Uv| -zMdrtul<0y!oT#j=gRQvYH|F}t6(HToxF?>YLnAVj$BGw$^63(Gy5pDuPn(@m0`v2A -zo#(frP7_$1^Y1B2{a91m<(hl-lUCh5b6>sA<%YP63aSQHK2ImF4r4xj-uK&vu29G7 -zws|x{VmJj*bRF=P9!{ZjJrdXBj6RgkVPnrJ1K!4CNB>T)A(c9kN~_DvAOnh@#qg7O -zKiYm)ewyGL-P4H*Bq05y=}~&cSMj|0u`2PK_dbnP^yKV!j{KC$q&+ey7!9o&>yuyL -z+yl%)41_m@-gV^uJT>z -zU3!*tRGQ~#5AD>6b6Mc*TklYk_j&4&Rt|a~g2OPX>lH#cI%u63mV|O?edQhtXB)^} -z%0R`~4SsS`@p0}=ex5!IV9E}FpFA1Qdi8_L_gwx)vG13}z2XO#SUS|7)`3g>`0Pm> -zn*L^siuXS6nv#s1{%DEu?iVKX{8|ViO{l?G&Xc{aF;Q*CI-?zIYhW9-m}inUVi75^012id*S^mQXD;C5$?%(@Yov6S?1npKp5*dp1kDg -zHN}zwrbs~vrkA~2b;{GWEUVl4_gYrY42=Oy+#fxBy|0xGlo;ZaWxm -zob$CE_k@jFvD>FfQ$@mHMOuYh;>!m<_8sY1eS?V(<*lx47pr`ViN3ga1@ZIB?OD9> -z^1KRc^khMui(lmWM&GFhO4BNMw#l54gn2*_zsQYCPr>Cg*%t8}Vc+9lGCu&51Dac3 -zscKJi-OzPw7meky>%_+>fEpud;ZTbr$1B&H^GN%;<2;<{fsE5}6!6sy1>4L`G;Pbe -z0ySDDbTi<1pAg=1YXjYHZUWs=;-iV@VHRP!Rg3SMtUI?}pZ7S;`T+3W5AsEiG|FsW -ztaEqXZ%$RPK!Q-=5leC@+$Xf`3X&G!B!Y)3O4i)lK7^EUZybi_{m*w1+m@bU2cae3 -zL$2_!Nl4UA@}3A9J}YuC{TY<;&hA3{^6e=mU%g^nx}lHyiFLJK{o79!tE=C8T)IJ0C|Gab0Ma)h_MUK`6Ba=U(7l#PX{dAe5L&$A1`L+%pHL$ -z<%$wtqfGWod9mzL&0>J}_+jQ-#Y|t=xMKOTqx(vT3-q|tJi`q#@z&|HxTZxT^^K`l -z27_Y{`1}%<9d2j5dC|Uro?etQGSZ$*q)_qx1n#uo%=FTuDz}SG?#0Dd4WIV&J*&0- -z@X~s&ej}&CRo5Zzt8>S=Rs97-PDF}laDF_ -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 -z3!Q+v3eW@k;9; -zyh{5l--r%e(yC{vxJ9cJmin#Q*rCL2a?y5&=b|-ELxr8#63$4z$s&y+q8DLe5in6oc8MI2k2d?=|MY8oLZ`0qK(~{z1 -zxbc|Wy{t4H;X+q9+*MjCNVIwg5Dsa42((x7yoIPZl{B>3QrUSoqkCMb^u8}Lsuj)g -z?MG%fFXj`Z+RA=M92oO_x3aoR3pg&~32)i=>%MUv^@xoV4_t|OR8NHbzPxSmMZX3a -zdi8=Kvht=i@R5FYa69|J5yXoL$?t87KlhW3uUf4zm4xF&*fl&~PY_~GPkgCy39=a5 -zgLzc4`Z_F7V^4lFmj9YCPaA;Vx9qGCsvjMGcM(LE6{s5X8lAtPyyxnXyyLN23TZAi -zF*R=)ChrYI7`U#m&p6YCh=C5jw>Irr5B+k8kptep>G!%oNXCA~OC!?n`&Qjji~S(< -zfa4iHweQW!wDXxL+sC;T>dYd*7I!}Da{73y)J~gJ -zNKd~o9(|wM@7D)q;X<;5t8=>DvR1+$Yiuq3u$D+2fKEex961gF%T$pGA2ONU855$ArkbIu*LFKyM@=&2iyW1~*q@ -zWG^{DQTlDKVIAdWOQRrtzgrJ#=qR>7YGsE!N55Go$;bUYd(0!l{AlI2r4{F_Rm_cf -z#r_>zgJYCW!uclLNU8PizH$+alXtxmnU%JbZy4+5t~|XSv%rzGyL*zo&x~|lGgL`? -zhV(x3TyMFz2T!9!gdjcvIVI?i-+Nkm?3DWRN_$``$n2_->muhg*EbmfwXU%$g%8;7 -z8Iv2bHyQ@4>*n2BU!Q&w{Q5k3nC{gQSV#ODC;4cXB{O;FGRgL)gLz$iJfP%yeTD`x -z_rS^*xkGbr`BQb?3K3VmoQVA!{apv&GXuvJHa&(L8O6`RWe4q3Y82w|^eT+ghS4B! -z#@=%ZI&2F!>7p-dfj_s$bM=dKy<+`Rkr -z_ZeiLBJ)Jj=QYbBdd0uXn+z?oD|@o#9#7y&@1;D-&Kh*@^*o5W -zW|yB0%=_{2<3HsD(i*dv33}h%jEEQ;W}B$2={9koN541n6~Pt;YMj -zr^73s-w^xrXp7K%fe_;yBY1KEM?kp02olT0Pu-rIYKWzTJ8(@V6l2kzxvi#jC)JD^ -zN{fJcDiypuWBu^i^EZDBr{`FFqXIXp*Qct#866q>7)q1uj-Cg|QoOmTEY0W3+H7T$ -z^S9-HkDmIHxwGd!CDkPnuRf_JgyhuU)~tS0Jiilu9Lg_6Y+IgK-adJ5_<08)+ -z!}EVcdoR&H`&|X!tI=EYg%cO#$g`!{PTR4^q>MI@dA_5Et9J}?hV?$qXreglo$AwseHSVF{YPoY6MauVB*OoBBiWI(K^`^ -zqTYaE&U{#DRB$pb0%Nm -zNLX(k_H;q4>qc*8r<=j6q@s-h+0s7VogjUOF9P#lv0-5^06 -zN9{H|H*IR^$@C&RD4wv#jS;ra@}X^yX1RR6VD3X|wPlS&*fyL>LkRf=cZ=u8hY -zAD>;htbV>dAcVX+-%*b^9yJ}Tx(W|7fHJ0@q`7XEI-40^vGkGa)%dhhur -zp}C=|yeB~YmOiM5Nq84AdDyds{a_I4aYtVSn5~f>&Hd8uT#hMDOy|=r_eigPm)Kw7 -z#r+--X>f-M -z3k%FGTS#dl&lK5n2}50C^??M@A&To-*uQlw|2*VMY2SiActj>88?PJsWo&VR)8mic -z&(|IGmhk4$|;Ioo7 -zC%XaV%-n%3C8?zhTik=bMeSr%-Fu-$`e#VNUuJNylEI;Mec~C#DTt@HEu$wyo3BeS -zJGSsvHtY4!f>%TD(ZGq%ZgKE3cr=nM{+*90h`$3k&6t~v7 -z@?}QTQ<2c(U;`WG{-6}N2uQ^iJz6oSy -zesGEquvg3QJ5ADhHRuQT)dv&|c;GW^m7CqqN3sr`LgCuo}%ES-^X3@^SEoC -zZ3sS%@t8vB;KR;yF0_Yo3FobT#xBo(qurx0SI^g~v~D%;QLzi{a;wbxlU40!WEW3X -zb05S!yVkF4fQKMFm{|{02eS8QBb~IbWh)2E>K*~)9@e_I_|SXMA&}M -z9f14Yb@Wh5k1S&cRgCytCEg%e;zU(-1G7R9tL_?4C&EYFSM$5VnA@N`tWV5r1?=sX9k^->3!_Pj9VKF;NLx4MaB0*)6LE|KR=a#BSd6+9`=#i -zHuDuSkOx8KT(6{N0FLoLuO7gf#~Dh86EcPPKH_qwvXUpAZ&_q+7wgCb&9K5q# -zM2oK7JHpZ?42R@^EwHS09nFhiTyp!XTwyd?wkJN1elz;GeC)e#)YY(jV@bXwKfVN$ -z8gy~;LhX04{KU!no7X~LgN_N$GhpLbjqVISx0~(}L(V%_Y3rhBmLQ_cMC>E_d!MWU -z5TGIUFV@z-om8LweBhzD`3Sn>oVV=71whH@xotUc4xM9$R+naVU=KcP$xfT|EoQTG -z1&?7(L{bPMsHAe=)Ic637@+EIr9P5pHuEfGAO4d3pO^SX%DBZtniIx<<5WT!50n50 -zg&cHw(%vH!8ffIHc7!84O(es2;6$FWY_PjCd4{Sdo{)naN=&KKc9d-DNWy(IgWuH0 -z!Gq;zo#o`WHs9N%Fq$54qIm_Ue0L|Llu9%^4_+v9e`XT)k&ISr`t%JIseP7U)6cL8$_a{3#6n^4L_Kfk>5_=GXyupGIt)_`6@b@oK<%~lqv -z;UjzAXA&@02zgI0dI(N(6MftvuRKH_O9=Gja8o=HkeXkndD}Nr{}gMNve7Iw&DmRD -zYu?U-4CfJoDXe~9nXjx=e5d`iyCLjI-*hIcbHqkEz6ji5L%L6E?(LL4WLJ+sAoU{x -z_j@ySudGtgV8CH7cs^cWPsH?og9kaU=3C4))seC!FjsmQ^7+)|hM}u$%Xc=szl%?S -zp3(ucGyAIbvI5x?tszM#fgsM41rg`Fyj_Uc-S=>}S`}f;#TK)%0rYRgC8xs1GrhKq -zT$W~fg?s53W`sPV3%-w4p34mF4ZHM8*_fA!of_=fMpcLNSjP>Z;i*n!-hGwdF8o-N -z#nhzeY6eK&q|GB}5YBacfKj*)*HJc`u_H!!NUIJG)X02}O6%S)R}=3A5luGA13?BH -z;=T0A)&~`O51#N^c$Ft={LNI|iXoZ#s3o0a-`m6Sgl|HajA*>C#&dAlM5rNjgLXUf -z3S>XiN)^+SRcGnTC^G`tfkg{;7B|jE;NhaA+W~Q?6BhUA^0k#^DykGfRK_zs%N|EveEm+lwaqG`?-8N*x2fxT)rn|73Z!JHlg9{mmmD4nq{bZ -z1|E1ib?nR)?YkayaFzh>`^_DA@6#$8mL_xG+M2%IbDr<x2Qw8-(yUT*n*9N -z_VqJIqa4+HW|;LfSK_sdk;}=|F){VtuWr&BfD+rx8}e}b8x#c#v@^Po9lsdEat3qF0_+8 -z(=wzw{^c3J#| -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 -z6{qoD$ghYGmAjxeCu@BfUFR)lW@c4+ -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 -z2l;$PL-php-i5vw -z^95C0YGCsOJNKFl-Mu^4pU4)xR3WWpY3D189KwCd7v)Qy0{$#e9SZ9(oiAQT6W>Zh -zz*9DWx3KNcHvJUAw2Y#DUbA8op>(tfav;%V-Av`1q_^vgd`6^nL*Bo`#pBC%t%N7I+0cu!4`m*9J5LhDQIiY%CN*iO -zm-Vc@VzqcU^FAQa)%Drydm{?-F%*E6?^;!=9C67|68J7m7b@N(*hfx{AS$LK!+kXQ -z3wd~y?dFj1n2Uz#BBY9k53jiH$fi80q8Z>nTH6whU -zs_Itws3Oe9dd$Y96;l95IQiJ;J`Qrm@0Xe0M-NQoeiwy1PCwmG9LUk4!Q3ahCB^Zn -zme0QVOPqMa&%FT&P5MRn&ecfjVM=RQU1`)$RxiX>(q+@t^W-}SQEODC{D|G1M#a48N$H=oKc=-Fx{ -zgGkQVs}GU9o|cbWDY%pd4U55)Iq*mphm@+mqF#eO*n!PtPl@lY4pV&wen~?}Sm1Pk -z>e9CLfPM}$wRFkxAboO#bq~+RV|%HlLiwmA9Zj+h9jV-?P?2~u;lY9{UjgmY1C;w9 -zgYipyi@Zn)UYGBefnDvnZ?(apOWb}%bfXAw>FJX;fv?2p-Z^-(RACQG;|o|u9^dS|dUdY6 -zVvCzqa?e^))8mnGb&7onMG)8ZskfmyJt$8jq-+*czjX)Lu`p4e#8)`o|+IGX76L;8nXd9NLk?nnVNqg&{F{p+8H2j~Y>UE=dc@F3{l`@#P6 -zIF7X9OI@Z(t2a@3x5F{Eic*17CS(2aGDJ6wvv!0*7IrNr-o(b^6?~4m%9$nMRPwV; -zCRSG(;FMjQJGJyAJw9Sr(&s!LfVWR&99(q>KiPdXtuUT;K5yAV#^u=0;`ub*r&6Ln -zo~Yfc^~7gvFmp5A@$kSB427j{-Dy9W)s3Xd0j+ZNsoTqSABQM?l?c%wVw7JU3@$*! -zq13qG9t#HvEVHiWKN~UZGCD8gD+qfG_lcyo@5oZ8o$%UQ@RtU$@jRg|i3bd(bWHAz -z%_eBKjB^9AhYYR*!F-;t-5yhX`ye`Y)rG)#>_)Dmlgn*f%8w5P_1Kw2>=8 -z{N|-+s`~Ac`&sklb$J!xJ#M{~;lY5#g;(A*r-Ea>dSB@b#5-fV?8>0p?pxGypw`dO -zcfI7wq0v)%UHn8M9KCP7@w_7a|M^3DFNdg{lPXVmoV<^iV})pemKHxv!iqhBQwVi1 -zE*`pQpaGO-;NPw+7c=dR0ekvHf( -zg@1P=-kLzNU{SRFt`&uR7cJ&W%Ys<(>4aKZ^n`FLecI`3`A5{CBi5 -z`xewlbo95)WZHwO$q7>R1@%Wf-EPmN%>E -zbGGs=Hyjk7&+pD$nQz%BbR=#ZVT3#~-!AyQ(P{5J1sgW~N#U`!9Mi?-zC#@iHymvHv>TQ0?6i<5T0LmD1EL5jBLIOoxaBRyN?EC-U2#}_9!0F -z7<{RYQ77vj+(%3)=M-!v$q|u4BKkrYTp@)D_n_IT#N*y!Rx{spwZK=4uHj6oH%&;! -zM%M|lA;?RG!tTY$L|O`oB`0@3v%Zr#M3-xFE(*1VGMYVhk2j)Kg635ZV)qAlwB+~6 -zxM8>#k3L@UP&wC%z@3!Z9q@|F#!W#vS)%uiM$ehXUihwoSr&57Q?etViFdA^uh-b( -zvf;_eLmp@1DWds;XlVs#@15r1QP8bSK2}|Jw>1n$j?b#wA}zt3}W -zbNg77Gro6nP;>5PUtsXH| -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 -zD*E1@HM_(BTi}|5UWXh!wNHzCJJbvb(1amBV -z2+X84V|$KGrhkXV+6E%opWM|gS#ZuxQlMVub0}cd^gzh$GH$e;yXo0D{^&|y2>P9r -zf6v`zU;bJ+NFMdxC -zUrSf`x#D8A(0&&&QKxfhHPd%7Jo)kG`{0i-m*LB_ -zd0WO*%d5xzC|O-IKjPU#_r3QC>#Hcxfvmnc_cPw;5)l2ASNbLS&9^da*CQTVFW~#O -zZhJ&^29iB~bYB*Fz+`KU&z3-g|R(JICiU -zOQ_)XZa!|Fs>3j>qWa>64@{kwhC3M?v3B;Tm3gmm5Z4>_P@Yf*Hk^rK5KnXoFaUEY+EV0mp9NKfg -ztCgb(UtuJjtVcv_z6h~OaShTBB&ub@CxNIeiaUPz+YJdX1)`nGn)Fd?Tz{8^&ZR_h`fWb -z2*_d4SFhhkZ4M{BzjUk1_$t;BxfzJow>XmMRv7>TdVO;0FR0Uu1drnJsk1MssY#u} -z2CKEBBfd<>?j%7SW<9GBLm*PMpocf>jDI2b;HZY-VPa^#d#=7H^sg&`y5$u{t{Gsz -z&N9dN;i>QwB~8NLyzf~zrzR#wxx2G%iu`qrPr3!#XXO*j@B7k&J9DMi;ec$Bz7X9y -zGOY0y6Lje=X3oQc3?>vGt_=|RfSyV1#pzc9z))}RSxuW%{T8%3Nw5(tMsL=ucE;j -zw6cY>pJ?1t>y4{@Jh~pnRTfmd+>wknV4snC`2v3aIqX_$veypB;NZeT7Do0B^<=o5 -z>gj{R&K??@Rh{<*CLv#Y*s$(S%E9;bEOS2#9Wi`V&3q6&Yz>{8Ut;3`_F}xZBaeX0 -zg6rd5WH#LX-4UdB*1E+0N&Jk94cwS5?NfD&^zx#8W1qvfpiyP+qtb9%_T&kF8{BbS -zMDgV9mtukL&9@le^{I6P%BxrBj1}}f?#CWbLdciyF-$%Snd6fHN{5!W4{fYMrXAb| -zCimij=(zNGEyPu9x+i2E&u87giEk5&XYmRz_~SQzIBqbrMVb4j%!_WaO0AEyU4G<& -z)cmZ|r&hrI7*5+~SPOctLo*7(r)lE%ah@21u=*2`KJ=)E9oc(h`;;0s@BPg64-W(t -zzS7qyeuk{%G`C$1Pp=1ifWA(#Bt}2Ox!vY3AmI_o_WSbV#hkn@ccE@P@OT3si~1Df -zyNmekPTC{KurF#5#NPF{T#1&)F*D*Cr{cqX^vP!X73!C^eAeD7qBLn-2eyKpr{Eu(RZOQ*W|+-A_uB(ebTZB1#xnY -z!sC1fpMNPQemasLftiDsGtUu;$5`s7typ~Hav0J<$4-x~qKUorjMz;&yj?gGLHcj@1EPnN9bsZ3dJC5whytUqmvL24o<%sgR2WE -z=N=KANbu=_GuC8IuMHz5IRf5erB>9vCcz(oiBm%!>C-b -zJ^@>a{6g++Zw%DX9QitC(LmbseN+qjqO6u?V_AT5*qxBk_kY2c1oYSq{SHEh#Tc4t -z8y(}itJKOOeI2)fcc({aIv?4eRNHX9Rd7aQUx~xpxAj4)>%cINTH5Usz4LIG&|dI_s>Lfr4H`@D?qWqyy|;~BBL>92wkJ@C-6%E0#%%6b4|#ro5>Mts#>Z?)!q -zTb*b%2q%w|X=Cj1#mnB^geSWKzT?Yzpt0Ud3nA5w13{7?kIY8qjn*@@Gr1++k>iI+ -zhFn5#&R#RUr#^x7tCaJ_Eg_)n4bjZgv|L|%T*P+>LW35K+%VW9=UXF8bcfj&$G5vm -zVB0+4TC`!uZM*RYYt`>f%ABuH=H#K>8QNiLUSkdu!)qbJ%ccFI_6at -zVjw3x@2zXazPM1n-#vcBg5$z%KllxMH@&P(=Pc2F_>9E0FPh?TmpLXFYi07}-Ex-W -zd5{xC&dm>{^mjuo?x9t%vU)sby|hDVp8fdDd0dS$R&gKDVpO`_!>Z>z_7qlyA%clA-o@p&XvKSXt>)}H*KABQ -zr6J$i*0Fd*G?2bAq7s~<4?5(bK3YGJW`6YnwNJ3 -zGy7y1S3zCuf%7uA`J4%a$8L!5emV$jU}9^k-+>0`LvUvr=7N?9#%-49{5lNbb7IH- -z8Z-CnAL_dWC%0|LLcFGG=O_lRaw!m;( -z8W-t*4v%zs;-2M_3{p7vWfwYrmj%3aF%_2#V0e+6P?Bv`_R$eO{*r@zO>_?BbmzOT -zzkpRCXW)(-(2Y+rVsBE-NQbuHp^SphrT^;j1#1BDczDo!?0AA0fkP?wCrpC5{(!ihy?G1OQ&L1u -zS>#1DQ$Gh}_=poERi^5KWufndlGOWeH4R0 -z+`{#a*w<~h_W?-G_rG+6f*&7OIgC -z2EX4w{Sle^TnZ$8`C*y?f4D2eP3R28cf`>67zNd4Aq(|;mD}RS_v>;QPeT`wxG7xf -z9-ml~i_^=?6N1xqXxllnMf2oC&r3Bd?rXTi^;joRVjVI`LTTHZF7N$d5m`GCM7)ZB -zIK`+Am*vg~JY;n0B(bl7?$v~|*XNWd(>MNJmF6`L3H9AYZ%Ad9FKdhr-kS)zbf)*8 -z*MI?M+a4o}i#Q_JtH05{$8jy*<_;bNB-1^lb*vG*Kg%M-Tgm;XOB}9_O3s5b^{SW; -zT}F=Z?1z_9JU?f3uEtcmw`sHKK!;7_l&TlLq}Dxx@h(DcB_zF+$KJ@g>U=Ot)%k;RQ=B_axqk-CxNM1 -zgD&y~C&9dY7HZ4A9{h7IdSuVoOLAVGagWn$pW^@|-{e;k{X5;nlQZG^qxJilus4rJr{*FkFMXdUZI(yLoZRe!%plT -zwKX&Aqj8L^OGQAolJ)DDR=pjL>u?b+#AZRBb2&QkIvyxF6px$G&7On(3h*)4JvH)Z -zQooN2qBF9W)V{NhN}ObT)tL!I(HEjivPQ+?ECRyC!}bl`ezVZK5NMUX4uFvGxqiU) -zxS=WMr9giv8qB35w->*Dq+x7(<%aYzC(&c|Qi9d3J4CLOpf#8?iejHG&<*P;kwG-X -zO*0(0*$4-whICdjsa-#vp!;%ZT`l)0Bn1Li3FaAn#3GA`nkKF -z$oA^*GCNFJ4*UH)So9&f=T^EQCh{Pm?{mEV1Z8wbF34Yh&Xwd3%L64I6Bkn46}Vh@svFxFOFce+cRDvvkN -z;>r}#*px(7hw;aR0n}mLm -z`;mUQujCu*XSeyu^KU7@HGHV`IO5vpWn}kjK3e0kLyv0CdFbGUUC`zC!$AcpaIUt# -zg6i$565#sHniI9pH|u|hDIIQOjk(U<8-MLUUB*0*ZbfuTe1n-P$6*WNYmq((`Dx)( -zCe5Jfg9Pz;>)8MW-`ZO>i})~bZ~$UJz3AVKKHgEXHxO+GFZxTf$KCGUa$LhWyO|S;vT41Dyc2~DC0Rc0pj(RS@F7FBl`&JQ8pU~k{a)cUM8BT>!ZG9 -zhG4NI2fqpUN0J;%ia%r0rdbpM8)RGea&70StLNNyUy4tz_MVvg>V&TS -zD@C6Nj5`mMb0l}q!$F#>l -zA6ngcTO|@6b;4tZcCi~STQXoI8SEtN6^4RCBKoz;tXe8ui#%js7qe5nxO0SLO-)Lo -z&Hda(uUvkxC=z!>nq-*oUiE;DO$VQa3)UqMzkXD@=pm5XeCnv_uspP58Xw$6n8W9w -zTV~nvJi=dwj$G(E%EF;XFxH#qvqvtk+c}L{XZFgmyA@~n0S9~q3J%Y`NZ*t=6_c=! -z>vj$ES@$Yb`9v-u;5+e{BGRu}T01E3gC6(*YZ}QaLs0nACePxdB`23HaVZfYctk}m -zq#0!7SFUTqvmX=tUDrAI8P=%~G(olod9g -z!(aO`O&di*z&4D$=kLCEgm=Q!Z!sSQbleyln#aHS_-BLQKAmVi{hsHc2xc9c!@ -z+*w!S>yx6;65JLOejncD{BtCm&(EvDsjs$1Wu+H%8cUEB&L~HpuAC$Z^YNUKiQ~5Z -zw#NB`FMYS>v#EGsjrEX&cE2Ce8cJbD+iS00*?>lGsaY|b)JWV5j$Siy5N1&3Y|djL -zHJ=_-v3J|6yn87RY>5iiLmHzoeMQ~*WDL()6U;r$J2r_%(`eg(`As9GB#>&!5Mx7K -zg_Q>i>uYw;g>MD+`oh|StB0gNwK*kIm9w|TGDlnQowb*aJXlUNN1Yvt`GiCNDRK|q -zc?-V|qXTz>NL?!DYY*2jx}AkbTn6(H{Sl5Cn7rD3Q2=mXC|uHg_(Qt6$*#^hN&5B& -z@UHlSaPp`@%Ah@b#G3NrZHE5TU~)?AK%d=57jx;X=w}eL@#zBdCG*m&N80mi((C;s -zReN8F3OzFq#MX)7T@r_$D+=y&U0IJnLG35(nycH%J@M%0&BLwhrKcZMWuP=il}Cxx -zIB%3jVRGHz`YLs*9H}Jf7Kjsu5IySocD=K|buZHtQ?OSCx)U8H9lMogS2kIyrNSeT -zAICG}?xwRf58amaATS|iSRF?wiCdGs@{M++9s~UDres|g-2KzcLWhiVZ@4Rwmv1VDy>$khzyod@>lj8WUi?^unWesq*sbDPZ-6;_42#}SK=id -z8~$`?wY`lqKf+>t4lL*LTIV_`);w}q4axnoDAlX&G9_}4f}KZ)7ZetR>QgT5BRGB5 -zZ&CWhP$S%81Kv=&3{EE+jpgfKF*(gvuFH5cupLR~);^;abvpe{=pi5Z&s<2j*kXp+IV)IB}VfQ$~xOT4Jj5YYY9pjA8o*+F~ -z-xwQMzKZgAMKdE>d6UH}qJXfk?A?MwF#AqLZw;Q@*j2|*@Sfw!()9!MsP^2(J9d2^ -zD_8fgCz|^(e>Tbwo8fO99ltLLZ;dSGk?n^7uZX_ruK^nSBu&eg$?#>Sd6d}WK^@C0 -zm(JXnlUYE6QO%cjE{-Yc%N=2FZ_8AMutTCuRng$cB_Lv;FM0_+*@o>oN+;*U6`MXB -zH)GcDyj>iUR=fOOx06*~==WPk>MBhd>A7@QZdfKEi3oj?EvsE}YS@N -zNOc!wu{gj84c_8YUt{!xDJ&;N&z(m$tj2Duc;PE*S05;>hfd#;T?B(hhyAx7A6D{J -zJM<}vHYqTh_XcePRodQ7>j(6mbmBs4df0}*oofdKXJx_JcEi&+uwKqis#ADyyq}JzF%lX@<}Fzz@u3c9-C&Lmk4CL -z*Ok6qJT8kXSWKOWS^ecPkuadNUx;GqES?X=9BBQL>Z -zn_fr2dS!^WzRru!7lp1cQ(R}8_bLPKiULy~y7Z-T!oTaNfKrw0XxrU;aOhyyQq(G_ -zHCSKj$-q;^9eY+HL3Dq-S8lP>G -zPnz?5`q#&3S6U=+XY}z82yl8KU@a}iFA@s_hd`i~HO1aY7gw6^_AO~2D@MbN&0HIWLQW#FlIiEfrr8pIh -zPA4CV{^n}l_ku?>ZdG^gFxvgbkfS;>&wQdbj#?BBRF#pJnA#86)rJPjn|2InrS!29 -zEAooBB+1jaZeJEX^s~)Q;OBLrW~W*LC$b-@>Cc8Z*yNMV&7+M(ZY5FQm_bgaEP;&z -zoh9ToKh2785g-3(X>8n6mR;!iSWhN>^VO}WZIsS@&?`T0+ir7tB@f1qQ^%2U;*KgV -zM89>y7?1KNBUPKG52S^TzeR45^B|3GcRl=TO(oiQ!+7{}D5@I{Ru3=J*W%UEqX~e$ -zw@Gm;@mwcryV&1Uh`oIzYbz(?lu2=eZy!thzSw{q$nqGuCa9$Zi!DdSUT*uRQ2w5Q -zECz$pw3l0zC=X|23e(KPZDZe2UMEVo%HDnv_sLmjH-AWmP@46gCbgAAe#@5x= -zm(?hb@r{MJLH;P3)z=c(&b^=IV>tpCtGxV`uc(7{`$+@2|2sy`XOedARqfcB!&v+2 -zWGho%{S(T>noAYNMkAL2Q7=+Xx@9Nm4AR*yCF%SM=aOio@`T@N&ekMV^d*&i>C{qy -zQsDuv$#r;0+ajk>^kgiM%j(e=fbro4BwjP>PJJ%Es -zSgrsfVTIg0Ugb!udg(Sq?)?tkyCT2o_HzO)QB%TZ&!ZuG@AuOdnr(C` -z7TGWBD>!A}bokYgE5h3RNa#I=&Z|)mvw6Vh-ESkUW0Rj;=}X!DoGX}BqD;O?#zy`Ep&(8sg`eO@zFj; -zq6?j@xH%6JpU>%Bekbam7l)~tk1m;5K5U@9o$b6p+b=OL#-YuJbqHVTJ`8+C{HQ=k -z&-QtI3|=)^g9z@st1>TJl^7FGFnnCT(KVu2OF`c*c(tKZabhhV%Nn6j({t)QR8PnWhoLy`1_u9Z!86j^ -z&etXsUqyO5q&5ocL4ExJ~+XB -zpnFgdOvu#Z(<+NlKgzUGGUp=J#YkAl!))8NScPK~NaEASON|>jViizi)p(B{o@#=F -zrj1}~ep_)r>5_@1tn{y0cd7BSVw4*|KF%ihrLX?(6VMw94j0`^E%)p2GCo~Z;n>|@ -zH$gwR66ix`STH5}WxC_!=+UP%tU;6yUAz7rChCZv10^XwJniwd*ae1gc=K(5iA-X; -zW>!g(m>gaAh!;ITDSmQkHP-pjucZg;4hqBjlm~(_e9EqUe%9=V>hbJPfy4LEBEMH< -zZ(-|U4G3~y`edAjVJhr#cD1=3~2X0jMdB77Mgl&GWy?2&0r~0#`^t49= -zKuhDGI_7>7{c(NxPrYSNtiCFds&2S-Y388~W`;xXjTteGr`nW9ruW0{LrRJX{iG|JHMLHN3LhUWCWVkX*tHBoTw!X?g>Ls?hNu+gr?U3`Vd -z@zN!>W{pa@K@XRbrI+tM#&A>e#%F@P7wtPRz^M0pkYW9({#M7sI9K2HAhg^LVB&us -zfarE5G4SL|&Zj*2J3rv@QLkF|hXGw{4>JshzRFKF=WBFX-C;wZ`UpReDib@Vk(i)w -zNGdrIV93((%5OfG?XcxNGRGgOFqg%8AGNu9hZ~49EE_MJ0EPB&9oe#(L}bu$UYe){ -z-ky@2W^84(ON@FTH!g9VY>%QN@F>@PnPgfgPMa&7JCE-lcGtrf>=Q!4&_ZZ~O~Xor -z^igS -z#fRFZ_Z)-dl2YL-N8r_*X{$4zVMVIOXW)PK^4QF!J&BeY`C#&catxoTGnF6t^l0~@ -zoWiU<)KFQZwjI_W-iuszo0)?iq8}dN0_SSJA`IKvD9^v57Id3nv8r^db`siGT -z8-Z7fvlaq1&@JwJUxW{re}?Dcy4<@Z{;5_oZGlsXAD-TqXT^jjf?*+&F1N(_kFaaW -zk}OA+TjC>rLlCh4CB35?^=95DPY*gPD=OTtt^hL$%uW*2pXON8^dmZB0tM^9eLOIc -z-1w1|UbePjnB=oI?WhkVa8E16wLJ{CcyZc}BFqC`EIlAoIwk~#cU3>zLe{=9pFd@K -zO=)N@C0~?#Xmnqo%-{rkPF}+}9=N)p4^Is}ivKqLaXR<5*4Sg2x?4V}_l%UM-o?wz -zcrNhIWKF+)0Pza>T{8~1V_<#SAN~wqyJo1-10{y;y~JG9*HemdI;HDSV0Y}}M3v1} -z-nM$<0=$h;Yp3eI)PweU(zro<(u8B5+#lb2`(hDXLpyawgRY$LQG;eV)`^Co(AD~vQ5)OQ?5McXccT0TNZo+Jx30l{c#W(9!qTZ6a?(z1L -zAHLw3ef6HzPc&E_G#?lIw5$VdPO@4_c5u5LM@sC`&l};kaQ3G%^>1&KJ;A(`b}8H| -z9z&o57pH2HeL^x3CuXT!<+`ZHIj(63h=fj}@cmR!&dz6MN@;#NZr%qUl1^o| -zHleKZ8ufQk3Xh%wsPZ}6pj7BA@`?9e+*WLPaVEP`0cWKP_@3F)ZzP)@UUv?v7$u2q -ze|z6TNU!JvP!$|9Oo+;c#SagXIrhn}Oo+5tPg~IC8!Y&c#n~*Q -zBp_P!FyqY;J1u-@riva~wG*}s2*elh@GU-$a|>pSsqvVN*1FLoG<@=woN^&YUdeTr -zE^NMd6H<_y=6%K>*R~UWO3P_UwF+>WAaIl{=%K3yDSWj=nWeuYnu@fQ%Xbe)z<4i^ -z#%5F%?nm(TYNgBD`MfcA+%x!o7<7HrZ=Qx6$FQ5nVs?PZj&hcixw=%I&nS^Z{LU3= -zui#^(2uWtQ-SI<0@L}VN -zz7Xe7n={CcOWK)FjQ;%u+i`jn|FCuABh(k+Q10F6xqW%uY#yXI2%3$M@-_tY-*^|D -zbc8saj6GR;OfwHH!S(af_+Gr?az2R9LeX*Ji|c8AZ@)Dxc;F0S^ug5ke4D3Hk1FcM9l0d&$nU~9ZtUoJJ;>WW+Snu}m0!JL&7ad`r -z01Q70Bl{Ng0`7zG1GW}_3TrKQzLIwjd@XwP=_8hYEx`#NC -zw2r(K$ECxwaku_@Z=^QuBwFyRc8KZ*QkJB%NS6+s3H5lWuHKg;dnt|YplWy7b@m?A -z^MGj9V;%eulZGBCJSX{759a|x`t(PE=EcQ<2CL-0X9YVwj**@7YRr3GBqG6&(2I#| -zhr4A=UcYf-3};vl9u)YDhJlXV?Ax7jX^W27@xFp_Ip(^XT~{!Q4yc+fk4IYY>^C#c -zMlyj1aBhyS##OsHa6ft2<<@#jZ2UR>a7iE3)}+&)stw>(J`Xs`BXz!ylU?Fhr@yfS -znm_+k;fv=5wmO`@gIam1c0nGdJVF_S54m#dac6%O&2+z!IML5P0bAfal$YvD#^1e_ -z?!6s!n#kVozngz%_=m8z1^M7)Wq7C9L(+*AWp%{;E+;g;Qi1xQTLoP1VUFHKdMY~^_88l8$zE$1bNN|L_S_U{V73^Z|!9+GvM11N+^j) -z{Lc}XQrB2Sj}@BSdx3@5a=RStvE~8gq22>$xsmbY=@EMo9%K`H?kALX>N>rr=cLuE -z7T1w(bn2_Cjz_Wb6YS<`gtn$DhUET<1g}1j*1Mj`w+@i|^>brd?xw-Y2b3Z1^6eI{ -z)08Ucc9-4BD;%e!($_`;!C*hxP|?rcrO!PgJ2!Cdr5jE$0LoFTcd$EW&P(ahk?6cI -z!OGySD~L#v8id}iR{-1;#%JI*MZl~1n4k?!DFc>}44u})AdJXbpLV?*rGWFGCl_j5@7HX~6;(p|<JFUZ -zrk023UvfG`(8=sR%r5s<0LBRkAcNqHho_G(%Wz7;mjd#S=M){fUnkkt*xCSGfYz+u -z9MbL^@`y?rA@hd48l*`!&240dxKy%tB7FL)7(4)r -zC!*iOmz_TLUMPzb7a`hv -z%S>fjn`!A2tjog}91iOWzW`?&J6D_8qk1KefSr4+t`$K+96w;G -z+AcEmPoKh>UO#y9R&p@j`zrfq7dr+Xr1z>{L1ue|OJ3a8l<9p@t9U;vKG$^&A=Id^ -z4;AI$a2N*Ntf11b8Ri?obVNXV$WYi7S2ROEGg91QsKyDzX54;nbyVF+=sP^4lX?jC -zBInHeO%=*>Z^UPHMHku6Esi2vnsO;Y^WaYl07+MDf_r+d`E4@rp=;>RL-fe$%_^@_|bvSHcLjXpDv~&uw1bz -z=Xz`d?})o%`FQH}%Wd?L0F?x)fPsT_&s(Xw@0ka`OUyNw0-8NkP*c@%7-uA25*31a -z$p)&~wEnJY+i>y1jhyp9`XFg%KeVkjbjL|b)-lPuH3%o`LU#Nc|APoM>?M%lVkL2lx>LRjR&sg9%MLH#i=r$g{nl -za+g=)8OH)WKJrM_OV{@mm;g%QhDswimqdHiUS6Sx!RaA_E_j?c@tc8Vffwk|JrnVG -z-$3_0qZPdwupKo}V^F)bx{z-z^t -zz9vZ!P3>Na`o=xik(~n`+U%HnO{?xt)7T^bL&$Uqg*ML~7Q1feCD(4V`A#LJxlJde -za+699C0*u+^cv9`<;CdZ(!>ZXx-;hnWQ=^G-0MrnB~+9@2l`;gO*%5AZ^J4tL-4}& -zs4yDU5^jkDpKuW7B-na!Day@zW=?~w92#rr&(B%y-g}!i#xNz2HABu|{y)QIq-#Xv@&fuo!DK%kiUPI);!)((U?QuyG=>dX5}({=IHh6?%R7L|r6B-#p_9q_bB9+`zu`E4jIYv&dq41ZB@1 -z>S3`C&X>D;$A{Af5DySiKB}K{>x4cw9+@BuSH3$47>0B4&(RT1$Qe5Dz&K#y+NJ&U -z3muVQKS>bXqWIKGu?p3c-5+^aCfjD+#nWCM4UduJM4zHMD<>%UfJLLl5k<}fHbVs| -zk~l|I&t?x%5U|co@i_O)^6ZP5sJQF^D -zl%xCk8Y!oLH@Mbk9%AXBDVcm*LdZ6yE+08Zq}1F32TWX%_|7BWheN+s8LE63l4Z2H -zlGcj083h?HEPyv08-1+$2usJY1@(vA{DU)xfmtO2MyZY;Nglf$pLIURrB89Bob?|1 -z9DoT*PVXzcN==2ZJJgDGL>B@+1K%q=xPtwb^8uruXU -zFi(-jqe_htwR8Ij+cD7<`NXa#=#i5faRhU=C^xp5T0c{dy0(_`AR~lb2%WlI{D_Dg -z>;dD%dx6%rU<+See19yY$2-qs2X0xyq52Jt=E%_-mesRbqU_L*Q6i8BsbS!nDP2O9O}zvmmzh!RD(K+KE6X>SA`5=S>Hh!%s{5%IggO1izA -zbiZ@Ji^ABvK?(FZH}Za#%^fgJpJ*iS!%i#u?P?mg<}euDyKTj-!j{ -z_t-i5%HU(XYZitr@i??Ne$B+^^9sBVwI4j42fDWzgym6H)Z8ib=6lBe5_1 -zhqf(BlksyaF`!=kw0A(@41KnxC>JiK(5nky?oq>S0%M^1#!WN!V1=DZMT<#P!#S#O -zudgJ_8m3oN=I0dq^&OFNfl`-(#MU8`Cg-;a3r^9{SsX6zd+tn-K9G&Uhg--_>$!tC -zaLHU>-sBrt6K?t{7aqFCu&MgyaC)WnRK?Q6rA2AAS)<3TP`eWD9+dT-@Vws2C;Yv+?mt;vVhX#j3sgY+U}#9uf881bIH>umW|F^ -zTqi}P_g1oydZr9TXbZC+Q~sO|*O}TGoAS|pO-^{R#CGv~Q?c_?1oasG)~Eg?$IImN -zKc|`labWHMK+HarFTwDByP&!*CXoRJkpr}N-LX{Gi$*ph$1Y$I9p8ZH -zHG3Y{%GA&b!tL+QvcG8pnV4?UPgABM+~K-Km>~iXz^C5qY2VP*%Vu!$U_QwC$uiHw -z3EfQqj`1NEdrT;K=KwqcpZHynVbZ3jcEStATW6@H;gg=~dmO+6U&uKoWL~=gR-&zp -zdsFUs(d|)!M(l?(K4okL{;Gw=>3+b@_qJ@d`Tb{q_HuS-9(GE_yPpHGGCw+QL8Ol# -zzwl+P(}&J0eYb#e$8xG}I`@hPf$w$lS#buK&^)isJ`&gBdf;}R8wP{<-eVqwy!V>i -z)h78)5D@xBHhdb&qgCS}JmN@qYW<9kMTL+$)VXi7d>YAW2QMFI_IPkTDWLHt9yFI% -z@b1^VbNGrn~C`w@;XTP7`&Nd0u_{I^RBZ -zjc99Ww<{LxJ -z7e7q{Ka;ugau-RyPq>h>d3wn}8RoMkgPrBHcuQGDa3>MM;4J{5J6KmOuY_ -zCFxCH2SD-5zb-F5aX3ifLsz!&q6V%d)JGlw9@?LccP4us^kkkFDLCpAj}UKnhAN=0bpoKy^;?(ho5d121&Z-qB^^y& -zNIaFFdK77gR4Z8-fm|?Zpn3=qwrxI}Tk%T+mGu4Ug`US}|9qzYiMvbh&Fq*3DHSVq -z78UuV)Nz_$%$UPBpMR4vM8jY@d`unIN1EF{nK3LC7SSRFKa2e-4E13zHma2Q?P@a^c -z$Rt%1Z)S_EI+s*J@8vNJ`TT@Pz}|*=T)%xb#au{^Iu5=%wJQ0Fc|=1WkK5lVU$5dq -zCzl=w@m-#4k8w=H`v8);dK%xW_Ud~4U2X4hZls~D1a`kCzwBENaa*AD1AaK_0GHb@ -zOlB!Q5&-gPY!$%RE0+&Wy&89@Lh=$=l7*xCNlVg-YXh*B6^{V<_YnuuP@`^yr|3X3 -zYA_$kE4)W4(i(&*?{ydmRytSsAmcZoG@s>AfgueQ;&(m0auXjpi&&0xU0@2>YaYnP -zuYHTlZWsj_(}wPO%=-3LwmxjTB}SNX4nD4Id-v8iB|+MgchNE;$>wuh_V;_u1pV@% -z@(B;Ra}FKcIOXoZZL>y0I{x7DH*lOQUOw=R?BA3+0)ci4?1txb6g -znEG?nIQG2J$bdBhWEso8a2woE{L42#D(ZMG3%oApN8R(CneCOj;IyM*_Y@?rIT -z1-~OuPvr068vl7YdCy}iolPcJpl^qBsbnKy)F+|)3E^G`TP8Sf6@#!ZxzEj>ZvO^j)!a_JXwyLD0d6?b^_W>m`N{gl+L;^7}jJEpRBz7hBq3 -zbuR1H*rSBL^+}WSBQqz@+mjMp?@NGFt~%>%p$hoPlKz_V{!|DK12+ab-&%O+d!ltE -zAmUa0M?-m?F3$t&smAM**Z|jMwq5NJ>Wze<5apM&i2ZV;5l%B;A5<^mqlG9DP8OBm -z(A>&t>nSyZFFZb89p5ox!Bs&_&Z3)kXHGHTgJ1AsGDE215rXLYCUGaF-H#sak$4q| -z^ETfNlUp8cfIgo^f9W+ir{gFhHVG8W$R1#d*12?u8(jK&`aTk$>@#P1PTLS@X=8v1547!H2z0lr?1lEkM%04BbZ# -zd}M3@U}_scoyMsf -z&T#3o;plI_!knY`8ufVuG39dBCrWHMd0rI>t_QI1XCWLgGz8Ww(SSI_W{+L*CsxN^ -z{Fo$&IQsn@Q)8h|gPMN!&QafORR2uh@$;JU!@6GOY4XbNkddQ2N`^PCWHQ#lo<|ab -z=Y5jA%!J&`cdBDvuBi&?B1H|;^iP&!58}#dU0wS|cJh8r#$*Ah8!sYUJa1f!mmhXt -z-BdLb#+Q}Fs7Bgx>hs2=gN`rRGnoU4)mG%p)%?2V$w%C7UU(0X6vB_%wL0v%bfjo_ -zUhI9~y>CZb71v82#9)Ri<_DTiU6TT>ms6m> -z4^(*!6Cqdc+cx9G`SwNqvpEna{9!E_?;ybRv9r<&JB)%^a_M{~2J{l$&<#){SP$>d -z#0479#K~^(L){%Gb`{UXUVALsEsFKTy_@FHM9A2;1P9N}wTR=71vlg=zppqDi{Mpn -z_kJl^KUYk4g6&TnF7$++&02-p0Ei%4lIE#9!^f_i;<1X1N9}GSWTQ0XL!+5@)KHW; -z;{bHJ6SIxW*CUH0Sesak5DIWc=e@6mPkPNGV_Ukb)*dL;MUrTerHiI@9_ae|w59@G -zc43ZyZ#N8x<(@rFy__h$DF-#{=7Q^|3s8fZ_Da)tppO-b1W|US6Ir -zpRQjeRD#Qvz*}4W04pG%m-PZ{Yi_?&4=6hRo!?`bMYD-5j~s%bW|@LLj#T32ff%Y@+0*p -zVsA!7mI|+w^sLgEiGV$d-vGY}u88yFYuFDkX}y9aa;f1S~JcR_wsbr64cVt*!55dwLqX$7(XNRisGZp`-Ln83=!cq&+4dEPJ)|V#; -z7wf{kD@q*~{jeXc>mA;Bqt^O?tXs!xFV{L3YoGHdeehw(x2lZ+)t}(q2Cb{Dcsg(Z -z^g5v9+b5@8+6kE!i2*b(<$Pv`KnZL+np>?h4@I35X8lP?oIU=6CcifPdr#k208R@{ -zQ1v+?etb@RZu5D)?3nKGy};v2nWuNpG3eT9?Rh_rup|(A+~)3ON;0yC`~`@Mj3oQv -zfWptvEksVbKbmw`xZ2*M8e5B?pP9rgUg7D6FulkB*>fW34zzt^Qz$77wreRD>wLZt -zM@OQ*K2wZa^494%d^(zf?E3z9`?HHV+$!IITzFEtMPhP?@jaRd6H*O3h^ -zqV1eLMg5q4JKymTMXy)3NAJ1R6q4k!BzWmX=q*%z-#O2?K2RjUH{(7Av@Tpp_`bzK -z1PMf!(Ccm?kI3&M8KPjdPURQLKkN5{tw7*48V+c<3g@HZ{R+m~hv -zPkW)-$OiC6|EX0&764wZ%XMW&L));k7-0H0TbbIJ(}KZA`qdDT -zWTthyx6+ztF=|2}%-(8+fo6jZLy#-SH>pprp6D)d!Aa0jdH^lJC>dk?ZPami3@hn< -zky8#8$zk_MUEEJxfZ%*`A8<-*`tijoEOWL80A~VU6(NE -z4QfM)c_{6(o4qWE<>$J%${#!3;z!E~f%cnI&2w=|6XpiIj2&&xk45?Mdb`Pq;MxM6 -zJnZfjajbD-gz`PW{fxJcsjL8}yG_2@bzf2T0K`Z9z&>9}i>q6Talvcp7M%gosjDbI -zuPz0DUtNaq$yc#X^{HWdbd5V7eV+d8n;Yd^hG?s=hx*6&6c_;cY-Oqje1O%sVVIp1tW8%}R;A3gZ(s?lil -zw6txz1CN#I!u5izJ%;kQ*YVldBd0F`-%u4*;W9FC7JOv>J3e?Z{({fMiwop2k*_OO -zs+cbuK306M<6_Qg_S<_f{@GhF?8uS3VhthUKo`-P_}+R?OTI7g+Ar;6HFT($|Jm>T -zaO49xE^@AFW^{1h6Uhuy -z?IIn}wSDNY_&+&Bo8>Hx_t7Swk0k+o>g!s{pDm@HC7c&QuT&<>;GUf0Su_rZ&PAxv -zD$6uq?~VKNoo#-n4Ru=lkgxW9b8-}f2Pe{Yr-K)@v03jUlP46$Zu#E!3Y^_XtLS9| -zaqasaRZv6+-!p%PYUyzFp>#5_)`)t!h3$}r^W|7RpS#qiUhwm3@>S;2OlG_?0_4@` -zlINxDDY$v=<*+`Ej}4v!d$QVwRW -z)L->;H@O%NZ6p&2pb(W3VyCQ#$bFFRu@KvD#qVDZwy)O8CXZ5_j{@G$JGreNBmtmCw>Z1dDc>x7$8h#T -z71ec<56^0xyUon&M&|Q=@*LS37$tJCWjnIleghH}*Y?Dun^fT~;`51&!xb4}NTYg) -z$P9KK7oZG0k7DA@5`vi^x>UL)amz#gu& -zf%xgvJaEa1>E)8L{bmam%jr0bK?boD(%gp^Az!6OlcXy0e%a;oQ{G`-bKrfT$3l(p -zZJ7lcwd6YMC%K|;Zp7&!1}dkxGL!0a&%wR*C}ZPid^&Ich1UW+5KGx|x&wD( -zJ5RS+J#>6BFhu(0y6k`UqI}g_ug_aewS^5`KvBF6pD%V5<4)T{V=YTg4?e>=Uxv^m -zSUgK|zRr(Feh-l{vD-;}%K|Gz0^m2eRmb%zBK6cxgzPv2&p`(l5hZQmlxImU7&~O&te4!0FZjZ=>gke$A>x> -zB22d*cR?hPL!5T|=I5Sy9xyyU1Je{{dof6imzMP^r3l9z2fI{&j~x?SMUH+2ZeAK? -zTe_hiz$Q6XSA)n-i&)mhu@=H_Q{F2|3Juq0&*hm-Z8_+)gYhBkLXkpB%?);^wAbU#I`MW1Vl>hj;lC -zCW~>KS?j`+J9lKo=7=3d<9Yb?@#-MTlH49+FfFw?M-vu8r>U;n;AigfRw)-JkZz5~ -zaV{CC%knq|`&umHMbR(lm@w$m0U2FZwxX+&*OZ7uhz@h6;M9YtiFR&qYVbw32`jG6 -zbNzlEaDtR}mUPz6%+P7xL$Yu$$U<@|gM)5`!eLvTF1m~b2wWV@;g98h+9aeUa<(Gh -z3dxa^=;9547pHpdUD2TW5Yz-P#oflt^4~p>E?==2<*3y0ARDhhUOX$(7QC_ds -z9W1lkE#zaaFw(O(ANzY$^$2C3a>``T8b881Wq114fOuQ^NzK^@u^#B~eBh=u^0IqBDH%B_4W2bDYZy-imCC$&L_70ynzG{h*JLJ4vbm_^rlA9)$&5 -zdmK1aL+O_nFXp^t*8nhkt8Jr` -zci<4^R3t(<7TDZ7uWZw2di_FfsK_iG4BrRU$^)-aJSkuA$(385ZtJ1@sT`So)>Wd{ -z-fIwTh|LA$JwR=G=Cd#aGB|P1tN!gX-ew&yeLSuTU0!6TaNW(b?UNK-!mKOwp1DZX -z%VM40n|g=_IaQNPcHOD;Se)Va-Ra7tz71m-J6HC0KYA?|baXcF;)BelJ%o9u2$6Ln -zGi!;_;B7`r)uV6Yn@%3R2H)v>+D3ro@l&m!XR!7q*BM0N&*h0lbxj|TEQ);WQC%Ls -ze-+b~nm+%ahEGw*F*o{PeB+=uOkcV2@0=@Cx+LnYCc4_jQk~kX_wn2deovPlj?Y$t -z_Te{O7~oUlJvz6`Fl8PW-@u#B;d9BA%<2;i5_EXkT(ewH7+yM$NZn-z+Y|41J)gM>#P1Q>MQafr -zlo_qi^NJla1owN$q1#|`Ww=bCS(hs)$#q|86#MK-fF6JjqG>_^9gw7lRliR6_xV5l -zZiIi&UwTNS&8f_BJ3;QqtOq_Pn4#b>qb2CF%P0os@sN|)qv|bLqp#M$%)SQ+)S$s3 -ztlRF8J@w7<9YX%vQEd}INc7KgP6O6_h5Qk^&ptL!sp{ULPO2l?mNs_LvSjHI*9j<# -z(QreW&{y2Tc^ga*=A1eceT@lt^JNaiO|;56qw)C3h+(#c__oQa3KWHDN7ny4|Z3XFOWYSIN~#gyN`j|r2sQjl-EJJp-7eVq;-}O -zbUNqL43ZV;=Y6N7ddjGlL%+FmI`Jr(Q7Rp|O~WVz^X@$*#C%>5!u38=Rhaw|)C>c^|5;}&YJCP{@o8{xd=eY=5hbfV -zE&ilKk>64XyAxJtR@vfmB@C5JW9jR_s*fp@8v5(~ZT2LXB$Mhf<11{yumhcRzH=#b -z?-yb7xedEMSuO`3#lOK9jb=16!<2;6ENm0x5$Y3VTyw^s0D1fv3m%CG4&6BS*gA9| -z_(8Qgj?^&fn)0-mKCxnaha%r|n20?6ot^V;V>sscd5y@KMao*3>wbLj0e^Rn{LRVv -z&n?bMj3-}NK06XIC36WDXfh8{k4X30dC#^U?F<+lrHAGDg!ZO?p1eS1^F8cIigG!p -zR<@n4LtgXI&nV*cK(cxIvdZRc`9pJ9qJUvPx0J&Xy8~&;4KKm@l4IQD+r7WG=aoEm -z$`daM;`176S3FrjoOY3z(iltb#MX8gADQV)w%G^$uC5IvejQ1Q;s_}ZJ+SYq`mNhB(oVBY+&Lb926~G?B_Fazeh=6=~ -zc6FqvZl{HZ);Tellq}zoKPx)^6staEVU;z321XS -z-w4?RT@z-Z_D~{CKWC~Q)r?v1;nG06#oTAuRNq46wdxUqJ2MC1+k*)Gnh3D^Q;Hc! -z?$t8|eW;b%EBHiI-`X~XFGPpDx-XUoJYn(f$;jy<)8?jYqsR}Tu<1R<&k-G>v3$KT -zEQ{lAJ|=jb&bZZnLxKo-%Uju4DXlOTy1^w3ZoMDWc?7or=t88?nY~;k^NK>Wv;NyuuLLtXD^|PUsic^NbxP1;Y(*z%lb5StBfDF48v=43O_htXTCaF<(5{kCghJLE9@sb9f}FCu{V{S=au;P4C7{b|9<^ -zY1g(zw8{W=%$CAeniiB352=)#j^c&;uoI1>(Q -znb@f3-CGywJ0uEc&s_w+w@0DsvCN!2YUz4;lkXs$Nd6{oi -zVYA8TBN2x4bg*k(J^TLYwozzs3i3JM9HDaH6SVE^CGK?Odb5Bk*pB=4gd>VcvZyuF -z)&m)~}4;I0&n} -zb>#pn$zwgjr&suSRu65w-=MiPWMj=Gj~vj! -zjJZ2<-M%4oyd&T4{96(Ipykq<9)hD&Btqxi1)IfgeRYkTbMgXEuEy1qq2o1BZ0iH2 -z2e8&PpxM~_O0Q%ZfsozpYvTj*n$B9rou}dLJ8!$6(?q@}beO>K(e}H5{>^@?F7pwe -zhjEDGS~(1+?yt4iqnA*==a3~FbT{M9DFXM*BhlqNE)pO_2wvZT_31OR2#A*F!t&{s -z`x)D`Thq-;!+<+ygYO~0^HBo5esLO!MtYLYdGz84-?yZKo{aqGK+qm7qn66LSIY;V -zh#GgwGI_Zq4i5t3GXE^PXeKx2NfecJHxs -zLN%lX565d~`44Nt}Q`+Ues?@aA^^cuXV%XaWb^_hJ^Egp$2@V7L!b#Rv+ -z^Cl5da2)am)dxha&a^%u$$F*b^Tj#??6<)0DRjJYG$k+G#?IX;U&T04L`HndiZ8tm -zm~IC69uI!8^^6+z%_9XIQoD@OzSoHW<(^%w>@Nd?YA(44nUL9auz1R@zlcu>I+Q-D -z_4)G(rag_+VIu=#j2QZ)m-%DnMQ6QjfInBqx*Z{T09jB~6)up{c{8Kv&tR8IgeTx5W=Zf3-o|G4u$58$I=qdy$?>TMZdKq -zQ0H3mhV5OF`ixm}&46=}Exzf$F)g_u6MRZ(FMY9V@r@u~Tl_NJk{_qP#u1TE4HL&x -zme8vkAOfFL{6(3@w?f@6-KxB)?+4$bRKEAEo5Py>%_`Y#_-0moZ{ina*NLxjkDOb* -zz_q>dT12I6`f%hwTY6Ngl9kZG+(zd0;)Upm!%wMUb(W*vvskAbNHXjS=kD~XB5bnd -zJ$N1W!WYnRPDV8ayhfso_KlY1l|H6123iAmwV$%m@74NthSz1<@*#Z8--sJwzY`$o -z_X}0=qhADmzaGB)o>Rm0p$ba9{hCTVTw{NahgJG2u&g|?Fx|MeRL9>X0(sFluv5xx -z*A<6m$Oblj(KBUhvF~xGnB_a7fm-)8p7Yt=iv=ffwiDjYsP{y#aNCipl*Z-9cn8UP -zF6!v+HKbScI0qk=4L7e=J&3$~r-E+sUJQ85BJHg^>OAi+MCKW>^W?$luDtVPT%rpC -zMBbYH#%!o_>GklzyNYk|eGUoqMNb^L`h|aqqwRM@)EzDS-N@wKIN+Vp>k${4?mVe* -zj=(pL*MTj1hlcGQC4O?LBUp~c`8u>{LxZv^nr`bThF&*=*RnxL8I0~V( -zj{se|c#c{5cEvTCXxJn_@%iPYW>?)S6&^(xP?@coZQnsd5G=ogE|DbNllQQtUwOnO -zuCqIt;1a|Gq9bUHuOqOqxCQN(>+F}(YlK?{!w%qM-t$C`ZyUOIv}B5^qVMa$)8A2N -z?PG=bRyQnLrX4=6kC%Qo@1~t7oanuIlf2NEI!8ofRaxmiI()yF33)Uk!a$VIE6Fb| -zrsq3s#S*s|SeRO*Hjs!;ei487+hf+@qr6=wlci33F#c&pEBDW>(CxnAOt0r~Y-Hb{ -zkRg^=6g|1u#yD@BJQZiGw1u+IlXpXqc+V*Xw8!3=+@6R|1bY250IbF9j;69xn69Y? -zC`kdDeAz0|a9K~>n=FVS1!h##8davFps0H1-HiF>J|fKV2nD{sf}j#6^4gPatR3Qz -zZqEz4eB&5c9naK^MU0R`bu_sG6;|Y41vh_ao^AG;_OREZE?)%( -zH&frPCyIj(pJ}-8%!rJEAZ6+P3NPtQr@9f}I7~5Nx)lt;A -za|d|o$pE&U1FhV~u;5lEHF5_ukM1(;_EY~_4=3LOY9V_+g5D(|@pNT>d%I1`RbK`= -z-veVNPfcoBzbpCQ@x%LwqFw>yGcd0ycflOxh~-qx63}(5 -z_DpP7yCW`5_(&AiCgZ;9@D3fi-|I9Oek_IxG1<@<5RqaU%~`K;t=`lccL$sAb^3i0 -z9a-Fm=lb|LpplI#gWtKqBZi!JGyQY1`wV!_`sYArYcv-gEmQ5n0m*(x)hCxZUlaD)ZtvI|jfaVz+9+;d06s(^g(%qoi*QqxFJT8fflce=UqA9*%TPh5)BhZis?YtHP_{*8l$6cu?RW1&nLyydyiwXq%`DHv* -zqs{Ty4nKQiA?Ct;)bOAF-0wo3D+{Ai -zj>mKQ)he(9-QXN3<+D6x8X}tTs%e2&ibxr(E8zW&9JmI(mA!@E$@zm)-s#^6kl0f| -z&Nm=|F1G=G5!w)GeO{pn-aT??!He|>E7br!nmzR9Pphz)ZJq}0398qxQFH)jxnv64^mR>8Q -zZ3k|_M*?=k;d^5sSV^f55YC}~tk09`Cc<6`;@ZsZVB% -z$PkR2%|&y;x#xm7ZyUUe*!W)7`IY;S?e(kab5Hu6_fV~Fd)Hh#jh}&5uJLvB-7^S& -z_z@9Yr}o194j3D$0rbEt*VCSHN%dm#xg+EVuEa~|qEq!}TlYV=M?Y_bVfN+R&lBO^ -z1YT~v^@Nibti+H!;A%;OPuXIsl&Y9iEPk)B*yOWah;I~7n@RnND|+(MPK%lkeH*CX -z&Q$3fYg+uqDhJQeb6PR`JCD9>)@vHf_sr*=dlU?Z*^Zy%rdC||#Oaly}J -z*K_P9g+`XqHN!Q-?>|3-cti1FFoY8>d?+rg( -zSt3xq56}ETF-B-8%=8I03i27kZvf#7gXQqO%m6X+NYbGvCD$X_>-zrl5TlOweM`_1 -z#qijU7L=SC_LKV{$a)f!`GB4CxjK#W_4vY)lZ!602X>vafT!#6FyQF#6)YX5+nNXb -z?36^r%59#<$*!g8P4w5QZ1l2?NpsaOMn)_wKEV&PM&$F9=bGpzg{k~o$JaSe8KYbpoLii`Z{2=| -z?@43J-hSZAM=S3x1vuk2#BdaD2l8%)#2qODrvlBVDYVwXyLCZ2NbxRXD&kiNxnKez -z_sntMp|rVuS?ft^ip!U|8G(f8^R)5!j%LU=E5sX{j~VZs%krR@k?XO~1Sbq1_S*;m -zQQ~*+$oV4XL~jWo7z<2M11t1n3BoI5SGY{Lnp=-w%sS3*S#qSQ^mZI*sQXPOv*%`a -zgJ)K|jKybbCFrb{#l`pCJ_!I%FS^}W-!Q9;mb><9&!!>Fh4NX9_eskVpOK0lWZTFdy*f~RWtBuCXksFV -zQlQI#+Bb0`c+WyVz~jCZ?R86CVvLhs!DpI2DJNSVP9T -zO`y=^x=VMiB=&_Hlg5|e46Fw0C+k1!nPhg8SQTx|Th2$v!e4>k&+mLSjVhwn*(*eHnOHUd5@o@%d~7=62$AJH{?;l5WG(%(>EE -z*3_U~t=$RO$NVG|>x8sqe7nQZ+l*Puk4J(W)Eg5qa-J?fo?%^kPXNWv -zt9C$;L$y2CzUWMfa65gr`j#K#quW^R6~of+GJ%zE&*45)fWYN?1Ne#>o!HPdigu__ -zZSRruL>L>byIc%3&V8NkF_KAs?BR9ya}DdTDD{40MJ}4ba=&+ty#Z%%wZEw+2Kj~` -z^Z^KBdVO(5{1n5fFG=Vr@U4y`H{`8Pv17n*C5$m`7(qPHwyUgJIrkuX(9Eq&I?f{w -z`@JQ#v*r=$t3h)QHe!V9o5ZwpI>)% -zK;If-$u96I)Vo)W?~$4%?ssFW>X0GMju#}oKgM_K$%m~QH^q?8Re7WhE-~ykZvD;F -z%28~4DCb~rxo_kMyTvtD#8+4yr*n_?mp83|N7rq#6Xj;&7MJO)&Mkf9|6b9u+D8G5 -zu{zwYwW8eVzKe(B91kA|c3g@4mMEJzAps#@w6zd8?<)!D;NPwN&n?pp(cDX?c#Xc) -zD=@G3VVfwRN3PtkohpL$OLwSH4&^~TkGK(xN#7tNr_$RaplL#f4LSG0+Ysd_+$=K;rKb2*=O -zwnsVg7MOjJ?|stCS1cRPwY7(F;LCdC^VmLz9?7v;E~ow89&0Z^FB-X;z5CV=majH^ -z+yA{p?seoXVCWRacHD1ouf)Ug?)i>RT6COkmrid&fqHV;;j#SI2aaFf!wq~q6eMu? -zT8>bW^Wy`!hX>^XP2u1`3$&8jJ<7Oxkm4c6G4Y^p%iHDPyP&BB&-Lp^2i_NUVP!oh -zPk!%I?BtW=Vx{HQ@EP;$jTB|q3EbTn-E -zNSjKzK?Vqt8rs}pl$DMu&P&z2til_*Fgzuf!rjSi>)8eTiPo -z%9!zx{R!z<so}6k~zj(ExlGS^H19@%FiTv&gPR+Y6k*Q&ca+Re#JyjU#-s& -zvnijv)Dqj;*t$_&kf%0;_Q@7?qTArtr%HcEd!7nYCT*0Eg7lzj+P#+V5X2ep*Xn308 -z@gHsXRjIO(8a&nhnQ;`u)l{_x1A3yhjVnhjt=uqd%~&r~HG1ANn{ibtIlnwxAiw@( -zKQZ@hF!ZJP9bF?4OD-4tyq1Q?HPLcVlmYNH{I`g&Jx+GG{k&i6hE7HFI>49cHT)}^ -zQ+hP$%f;@e;GVY7Y+6u_2Ew&M#9;|L(xAGJAc{7d1xBiVJQ3-8u?PO030LWk<~9T- -z=im;AIsSzpzvhC+3+x4 -zgKppo6u+k(DUUPWcd3i5hweSa$L+52W6^9kmc3ev+@Z$g)lGb9%Ni;{%<$#g68WVl -zWVy$DNF4O!t)4E%MISif;0V`bH7_F1oFw)qIDSr00x2iy-qzzH?nr&yxcaf1W9W~G -zMyk20(-RR0?n#BXw@c)l07*kJ#xn%`mUz}VCyPfIXtdj~Ub8Zyvr^iS!&%q&SU{X$ -z{db_VY%W7zFrGcrkA$8)*Yj#{++0j}&-0Omu|^!+6PAj0MEvOy9$vM%-*y#$=eXrn -z({#z>6PJHTY#jt-=H=8As#K~JqV%M%YV{PR)Zz0rB@g|Oq<$vh6Wx7FYROw4^v -z>++Y0@|w?{N5m8}H^=XL)EuM6R1;6h#W@qgof0Au_GJM~ndR43eZCG+_K3$-V%)F{ -z2xg1Dm7#qW%9Ur_AZGD=<7-*)?WOER8n(wdusVU$MbW$7Px<1+ygRZ9b4Dws_o3eL*1!(AhwxM= -zfA8ystWLgl#AK3*&gY|NZgZ9&qh~1@-rDEwE@C^YG2=!gt67 -z-SUer9=@2nZA!*7kk^t^RCuY2Y=`-rnw3Lj3w^(l^3rQC6$o@{DW3iS-eNwiDI|GD4^bHz)w|(`kmqwvr7W%VTFE&1 -z1ucL{8cpXHr?z;*{aX;X;bKTRI%g}9>y!&&nm*w>Na;Gm~upEGL>6-`Zku#9|fuOvfg?a@P -zc~9*ZLWHtbF4Yb`PWM&!l5+W<<^f87Zm2T5&+bNX*2Mc$UoO({;`wH7?29{ekTMI{ -zokzf4GdW^(gEevSgjZ7O=)*)RQT~Qv7V5#dzxGXEbhqRVgl*|#%7tJuuL6Nf&REiL -z-D%f68i&-t%UNmc^`N(WP4}8S0cnquQHaK#zE7gzes(qCv`aNkXTe*Q@(we{%I+2nB;QAp}wX31nM0bxxU}= -zEC&D^1cgFi<M^x;q-E -zmc>SzEfa3Yy`aVC!~Ncb?z?jARzC?hk_*8PR}U36-T~+D|a}DrWEj=#m8z2d-Oh#KCh3nm7{p`cxOjqJHI6f -zd`SJWyD$gr*VVt7X2cFQONH<|PP9|s_A#1?VRO*^QRhd<>6CC!Bpxsl -zh(D_Fo$}t#KG)XIqjBe-2O}{u3{GBwSNfE2-CbS-F{WJdolZ$tN4+g8ETKmtGig7o -zT^Bj}sM=6b+8h^ed7x#M2FySq?VRTTY*`kw9M>lr*&ARJgC}4X7Qy#+PaR6q`*fL0 -zw{3Rb0DU+9w1s?>kOt+3a0N}usV7(|OXPh^(tXRQUZwjthos&lbe5ht2TyD1N;~G~ -zkfJ-Q6qOgt7JJ+$pC7YV2cW1!UD6Q%nx$veZtv|RVLZ^$UTqAlxA2bciR_i>fVI5J -zN-E)$abaFD)VIGIDHC-3i;%+5fKYN3l-DNWfu?$iCJ9~xIIQ~6^ouvY*JDUXAJxTx -zQ;7Lhcn=?_hg*-s2z`%L(30G`djtr#o@NlS8y=L@52Mz4xkScvUyGu1&D!RiUUjXi -z?|s~>jQbSJAOy?PL?HbdNl#ON!kiVCS-xxk_i0GEpEW&c!;yvPN3YA_?t%6)+c*ag -zu~&uVfxb6(2dRSJZ%2M%-WTa-%b9{P1eyb`S2A~8H2UTPGOcb -z1|9me_|Mq=7g>41kN=|Ej`qaL6RcrKpcUUx>Y5;30ki7CB(HLgV0O6{cQ9;dCA`(f -zK+_(*GvBN;`IP&Ei&Z*A@sue(D8BT_25M_I$_(q7fmyN56B~|ILcUg4oB9L3&`_F8 -zPcggGOSR|fK`Y5@N$({5`6V^&0K$X*TxLXH9++B*^Et(2aLZ@I@d#uhexuJRp(unD -zrMmYhEPoc_WyE}8PQ7MI3&;4%4*F@P(KsS8^e$vmFC(r2hgxwCjnzNnq)7~WR_Z*$ -zdj&4u%HEZBQ5bq(eD)DVt8W|;e!2F6fQl*`W(ATyLD5p%hIDPOMY&~!OzU-ZzBKJ{ -z?=0{#XCRz>SiKcq)*W}g_&ha(h_RVdhMeEnX^~Cb{9IL$>W=G!DClvtI8hnmPY+t& -z*v~6bCLK$1vV8X2160T1ysxF7;A5&WbU32@5xjzW|HfTX= -zgEN7S`%*>vqgrcuo&tY0g%gEMez(8VTyu1z<$PfiTZj)6@&QD@N|5U(`5@Gd9i2sK -zL=rfv+*3+T0%Go7UR@nm<*3{Rg9-Hvqi>y -zn>SQt=Q!s>C!t%{`QO|-opD(HaP#)ZJ&SmbxI2RQISSu+X6sGtj -zyEAz^uK`KV{cg>^F2p>U={LW#9|hO^@Cw#tgXFejqe}gSD-x0zb4}3eOq5wua77=# -z`sSObPXP~b)1Pf#{@iYDto+VK9-{SeAQu9(^Sz5I-c#Y`am- -zTWu)3CDcnp)a`#s4sM2L|BJFGuPU;#;ezxX5ITD`oNtMD+&)46DC36FIo=Ll98Z-* -z52Ev!f-j`sX(z+Y_eL!&p9du3*(b>R!9LRg(1;A{m*)Hd@|`6in@pCjiUI0PCTH{+ -zcq@Ollj=^|QV;=HuF}me8?l@>m7!idYSeS{h}%=(+(4E}peg5OMb(_%rCYZzTmCwE -z+QWXZd<)xmSs09b`q(Vu8v5qPfM)f^pLf-_G>n}FKtXrGfyuUbA8YbVUu3MU}MvuI7 -z`0c-&P~q%sr9Ev4y;8~Dcjd{4^tknPB(s1Qjm#>~{M?2;pI9$@biMFja!1l;XD9n0gaL-QE! -ziMgBc)V%gr5wM_B-_OwGQ{5oJb&6qUu(!%pcN6wIWOyN*Nxq_FZKJ`x_v!p~*##~j -zGK_p#7X=0{R+2wKwlTWCXJ%3N!UemIkALC=xXXDX`#rWE)@jL8`#`L+@MQOWZwt7W -zInRYR61s3|&uDfKq~0CGyBN++o7^l}HL-0`a-#+(iC&`3WHp+zlh~kUd-Q@l^z`G} -z_eS+%9^YA@lVw3bOd8F^-2Ai}Jy|*FW_^0z7haMleC2We=gh^AdPuNt02PfHryUi! -z&7QNV!_C20Uk-wAaAx|;kpq@NK -zb|s;MaVHKKT)u^?+8p@x2`97f6k53Q$w#Edr)^}(qIEeRN_S->n0QlCs1h>nQl(Ch -zUec?3q?583=Cms$Ij8oNc;*T1a~}Y|HQ5U$134fDn}T;#7u)sXsw3Y=6OS2-uW{h* -z!$dO)pOwk_5@1r|6*H4FG@DI!#;?~c5Jz!{_wJYSa`tJ{G4Q^%&O}XgB^uq!t*UAq92FV>Zw5Nxk4n_X)PogrcF$m0%kwxjt)vqP@&GzO#lM|X -z4(oRxdlSkM{D!S~->)%X+;KbS(qIFjO!j=;V#4;`2I_QeUnUp#+c2Rze64Tx$;+4G -zd`{Pmi4tMp=`Qx-543T>Jum38`WNMBa%4oF#+-dC(?!%ETFFFo;0Q&!K}CA{<+r@E#WO7p%P` -zaI)6!C8Q@7FTMsbv1*}On%LXUDv2iPl_*@Kb!&uy~ -z_b(Jq&e;W-&M0l^WKiY||8D#PpDlgT<=#Vk(6#(3AGLGTuJatQK)rUDyc04>p=W1| -z-gE;-S$BMYhuSdPW?L@rdAYEBX1iU1&K5f2RHmal#`R{RxZTTozml}Wk400Qw2G5% -zzW+O8TrsBsYl)}v5gF&nw53xot=)WS)v&YkgelTttMKqx_XeK32d^Pu&VwZEW8rY` -zjR=nJ^_c27MD!M0@xZrFh&R{D>MmjYyTAMUl9g|LFwOl;ycRH+1n4FY2Ou6gsLLue -zt6#geP_J#QdRp^JzA0?Ss*P~vyJpA0PwdLc?WQ#Zk;k5hL0Xtip8Wz15U@ -z4nd?I#PLM{8QmK(-ht!a4cF^mV|Q(_&y@=uPei9|X5FJ99+#%*_|r&-%2$g@Y95N5 -z79}x0;=Vm4;bz}*c(UI3H*r#f7(IlCA{y_d4DHr@POlTvFN6?e6MG$TWrCCZZQU1 -z_U2@E>|7Q-x6;h@#f-1#Ns~L|-0*W0K95$(+RtW`{Z_8V-iAZx9M8Rm@#t46l*sk2 -z6eiM{7*b2~;snEd-^FH`4&np!c^c0E&<&y=FRM~}U_Hs}?xRn$_UE5_R}cv@sBg>z -zOi9iI($UWPlI%I|1{p$*Q|7)Yjt>O7-HDIzC*BZ|eP8-I*K9Z&uN1>q;fGOYa4M#0 -z4vodoI&xv@z)Y3l1$un4tV{DgR+295=U2KCC0YY=glyU}Jl4|h -zBff@aKr9{1Xej!kf09o>)}V*NwHbT|1YgD-`y`&ftWcj}_kP=wS#@#+4rZ}x6Z_~v -zTlt#7Y;=)y6k2h?NH@isp0&uRG0J3n0l17)3-oY)Hl{1@{qG!2$c{gQz5jU_`?kZ(y);b}tS -z&ks#g;&N5di%N80o$BPz?(Qu1f&06h!~g&TXK{IegDlWQBCcT9@ko;G79@VEF)g+I -zPQEx(A0^8RJ_n(loSV=W66B091ZU4vrC(LZOBurVJL#L3B{zH;M>$~V3w%=2&Y~s-&8_^}zI~R~#P_>nm&NjOv?a!4q64Bi#$JClGV^t!kF^izqq+ -z3^NaSw;#Wf`W@~bIP5rX;=``81dJ^+nw`{y4PXiPLRAHxRJ@uD$U;k7ZwqihZL=`dNnG_n>OLGP|wO -zN2a3{gjhm~E0(GF;Em69neuB1w9S{Ph6}k`Dx9NAQDW-G`TBm&f!(}yEbkd$+smk? -z_o+Pp+HpK6aZAa1Og;WpL{3Bcg@BUFCTy!fMh9Qa?YUhkLQ0K9g`e3wmQiO4#D3SL -zQRI2PT!a_Xo6tVBG?=AlXQ?V2d% -zB`MwY6JHHQgNi?mTOsXNFVjrE#lJ7OeEKrbjB~zS65xJtT<7bPe2Ke|{ote{~`xvi-E_cacbggjD*KrN60?H201w5RtiJ$vsg7rzo@3DoRq -zpO>nmvaR$efaZ#xz4bz9*@)|R4Fc50nU8BLdsaSC0PJ;NMjEV(jYT{!X+A+x6}3-0 -zAeu}23ZdO)$Qy5kcS~H9{cZ+q>*P}%yZW7^Kf&5Pl?__sd_t>B@5t4(z5T?`>Ug~b -z!Fe1n?I~?9Nfi97lfE8}hgrv%Edjz)@wJc^<91}Ore3mg}z4qBxNA$%>E8Hx|Q -zb%=N$LisuMghXGy3gN>iP4}$Un3Hf;RuLWeK%t1*Zk)TKx|~f}SeeJi&l6R)bfS%a -zHdOT0te|s|_%6bUY%Hvq(s6kTI-Rb4{v6_1H1uKc4J-(~0GGn>&_0w0dUBvVzYdg$ -zv5#&Jp9{v1{5$VcqauZNZsON9ps$~a7`PTW2g>jb8Cdsd^iemVjbVOqo8(Q2w0q^d -zN!NB^Dufujznk;j6XKLk?CpdZrim{|A@V5+v_`(?961|yi1=PUTtd)6iXfnU(_zlG -zhXNFmw+la2)Mg7er7f`}|LhO1@#g_8rB7JNZei=?v)6iTYqsJnC13@gu_wXbq?k7g -zHL&-VMdUeA@i?W^j&F@zFfS>R8BA9&V4AK6kjYIzs<0e4yW{JY84d82?Hu9I9lf;} -zSX_8vze6IrZ&-`sbDNQ5z5S$!J}y#gb$Zy8JztGvoR;RtRRvGeCZUDh)l3waNNnG+ -z2ernI`Se&)@Z2;FP{7ahe%>^bd8$=nCAs7lpS7YS8(Y%g#o#9}`L37mnWrH;I-lnD -zIZr`+9zttxtwHmz{HLvF_}Y=UIT7G!z~Pip(adct$|Rx9`_KA%GWBB5J=mu+?(Ms~ -z*@%7_AZ}^e^{2SYxD0rnM&rDEkK)=yC}wzl-7-@`{qxv>3h{VJVH|Hr>B$(+Yi=O! -z#|!J6oJ%=~>dwU1)5Z~|( -zKzQjsP(`&kqJ-Z1IdUg6tfDx~&&Zr}Y(^y1z{Ya;>wWxLCiO_#Hlig+JgkT)gN4O2 -z={bhjoiFw4=LGUl`Ah;(NY37ag%Wb)g7X?kr -zc=c+CoFYvok5e{Cq2g(MwXdnWKKKnKq8wwyn^sSh#7Qg)qn9L-haxVP>;V?lp?uKr -zUGw1!?0xYKfoX!hkmmT5!cDDv^4=5P$B2(ZSqr`|;2`Jo%1!@{G?>BdB}P4@LjgW= -z@vHr`Xu}XZD4T*4#4aa(R!$6fy}STk*l4j!*Q|sUQK;M=aF7SU%TmXUu(P{LTQ9tk -z@t2wH&(cdfe;(Bm6HgH&oNp&$XXU`4m5z4Mmlv*t~s~<-d67jdN0oo{cYnUMU=RG>6)PWYF=iW;`iCw_= -zNhL$t2)?kRqPzSelnB)DSSdo{y`qQj*FP@5icAl?==b;uDZ&Q>7q#)JS(DsW{<;I5 -z$P~HEihQn#jLn8nT9sPEdi(LW0@=LYwELUB0}Lmg>SY#$^5t1t6+juD6C -zFs*am_{{w8y3cz(A;i42+aqZ3g`XJ8Ilo7r}0a@NqkID%srUMjooy6o^4 -ze(za%q^&c!Q>Y}w%(KN{d2>LEC3{XK<!GZS~LlX2rtR% -zTkBmWuzpim{G3zYW`LidZ*z|W&xy|w3%(op{p648?AItq;VdGs@a^spfj9=`R}JRg -z&1nb^|%)CebEZ5PAhn6z7^X+ -zSb};?iNzXCp3d@|uOac?3)chl^GWX;TTn@@Cm~(>k!4LJnE^a~p8oZw(OP5+5Xr|U -z=zgeS9(d23J%~uTpbyJwbPVDJpbH2+@@+vitcD6 -z(b9X(F4R;C(YaaVzteG#uME$eK)Uh1!CoS1@Ro|F+m&H8d(G627fmq -zE(@V{C~rKz4Hc#i&0ky9K8IMeM-Q8%^RY9_&Q>qG8jDH7zJGk*)K_MgOK-S&=U$SK -z`{pe!zyGw>RCvFgdWPV|J7y}sL^G}Zm5Sf+uamE8p`fM6nF%>4r#CfVZe>f0-T}_A -zqv|Zz`7AycJ#FkSxPm -z-&8K3og4$fTzTRy<(jV$Yco|DL#3`^T6*|dR8RF>#hbkeVs-_YeBXDMuYq4x$Q}bk -zXFX*lUu8evr(DE+Y!T{TVc%%fa99(Kn@)JdE|!DqUB0o5ZeP3F6Xl`^#8x8H>rL;6 -zbPD7_Mg_n5*7un;sddmox~F?D!tIJMtz~;SW)r}9Zyp>j?D7+J8dvS9shGev6R8Q6 -zxtx4hTETGOp07nMe{Bq9i%jlS4+iiHIp_#aQh1}Rgeg%ykT*?gknhUQ6a8!_ZeKh@ -zRp8ik4ksMUt`$-Jjv7k@;Bf3zt)J$rh0s<{fhBT(|GTGep2A%|bL6X{_?j7YlRO}4 -zzFgO{8w`Wiww36?z9ir5hr-`+^pz%Mma)&3cW%B9|GdrYYm7v}(bw6J9MUvXQh%(Y -zh`nUn)Qq!zbP`(Xw+C!sE6_-9(t&Zf0DsWGEN-e%;}AW_FN>*U86Pctd88;L0|#2$|$3k|m2 -zpV!Mkp7GxIvPd4Y6Iu5#-+s!AH)g^B{bgZ1wMu5C>=W%G5f2L;H7tE65uCvjW=~iI -z$(;QS0X99g6e2?S-7~&^3+837_wee*;(Yh-?`7z;$FGDgaZ-aN?6W($8K*52gCZiY -zU;IiWpD=i|IC7pwKUv!{-3o>J`SldZx4$Xz2nNodVITiIzO}2Dm$yseLL(A6+>yH+ -z-o|MtIJFXAX(0#DQ(AXMQOB~w!yYyT9z%3+Ss<+I{Y`?&83%om^3;6l1z?W2GPG34o*hud8D -z+>$&0Y+~Fir0t150eemwoStfUIl%HWlXJYYM~Q65DUZZKF)fZmsq=&OJj -z_#A!qO|X@C_!d44{*^c;n2y=Xt}mR&)7@DTFQWNN-tnk&B#mr@Oi$$36BzmvetC#g -zsl~OXVR>9T0_Zc#yI&c)Lu1d2p@)Wu?qZRi^@s2saY1!y)Ay8|@65dS5s8A-@o~rZ -zqNVCyjB_a~=5gUt2es*x^s*wDOqcX9!u`4p>s%|wskz8AWqbgDu+X-Y_Mu%Q8#8@1 -zFV;h3iYqT_L0I?1-5UWI=j@`8(QMKET0+bTAUR)8x5&y}?NnjKCSSpXl(CcD3bDH3ik@BNy(>^(1>-vLWIa{cjZO-wrs -zZ<6t(GJTb0I@9b)VnHBTNm!%b_CHQbR;w?96ToAUT|Ia9g~Uz&&Z<@Gd?g%RWRt@k -z_GK9U^6Laf`gPiNGVhoZcDM3n^*6@)a3aQ6gw?}~QxH(O?mb77w(32<-P;9$VuG`5 -zed#=j+D`~5-8-!JJ -zcaeh1_iMr19s*o=Qo&BwW%g~fzXSiD2e}#F%w -z{{6gp)+nOS)oTWu4n=h%oAQO&c-WX^WrUNdlKaAi%Dr^^>!(l0 -z?QV)b;&Lj(HT`(KT??J(vq~|^I6Z;^5w};Mzl2Ehv9z4$Qh8N~a1HPr` -z*cB{ZZ1A+W(5?Hp755Q+8rA)r7_)Y{DfKcG%kii1tRu;9N%_!$vdhP8y869NAD#xF -zFP?`-^K-$^2rJ?E(wKCIra(Q#Cx$O8<1kQaJMD-wL4lxy-JG3X} -z(zMj6AbJu__iTahHs{@-+>peAgVg2L+{!RnI#6?UOmtbcam1g5!e#n=e-8WgEWq-l -zgqS1XN5WF-T0H##rRiJuVNt=ItF9cJ@q#B*n0$W5AhzMMC<*Erv~wL1{Nh{f>5;Q> -zGW3Y6j6i$C^Ye{hW1E&lC)UEUWP9rAPd=#=Q*tomfyf32e^{ -zM^uOR`$)ob#UCfHf0bwF+q3kHR8TwV|Tp2hn -zaLgX43?nAJz?18~e|k_xx-xhZelabw8^@UkgyxQ+JqNw~$_VvS6j_{42~*WZVA2H^*Z0jCS9U(L -z2*1PU!5GHNwn40YWgmSk=!G7-sXb@eti4_J1o+W2{+?h=)KgA)>=32fb->OC4%`&O -z?s(v=V`|MgvOd16J5=;iP2me;m`-=o4in20eup>KmBbCc)7U#`W%tBAJcXy{ -zyPZnk<{g5WfqWNmK3WB{$^pdg%_tdv7{bvsc)<-d2Zt5iOro{XDcl97@l8(iOwO0O -zUo5b5zUFoA*4T#*qfhJ9T2JM?FnS{45<-S5=*CCiRdKR#ryqR2sD3XJi_oECyl`$_ -z$xaDf%9JelZgq;s4ZJtrY>Dq88tfD?p4Q7(#=?&ucqk9aPh?)Ro1y+)%xxG)yhlgF -z;lS8%4?Hq?Q|3JNjdfCyA+G8fxWzkj68aPy34<26*wJ7A@y@I(iXMe*GGMoKug8Sm -zd#|@F7`Jx3XqtRAXE^m}pEQpR#tZ8$U&{c$tE;`4-<1m8)vwQ`(7_-mdNMkWXXe-1 -zGj3PNd(3fAf}HPJ_td->w(lEAdE#jjcg`D%muc_$tTq7pMN@3EDptwV0jGE{1ho(H -zQN`ao!Q!%z=h}CD)p@u8?}Xe(duolJ=l^5gvp4|ME{qx1>h_6`s_( -zSU8S;Z9nD&k9ht5FYwArtL)v~mTtE?>NW -z22=Ymq%B8oop$L!I3Z79ZmC3AGgBdypWr!{cD6ATvc7u`eFy{Y(ANe*ql09{_VD%#QT-#w0~`ikMCFBF53oo -z@iKBwy;<4cjJwU{69fSuDtg_(no^Li`mUeDD4r2g6K -z*Pr6ii(u6pf;n*_2LK|^lYLr#4Mfg_P|mqEWP}8v+zRP&#pJFyK8a(QzzlPr`ja -z*bW9D1FY3*cE+(2VRgBGwSFg2L1JyG_LiX_GSsn9qH0HfVGTBEtx~~dt7c$`)h3R; -zgg(JkL62JeyIhu%a^Ws*X&yKn5))4dXP*6C+S)7jqTz`LM1_;*rgP1ZsKOH0o*sUQ -zM)J{Sq-9V(=jTUE4-Rt$_-XXj*+Ob(6ISn#y(Pud<(|cGw`N-Ms7fQqKG6NOY>T!v=hvCo# -zvcpx8c1%fP&@W`1;P|?ICcqI%{`7su6~WIknjcaKAG#~^)r%`Oe3w`4&Y>r@PVbfj -zVerdgidr^u9%O!JS?LE34I|~Ab4yGhn4fkys4rSHe63oxtIvVQ0?PZ94C;42Fy}o~ -z+9U0o8nqrkY`uH#XO){N%}-ArsK@ScPRj8M^i9j|vn#x_S*3OKGq55u#ufmK3n`+N -z)#=y1iz!Sgf7b7t{CUj#f}H71R`SO>ZZ(wNJOZZ(>5OQcc{xi?P(tGq%;(KKhY_8* -zXEAic$)dO7__?bwMlWDRLjhCH__+gLt5vLly!J4LjMX9^epHj6Ngf6Idc;S#9d1QC -zaQ6oA#zi|)okzu8R!$%P3O>Hpe&-aq0r-nfxHQ@qCfs|I;Fd`nsRzNZG*H0B&k1Us -zYVv$lNpDr1L{N3fM>Vl>Ug(8`oZ#jck1)T;vN6}%E$lKJy!3RS9Wr%%B2ealm490q -z=dymMmzP9^$Ldln6`7>ZdgYi9cb4+kO=LD1UYt8qfveOpV-)u93tZZgWPMrj9y!6< -z%tj`2xu=3o%+qVBW&1MPTN!B&^#b7=89{Ygg -zEvzc0d&`do!&k_8sx)g1cO_O&xul%XY@6tZ?v3P{M^H_ -z*74B&CFQefe2?y&htlA8MAPnEJ3{EkKFb@(3^mgem5bDI@0ME`Q$eoZfVr#&_s|F{)B=s^P=Q%g$D6uG -zWN!M{5fPmw8=9tk{Gc{L9+Bc+XJiGM%>>P~> -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 -z;r0Es@Cm`O3QVY`op#>IprdFkffZu4EryIKoi -z@#5noV%t@Wx!-a5r-I|`eAs=@U3CplcCnQhiTJrTa({9QC4?HXxz)(d9m18)HFrM& -z-Cq13{I>4r;WUqoQmZEpD0gpWk|USVr=cxx;d%)?OnMXjv$#4WBe#klVdn6@L4cji -zt!o(qv1F9{Sl2=vs0)UE`#k9R$=Vhze8MT3p=_J;is&txV5#_ZjLX>`oZ1rD2@}`N -zd6cv58l{1oEvf|I6`^m6{~BoYd6eS;X{*ahc32pWKzx^Z^uEFgHO#BShGpmTRp@;G -zmAU)tcECGyytL0)^6@#y)hco6#OZv#8Ah%uLzozEM*>> -zn5Ci9`(U7a@?$PRmsajuqxCpwbew~aGMp7nFEV7_#Q|CbxC=Uq=1Fyd78*}K*0{t8 -zTdk{XEeJtesE_=osh(iHpQDxOBc8D)tLIXA-|?ZI#}n_2&Ley^+3jvn^Du~p-@7P= -zF;b0KmN#$dAk;2zj21zir7S0vc}(?~CPE_V4WDD=iVI4H^C?);qXlpbk@D@N=H*m_ -zBlo*_ombzxaHZ7m+q&41-EvIQ+#FJ1JG&1CxtYt}S9xiXOW!kiW^J}P9_e#Y`GhqI -z(20WI|3vlgOl^u4GHs=|uvZeE9u4akA}k -zzC8CZKLq`<@`+Csq4w*-?#BZ4t-m0F_9xHwjr~95vDt-_VyP8HT`h56VRWk=cU(T0 -zp__PKxm*KNjJyfECq@%d=%ZHmEOKgpC)bx;1z9W*G@Jto_hw|>7lzeUwR9fv&3$a` -zg4P!Hqj+&{!mBL%xk_$bHxWZL*ET%K1lA|dW3!U&XeVOr)%bm1BbI^t%B_SL!bf`% -z2(b2Hjyfa&sd5r8z-H8W8P4T_X_mZ;_(`K5nfK?4$1w&kZk&lkY6fJwP2ZwNO-}YC -z?RcGkYJ48c$7CImicKy|5p>Btc{4x1@J}KhZ{cS==cWX&8aA*`E&lp{8|M+`Q+*zJ;Gkol^=IexycB*epnu(#(8jd%f(Vd53xbM=B=1!Q -z=i_E^6Jg*+o(k2v*jN?!?3(Loj$2j_*n#1a&-=E;oaIC72*;VUW8eOFu%Rxa0N%$2 -z8!7v-S$(J+SinIK*1d7vxUtKl3-BA=eSCW`?bAA9$rBS6hStp+57tomv9L&GK1H*_K?#YpG>G|BqOw%ptvb1S0CI5 -z_s&-&BaI(tw;FpARH`MzIy*E1rC2+5qt0AH?ptX5bj|U$i^Nu?vDPJ -zFpI?>udxTx?ect|T<&YT5A+<4qYkk>8)kM4#;zK+DzO)Vj>D&BeCOWfBZG%^GL;$S -z)MgkIbzezYQo&OkM&%?|tc*vv|x>1P>0H -zA^`Sho);97{Rl(fQv2FA30+i%E72k^sHZbBd*k`+4R{^z#ly7?K}SqBY7Y6_8`2Ll -z)yceeFQ?JD|3fi=nPXSsA@uKhPwvEg`+wnT#kS6d67OlsdrQzenf!trIOs|b_BZVV -zKFF_9K{u`vfukhTJ!Qz& -zUsH8skC5%xWDmHIbw1++hZ9$h;da0O^!W;u)ORqG=a!{jj?nyW{(QWY)e>Cl^AkoC -zI9@QqZF-V;A>PiXF|hP}oaB!At*SOoB-_fGWy6=clcV0kGZjzR3FjT7``P`A0PIP7 -zDBOVQQ@(we=`7#r`wh8*eS^9Fe&AHrF`?FRn*VNvI=GyzR3#+p^S`W5e^@RYeT*`v -zPNinY>Z9u3oN2}Y*&9jb5@zZTl>>k%1+$<9AsW44GG>M1ptWf``Za+9f37bO4)?-6 -zLhO$#%yt@ve#R|E3JwsjTxn+oKJvJQL`;udoVrkALXT?O@kbcsas6|2GhURpj-E&9 -zH@~;4QYYs6y^+BubAM97Co>OOFJQ*hOQd=d&iX)jk&E2E9j-P!Ug$A^RxB;~O*JtF -zeoe?!B5T#(GF^jsWZ|2IhwaV5cvS^Svi3V)jFmOhhmK_slD>86d>F=t9GcAGhFDq$ -zkxtphNw-ZF)N~o8T~0{U`6i;zVK4Y8jWN`yRUORoxEH}6>!|Y(Xkd)qw$tKgqJ1`P -zh#w~p5=W3_ex=$d71ff{%tHJnhe_mt`MVhW?ZcZraN<+pj*8%TV89#4``6D}SSp^b -zFNpvj#Sb$Y$UT0RDS~PVAErIodOd@km{sX8GNBS>>2-BhLo#?l&A0B|<66WixZ`^4 -zC+sKbcWj(!BtA=S9VL56AMT+AF9+-QO!jd>Xq@lv<%05V!^oo?yNUTlv;L9pcw -z46k#Yefp;Cc|1iZJ`3`yUYZV4)5~_OvGv;hSY^UKq(FRUc)$Y} -z=e=~OK9xBt*>9L>d52%7EkOkn((gp?{+dNvRi`}(10gsHr_d7wZ@mxav)E!SfLGELKMz0(L-I8O-G~#_X5y -zOuhgP?rkDcgmeo5o)#;e6K?Y2+_F{xY#Hk^%dGd~z9-Aut|{@ne8P6F)sbTWU*Bj# -z4U0pErj> -zc4C0y^cs}h!nJLU*=nu9qB~ac7|JRAoZ@|uANBc6Ir;G%l$&Ebr1ujU3QKKLpG!PW -z*So0lCESi`4NsK~!pS)_{y@Q<9p{LdDfQ20 -z`I@z-#~1zINb%LT7s=ePoizXS_Hz7tc9^ptuMujyE85I#eQmaB_sn&7>3JJAkoGRT -z;{LNCU~TkR&fz4sI9ZeaT`IU^LVI^^heHl4PwZotu$u$G?s)vg -zi{TkQcSofgFb+IsiQmLC&-CX*T9uM@I^dJd;qc*OD~#yT*Bf6JLZ-cWExiX%8n%7b -z(f{ltx~JzFLk88Ld|q%4aJc&d1LmWAHlLup0HBKl0(xcEH4Dk*1f`X)x_FrW?-w7r)zR7c$JL3DT^`_-)nLEY{yJYI3{ -z(2;!~Z(%3BC)$xLHe#@x`Ix3=|nK!UcbkpM5=CtN*)oZO<})_l~kXuEaF8( -z#l*u_5B3pB$Vl=$O7LFQ=Rot8SbEI*{mcgnFEe;TeNrnyuXb2)Wf;pPj0^XE3V%L} -z@r^Fx*_eZ=zBnOzfwxIN1kHwYS5O~Q)PNxBvGloi4u@MndVXZx60p!{A532O##>NY -zg|^guk@}%i?GIl)G^8quZ15liHRvET1*a!J79N3jZIiGE<5dWY-oq*UMN2qmxDV!P~)bfeY(it>zDR^ULSnuHdi3heLU^E0OmM#)D^xy-&cdn -zMHC;%dqEd{ -zFM$)?or@(SC&`{PF`~r2MDJtQKCyi*%x9_Y1@e9V%_TxJNBquFLAp#T^S83aGExB(#IDYavw;eJ5I@Y -z;x=@_f#9%vjWVZP)>Gb3Jr90x<9D*hKnZWoAjEBuhNaM;SP`S!l=Y*Z_l>VyOUeyEO>V|%etR!Lc^Q`W^0f-8c5*Kvm -zv7mGF^5A;lr??}2JLi?m?^*$IZ^zrkf-LWw85Fn)s6-NV5%*!tzDJmp(uq#Oka>)> -z0ic1|@!1OcrzK?QF=ML_<#Xz>q8ZsLhM;{5eqM2qo=I8fd~pBmc`dycSX3CoClZV| -zJHB)O6mveUU3SCv{M-!S+_atXTrYiC%*_xN6=ih3x+3%vTU4|wn}J5%;hWkIrY72z -zu@LRkp&S>C<|=N|bJCi9Qdta6cY9 -z@%_`iK*tGxq9G5RZ#+uX%cETfj@H$*5roCh3aP_td6!fisl|nO+4;&G*)6^EIbBQJ -zg|Szb&We(IO03R}Y?Ng@HR47Wm-I4w0z({*_L=!Ee#^7C;324oWwdYR!<3T+6&Cc^ -z8Eoe#Ufd!&^0*)=wgi5v_OJBLrwd3f;A9sbTXAEEudVeq>^ye&(9diYj5~B4hjS={ -z8%mmq&uMP&``8r=(rWX?&v@}xgTmn>p?zM=L551rdHmbUb=F1SRY)N;yw4Id?Mf1JH-rDX{M_=_TtC!I4 -zmjpJx2Bv%*c_lOvy7(pedsI>n)aGN;T;9-)a2D?D9_tGysh9IRelC%V50r6Dt;bab -zoVPUzY(!7I^hK+uqiK12<}vZ?OF@TxKhNr!98rBxu~3<6_=>%^g$9pmXs^`82dXq@ -zVG2~M>ILlkSix4yk-kIa$IoHfejj)hTbJTbt9R!=uaeo1R**n1-!BP7o4N|@=fR7; -z=q_RRv&{K!%|1gF3IQ6+qoQ0dPbj$zxU;SRC?;i?KXO6273>c*VjwYoQ@HW)h~%`R -z?d>YqXc4R9TB`&n%muHypHE0kefU;Eocw&RY2Y%MN1l<237DIO`fG27tVo!DcaiTc@^wy@lh?Y$A`}& -zN6@4f?_I}oj*Nq!c7%)}T!1^S-pA{~HI&n3Z~NN&BCUIS@@HmLjCon>z8c$nodT{c -zJ@C6ztW~42PvZPDq|wy^s+tNuZ5WX&Wc42H{8mr -z5?{M99n^r!o);}~AM%sPvD%j|(RboiYf_+-#d!QwEc>HAYKWXp=??#WJ8hf`g -zB%_a3x>++!YhxGm1Kq)f6D}^HHlu?nu!b(Vb$PO5-&ga&&fC4U78udimr5Ffl2?XO -zAM8%%1UPzDK1VH`t(SWkG2`R~Gfz43SxX>-DIsIr#%^LLR?-g^AV -z%#K0$BM39OK4))b3LjbUL!a{4@MoyXh?iDPl}&SGKDGo`8)ROxAfo%;LZ4{OLc~`m -z4sBo$*u!Cc`i}BpdmQ}iycNH7U*Lh$_53GSNbY$!2;<+h94eMTpK`XLelU4Uu!uNqUMlXulnO8V6rPGd5%Ot$uShFV>@2;?W_`ou -zc-?yg!OvvpTZRico$N0mMIN?@?C{4&^-*9yUq?ZnqXk)o1y{36_Qb*-oi4iPlJ+BX -zV1-66F?EJV4leFv4(f1)=M@Snbrvl{a8-RN;8enJs1(%QPUnz{!2qIRp0zlR;`FvZ -zS|53(S`{DDCBv5_e6LX3LuURpp(Qh%T;@aKF@E;~w&v9n8N?CgB4jo%M@qRLWuF5> -zDUaB;>Erw_rp`h9H1~u?0_45WCffCWl(x^1;z@bT6L?rqx)iBpW||RV~cn^5d)CofpOc4qdUuz34IaD6)&RQdyt~QhVSCT^7#q{X!b2gfydr5YY>9u5@Ii!cw>P(?hpc&IVDCRTU*quDv3Y;l;)^T^9L -zw8WWn9aH$e7kr~1eO{AJk_P;^3WK%4eQ(NzALG0}6b_%1z3st!ZqTbcQqb~uS@`pM -zSx;^p+QX -zsdEF8^5xr;f`tP}u0&1iwX2q&&_`GZQQr?Cju`mDKTRlUZetlH#W|_6i`;h`eB-t) -zVqJ%OR_mOW?j;Kng}!bbqn}iN7fTjJXc`6w>&$hj9V2p1e?)9*A9_r(^gQ&*!V&k_ -z<2Rn%uOOEn!aHb#1o1E(@HswvPFn)##RSc)_zIFDJni^lAGnw8lcM2= -zStaDMoEwJoBEEZ;Mu!NqKdoX~Yq?oQbxQS;VNlW~;wt!D@Y0%1j8)&>wiz5gNCIZ( -zEIQwiUMCvJ%@8z4ZIsG7tNr+y$g+vZ1KDE22d+U1n<*E4hv)`sbdZoO1ZE{KhT%C! -z&as8#vgdj}KvccX8W*VGK!Z5!cU?Ocv(e1AUpf^#{;4FKK9ghea(yu+@F7OeT{QF6 -zgo00ov)ScUrjS*!z4yJqJFw;1qyaz!(Ts1u+HR@Imqh#6lDDsuPeI=1NIjhK5@0ku -zKzbGwq@um+zA9TboF|vW824OxsX0pMUIOe%$j03|kxjC!XmiX8UOL6Qcl}z|Wp9#k -zD`$2e8*bXDvD}dQw!fA3DCY_|pS=%1I&S3RUP5!FCdUhpyn0}OKb+vArJm9yXpyj# -zS=4Mh=u)W7R{;F7Ux0?PDN-wsmgd9P`GN3P_h3v7v_*32 -zkzXlEnXLo|tj?KDJZi-Kfa|&0pEIVEf4-83J;2}$*eIOuoIcpp&v$LJc30+>`hd4W -zCmglWODi#$C+F~mh2r7Tg@EieqE95RHIVsAy7&b}WevLN*tYdg4by4*L`aZR*V$_L -z6(DzfII4CT=wVzMQodM9@E%yv=%VB2l|>^!N_B5IJ;;uddEiy*3~e0*#<>sglD!~- -zIJ6z-oRK_&CX?o=^Qjb^^m{&kHuCXYJ?B%XyVS3^*aHN@*e&hhGpW!a_Yo#iVS1R* -z(ir5#*ORk%^WIA*8nC=9ABUx*m%HS8EuL|Q|Jv>8)TU{^dj5W^zjexxP+i+bSumQQkIe#FYd2F>q@ONkJLW6?JdJK?b{EJ+q|MbxsZEl!@gN@m-d7Go&HJ% -z@$m{Li33;QB`^I9m0hwG*)#EOiZzx(Kg^5+|&p3Xl!mOe0iuWtBJqcSHJfhwpm+^mt%c2 -z+)?Gwk$y#ldS9^M?VNSYI&|5yx`!NRLv86qWjCI%M@$38f+5u@szPr_x;dp{+7Zqh -zSk_1leo^di4O2Jy+p5yP&NI39!jk*#OXm?6r35r!q*L&A8JrimZ|7g@7YH`khxHI= -zSIwid*%A+pQ>n#>oJWgSpsL)RLXAY5&8AtM=Aeb;r`(94damGAnR~@4QHTOSH#m2w -zCC|9w*C!lblT5Jj-M+P{^f-W>rD*i7 -zOv<(UcDK-%&iy?co&Yr2+bVi8-ahMNr&EK2CZw~Dh_Avemao4$9f01h=&Nzq79!f+ -z<|byz*D>RdQ})SAOZY@tEH+uB<<%nX%r%T551?xB?IiAgn -z(!r%i`cLj$&)YV`Y=4eG1p!uryhIX_HExw-zXlg74!wW4PpG~ -zn;>nE%jHRSJN@|GI%VQ%;l`+0u7)9@os{o@@iu#?35(_+CfRwl*DUDmoOn6L>=aN; -zLO9iD+b75+2G}p!5~yDS#SJ?13f)Y>=hD8j4>8wal>^rwvs$N{^I$nXLQhF?&vNiG -zOsKR|uw7J7HrYasU5YET{Ge!jmIf%dPAY3^;b3vGr5jy-wSI6tHMj1ahl%k&c~3ex -z8N20o+YGgZ3OMy7&9N5+qd(DtGr3piB;D1|GlOPw8rS*e)FDN<=fHb5V+k!FJmuAa -zQyRydAB(g5wKl~k%5(<^?RFSC9xgQQ;`j8ZBo<`epjMa!qIPcG^Xh;bSK>=XRqyY~ -z4R}>;jJDd@vFqzgs5=2?#IYfGQ9c2r8pg~N+&s#C8Mif#Kz_0;;jo@?nQrzs@#17^8Sp%Qw -zDUpQ0(Rw(_uj6LR&T31@Z}2-1Th-mf!YEV`J#OwAiTh&8i8@n=`6*uF!-U=4tAH91 -zETsD>x|DxTQ(^<3SgC-Y`OXCO09ir6+d$Pq>mWmzPI3> -zbqCUJq^<72VBa%(R6BO_5!hTPf||#o!7mu9S-?1EJK{OspUng{eN#*TpVM03;Hz*h -zKN^+25%D#~{d0anCAoR!n;J?ahUjh_s}raf$-0pFU{WYA^Oz!$U}`xlfaZC?^5yEQ -z)extmbsqEenbK5U;Q)O}njK!|z=5k&b(1QRyvsb*vUsO(kaV7)eT~Es#4msoNFI!rYUsBJAIdtQ*$`qgWa~@h0 -zfe<8}qPk!euHXmcascMgC(ZC}FAB_cVVjm7kBI{Yv$3Zy9QHffZ};@xxBfqo&Q`m@Q1i@w;_BQ!&F6C@>19?pJ6n%}yH_;z==o_lMFI*wtM -z=k8&48#$1lK3!ZB?VJE!aW2%E>metlFFQU`|tlTev -z4?E%Ng`){q>X^jk@4TDB!XMmoXF8*W$?2VkkfP#z!!kQ9dYcDp2XGJ^Wr?({9@aEk -zkihez?QN0aIMO6LX)|lr4L=MoCKIIxj8U6za%2OlWd&f?OGT>CQNO -zk8wD{Bhz<<@IJQb9hnISm_Ad0q^vG|dXcCu0<`HvumbT*4R|qH&7OWQhp~Ek3ZmL) -z`ksIKqg{DAOizZ5sJ^hk@whX}kv)eL=}gb(mU2|b_&AkS5t)w?)Cui8PMbBOzCBJemmqF_ZSo-R!@?`Uk9TWQ((v44juo4cQ$o3nD}aQw -zM{Fxa)ULgcB+A2A#!Y#B%H6JzrI&1-XyL1^+c%;?=w59P<5^e4yh%nE?mUX&*T2fH -z&y6|#7DiY;eLT^Zd*AQf(y_WiDLMrjNgCSD4!j~zC38RM89o8w`_r -zg8Zo~A3;<}ixR`-;IoI3vh_uhn?T=-GFP^ZZF%z4nUKtpc&My|hmXx?2>#>&Ag?!e -zeOa`rxrY$KS6ByP9>1}4fhjEfoENl?T`}P%=_e{ji|3}=!SWjnGK^-j_?XnmbnF{qC;GFd -zB6grmlgBt?K}b>t-4iY45b$ZF6{E|70gEphKz){hyv3~~MQ+;jmG~P8?s-+kA)HA -z!?HJ1-e9HZN)tq~QVmS;WABXUZ289Wip&7oa2t>4Vg~&sgy?DW0K+7ZV6gyoE|xEW -z2S3NXJgxDhe+#<7tDEl}62kukjtQ@`Y0{ -zh2y&jtMCYcq)7zMCW7z5jpmA5cB$@GBgLMcr@>(;tojAq6h?%j_c-bRPSuTOp&RJ; -zKDi`9WXkSxO4<;rlKB05igNjds7oe!0G?hwq4Km6De~j(>-(@a55Z@`)0~fr?^}23 -zJ{nlpC+~NOW)&XNw~iGH%3|V+!MIj>N&(nhWy~JL!COtRcTdFweHxI*LqxF_TrBQj -zaXbM~9n -z0i&L;?%1^<*vf{pn0mlh -zk}_}I(VbxC2~y3#@g%Bh1}jvii*g=IzQc^fkLR$e=jVv$lR;j3nmm2yYr^dtmxe2F -z5N`urx;HHCe6=1W5(e<(mMos#-mhnDdGS9%LJm4CHu$NHd*P7gDdS?_@4TsfO*=8n -z513I*_wA%v;cV6K7XMKtWq_*(@!mI?a_n4b(k_|+0wTD(I|se&2-cdC07Bkj&Ag%H -z!iOJSHyRA8ufc+m=Z@*^N0@Zd&rtaTngWl6C(*aZ!aw`7=!$bL+GC7grt|Vwtk|EQ -z`{N^ni0Iv9r!Q103F&9+*N5au)vh_44wAyeZ6s}eYWyHu`UG6xYiFv9Su0h1%05r$ -z_%avgU>c}^evT787qQM7y!DNVqXC7G=8Gq0>F|kT-d%Y)Bh(@|<3GXAA -zPR&xkFB03lUPl)YfUm+6<)&?{OLFN@Zl&*o7|of5bcB9NP#;-CmJ72+SpL5M(w)4C -zFbMVarai-=XYX4pvi|75DgsyfS8PYfys4r5xSG5TUF5d~6yU9Av3%@U=o;L-nM+ttrJqxoW5_DKrW7oBBv -z=4*Q)_!#SXf@77+kxsi%D|CdG&zZ`4G0Bl$=dCa+TLr2)WHT%g? -zslr3D5PI#rwbDqEemc%fO5z|*aLh44m$}E2cT@I_oqerKGwPmE0h5#Tu=J;naQIyp -zZ4J9`8OwaTU%;L&y+aSZ&vnAq^H}G1M@LSlwhj&xFXmfq%`=&E6OPc6)l#v>T(=aL -ztYC43ouk`#CAmaV|9Wt5|Ll+V8b%{d7DK+o74em -z6hop7I0nBg42cD`J?M|JJlZFM-Fnv0#4E05Jo%*KXY9b~y?8)RMP-@%)#;{LOxd@>Um%F3Gr*Z7U*B%xudAED6XGh+!~e`>LZ3qJr=gII -zHd`_DFdVK~;B?~P*uGB~jov|)>>OCd>J^a)O*o_a#B@Osxchng=TX3w>{h+eqZ6*N -z@ZQ5r`8XsoiqKomv_%_*bq?60c=ztbJU8`W*%Ji#$UEuDpwGHJ=?6Jj2pq?U-rvMLYE7Y6%kGvQv^47koz9~-(OIPX-i0x~t6#-* -zW8ngr&sP?4cLfBIwZ}t=p4dGdD7sfmB4x|_;$!3z>LK^69R^kG)7yMa%r4Au*0sJS -z^F(A$>|4Y4Ad~gNmqZN%XE?vXJ>_sFtkln_A9*p|%dDx5D^FB~VBK>@@39@3r`fh| -zMrYzVr03!N#qD!W#?#xd=U$qIv-sC9;02{gWx17J2;hmL;%>2#*4+1NklzoCbiZ3_ -z$6Mx{0^u7<3`BYjjK1@TyX}5BZ5rwv0U85ht#9$_TZP9%;EM%AWLsdF$C!_fL~A!9 -z1j(CX!T?g6Q%N~~jE|`REkYc5(nuQvI^Qc+0r!&_5w<1Le$3y5rhbNR0lX2`pXE9e -zZI4)}W1zG#DL)|DIFE6Z9R3_IY+B8Y?EU*yc%qM+2c>B1J~GBh>F8%|E+1@45y*2L -z)St41erq1L;-0UStGo3djGz{pw#ePjgctcyVE&Ye0oW~jXyC$UVYNSdK8ou07^+iY@NnQwn1Fu|}y9H4>r!k-2D -z+`PNM-95d^=V_jmbNddpoiAxApvr;x$a)aQiU1x)uvX4QbM6qAnAi-}+PZRHll*WD)uX!$}o9ND{RxqO7D&;3f+^bAVSSAg~4 -z!RHC|G9-BFGYR(K8;(ay%(&o|5Tvil3m3fZeBZp+R;$Yn)nzF^ipQkxl_S1;S)FOJ -z!%o2qkN>Qn_NuN)$d;QB83*ggX&9XZl*p^&2}YpV3@0zy -zt!v=^7_k>6>v>BBJVDXg-jD -zX7aU4Yi+aJaG;LU($^#CY1KN;d_73n@eXYswOTwDZF?Wj&rFAc1dD!Ck;6e&Zb0A7 -z6w8a5H+S-)pqU>fHUg{1+9i2UV>WZt6AC99B=Rc{gXPP~LS3R+l6h+ztUCF?k+WYi -zLrgiBDBg!Abq`gc6P!mfza;1pR(UZ3#1hPq%#Q>YX&-zeCf!TQium~oAG$~SMt#Lc -zdYuozqypL*!TV<*3ysXK=tR>7k$$4k_qO*wPHF`g>@vLlWYfJSIs#F%o54=@`HW-6 -z!~qt*86|zaXBAv-zG#4h?R1|+X*`W^VKXrYb<}}FP@q1KExfud5A&{|$4#cq*zPwW -zTiXILbrXo{vpmD5O7jtBD5 -zuY_Aytoo9qJ#aX41-YY0pwn=xxS$*8J>gG(2ERWqu6b+h!22rWFA3WX=NzM9I)?aG -zqo273`}X&KCd{S@+{a-EPv!B9r$H1mpxEL8I)cqHqOOL=J?tsPyNJAZ1Ne#tT!O^X -zV{hti;!{w$;TBJha2ygDYYhR^zbegKz<4NMt>2N;KKA_tBL{HD+`6~XHQQN`pP(TN -z(RG-UiV<6lYxg|0enf=z6B!49^H_)Mlcq8bUuWnh#SeS)4Z@Kc=`4mQi6T4 -zEQYUt{Uq?{?Xi@GjC(vT#Kp{~VRs3?YqNY}3lVsHxd6T0SbR`5l|v!&A?)eB;%Pz2 -zB3}lvpJdf1Js!9HK!Y|w(nD)5mEzHO&+sp(c(5K)mmMjHc3lfT=a?(=2)&n`DnnLd -z&xdyT^{l;~$8K_e=Hr^id;u!Gg?2~~&s)X#Fe7`99mqu;fM!``^@GaA8%A9ls8h#Z -zMC!&8sq@Gp(&M*Tx)XbNUBBJ|=M3q&QKpVG7lf|icLM)dc5Y&_6jqOTYCnv2N$+C0 -z7S3ph+MA&8%A!nWh|KdV15RBNOt$PX&6gGp}D>0R+AtBhX -zWcM`Dtrt4)S5=`S__(hqu?W@^hHyY=1vY{*+%8+b5B0Y!Na);q&wGrE%~xcjtw5~G -z$@}Ovxl;&}-4plBsqKCcFcixo@dS9&*>b!#;fLGOweqwBW)TE|;flL{sc4);A&Qn3vWDUwJbY2f!&&<})}bfs{A+wqCww1NLm~#(S`r~K -zW1f$Yh^G_Clls2L@?6V!GKzV@Lj3NF4J0W -zvvzZwb16QW!Qnn@k;Z650qB%GUcNPziCy0Xn5^oqI1JgnZsuENF@C9=8Z! -zSLG@33+l0EeG_#bM!mom-?+rJ#zwO!Vo2BKg;gJ7I?9YJiFtzM1&aGn_8I^tmNG9Dm|LflR`R -zvG0Y}2Jqc_6T4TU=wuA=eC->X;@Bu{KY?5mLNM0!_;+zLNU=U5H4&soqUpO&2nOTW -zCSiTp4P;lSDIWo)p-p@{E2Z7I!<8?E*-e!28ph|_ZN7~r80QWB5T%@I|Bq8IXx9*wv(tG3S -z`uvV2mIPvj*7m8Sx3eEVUD4U_x8)`|ku4sv`TSM<_IH!3!63~DEkwxjmF}hbYHUCK -zRa+p8uH|n2ct5Y5BeRdV=NIj3_%Q~>5i6>jr=jqk -zfJYTH`{cOwRx%V=?}bNB8@UJpfO_l&Ydk2H{Fu=TMcAlP5o=7>P53FOoF|ij-<*hN -zIVjSphi-lujpLig7kBt`9+dBJ7d?x7b-1E4#kP44o7bL40lc2d3F;mprCs!Nsk%!g -zZV1r%q9bfu+neF)VGW-42RQuPy`5rDh$Ivax%O97ELx>xnIai~Lfspb|x%?GD -zDV|ksvbfqn+M-Olhq_^3z~T*_`>h}7Bd3igwrF2uOg&nDY$Cl8h#v=m>KqzzMct>A3%(3F -zenDMD=NQ0^u|co=Es^ -z{pDIqcBvI-he?=J{cERdc|V6{@fldX$!KLq@*ZWr -z@t{^yQWAP+dB3AB@2agOxem5KvGwE-j2CTA(tQ{mEPT$S<`LjWi!Z0%njt?ZqI5&` -z@YnViHj4YoDL9dj0t()1zE6C%Tw}L7>nZU#WudHJiJLANt4F>*;TJ+PqFY^U|~3#RlrZM0TbyRDKK^S$cwWOO9yp(|$wbK>cm&WCl^8z*Nei!4mJ -zj%TQ#i*&%`gaHhkyvvXPY2FsU`C*vK@W6ND6HS}8B&nRS?_wF -zG{;OdEuMn4{_2Tl_2LF)nZX|p-N`hmy!a&^I(%LZ5{#>Xx;yg!QiFH0qTuK6%09D*MH`8O17cc`G0e)KiCv -z$6^c&#IH~B?19BAcfZ3{Y4n!PqdO?1exq(JCy0La+9KO=k!HYEjl;nIY4^g -zynQd!%ZImNs=rKVEQ_6a%){a4~unE)SrgZb9^^54WBMjd3<*Y?5m8g>@R`Y -zPBD4n9T~f2Wv+N^W**(v3o(x}LJ&ljXGb6lB_Qp(nXe>zPus7$r -ze`%kj_Nap9(|#9?WCCsRo*6~JI2{`+r(FB%3V#3(?USv|y>CF@==DB5sRQ>?pF9VM -z(cyk^fdiEG?t30%`N{|oltJr`=b-bQtm^l09vGg8XTSWA>+fy1{UGJn=mV=a1jbWe -z9N9fQ2m81hLbl_mG1<)w?wW_?u1bi}CYP_lLPveo9xjh-8d2%II3ZC)u);j%9-H#EbIP)naAe=C?G(zy1OXFRXG2pT=>0v+vNTic@FE -z_`uN3qe?d+0aZtPByE`oAf8fBQi7V1PA~+%-u?9+V>n%B9N8nDDmZUsK7-3T`PUYmsSeMaV0i===!X -z+vjygp~I9!MN{Xkia_AV7stvs^JM#1y4E4UY*A%}n@CSG?&0sI7s0^<1`Qu4%?2p;PEbQB;s-l}vp8dY9j9$#;)qDG~y3>b`9ldiWZ-yQRUx+Mcnaj3tG6nY#zOssOO1n}Cq^|cB= -z^N6Yrd%=AR`^n2&1CEuezCx$=BzwE2SsX$3j*ryM#W`4-wq8{Q?vJKcLELNi;$}Br -zx(9vnt44b&E)IW>4@B31@8F&0mC2G5J3eElng}e%eCLJV8Y~ -z_o+7E7W|qcND!pkTEB3Qr!Sj*&D!Cq-@S0a^zfAL4DZh2lNt0rkS>vOQt#{!T7Gueu%bek~8q4kP;EthBK+Efv*uzWf0F -zPHvReh-cEoRRy3{Awe^2@H-iJ(TSc=sWH0oG&#iP_-AB>*;VXk?`V4uRgLyKZ*v=Xb@*6UC-I3)AFrdcL8u;;uMliRUot9{cT)K+Naxy*^56zVRZyh@5}Irb1lH!JQ7mm=S>kN -zMD#w^i03J7fixhtZdEW(jgwjB^R=m5volc-wQdm}!!Pr0=`-|w%!1?87Wa|XZ6{|c -zWW2LcZicr2hpqO)x#k^N)#w~Y-JztgGE(23RD;_oPa|Qf- -zmx^54gLRG6#$3Q -z5WsQ}ppXte;gw#drqGs2{eCIh>Usr|qu*`21DO>ZAOVDSU((Hmc$RGX;Z)96{KdlCFL`m&>-9xUOMu36Hn3CFSRsu`C{I#||38 -zcg@`TCch27qK2c+bXRtl&VwuCHOkw4Z0n6%>Svis%zVqKzO%{0*?#8a{0C_Ky!5^< -zPNaR5$-h>%o(arwsB`v?7*jc~wSY6^juqrs&t^60n4XvXu@H3t8h -z?kzW%qLE?J(M*^8tR|o=Dgc&^$2g -z%X&Z^|5(qJWTmf-v4BumShEac#2&bPvD5yJ6kgHb)M7`M0VW -zRTz#JE{yMiJVZ4&igmg5x~`Y|8-ZQ1ROqkm^%G7t#{AhREZ&k1i@x<@2821cCD_K9 -ziPl1uBv1ucz~TdsYM74V{0UAZThl_r8%#QTGl$hZa=Mo1Eb5&w@Qb(r@-Nt!$Ki)4 -zzqZD5Hs))3Fd_;pS#V!e-uvdQvG+3X6Cm`0*k%-V*3%6Z^kirnuwTum7=u*hx&fP1 -zfLRM=WIavYWLCUjX?4HE>NuZSyAv7X%}+?lcdIM%=46w7Z}NbjeX{TLTI-AbDP9!h -z;ZskX2?4gO8-<$|JU%lrO$Fl>({qaN9a=r~7CO7{HKBUM`%U~&J@NIWm77rC#pH17 -zXST0QBQG}Tuvi;y0-b8)LlE@YJmCfUjJQ3y$nN{V6HHh3I926>lAnUEyY`iNCw=X) -z?JmXJEqcI)gxh1zew}XUDal7w`*S*&Fhd?#|C%Wn)L%(o3KL3zF0edebu6A_rV}tk -zf@C*2A2_)vN?+lMsU;N}+52VJ>ZCpRA4G#r)|+dGSKr#N&ruea8kG9c0ZiwZK1F(L -zLbV^Z2^ayq2Q69N4KSMT6jWx)`to;WbJ(=I*nrx^&z;ZbvrYF_K4p(og?GtsKFM(N -z0kF*A&f|`rfc4>r)waugnulj*V{M -z30**rHB)4WN@9j5cxD06Vz-Wf;w^Bkb@?)#mjmGv$bOM?&t@w#)hUoiKVy&k@S9qR -zV)@$ju9DS4cAExtobVn!aG`_0Jf!HyJ2$l@Ezr)vLR5%z!47xFgRLQ-CPgcZ&!+*P -zM@#Zv^>}esG#sI#tA4_U{=ELydxTgJgD7sP<#D)gGHcmbzeC2ldK?TN#WLkCSZIbM -zi3u;H&%iyjA9H7zuRxx-VyMR3-q-0Q -zR7Q3(blAk@^O))pDvXq@?9T|2tZ#p|H4h|$y`BI@~4ikO+lxF>Y`o0xVd=aL_PsOpI8aBWjahnv|q_)o3T#uuHDM{d`YP#9`SLt -z9o?@d;AOyAaXZXM4~Rpj!(EaHjznXb%&^H4qWa3mWvQkz1>=dX;#zwDUl&~hS;OWlcoC|=Tl|-cdbG~K${K9k2O4jaE@0uUR>763 -zeVTOr@aGpee%OyviZgQGd;PB(=4%{I8+yO9y?iY2 -zDm`IQJLWE5Z#|E^2T;b2%Z>d^jU_QDoVOP;_&5PDE}WUI7jvr5DJp>$=~2d|6GyFz -zB^)jE2B;s?&-SF_z4<;Guq6QqM;77)IXp_$K%D;d7uj9l@zfc=_vvcQM6; -zG8LXW)zUa?Q{FE+vQdO|%bhsxT5WjpQPTFH4hF~DG~4ktmp?-X!5rqW#EhJS`U3bm -ztI)kS{2bHHJG&F)%?<4G#D*Ntz7ldIb2|)?8TfPibx5jX&?hb;rys^AI>gr3h3?aO -zG|cN22|G8tuOm0SDHeLGB9e*q|BpU*FHD=VE!Bk`WuHxah*1k;e%W-#j_L4bv8qYx -zJOSczUhtLP0_>}^nWJT*xJN*;`Mj8l_MlQDzZ?es926(d{i>}scl0R!yOfU$t2Ji3 -z8*IQA3FDEk!<K>AY;fJb1W@Ua*0%meXV>>+8R)<+D8@Tj>7&t0^;ONv%bd(_NnN_*UsrQ9LjNS!B@7PX -za|g*p43^f9d`_T`O623gOEzWDSNwC;MdHKr0+BWujt;@el_xO(dArk604kL92|a?C -zIx4CD1jHGKiWu%Q1w3z+jm~;o(k><@9&h`4J%(Xm-zP;UsT+D*77#Y -z*v@Am_w~vWOnkBfzvH?fXnN6HyT4SEB)h^6r#*n@=-6ITlX|c;47G7i^Zya{?zpz( -zOmnDzNAckw0rSngUOpi}rc6QepN7ENf~+N+2HNP|=d8V|iWwPEWJWxMwDv3ZnbawN -z+wcADw4B>TIHpCeFvpHE=*{bQJ0y9h;E3=NGHUmQn>KiCX``Y^@Z+zqGQk&W`}2Ha -zp?p0-u~;lh1|VQsmHi)pDNEB(kVGlM$bj^d@>=yjmS9{n719$lOyY=Vm`*MlJ6@BH6#VR*ubO{1O(%&UGG7 -zQB1tIPka$+8@0f3y5r0HG|-Va=i(F4Uu+;*Bel$7nSn=9FYQ~-k1IHENjozrTG%Vx -z@9d!9pu9WtR)jtc!sHakP#Qkd_e1=JRiFqzSrc#zT>)4K1n3Am0c<_(PJo-Ap`#fQ -z@3o1zMmcjMT+|;+m_#6x$tQ_dsDSwZ9_vXKz2tYK+v5pToA1yj&Fi6@{G|3?Vty)V -zYj0tO?s*+`pVpY8nELolA5-1ZPHrp>aJ+grpN{Tp_!(RIdGzown8N4SVpjyUFz6cX -zL{TVXCiw~ph@4nAJ4JY7?Vq~iQk!r+QjZTcCZ*xJ?LSUi&WfDduTNV!u|pMt&e<*(ajVV}stI9OCQ=h!Kv#eV9m?mn%r -zRB1J5oKBjQ9gVzjPd>8AgT+rHAy_inTblHi)YEnK)HHd42?kXd&EfBYZz=@0-`+3O -zjS>Ut3oLHchv>D=XWF&(g7r83We@+6`G)#s9`Vn1ma091R$}Iey@KXm_hS}*Y|nQ)9%NkjhT-ow -zlSmj*kKXdm!9UAxzuWanvX0VuE -zPcMi^6fj_(n&^Gi6DO3v_u-HfBzhhXJH0%QylsiE%2WPwWl9k_6V2*I4gZOv9|7$v%E!?&sW5T>;5^Jlwo)Zy^NVz9CediCPaD*!J6yA6&n3rW+r9 -zXH}?V2Ut*PPNi9tyw)fD+htgdJoZ+(08>D$zeh9z_pxkVAPP0&&x}WQ*w_G4J-(M* -z_|NuH+VmY8dcd@niou=LDRW{fdTruEswoVSKg`<|y@c9hultpn8)L<0b@%M96%pC?%mp=i)6 -zg-T?pxleKmj3$?rYhBTgR`9_FCO^363OJn0GvsqO+0a#1pmapEmM2D}gimx$Px_dt -zdx1jS+kNb*Zh_9_Lt}yZbk{m1&L_g9j?k?_Z}pygwB6+qUGe-P{6itVBZ3lPi%?>0 -zpv95;3k68tCpQYld!8(I&^?}rL0n;H8xO;o=|ubvgdV+i;NHyidk(WCknYYt3PPR+ -zhi95}z66OBPzzD^{5}nckwGXOa|O?3al-=Ey#u0la`@EZEX<=b-^s596S_o^lK?>Y -zHy(N3GYD5-xp=;cO1y*2gB-9|cx*1YTD= -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 -z?%O}Hasw_1!wKh#!pFNn -z^kfXh4j*s!!$sH}A!WPDPqf}*!gZV7zJT4C-!R=%Pom|8v4+u!Whq%OTU&RQcW;1T -zOx~YOgz)!^EKu7OviEJ`U8`>r9g;65xLCXSID}w#jK`y3=cYQ5`1MhE_qp&yavwna -za&Z}ESIXtlMDx$9*wnag8|V%*jJ$e1sR$qhHC21Rl)1Vi0R8BVjF{a!?ExjP86fYs -z@8388e9N)VbiKNvp?oy5U#;kC_5IqKcXR9YGoO#5JFR0LBH<@*1W}-bb(ER7y{L_a -z-xAw&8VPJ%c<>`E$pfTTZbXs?9h|vt8l7lrwx^tFgL%_$+YQp9B2$i>iLw%X{ER6` -za3sGSZaKWyj-Q?{7Z{4`N}VFF&+@yg6l8sNwesN+>wWrS>QSFFFjd-#_}V0S<~N*B -zu7XcpF2{T$E6JL5j{Y;I2^dMoB>mCM9J;h4K+|;a>N*@fCZ3gNmNTNR -z+^HBV9h+|U&v*V@Or;I6Mif3zKH)sJ@71D!XSKmGTrgpN_FV5zmGLZJ9tXf^+fq2OKqYqr1w&)R$m)0JjeAl$cX?A;ZBVcQia<0 -z%cHIH?XaDcOx~wCM;=W|UC**_-XwHy`Q9G0gL)pC*z%mcxNs2sP6pZv6ADJ%?!K>! -z-){&SqEwV<8}QN8$#Gq$2(`o0;ztUJH?$x1bvTuMum@C&i|9KO4zre*V}M0=2yV(Y -z*t`47o`H*u*Ne>q%Y=Z>L-Ol6F-u{-D*hG@a*ntk~5IYonq24bfgIiGHL(qq^o?n#Yqkz>j455XZjWwCLA+Xli0?T$QsSIbXq -zU)2hV2e4@{ON{bGvdknpurGprqkg2{gpeGKNS*~ZG_M7xL1k`UVLYJ9s&Vx -z?l}YZ8-Cyg7NAJ9J_Ys~nk!D%w0xor`|qonTui#38tnOumN0$US7bT%z*$ -z3(~P}pM8Q;(uyZ-&J{2m!uxp4d8Fv^=+EOv$Znf=q3UW#&KL2+;rNtf#{6Gn#Q*O< -z|M_2Uas1c+_;2yw-#7cO|NlS#^Z(UcSkt>PPsY6sg!FKK(wJVAF>STrJjlC{7gJ85 -zDeIRekJ~0){IIQ_rabkuCU~o*IIeD8gkpdAll(XfI!;v5yXqWZ7*~bQ?9b)fp0C%V -zPO`*M*Lhm69)a|y3ioo>naHbng@}F1$=3?BiNRbWG>)LRp2;d4sv -zV`=jhBhTxD{2KNZw#Qv?r6OVoc-qgUj^sS!g502eR6~ncp1FNUZu-6^6e)Rd+d8_uo4jQo#+6XsJecfw7^~??emSN -zV6oV1FG=y8%wn@$SMrnVq1vCDES@_EYXzqd2X!_NeVJDyot*j_B@}SYQ;(h0wT7tl -zp1ECt%6_mFdx9vAB^fbGFZ-#w`{)|z*#)>{cLDaWSq%%S(>l1jhl_ -z(5JNa@j#8zFu7#FbXeLxUvGJ2IT4)j=^BNsMGE=y2Gl0jGGflkTdnF3oc5_@*<1YC -z+(BP4lIrd}-k9H+CD=NuyBwfciAqli0~*KRR$YAy=th1<1o&7`9{Z9*LFqs`T$793 -z$NeGfryK|3KlvV6&sqlBeA}8UH!C#4_dBUK{~b5)Y5mhFdn%9 -zOl1DFujn}IH6l&z@OQaa0MnPa6ckj2zfm<(cnIB2XB{!9yBqh~W1x10fms(3X~oG2 -zvLWN(pdYItKCB3fnto0ni7!pYhn+a=QTyBNNX9I=a@Zsez{Hc7cJDo(dHznN1!kf@ -z_9)sLudu4vkdM$ePjLXxK3*dNeedVth}@UUm -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 -zqvU=V -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 -zzO(#vl4Jh}f|fu0|`khM%ep -z*kcEt77SYe5z+Dt!3AuES-n1w*K(R*IL}u;SH%c)cZR^r){MJBT;bqVUoF>K@wMQS -zaKl*Yo6VQX4!mY2fof-G*mihoxk1G3+68^Ik|R+1gw$uWN`E^AHmrFS1c92pVswwP -zcd%C$Ur#fII@Q{MzL(r;H3FK>;g!4k{&{c;@q(wfq9Yhwuc5{q0LcEv`ZVwew?Wij -zo&-|#ED;5kkR5px4_LxpVGy*>+kk-fv}>MN43Bpx+b4mtpz-bAx-nK-i_}-FqqGK -zQN|f^)lLjb)8{;FNdR;6^%9?vZ0sRw%AC91dEJMk2zfid0fE^Xf_@+7%L*`{gcJ^~ -z6U)hR@bEohY^+-6tdOJvT%tCMC-Lx0W7`G~?yi#~a!$$@v^0Y9)MngjExhyDOkcT& -z@o^C3b`8B7={(&Qi>Kn1SGYZe`K`DkjxtwEO4R8+DBkM|<-Z&;&iT2yOZ9m^^gUkJ -z<5CL4q{PL4Zu8VE(`Ky4HO(^(FS1*ivkz)I-dpBshNbCy(MuPZFT#Mx|@);T6)(+e-mes -z_(%5mb3;=E8J1J?&G=uI*Hi1}gZVgp7C&{wM1DRl> -z>5voWf#_L%fD~`}+m?ej9b+xNSE%e5pTh!Da*Dl-dFoh<)SXpBV1NdDZO{;Q`X(Ut -z31X4L>^mp4QO@<0FOo0}59lLYsN>EVz@^>@kN4}4cmt;U83wHVhK%x_=GVZTPO{)5 -zb@Tb(>qbbHQ6R}9Ot2~G$_@>)4jl;3vo -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 -z;mWn0Yp)*(Kb`9!?MS_s0LfR6g+K -zJDn%T-|GEL?3^mvVj18{oyWYip{uvDkK*p=cg?SLHvSR>d4MII4q!Mlkamz6 -zhpuKdvz$GGTP^(g_a1YRY;DzL}A%Q%*v%4`zI{O0#49Z=^izUujYP7p_0Tb|3I -zmY;QlOC4h2ERHd)_x%r?)P5*X-?Zb+;^a(6T=IGpBifi0cn-=+ZEaheu`y>Ps4uIr -z_1m@aij16;jPWY=&MWtee99S)%^`D5SdGgdo=J3q^{N{&d|}e%$5lM~=6=Up2;$tZ -z`epZ!LkMEgh9(f3+BqWAjh-W9ev;2J&$(Gr=uqcz)v1TWcf>5ZTVd2U@y-mM-d=us -zUbt;ewfds5B_r8t8oVDo1?M6~JC4wI8yX+cUi8c>!ZBgB*y!^xPibF+gSvcGma=O= -zzr&_i=WbARADe<}-Yp|2OZ-joozX8uWNo7mpMuP@?T?;_iE1CZJLmC3v!zY1O@7VV -zXVVQ#b~f8ypLYvmEq}xk-iN>Z9!x%J@}2FFXU*Xw-I7&55$ESFaa)(|cS)kgn|Zi0 -zcJ!55#!w2=J%I5~OYhKo0T3Ez7t|l-C~~byo_yaN)pi@FKm;)@OmC-S>AJfuETAVI -zxqS(G$suWNCFq2WaynB#vNES!vv}X)0_$NHz8E%7Pl&@K1zF@*;$B*MB!h5$C;w=;B9c -zk68%eeIiotRZu2KCfp*zIj{5D4d){Pc%irbuwh=Kn1Z>O&?ng7KB0CdwYqk@{KAPO -zp?<(!apVG%oGrwgk4_ckz26iyYHID{_`Prh0S|}Y&$s5+u<+5})571(VCx*l^Nmqs -z8y!uk{4CP!zVan(`==$unrXl>H>t~?qvw4D91osRT8&g_4u@QR05#u)6809v=|z}= -zhf{Vjv-^~Cr`~|+gPE_Vqfvxx+#|7sFsF{tdGtZgBqAT<>!%Mj*(`mECGev6elS1E -zubtk5hMm^A4HZR@PtegfF@bWKQ)$OgZ{15M8Dds?)S7&vsjO3S^M>pf&I!j(8P|Or -z_3<{29>Ki5sr*E08%`qJ&9$r6F3j&k{GF0c5PK7mlm$PwXWv%k$%EApv=8?P)E@pk -z$g&J)it79Rt2gWt@3ay5#fwDu@HaW;eW4p4k=dJNs_w<9lbPC&ips_Fq*LO&Z}{!f -zw#WrxUOSNQ4SfHzYXg){cwU98j}}_7%Xht}FF%=V9Y^b_{VXwhf-OoZKX+ew{J*P2 -z4LISIyg_QWFTIziby7u(4++K{Q)C3-r?S3!IIx%l* -z%;Y)uY{R4SI3$^`h@Z~?x^%{)%?|f9caR*LIpZA?E0h$qo6P*V8+M^eB``zkuf&xDB?#s(m?9y+ -zRCce_NWb?UwKG}^^5;^vPZVEC@%pAB+mu3Hp9RhLykD8Si_2>${a~yvoGq1c?O1%W -zTqt*306&B42Y4<;LaHN2s0VjEwv06l&1{?>koN18^K*jOeoqjCFmUhZdaTz!qv^YW -z-cJ_V1HlWgM(@Ty15Caxki7c^%aq)RN?8v*ad494TxVQtmTJCegMB+Af-4>hTn2+% -zj#^Gn=iEN^-9@o2e00oDt14w@;Y}QQobQsEFW74m&^)iR`C{o8ps~%s#(Qpj#(7Wk -zYZ;K2sMLv5npFY*YAuufi@+@pZ<0h{Dh-LAGml{1=39MP?TGU^m$TaXbtx$}#|K0q -zM -zQjy4Oy}*~w?3trCh2o~+_7iW2Y_B2U_{nzs=N@uQWdf@BDiihHO1OTh -zl;NIgqm-oGxO=GnIhP~OC_9oUj}qtrBYk=E_fe+LbCFe#L!p`l6eBhAO -zcbIyLckd7da$S5R1tCotGR_>zzRddYv1&RhuYX<@R_3;Lq}MDhp7dqNhezM6*(ZVS -zBhLqY?V?VGkU==1zhA2G?G0Q$?3N5`t@2h8ukXcqQgw{ZWH?S-_*^`XVA8yTM|%s4 -z4WNz`qFlWO?imslt>Q{7^dt(Wl%gl&K4rI`xq5xBbkW~oRYRX6Mo-+b-bpG4dVO@a -z*vc>O^+Xq)@8s#rrk1BZt5-@56^`dVxxq*C40ADaTk7E%lOvoT8A3WLM`}-AgNUw* -zrlnVQ3Z?=G8>$en`dLtMo~zgu3RRDz>Ol-0i&3r60XyEeW)yDgSy0066SH#Q)|F^` -zvaU&>4()gQiL@~}J&L}IQA4U{M_8%&@t9ouVo_$v4se_3hk5(asGI1hU<>J2!`9EqUCDm_h4L+N*(+Vx3Dy5s@x5}*m-91=mww*`N&e>Rk0(Vd=ty2Q3 -z2%v1a0?B%-l%X8>z>VW!+ajH89;NEQ@&rgjU)*CEh4u;*-DhvT|0ju2FGR*jkOa=v -zH5rq~`=lhlYG<%IJl|z7D%kBsZ%f|^Wt~oY{Qiocq$<5l`weL-4B0*oL(42up7JVE -z+XBnUi6N&1Ss(qaCxYw-i)A-w2!J+FmSHX(NRBT?$l~JQ#u?ifVN$wv;1VU(>t`q3 -zO0P#Rs9Y`DFW&;-=I|3hcrH`U(@9Sl@jG -zj}vi@5DWp%*|NTkTa>V2#4(gO4@%KYs4Px8-W!ve#&m@#cVn;feXMM1SQk4>9k%x2 -zEvg?p^leY@A+r`s0TxvzFtynuY%)yxDAM9iR=ab785*@?Ik-x>UZT?=X95c+>=8tG -zXz4J#r5a8O1osGTW5un@2R2*KbG-sFA5v^HGtWH1{zTvX0x(~7Gq;#S06U^Yyij)C%6A9!b -zK++r;XL7$-%fYB -z4G^zJUb-T46`n45RWQ_@({LudD_n?<@lWjexv#8Q#&&fd5Ap4yIl#AKCsX!}GwheHxAYxSxwsxt^xEK|U2|OT0{skAJ0njiZop!n2)8L_ -z%zX8s7aWx5p6PQNg|6E5kQE-H6zrMDUmmL%?j1Qtrhz?f&HWsd?#b@y&Q*;%{g96< -zmAJhk>k>QIt}xVFC{I&G-N`C@?bHe#8%H^J%8P43=CH6~1fN+A#@E^8;Y+sWXDws)&32FV -zCCqzY;Wvv(*Ir^PD{1Vya)P6d!Ci{iqeouf`od^1pKN+>9H84QBTD@1x1esvIUO#a -z%b1KpN3+MBq7PsF(#bH-aj&gwapt^E>NpqvV^A5C3jEp?YYrd~+@9aQs-X -z3J??OY>F8F)2-q&1ygu>m>#|yw3ag6>-J|`VZBd<$((g9c8RMpZ75XH!>isb?L)8S -zR8vd51yB4G@csPy{oD}p=BxV{3Ep0KSlt!C;1|#jv@W{!9j6O0@uay{aXPp6P_&_ieIi*ql&#Y_erCEj%KG0BC`K~{P4gIa*>vN0G -z7eldI<+D_GJ+UJ$Kdq_XRN%-O~8waxX6T`#lr>vetRxuumVw -z+#^`sU`-S&W@>4J*XsQ_L%wt&nh)sR;_>_fNuXAu@hxvz9>N)n)Y<_emmBjNpLJrqFiRlQjB7u9>2IBj)qSvn=65fZXeW -zbCg$);ZNj%on -z--AN0n}A}@c`x2egrH{ki&>2Kekg6a2bBPlkLr8up)iXgdJpXJ#BJ;4>$o9o0q6bV -z70JiAbecrnG=ON@#%Mr8TAJ=BcT9Nl0MoBKp7=W+4%QOC5cc-IR=ahyYV#ab@Dyr% -zDm`e4@1~Y|n*4Ke`LPiB0!}1pb78Z1?rP(r`DZ&d`bf0OwWW?naOJ%YLAlW7>ru{8 -z2o#Ayh8~1~b6;(kG#+_WzAvZX(?4i=&Nm!~Y{^yEv3a$-`4+v8|5UoO>Ek{^?JP`| -zyFjX>^8kftUwif1FNgp=zo@LkC(ejHm4hl@adE82;r-4mA7Hb7uA0j$gr1V?gm;I$ -zB_}*@bA89$GZr^(=hVLC`gtwsoVejn|2ff(vTBUIO;V~iMJ~yuDshJ!xhHBvL1XmH -z9l^e#S{XimA#1RyKI_^Wjijc$m(FcBM9^xfo`|H9i9rkcMm8>9^CKdPXYIhXrzGLz -zXPx{M`3}GnIzEf;hDuq}3kT!dpcZE|I7}o -zNO~Uim#NpAmY&pInH2$;nLA*F{v-^j&`PYZuGdq4?%jN2%JT^FEq8|sdH7-4$Bw11 -z^E?J%Q4}mNUD{dagr(oYllv`sU}A*Ntl_h7QJ)isdXlN+>MZF{?4c*ve6O_{5I7um -z7?`*xgYiCkh-m9ZZ4J3gR~GRI=Gv<@Pp6-&a8+@13USl?%IAjIF?)h175qKwQH=|E -zPxhGFIlZY4?uTHLP984(&sa1OrjGh}TIogatKR44Vi#77#S6eAFRGg&Vj7*LStm(@7q&djul!)Dt5B4QPj%yM{&hg5=;mm+Zl0r~Y@PubO@{^_$7Ly|~P7%a;$t -zaJasrT`$du!r!lx!&ZgxP!`S;D& -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 -z+4!{-gU>yTHl|?r -zzu+CWzRHk#1pQ^qp{En6^(+T5X7gP8HmpPs=a~S6uM=6eu1T`*k#7Mnwq3kTOZ4^d -zSJ-OinIqrgH$jKoHCJx5z1U^5%WRXM?Yk6A-F4(TFr&8N(qUe4`_W353lb~xwXR9s -zpko?|`0&8^(Oi86n$Bb5I!Bn#pS|*&!I7Iuev!YkjK1|0@n@M~^oSGOT}Lrh@y{v0 -zk=10ng_q$bs=~B40Y3)33v%fiWIKJ6{Unc}rNnffJ&;xH=Bxpaan_gy*COck^|sWJ -zI3ZicfE?f$?bfa}an2!hnfpn7^OG7db|??W8t1j^B=opJ!#xcLVQ*mcSPHMp3Q;3_ -z@~E777-pedy%b!x`Kf`aEZ^bCnvb-{olH;BMeIDs8R2kGed5?HUTjZTXxMoOte`7FeKzrz3h> -zvG7`*wx^-pjuUFF79JIE#M6%mq;S9BUaw+-^IqpG(^44wlD=2Q+%y*L#o79n6k`Lv -zmqHBjKFQIK3EctJ$YQ@9Fg)fCX;|=x=LvZK2j;@*mu=mZe%yd8!29c7|4i5A@ob!` -zC=VadGLl!a#BQX)lY`gw -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 -z`E)vNGfm~_Z -zaq9GCwYWD##(|X&fvI=2U2fIT8{g(sNISlbi+g}>-3Ik<#*-G`hqd>-xZu4ApVQy$ -z<$286EPAdxoq8fNOL^}eJENcBboxev^G8Q}eOFC=o;+MeHjq8ZV^2y2O?<5#2mJc2 -zLcniHcuwq^CN3Y_Z%_G=i6Y2bHlJFCWA}XBxJ)6uE#1=h$f!Q7yv&l3!W##!Tj=HsnuBDU!V#bxiwwqe>v*rgXXG@~TYx(nCm_89L7ogr -zzDaffbOniC)`=35IBubaej_qJE7Q-@?slJhBOba(ef5{Jy0Vv?E8y%hUVJ*=+Z@9o -zR%OJ&<~;TNO -z-;dNp`c72`=e#Gca2`?;AwhqaoN5-V=LjVa#x70H77(G&{;rlg{_j2$0d8BTRJDjXrnt3coX*!N_BV+AOy^xJnerfGKadU3B -z7F>Wj!BexHK^*%1F+-ZUJxM|&RQ#&s4w+=J2jjEUlQ!uxSX(Q{Qj^G_S=TiEE -zn8WDGdO{<>>;(y`+hfWm9U-G>U$0i&IFX`By-xv3-|b9o>JnU#^La2!BR$O4Z$J~c -z`0o9h9lws=&!`I@ffgi=!8FxKx(*iC#JqSpL49jw)urIUqBR -zC-WZWlYZ}7KUV(U!D+sX6#}*mmp*q(OvpV?i&sxA2XkOc-j2(4hTE^KTZ~_m_npnJ -zKCr17xys`GkTq3fJvP35!^K#}p$#ZBGPMs5$*U!ptZHu^)x~RKaFp(Ncrspgoh!mV -zC6DtDRscbVpFC0h?Gs3ik>X1g8Ks|Zk&f_*dB1lv9BN>+q~t?y=fc28c)hyr^xv!Z`W|7oUV2$#M+*;8z!Mie!Hj$l -ze5b0V_tiC2Ew;1idHo#7muGm>>bp7KnVKuc2G06f0(_SCVaFc9wBW=s+e24%Xf&i6 -zCq(TP5-dC1%=f*;t`nlQeMk#*?>FIi!_#Pcau{#R+()5~%!$(;dBv={EJCeIzG><1 -z#*c1LUcb)J*$~3b=f3Q};eI_LsAHjhTYN{Z@zE(-I`yqx2mNpG9>y~7Q)4G+_A%N( -z&4p9^0)~!55mj*Zv3=i?y5|;I9&3_sAE@Mw<@aNX4CDcgI-jmLw>AZv{AoF>3g4DdR&(4AOpnlb--#&`!LGpRjo%XgRAr_11@Dr6FHxa>c$3XSH -zoX)`vGB_bu1ZMc8;pk{R<<#`~-v9NmmC>^Yiv^&!pBVV>O^J|l6Tuwu#wnw;Q?7U@jQrt72o0ze#L4r>Q1Ja`vkx#R -z=Kxq=?`wML{d=H&m?ZDJ@QvQvH;w|bMZ)nkR^^O((&QMNk=UuH5c7mZ3}1g4jZY!) -zXHQHVRKh7+A;*;b&Us=$?Aur!-`*wTuT7sQOuntj^pwJbSM*C3QlD>jaI9Cy60+gJ -zNs?X&St^sWI?y}*kO&?H<8!1e4HZc^_Uz03ZJaZS73sa{wkTgyR64SQckiW+j5LJz -z*GvdiBlJEp1Q$=qDi$wTcD*`0Ibuv}KsW$cmb -z{$St)WIPQNf;o@NrWBoescobia`ACJntrcO!@1q31BLao7@rXZR-=x3zs@8Y@V=TW -zPl*MR?^?q*qkm`3=)OR(+kUKGJgSy{BjN4ox48uD$gcT8M*lQR<#*ts)DacNd#*KU -z7b=`NV0lCOhS~wW2K=qD?vJTV;HF_f%D|p{-~|SI{o7tCE7MzilCnSF(|_OGtqRAhJb>}-b-ggV -z1$ao@=iKkIJn2&%^PM$wTKz2rN-Tyrc~0l$Td5m6hg5~I9a@%iX4u3WSe -zvw~s$fco33<2=1=54Dx1a7K@qU%wOm=ocjC1YeDE+I$5ntLQvtX?*(hclDdWsND>E -zPWGX|lUGAE+?9g;ar!DA-_#TyT!SG=H0gDOoPZ~(r@y`M_q@6%{4(}s&7QA+?djg5 -z6R{GnBtFWDEi;b_T6>RFeNJWRtDp&YrH*3U{IEgl~OqOw=o=(OKvf52P;^O+|H>`e%;P1b^G;F5fa6uxWkdTfOfcm-957 -zPMl_5IhcO@bavqS!Vfv7B#q?E{GO -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 -z@)r{UZ+?c1n`3! -z9H&@y-U6{UR$L<#=9mN62DV-e^K}5`jsy4^e431!J;d(-8WFwHxU+X1%|6Z>0j2j* -zTCG7}cbz;Z2O_UwvOTtpCxf+R2B#@Zj`&Lq3U;Kim|q&FrF_cN4+0atMCblu*F7jt -zpjn(twkNHmTzc2Qvd;B*0#e>k2fWzg+&DlSdTklbPTp9vBW$0&i8wszh+`M7H~U*2 -zx3%NH@12EZ`;u<$i?CPM2GI~6iWiZo5zvl16ULixXo+cZSwGwDp*IJ6>h{%ZVaU4M*$qx;u%y$)B1uY{90 -zF81BB#lsJJ`E1<7?smZHoUf16Mte`wrQ4O<`~d50w}RqQ?D@Pq_^k@98XHi6-aCiw -z>X~@i?<(EQFuS}j#*ktfmWz3QElx-pt>z*t-2sC)3zt=m)E4$a>ic&l_X0z3O=?83;_cwQvG -zfrqy=Qs=~%I`mX|(iL-gp7Wot-8uj`}$b5uPqX*a{4^YwsoIaKcRiz -z(gML;mZj-bzx6a@SroV(&a%0+2IrwgM6q=)5BOcC%YFs#5j{}2sF^!lgICT~_>MGy -zZ}0G`LM9*Qi^z$qj;04^b`EP5e4biX5Ig#9 -z<`_igqbVtfOOo6&2r)?1hiY~o5|iiXK{31WMu;O}35?$iARvFpvtZ+XD@|?V>;49P -z$t@MFb$9)GyEzL|E5|HdKQSgc`eyOn2do=%grbo%b40&l2J!EhH;k^mOsQ#m%*VcZ -zA_Hs<{W`^EFSya?Vu3t2fA*o{-<>e0p0F`QKrOxJg1z+8sNcz;*61>SMX7x>m`~n& -zkC)a3vOH(z7Dr3_*Fa=d55}GXpJ*7rd9X*$zhlnxYd{Cd7DER_wT^Q&qMtJx)^?$EaGZTnj6%2(rO -z;Umd}9*VPSBVXks~Zv2uM>NBaapg(cSfBxrwB%099=!V -zl-)g|yB~4z`;K1lX7gl{>q_3Pd-yY5pH02nX -z{shZ=d-R!O-Sm<&s5h-_B-g}%%+v=%Ps1$@Q&1zy3HQxn(q^@MOO`{Lk&{h2-q$cr(g_n4sh@jTzk6pw -z7YjNPSzS8U&pA7GDVNWFmX^kRJ`YkA5_tR}xZ_{{;oUw^$=0l)H3y%j(#*(->o@U@ -zZ0e)%f4V2+i{>lMX}p^+>{o}V_PU}RP3ifzdFXsLmybT?Ry1=37Ib~SVb=Gln};h3 -zed4$_v9Fje&)ExfOLBaVO>6|7TmfjPmtpn=uLun*eZn2SjgaCz9j^TZ=-Aozy2=z= -zfQ@TNe&fU&CT?+UwIYD`JL(L*M~g?TlIF$%96UKtd>ViO@5{(a#+5Wr*R_#73|ohp -z^OS+hY9l_Z*y)^2a%-N)QFm||V$>GFFqVzNLj5Z*5=`j(=Ka&_I}5b2mi52d%mYHM -zALR9r0owE?^p2Nca?uO%llo|4^kHahe*JPfSEV)%9eFCtVH`ASW9zfyM97B2l@E#E -zD?fGj9QMOVrNJAEw?`$_)(4x;a7qjAgPgNB+G9IU7QVPgV<}u;b8k4fT%LDV(M>!e -zEoS*?9Zz5;4GhPpxm@2Ztdy+q3DV+X>PDJ^0=eKj}gb -z$K>)Jj|DmF@i2xV=X}?Y7=YtOXW7>w8v*D^LCkoXkog!~r>+B+y!DiXVM8>$1XHvg -zWN{swhEYUhEF`nRj-G^4;rx}O?eqn~$d_;p5vPLk;HhyXFRw5sJxys&Yr+NvCaxK -zd}*?P)pa8-YsGwhp|!-=zp}(}$8(R4Jb}1dDi%*!^4WjIt;xevsTEb#p9frG-J|N1 -zN|&jwE6<^OO&u@CvHK#N-=6VfzLD-ht2d(-cv6J -zu9}yebAghN-h4~_>&c*(LCnc&XO6-f%bqLW*;*^-G{o3mJA~}FF4D?5DgJdnCmrK) -zeJa!nl*_~fP1*e`aG25i8NLbH`P#W#E`+MzcrULoLgJ*^Io5g(h>NAk0FIuaJ|?#C -zba|W`6LoH&+uBn1pX}?Wj)_*j_96CE-n^WPBRfoZsSq)+uQndbEsv;vSYearb4U+e -z!Xf_$vBJsvn#A^eb=<5M6#~`02IJ%cT^l0K2BLnvO)bpV -zchLH*)K7)@yFcelR-uDDrS&9_M$TivAyq^b^jT;Oc2fuQQ>xf?3jTtYUbu*b49OC#42BbZlhcMf;Z@ND_nCI_Wmw;U)5Y~#`3yQr9h9}1ZC-s -z{sZ+nWAid%O_t~dR6nD7!H=_!PdC&&8LKU~?|a{(#)r%3Jzc-a+i!43`~6%SwI0qL -zguGBg3SovLkn&xnYCUk`ND#o#n|`igm%4$$o2+DxNtIvz40zh*;iyW|KVD-0(N2gU!`^9olAgM&wDyp!S0*-RRF)) -zh+k*7SvjJA~f`%>~6d>u|pkuvEEFLEj!rz~qdNnvxNNWMS6kgt3KH-W%ax -zF=2Ild*-S!0E*}ice+1U#Q46YH@n!;Wb@BZ_^xulY)Utmx17%2yn++@7|VnUz(4y6p&qXF -zmtYSHyj-zQC1H%9*xVBNY-Sjl;VrpT;LCjWt011Jh-PiWHSZ@|2!ZG>c`&qr3c7Qe -zs_9XXxr4}JS7DiRrDi$`CT^4h^fgGg6npZqo)V>dMLkQ0;#>dzl`Mqkr&vRr_65yZ -zrWg@SMb*A9{up$xWop`hdfyQ!l(vgW%@6kM24>Iw`eUg+{;cy=vwF@VZbUa*x^-SJ -z1qn|f1SD2}po}t|FlYIFB+p(o8uxp9S?pYaI+BzYLdCmK*OyL{JtU+;f~r-UkegpE -z){fEReNsPY8 -z%1-asg#IoJMxoj&5O$eEufNxN0>0*EH>Whv)@Fr?LdYLA60o4C-n%&eN!5 -zXU{nyfosZ!dnp)jn3uFs7;x*P3wkLFoJF^}$hlwrr%4#dKgsLx9KB5n>O+2H-eh??>Zw8m -z49?IootH_niR}pIVr06WZsr(3KNIP5;6b-A!w^>*1qMm#N^>j`#*G(|@sT%A8^TL` -zZS<89W*=x<7QSlmB-MND3@>hwg(l47h?ifC=ic`-qzR=HPDLWtwc8I9-5&u~UL@1% -z+bCIQ=d($Irwi#mLA*WuR@-HG?l<90)-+uv}p_M4F*QzFQacYA%6y4$%F% -zL;t&LsG-{6z;`d+>T0yPtLplDE}mKXe9ftjUa9xa=0V4GLPb#RI&;vH=!NEk2xJkx -z+V;}nOq0@6{5K<(9x?y3DxzWI)QjbHG;|B;>}AhOI%#6s#3lKbBu{j#_FUhu!*Ckw -z>RLPw@r*h$SvRm1aO^GZj}2blIgjPlAkgF3Wyy0Fbs`s_Ca#;!TkRIMA&40lQE%Eg -z5N+d~3v(hKFr(3M>5~R1X!qND=E@y?+A`@8l%OG#9E>SwhkUF=0q||pp08;BLm0?v -zI)x{;r6sF`i}Nx1>eIj$%BmY#Wfalr%v@*2L#O(>4{S`^iExQH3)u!XO;ZyF%Isgu -zEQIDvd_~}xx6&2^`w}#$xxD;kQ&^`3BNwG;20K>hTbjYqr -zAmj8Hfx&o$^x3sjb}VuIp6`Tx1d$#TOcp${qdI-|p!4I3m80=c(!G$aA22&pV+d?L -zkrjDiWc!qe+9RazPPRKj93D|ts*%((CPSst19;=e>Eh2Rf`IncLTdtWm5XNS-wCF0 -zC>%_(t7-{nWo_)ShVuijeJ|HOe==jMl@QV={lER6&v{b#@OAMOxJqwefo3N?goxjG -z7A0U`J*-z8Frz`iuubKvjPibaVnL}3cK&SH+YmKu_6)Mpz`3?96+N4wleYIQ&)e -zvMgOuBnC6< -z+)Hl3e3c(0A%6{im8Ahgy?C-Q8?xJ81{Vhh$-R9ml)ugl!gr^pQD!su70O=3bjwiKadUjcrf@ki%O%Q4w4AU&fh -zq$7KX&Rb41{FHOb;id27KPZc(zg)HTHNPe93omcddg;l8(L+EO6yszp#=O=!K`$4z -z%G^Rg9sV|bQuvP3=cZmyG=Nx}6*(e5whAanp8HbRLo++qm1vF@LLm+Tj#xM$L;!W> -zzUj%tSC3nIuc~C{CQ!)ZGW&xM0lkTz8YJ;a_OacqP|!N6Uxn_&Z81A@#(kdbbm<8| -z#Crs0^lag2ladmzv;wNA_YwD2Oy^F*xp=_t$i|J+bh<|6_>&sv3F$Gh7dM&XGQ4c< -zO786iv5}i^uw>KE?+Et0a$XwQ_{#mNEBTyTSBD+ZU%0(`@Vw;<8_0rJt=n9CE3kK3 -zFzLHIf<5WiZ*oSZS{k55)l)n|cPvFCG-^;V{hu-H(vvt-7wEp}a9vpMdyAGN2&d&{ -z0vz0wJ&7xn5~zn~VYTqvL+`AmBj2I#B}G!NRanZtv4~mwH7H8FT#z8FDdXV>c&-d1 -z+R6*XFKtN=0$QHD19qqbFMpT&sW9BO`|vI_ELP89r+dy8*`ClE)F+VeMDVxA_udxA -zi#kO4Mw$I~;#3^HFE&djaviXz85U)($+?8rFWoB=mmXgRz}CbYHoR+c&fVgW3%t}L_lgRDEMfC+`@;m(bRimykm(;&v{ay -z)O8$^7yL85>PQ^87|>iqh4}dHVOO58!DCw_akrl;$NOR`L&qTOV~Ev`EtY%S%`Mn4B -zyO(LbNo>LR5O;z3o+qb#SLCfPwIXWp*azeH9-%(Lw>vxO2tobb6i$SWr=<@q6f79A -zzKN*47HbgU2CKP3=OyKTM={nV=^Eap`x(;kEy4U+!a{!z98jljl)P^$Z4!gya-1X{ -zCeC3iIPx9{4!?_@wDH6gs)ZLXh!~G~ -z!qwD+ZC^uS5nV_cydi{Vd7Id97IUenWNQ4$#uH!TYPg@{A1%rr1xOd4yPlc|L7#PynoSfDdf86paJpCN!3ZLs_LW4X|*X2SlGk&H*Um5<(X=BKWQdaWP7Z(|2 -z$;}}?csT0@L^iK#Xb23jQY%4Y1*R&9XL@k# -zfac4VTuW3TJNN-%Ab2VygL!AjIeTjIc$)RB506AWVQ})HO+mlGxKl}~C6EJ!hh7+= -zV1oe9wBtT3Sc0o-DBmTgGH+Qao@O`)?NWZqqsF1?p7XI}XGWy{`Q>PJ-QdXDW06nF -zJbG0Bn!WkU^Cg29EHTn$OJO8P0ob5uUuH-1yx{e#YmWTxe!60%U#y9_rs(msv{Xbd -z=3!-Ur@j^)({l8vm -zIKJQf3wiT=_(0v#oZf-TxuaRou~@P~k!f2YDu4UY-zn_VB46|E -zJfHt3%VW9=8AEd2=LkNz&iz?NsYIj2%2RMa_I0nos}%f}@Yne|Ky~mt)u=q#lX*c& -zO`Zz!Hw><^RJX_-patukRMk7jo~&}Pcpuq&;VcJ2uI$$uSttY#5h>3@jlLvz^Cq+8 -z*s7~C`2(~g6r5wpseLNY8&GgrH{;IuwY;Ydo-(O~EIyH-eDu^;D@ad-F0#^DL1!^3 -zl+_3Q%sN4pJg%uX2=kto*Q16YSwgnY3wOuRDJk!FPB=d7$5mU(`deP<4^}xN`n^}3 -z`KrWY@UW0H3TOC61h(^M{9#HZNYso|b%=r>#JVOQ5#2RdBe`d#a4gv2Zp#DgECJ-K -zg=-}IIlLjE($~{;7_%E>Gj9}jo_Zio(=l^-?-x9vD*1XBMTx_=_Tf<>r -z{`)o_JNc9WpUZ9!*N1ve{EB10`=!p4F7qk&oxAnHypf=>xL%$1ourRf8(FD -zcPl@e;6l5rrW*I~=9@Wwh_0V5&mb<>7j=8h`AQ~nO;pnMSiFzf@BX|!qCXYFFCz5q -zdO1V#T0E5Ez$h%;-OhC4<5n)`X;76r^qJ+6)yYLIN||$-#cU-(7SrvZ3mst0&^QTG -zqUernQE?t&o_R}4?BWX{dXQIr8`K&hZk!tlk4o<&w67VWgCBKKt8BbS-*0&F=*0oZ -zMeAWt6UrzP5*QjLz)mm8FO2 -z2-I+s>v!$dYrYa7E2agr-qVXO-YBuK83*i;*^#MAZ(g>1(_9jobZ2fiUpUa0x-VaL -z59z*_C1ut*VuGweb4PpKJ?#4NE{u-bK~Dn>9HlY-+$7>)@d0qrim7PQs`%~~Wy@!> -zH+E{Me?_w29ad4tKj-mqpU4FM>UwmK9&`NqKi53TAD?^jsY~;nrodG>*?Zor|Fk2W -z&hy<%p^tS=i*;N$VQcs78H?J!6niPC7jMBoJ?B;N=p1_xh)++bH+);Dv24YtviCj^ -z=1I(m-RUl(QT$rFVWL7g8$-gz=cU~j_l?6If3MpM*dA%rej7WXt~~Pcs(v;~1td}? -zWj0du2Iv6Ii;l-!u2Y|v7KM&k9z8Sg!i_c5;c2nG)4ZLbE!+0=zs}C2+?eQnnir$k -z?bK2pLG8@r@RkqF(IEM{dSUCrD(86DA)V^K<`{21HR-wjUIwYZ2iM9v48|dY9zeqy -z4CG)tdT2@6*CG~uvlVvtKZIRLk|a3}`w}VcM=s+3pEM@VKE_xbX4<-~Dl@`e1ObTx -z%s>Y0Rl39L1@DueeN?0(Pk)@O15Qa4J~&SZdSs-L(4-U{0?XY`!c$3duTsW$B3s`^ -z7A3-*i4=GYv1FK@$X&I&FmiHgV^yL`&*l?~YF@9{m_t7ohK#tkKkNJ^#}bTqv;qQ8 -zZoU$t)H*Z(1IeiT05vNp?@S=dQK?JG%rH+s#jbrhjV7XpuGt0?yjC)K<$U+zzM-tb -zI&re(3#dL^$PzBX#oc-|7^4mFNeAmn`FwKrNv{!f+yS~^>|ciQh0LenT2HgNStGc( -zQ3LAT!`Cj$>&HV=@d~Z*FZenmBR`X3Z~1iJo^S*RzhRF}s{Mr}tW%yjJ&DQonN|n% -z1#T9#-HN{v8jo`(#_LF~dXuu!P(A?k=rMas<{Hz5sz-F>>ac8>PuIyicxIo-WDOCO -z@5E=140k-`>*lh>_H@~xnhe#e&|{B@R&wp0qzybjvFztQ|27}Kw~jS>A~xVR8z?ef -z=IJ2iK9x9qlFuEvr{T7d?W)&d(Q&xt@|mFUCar(B$OCk!(L%Y4SFUNDXf&1iG%404 -z+y3WWqs@DPqJi;jUtf{cYxcx_+{(JO`DT -zKqlT@Z1EmO$~bB>VPAELt7=ysk8C$$dV1^Xf-%;FaK#BdrX}cRs5o-UlE5 -zxRiR|JLtXZc$tCt!k&S%J&;%Km&W*TH6bc^>MI#~>KLZA_uC+j*QnWrAr5zm4T+zz -z^2_qsZ?qVmI4&jZ+wFu!mk@h*lTa}j)#HA5p`vNoCKSjVc%bzu5O0V=OdCm()#faZ -zQf?zbAwDPRA;-n2$g#Cn!xZ6CChj+07W5Ro&h^0F!hPI_uehw*sdPgHypC2qO2?jd-L$#i^`?YipI(|f -z)t-jJeO*ofJwCFnq8qZqRtopK)Z!txF8JYDf!8E}9ZKL99p%H6?)5tH%JNnMo^nl@ -z?Qjsz -zcXd^`^Xc_{9A!q4YoTg_&Ro!K!m;o2QapyVUgFAh&aE@P6bW`EY3Xn&yFDUamlK<< -zK-XHT92qs{aUAb^PTsP^PeJ5~egdIH1lnFPbm+~vqXw`t^d#R&#~$@NlH_c+D7!W#U*PExWw}cwtZB#d&l(w8*N^)y?0#8S-{>qR-A9cm%e~u=4bT_p -zUloTfK7XF~AhIEzHbklQx)$CjICRb^B0RVpmtrxOap5Os(jOiFdvTgV&;tA)=eaeq!1TpvucjRSoB@~;Lpk;&zI09U_=;)n#8jB-l0|A -z&46ziy=D#+k93_A8>t5jECP-~*lk-$!?b;>NZ9B)kPJCh>>=H=nQ%e>B49Hp?nW13 -zF5d6-$67n;exfhw*A#~QpWIj7*e4qIbaMC@z2?oMcb6vRR;AdriDs1WJO!7@VX2pk -zEp8v;Z`*XAco99X#Uj3HdZLNzt??LbHs+my)iWkwG0b3JviLu}cgAII#iTgqsx}ni -zkxN9Qw`=gS%FpP?u7?YQZ33)RO`5^r&Reua{sc77j9iVt*@P=(SX -z7HjoI+uc#ZHey8X<8|(V{me|`h~}qh^U2(digno`7??{HK1H4tFjoOsob+Mh>F?C+ -zX&9>@Dl4fGdzZ-jL~c>0 -z+ovoD^DGnK;Kw`F6<6AMw+oPBo9w8UtS2|^aDYSf@>3brcvYoHV|a{bpysCG9T4Ou -zOEx^*7vE~PV>}_C)(${=KQCh`NQBo-u9GFi)a7XspZ)LXWFqQhU$2{!p`vOg=ns&s -z{UVhu3j);k-NfNbUQu=8KHNmB=vG|=B}r`|tQ%b(kk^TN>~ku86ff4X#gu~rsdC(e -zPQ51g=(HQ%_~v7rO6#;di5Qwh>xcI~Y1szn`sur0C5uEa!+`WWGU -z$zJl-Qk?FR^n$TrqSsJJge{{VG;AK%jhlV+#?^e?)OCtpuUV6PNRo8TS8JpAiI%tG -zv8WaKgQlDAqb)1K9O-l`VIO!GFBmuxrU~n$ehp;z2QLR`A-l$lP97qT}+^weih8wRG$0B<{jxwSg-XxZwi0 -zx6iL6Yx$iNo7HZn)OoQpyq*9rKb@7r*-r0yy4_F&Jf4^5s%MAH%B2%c3Wiog9FL;A -z9XZbN?RkDq4tVjdXc^CU7xZM4d~PUHgag`U$^V=)3jm??HS$z%^e(rpOecdHE#&YVK)LbL;DE_v6G-S&dd|J>0M0p}eUQ)zvY1p=f_mfOGbH2sH?_uyUC!gRBX~E^&^c9G^z~PKZ~>1auAZJe -z`ZfOshjBZjLi}S_Oo>wI-`UQLF~{5E`-=k9FM)BNFG*FoM2zf}Z?7eF5ys_P8!`h0289Ml8Iqb9R_eop(# -z?`+xNwa!PGg%5G-2=!wkRrKWqv{$|YaEF`abL5L=u=wV2@YbaR0`Z`4{POwIq$Z-n -zCwbPcL0)F7EbrZkLw?5db4t!5vCUg!|8z+_R(sI%b6XSSuOj`5pUgqE14oUFs*df3 -zraYOlPv+x5QqZOetpJm?2LTG7zbWztTA^Jt?15P>@?|ImE45z6fCEF^=qoi;!(Uv% -zvON%N=M+jMxoD)a&YM6C@A=??SIizu**U8c>S{OB -zgy@sljJ=N2SFZUha-v=cI)7tTg?3B{JW_&Ys~QtRAyM~yi5L9Z{mI=YdJgyvgA0%e -zwRnyz@eKz;6e-2ed>=yDhYM=Ox1;BgGd8G@guLVVU3t89*0xur@9PCe3E+zePIUx~ -zmh^i^_1cc?LO8(_I>i^!{hJJbdXbLeBWne#7l|@LohE0p=~0l^uIlcMFSgPS)bb&` -z?%xedXur#O!U$N$ufh1eKF(p^2ewDu(Iw65ke8@HM?lE9!8s5O{csM=0Ql^snm*!Z -zWy=|FNxph1?s(jK>-Euz4LC=p_&bl}151Pcy34r*aw%!l)YfRH+AH|+KN0E6Jy(F` -z8^x3|KNtFS(W0JX6G|C(U!_ka7by65ZnvFP=gx{ja^wh^6;>MtO>}o3dIDVfOi2tp -z_#95Zg8bdC*IO6o9;rm|m^RkCceS3%FQ%=Cd$VRT?a^kIv%-8c{e54aac%n^6w;G&=!-Aia?)EYu4)j`;?;s<_v*e<3lFX* -z6iiGDCO7iSNA#vS+hGkR+VBz)Dk_JUxwb1L%?aKDb*k -zHTEU@@a)p#&NZ@<(X&&A6irRCq7a`aGR>474+KV9Jo+eUEsAT)7ek$Mw1iMNh)tgW -zaA@KY#F__Lf$NWS^2Yi;0fv(atSx-1%@>7|^3Jh~M;*jhL(UPOW4ws%uO>O4DB-Ko -z3e)=;!#o1vH)kJGccscn5k}XE>jc(jMt061a5OoJ99{XY_En9qwzv(5mp|P{jz}SP -z6%HOV%h=D^_E9_W$1zGxh#DS_YA+c+de86{a56pB4|3(k8GS;%nvGvv-y{JzU7u{7d -z<9h+~DS0g9_mdV7Qbm?tQ&N3ke6jBKH*fe_GgB=a<)(S&Tj+YLu8}VMs^1y&YgKw^djI4A55uNEZJ5q2eIZ0^H6^@XQ@eXY#r -z@jdIlpmt7oz4m^)+x4U$Q9bgoQ}mUNeYR8WYYt>Jm%gaKNk1oVAY(bahErl=ynQpl -zjA1iKlz$uFeh($aIhu+W#KS+o{$dAt`1-VSj40jHDyIyZk5*uL!Ns_H -ziZJ$!&GwOnF+6G78AM-o7kNKuy%P?n%5vl_mP2B6qzij>v15yr?=s$RWYa5GcH_D~ -zwV;nW-J6%3YZgvi4#Zi%&MPGb20TKgHd=*wm!7))Qv@=RH`Q8G=Rr8!_nzMCVr9uF -zWe~MPs`I2{EjizU8`p?cA4tGAPM30Kj-KhTFzDj)ELL;2J~RohGI1rX;#LY~Uu{5) -zJ3wvu=T)Jmb%#05xzm+hZBaUP2)~vzPfgS&G*UwrjXLD*G`|(Ku!eorU2|8PAS5_n -z6B|H{)1pTu^~Mox`Xc?_^J&oagQ^JhRWF{!KK@9B1oJV8c4>M~FJ6Cng4i|x93N{rg5iYCr9IJ)eB68F-sPxh -zE3#?kh>SrUDms%VivqvN%}QO0M^Mft`V}a=az=-49p*1+@5zX`6ZVS#5{*M1xIwh= -zs+6C69~2456NO?#TOD-Jimgap@TpnC5jZi0x?}eQwP1@};fumz8v$>X!(DGHtBVLM -zR7S-QpUy@DdyVb6c_d)yq4w*xHG1mOQ#9UaJdd9T#oimu{=jql99W4xzG7xJGfa<1 -z*Bna4bT%69UO@7=pWTNYKi4(*3mK+c#mt~>;Rsx@bPg5F3f%szN`&Lwdmrzuxg(Y) -zi)MQA1dsx+TL{t~*%aj7TF;k{Yrn!B6(FmJN$t)-~;I3WkPV5_1%&q>(>=em#zpVvdX -zmL7+LZtN;(zMrW;_m`YpaK-bx3TAl`3WsjTx!<9ka_7^Z(R@F*ojKN^SLuBWh2yi9 -zl3~2wVY$-w7EMW&EG|!-t5oj=#j11Q32<(+oX@oX)XzP(-x;}ZH;-nE8ll>BcGj0Q -zbY8ulRoPcY4x5ozg;lP+CsBI9WENZU%9rLgUQb?q+&c-e -zZG_M97@!5q*;GV$tfPx*Wc;>9!@aBdtrXrsyMX&7`db!sJ%r&_s50z2*d2v2#pa=j -z^TnTkMttloos~#n^try3kRa<_z4={N{U+00*=`?catpP`i|W<*6R|~DoDKnXQ!*b1 -zfG0iKI&V%|eE~qS_Y3^yYPhE3H?^F*`6(q5$0ta-KII5slLWa*?}r7Ej@7N&$I(vn9Jcc?83M$GsV;*`i!Z;`w6t)?y}T(-*D8WK;Gu&s -za*$OXY|mxHvV9`3_soQ>?adxA&J%)9INq&Gk4?pm%)ENx;>A`hMz39gM>QWaWfO}u -z$~p<;l~L#)|+l&ds1lWYS$Bj`25%io(J<0(n9dIgmV>SrI^ -zzt@kqHf}%|?nOn@*_{;Er|h?aneGzFixMQ`CIJPa5 -z9J6V(@sX7B%Y!tbb5{A9VOEV`N_yTj#=6}#Q)pIw6W)ruH2~B*H?Ny@Cr<_|JhG^P -zfiYe{v}Qxjoq!V5SpUK|IJmE~BKfM4oKroY=X+S6GGA^djrJ#+5?|j30J#vU-kL_u -z>w|3#?n6C~@%hqQq-3~6T748XO!&N}!@e8mak4RQ1n6<`ZP~%)Ku7+V5aMxk$B8}< -zJsjX`T%!TZ%<|cHlgv@7^OZ3hbX*rRQMqgDEl){$-iM*DksqNveox%T@OO^xZm8MS -zSG*-?;^zzmpMj|_T2fh%w}O;3)}Hjfz9CTCjd7A7-jigJb6D=R=-MO<(C?OUcV(kmt2W5uxP^C7IJZyTR{T{z&J7`0ZT~EE`nY*9t!ZWt$kZRTDZXu5_1-ji= -z^NY&&_-VYRbWZx~C!(zr@&)vN^VW}>!+WQQ48UsFF5FDXu^TP>ICk-0ZXkcVUR|kX -z*jY@x4A!aLNrtIygw)v}l1L+Mfgw{99QkdeqG=z!I&yo7sW9TQc^-M_Eqj}H7@vdy -z&jr9L&n7dv=7+1Yu|Y*cD4ZXp#p1qS1DSJQ52Lzf*S*szUF9>+bOXd|=udZ}R?-#D -z^YCrg6qC<=e+*&<^R*Fs9gq32;$*;mN`8C9(T~;EY2Wu-fpsB{Ry)?Q$+PI`{^grse4SC32aCYJ -z6IQMVlW;sWfP|MbJ_jV~>8k}H=_KE&%81DsJ69vJ7YOCV7!mtHzklPY8?WWbB>*`< -z#=mlh)oU@ZMQMJWX^&n&Utw}PNl2ow4u?~}t1UD|SxDdMlHwC*`((vU{nm{M3)d?w -zjYGg}0C4A|TO=0oSy4#OIZO81tAncF00109sXVIlefDd}uOC4by1l+9oW#NCP+nuca~I@Hz)0B0ly0xt?7=eGbar6ei%N6Ay4O-S4Xc -z0C3KEoJlYvn7~mb^I>(UxXf_-QTc|MVW9W!P0Ry5V+aIf*0le+WPM9j`v-{@Zc%*8HYv0 -zb4B4E5}F%*rnGkWI33HZROUYDo3%71-F)g{)YQTE93S`eT*Ae|Jvd;x$De9@>-q}e -zxz=Yp!E(>ly`+M9Hv{YDF^1g1KG|k>fvUQ1k_JO&q`j4TJT}DS#zj`N%xetiHEuRU -z?k~Te>Fo9y8mJLPw2kAc5YvG-IzNB}<%QUz^56>OiGubloi7a^s37+$(P_T157f9+ -z&L_aaB(@A5M9O!&rS0~_Q@~zJw1%1V7)k)lif_h<;k!;hkBMMlQwmT-MshsTgk7g; -z4os<{r{!%v>wh^jARx$c6-F-(i^N`9)|E`8S48I)sA9gaNZ%G;^VkPpfyGZNL)o2utBCPyP1x -zN6kgzb1SG3&d~F1e!u1(3%f_59J-Ku?<16>DE_(H)ps4@G`DiQ4DQjP0%gfo0F`|d -zybatRQCiT7FHqgqiIC>j?aZb{WG#4jT%?eST-tVS2PR$S!caq6G2#829Gkwk@}_?o -z7jzzFe6%?l`k`ruBR5>N&QZ=MK#m^fcwBkbH>w}|ZbIojq6CC|LiBZJAYUACtqT>& -zmD3Z=3C=+5HEh}dX+1mcdcI40kxo=|szk@VOXQ)UG94}7_qR9B()1bc*+&j3;nJ=6 -zzUSQwqE!9uTt*scx}`^=q&l8YS;xs*DPOaj?tKoJp#4fG*WX#c!zx_&>5f<`L+mqf -zo?J9f?-paj5p_s-;3LFqWTy@LW|kdE@+bOwdHlm>*TALAwTA>WIkzE4f(SR9-%y(3wzuP0poNPRwHxk(Qtp5)%9 -z>MrU_tdT-`H)-Qay96x8ZF@SzpC-)cd?fca+GCQ(d6M8NQf`sqm!YEA^4|I9v&T;` -z5~GY?X3)D7C~yV3?xDv@@w%%i#S902&YTBr=ezpz1hQdcX%JqpP@QWagZhQHEOp2$ -zO@=INa7J?2$Uv2ra}GbwBZAq9~Rt;c27!d -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 -zzH6jbxYH=hj8?JonCV -z;TV{4T^Gr_aD)}%=@y~4l0lpc_*I6^#uVk8;`6l}k)^{ET#1hvCbPZbrLP#JN=43P -zDeTDcBh(;^Dw)%$&_(qwoZnVixQ&Chd@G%o)-O8vBWYm886)S4ZYQKpEXWW}0Bmgr~acerl-w(9+D;`@#{bP)$u1ga+)i`MjzeR$TyW#J0@%@>* -z_m(^2!AD(`+ZGofo!+yKf{1ee+(ly!zDpwzvH9XP24wdwO9WBYZ`!w{mOsXgb9SIw -zC&*yv+A;Gd3ifWkvd;$$+=gZ@29HmXSi?cIg{)VJOLc_y$YMm(x%O4Vu;{!32hRm* -zM$%JD+mnIOGLNs<)h;Edu9Ip!)lW&C^|-Ab#(Gk0zaa%l9NM#DP;r;hY!5xYafx!i -znSL8^raY*w@Eu0|LcHHe%3!ST*=p@_m2zI8a=B!8Bw!=5K+1F1yy|bpN3Di -zt+ch}1l%*+ooq+^G|2+MF;%yf=(!uwHUPIy+4 -z&XF&FOcFKRPmDiK$hP|pQQMRFppG&l7pd{wS0&j>j&^#GWUtx2b<3!B<}jtmr}7Nn -zw${%h;6{CZ{^FzCX^Crc6 -zxAbM(hUE(s1V-`NTCznclU<0$!1J`esG1@ -z{skyKRSukx_YTM0N43<|*n45u4-UN&n&7@)qr_+F7Z%GYXG`n!v5a$2EO1@aVXQGxexRQ^1HC?hV&iPTwxG`5aE%2RXO4euRiN?U -z?{o-05Wq$pK26&>msWjUuwmN??=maZBRCgucM(Vg#mMXP9%(k)BE4=o_L?HfTdB3xl)yme4J@HFCfpS+5G1XXc3?omcJ*V1(jbvKHdpDXw6rgpvGQl=eb0T -zOWb)$Sn~)4%zwY-QQ8XA3C7!=Mvs<8VG~Z?!s_Ku#M|ye(gi){!&P(;OD>_nyLYo* -zID3~ryDzF#-IMkJ+7b`=;drl%2=3QEcZ5E3-fMeaZJ)roN>LMXS+(BIv2SAhQlYll -zTe!IpaR~9k7DgCTGM?P^jYC^Fps=PE=K>!t_Z=}E>&H<0Ei=82ul&x_*@Vp=R}lE>)|0ta@9myAOmTn-(2`tMOZhUQDH&8ZV_ -zU1snl42i4qm$u2%29`Y8_k7mGdh}d+!i?^@2%~4yf?8CH-RKyd$DRO(xlEqiHi;-6 -zX25yUP~|3eb964OjU0Az -zH-B9IW>R1CD?snv-eQ%q_{h3BD1A+sfXaIBAP%k`#~ZwKK3Kl@u&x>8-|;gjLn9~= -z9=r!@nXf9vPG-{iivuESc=Nvr7`shf{{p$J?8Cfhx -zrgA3hoGiLaU&NC>)@4uIz-H=-p8rmcmAsNX?@magKO~R7>OOP63_k1o?lR#XBzF-? -zxxEy;LKr|;B~NcGC7(v?dr3FG>Bu6&RYT7w)%={Cp(*8)dI$9*g>kzu6FW{aEbRa( -zOYNh22N}jZGCr*{7a`uhfJ-3c80RS3jhKq|bKg%9)B9OK8q2^VYWF+macoH;jnI`4ft?;>1e(yu2qv~RyrUd~sRqaOi9u;R;uAGp5JRr+>-LOzM -zw3b>IgZ$xwXnm(ITx##lYTPnoyk}IYMmiDDHU+8X-ZQVjQElWpu#mbx-u-=RkW1nG -zSRYOoaLp5b=bKYVMpfg-7~Y0>l}mhXgR8Y2A!qxJ}WUG92Jo9_iMtuMeH0msd^HKY{gFxvTMVQj+G -zcPJKiWcC7vhVl$FtlL+DTUA{>6SC=h$DfE_BzCjb?{(R^*Gzc+s?*dK&^ -z&42sE6MZ@4_u-;ffw!Mw2b|Wk$RYRP_dfOgnG)SBxa&w&O5J$K5)P&LQ6@y2JxrPy -z_8Fzl(WmC(Ub#S`pyR_PDLTdtqmJ|x_N8d$O&dFkXnGhfZ`)B~kj^P?i$EG5V^I4X -zx;*d7JvEp@%3c9oxL2&Od1WXsg(yM+9p@qym~Fa`ta`WeCMa@9uaCpaw<^_JQJhkIlCiCOuqaqO+Y_aJIEIWE~a>mhc!saLA`iFM;u -z?mQh2xdjTl(Jpgcu5a7za2Fwi34$#HPo%cJ>XO3z>g0c&IFD(a#1P`8spECd=E3Sd -zp9g!(-Orf_c%y`$9uQup*{jDy^AZ7F_vS|rV`|}^wDgHOzOd@T!jh}dEmA`p$s*QM -zedqBWhO`^xr;i-x4&~rgP!}aU@AWM|B>Q65{TjxG_t$R$^Q5^5qB31+-a^!4u_tO> -z%G8~UZsetfk$EUq@s_I>0H|ViFC7t#IBI+N=0h32%&s-a9~zt@!6SeS?C)J@pr4K* -zD9-cNbi0!paz=#dIRyU1^p!{A7qiS^&5X1|e1L3~v9|XTolb&0oR3u}@Mke3#gDqb -z9aB<5j7=RAVKfd-52w{HZlg(`R7JmtPjyOhGG#o8VXwH2m=$D%VNfms-o$})&pHYl -zi%-8krBtJGiXguxy|8J(GikmdU%+LtxBHy>oVkdQD4(P|*{{M~DmhMxDx)CBGIhv% -z4um*gkkenj`LT%E#MAkB@a9{ND#@4IdAQb1k{I3vQ^no9bh^6jWZ0G7Qwm2OdROF^ -zp$cz_9a`)PsA{{OM-W{H*Rtx!!6=oZzc;cEt-nvZv@@#ALYb6&w -zKauZuA~ar+q4&=k3lmV3MN^L7&#M$w1)Evj#x4MLt$uySluwW@DYr+9V=r#c++_Sr -zqJiwYyUfFghaN4WiTF;5kOb|I^}(Ja2An{LB(*106wV&@<^Bsnr0!P~tNx39nu%6l -zjQNud{Mjd>fa3HuTF#U&zrjy_S-{`tRLzK -zEBe_VfNSKk_V+os&m+5Wjwo3%F76&MMibEzoUa2{kLS1LG?4vjZx`Uhs@3zb@zRNK -zk+*meb3vS0ZfKHO0-}l24K_vs^e27^?PD;CO#J -z4(Re~%naMRm8gU0+bA>oUes13_AxP`J2X1@)D=iR0qPTn<;zHjp6+{n7@7nuOD9S< -zB-+~ff&!DDv?ADt8TvRTz`T8zl*E~y -zmQQnKyuTlXo1+->nIo+~NvVp6X^&AtuU>rj8M=t-x7&*NVe5l-`@%7`;Lak~BkWs; -z>}!{Cwq`uH^)t)#ao55&u2a~VR$C)Zgcn7+Y<(X5Sf!ZycNcP3)=;i3C?uW0xDq)A -z2wQSYh@W&2;nT(|OIAG`A>e5NhlOZq71!p3+L`FXQv*C>te+E9Kknc82#9VDAU?wG -z&V4oKh$`?ycEoC6ggyyG-@R6uK;Nt98znU=7DkHw{DPG-O*?hFm8 -zi%SpdK;FB^Z5P{NKT&-9Lg1^f+4oopK8@S!?=2lDH9Hu$FI(O`MnK09Or_f0{2rMH -zA*%ka!0y=BIDdb2uH4@l(uoE=7;jl1&Rj8m1>hkOh+DN>{@fKF3$xF%F%YnHC1|7! -zuy31mxsYj~0he9K^aa@Fu7nd|hm5YEJoN91z9eVQoThVM(Z7Bl!HB1jO260v|Jo|$ -z`hCzJTeyz@cPbX#^Qy5NJVz3!Agnrs?7fBcSVbE?2l?@Czj%(B0zGD;;eO%fFhNYD -zoQL!kYE@dL@qQ{?2|??xk4gX*qG%v39QzzN;+%PG_o1*sJPANje1OA*3?8cRUrV!Z -zdA|kBk?o&}Z1OqqMVJuHHRhXVL$BT&Rqy^jMKSaA;RLs$;-N43fXv=II8`Bw4^dr- -z2i=rU3l)>Ul1}>=ka;XT?ymsh;x`*9j>kDMHIt|~Bj3zuK4BQSkBzbpm#f6Rdz440ujXtODpMlRP{=D0H{0y>38YIj3(}9R~8qsMw3{avh-*$m*MJS70NjmoR9W+sKv(3Q*r&X&slZwC$+IY8aS!9e6t=yGug80C -zqiIoaHCLkXo-1v*KHQm)5WeNNc#A)ifOjFQ{ml?_8pdf}ds;gq)5RW8?Tr382ygLG -zw<8x?O7V;AlaMc|+#EeDpAbCvD^J2tz`q5u{xvH!epY7ASAghaSoaEkEo8U%ag;;% -zv68enV5O(?y<``U_O{Wc8}B#bs7b0Gf4W85f1=;d6OP&=@0Im7R~BB-lQ_2>5}u;c -zM`u9Rz3(03d8Ewgy)C{2Uk8rdbu~P~9C(4%k=JLxKvfDlwKv#zgaU%=f#-pzeJ|ZK -z{Gz+fcW)IwS}%AH$Q@w3X*)OGPYZ3A5|RCXR}1o~L6`gv59mzG=^JAeihKN4XMV&L -zuRz>v(%OBBl%j4XCRzg!`&mXqlc>6IdYQiys(k+=t{V4gwY3GNxTlUWrlxEFTt_|4 -zW?09wrXqwb1nAs3YyGvTnu?HLiw-ZIq>&3so%Y~HIfEztt@(U<=0W&rv)M;D-!nZk -zHInB6rBlCWG*vDaIk2QK39yoB5I#@Gko~?_Re$H3@oDvj*4e2w%(yD{IG)!U%!Lsu -zIL4oq<~Jlr=QCC)Y60vi$i*eSpo^uk9NM*mbBU#I?&A*~`q`u3@9=z2 -zA)POWWcA~muusOqqHArqOrIJ>7KcIu -zoGP!n+z)?Jy5vgo6Ez#+p}jSFcpkI8RGE<_5g{jLrIMQpJrqv^2+z~y!a4WrWo8qZ%^tOrSRP;@kTl1)%Ob@fAvWjbRVs+mFt763xUg9m*3(>^LMk5l2sn} -zfL`HPPd>e$Wn|q{`ZCKd$9TPs@Br{@wQ{IP#;x<%Fjd1E@cjlq6Oa2wY-#IOt!mN& -zy?-f(%)M$b!p4YZoZUii9lykId&kYy*L%I@kOij)b_}XuenWLJI$9zPi{aT<{pVx -z>J>(xQsF*;4*1BE7s+JrW#@j+a(9|}q}A*T*phQ9y1}n$KhGDeh^NxqJ_SrAXe*f&s-I)k4D0zH(wXeYjm_!z^tJvBzI -z_uF=t_R>nA%gsP|(u2oUb>}k`d<^y;peq5(t{W(;-A1zPD#&52ezMu_1U|-j> -zUG@4xDV_j*)L`4B0R6LbGGaU5316PJoS>p{m|2=+^HettbIiwDedZ21pCd9%bcz_6 -zZn5_b^II-@US)bWaTyOW`=*|Y;knz9)`(9v0BS7mCvVi?eop3W;GZjE#+WW&-Mc#g -zln*8jBo}A`%tcyk;c?-XM|bUXAbp2$_oSO}vW#cZY`(&1boq3NGv%I3?aYVH^~nhi -z6@41vBQhaHG20qkqdU$;0b2H%hp>M!JWT3y9*}pTare1X!!xXKK5JSyxa$youHADm -zQZunKB5wdXZ$7fLrEHR)k*M+9!K&r)<)%w07DrRWS#aJHl00u0lXa$0T@|l8s7HXs -zt}C_OkWt7y#imx1MZk1E$EWlgd$GqO=PrXsLzD9(dQaf!StmnFptC%(=IQGwRkT$NPP1GmfXuLAb-AG>@OXo!`+($L>wx>k@q8 -z#+vvUFkyoatbb)y+~3L8S7&NnG`@qDwR?pOS$oduCH86q7(zR+D&w%QBo*E&4BNw? -zaOl8%=^e0$UmicH^<)qz=)tGdC~^bhU-$$0D@FBcbe*u)db=q!N$31!@#a#2 -z0dvd*UkKaB-2VFw(COkF&~t0#=wsVqAVzEB?KlwVu~;O*b5Mh$@&WzfzNwuenLTmt -zl8}y6z$-?d2^r{6Y^oe9B*}9e!W0J1IZv?yqwhWj$XTCnYxi9%0~*goyfmzq5F87e2y*glv&pLJPgLtY}Q8={i5VmO<&M@~t_nJ(~>X7>YZZ;N1e@?|G`3W#p6#y$v~PmI1A(fLSH -zlnjzQR*l&wvKY(5aJ8h)@pz<#^r_Gwn<3q|0x<4!c^(13oRbg{txqNT;qlqMcN&l8 -z+L!wzz?fcu3nHG0Zg(HEaKS?~9GpBOP&aNBpF?~c6&_pnZ1m_5cB6q4^hCcR1b9Bm -zR#1P#X;5+45TUJ0Izq~r(Cyu6ImLBwkN$cs0(v2jjM>F=PadRJ6nVe7vwW~*9pIMt -zx$Z^WpDms9;C-yW_cnZkvFcBRMaq5b7&!GQC1PjUlX1H5qT}E9MdkOxp&xf}Fb1%= -zKJk>Z<;q)yu^Be7II>2ALL$d)mCT|1>vfQehKCTgD#ggqLK`pNC*q0TmMBim#aDwL -zxxKB2-R>!~G0nEyU;`i)gmewc)KMx#e8h0-blsNRNH1YHs<_~6ybjiz)NZM=CVcj3 -ze4wI|hBQx;zE*M1Vy7dH(S`3;RYFq^h4$EK*;(HtNhFL2U=X -z4Tk}U){aLh^Rb&7qF_VF^->4 -z4RU^MrIN1z)$G@&CyNB<0EIW8(0km$oe1atzwhsl#jh-PUhTs)F=n+Un&*NW(I@S{ -z&enm8lkh5)e#0t)_cQbEp3ikEI1W*t8_mHpuVyO@?VJ#`r`YETA9@l)ITO2YNT5m) -z?-x5|QuPJV9m$3v)q`%m-#2SDIDKVCrZVv%aVWl*!-o=f>vQ^_j~4Zv!$*sbabw&_ -zyMJcc77})XxAoY;)-@X*gT^Nr~r4-aYF$3;hE`LhttfbW}r&si*+uQ`}Ic~nLo2pQ$J-0->3XgSBh4u{vdj-!!! -z__IO!LQ+`=I}C%{^W0YwzMf3Si2yvq#6{^Uu3vhMwg8j1+ktUne+2?;TVD;1&xerL -z&%01A#9YSP0~j|UL(Bm$WkqD3rg~3TjuCx2;w=kHN>-OW7DOpmuiS#bFy?dTiNx#X -z!5}A*U3eYvYxZ -zJv&sKl=WG`Q2~9q-kI`Mj>RNo?bZD**~-U-a>8y_>xQl{DxP_?SltE -z=Rq6G7s%siNKeYUJ?&Hp;A7vcOWo}C729K~t94Gyy%!A(L-1buazSHeL+C2wFBJTp -zo;{D8h1=&2Xla`DA<%Umey^qaNddsK*Jx@Q=UgN8yg8INp9H*LGw65dM)0(Jj+!jZ -zcjT^|wK>OjOuyXndH>l#H+vHBJC*gP4B>jbO@fde3ZO71DJ!XauPz9=9&fKlpZ|Lz -z+^gHRJn!`%OsF9#bYGw;^3T)P2q5p|0UZM>>!njkcxs=fIad$FThVgC)ts&53uwC+ -zl%8BKd%!^8woqA>_nfyjEa6B!&Y_h3>MI;-T9!_0Dreg~j8T+OQtDnxul@^)9B}{q -z;RG#q4WMkADWAr_bw0tVj)i=r=2E5JN6X+vXhpiOirko&}a>;fK&*5-oUoFbkh+S~Ss<}24q@MP^L -z^LWJa!JZIB;c5J4yi}?E71PB1vKT|Jk>{-@uq;oDlaJVsT*=LS8hf##?a(({GR-(5 -zNKbj;*PefI18QZj&pEGZ$e_>cisF0lbj4U7rrN~O+gB~?YuhTPeXGQMXP4|tO6w;- -zG|Bj!>S{r;M`Cdc4A&AHAK^TyU&8EV^-0)n){A_K{H-k`szOD?r!Fa=e4-hWOz(lC -zrn{V;$vwqoDME9uYqcZuiM3*3GQU^fznz%x`Zi&}tQVvNy?bf*x -zb)p_#Ue8BZ&uP09dE|jah%N+Ig*DKliMTE6#WI5zm$NQ4+FYB~eya0PvCoZzzHC4i -zbeGLK1a}Mez`HA-v7_tfVw|7f1b^pke_fZEp(0K*@O|p7N9HopA;GquwmS-R-{0Vl -zAU$wSi-V!qP4LWNZ%FoXBWWUguXb13>+R|FD{D*ju+gFJs~{W(3_HhHPiAZ~oc1BB -zI%ztsN-QHW5COcHVA_ -zrP*V#Z_%qwkjIwhI`}=4Dxf73Fq!oQxpX{>MQ~no7oKjNnVPl<3 -zYk9BdT*i7r`Vu{gBA?B86PA`wemTr+zAIuFy`loCj5;u8-^5fXRDDSR)C$<_2y*lD -zQ{}Fcl22^nfzalz2pqw+Mr -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 -zs7GzFzagCX%LA@H|fL -zTdtf47kL5HuOZ?1J>P`Kyrjq -z7sC=fR~`swz$3=+9)g=)LJ<2-S_BWI@>!Hfg%e$I+VSx{S(NcRMRz*{hes>#VR(Y2 -z!SouvSE30+WWU_8?00TBpHp(+;6WuW0K)!^Nx(?>%2-480iggQG&pX{6>s^a8zHCW -zL=@qxDIbYEYvm`KDZ!}x*4oFc!*%)CSc79tU1!jwXfOIDvReMlW{?EGWw -zN|J87S>%@J1w%x$|0PxETo1pB_j_Q6pMAR{1ep?K9xUx6Mnsal(J{(%23)M`Ua5a7 -zq>l7w!ACdm@oqLQKXOXlfR*(nXq@qQXq<{W^2(*fd*;y#IWMhqNhY~N@$xH>m7hO5`aVXA( -zs8t?Z)sGs4G5V`oeI>2VoajF2=2Gq4!o!n~b?FY-CV|`&r!>B)$j_Ec-b$T_(R4jo -z4;?;eu~-pF0-t6US-|7YU{H1DC9uc-UC13x&!{{4O$;6>zmCW+h4al|$lL09!gL=S -zw`!e4k@Jm=9E%5$>>S+;h=~419V9;CoDc@&jJk8|%PoCwpL&D>n-r6%t$mLj?DG*q -zeXKY0>)153zErookZ=G@0s55Zja -zJH?Ny)RC`!`4Jo9$HMQ!)C6&j5DZ`JJW`4=i^iX~9S?1Hn2=U{p$XIPM|tY_icu@! -z2&!A3a`Am@&#KX;m)-M|k&s<0NpXHF%x+NM7ZD5#3w~8HR`4*t-OG<-xhh_nCQsg` -zw_Q-0?so(&zIoe#9zK+*TmEN8{PPwi{qR89sWgs{*P1hc@5wYKY59CEVB*%mPc{bk -z#z}^Ya*||u&8#2~^+6V&o >h|Ulx7t70od`(W@nx*v>UN%a5$d6HY)cb1dpi_v5e${9%A${%d -z-(d5V2gy1WKHPL}L|(Xsb@upYq~DK@l|;fL-4N^Y&`O%{2mSPB*Nq9og2{yHfB>uS -zNbuk+DF#9O0 -zyXU3*d5ohJK&#gfr61y+q>D1NK4UjRD-UlU9dayA6lI8dbxo=5Tkq5b}4n4B*R|*tlBa|zU2K7 -z$w}+5&m!FXw6o|gJ~q*F>E*dHTfH9eF#W4j8q%%A5&Q^ -zt>L?T1De!?97fH@vwHrw~%v&DKf0>*?|hxB-Ra6yVGXs!e~ -zw2IW2+oLdrFDC9?{C;PQ#_lk_%d -zLh7I$dLLo$+4&FvKS030M@8`{z8I-<4jVS;H+0^Ta1IAym-scl$@qSBN#(1vDqY=H>)PBm-@VpGRrhd?T96k&Gb!wM2;IHKuhmkt=))*~E+Fm&}k0+5X -z*{urfF+!2JV+v9VF9|+g76M`ATd$6rA}F$H%S^z5ZyGGF`9okd>FasV!v~X|9W1Ty -zzf&2cobyla+}Z@^AvIBf2XY#==6G>l$44{`FoF48G|o%&XiJqW%;8%wf?r2NU9F)D -z^34UE?oWw1Zf$Q|sm-X~)$Z+4zM!ux>hwz#h}Zd!-%lJtUqVlB<~rnLiE|4d@JnIN -z5P?h5FGU1)M|u0Js+`aYySNBw?KIdGV~SPSnMh8NjfnhFQ7tUaZU>%IQ58$k)0?Ks8d)5Tn6`+@V -z)|O(ZKBr1OjGr{@WyxwEma?;ApNYbuxDP5ZIdh|&8hP>TuDayG)|@ie2G|KC3?;P( -zF6d=E^xf(}V9k2cL(s_NFhGrwW~{($%(EAGtM%lN9WQ$@&S(M6pab~juG#P_{@yFS -zvykfL?+rR`fK~0V$K##@3p&mk659Q>An&Mvo734%pL6N<0w*)asU-hcX^$pbqh~SC -zU=_R^Um|Gf=BV}A)8%hKnfUX>jC1}vOZ30p%pY!!L#0%gA6t=L@`}&A8L39SN@asB*x$rD1pp?&?~ldTZxp&%Xc4i=HoVp_nu!8c)`}VcV}< -z9(foG5*p=w_2|YI*rt8KUybdA>0acC@qa -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 -zEn@NkuX9hbmk{5KmoxOCH -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 -zb6?|E*jXdca2jYO@73yykDzl0ci= -zUHocU+C?)?H>b$Ed#LB@cE-Zm(NL|u>at#@H<(2ODoP$Ey|7t$zKoQpw5O*h^Rf6Z -z>!%1ZCZh13cwglV)z!@P$AhkA9b$l&?@xRe`m2cOC6+|W~XGd5`P>Y#umlO -zQ;o*1z^f)hP;4|3y5I3!`N8R?evBL+^!wS3lf5^*(h1^l<$(fQor5j1U-LhpL9h!B -zP_Y1@1C&;0Hf&VCuOkwOz@HUITd6!;i0vfs*w}ql`vQ+I)aL`{Ykb{91fBNr)rNDS -zfpG4l>gVOoF}t@QKM59BYIMF1w&1Ec7}5@Km>iZHPSNAgda$*uVZn~(w))gwLY$;? -z9%?&~Hf}kJ;O&LQN^&DiTm`RTupTi+*s_TT);SfajUoewb*YN!T9?pevA3#3zVFZ=cD@v$q9+ -zvc;)-Ugh$d5D)UHAc$Blo1GumRxul=hjM15 -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 -z!|O;^B8CSA%_V?!xaE6Qjp~xn -ze6v*U?7c2uc=`9Pqk)b0u$C8lSkIu{dFGrfwB>G{?DHGRa;=WU -zcaLnU4pFj25J-}rr#nqdg(9P}#q4Q}$~tBZ?q5dO+mzG7id-c5xIKivtCt^ZE#B_E -z|2+9w42HyKQ;MM2XK)YB(X_|iUN)}KfgxF@db#8h6zt$0vg@>#XRR1ONHP3bxO}mBC7X_d&2h1 -zchkP-?Lq00l4K1fkU`nM7MM?Os<_E??r@p*vGZlmmisV25faaq+xaf@R3X_v#EPZM!2Et`{VWAZgzAAjO7N)Rx0{ixpC0|>bdg^xrHjmL0 -zyCgyAb$6^9`&#lh^S!9;#GSJ=keft5(GUCz!9= -zmyls0n+m!)Jr;FT(;Ey=rWoJ_xA1%)GS*8Dp6_b(mV7Vx!hF7=)u-MwOt|0R^NhX& -z7Tjt*hZQLiH9+j%gUh{!e?g55`BQ2Bp7wvrlb;!WJOAL!H -zn!2=ipHjHXzG+WvK-I}!8wi>pk3J#NgO5T8J$kxR9?i=cYGm{A)O}nrRHsjH3b(?X -z;QMvy+;4`3x_s55?*}e@^Sol8OJ6_BidQEWn2WD5>wRp__en2EhOz*&G8DsqCkuHX -z5^L+hxaE6}BNECUB||t6!7e`H-rDF63S -z3Tmcp$&)rdxh->Q>*jU2SohJVKhu681{_%U>b-fO`fb;5`umAd`KH|M*(drkpbfP4 -zysC-HegBC)dm`+r4m)8o_1^S3(L(N*@6!(6@0;oq=F$~>L+_cVh=sch;NW%yJOJeU -z`o4NEB`}zO$TZ#Rh<&8b09+%RyzDv6gZgBW_c^9dt)P!KXS@aYjwp0bVwwPD7m0CJ -z_QmJNua=hOQj45E_JyfEr3}XBW`HbI2cxrmp53Y_POPvvtmG^^B -zaBlUpbI)g}8J8L+W?yR#MuFpeJnLEOQmHzUEi`wiVF$`AshrB;JU@Bmfz;cYts!yf -z)TgXON^vZ+5b?zA_rM_GAP`jF5;&~ySIz7wJ^_Lp`TlI@&1cFFUTWDx*`znQ?~SW( -z(Ne$w#8z|!YkcpS+gHjtScAv$=E@bL+vnbUmewaF&iMKd9bSPjnI35o(mms>d;4K4ch)s`|8u5@cEfNzx}Ll)SrX1N5>3GO -z{8;blDx^dEMI}#eX}yQ4_gP6`>Su#zigU*i=6kb$AKeXG -zz3XKhD5$`DZcUr;*R5h-%AV=?EBEKq!EG`07|gakTo3Vtb0g8}uvtDY`)JmVg^!j( -zo?CuCeO+}1d;v9apXcaT@Q{9T+wsE*fViM$m;8of4ANj8lPCF)hFNTMhe31VHw)@B -zJdRpbnf!(4f7tMK1gx&uH;HHDL|ia*-OH}b{pvdo-n&c>r${*NzMU0PL5wY28aSdt -zZcX{5ed0ae%_ShlkcT~d#I_-Ym7#WhfXyL$>12m=-3!F9llcS-HYDdMw~8CvBuL^q -z*$cEbIP)bq#n&zJP5isYt7P2Jf1~2E)aC6#`kd$f_v6y&A+lMoY)8iE6TuIx-gCx(B$G&J^(^%T&PoqW)a -zARsp=V=nzf&Y!12O8SH|TBwJL1Ioi*)*Lu3uA)y|^<$p7*V8^c@?ye){bnbB<0{@W -zz$qM}nlq^^X~|1^RzVde4v@LwOtzNQiKCZHQXR`?M4kD0R3yCaU*dleDnZK8>}=^V -zC)vH&Q(p|XDsiMH;T&?q)8o)M&n$162O1L8_Zf~z(?8FJ6uj@y>fr{KI|tD(!SO+5 -z8P(%dosEp#681`FEr}GrgT@@gxGd>IX~({UvitQNn<4sMR<2DtGNSE6d!6IaKLUK$ -zisn7SF|-Re2La=xg$xqn`#c)o0PIIc9)OYF)qvN|H*@Ep&VJJ~tXjQpQNkQi*wk)O -zc5`Jo4R?W1-WP~oq6(fPN5XJc`9#ryfO2*`^LD_t#oqhuwnCG^P6d&jHSpVyGFre( -z=Gof~OQ6helG%MKYcE;MUXa6Z!=a09Q6}gu87^N-*W1AbRMx!YaMr_Z9V$@Fb4FgR -zx(uu)y-%l%MY~Ui2JlH1wzuJIVa4Exjyo$5C1`g-_OSD94w9=+gf&(GJvSuW&lfM; -zX)sd}DmwIZfr8$R>OD85SuHVS$&ob3K(aE_?q8xal$`Hnfn1+~KKQ`yVS$gFJOPs( -zSVMT~0s4chrytr&TY^h9B<0Y#aYx!on>)Z -z=Y8&5u|ixzQ+Unz;yR_(xnGx#yf4)v-ppFxaL}x-amec%_yohuH+3`;^D&a7a}kL~ -zU&-^$+-&Je*Qnt9#%ywK@_4M9)l@FUh~G*Fzy5FKxzeBqTC)kS-QZU*M0Q0WdYbA{ -zR6>Pg6IUuuRIQzauZ0*&!)26D+XNjuPTq8SK9Mx@DD)j1po88~qwc2Wa7o&CT`t}o1M`SLV+^;#Q;g-LBy-%y8c^Vzzg#fxIrUK97 -zqwf%Yi-IMmj-N9YIyav4fPvYOMqCYoX*a~cst~wyPVG0-oV4#e=(X=_5li9|leSV~ -z+%bMApQikq8 -z9v_E=2Y2zTi>yh!EnI`bYnAmrOz$)3XP2$zeYO0;m -z49j0UyHlqc=&QTx2Q_n>=pGft4aNJpELoj64Y=R^s3-9JdZavC54)XL@@R6!^Gb!=4kJ -zDa@w^%lwWAJ~WFZ!iYzUdaMT|p3@=nW6PQ~g2E@|PIYpTDqSM+#_ONi%2%!U%C)HB -zvT=J7#<6c~XZU~?eJQa}@97hOK^Q!+n?e0&@A;m*2M%o(3nXFZEiKX$8Q%d?CHc)u -zTcVZ3z}^3d41-J{eCGN`O%k0P0{4u5Fvoy%8O7`92G- -zQAz81p6AxZ6qNc#T-Qk4#4o3LC+$k^H{R2m)aZ-T-pHHR2;Sb^9e)Pz#_caM<=)3{ -z{EWi!`i6@qe}f#(W}rxe;DHe6Z@}YI!>24*7B}q_O%`HMV0Jf4L}t|!{yu&bu{e8xslvO)4Fow(uFyvfxfG=*3N*ucxN}_B(>Ado(uD| -zp@q#-9+6wLejsmMA78D<{khvFCIIlHrIWHgCI97@gCu-;T_ARzRxe3PNQuCNc@p#9 -zO?W@Vm-G_;<)1wJ$A-<{|3C-4_;vT6`QpAW#W4i@g`fWO -ztVqr}+BQJq1(dhwJooD+oi=AU!Qwev)PZidAJ!ZT1O%Jk5F7uvqr -zu}w@te1%)NEnuvZi2*>K_!V-SUK-J_t!b6>onjaG49r -zv*7U-nCP0cNHL;c2*szlA8b6>o^!t#H0C@xgO~cA@eQusMgxTlb8Ff15_L_%6`jNh -z5FdMBGvC|JFMk>YYRK4P36nj=4?%yoiZ>r@gvvRfIS2RX;SsxtqQ%@OYjwQt3T#cL -zpHl4grz8yh3Dj{bh?uMWHTZ3PQ6ErYl?%7JJzWQvcv4Sl*v@0$0nAuf+UX4&zj)M$bhx#xWuYXFe%DZ6Rcjtc3GgF*gU-z)jzDY1 -zPNDmxhw$8G!AQNARE`AV_q~K(Gk5MLA9fD;8x*)MS^DA*30e&7E -zg|fJ(eYc~lrry4f=?@-QysSU(P+GTc*`vs>RYQz7^nU%UHdFwc`Is7ys*a%kP21Bw -zpF2Bs>`

XRymFBV3vSc1UQMqf`wiwHYEE3meE@vFHV?FJGX)bEQlxje7t$S*|`c -zB8wsjo#vvu_wuzOja%UP4bgY2eH8&`<=8)iJ-T`8`kurV0{j9?JYdcHVR;;9&%UB+ -zmpNU8jwn3|`T#_tH_t-^_r6|zDm!tNDBli*dPR4Gh4H%<7QH-ovv%m4`$_JSaeO;V -zG6wDBHNC)XdT@4e&8pHw&ps~Z?^R;kO@G+@2+h)*YrdKFr%bNWjmFt91pdZK%Ff)U -z<7%H8$R|P>FE^gk9v9?Zpt(pyX~l{JF)@J`fv%( -z_;X+o97h_4R~E3RA8eJ85AR#vYv*ZXwchfHI8~!Yb6V(qeQCTwtiB0h$hjA{2&peB -zO&i=V;6{+ECDkZh(%Hh|t;Ec8Md{JZeMUzoS)>--oGx5yTQZjiyO6S-N;ds$hPph< -zepJ8XUpik>&5@(m?^E>WplYn1rx#c2bBxy3M^EeCX+hhG@|nPI)Wn>xLsFL}zp$xT -z<;rXJz9r^8-(;oxu-x!_Xh)L8Qf?J|WA&=Ak)LS3SNo3g1lL2ako}Z>b9D`4EA{V683`MtsZ^ILGSgUF1Oo -z$1i*BfUrM&`07}%Yr-Hz4+*dY -zOfQp)&}hZ%oM#T=UXoze2Q6`z+6B97MM5=Fya(TZyW1$Jo^J!3<4ktI3i#fH-yr() -z1PSIu!hrBSo&eQPZQX37iYMAqxKc(0MvF;~LebbAd7f$?(LDuokWFOayH|hJrR9Cd -zM8>OrVkz*|q2uGwdAKSwEgYEmejyU+=B}=u=n-SbZ(y|Eu*nO4PS#mzlq`RcPs;qB -zkM^k(_Lg&oZ4fORnW=!!H(Dw~qU53B(YG}u9rT}PNju0ME?>lV_tlPiszv1z@ssJw -zdM=!!-&9%vIgc`|p%-VdW8SXVRW=j5%kC_J&fgTT_^wv4aZTAA1q-X&DB`?|8?R)Z -zcg#>e@m;@kepQaGI26VqY{B^rYiG{;^&2*P;}BJ!HW!oWZ)B#X?nRyI+ioMg!>&## -zyLT?XE%#;91YfeyCt1p5L$uiyp9o?s75&CH;+w+#_Bre>$no6^TexBm#PZtHA;2?ERqBNqtZDcGdM+ -znPFT%M0@)YS%fedA8#9(K18&1Sm!)z=E-WL1Mk}aML@d0#q%Oi7x@-NFoOc=tNH5* -z>i!=8v{wj!m~`gV9!V!13wfH@zJwBQsTtT4=$c%SLipsGggo7L-_EM+Io}{wLhiib -zhGp1{{y=yid>y!~`8Amzs5#e+&edMKCealzz~h6~Fm>f#`+C|0b%pTDPJU98i?1L! -z5Np_;xaiMb&B=q%uadjd5tF{V5MO`b*@OG_B}@C|JCj>x`1b!i!Q(5S1z>~?i{SUL -z@6?z4BwI|dkF{2g+wK@yrF)*4$uYbWsRU-PioC5Iq>N?D53}7B+^x=MJ=*4++wq;k -z$X(Mr`CE&k{??+jB`(R}I(m+doUPun#wxth_X{)cE6>=S({#|EMkq2PxXxVjWs@~s -z{kqPQ^*e7q9W>uTEC9lD@8$QNzYa3p*j~aulk(r -zVUEl2_Ual%v2NIRXPC#BM8*oDBz>L>&zf(diSndiqVn5@d(fh`-JVAHu9Lgb -z6<~_^yWRu1-*zKr`^K;12=aZ(`}ryirze8WX9;jvVG1ySc+n0b)FsOV52WrfAKmvz -zlh+C#p5mPO?jVmg7dk&+4$UDmIk7>T4~F-CN36rc{fxCH43bw$$0IHdaZwLGUI;Fe -z0wq{&2SE}8DbHRob-v%Q0Ce@ZkN(%TJIa#!k&Q5f&8;Z&LlsvEaP0wjbc45@a}-Um -zCjE*(aXr)gjAEmgGG%E)Ov7QinyPJRW7nS}#bsJk;IY3HM?EqppE9a|O|rRyH&>N1 -z-D6IiQn%+pf)0dhC25#I9oyKbEk3{qz50EJLWSsjPwlanD5Bb -zEuk$%bP`yRZ*I@p7$MxAny~Dx6jw1b|5VefpDfzg+W7XWXhC)oOW)( -zyC^o{Vs%-pJ|7Y$`E`K{g~v%-UR0cuuY^}K6-_y#-zMX8U&4@2TkDj6EzOYAq -zp8j+)F|np^fROYPFSOs;*>}C=k}-&&Q9#Ae6*^q?P2B#1UN};94{$9gVYRTRtmG~$ -z_IWU!&CpBsc=+5y0+?(H6W#J0r?!szIkr5&@^IQS_O#KBQIkzI5`+Az<-o8%YbEq#ZZue5fZ4Z^f?(yT%=*OMh}Ogjn8EezXTO%N -z)1yv>`{WHj!xi$B(T=0p{jLz9yQ}sNSsd8L%?XcZ-F$BLUOX}!5B=%zdf&)7xrzID -zl}_m64t+v~?swpv+0qMRUk8B(i+sVrr@4i!NQ`o95pi(85hTEA)C_N_DOSO~v$vId -zP0T%m0w_rB!knE7Ex6+z&1e05+3s{@Ft%~L4oBunBNjyheM!aOlN -zr#7&ykLN;i;!h|&KaZFYIt4tbx+34>eP8XI95zG^@=3I(c?L71Ln!=H4Ds5i@YrpmX7Sfs7(WD^=l3MaVS%Gz87nlNZ#qnh8@n4XLB1 -zp|n-t$U}o~_VtqH8SNg)#^VO{#aL2aI)En|&LLwl{xX78u3b#1g&W4c9REISqVEP` -z?kP!mP9=%?80Pd6tYw{cl-l52f0m_GbBU{) -zm_+0UX*bXN$`5d2)+hR4aI?8qnu=(XqW3_2Nu>CsBLgU+XFm&H`y^d~SJSj(@(3{? -zJ-RHHbMs_z=|up9?;^?3A&L|sF2BCtFk-% -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 -z-Ei~RBsM7_ -zng1BOlI%!w*m@<*0GGsc|0DS^)ZV3Ed0X9*GK1tFg1`ryHqyPfgEZ@b&q*ySf(E*e -zC$~x?HJf)7{2Lca#>=3>fkzPvDT{chJD=6ThWMKGIx$(5k=giC&+|ud5J(5bKilg9 -zShdeQ25K&soPXZ$t9N^^i-N3D17v_7V_X%wpBRO9e;+7!R=St_-1mcZ -zX;7YbUNcO7-h3Fcnp+YPZq%gd;1gVZ@M|}d*j>bGz_oj#00Ekqc$J2UhiT4^=a=d( -zh%@tCg98%v)!eDbL*s<_vgXmqXfB#bW$$dQ=-1hG11I^ -zKx8CMGl^r=2^PQuGWj;Z_bz*0Y6 -zxsX971eBLb7>d8B-}A-tDLpGC^1kxTy{A-<7Wg;8d77;vy_%NJ-g}Vdxu3>T9BL@r -z_n9`U`#C}W^82?`3dYLzyUYTP$2ha|Xn-ceD>sBVcNVa0^Us;{ -zygG0B-or%RYwO&C?5e7`HjkA+eS4+e7suq}YtJ=Zbmnt|^*ZMgJ|W7pl9U^#@&Wl1C-!55uL3^IOy2^o@M$w&-4h4;MxMd(!P^k)>Xk4&WgSl^w%lh~ -z#OC2AxHSuHFXTw&Ltl%%t95wq=9R$b&inVJl>fYxa-Rv1Jj-D5J$A|S?d*|41g89Sel&4eZ -z`skNq!SPPDH8Ll8&_NgU;e*PWI+%)2NIlCq(gLJAC%VG(6dIA?gEVdgI%6^H)Z=&p -zIMnMZfq8Y`+ehOlRuWiL{WC$&%HZhpNpa0Mt)D8H$47SR#t!#=+Sz(dj~&uh^_@QN -zGs8gv@2?exfWFRHnvt?w#}nL*WN(qK4f4v9T*p%2O0Vl0R;v>B2`c+57!oS<`}}U% -zSLmn|`8?u2OrP`g=9#SeGS}8_H%w6815(aU1J*gW_A3Ov3ld&4DwUUAIqhnr)ItepQj=)WqS|q2{F0YgyZM*_fGif^#Jb~ -zd-6ZYAARP~2|6bmDg6d)@|RUT)_CjvCgJdNRb}d09_#(;Z66JIorkf7)$@%uuUVsR -z3+sC@lM)w+{bY8Xy-e4hS&ej`n1obN@CQPB{e9La7Rd6HdWYak}i|knm>Kl7m@-pYH05mRar129W>huhohI$l$(>>pmr48NF>~R39@v1iE -zlTOeXbS5RF0cKM;^v0P$=rNg=R5%=?6 -z7WB;4`SQ5MWWEXjYwL~O%aB+PAUULbguX;3?sInE5i|}cEll%R7b^9H`brDrY@0Gb -zFS4A|9Yga^z#IL^tq&;uo}O|DET)DbyoZ9 -zCp+AzCftsJO_yfj#)S02Kw5%ndh)?@)|qno8qCVWDt49(&5CMq^ngY9;yCGGYCNJc -z_dEuKvHlJgFZuEN%<&O0MG89atFUK&Gf|FxgKum*;-Sn}n1CmR3HA1O8;s9_i~>`G -zDKQODA-TY5nidqx^NhaRcct}g_>t3`u+w$}ls5lak6J}fa>&ev_^G}VYBu>c0Y3jJ -z;OA)WIp@yt=}|HZ>|#0ajYbO*YJ$Fpkfa6zH6jD$;GKuab?-uxPtcWw!RND*IGCAY -zF{AI3I&mS~?1r(!-jKNdHD5(1*KULQ*C+Yl8)k{lm(9V2suFvG&jA8?%4S5el#0*Z -zF6@39@{4TevqVsr0nAVZdVRXj{Zd%;vH!_;IL69j;6$?Q(K1C%m!21XDYK-%OCF&f+SdJ&E89-{_<+9GUN)XDi-5@3&zy -z-nQZs?Rk5Uu<^v%E9%V8^v`j1hszh>0moY|FoYoc!Xj9D05wS|CKr0Spney}EU+y0`JV8gr#qi`zqt|VMMO0&i%cq(TyTRA8wzhG5gpiRUDBueq -z>+DxQ8SeAd2? -z-#f8!`C5|MQ*UO%SOhfqq~@2dPvRctR_h7t%5nbj6NvF#Gp7}Y-K-jyQd1MO_0H+iB1 -z_IH0&{Jf}2raqdG=ia6pPjinoe6wl{AQUt^zS2{9oBg73>ZRMGy79FO7DvFWf&(-s -z=?GQ9UC{4+aE^|u=A%O&koMdY$VTJ=<&1pssO)p+X*1Nkj_Y5|2m14W5|qsszQ{GA -zl&>VY0ae74S;4y%mTwA)m-d_+H~V>>o|+3^rLTWB*dMn>PO_WJ^H1}*59FVd?8whO -zS{a^Ly|i)Tir0G@(3jnwXqH=Qx3keZyO -zXmP$|#7jHm3v9Vb@l@`yZ+O+*89y7gRHL)sTf(&H3(0R$H{!A{wmm=AD^p_%da~u_ -z9=ts7V9>?YIbZP7V-jwt7~Rr>3UEB8L|BrK+s9jEi{8V7x;gxgqfsax{R(R9%$e{4 -zy9u?C@x(;oGt#ByFqiZ=?=)K<5IUujsE#g|G?5u?(sd6 -z&QsnI?+HV~9tJVoe3A$QtQ>^FpLYlf{@xRC+V`fe8LusVqc2+UDXBU*dG#FDokY4g -z?hVTWx&a}SD9f_sxBH0Ca9tXGhzl5-QI~wTu}FwqovO%vomg2bFCg=C(uDrpAeozl -zV&HwC-C2wkXtL-b{u5fy&nqhsK^T5Kdc`#)1#Cf|@xOL+Tt@op$+Qifrx_7&nRe4Rd`!KnGxPtCm#**DK2dFeSc -z=Q2P*yYSBePJXF(z>@D?m6RhWpP@YU{OW90d*bcK_2H4_N4Atr2}!g5kq9Sft`INGF{Z_vGESf%Q6Xjk`tq6Sl`JLV%8x -zCZ7_Bd-1ClewJ7+@dLxgFVO)GU;A1!uJU<^ded0y7DZ{vvYl2V(7wYeiDk1w3Wsj3j504QTuBz -zj$;t3Fb9RvC;KjvX4Q?aqS%*XW+%>x?{z{VRN+I}xs6*AoBNeV(1itilJQileb+Fl -z%Z>;n)pO{b-oSL1gi4Q?RYHcnn6!wimx>j?vj3WzM^}Q -zA^D)=VC}L>o+W72$KGr22TJVl_L7`cii+nS$)9uExxgFu=rVSJ`bn&O2${r5Zli{A -z1l=IZiIbX_ook8yO -ztJQ>i=4{Eqb~H4}yw&CKmhgETZ9x=%yA0Hd1*-SBd&JtHH)4D(DrBL$hsi;l8n-d> -zj87ot9R#1J?Z?5G9|quB?Z^;m-Q*;u1A70$eivef;$YrG)X$Ih-AUK=vf~Ps<{daUO8&~JH0QjSg>3>M-TJ8-5Z*E*1lmj?y0vqvYzWS0zVy1 -zL|%E4Yj|qn^nr57b71|+ZY{oQdR#;-Ra%%LZdVQE=8c0gDJQz@9g2%~KBx9r>DF3k -zSAM-9P|vjS!otlX&1XTcoz~udCU^x-kJ~=Rgl|CnH)J)bSDt#2DGJerg2tn#(-_`X -z9DzDwE5*s=e!(=v>kLop^iP6X@YZ#_4*hoNOvc)5TC%)S3nn$9G2ic~10{lPTwmaoW-Btw9MZ -zXZI2WCMk&fXrMtHp)Q$E=%p$g^xK!s3)b`&Ux#}ih6;N;Xl4R3w5OLF -z^GSFqJP`Lii#T$mc;fOm8eF=B8_yi3n1*LO1?LIl%z*5k#oVV0wR^4_kn$ISXW&DF -z6cW%g1i^Pz%6yJv)sre5Z_`RbW>W`H+1{^;m5h!aP4q{Fe1~A2ll2>(+N{nl(mA-g@?spsKj|lxy -z)()OH4agx@dqUBq;L-JA7{hNu>Q~DS7RSY)_u>g}Np0t}sGn1q5%K3W)?S-wlCR>| -zE)hYXSmL?LR5W$+J_tLDZym<>Z5lr3N{ryGqWdTj&LKBC#_v%aBYnVM3Ga*HJ`rcl&Bu9mC-=y1U&ZEZ8PW<$ -zI-0l3Hx{w3hj(3&FS0@D`XRELc|_NaGhJ+WWXnYH3`VSQe3j%HV_&`KN|5M*0>^WL -zsx#Su#I(M7RMk>XwYE)O)31Mk;#RY_*|Bd@?y+O1pKAcxwb{Zn61b`AOh`{@NS!9; -zU3q@!@H`7Z+P98yH|DuU@)rJ9;|+|ab-8&?QUosqKOAUjfaiV(4#}))xw0L!=S1nI -z?7gvgCc5T$!Dkg5b^+0g>GCQ-(f4Zowkh_~a8ayIm_M8S^&>YZ92eCmY@QjyOqU=C -zzY0OmOZ{vRK>FQpl__^IAB4UqUc+_w9vYc+u8C`_Us$&~vj{x1H}Ahrx=pvfkZzeNEsgHv%BuqGX-91<>lAT}E3>_Q51FhD~9o>VFng;A19LKq^k8lx9 -zGwVO2|Fkme@Jg -z4&Kh8*dRy5O=K^OC#H|=phDs*ia_9PJ;-}7sOJF)eQ9DxxLH@}s$y{>&`^A`0{xIX-K -zg)199BZ=Qj2ggs|-$t3`1faZYOx|*p4)>#{_?ml=jvRCC#n5#4`o`)J=u#ZaOzEfya$Q?rqE)=NuP@IjJ9)km>ysty_03GoJ3ZEgNt-7#ukaSY?G*0;UOSbou|pzeH%?za_<6-H -z)d1KD<8#6vYdB@n3ATFxlUMeMnBN+feqL=6+BZK4qsj<`=fJ^h;`I(;A2r0QggekC -z6N<6;w_b8~&}%{yZ6{|u_sL-w}Q -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 -zU*-xmcAbJ%JrB -z*`;Wdrc?z_#puB~wvs7u)p0P1p7XnwY5m31U4N?LZFX#$MD2lQ4b4KSeoS7&_bYLT -zPu*-#>f&90TgdM@>F0YL9Q6c?6D)s%lk&p-X4pJZoMAL?8K=(y(NUwLz-{sb4j#+H -zGLB^|q_-U~2*%H|Bt+2n?IgPQ?q(?Y;R&L&^TfaW1!pjeWM-L_;-U1#oA%|y{l$J( -zee{DOSRg_%{mi^%()!#JXu#8g!28^V5d+HZ@oJ{NTsBx$L~|o^IW3gkh@^J>b -z$AsnP(gFQ_8D>8(!>Zgvt{kN6_bc->f_sxr-f(dLrr-q|+wD5bT}M`NdLMNV8qR+E -z0xw)Tq3S2_%ciTbFX%FRJ*aS&0Q&vrcgFfzHVr!_(>J~5~$AZ^&)BV9USr3TnLrdOBhpzC<>Rqy>;8pm(l)a_^9&%!1Lg{S

FTjCk4EfUM -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 -zO*zkqzdt5BBfvU48>vA>qNf$NKL -z5|cvkks@b9yb~zrOf{3eZ~G1DfN2Tu@dK>c=Nit8E6R0+hdn9(Ou7hvUYb2daqyZ0 -z0qUym^rykgFEHn%m^4sH$^XyO=|j8kk+R9_RvLU;Fi~&9En-zvW^bsHgl>Fg?d%;c -zV)o!1cQ5h-sbsXwT>6QKk^cbkZ%@Zxu25%3zuiQI$?a=*nku@4)=dL|eQVXN7 -zkoY17vi(!`K-DpN~lO9#4uDRBp -zs&riL9soi>y}z~3rmVhuA(raUbUf!%fSrflKG`%ibLjp2g&$L>+4wE{RMbf>a>H*{ -zC(j*2jj%5YL2o%c<~*$1j^=(*^{vCFOT2;-19$>46poSS#7+aOK0dC9v?bvC>Zd|D?C} -zQ-W5cF*~zy*X4E|=Z~u6M2y>lqt8;W5{=$V(4cH|FC2d#*5}qOH?jzU7iihZS@H_K -zd9%=5^{a0Su}Nf7e((kW6+jvkqL*SAVIm3im68Wig+ghLv2QCElJ^kYGnr -zB3($5N49&Ga^eQ*6}WqRc_6eK=(AUXLX*9EiY=(AeDj{OUGyhJze_o%xbR?CIwQ*e)zkyh%R@Z=AwU3K@k|(>Mb7`!7 -zbsZeRNA(_Q9lv%Tn(*0lu$$+?)KY|LV{^Z^@}g(H*;QUrX}y|M>4Q1t$F^PjEq~7# -zUA*Ptl&|UsCceVj8ISa;u!bE0y<7KdBKc0t*xCBXotw~x+UJ2kJ4iPpFMZOR+Y#J? -z=Q6LGb?WxpZm(2qSI~R@S5v;YJ33yL8T?O^ngvdjv$iLE$L{!ALbiqS5!G|~a~rFFtev{(#H_sfu%_i}||Cj%3}Vb+aB>Zm2%A=SH$M -zQCV(;-bjt6PtQ_2Ekp8r>Jpk`=T&f~>(qSfG|b#A7b-hA$F7jP9pZ@YSHU~`1tIlOU}J7UE@L%?m?po -zJD>Roffx3H<{@m(n?-HL#u-V<4S8Q#T~U5ar1BGC8=xDi#2zRd4|?0$sk)orJlNIt -zfU~aTJQM)TK(Dai)WS=JX(2Z-L;)h{#C}HO(yWYof^JX6TO^phj|AOlRm23*Bzy!;DS71AeWXf5RHg1rG=5XPk3RT0!IEvmQ2& -z;l|{AK4#muNl31~lsE5ZRkFE6LQ+qijrqLjDu8V^f7d;$YQb~p*5(`mM -zKCxYbkPvlWof<%(J^0<2DxW^>_taIofR8U7&T0)qq#>xV^CEPdm!wNbiIw$}CAYEn -zID0?ix#6!ZRh>mY5llQNE5vanb+JFK4)C@$#?Iass{s!C;JnlASQ1`+9IIcs#d}T! -z)P4Wb+7Yfe`1Gxv)|=Tl#8|Fbh+TG( -zB7DfO(3*ld@1C(*ryUi(V@2I0M|?hAT`C=}#kf*_E2^L`VY+cx-q85^7R}AS%cIVm -zP$)`g2i_x`UABdO=JDr;q32!1(8ogPw`fXCb_`~51_&3nNPO+J(o7=HBY+8uVl;#*&{xBBom -zmQlbpDS~(%<58&%L*EM*FCwbq*<1V#>iEln>Jg$R$CvIuac{y5z9j$lmN;>ve@6P$ -zj|Ijap%?F1z$2d-2(h>><>L{2zC#X0@aDtWCtki}n#5!+I$S3pAdg5hq4TX*CmDC7 -zBzapKh6_)4mpFGK2*FK0k3SuL{|V2CbhN16s>|{1;lD*)baSWP{0!`PUPTo>%5T27uN{)umO%BIvaT -z$z{%N5uBe^D7;dD6>+%l2Dp6_Ab!TtrrLbl=IW^DXVGFBM|!uW%cGD-2JITX -z0{Z+0v_lSNN(R&jC_|hOLfeM}SL|Y#pxF_tmQqcvS2X-X?)VS~r;J{S>Pz=%Oca@~ -z7m|E(m8A42KpyDtCXIKdo#eBQDx67nuQ1x_alI>7f34N!?pwEBfcAWMRhw}Sv5>Ho -z#$3eZjS5*=RK9dA!wIYlA56(ULZ-<3?WU`~1QcV(s^tBPs3U_fzfCD$4J54dej?+& -zeJSs(rb|eDP!KJIUU`OBQr*gbEfyGT#`KuASImV^Xh4f8AaNxcQ*D%K> -zPQtOc-^`IrXG7XUa8rjOFUv)nrXYMj{An_9(s5au_GXjtPnSCIJm1UO;n@JU*%b8p34)+&rM(F}UJw}2zhaqEP^50wDH8InBq -zC8O&^7_8?}{xvUnl%Dv~sXjhf)d}W*F!*tQ2#y@Ua@tF9cj^e;_;mM8KUM%u -zHdX98!uG1sOCB}_5OU|pgCBK*qz{RtrQh+M8i}9KL6+YnSS;@kYxtGUc<6RM$QD+B -zBmHTt9RZEm8HHf>9)yw*cnrb7Z+1_wHhz=guXbFp458k=`GEEC0l5Q``N{BK(c{-A -z)gPtdZ*mqbH;fEdvaC~Sv%p5*$G1V&K;5(D??Yzd!Lu?CEQ@6Td>LKOHR5nMyTKTN -z?0e^HL)KkRJfD-N;Iw2vu+3O*m#02;r(;3)(4H;=RYr-NtHqCJFMp?YU8cb@XZ+K} -z`FXST#2v1rT0g+Iczxb-yT!QDmtx*0<@>TjyMG@$@PEvviF-S(h@LTg;Nb*cB-1S1 -z<=Je0hzI&JLokk*%WZHEpxc3cpHArU!YB^v%h8L`GP&%ej&9?n8i@ -zUoRmt9h^ix5d5$RA326VH+DX+iqE6B?_5Zi3JJ}Z>02(8OF|zGz@4d#uFd=}g -zEKC%Wr*D?rAQm~yr>_~x&UN7Y9>P{x@-tA|+f_QVUr!X6UORQJ -z9yxrPk9cbbLr_Q|DxK`ky8ytj(C^LMOj2#b%h%)x+tSze`54<{=`Tr__1!9X)Y?II -z8FQ)P1-~4Gd+6>R!+U1@!Z~+D`=Mb$=dt(H_L4@s1K{P(-~*O(#O1p_WZ-+ryB@Mz -zAA}5wS~p*!LPtg7pRC -zumHpOSw1QSUrTY6>LCL-dh|lmSbZtTh_H#?IKq-ca0{J!r<^r3uN=}*;1xuNN?=&hScJIrjph2)2(zdSpEh!ugSvP5_NE{eh(d>u -zT&EkC`4RrJp;wIR#+`!%1xGezk!VozGB0kb5#W79o%U6c;#IgWZ@(Sx%BG1eJD+Ni -zwcI1He5+p60i3h#z9hXrL8gUux>vF69-(-V$TI!D%t^Ard^OhN_Qi*pt4=MB9Jg;= -zVh=3}b3~i~^%@I;O4T{(_FzaO>{TyV=lV=5*AF)#zo0rT#r?wE`*Tof!amXYs>s)^ -zoN2ynrCGdY`KZ)zHacRB1|4Gs0U<(k!TH1zEs20k`eA1kyaXglUA^F*g$Ho`NcU0> -zxc$T{Cjq_Yfk%$w6R7>OXeI^;UJ5@1B~=r9&l=i;n=AGbNInkFib{<1wU`t!-uCdH -zSkd0%I;}SeY2O=AH|Ji`&%ld+8h*}A11XyKV!Vw|xmKg7ZzH`bka73H+HM?{8{;2- -z76UL2keAmT-mY`lh)I9%yp95jhpx$Yv3tMM=U8H1ewgB%VJ&qJ`y>ZVCLYDT1^^OE -zhc1XAw1K=_4+7eN0iN&;;kY$K6H;_WSW@TeiB)Ug_FnY3`U=O@YxVg89>5G&=!BF; -zNX_c#dj*=-s^_zhLA`Sv`tHMNTBNmC$Wv49!}-Y%zRp@VUD!vU{ZDB}ls~WDDy}xg -zL2(H?R}J-C05vwf@+q&5tw13jSdUN25a!khB(uUX-MR2yiH}{M>-+UMs99Zz$IxDN -z;+p~88lMKTPOQymA3wNKr!Mdy9M&e)m?RU*X@7)b9zs)(vWN+~;hXo6$B7fSr7oL- -z#A7{)eocLHy6C5Q?Y$OajZcvf -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 -zXzKBG=Ez-1;puyZw<$^r^#0pAKB -zG#+kbY`}$!Z)4AC%lb6yECF^2E_U_*3>7sn0S<~CC0ipIVLryFbo$`V|1oxDIhN%r -za7zX=elqTVNl!kvKU1nFb+^=&m3KHc5Me{aJ@?h!dmC{gwYE|Z4rK=)FT0qTTu4)b -zL1GnV9B+x|rZW^@JHJleh5IUSU)boL`dRj+O|nHyf4)$0S_EF~_@k(H;ju4fv6sWN -zvC}_a?&?}Mgnj`7;ZlN_ACS~SpsOqUpAJcW|H`XWlH*_F -zDrFnt*S83O-6uVeX9Ho~4z(fylNtD<@3{uNcw{L8K>3m(U@`HvoDsdr!iIbxg#A3U -z_c#}IjZqkb&jzD;ORNu(~iA_2-Dk#Xqm|YK;XGavl+LY|-wBy*-m?NJ1>*iWjA`I=S|4 -zqIpytc$_V`+0A8c$YUpLc@**+D4|((FV4DX1Ag_j;^Y+v+|6m|oY{hQl -zd?`5-TZmjbPnDy8D6<6LddvjUVl$B4#lg3-Y@YjR_dX7t)JI_K03eSXUORp>FEO~6JW95s2-|csEZKR(gC@0 -zMEIeaXyDoRT1J87Q>%~V+AGU_w~psp-_7*K?}TC(Ze~+wh+SqsE&9-JY&urn$K7~Q -zMyF7Cb@2Qo72##&1|=O+==bj9js@Y5#=I(Z*V4lAlMUMovpPqiA19HM%W%wq(=xJg*b8a=Jv5O{IXM3&A3-R9HW>gvxu~K?=rQi^7}3JdThsS -zE__3~=C3xtz`TIz1m83Zz9)hX$Kj+&gNtK*bNYN*?jS!#z{1=zC<=>92r;Xr6FpBGvCd8@yqRg?gqhtixr=3{J6m_T3PtE -z|Hh?8^?a%mxOb)7Q|nfjK2mKsWt#H}NhCssme?yo`wGmhM77nhpf*UaQGZNyGxz}U -zOrHKktq;f*+!uH7_L{HI-!h -zH|J`(>c(g06Gj1qa2_4XiM;XH -zx1#apdp)olk2V#&R~t_{k3Js6rIQF(2r6;F=H7FM%8y!yUHMuwZ18i%!(qlVzAN&% -zO}LDTI|3RAAYHh_8FEPah3$UCSlGGZ$SozC+I7bxM6fn4<#Oa}wQHpZ%^uN`SqW(-O}!S0ntV1Ir?^Oc -z!j5=)iwb`YwAl7JD_FRe-B|Ef>y8hmtzc?L+)G`yC~+qQ!#|D8&3I^9(`$7r1p@y} -z%lFUgz0=mmV;X$nz;*E&9-VYtyN_eXsN`HIWip}(2auY)9*C1EpK8k63yZ?c8zPV2 -zFxV?X`;r<9r6qjbv7hs~?nRU7z?1f<;<9_=A^Ifn>=h*8oa~YPX3O|h8~!dbGlb;46omr;qZqm?M3>7pYj=-%fyRxWevtyHnD%v -z#h}kwZSIt>?Mv>#_CPu4DG`s1b?2}DSzqCTB`L87?CLFPI(41QbN91NnS9CWAOEepNJKfxuFylf^wYSztaL>J|r&|cMZ+KpK39Dyd=IEUx -zQ?JnO3{9MaZYn!6^?v&;cK>W?g=Q<_qQqVXpAM4AJ482(N9~n+X@mr}ixw>Lir{&i -z#r4vBuCpAxpOtCh+rgWq#ohh@=L*Qty|o>drP%k@Ar48i>x#9s4QTk8j$c=6uybeB -zvSei&U8j8RVf=Y{_QL`rbvd@P;B1(-ipNOMppi!d;B-#`T&|wNsZII&5QF}_=&OsL -z16xn323w{4vt!)Pl+jC -z@^5&X&!UabX-|2A@kfYF>W39a;1tf*oC{A~ZdLJhJ+yUhpq4DEq=>6zsY2)QkP$WDE -z4PCFs!1A6T8zbV*U>m8#viYZmTioW_>Z)_^=Mi>LHy|N8T}$b#7x#T|RN6=^DP90* -z@JrgREj_BBDXVqI6uauX=Qr$bl{OXDZ^n{tPp|7@dd3yK^oSZ8$U~S&H(@U>R{&xp -zxsYy$JYaBR&WkS=3s;0OoEcLbvS-Q -zIb(21l)WpyiSJgq`8653YpPPPAt^Vaz{-AG20tO82b%%#D$Atgr@G9GXOkWvM!#&W -zbca&##mk|_`^kHjPvtI(kW<`;-g$!R4WT+yDaT$YkI#Lrfcy9)k0>19^~8zoj9TL-n)z -z-uW(it;BP{05G{8S3xF&qgD#&`dJ7Y;mZoxUkke*p9d(4W -zg7Ql2BV#WU8FaG7vPK|dai(+Nb;;LpRv;IWyCpSG(j3Sjxba2 -zt~_`Q_mT(imCuNj+>5w_iu`4>&w~d=zkWkLx_bjg=V;R1^glhAFaLSvm)CdFJ~jR> -zc~SGw2D}F}cbg!hEc_e0%z^4-FLOUI&<Yc@aE9BC9M&Cc952EWTU`N;7SpyTgp-*~Jz+2#}O_FzpH -zyced&4Zee=o(o_v20N%#^hmr^o)74uzj`tK>b5`wpZR>6*trQs;$-UzL&oERr3>m6 -zXiR*Lw&NIqH@z6hR-*dn@Ce@PTFWJeU@Lrq&rQG}-M6wu_3#`lC~31&lJz9&slsjb -z4py)}%~7cqy7%a(I}(9&K1XiRD}rYjFeHM8c`%*$(-69>!}awHOLi!dsOA<`Mcujm -zspBE^Cvn9*jk6=0d;$^iJ>BcQrPsIgL48)2+xDQ;Pm#rMEid8yZq(c^4(wzStN7&& -zu<eH3t75jtG>&H0yM3u6SU -zj@`G?u6rz9gXP;i7UsKxrdi-x%6>AEj6dm((Sluab-~zr40k`k;g$cGp=g6}1J#W(i -zzIXbXt|CLh1Bg6tU>}UyZ*1e$(<7k19;u*FKlwiNbENe)y(0N){Ege!r_pcpiG7fz -zY^@3W(`htSHJkT9W%}|Sx%Y_OoqG>q2r}D4n@kZ$>ww7Rlg6-ai_sWI_L0g2I}4C5 -z4+Q+@YKS|{S-3v4dPw4$GNl94ot$sNSow1a*zp>+9_otkBpK{7!4OsXg9TjC2OsyI -zFuicQ4o?KM-`g^HZQj#5FZ+Cqk7#TRk}rJxlz)IK#N6+&zD?}(wmH579r;eL~5akfZJ -zxAlO&r~;)!{z*x)s)P7L==wXVcY>}*v`TM85r@S?&x_fYR9E0_Om*3V0cj`{2vo8Y -zN~wn--+ooZ<36SK$xUL~O^NNMa~#Ri0w66WCSY -zQZ2L6WnJZ%f5&My3w~x!$?;C6CA!NC2S^3?URl9OUai!G^N7nvw&`Ap>3i8H&!dJf -z#na4Zo=a>@Qs*>C6QB_QVN~NBtBB68Q_1K?H_+UEI8o491?Mqj*oTQnOF$oYPg&e3 -z_1&=Q&f^=$!@Bjp$LnZ(t^^~|A?R#5FZHZ#zR##v&@(9vHI$7KKe-y0P1uvpC;OHu -zfIhZSIvuA#h*QeSpu<8wpLIj{qHT=sH>?|eaN#n@>1119&Ch!Mz^Sp8T!kyBKTo>r -zPA`E2X2JvV?q5gJB5sTjs!=NsRC3fOC3@mU0$I!61qC{I9RMMd4y`S#%xrm7gP)u0 -z(O6BBfXDXnt}+t3!^nD?j$~X|>+-#5H&Gn+oBWK=P7RO1l2LbO@nf=b@_w3owzF-h -zYPJ4gD`N{|RTN>T@0;&5ha3 -zI4?lloACxqNV$0iK)l8BuP1y%?jCyo4~l?86HE4Ydj9hoaHyfcT;qg^)Z689IrSTs -zcX7$Z()|Rs)LI9l;!`ydC?U)|cjB{Bk6~8>7=O=MUv`@ZUDq{9g7?fa#8C*$>tMYg -z`6<|X%vF{3h3WXYJAF1Zj^jedUK+dt*NB=YuitYHzS0tX=|Eht1l$JFpG@syCZA0S -zOP})|BDMD8Gex(h&6vviJHcSTT;Og1om-~kbB@0HG-)QEBNwA9yiJ{-#?gBL`HbuQ -zyYqOYD_7J0?Td%kAOhxIK6DFKubdVtJ$Gvb{CrJZAjSMm`_;X{dh@}77vh8({lLl* -zIDwmaUS#9YI$+)hjn6soSt4T9-GxFhtjD?PT(BGaY3V)yMYqjQEU|(B^a=-V@iFy2 -zHr^ui)}J5qRdUw8_E2ZcFfl}$^_o2nOK~n8dF%!+Nzk6=mm^q-BZXY-)(#k#kk_ki -z*y?lq(C01cOupval`svTfzj8xc2AQ$7A3R3wbnPQzFu9p4-x5J+O_+@!Rg7vw@J2l -z9R(5m9CCqJ@6Rq`;DC(Y&zbh}^z@_U3`-HVJ13BD1i}I6dMSqM%t?sSBlFE2^!uE7 -zunv&bjSX+{l-duSz^dQrC=d6ja$h%_ocV67;n*V@V>1mTo9*_^ym$h?syMy3kLFHE -zctIP{*EA;=6Grv6-*h=tDc^wT+*?PkJ2Zy$@2FeR?0z2cIG3gZ(Dges-M~qIZ{_Py -zN!ffW=se2!UfRebn~w*k)Pdtf=kQC)es}Mkv-WDXWv<$t)7y@4*zR%CdyTKwt3Q(1 -z@Lg6r-Ul#ZKkZT^D>?8&`xSYC)spL*hrgB)MN5D2;O+LXO1!ixu+c`N=$I002h6AJH!}&zLchz7qj*iz -z9T4$=epVqyll0B%s=*>4L$$Tl15G@Eb+ydjf~Dx6{vcQXybw${#jf}<+US;6?)~(z -zf$hx0@;5xSRt0$*m*gL?7iC<9vpteunr!je$q3ue-ONb}e*!zcTK0;B$ZEb`bU -zWoxz9Uc~mC$K^NWlfPOdgHP6gy;>nD?`KR}*egH7ijB!mcMeyluvUae#hD)jG%Y*% -zK(Qy?EfxCOm@S}?2v*5d>GMY)7JkcZ-8eOpQdLe5RrzB95zBWRWpn1{R#*-{hNimc -zjQ~03J+Dsi%0DqQa){X-aj;KFxu|u-~Y19U#!gK<<*(t+rgptqG^ -z7(@G0G?`oZY8lGDY;j!&_ -zDwOxx1Rff*WCR;F+!>!NTC^$xg%_7voU`XxYqUz}$+^{c&!c|+BJ*)BkfZ*2>dofP -zv}VC8X{G*(6|UcFkm=3q3J=10cE}Yt_pKQpd$14A&Zlf3YM>u!kL=&lOgj`iT^}zP*n@);zceJ -zDzVSY5#5f}+;q5b>Kb02>8lED~$Vj#3Y^b -zJI-Qa+l^w)_Pb`dccPp08*yiciV)Gv(=p>_r|!cCGdfRwMXd0ytdu_5v-Yb+% -zK64Z_yWQYC>e}||;_1vTs@S|*C1>;OVA$Ct{)AD&o4sp@Rj-Bj{frAB*6Qxp8Y|cZ -zvUMP$7&RykGAA`&sFTBI>0!J)sc>V@ZGS{b_pHG5F{Jv`<`{*UY$sbHnu}+8<<5@! -zCG)zTw*6M%{2%AgXXv~8g;Gm)?GfF*XHO0^@+Wt>dm`Uc=8}ESYqqN;R67Vo%{bqvBH@<<0aZjAFmnGKA7nz$L;HFuQO@_DX4y?4FC&bbD#Hh}kdmg)xgqd*o -zbTIAQ6W^)UT$ZZGzEHAbaF`RKX{hbIt-3%+nx*Yrm-a}<=Qq6lS%I$##GF^pXP_T8 -z1I2b%d_ -zhG{^a{z}l{9Jsj*gJ;2Nsy`5VL?4}(zH4%Nto&7khwB0!S@zM-Mk)#DeGp^yxOG!=N?Mkivlk*wI9CfSK&wu4O)-Ckj?Yx%S#ZrJl`k=SopemjlMKn;r*8Qnhy=v|F@EIw -zeuBkdvH*jvT`9(}W)?kShml;fL5ddIt&7Ck?j4E;YQyJtbZvuKd48sH;hVpc1}iHq -zrTaj15}tws-Z)yl2OlqGIWCvy1zZ*De%JERZi)Mr3i7kG3L>b?>Bn63CF6n?pi4}| -zQfGF;iq5siYhCN0Duqt#@gNc>2((YWK=IL)f{+66Nu+9c@qR1U!9Z%!5gNCIdp<$z -zJ7*SY{Q*9(26+UCi79?VT#3wd5Fe6H`1*YM)UWT9)l&iFnx|)k%v}49(>^!O0r?y! -zMVE%ZO90H{e#6d7GiMC?AQBw%pgLJL<*WzB>rw1*D7tjo>K@U@r$|k-Y1_XmMivpp -z4lDDwijP^Etu_zPd9@JYyC4ED*5>fv3Gk;68&?GRt@V}hsm%XwOnHwlJ=ziLS3iS` -zOq%1AX45RSe))4{e9x*89){uNnj?mG?V3bC;8P;>DjykKo5GKI9Ju^wOvrsqs5ad@ -zA5+y+*?AG*tTWN88032TMr;Zu1AdZ=cW)XhS7XC>hGr%dP5~+RCF=`~Bb;9FSltEp -zHIZxfIGT37eeOU}Ut44K$O)MBPG5f{y3qF;6TD=`%gt36X-~r7`%6`h?5?oI8u-a$ -zn;haf6gQOW%8`6Y0tbhDFz+6yNy_(tN1U%&%>8;5!TyvtqVwlLdn1xNk5AA)o%*;a< -zFmOrigrgggLYncm-V?WOM94*d_*cfo=z&VQ^x#JA;DR0Xj*UDwJp!&+#5T%f3Vr)D -z$eF#MxmiyFMnQJ$ERGil^eB@ -z8y%+fNL-IQ33tfFVWsXXAorXXsB@#guDfIQUNuOikBU6Z0FHI6=`Dv2--kD@*8~~s -zp;uO<$fH`PMH{K#F1)eoo^TS*gFQf;lN+&o_5Oh35-zqLC -zo|o9$GM48veZQ|lWSY+QRt1fJUCb5DH_=|9xV?i6QDa4(_+Y^}IwCY}4l%w0I=C|I -zt0uOlGI(N{*Alvt9(%0uJueoe8364?+SfR{iK3qZ)xqn=%gaN*D|kw|Mpx%3ZBVV< -zb592w$z#~(2Ht6$0h}Qel7^$4whn0mj}(8DE01nAOO)b{iSoHnP<;e3zIg^m)W`2L -zg%C*Aw9)TL<5#|GIa*s{tL*W=^Lf!|l%<7s==uDwD(4Q|0bo{CJALhu_D29DoaIwO -zfaB@PU%z4UD!{kHgSg2DjGSv3piTclr!{CTM^Xc+lEaTdW -z(z^$@USeE$OCOoI2rqTpHy=f6k2F#BmN8v8!*y03h^X0bQj=Pe&w_d9|T}-FOZtBI_r>#8+NH`i9A88y*L*3tuxR1KecGJh^2*wZZN<4=wZ6`A)pO -z51&tJ@RZ9jy$dWG&3XG%i|wuc2F+p_yc6ZI(xqcA4_Z}SUzb-igpUB!X^wmByw?cG -z1(V4B^gP)t--oJpvIhy!O;wJZf2QgwZGORq`sr+sm;*kxU#&26Y=W|qgD9QxjL|B+ -zItMR{awuW04H4Z(9ySND755xmLt^jdYpsPs2d;aX8IpX&bdmUzS3GM|b?~!aW6fB} -z$LcS*QDp9lL?6TY?g73*JYvq?jE%6HO4ZI}R&D$C(SXb&Prk>7DdQ5{w^Oap7PFp% -zWV$1J`ViQwwr&;S+w`@q?Sn*HCw!D4f5&Cv=YghAD+7GAPZiT$Prc`sQuZTCJ^QAJl^EwG&PUYVMBOOPm3J&sl4B5%YLfNXlE~v -zE#CKFu3osQy7-EUBEp_P7#(S9v^JBANz}Sf*I;dw2t%Px9@4w|9xYy!`#!OU(@lv} -zeZulpGlYJx9}scV-ny37Br9!Ue$owgMB8qB-67(=Tj9rS9)NK?fBO3o{5?}B^^IuF -zXB2OE?nFx+)_~yr6hth4OR^lU| -zLpFML^L`MxV<2(kP~9x-$XLp~8P%)8?=f8>*%qV2S6Fd&{rX*w6scn;#2UYA?@JLF -za8us4YwMDVsEUmFw6OFfwZq$=0x@$^KBokf+wWz1A59&V;cTbar1<=Fr_I$Yzkxz( -zS#Vb|s@>^_YE>ZAaPAcBuMrT}fMGso8;3x+B|lQ!+Iv#UF3BTFh+lSc`9k>M -zxg~q?_)C(EN(PwZqarsRLr(hSlOo|9!O04GkeTQ-%q#hrO9Ke0a`fx=pET^b=d+OB -zU6U%bS9n649|0_pubrV#J(o|-%Quxym1TV5-U~c5wZdn&P@&^*T#bMG075ZZt?G4C -z(xXjn4}ZF?mMVz%oMZ*FUc5K4%YyU5^n0d+4&A6n_jTv8A_asmXWDy*&*gxP(7 -zT5cv^hfAyHY*TbMJNqE>z1k5+vP>@9#%Jo*o1A4Yo!mCMbu8i~Dta_rR`@~lF@{ge -z+TpR?E1Debx9!^!0X;9x`>lSp^i!Go=UDi61L=C)zIfF0U^FsQ{pm9u-pXz&dx5NcgKPfl^a8ogg94K+wWihivRM@MMSjT_!E -z?>keeeQo%JU*EtvS0+gwS+D%OfEW95>jqN!4%Iw91?MA32dlg@+%C#12Z$UZYK{8< -zz>%pDfy<8v{x_fgcD_H}O?0LYjm>qKF1R%Q5Q+PqzOV*c-?;FSJ>Xt&!*5_Gg1xNR -zLQ9E*gd`ZEJ2%`yjdLI2V>r=aNMlwUo$Y2mi^ke~NttNqf}A@FuinKA_j<2U_bo@f -zC3AilYA#&$M1sP73GG}-QX%bX9=3X% -zpxoH#JRX$yGrg;qc{qYU_2~!9d$+xv=PEm!Q#_Yu%6jz6-)U#hz`3S2O;Rg@f+R{7{sj*pPk9vxljI?36nBR~;`={ytd9CpWakE?$9yXd6QJ&B|-%oSvNH}!-N9f`}rmxF8z!%PYGRY -z%YCpkd*Kr*IdS=8zV-g-o;9l?1sFJ#3?w0v9;b){moJ9yxK-^BpOaIGTzewj^`qU!Ex%i&=V=7^2rY3 -zDWjLhw?4xU`XK&g%uoICvjqoH#~AGIrcVem6}0}DuxA7Pda`%fUPdjoxkd?(GnCHP -zyRUIxly3WOy1KUF!tJ#I_e2K?$uQj3a3DQbOlS0H$(kDRdvsI5-_Zm#_dKXkMK=>d -zNQs)d&-=C_f*ON>!@D%=E4P3e8*0A^i8+_`t~Y$$+K~+`$}~$5RAeJUbKz@g2-M6# -zX?&GNeOdLbEBJ|F{=zd>hHmwyDLt5IRpLj*u4K%)q5Tc-zDXb -zmBc*OxJ(&cZ>aD7m-K@29iA6G>#*JSDGHRCATk9`KM_#n -zcr*P?XG_r;5YgB(=h)!zx%Y9QfXxLe*E^L6xLa2r4Lin)l&p+LN#CH4&ntH0I(&OfYGH_Ting6abMYT6W@V(3WCVK -z&}j$}`tn)yOC~)%jMtCLIoDkdAR@J(#nY9k%k-h6z>;#esQMSz5R+e1|7UX{E;u9y -zJ_p_Enw7RJdFrf=3XIyV{6dKDLDtDRciWj^UTK!^pGN+LW>h1+g`ield5!1R1rj}< -zIl<^-7y|`D_cq@--=)2M18ygxpx#2d8dWJ5N3Ax07VP``fbnr&GsSCpY`3fJ{14aSX$?M`rHS -z)ibT<(Sp4~LiFuVtshqLq!BalTVj}iPZjeFoQL;$>6Dpp>{`lq^^Cnz`k;5Hk88c+ -zU>j0TI<5d6_g8N|H|?up_@1rh>5~=abMTO#)>p*dV#$Va#Hsh1*R`B+>~^EYtb<3! -zQyS?&iMF{#l&V10?t2VcAG^7Uq~v)bL_jVbT#S50}_8zk?J14u~X19$85Zf?=(wR9KCN9 -z&eqr5L7vtfML~G+^Du9J0Bg9G$`A*Ifys6HP4`zU$82qI@7ypDv=#{!eFCQMh!u@% -zTrIMDH$lW7(p{087Hky9NTS1I3j96t8}_7V5wnE%xlZbBII<`Es@8W2xV~N`UV^i? -zSsXqTz1%1cmI40Or&J(?+|bGi7KNB04kOF0)k05_>W-nF(3^T17nqAC>YGaa>R!MP`j`L>NH`x0TQm*A<1qPR7nSA4r -zj^2`{SG9UME`#3s`f?K?!LMD=5NZ2NNB?=9~p&V8EURfoLtO1xw!b~1B%6;M5YuCcAxVWDP$QOkoSarEdzbf+zaOGYUjO!UWs0|tQPi${0hc}V`Jti -z`t;Z<3&nQS+TqqE^w0loud6OpeV6Bk&ypstxqA82_vKjDFtBww0Is903(9w$Ko+&* -z@MFNs{9RtIYv-2ly;qP4(Q;dLKS2cCX@AzmF#;8)$FlrJ@jGN0U){LvuooyB~C -zzI5!3PPW`t0us<_z!W)@qa^v1H$_;9*!o#=3tNtmTzfCwflWv^f)*C^z_dW&2CQ_A -zy}9xpDD?Ow&^{cD>=7tVvNL-DW$P8=D7<`)IxIaI`XK}zs6JeBMgw9Z~>=2 -zz{8@cR)oV_q=Kh$K<_yb$=neWqc-n*Phu~M?OY&7Qwj9EN2q9z5^nOBTq~qsXZ0mB -zK2$!!y$`?NLu4HCL=&ZnSLwiIicxw1>~0nxA^CHcEMp3BK)F*^GP(%RdXk+sVnmS& -z0xY$nP^fjai%BK<1eTUuAa=#G;S|mg8fQV5L=v`|OZ};{LDHwrNm9Rj==bUlY+CKy -z(}AX+(H3pycRKRwC3KuPo3Ma|NmtB6k@KucxZu^1y=JcS*}UHNlU2T8J+a4pHtfbe -z4bq|4;4x>zVf80H_bYun%{S~{L2Gx -z3=+&;fd@@biIj-i$@k}7WdW~mhig}X#9IgR^+^ZX^_0(>MThy7pP=LbDEI>wv{5+0wBmIzO{%8%86-ABCy)YSOPVxy9K -zp>u{9)0@1{DJKA>FNhfLzR4;sPmt+KI6lq{#j5$J)ydC6qS*+t$?DKO(#O|Rrd$?@ -zKQnqgE@zJwEQPD;h4&(>yhd=vc|Cm9HHZQ?@oETW3Gux?cOREuyy%vlhjCODA42=j -z>*iN}9zW6?CWbcc_nx^dzR=TGW@_iCKdD5eVJm5wxe)TDW6Vap%7yY4V>UY-``lpS -znh=9l>m?|$2!iQ-pq`?%-l{Lb`VsVwtnc0G>Z6kk5&=WC3y -zzD?ND`h;}p>Qmp%;99S=WIaSxJbX_ND8(aqxcZiCo^-ac~!(N&2lOik)k*L@tR1<1PXjg@+`%vUjvh)jmq~f3V8>O7I1;9D= -z+l`Aa6}5YgBA=8km4}uOUry$rWzWaF}@o+vi -zJCNC5Tre%1e1b!xXuvOW>fGk$_~MT1X%i8n&o5LFQ<7*Ix%Y9H1HyWzDNd5PzacvI -z_z)k#Q_=#|Uo05rY4c?rgU2@3LJwl@ty`y;Y}fN#{jy@f?wlt-t-NmRd5hU0q7brA -zCy&@fD9I5xkIWzc;-paq32ndY-KKYB@jlFf&}KTF#XWu#TCj*qmZk5QfBsTAAc6Oh -z6Xi=!JJ7i;+HV0IoX_9+jAZ%sJCDc@kphpX#d=8By_qa}u8cIi<>64PQeVqn+#RL-{8frq?3Q2;Q_+0;z#iA`nX_;5*~Q~m9jLtX>y=&Qibhvu -zPK7(-#}|3>aZQA8lUmQ8^Jk-KL}F%{r27|S%I}4QrPcf2rFzep)f~4F2D`_fHq~LO -z#T)qMt?w%~>QN5;*S6y^kaX{pu5aSeN{7tyD|@pl+vH*MhQ_}{N8Hk=%lzfkxD^0F -z>08EXeWv?F9vr$(zYDkGZ+~iQ`AqY)k{NR@_=Twf0H39V$Cg0rTs~s5ClD3T5e=Z( -zvPMHl>L}`W08kIW&Q79cI>g1Nu^@?`d}ElzRL(OE~#+%E(8eUIS;CGB~c(=O)=ia{>=N^CFu!h -zoLCoPpo^PCmCJLx4nE?ZQXBzm_=u|9AOn;Xa_spanY8IUTEY8RiiW-V0@r$L>U4$M -z`w8D=0d{+%_?{8bXCR)$Rt8A-2M)!nsGKbfJ$m6$#fxW7C=z_)g)#PC8$5pe{jsg( -zzQx;SmM-#iAm^8Pg2c4*6z;i5p%1{2UKv>-tOOrN6qc>WX9pNIBd>c?g2}z~xZazi -z>qb?gTlc9U)aY~5<{VseQ$2hcE9vsR^^SCnonGEY&@zZo<`Ox`}gnAB@LSSUTjdP8}`13lu28@=fkF=h#K+0G3 -zEv+TKKxw?EDaT3m2z(d1M4cKS_;44xKX~8Lr;IC(o=d00y=r71LheByjN)41ywC~+ -z#MO9=Go7Ri0kC7OvQR_AhxsPRaS?+1-DrR~H{)}ULTP`i6*U!s3lzWoGw6ix(wk3w -z4M+p;<-K3M(BtRJm0SI1xb3o6NM!N3y$=jyJ^ffPF;|Rm^s6#l1|~8+N7(Q3x!Tiw -zJ>QS(ye~0v)65pavVW3$_H!xx{M*0FGH>ZVPzuV6`0ez-c)T~TV1;?!Y&A9&B0FWi -z7eS#j}ne7<=R$&we=m+<1)%Bk}3_&zhiWqZ`ufX|~c(Ye)%S_u7M -zySEE()#os=yGGSx>zCN0xQ|_HBICTrCpPx6GN7aDe!*7>Cu5aEw@Po^h13RmBLiw> -zp~`t?l-W;xF=8{Qd}n4tyL^)j7kQZ*2+*mSrg6Q!JEroU^ZD0p9#=X-o}@#863dof -zcn*UZ?7qdGQR$ag`(AbYi4fOQx-adgfJzZP6Z -zG~257gl)%VINfS?W1{*q;U_x807ZS{m51FD51fdZuHVJ`=iy{sxevn{m5ZUP-6&su -zIB@>L9y!kFDFaevJRA`>y?NB%1h -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 -z3Rp>6RPhND^U`!6`ABy -zhoVgiw|o?j=V6!8{UWAyx61cv -zXbp-Fu?q#G=Z$TM9xL@ne#?Glp7Z&Abm>et@annQ4}`SLf;tWuPKVZaFYXqBx8~PF -zUDeLv7S6Z3?%c{e?Yp>nz#rl7{hm0d64 -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 -z=koE8Gm{}b{;3(am2ovcTLBn!m -zm0PD(`B3PD;}hbjmu%Gs;^x!CkwcFL(suybbhLfv`eE!2;B#n0kK&i01y5*b+_~qL -zH#yry?<2<#&Xmx79N62=+yGTTs=tF_aUkrR0mrhpw-tK*OQ*b`uii|Z2Y7nrXF2W< -z3AhLuspjZ!1aQ7gXUj#Vui5&<@a)>-S0X70$FIm+qAhuBnW$)rn<<)U(t^+95C9KK -zGV;r2M;~xUSn~4VReS)2e2x>YUw`1$XD2@g|G^Sb{(|mh3GyP~*d@O=R6VX?^2)+_T^FAH78n-|-c%*rz-;Lnl#IWn8*9b*di_RmCI^bt~p2}8dc|8um)`DVcd{?0f{<=~Rrllnn9 -zoG$sk_h%Ax84qfY7zPxz3nv7u2zgLZ^VfjKb^OxPCND8bn9)cTUB3!_<%Tnt^rThx -zlYFkyQ>Q`}X;aYVi(jT&@#FO7{D?{N$h)__4WEx3hyW17Jd)cuZX1s~-TP$u`@tLr -zWivLc!{4wV0J!yI{+qE@SQ~k}@D=WnW49OhZm)nf-jb~t&iZ#rUlDQ1#=FW0HgXe* -zAg1!1%X5v(>dQT7c-x41ywo>+GC?2JCFcA>sb+3GEmi8U?fIlL>xqcRa*#bPtAW6z -z+y_h#tt&!eo4LWDg-$l7nC8>d1^g;nAUIfo+7{E1)3*3@!1_GqD4>wv_?<~amY==C -z`Z!=$-@|W1zxtadLH$_$T#qrj9Qc;fwT2RO&|X37)+@%z6=z -z-N>2X)XZI8Sc(jYSF*P+S>1FnI>afwEhM#v@MBbAf_#?FL1yiQ27r4$WBuYkN@Nbd=YyXEBb+w*V!P$BntD8Q7I|>L=z%!Rd-aGPsW^08 -zAYNgT!-O3f!NR4Uv*$*ib_janu&sgb>AUOS4Ws7%UdAF}J!LXDOGJ!#){5di>@2($ -zgKRTA?&r^vZhszyZntGHeLd^>Da)jkAr>3ao?7#9F3a<_z!|^VLe=MD=MWUyIadMw -zv3I6$sG&ljS3eWLTjJViDF>zN(^&~hasgf9ZbdfO=g?;LBwfk{|4ipJ?{yso#m~W$ -zfhQ6UXL{ffN_?M!@TpR%yzQIo-+JpuE0KgJ3g-@TZNp -z`f-O;^K3xRRaZke_JrDAqboO!4@=-@wHH|EFhO;vOrd%V5iaFtdp|Pwvs=F1H`96U -zA{o-X=kXhntLXo1RCGaFfU#L93bbxjDn^@0A8DTx5Ccrmo+) -zOLyy$ZbYS7-_IobzF(sc(6UJu=H?U*pGBOG<=dyBVheV^_|kbAlw-k3hfwlSW*BDX -z0LsY8yQD`gZFKUX;7Ws$FBjtqxa7WdGc)Mqo0E!%4&lE0OpWMD_nNa#K$~KpAh}rROB2-T&6CO;Qo{};nV6v$#gDi$4K4V -zVxL(F+@X{t=r10i9}3!M?FUEqn$4>by%5QIkV^WSVfa$p1TQPGiD?|Q?{#is!Z(t; -z7_EFx!%5?zm -z@Yuu2XBYT9_0Xg_*2w8YW|@2{Ys=+eor(hNjbgl*5ssM{8kRWyzA-U7@JMt#$?;Gn -zA65xM6_+{Ox+Md0h=g}EQI25>Ug1Xe0a{0)y|3br^TV5qv>Jka9wYRIRj!$jU4mm3(qXP


;$zL+MxI{G7r<YyJ|ZNOj7 -zgc{S*ed5kuF+8O3*_$a4Fhk{sYV=rCZfBgeT*$G{OsM}kM)dV-d%s6LX9(LS=9{}- -z@tjFHaqqbCH^?;J6`559oNbPkMAtS_&M^zUiIs6YR#57$pStsQ>Uk7lynz=?H8U(7 -z%a3hA_Np+Qs+D!iJ!!kBV*VNX$^rhY4a5L`<^!RaUU8`*E1&vjxKnUW?_2TW-aE9K -zBwEBi1bFj+-C*EXBo=H@q&NE;jf8?%>_zcy;jo<;u6RpkM`|_jl*QA1>!SBj|Gg%f -zW{cmTFy*1ovf95u0%&E}rQXOvjz(a=2jSX>D|VU` -z)bbMUbq9REbVS{dtFV<|Y^OKBLGnXPjcT=&VpTWA9&U&ZQQQLRO&QUpw_px3bUgrW -zqkWYU9kW{I5Rmd0XpLq-tTgu(y0V;mQ$H{I6ZZI65omPZqsX+!OHn?NwX%JKzJ`Iq -z(KyulF6>0#w4+xZ?WT8AD{ALyVL6=CRTSrHG8i5Ti&qKky51ehraea12^GiIH~0(h -z`lcqVR3`o5%9CJ{H0=XxQ)llvLV7{Yk>S;jeE^XC&85_ir6xOaem!pUF6TT_ebohg -zoA28Uui#vU?9p5AQMPr?ynT&j010{m)awFBHm~C6Fjh|>4oUT8)^SySyNFrki)xB* -zqd3}wm9sQ-Jm{$oJP&Y(w5V8Mf+cGE<|x9aA`!iA$E8X9CUyEe4x@JM^NA!F^s#)b -z@%|YbA@S$&s4R$o3-$ogWKTbu~{#l -zS+u?`Pq)*%`h}G5045(wSK5Hd5`n5cJPRi_%+yqv>67Y|6f=Z${3xDD=8QFFfE>B= -zwM7Z~Mi$4l*nc)L5`Bs8Io-JDsxGoqR$tW{Pw1S-*9GYjbj!e3PAXXM69rW!nS~87 -z%1WOtd-|O|lTOKKk7BtzN*)c3Gm*KaTd_Qr^(8LXjr}~PoH8E1eU2>nwUXo!XH@6$ -zWHDMux>KxkAN5)@lz6%iDV{KG%r@u|R{5jlCcHH7GBZ+bH -z9_GIG8GkL*qhs>fRy^{He#IaZ^0n7%S-!>0FS^RYb*IXQse%)>He>%9w$bFSkEh2$fk -zFvl~CNz;!W|6Wqxyeud{-*oJaVe8Rv5#@k$hkKu7nztu~m+NBB0{L&Fn4lZ8QEXR33GSn>2s^t=zCZjzHC)fIk^L9~w%siXQ{n~-=P;YvXA0+`9 -z*?XPiqKYlwPv%5vZ%qj%`HNl&=Q# -zjoooQ2Aq*?Bmx6?j)d#!9^@=HLc>RJ_^!RWC2403`HOfuJ)hB8cOEN+8?%`2FD*-c -zMk;!ceZLeW(}CM2t0a<1lan=6U&|6u#}-Z|?^)Fl7*!IQkIvc?m*td)GK6;h*6eNd#O$gdp -zk69ia&lq2}&+mM-{7V$u$l15Ez4q?fFxRXG*{`u6z||?r?4K66H?DZ_iSrQ}&y0tQ -z?)G-(#-ZCRrz?2mdn4m{-!~r?O2Sk)SMkJy&t#sP)k@qfeR!pV^{K}PwZWgIaC_=y -zb?k6imbTEW$@dS4rifG3uP8oI6n3^5OZzA(4fw3xbMSK|&kWr)Iz8C&2w^qE#kr4r -znty&I4S4R{IdziRhl)T_Xc-`uX{dr{7wJk -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 -z&Y~|l1=<r$+$9;~bN?>#e;%@q -z^3rhLktfjn{lU3dR~nNJb-yJ?Y@|bVdJW>lFS_k$Pp;s%osmFqenYAIy@L~QzdcwK -z_XcM&KO{{XOdndwX#J#Ad4syg);&{uf*xF~(jm%;9IVc=uagP2wHjrH^~}IqG+XCA -zPJDYh_A{cVK4D)YtkP6PiMvfN-94rUzX0x*iZ84T$RL|`0HJxJmKiY~h|XQf^Et&- -za?71Ebn`64OYgr*DheUx)wfd=meXNB&lNU!EGa~2;W(S@V4P+e&9D88-i2(bG2%LK -zs$Z_5@%zs>X?%htcegK`7GC48$Y0L_gV&{J$#2VqBZgs{H4!ie!gU(hY;t6mItLN&qzY+BLvcxC1FS_Sp2pOKiFR -z`LBh|cV>`cgNt3^_ZA<91f9XJaq|v75`|Y=;Wk~yD)|ms+kUaOI|8^k%9jcptfQ_t -zpU+HqZDjC^0C1^wIF{Z0z%R-LPVWF9Vh_{+-Fq>m(uLIB5+F}Lre6*nWElNruY!uK -z5Y%$!C~|=FfmdVhiHDo}>Bwpq4VW`$X7X~1v%i}^-tVFinzn8wv1FOZ<#A@1HkY?H -z^k#mI--e!+mx4ntJ%*DR(KjC3jM?G8%e?$~-1?;!f60aJ*GmOXW -zsc}B%%Zk&YO%3N?G-37$dLl}hU2Uls$R^IICeP@dEN)=a%W)WRZ``;Fe_ -zJ<*TsGaUeZ_-K#Ktv`aCv-B!X6-(dmZ9s4F6Oldx@z~LJ(akAaicd_{>en4^BTrc~ -z7+f33Mm<^QJDk+Z4P>PRT5_^(+&iatDQ|YNRh4Va&HTe1zNdo<8WJhcNXvoNRRZXKv|``qBK{vP}I| -zv-Xn>@VP$3fqg3(v`yH1XrCl42&IFRLBS7N!Bht=a!5{m4e(~v0DXM{^6?D0reLYNXGvgzY -z_Bp~?PkWHgNg6}wk;{*}jicM;I$x&OscOsX>zJ)wxh7G&iBY8E3_6uizAWf6OUt3F!8!xo -zW8rswrOG_c83}WdFgVb8W3G&>+&Oz%>+6$Z@HDBRlg_|zce6)ap7QRyZuyyYBM#Er -zg>&5Cc1D_SG76N -z+p@`Q`K>~}wR{Ds5%zm2@+AFoJu2O|qQJgcdJ0uS#$CFl)1yh6Psw#reFGZp3PsMP -zJy*Qyg!aitfLj=Q!Q_KyG1wB!QC)1;#8pR5zngjM!K-m#_FVhi9HmDurErnlB>_-K?dG=*O{n)sqpBwes3TWKfz;g7)tQ#i -z8GGPNHS|1iO`{c9=U#e}tnX-%eZCcM1z&x)$cXP9%mNg!%^}~jB!S5qgaWsC8FFnL -z&%)?3;jQ@mOL6at#e0_9XCkHOq6=eIXU0{5S;!+vE=S<;V?uINWRv{N!92Jejc3UU -zkybSc?`i5~Sy~8S;Js(u&4*gt1&eQ2JL+dJZwJmzj>~kuH^R3^4UU~BufC$mOWga# -z_6<55#>u6A3V4JrN-8YXc}y&Z=}1L_T{d$wwtljWb^OWe;D@8zpjFIstzA(L9kZt4 -zp(|1e341#ctc6xC;+JXRwAJTxd0lceEn+aDb*!1U4dF>Az4SY(d|Dbg1ZwN884(@Q -z_wq%{LHxAyJ#!&S4vx>E2nt_%dYtvZDr8jB`Mva+X32=U -zAScsZpYA_(fVdN-(D=*j-;QWUDbD&RkM#m -zyiIVmo+|ft0+nz&SCA=lP>DDmIXb(Ku!Y%H=Xdf5Wbz+jSCS;zZo{s`Q6!ff#QPt~ -zp_hMIj^5ZE@w>CKG=P9a0le93moa+w?$7HVjB*V_)8MAb6v@>GG-uAH`S&In!FAxv -zBRh|_Nh}_K-&9jv5#Z^oa{=cq^gp5A{?8SxS=c3yDEm^8D^+XXhRp6qFzW% -zXUW*eu4aLxkTHs-4SWCMAiNs4sP`$)Gdd-BL@NAy@&C$uA6cbL;05y2o=4yqz_E0> -zfEM)jim*>%)t5WA_Zp)Cp^$!A19O+o;N3CXcI9$(l{ZwM(IdH7ocr*~&OLigI-2TjB9rH=BkeFGI+Y`XdX;v*4Ux9bZdSbY9nc|=R?%d|hUl32Q9w5dv -zOg~SHoO6^<5$T~t1tQT1yu3?(&+pnwiv7Ew#Erx=GLul8_IdQe7yWO2l~+=&ktu^< -zud%PA-*AJ_MtaQ1?fo)zk=CSE=w2kp74T`gW7YQ-ZJvEPw=4lOR9WA5c|@bAx9aGn -zQzjZ5k68ZFOz7xs&5@eixp-3`M?t5Z<7eN7yc -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 -zL(7~rOGts9ynd?6vr=>%ysD{ld*qAQ5 -zA;NGRsdLTrA@-sf!fC4S8sh4kG>X&L4V1oA?{ -zi$B{+xCa?8GC1`3+xTVSCqBcWBNZOus{QH~tSK*1A6tC2h(y1D7m=O^y?5?t1U=E5 -zp>M)Mua@hp?p7-|ayGuJna6V1QN -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 -zRq*kxj5SU4Jw%b=3Um28 -zYq<|_Uv>YEGxG|eL%zE37D86WcMhes9C89I(Lb-4S#bgyp-PHa3@yI#h@5g55FG;bFyD+@c$K#EGryQm8g|Q?r?E{`ZaD}O_u&+Q<*L@`_$4I{| -zFv`s}z6k#J;m`T|!uRcuM3OS0&u*WHk@&k&uQURzZgiqyGMWpZb(}aH<232o)oxny -z*jf=m-4oGedylC-osS~?;E^9EICy6dF>5@g^x4-&t-B~Zs2ae|)LY-dOSAcMV5eSg -zx%$Mpk=M+~cM|`&8ccfC$0Y32fWjdIBOWSYZs!XlgL>0ru+#}o$2jSI9rvlei%4eV -z<2@eLZ>!o3e8PARAnei2x7Ov>m1CRwmCKP3uj9wYBx4@ExqVg{x|Z%e*!L`)dNAwf -zVWFzC*(t_ZZ`BfQj9Bc?N_`xB|@)4rOxt|do+7}x6u(uvpZR*6Ow``U+q?LpGi>zlcEWKDjPqIBh -z@-?i~+bOVoUDYqJkk#@l|8Oh21D8Lm42k;sFqm5@0M5NYpiioninB;VbX%T2EwFvH -zza#C7b;|+8sh&IMzE4*>jd-ddf;_~9x)-{c)x8*dv -zEyO6UU!0_zY^p`WiP-Azb@y!LmHZw}3hfnaz4wWbLI0xJ9ICM7HqDoZHE^0bOd$`z -zy+4-$0*|75HEznm3)3ra34aH(?NC7R6Xq(~T5<4Kq$GJuS81*%!efYf{g#m9@T0~y -z`$bC3D4o+f!tZa+mC6CQ@<^u=BJ}cc1Iwhn_E;|ZgIJzaB0Mbh{+_e=65}f?h7X$K -zj6n(q#os01&#PbC*_`eeipn9*3+#RRXis9^H8mnEccVKzrn^3ClW@p}&bdT#9iKp2 -z3+MZ}cYrmK -z00MWsvBq*}6Yi6)R95oY^>QWQay4o>I|*AJ7ZtPU~jw_jDFnQIr82|t`pxrcE-35rH+MB7i*rv16ZU}EB;R%aDqXO8KWA(sGkF>gqP$q -zxX{@w_})u4@uR5Pg5ivfA;MMq`y(0S2H6c{%VANH`1CnzJW!0+iz&g9|!Bkg@BswzZ%+W7i -zHd>ak&kdg0a07?wG8Met-7Z`{hKgIU(^ -z;qz7y;_N(%UDPob6f1=80%4n9coNDCLA|B)ePjgA(A_@q_Q3_z(+!vR<{-rJuOU_@ -zoho+tb3qrra7~@*p7D8hx#|( -z`XOC1UnB&VobcSISTKlncRy!Fe5Bq%Hy!p1QF3b9(faI>w$smEBKc~R- -zne!lanzkQjILGZN@$V)bjvW+E(SYLucmigFkT3cH0rhJFh;O791wp^g-C@#WPlEts -zl%}MitvU>T&vsexny;Zx8$I+nz3cGJRU=dqueL^~&GiV)aMuWlV*;R46f1<(LfHqf$%52hvwYUM(!- -zr-SXSH8^yv62Xo>5Xpe{4hZ>NlMdnF>csF)Xx+jndLPmCc^y9$i^InQm7@H!Q{>LX -z%F>gP`}vVb9GZP~*5@I4x#(TS$JO~FEap05;^T6sZdsCh=GEX^gOA7_l1xnNle2)A -z2%vb3#yvUjFn)P?^c|DjZMG91%D$!29=hPL->D0Jzrw%DKs`pT{%EB#6#{yJR?JS( -zm$@oHYJOIY-%l$EiB+rhGOdPF@+TF+atD%*j9p!vS0MXYrt -zm(SiOA6Z7^3MRTZua&#COoP(l5R&VwVr-@C|?Vz2`kmSs=9X-#j32L -z=BZ|K^PTD4`Ojn~^57ge*03z$ck9hV86QV}wCmD$jc~=1XAb76jhG^5nL1o|C(osT -zo1vUuaW>hGJ{^JpP88yS?Z<-%)fJK@7w?6m@pK8}Y_(__oFAr^yc)b+pdn -zU_{?o)he~Ox^DFx*UzKb;_ZSh1d_n|OoLc4cj&xIWNo7R_@FgL_CD}Aw>NvF6{)%- -z{T_(9y4!PM-h`PQ82_Sai2<3vMl0p6C-Xy`(T)xh5q1E5YU6QoiF=v}NiKA%s`{H@ -z2Vn@S$jcMe>k*qzLB4u~b{q1G+`nwSZ?08)r6X=E!U;S;f;40sL<^5X=*x%d15vg>)p7a~4-Y6Ow -z{y-3})cO1-xW^723`0-E`=tBo@wAag#_Y)jP%od)vY~Vie(pm8O7Rf$2}3s9&r|5Q1)J!Kx48dY8@c4EtQ5lIvhlJc -z8NFWXoWQ+FNgJY*F{L6fdD%-*FnYVnBFH| -z95oIZyKNK>Zd~+>Q+A$cNaITw0q}G+>07tA=H+>RK|aHqsc8n;h=oMIegE- -zN$4K?HoGrvlYyBPSnE?V>=TOL_o=%H2uC0z@Eiv5Q)Rg>55-cF5oI+7&Z(zF!LLn4 -zynC^jnnapw#q6JofnysIho2ZX_r5sITJ%=qd~?E(7H;h~pP1?~x!t{@6#aFM@Ubp0 -zck(ELv#h#vR0{Hu#7OIz7egs0DPlsyA2E|ozsKM=j|9P$rE|8lnD_QPC44||nZOQR -zne6etQR68Oq32e~{dqKo+2x~8xWBZXz;UVFA1dYL?IIz@U@xMZaFpK#n#y7E0ig4$ -z3IG+$Xxv%2QD^Uvd+mHo@MsKs^A)Jf@{=#;OdL4)zQn5ubs+W!>ia&(OgdZvk>^-Lz{0Jp+>;NjMnR_OJh`c -z>-#j-%5=x|kq*zhPv%F^FDqaFrXu9Z0i%+BV(yh?BslerXWLUOPiSt`XBDB3kG>90 -z@rmARn$>3b4IS~bfw%YaD(FFv3D~{fClG~hy3O20j#B{2cgT()i#{5COAQHk!XH{b -zyr=ibH?ds4CbocAS@v_4+#FL8MN~WWXp;%FZd_m;i89p3y6W7q?=rsD -zs~VXM@FpB!MIgZ3QayP|0OH6E9Doha8*Oc}Cdm@B-`LnQSNi?$m)b1*B`Lq{fm9D~ -zXo?J!*|VdgI%wPS{&U9X3Z#U_Z8I^dlku?V0$Z!0$zVk5)n)+(V89#Sx6(Ttx$~XH -zoz>I+>Su`Fig30I1Q#7m4w;KYG#_(?R1J6vmqrSGNu-P_p%JoQW%b%LFOtm~i^VQY -zd0asmNTpZcg0#5<+o(_J*ne=4{f#yfDA1bakyI -z*ZRr~4o{rnZy*nx&*jC*4fWfQ-GO=;O5;G|IhYI^Z12AM6hX)TN7N2==iLQ{_bLmP -zrV->i5_%A&6~>3U6=hk(hIAJq0G&I_IF$W2^Ri0f8PJ3@*5Fp!DsW -z&Ep+);8Vn}?zrWomrKV$h`&-Bs<=;2nd~5#P0GN!iXT=wVQ%@&#h*$Nn@6FlY@m9J -zrqRyUQHwb?c=E)#k=rJ&3NABWfihVpv2q&ZM-~RvuYQ^8hs1yfxF7c5Rwv9_#l1W) -zlIIAgJyqXBGMjV`+8iJHre0&)V-=1f(`<~4!!7nrp;K;gUO#E32$i+kPaZ+E^5zp3 -zVeG~0w&$s02cpv$9erOpwms!-timU}ykK&Od_!FFti0SFPIcKRlFdpM4mm#QxMWqr -zg6BI-0eXb_;bNrYp(Y%;=45dKFFkdq$(KEz*o*VIJMEr+B#F*cn$A(IbBHbJm09?v8BfnFUunF2 -z9sn{wdA#w`2vyBzoqYtaJ_(Qc4FuLB!t_MeU?86oLOjVX2_$wjD2$(MZM{Z0k|ILv -zM{m`XB$~7wvG2UXYM|5d*RP*J!xXTjcNwclFZ!e%lGB3cWv&}V9iPdIWB51c&HFB1 -z)eympjrxQ(7JsUlT%w*}sL7*xnw4JSl;({0t_F^UF)~}>{f6=K8qVP5+ybX7D(l&o -ztY=(GV=_QFJO3;OPJVDAE}_3i9o4OTE`2U^PgzR}S75&NcnGqNDsc1PEW*j=3&%etsH9IkaGk$Y`-yR -zae4uWUDHP7bEG=q;kOx{BG|JrdvC!O$XiKRx5U3mt=H)~{95dS)(!+*z2jIX?`;dg -zimfMKs;=4)!I;Q31%H*C&bN!WTFX0LRk<3c^2LnC^h>pHJqi|S)r>VRw!IMGm&)h7 -zSBd04Qxszwd9O6Iv7FM48!Sk~A>5gEq8}O?Xc7l!4kKOSoIYYJ^^z0Mklhm^VZj$) -zTH2?|#&tGAfaZo;R)9~3#g+GT(zZIL`%WFHCrUNdQ;aNjl5{wz_%i(#CLRzI1T> -z>HG&tI`=kQq@xrQyI5b8s9UE;@FD4vScwotud`m6BN%~ChC@apE#9fU#@PGTXCNr;~FPEQegA0EJ{5VVK$~{ -zfz&GRclvEoPN$nCI+rz{F%P!e^K=;n^%K^OZ -z&NQ$^eMb=qg^{;_?q%+SN&OA5QPqyr(&af2@5YVmQe^*K4F2}vjcT}lztbS;&h9TG -z)r<2d6r>aLh=rX78Q^B8F@pE6b>_Z~=XrVkrcCc)tvaI8za6Rd(wqGlUFlqsq4L;Gptt&>x@ov_p27B5yaEY4fYDY -zUy-XX8A)<)khBbP -zx~SW<9*eE!Ue*k+EeV3rx4?X%N=XNn53<26%er_(znN-t2q84Gv-1J5!^Gsq_#}My&K*nc*D|Bz5%0g -z*daS+_$m*cmu2!h*=j;@d2!$boV{@yeamdm)dcZPVa -zHavWqc*OV|k5~Tb^m}^&vIv)T9#6pzvFNdv96z_T{myacw9f?3Ir!dH%2}wG0S~O; -z?ysO_3fPne^5OEM<+pp -z77*--34vGh?o|ScM_#bUGYTIfrTCynrhT1Q8IbQuOGz1bU%9eLNT1;6>rd4qBpJzzsWb620=9hIV&gLb4O -zeGz)|y~~D%N*Xe|+ww`umZ%Q%>motBbqqceAoTK6OA$g{$3(AGp75-5^`y6U@45Cl -zsNh-ab~+JAx!)J~Q82nG4w<)?yF-@(g})EB8d(n9_QY*m$A`0IC}Exk20;c2N3E75 -z3}W=L&^NyvcB5Y`8(yo_P`u6eiEya`^a~*&_#Ld{?i$hQ%#g^(H_=BA`-2r-VMOy9 -zD=g+grk$8?3OL?SEM)+se-#9H2$8lkl6gF(+1sqwpCUL{Nd?@cIT+w+k>kPhbF*c{ -zZ~Kecw`7mk6GR<3-&XgG1GbUBLdHT^(ni*cBo=C`k>4l+yRrS4tc$K{4_rjxL=g~J -zpCvj@$Dd{nt@(~`w8!U>u%;hdVcF1OYwW4H=Arj!;5x7r_^*ldsdESveD78k@Pv7f -z3V*HTQxZvs0WP~ah2fL^Tw-l;jMxddUb?n1(@P8^nrS)v4S?`?&Uc6YPoImA@o38dJwHkAEdsJ1KV$Yai^WqM_pxkE`oyJ_;$!`{T64B)pof8 -z2tFp7uT|TdZk#K*$|yJdCZ$--VCi-+EvL&P*)8CS6gw$@_7fQWxq%FLsrNEHX!I5{ -zRWCj^EdEHP@@ejufV1#BL8c`MQ%L@5J_$t)_~M~0C6>XQv52(lqhl$igIy2CKGU|M -z_0wU$c{H)tW@y?dIId5@&(DNiXOtp3P1Zu*-+HSmxNu(XWuT{#!+;1Rc530l#pr#Q -z@{~%G9z@cD`1Wfr7>-b*TEe5&i~iW0gpQ94!I5vX>t5IUeWjoCZK9nEV8;|~lr-gK -ztu;Sc^->}pkPsg@+fN1EiQ&dI#~b@3)>QN>ncubo;!Zg~20@m0WeN$V0!KWE>a!7I -zjG8MC8pDWgK$Duc)C+tC)oZ=!^iNC3tB#%uO%~_gC$G_A>uZQ+f=9^0`ZBpgThL0} -zcuEv4WY1#7Jse#L5rEJF%+ff=((*U+0}qZeIvqG?#Q?ehTT~ly%wk;5k;8gEcY#aE -zI`|D*#nYh~oQDTVF28yMUMGU?sp#uxfQ{_|`IXSbV7{OK6AmLt^>AG^cp{B^D5}i) -z>_Mf*_qVxfo*nXU#4GU_z&+;$CSQDI@yRkNZU>NFGb9b-bvURDJ-!t$TyiDwaeVEm -zzI**rs_Y{Zn-lkCgBhb2I{Y2PJyMM{b??w{6?nw&o3e6;NRw~f^#{_okl=o2c5KJe -zubqiJCv}EdkxY4O8&%)iO5}@YuYbooFW3@=$9EohO=g9V&cU{=gyT+nAs(*Ho+_3F -z6DCm-ES~{Hxld;gjONkz-)X?G3GsKB;Q&o}gMEj{;rh+Cv)WE@)dYwty2xlARd9ZG -zQ3pg0+ylsq$#g-UfYK49sQGAj*kPl_#v* -zqpJtbF;sn}orZcDf_ninGblzl^zOl_SI&~}0JLBKwu+WxgC$;E*A_g0;d0v?i8E-2 -zy@8`P&|cD$YNpCIiTcdYzajD2=gyK{Sk}6T4p2pW_}djm?|LQo$hq0OWa)W&?P{KL -zwTka1Ly}{EAG<)3^#!J0xn1oP_$2!}6EAOA^2Ft+*L~mIVHDE1B({ -zbP}lLfv`OO;N}SI=fR7$XeO>hMXzw11=$_(UBOxF5DlWM3IX^MZQ{wHQ)HYK#x$TlX7?a-Vm-EF!xyT?f0+5!FOS^ -z1<$NaIzONi-zVfP#r?{Qp0X!BTQB?Rgn?sMcAxO+o-X0SXrG&jR$k7o;!wPJKqQZ(Tl0 -zzZ;d+Bi -z?!w9s$Fq}gazg+HEtkxL5=HN^Z*Hwb5CGZTyXVZg_I`apE)<``*nDz~B>Ee>GdFN6 -z;Ik{H)1yPTwKNy?<*@J6AKrP;-~L%TwH`Jzbf@jCaSj>$x}T4(G|@gCnld2Sc*bM= -zIMid%xiKu7rqGy@Xc(?s*ww7jVkbgO-t`EwUGpNl5_!xlFAQB9hVz;9?w6S?-*Q7@5d{uXf21=Yd>Ld99^Rb1nI~|BZz==IwC=0NtH@^-&F4E^%20Hk{8G-_ -zR*OFV3a(Gm>UYXOXueU8A$CPDz3_gMlOU8!5Eq+wrT8q4`3p;E{YE<^MqeB~#_Vqy -zv9sLc-+6I05IBkDsl$#>&6ga6uP@Z~9N!@YDPW7!tID>o;+nyL$xSmTRI-(uv*Hht -zpcqTO4e8bQ{%t4B4UTptUetO^52NDq-fGX}OX1wKHU6G*MP9gbMHbIy+98IWrxfC? -zjA8}#C&2m|Hdb9l=N4ijpMy0|!3DLV8oa!`{k?p;>>{)-{rOT5806FqI{uyUZco{( -zOK}hJXQ1)r5Zks34rhZfKljs

%y|=lM+9bx#X7Na5GWAL^|x9M}^ -z#;Z}xpTCQI{i!9GQx8V* -z1`*AB3UwbDCnCN&acLc^K?keq{wC-=O=xi0Y>g3IH-w((wLCfy51ZCe~VW+ON -z5vm)x;LM+SD5H^{d$lt0!Bj?RmxLPo(Sk!UrzU_N)=sFy!+_>o4$!!y3$v*mdHC@& -z?>>E2a_=|t;Yd9;U2m1?S-^7}7jWZ#RrEp0qV)A*7dTCM^2@3-hn;G(Ai%t}u1 -z9Bp3zCLt>$8|Iniau47`g_=%=6k_IuX>qAc=yEu`pz*pBZL~DEv`6n;R__AZ&sI)f -zKsCt$hR`M*XLuNQAIdKOtn#w@2rWqYO$fU0j|}C`dtl%j#{KwWN6*w-i{~7;_dST- -zjnBlt>pZ52IoqnP`bwkmtz*|_4K8Ew(=S@ZD&yq6)gu+6CZ0_3IuZg=Bkya&EW|>eJc*zz#fEtwvo9{@>8 -zen4dS9ksD)ZA!4Uxp~JSC=#b{2qrcl*&!-g%iW{#4f=3(A*wNc=qL)d@NW}JC64zV -zKX-A9C64QeIe@1{)_IwqOuzyl&TlrB*b9L6+QV?a&Oy50na}MAxxAxLU30vijA`t2 -z1~^yPDk{IZsPwh_y!W2KobwjU!krWdk(h68Yxs33^77?yT)jRk>QI70l<4gAmSY37 -zNP|AqOFna6HaSI5FFQ4Y#FeYEoViPv!4!zUuinW)zP@g(^>z80ac;ntv~88!qs?ri -zUbDTu#e4CTCEQM2N<{&#)Rn#O&70fK`V|~Nt$<1nN!ufPZYM2eDnB(8{GFqHKQK&S -z{#4-g_khu4Z{t^(RIGOHC|uv$h4s*!Xc$KcF34s5N*@k~-dnNz6tsWc_M@wnbd5{` -zPVQr~_B5s*`g#?Tp9ZBm=dBr%lP~r;O$9{+0paS6oFKpc>32zq!6g!oQA;xsSWrw?#NV -z4$yPkKSAj#9DQxe1)8O%|&yMp%m!jZdB&RILHS9*z=WD_S_aqJ643B -zHQ_Ft#RgAIxO%#-1@bE;A-x%3fLYPKf%hnJz4d!1>T|}Fw9i-a@hB+V2JHhk9;`a+ -zvHNY?tjv5JZ*StKtA=oG>jU -zu)_pR4Ty@a)h~(N!FzHezbT{FO|)#^m4w`|cS4WOdb(Gb)o2c8LYx*OG{6^fX1%zXTDS0=9Z6@i9q51aW -zzn%bH)q-U1@6(QYU(Wn|hcDPSTzgf!(_^CK_=|NnrOKmM%#NZr3B1R{2ANBIR94$X -z8#v;K3_tMX$NvS}M4YUhC!bWwIVFR1xOn$z9E*6j2u|k^U-4`rYx7+9JymK*d|%{P -z*`?J(9it2y^ht3tw6Gr9P^%NnGCM{V1R?foMM~{=o7WSd_h}`Rcg;W7M_h2-IuO8N -zC2-SNsRmg6Mc7gIy1>XOOAjj0KL2i;x!l9XU|ks%^wD`e7Kf93$}N>3>^)407?C`^ -zL2IhAsn!&7WBGq7YfHFT?{4+WqCBi)4S1#tOV)@dBA -zGd|i__jBiq%Isr+QR0urDPNq6Tza`$AT!O3{3yvOR_)?r)ECt?{DutrId=r-NY98- -zJW6zcv(B;o8Sk|zN+Y~K;=KWPZ@p!(A%|XczV}JqY3uWK?!z~bP)!zI&I<|`(y7Uf -zL$7-4eexKsGJ;}tT5^THbZ+nF@H(K%P8~TnyfSWGy%py%Y`awC6|p@q$ub_!VE}aH -z;$!K{y5L@B+7lQll_71uXX~ZvC9Gm#Bzn=ltpVIf7XLX$zBR-KYR5vYlIjEf7zPo9^v(vxrlEe -z6Q=pn@dhCL+M@4y@1cYR`nNVkb~M;plsRuylr1 -zF5t;~lX}IEFv{Xu;#0vrkkt=vDw=aE_Bi2PwDiF|+(d%l=F}mCO`J3IkW|jO+6C5GW -z)0x$NKs@(1lbd`uK=9s6otU{%G*2Q>`b7$O@%t1m4BjMq%Rb%(4p`QOGjaERW6Pv3 -zfaVK2yqOV+t%#4;9xF3_-gH_#Ew=RCVFq6DL$>UedlZ9v1Y`tYlAIZ~MHoBS)XK(mn1J -zv~?X;R>9h>iWVJ(R`lfB{5qJxt>p*W8hI3 -zbnC9~d^~^Zfi!-xj>rWUo(l-Q-nmRFV!B8w;<}WJ^nM} -zTcLsPU+12~^0bY@ESzs-BuMj9$K6Q;J2Cat{~2`(fc>~R(t~ys_(0z?HwSf>4r!MP -z+oc1KoA*5hdnnToI{qMZ8yahFpLZPe&(Pof^1-`~4 -zIj;`WS2&V-_?ped>1sHyGO5-p~|LBm6SIRMC)<@-P!Djmw#YlYYLp6%znQf -z2TC86<~OQb?(1(&pR2v+eqWM!ch4U6n)9@cVz6maoRq}v(P2Jb -zBS?n?l`K8XsA`*KNj1M-eb7f>hq~-ht3e%_N@c=_@m!AB1ZvjPNCwLHsSo0Iu*EBVd -z`QZJI!&lImN7^N-{LQ00C$8MLV2}5!P^!58ork`KDSd-5599i0ZW?G$(-vQcOqOjv5o

8Q3jr6~N?C^+roX|I4W|h1XIZe(S09C3pY(SFv7cX4zXzJuthIbijs$)! -z-d7$~MrmsD`dL|^RO!gVBW#L1A$||^3Vo;i-(}#5@W}LC6@I)t-jVqmelwV@DOp|D -z8A7Cp0ov}XU&pf#tqFVZ?1$C!V~} -zs*OjCbLUlz%4)uVcF$tY@r1P$D>`=P0$}RgX*9wi6$kY(d9T_y=_t+dCm&AjWf@v1 -z1&1ypLszfzQ>ITj&D7_haBXY{zjL+;r;dn8M)|?K_bq0ivuW3c{K#Jr2q=NNBXxSaqtJkuxqq7wS|mFwar*0>3^#Ag8RS8rZ+S^z`m -z{`O6w8l9@Op;iyhoHb@laQg=D#qBCmDHJ_;Z#-pE#~~{W#|@)t+(vHGTlocX#r*h% -zaCMgp5HFWiW=xP=D#0heVV2{qaJ%6SdR|%R$A5DxJ^YY7r3p1X@1LJ#dsSYydCV`k -zY$b_YWJz=Co9P<2mdh_sGCSsllRiFI&0iR;U1Qgm@`{}&#pgn6P$qqahx3E58mQ-5b@r -z$vHS8IMy}|$E?8_`8$Zxh3#YJdLR#Q$ae1Oy?HKJ3!w=JgC-1O1Q@)C>Kx^<|0ocD -zZb)%6v5~O6@I)gNuhHAH*b3f;0f_ -z3$=dBygbhoPH5(6K*L;N{EX8-Yi}e0KKp&Y_)gL0%|&4dUp;pqWx|)9{D!)waSZLV -zqk6%;-+4B>WPzN$HzXyQwk+bpkt#96n7e^5`#%*}JcG&6!{`(%1V_Tc5!0s7NKMa6 -z6VChe{u#<^$mJ9VbPk*8a?1tGbZ!cLs}SMyPjQgUuNTo`K}Ek4d!B6He&)f4Noqnz -z`K9SQ1yIRt`WT|GXo=hHq0sa7gMmG24zC-OJ2=#>!0m52cinm-Mf0B}0?qEDVe#X# -zcdO~5oIHE@5PD__uvy!y3(SXJuA -ztbb?oj)p@Roq!h;1DC-`Yu@ec=N!rTgiV`ynT1v0d%$0NA8Zx$Lyvgea83i&+AE0r -zkQE?>l}bHI84oeb>BweRJ`(+&?y;9AFlS4$_{_?^XMq;*X3#tWStoMx&o4TU0%s7g -z&?wzz10#V0yNX4eXRdiKjeU+VTHm*k2EZA0eT$A#>8?Xuusgpo>)#}Vz6N2A=yH}X -zdYzg{uM00M6OjtGx-Su55U4Y*QgQCg0WtAmz(;IQA{88;v!vhLi?-^=OPYuMW#Oyq -z)_Jx~7I31nFe%SX731>ZJ~n%G(Dq|T793^w;C54c2^vq({czGdQyZUHQ^=4RzjBD1 -zrf&E`;6?eWKX@Mp^sP({F^HVp0u92h6W^~rC16I^YM%zfIm+b!BkW3&EXh^il|al( -z5ODt^eN()@%(hzeqRpx*BNYtpA#hLKOW&t$LA!LXI9|U#*@;(0N7QQ(d{vLzmTEG{ -z6oE~r5M1=G^Qm%r`@@#Ed|q`5Sz&NpHwlt8BfWNACi5cb!VBb96LS6!4iSG|P2)pt -z-yZI!WTOr4Vowe@_k4TDVGXGdmG_PlSM=t^956LLFT0PL;JL3;JdT+xk_)e1Y1Rhk -zokXA{`UcaPUDBL&%X#Uw(DUl4)Y;l|4B*^(^qi>51}~2Qh}AZJ=G{csZdYhz#2o+R -zk5(X&3-lA^5`gIVd^T$0915|MrpGcboUHMsp<*LOThit}0@C<6yV$oCzInE -zHb=$IC&C?@hacRcp$BC6(}4E!&&_hKYC6E9Te^h1y`N_6jVu3b5|eVE>`ubxNV%B9 -zZ6nuVLXhEMU58d*b_W|^@Px)!=A6X@$VM<;IUxyQ-+!jj?zWDPI6cg6Mfjw+DA%pLVc^7;I6qz_0c9Qj*@57pVKTQ_}nAQsdiee%xTTkMbTA1gX;9DtAitR#V-f_ti{ -z?6u!h{Xm-x-V1gW2eUsRZK+SQ;Kt`=c&Az~o(AY>qAQ&jKWQk0BiV;7yyy5QMYoxH -z=jI8yjdX-bZGmrIJFnTpj@v=T_Yi$Ma%p==PixtQ2rJk7?d=>s2>ohIPuVp|nu=4y -zD9ZxhnP=j@2+Qa^<0ZD|5=O*2-t;^tNYxpM`cdnxxpK~p^Uc-P2-*+qO%3r3y%ffmN<1- -z&*Z#{d0%$_)g%J`-i!8zeeXVXKG{qKpHw@;{@T_FrZ#lDcNcs)7{9yuk%t%_QplE> -zsyPLye2QIf?xV5i8m;)n;dwN&(*cDzddKJVV`@71fq)SDjEFx&;{wQ5crj&}+nF~C -zR+VxzvseV9VTA%y7$13O3m_h&)NBXIAqj`jTrgjxAOhrvf|a@r*U2@$i_?7c$tG|d -z2ajJg)V`E=hrqec0UY4F4xoxQa~De)*f^zG?!H)l_~sMDY7nV_@HqGz=|A|XLHYqo -z=cCvMpbgomjop{{7^9YY=>42$MD`GVO3Amb>j0x9-l5gwF%t>?>%#kE@sMlsfEC!-BsAb)aZUkqkDJ@CfHho`zcDiX}}Q<`D_w<?eHkx%tx710XtKLrik-MLS~;W`(>ASvcg`lx)1+**dphlpj54 -z&<#iZ=xW?=2K9CQ_zW-?`5IkaM4pzBHPN5ifaRHczl-F$l@WA#@MgC5E589=qJs?l -zXoiC_Cilx9_J>bif3TKMXSQ~t>(J0`t~pe`>3o9#F~nO;+}~^RUZzjCJCW|ZAiu<( -zat6Rulo$Fs2Z*NvBH80q0c>9UkifT+(NQw*!Ga+nl&W~!@~k*o%{PAWehr0vY{ot5 -zp#;ebEGO@yEb}_2%)u9AKSy=*3a6Sy?ZF0TBjMc2eq<@?&B(aGHjtKGVgB -zeq;q6l)aw9v;xyQbwMO;AK-^iF00AQW;z -zd+`t>xSl!4=-~Go&azUtd5>0w^Fv_qep}L6bKs*_*d{owz!xxYecv+u$Rl06av%dx -z_iTBspvp9!Z-vcp==#jmVohDAWh3O+eC@d{ -zbcgQ|y@5vPde2eR*gaw)uW+Q}g?WGPpBLAs3oU~`JrB%yFH)RV(I^6soa0(oAbgOt -zk71~W<%~m6+#56B{nXGw{}{VE?voW~+KAc^}irM`1T -zttZ4<KCq47V>xf3|Rayb4Ps3dBRyF-F^g7C*yIIarblTJmhz_CW@Bs*7OXXn8(KW!KFN4 -zd*jm>n6fi{AA-A&e4`M58bFjO0(JfFde5UThH@7Dr8z2g!rlN0M#Tjx*o}?pW?WL} -zGGZ%u9C8OgWiInH`z{n7ww#9;yIJYJzNsUh8AF`<#F$_E4%e3?gkeNfJN0GsH-x2R -zU}bZG&d|zzoJJE)kQ357I{i2npXIyy%3C7mz&ku4ha+)d2@NPvLrIrp;iS(y4(37O -zIFs-~=jx$21s3ueTC8QM=M9abg3x>L?x2MeRmzr&nc!tZ+8f7<^-z}t-C*%d`b1?& -zg9hxI^aZieThBa+Cf<87%x_Nfn5El_R>zk(DQu@8Nd -z%t(TC&bj9_g;j?r$s;uEskQ-wWt6$MY5gGD0;;OmM=}sV3cXX87+WV`FWxSCEEe`v -z$0qg@JOWrsFLMXk81|G)j+}@G!U;cRzm0(WY -zn^i0@+{_u({t5XP@WdX6JPBdvGsGgn09{!+J@&AjjW2K?)5rJDH`sQ%y!0VaW8gHh -zL-~CTm4jfZoeB%rW-~*m%RnhSUpC3ebVpFU0+6U@heni7IEC!(%<)Yd%K*pn`QGM4 -z3=<7BGrcx^CWeU2Ck^8RF`vbe$3iMOV@XRJ&(%3qU{oTaE7Bl1@A(!RNg_x*UagvhBOlbJEfG3y>^I>wKo9<>N6zs;y9>xDdJylcw9z_S=j$S;E_+F)sonLXkvha-fMYhR -zu|QiTdVNm9jZcgMw^KRFUJKK!_H887xk`l;h}VH$)b?^&eqQ9)#7jy-$(t>rtu~^E;P3-qhrtmjx=UWnnFb9|RI1(W1f> -z4J|md6j_!fdp=jn2X?e>7zI^O-9Wj85|dbM3CYN}URdL+oU6V9{b^0dYY;ppu-0%k -zQ@r+{0vrZ<69v@-tywSIYw+;?+Z%lIN*}8DbmjTZcU1#&vdC_zjaahj=Ap|?7ZolW -z8Q#jiV9DMO;lV)p9WNrgdG(C(Ae8#mtxw&Zj*m`lS@#vfSIb_n+8q=sUj_i1{v@&a^F?dv0eD#b!JEQ} -zY_ZjQ_^jPB`)G55HoUA5&3?oH=9@g0AQutS!fVN-ULT`a4uep7jU|pH> -zyta+daG2UOLfn!+RV1>JgNM*<^AGLWry6D;JSLw&PHna~-sY -z->l}kNZQSxg~aU+I1Xp(J8qPFPp-1&tdcrs6-8BeexjUZYI#46*4wLu4FXVCv9F)A -z=L)wy26W?mU*`xRKXD^tf6!b+dF!D8irY=erxcJVYLu%wxo8bM!T`29MH-20Wr$Y3 -zRl%^)n+Ltm>&|94cjs6gl~3V4Z}i7AbB}%Y--P~xEjjFt*&(`lIRjbeH{TSbc2b0r -zz7IDKKb39JzTZM|D{!T5dUSEip38pafV^0lsqDWt9mZ{BKej+)B%GCo=6duwmQ -z47^|;4SOLXVHaxOZ~lt<_tC}yPL2=7J$e*(drll^dQ4S$Zim -z>E+x~T5m`_9OH&3&oSJa`$49$62$tawrhUc*KxV59tv~!4Y2bWTg9jQ;4$a12(W+% -ziTen|E+AY*@WX4#kxe%rU;>W`$~G{$7^*;&B{Ff8z7?ew4W<_L9dNaC@Dr8cGEUl8 -z5}6-jB&0ksTS;pB*a}mZC&95P?i4a)io5S9aZ1b&4US%;3-&0dmbxF$y!zRH$eweS -zue`=}Coxm$G2j>J?j0#L_a3FPTMGazWFGi^o-w=U93J^>vHINV%irZ5Ko1NMXmLc+ -zJ4hip#_$amHwQf+&-%Kr5%cYfSoG)v#Upc@?;mnA;N4cLc|m;YK~*`rC8x8y80XU) -zN6mZEq8=LijquFz!-L&W_XN|%p&${+)V?N*H%w%tef@<=*F8w#@W@`o=Zvb&E1KEl -z6S(i^MzSB+qtGUw(4E!1etOpA5N|3Ojl)4kTHwgRGbVEqeh74mu -z!6W<)c!c(Zh||Mj4_XI!e4^H&X$jv-g;`41gV4!*rY{BK(R)^{usES-{%jZg_q8^) -z9$|M9?j;ynH%Wc(>MrpI={0>YOKqd&3cF^gpKk;TUV3_fpE~&%qz&F>^x}s{2eR)& -z_g8ZqL9V+`%{w6_kBu&MSoD}*Q(!=SUZ{p@m0DKz|`@tgBe>RN0k4P@` -zV|x|oYG>NVId?XT^0+zSZ@@FI7%#-5jiml!_= -zJPB>tDV}iZ@g%s%v^VPnDu3USD?7e>Iwj*QlljC(&%Wwi=lUXIvVvZ}a@wW%g3)%> -z9@* -z15uk8*Y3zs`IJ!e42j%#lsE3Q3PTg&HzkFyUb(4{5gYI+QCRijIcHvJ^%cD2WU{fz -za*-$lnpYR?w$y&2-Ge|6+WXpT?Z$|;4cmEW)E*!7hmVC_YLDTAEcH1hp7PIyPW!&o -z@}f*&%5Tr#_eJ=QYdZ5@`}|#-;=If{pA&B)*6nXcmuh^hZowx`r|#(f$j=;egB`mu -z2DDSMFt=}xr>cIv$B3n7vw}YhN1~zUz{L` -z%*P6lZ6HmHvJ5VV^Fn8$glNJgD${W$@rUwI}Sg2kq)seyR{9t1_QHq1=?# -z8?Q-!cE(0fN4p-aCuTFUdvvqGBNMV=2wti8TFAQyx*qwc>SNW{P786U-v9#Cu=_pwX5vP1Q^}0++~cT)qsa!icV~9yO1xL%Rq}9Gpg>aKdf| -zBJ`o2#kTJo!|LU8KOrs$prWL2M0EN=hdLZ4H^e2(gSU0gWjwd94xLF`3P1eeRbH-U -zjh=~YgvYL@GLP-hx7m>*HR -z#vtb>1ohbdiwU&+tgv1|n>quZWL+j2iG5N?ofYSZjR)Pm6Zvd7)nQz^b14iQYNAKPLk(P;$)=*I`xFDIvtzyN@hg%beMPW1J#c -z7cgHUlcUG5-ljXE3$Hl&L~;1cRUe=(+rEKjhoC=;RF-5+1Lftjbmdse2piQ|^~US< -znItzAi`Sf*J(u)Qk*DfWoxGEDZ_tHUzAO4!`J2yu?NfwbJw-k{OAfj6p{BU6;`1iz -zr!H#`vEZ#o#;(hOX2t1mg6ACX6XNziPAr>x&!KX>Noo=MDc@` -z<2bE1A7h5lQ}%tiFpl4L*$4kRDfTP!xRya=jKt1Pr`e*S4qt*J1*Xyb%@&;<9)kWFsowXqJ3XNE%IU0 -zLO<0HyyWKxtqh4yrKrIK*uYonVffbI)M~yLzK?=wPb!PVl~4cKf&eV~)g!^W -z3oxfpQ!fV^GSNfbz3uR2y}n<~fyKMcz@zNN`n})obH%#jb%;tT^RB%3#;nQ%g?jvYPX|{~k7If6b{og|3t$T6w@!)&xb<&o+ -zeFE-r`tFxhFZlxXd6|RGnK3!JKzV!sA~6TAnJgdUq8u&Zz#9eEzikKjEbb@x@~8Kj -zm6dv0r*TC-zvjozu2z_NygHJNsre8a(4z!l%EO;5mqX}K6WU(OT_}sfd(8FI)uENK -zpYz+@b%o~Pwb}-;v6QMKFDO7WB$1C@j^!DPic4@ -z##x*!+3CX7UZ3-Lj;-OshOxA`eC`WCB${wvO2r|6#g-u+%B6hhA0z0*k`fer^-GpPxjsd3PD-aN -ziTf=P%3}uxODRj$HLk|O+WPv&>%t!mb8ULB9oY@*q7O3nA>xn6oJIatuJS{08M_a? -zg;vvMC7cKg9#`!08c#ax=iFERw%%V`?|6NX`oib>D%#hWZ}{HFbFaTjwx7qGkH|W1CRE=OIffb}t~cDiaSbCeWzOU2(c9hRtDob}CrEt; -zBTs@fqy619{=D=)p}}m8CLFLQ^W}~RAopvDqb__y)>|P2YR50sc+U~OpL88z#c)qt -z^&8pCG5nGc?{R_nME6!2+}?>%FFNCrkun$IJTTeO4`FPtrP6!SR8vf% -zO+K66UG0O468CirFCkL_jE9t89>OEncTQfh2l-Ce#*KIo!Ki5BC|duiInJCm)vFQ#E1{S<`oA -zaLLYm!k`B&ud{SW1*qgNqjTrE?^w#qE+@W_SDkQW~FILifvL5B^Bgg -z(y%GzWlgSf6hi%6#zLVap8taQPghZ}S`s;gg-{dw?{B!IzdRi-ob2(7-8oDz?0TTBr}QHc+Ls55w8~3na5)+QGp*j@7>LBP4Z!u -z)3`uhN`3Y`G7=ZjuG`_q4JZuCZsGTp^qd9+cid4`VuUXGNdZ#nNgadUX1{00j6Q80 -z4i4s0cvy|+wEder{V2Pk5eJSe$lN9vIM>eJ8wL@T%h2 -zb>|8^C(MLSwc(Z$9{9Opi3(~TeR(1hg&rys>J?S3LhS6S&Nik;Ps6=6<6H3hl3#}M -zOJYa92@}r4C~=1EQN3_%I(V+09Gmk3kmFC8@vuLyzwNvhrZ1v7&owU$I6OIb#l6(!NKc5twTL!VmpO=L4h4pC#{tD43Y`Z3=D2Q$SlP -zf>#;A%|#mo3Sl()g_@P0e7v+g?u<+DjlLLTv9m9R&gbKJ?BOt=f!!B}uBt4kgLojihsEU0`bOY2r2!OQG@nhV@slSqksj!TR3qIQ0( -zND4L`77_grVLkd~( -z0V3QGyK?7xvl5}n=bHl(&|Ts7U?3e~>xip?Mc<65QJha5H(!nbl_Yoyv#?jqWvLK{ -z9=!88BrRzACsCYrYqjMUF$P57Hi_npyNK^r-Xf*=5x{i|U8kRAPWX;-mE-&P}f+$@Mt(-fhU~ -z<>@25n^(?#oQ7ZhoJE;M+?;rz?fT+9=%4j<3i%1rqzOc*`(lM3k$M#FE{GMhp^oA~C=+f-srR#^5p2K2cPluOZS -zo*PStmn-N7o_GNT>uw+IRTd2W+$kb+9>g$wFHrF~lIB3;QEvpTdKfObPZwO7E;Q`# -zLu4<1JZA@9mpS0njT8G(4Ua1FI}mu!IhPVVeDS+S#^yRsaP2{fOLn&RBtL{|#p(zq -zNUcNJpI@lzIp}GmoJNmDzG|j%?ou!_9iaZr4GK`s=*1&Z-zy-&+@M)NQ?6lGGKp!( -zx)~#JQvrC-h>_lEn4TJ2!{KIa9m!Ok#w6NVND>^hoX$2s+KPo%Z#lVI=T? -zLD6^eh-9yTzlx)L&dES@>pHVL$zq2d3S`m+yg{7X@4NI>ucXkMsGH -zIJ%8&T`_Yln@2!G@!TNoy+Hj5kJbY$YP6`J)q*YisY!BvdqUGIvE(v^C-9Mk+WGc& -z{<+FWXSXgWoxtjIL#%IKQ>D|5b-#t`n^!o_Lt19-SejKCpDQa7%sMy@>SqI#D+dNo -zkv|~xDq~10HK~+Xng%ytfrld^zLj=TL{0eiWw;F7AJcPhu3Q}0+t>NyY#k3|zpAUC -zi!(>=7%Oh7yojuxx`*>2io8^CiZxzqkQM4+$F4cdebvhAj`O|t;vA{Dtqvn8-~=+1 -zIh>9y!xQ8aSAh7=qzRQ>vkP7q-`f(zX((<1uzEk-XG}{?$|z_372u3}TP)^yg0A~w>?o%>D15uFW;NzO*8Z*tMH5|Zasx-4x=EnN^+hySHaKb0lq2!CM~(VG2sHBaIeHpNqOW?-AigYZCpQP(&6&!AC}e5cj^i -zM0mE$A5}0SUbo5g&#wP7c+v0(ojOP+Q>S=V=pr-V0qZFibqXKpj%(PuMEJr!Fv>;-}bR -zE^_pqBsbd0OR0RSC{{?mS)C0txO5&o`6utFJoWH6Ru$`ff{d1~v3>0!O$#*ep6wNa -zzVQ+*1YvK%$yqThx-xde+qJL5biKlg%8UpVCxcdwcc+=lhesw&(KL2gX??00V{Ukd2j%h9&thd%d;L< -zOABxgmeM43dq-n8DY(R^FMyBRw`h}2MI6<2DtmDP4r?h4a(i3>Ext`Vv&Uy1SAT?m -zt{4>QUeHhIK0qaGfsG&hsIYfq1r{3xp?$4tUkVY+aE+{k8elG -zE4~|~7`7wv>ita9*42IOOseRZP8-5aJf3vVW|Y%w=9^S_UW2(@Ij;l+x^7;7KoB?l -zI`(UqDoBGAtHQdVGM=l084~gkJsfF2anN)<@8!G?LlXD}?~;SE7eKk~SnMjQ0MVo7 -zx@8xkR(kH~qajcy9|yynQ&L$jO0KUaq8;QGCn#%~Bk(u}z`Zi_s+uVK=E*Fbxun#| -znA`r^%5;X`(F03ZrR=ia??d6ax4=#4Rk+J_H#(w*z8R1ayH0x@ -z0w{Nm%-ur`sCQq*nog+zc;!ao%8Bh0aTi4r384k8qcwZbpL1`2jI`k -z@n4p6X#~+dLWH1Kl!|X2IOKauM@`1naX#Dp@L+SP&K?Ps(~p+5Lw-tG&BFU}!R>6k -zVnV&+xTxq_I2CHfe^)GN}Qc_QX$=j-i{;8Rp= -z?xSGIV(L+GF~zLTXR{;QYjQ0i^}BL&EJ_juz*=~uAI>LM_`(!#w7AUG^GRS^T&<}* -zq57#Uv^trBV}%>5kL5JZ223>smtx_x -z+CN9vJGyXoK4E2HH*?&h*RFMK10z!zw3420+UQ#+Cgt*%$U#?`iM#RMl0zf6?sYtf -zsl2lp%edP`uMPMELK!1iL*Dm}oFn>u`j>oMtRL&>Mw5#3$SDRpoCq{+!*lNY-IRzW -zAuy->O0R!gl>I;U&K&i(B)Ru~t)l4_#GDb&iz#{V;5lsySwf!B4tnn*&qb<6{ONLJ -z2qd$Ls^7imoEW~J%ot?Cnu%e3)8#Y{dAQ9}W3%aSsl}fn7BD5L9&v@~Zv<4yf$TGv -z4j-COCpz&0GL7T6Xy?!;HxOHPz<|r2xjor^zcOcQ^C`J=1scWp>9nD+ -z9!#w{jf=P$cIt(1O3vq|9pItvFXgD}MWTE1emyS9#Vx$glzATNZ#WQgk+>_06CLTEhbGJjKiAI09N8)oT&+kkJet_v_|d3c9yh@UVoBY@! -z(@a=bhvR%3;q2>g+^SxtCV`5_qQh`{9cbIBu_dap_IW3~Oxl#zc6o&Qc6;RB%u -zPOIr6j3+^P6NveJDpYP?#uAd~ahl#$Z%E3k>_vg;XPE=$@WH@@BQB}K_hDK4MeTjW -zug?+Qx6;L18e>NwUXTUr^n@mO4Djt(UL9cCpsa7=#QtGFhn%43Gw?Fpxv}+-Vl%j^ -zPmyZ-lEgke&!neMKCx`wzMF-Q%0&sTjF27_>CudIh2%pu0P`rDqvbftiH&1*6x_Z; -z5I+7$|JQWsatu3!U!!*3t9652MR}uK6YsfwG=X9vMl=wn>19%o!ByNoKzrih6P6)? -zhSlZymKDK04sr1u$4g?^0^S%E$LCvO_M95E -zq2W|~)9q69f@nTVS0T^7ih_WwUj-fcwjEM1GW)hurj>8ya5)a!IZ)7p!oU?|GNf~N -zQHst9U!oGrb8_x;(aF2@RVUxC3y?BLU|-fcdmKDv#jfz8KW;(qeL2j)2q@sa=Y_qH -z=e}=ok7}HAy%2WW)HACIioRtc^Z4xWQhsHm(%andB;F$mdL($9*wr6ks9HzkJH$yEVO7 -z$M<-A;|=Icy2e40Ty8&c)|?61zcU;Uuy5oBJ+(0i)E`@(e8CZz=hXeWpd);ElJr8a#pj9b1HBQXyH -z_ipRcMn5JH{PDs(&yLHH=x(+8O5#!vVho)aK`PI9UTxzD7wo)@6YED_z|SL=_O)vW -z8C#3VZQLd1>{eWNsX|J-NNZm!Ib1`xomJ6+w$Btamp1N$eo&aB;=L%Twvp5kBx~d1KlHEAU8f=-(<31kX$E~hr -zFw5>@%0#hPhU(!6o;n?U@@TIG&HZ*e8iRA4<8I1f3h1Km{mIO%6R;L=S_@m8ek6mf -zEn6f5^HO;ig6g-->wUG+_L6qPb8dXohqvpAZ1xlT -zXiv&=B1GLTA~=5H;0zCZFdJZC9a-(6mc -zrhS&LKxTQ0Whh~FN7&b1W}5rtrPUL^p;Zw#fJJWWUM)hfc-mp(y2jTe!+Eb%$?>Z* -z>0lH~YEfksIwhYt@F8G+T>M-hV -z*;y$Zwa?P;Q^haao|k>>!7~TGTzM3w_-6H>u~T^FJ-e9|NvuG^#6zA@+G^w4>s -zc%E2X+_-t`%r@Lmx-}wd9eZxSXYC6q)*IikV3fKiA2@O3EY!Swq{Or}_; -zEQMt%{nk;Fwjcgx6oI-yI%{t48rfHdlX8S2zM^a|&ie#r;#XzKuu~q#8T-X;c$`gq -z8w&MV2#o8k1I^IF*v7t?q@~z-alZRwg*w-xZZTYqZ(i!%zL&>1vRX*B*v)T?&N!}| -zEu<{@%8&c7&eg$be7<^m-}iO4r!#stvY+w-V7u&g?!x$!yO&SR%U#|?U~SZLg!w3h -zAh@5?hs&QZ7rP6(`SSkGueB>Dj2<3D!l=rm-}CL6`BvONBzYe=6Svw6MUU~a9Y*uU -z!aDfSdE&c&n<-*1FpzN9?VMmaO~N+!GW9ulzhg%AlOpNVIy_GX19v8!HEX~34-0pF -zk6JdAh4(uxH5pf3 -zoafoR`4Dx?7Gvp@U5z5%cxjpfh3N#Noz(S=5_wRyU6~57WN6t;d95t_mi4z-!S&lG -ztMIrAFD!U23)f4ST_lKz*F)-#)LN2F_1R&iIe0{VRfZ^DlqaS)HHV1{j3;>2a-WRD -zao?|PmgId;lNVu6N%eXp1j$2dS$fp-g_EGL7MQaXfubB3~ty>%nJc2hYppoc840Bqu&6dy+1W0SwUX -zQq|pyqiFQf{&>)4wE-y>h{uU5vFxgMG$oWE4F)21=xV-jWa39tHc3d}xLWBn2Up@A -zykF-QqoW?m3D_qWf@MybE^Ml$D?ODYYpE6A5^>21+Q(O3(k9;~cs<$h98#lVA2wt> -zS!TC*wI=La50lUM`hwLSUB1MLNPfzx+6=vHCy&8U435jkvD;ivdB`>{9H`!hcxT$$ -z?laZ2%5yX8&GM0iy2rsjz){klM|RqGr5oOOu);6 -zpSQ;v3d&>JEE)I~rLdCV-m4u--x%QsH}N!R`=jOitteD8L?|OfW$f*~{%x6S{{}b0 -zulWs6IqpP0QFz`@fAk4Mizwbf13MiDk@wrV+`}L*ct2)+Ha{a{{%mPCFoJJT0kg`( -zo2M?YRcwEqdw=`iL`5#~t>?%|Llt0haq9o5E^FGbsMnH$a9w^9&zf3Mq -zetKVLIai!d^j?-Tx3&7-tcaphFPgqI#`=^q1GwLtz>nbysJ=CH2eRTKu!rmXs&YH$ -z3Gf*JlLMQkDEe>>;(kjn80+G_<3iIU**Py$OgP$dXmj-~uJ%Em -zxOb$xJaX0G3GS~y;es)qkl4K@wxRKDmtN(Zu{tvk1H+bzZ-K2DZF|w2BSe!qA;vwZ -zN+8)&!@i7R$d}_rl+7*H&R|nC0JEu=`qcf27r}cY4`V(QDmCNttrBBN0VFxMGLJ;; -z8Qs;g7)Bsn;}=j_`@A^$Yp$r;;f%fz45c|9HR7rf(~r%_C*=fOc!_K9KpE?VIvPJ$ -zc<@;#UjBX%0N{}q`6csj;+1ed5HY!Ua{DpSLnr{e>C^U2QLSZUzx=V~z}h9cW_Iu? -zLP9tyJI3QUy$>nCps1ceR4?c^0miwc@Dl{ZH>yR^|e1GPEnq@u&A1gdx->sUmS7DP<$b(hMDT=711rpIR=wcCWfyO(`Ofm7gZ8Pj)OS=C -zZjRA~@duT8j!r-4$QuxLX_d#vkh=A`ZJ{O40Kdm?x15+taabnuZBf0zf-#wy7_ThZWQ$2G`imr3!v{|8eNkUI3{Tl5t`m(xQ -zL_xQJ)S3JI))Lwwh5Ni{SccBVF?}ZmNo(-yxOmZrc!$BhlE!2GVol?cK93p4bDNYU -zm9Ca>+(RoQvwZAIt7&&SF`Sv$du;Nn+t@k_u6Ssf+~G9P0OGxMnU5(gO`O`oAlwJPipa1n4lm31*`g_)C -zY_=dR6Nm)4ST8qrb;dZA03JH0OLwSVD!Prsjxzdu><6p;S^59~0s;U2Km7mquYdo? -zzkCOBYGY_&O`vRH$6kPuqlZlYUJCuY52?>76;`ejO<2;pJ7yRP!KIKoMRJ$t8yJ~8 -z)TSieX!hgeAp5z}<=-C@1QZMoI0PgVGz=_U1Vkic6jXen(=jlyuyOEfTPCEJHieXo -z4mkxqS7{nrx(tl`RSdGS@%e_;e%IMNynF=&g@olPR+A$xAt@y-BP&-yQAt@vRZWk& -zhUN>_`YmNLFf=kYF@5R5+``hz+Q!!Ifp7mUf1kw8Iey~gsnci9p05<#>EWuYn;&XBCxI -z)iu9XxHdL5x3sqP`7bcH|Kw<-_V*o4|7K~@-%N#gA%}da9I|7G(C^*FfdegGzS4f` -zJDdoM82#43?S6}n(F6#VYC#QLeWC#x_$*6?1wWySd87rYO8SV2g+3E{jPu{jQGb3( -zaHgMh#Z|nOeYE-%H%>UOmz3)*oV|GoJ&>~9gn3NB`}wzy0;Me**vj|Nj910RR7JQea&G - -literal 0 -HcmV?d00001 - -diff --git a/ms_mod/golang.org/x/crypto/sha3/xor.go b/ms_mod/golang.org/x/crypto/sha3/xor.go -new file mode 100644 -index 00000000000000..59c8eb94186e2f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/xor.go -@@ -0,0 +1,24 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (!amd64 && !386 && !ppc64le) || purego -+// +build !amd64,!386,!ppc64le purego -+ -+package sha3 -+ -+// A storageBuf is an aligned array of maxRate bytes. -+type storageBuf [maxRate]byte -+ -+func (b *storageBuf) asBytes() *[maxRate]byte { -+ return (*[maxRate]byte)(b) -+} -+ -+var ( -+ xorIn = xorInGeneric -+ copyOut = copyOutGeneric -+ xorInUnaligned = xorInGeneric -+ copyOutUnaligned = copyOutGeneric -+) -+ -+const xorImplementationUnaligned = "generic" -diff --git a/ms_mod/golang.org/x/crypto/sha3/xor_generic.go b/ms_mod/golang.org/x/crypto/sha3/xor_generic.go -new file mode 100644 -index 00000000000000..8d947711272c3c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/xor_generic.go -@@ -0,0 +1,28 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package sha3 -+ -+import "encoding/binary" -+ -+// xorInGeneric xors the bytes in buf into the state; it -+// makes no non-portable assumptions about memory layout -+// or alignment. -+func xorInGeneric(d *state, buf []byte) { -+ n := len(buf) / 8 -+ -+ for i := 0; i < n; i++ { -+ a := binary.LittleEndian.Uint64(buf) -+ d.a[i] ^= a -+ buf = buf[8:] -+ } -+} -+ -+// copyOutGeneric copies uint64s to a byte buffer. -+func copyOutGeneric(d *state, b []byte) { -+ for i := 0; len(b) >= 8; i++ { -+ binary.LittleEndian.PutUint64(b, d.a[i]) -+ b = b[8:] -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go b/ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go -new file mode 100644 -index 00000000000000..1ce606246d5c29 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/sha3/xor_unaligned.go -@@ -0,0 +1,68 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build (amd64 || 386 || ppc64le) && !purego -+// +build amd64 386 ppc64le -+// +build !purego -+ -+package sha3 -+ -+import "unsafe" -+ -+// A storageBuf is an aligned array of maxRate bytes. -+type storageBuf [maxRate / 8]uint64 -+ -+func (b *storageBuf) asBytes() *[maxRate]byte { -+ return (*[maxRate]byte)(unsafe.Pointer(b)) -+} -+ -+// xorInUnaligned uses unaligned reads and writes to update d.a to contain d.a -+// XOR buf. -+func xorInUnaligned(d *state, buf []byte) { -+ n := len(buf) -+ bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] -+ if n >= 72 { -+ d.a[0] ^= bw[0] -+ d.a[1] ^= bw[1] -+ d.a[2] ^= bw[2] -+ d.a[3] ^= bw[3] -+ d.a[4] ^= bw[4] -+ d.a[5] ^= bw[5] -+ d.a[6] ^= bw[6] -+ d.a[7] ^= bw[7] -+ d.a[8] ^= bw[8] -+ } -+ if n >= 104 { -+ d.a[9] ^= bw[9] -+ d.a[10] ^= bw[10] -+ d.a[11] ^= bw[11] -+ d.a[12] ^= bw[12] -+ } -+ if n >= 136 { -+ d.a[13] ^= bw[13] -+ d.a[14] ^= bw[14] -+ d.a[15] ^= bw[15] -+ d.a[16] ^= bw[16] -+ } -+ if n >= 144 { -+ d.a[17] ^= bw[17] -+ } -+ if n >= 168 { -+ d.a[18] ^= bw[18] -+ d.a[19] ^= bw[19] -+ d.a[20] ^= bw[20] -+ } -+} -+ -+func copyOutUnaligned(d *state, buf []byte) { -+ ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) -+ copy(buf, ab[:]) -+} -+ -+var ( -+ xorIn = xorInUnaligned -+ copyOut = copyOutUnaligned -+) -+ -+const xorImplementationUnaligned = "unaligned" -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/client.go b/ms_mod/golang.org/x/crypto/ssh/agent/client.go -new file mode 100644 -index 00000000000000..c3e112a9396121 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/client.go -@@ -0,0 +1,849 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package agent implements the ssh-agent protocol, and provides both -+// a client and a server. The client can talk to a standard ssh-agent -+// that uses UNIX sockets, and one could implement an alternative -+// ssh-agent process using the sample server. -+// -+// References: -+// -+// [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00 -+package agent // import "golang.org/x/crypto/ssh/agent" -+ -+import ( -+ "bytes" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "encoding/base64" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ "sync" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/ssh" -+) -+ -+// SignatureFlags represent additional flags that can be passed to the signature -+// requests an defined in [PROTOCOL.agent] section 4.5.1. -+type SignatureFlags uint32 -+ -+// SignatureFlag values as defined in [PROTOCOL.agent] section 5.3. -+const ( -+ SignatureFlagReserved SignatureFlags = 1 << iota -+ SignatureFlagRsaSha256 -+ SignatureFlagRsaSha512 -+) -+ -+// Agent represents the capabilities of an ssh-agent. -+type Agent interface { -+ // List returns the identities known to the agent. -+ List() ([]*Key, error) -+ -+ // Sign has the agent sign the data using a protocol 2 key as defined -+ // in [PROTOCOL.agent] section 2.6.2. -+ Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) -+ -+ // Add adds a private key to the agent. -+ Add(key AddedKey) error -+ -+ // Remove removes all identities with the given public key. -+ Remove(key ssh.PublicKey) error -+ -+ // RemoveAll removes all identities. -+ RemoveAll() error -+ -+ // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. -+ Lock(passphrase []byte) error -+ -+ // Unlock undoes the effect of Lock -+ Unlock(passphrase []byte) error -+ -+ // Signers returns signers for all the known keys. -+ Signers() ([]ssh.Signer, error) -+} -+ -+type ExtendedAgent interface { -+ Agent -+ -+ // SignWithFlags signs like Sign, but allows for additional flags to be sent/received -+ SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) -+ -+ // Extension processes a custom extension request. Standard-compliant agents are not -+ // required to support any extensions, but this method allows agents to implement -+ // vendor-specific methods or add experimental features. See [PROTOCOL.agent] section 4.7. -+ // If agent extensions are unsupported entirely this method MUST return an -+ // ErrExtensionUnsupported error. Similarly, if just the specific extensionType in -+ // the request is unsupported by the agent then ErrExtensionUnsupported MUST be -+ // returned. -+ // -+ // In the case of success, since [PROTOCOL.agent] section 4.7 specifies that the contents -+ // of the response are unspecified (including the type of the message), the complete -+ // response will be returned as a []byte slice, including the "type" byte of the message. -+ Extension(extensionType string, contents []byte) ([]byte, error) -+} -+ -+// ConstraintExtension describes an optional constraint defined by users. -+type ConstraintExtension struct { -+ // ExtensionName consist of a UTF-8 string suffixed by the -+ // implementation domain following the naming scheme defined -+ // in Section 4.2 of RFC 4251, e.g. "foo@example.com". -+ ExtensionName string -+ // ExtensionDetails contains the actual content of the extended -+ // constraint. -+ ExtensionDetails []byte -+} -+ -+// AddedKey describes an SSH key to be added to an Agent. -+type AddedKey struct { -+ // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey, -+ // ed25519.PrivateKey or *ecdsa.PrivateKey, which will be inserted into the -+ // agent. -+ PrivateKey interface{} -+ // Certificate, if not nil, is communicated to the agent and will be -+ // stored with the key. -+ Certificate *ssh.Certificate -+ // Comment is an optional, free-form string. -+ Comment string -+ // LifetimeSecs, if not zero, is the number of seconds that the -+ // agent will store the key for. -+ LifetimeSecs uint32 -+ // ConfirmBeforeUse, if true, requests that the agent confirm with the -+ // user before each use of this key. -+ ConfirmBeforeUse bool -+ // ConstraintExtensions are the experimental or private-use constraints -+ // defined by users. -+ ConstraintExtensions []ConstraintExtension -+} -+ -+// See [PROTOCOL.agent], section 3. -+const ( -+ agentRequestV1Identities = 1 -+ agentRemoveAllV1Identities = 9 -+ -+ // 3.2 Requests from client to agent for protocol 2 key operations -+ agentAddIdentity = 17 -+ agentRemoveIdentity = 18 -+ agentRemoveAllIdentities = 19 -+ agentAddIDConstrained = 25 -+ -+ // 3.3 Key-type independent requests from client to agent -+ agentAddSmartcardKey = 20 -+ agentRemoveSmartcardKey = 21 -+ agentLock = 22 -+ agentUnlock = 23 -+ agentAddSmartcardKeyConstrained = 26 -+ -+ // 3.7 Key constraint identifiers -+ agentConstrainLifetime = 1 -+ agentConstrainConfirm = 2 -+ agentConstrainExtension = 3 -+) -+ -+// maxAgentResponseBytes is the maximum agent reply size that is accepted. This -+// is a sanity check, not a limit in the spec. -+const maxAgentResponseBytes = 16 << 20 -+ -+// Agent messages: -+// These structures mirror the wire format of the corresponding ssh agent -+// messages found in [PROTOCOL.agent]. -+ -+// 3.4 Generic replies from agent to client -+const agentFailure = 5 -+ -+type failureAgentMsg struct{} -+ -+const agentSuccess = 6 -+ -+type successAgentMsg struct{} -+ -+// See [PROTOCOL.agent], section 2.5.2. -+const agentRequestIdentities = 11 -+ -+type requestIdentitiesAgentMsg struct{} -+ -+// See [PROTOCOL.agent], section 2.5.2. -+const agentIdentitiesAnswer = 12 -+ -+type identitiesAnswerAgentMsg struct { -+ NumKeys uint32 `sshtype:"12"` -+ Keys []byte `ssh:"rest"` -+} -+ -+// See [PROTOCOL.agent], section 2.6.2. -+const agentSignRequest = 13 -+ -+type signRequestAgentMsg struct { -+ KeyBlob []byte `sshtype:"13"` -+ Data []byte -+ Flags uint32 -+} -+ -+// See [PROTOCOL.agent], section 2.6.2. -+ -+// 3.6 Replies from agent to client for protocol 2 key operations -+const agentSignResponse = 14 -+ -+type signResponseAgentMsg struct { -+ SigBlob []byte `sshtype:"14"` -+} -+ -+type publicKey struct { -+ Format string -+ Rest []byte `ssh:"rest"` -+} -+ -+// 3.7 Key constraint identifiers -+type constrainLifetimeAgentMsg struct { -+ LifetimeSecs uint32 `sshtype:"1"` -+} -+ -+type constrainExtensionAgentMsg struct { -+ ExtensionName string `sshtype:"3"` -+ ExtensionDetails []byte -+ -+ // Rest is a field used for parsing, not part of message -+ Rest []byte `ssh:"rest"` -+} -+ -+// See [PROTOCOL.agent], section 4.7 -+const agentExtension = 27 -+const agentExtensionFailure = 28 -+ -+// ErrExtensionUnsupported indicates that an extension defined in -+// [PROTOCOL.agent] section 4.7 is unsupported by the agent. Specifically this -+// error indicates that the agent returned a standard SSH_AGENT_FAILURE message -+// as the result of a SSH_AGENTC_EXTENSION request. Note that the protocol -+// specification (and therefore this error) does not distinguish between a -+// specific extension being unsupported and extensions being unsupported entirely. -+var ErrExtensionUnsupported = errors.New("agent: extension unsupported") -+ -+type extensionAgentMsg struct { -+ ExtensionType string `sshtype:"27"` -+ // NOTE: this matches OpenSSH's PROTOCOL.agent, not the IETF draft [PROTOCOL.agent], -+ // so that it matches what OpenSSH actually implements in the wild. -+ Contents []byte `ssh:"rest"` -+} -+ -+// Key represents a protocol 2 public key as defined in -+// [PROTOCOL.agent], section 2.5.2. -+type Key struct { -+ Format string -+ Blob []byte -+ Comment string -+} -+ -+func clientErr(err error) error { -+ return fmt.Errorf("agent: client error: %v", err) -+} -+ -+// String returns the storage form of an agent key with the format, base64 -+// encoded serialized key, and the comment if it is not empty. -+func (k *Key) String() string { -+ s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob) -+ -+ if k.Comment != "" { -+ s += " " + k.Comment -+ } -+ -+ return s -+} -+ -+// Type returns the public key type. -+func (k *Key) Type() string { -+ return k.Format -+} -+ -+// Marshal returns key blob to satisfy the ssh.PublicKey interface. -+func (k *Key) Marshal() []byte { -+ return k.Blob -+} -+ -+// Verify satisfies the ssh.PublicKey interface. -+func (k *Key) Verify(data []byte, sig *ssh.Signature) error { -+ pubKey, err := ssh.ParsePublicKey(k.Blob) -+ if err != nil { -+ return fmt.Errorf("agent: bad public key: %v", err) -+ } -+ return pubKey.Verify(data, sig) -+} -+ -+type wireKey struct { -+ Format string -+ Rest []byte `ssh:"rest"` -+} -+ -+func parseKey(in []byte) (out *Key, rest []byte, err error) { -+ var record struct { -+ Blob []byte -+ Comment string -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := ssh.Unmarshal(in, &record); err != nil { -+ return nil, nil, err -+ } -+ -+ var wk wireKey -+ if err := ssh.Unmarshal(record.Blob, &wk); err != nil { -+ return nil, nil, err -+ } -+ -+ return &Key{ -+ Format: wk.Format, -+ Blob: record.Blob, -+ Comment: record.Comment, -+ }, record.Rest, nil -+} -+ -+// client is a client for an ssh-agent process. -+type client struct { -+ // conn is typically a *net.UnixConn -+ conn io.ReadWriter -+ // mu is used to prevent concurrent access to the agent -+ mu sync.Mutex -+} -+ -+// NewClient returns an Agent that talks to an ssh-agent process over -+// the given connection. -+func NewClient(rw io.ReadWriter) ExtendedAgent { -+ return &client{conn: rw} -+} -+ -+// call sends an RPC to the agent. On success, the reply is -+// unmarshaled into reply and replyType is set to the first byte of -+// the reply, which contains the type of the message. -+func (c *client) call(req []byte) (reply interface{}, err error) { -+ buf, err := c.callRaw(req) -+ if err != nil { -+ return nil, err -+ } -+ reply, err = unmarshal(buf) -+ if err != nil { -+ return nil, clientErr(err) -+ } -+ return reply, nil -+} -+ -+// callRaw sends an RPC to the agent. On success, the raw -+// bytes of the response are returned; no unmarshalling is -+// performed on the response. -+func (c *client) callRaw(req []byte) (reply []byte, err error) { -+ c.mu.Lock() -+ defer c.mu.Unlock() -+ -+ msg := make([]byte, 4+len(req)) -+ binary.BigEndian.PutUint32(msg, uint32(len(req))) -+ copy(msg[4:], req) -+ if _, err = c.conn.Write(msg); err != nil { -+ return nil, clientErr(err) -+ } -+ -+ var respSizeBuf [4]byte -+ if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil { -+ return nil, clientErr(err) -+ } -+ respSize := binary.BigEndian.Uint32(respSizeBuf[:]) -+ if respSize > maxAgentResponseBytes { -+ return nil, clientErr(errors.New("response too large")) -+ } -+ -+ buf := make([]byte, respSize) -+ if _, err = io.ReadFull(c.conn, buf); err != nil { -+ return nil, clientErr(err) -+ } -+ return buf, nil -+} -+ -+func (c *client) simpleCall(req []byte) error { -+ resp, err := c.call(req) -+ if err != nil { -+ return err -+ } -+ if _, ok := resp.(*successAgentMsg); ok { -+ return nil -+ } -+ return errors.New("agent: failure") -+} -+ -+func (c *client) RemoveAll() error { -+ return c.simpleCall([]byte{agentRemoveAllIdentities}) -+} -+ -+func (c *client) Remove(key ssh.PublicKey) error { -+ req := ssh.Marshal(&agentRemoveIdentityMsg{ -+ KeyBlob: key.Marshal(), -+ }) -+ return c.simpleCall(req) -+} -+ -+func (c *client) Lock(passphrase []byte) error { -+ req := ssh.Marshal(&agentLockMsg{ -+ Passphrase: passphrase, -+ }) -+ return c.simpleCall(req) -+} -+ -+func (c *client) Unlock(passphrase []byte) error { -+ req := ssh.Marshal(&agentUnlockMsg{ -+ Passphrase: passphrase, -+ }) -+ return c.simpleCall(req) -+} -+ -+// List returns the identities known to the agent. -+func (c *client) List() ([]*Key, error) { -+ // see [PROTOCOL.agent] section 2.5.2. -+ req := []byte{agentRequestIdentities} -+ -+ msg, err := c.call(req) -+ if err != nil { -+ return nil, err -+ } -+ -+ switch msg := msg.(type) { -+ case *identitiesAnswerAgentMsg: -+ if msg.NumKeys > maxAgentResponseBytes/8 { -+ return nil, errors.New("agent: too many keys in agent reply") -+ } -+ keys := make([]*Key, msg.NumKeys) -+ data := msg.Keys -+ for i := uint32(0); i < msg.NumKeys; i++ { -+ var key *Key -+ var err error -+ if key, data, err = parseKey(data); err != nil { -+ return nil, err -+ } -+ keys[i] = key -+ } -+ return keys, nil -+ case *failureAgentMsg: -+ return nil, errors.New("agent: failed to list keys") -+ } -+ panic("unreachable") -+} -+ -+// Sign has the agent sign the data using a protocol 2 key as defined -+// in [PROTOCOL.agent] section 2.6.2. -+func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { -+ return c.SignWithFlags(key, data, 0) -+} -+ -+func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) { -+ req := ssh.Marshal(signRequestAgentMsg{ -+ KeyBlob: key.Marshal(), -+ Data: data, -+ Flags: uint32(flags), -+ }) -+ -+ msg, err := c.call(req) -+ if err != nil { -+ return nil, err -+ } -+ -+ switch msg := msg.(type) { -+ case *signResponseAgentMsg: -+ var sig ssh.Signature -+ if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { -+ return nil, err -+ } -+ -+ return &sig, nil -+ case *failureAgentMsg: -+ return nil, errors.New("agent: failed to sign challenge") -+ } -+ panic("unreachable") -+} -+ -+// unmarshal parses an agent message in packet, returning the parsed -+// form and the message type of packet. -+func unmarshal(packet []byte) (interface{}, error) { -+ if len(packet) < 1 { -+ return nil, errors.New("agent: empty packet") -+ } -+ var msg interface{} -+ switch packet[0] { -+ case agentFailure: -+ return new(failureAgentMsg), nil -+ case agentSuccess: -+ return new(successAgentMsg), nil -+ case agentIdentitiesAnswer: -+ msg = new(identitiesAnswerAgentMsg) -+ case agentSignResponse: -+ msg = new(signResponseAgentMsg) -+ case agentV1IdentitiesAnswer: -+ msg = new(agentV1IdentityMsg) -+ default: -+ return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) -+ } -+ if err := ssh.Unmarshal(packet, msg); err != nil { -+ return nil, err -+ } -+ return msg, nil -+} -+ -+type rsaKeyMsg struct { -+ Type string `sshtype:"17|25"` -+ N *big.Int -+ E *big.Int -+ D *big.Int -+ Iqmp *big.Int // IQMP = Inverse Q Mod P -+ P *big.Int -+ Q *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type dsaKeyMsg struct { -+ Type string `sshtype:"17|25"` -+ P *big.Int -+ Q *big.Int -+ G *big.Int -+ Y *big.Int -+ X *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ecdsaKeyMsg struct { -+ Type string `sshtype:"17|25"` -+ Curve string -+ KeyBytes []byte -+ D *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ed25519KeyMsg struct { -+ Type string `sshtype:"17|25"` -+ Pub []byte -+ Priv []byte -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+// Insert adds a private key to the agent. -+func (c *client) insertKey(s interface{}, comment string, constraints []byte) error { -+ var req []byte -+ switch k := s.(type) { -+ case *rsa.PrivateKey: -+ if len(k.Primes) != 2 { -+ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) -+ } -+ k.Precompute() -+ req = ssh.Marshal(rsaKeyMsg{ -+ Type: ssh.KeyAlgoRSA, -+ N: k.N, -+ E: big.NewInt(int64(k.E)), -+ D: k.D, -+ Iqmp: k.Precomputed.Qinv, -+ P: k.Primes[0], -+ Q: k.Primes[1], -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *dsa.PrivateKey: -+ req = ssh.Marshal(dsaKeyMsg{ -+ Type: ssh.KeyAlgoDSA, -+ P: k.P, -+ Q: k.Q, -+ G: k.G, -+ Y: k.Y, -+ X: k.X, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *ecdsa.PrivateKey: -+ nistID := fmt.Sprintf("nistp%d", k.Params().BitSize) -+ req = ssh.Marshal(ecdsaKeyMsg{ -+ Type: "ecdsa-sha2-" + nistID, -+ Curve: nistID, -+ KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y), -+ D: k.D, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519KeyMsg{ -+ Type: ssh.KeyAlgoED25519, -+ Pub: []byte(k)[32:], -+ Priv: []byte(k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ // This function originally supported only *ed25519.PrivateKey, however the -+ // general idiom is to pass ed25519.PrivateKey by value, not by pointer. -+ // We still support the pointer variant for backwards compatibility. -+ case *ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519KeyMsg{ -+ Type: ssh.KeyAlgoED25519, -+ Pub: []byte(*k)[32:], -+ Priv: []byte(*k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ default: -+ return fmt.Errorf("agent: unsupported key type %T", s) -+ } -+ -+ // if constraints are present then the message type needs to be changed. -+ if len(constraints) != 0 { -+ req[0] = agentAddIDConstrained -+ } -+ -+ resp, err := c.call(req) -+ if err != nil { -+ return err -+ } -+ if _, ok := resp.(*successAgentMsg); ok { -+ return nil -+ } -+ return errors.New("agent: failure") -+} -+ -+type rsaCertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ D *big.Int -+ Iqmp *big.Int // IQMP = Inverse Q Mod P -+ P *big.Int -+ Q *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type dsaCertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ X *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ecdsaCertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ D *big.Int -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+type ed25519CertMsg struct { -+ Type string `sshtype:"17|25"` -+ CertBytes []byte -+ Pub []byte -+ Priv []byte -+ Comments string -+ Constraints []byte `ssh:"rest"` -+} -+ -+// Add adds a private key to the agent. If a certificate is given, -+// that certificate is added instead as public key. -+func (c *client) Add(key AddedKey) error { -+ var constraints []byte -+ -+ if secs := key.LifetimeSecs; secs != 0 { -+ constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...) -+ } -+ -+ if key.ConfirmBeforeUse { -+ constraints = append(constraints, agentConstrainConfirm) -+ } -+ -+ cert := key.Certificate -+ if cert == nil { -+ return c.insertKey(key.PrivateKey, key.Comment, constraints) -+ } -+ return c.insertCert(key.PrivateKey, cert, key.Comment, constraints) -+} -+ -+func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { -+ var req []byte -+ switch k := s.(type) { -+ case *rsa.PrivateKey: -+ if len(k.Primes) != 2 { -+ return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) -+ } -+ k.Precompute() -+ req = ssh.Marshal(rsaCertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ D: k.D, -+ Iqmp: k.Precomputed.Qinv, -+ P: k.Primes[0], -+ Q: k.Primes[1], -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *dsa.PrivateKey: -+ req = ssh.Marshal(dsaCertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ X: k.X, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case *ecdsa.PrivateKey: -+ req = ssh.Marshal(ecdsaCertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ D: k.D, -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ case ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519CertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ Pub: []byte(k)[32:], -+ Priv: []byte(k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ // This function originally supported only *ed25519.PrivateKey, however the -+ // general idiom is to pass ed25519.PrivateKey by value, not by pointer. -+ // We still support the pointer variant for backwards compatibility. -+ case *ed25519.PrivateKey: -+ req = ssh.Marshal(ed25519CertMsg{ -+ Type: cert.Type(), -+ CertBytes: cert.Marshal(), -+ Pub: []byte(*k)[32:], -+ Priv: []byte(*k), -+ Comments: comment, -+ Constraints: constraints, -+ }) -+ default: -+ return fmt.Errorf("agent: unsupported key type %T", s) -+ } -+ -+ // if constraints are present then the message type needs to be changed. -+ if len(constraints) != 0 { -+ req[0] = agentAddIDConstrained -+ } -+ -+ signer, err := ssh.NewSignerFromKey(s) -+ if err != nil { -+ return err -+ } -+ if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { -+ return errors.New("agent: signer and cert have different public key") -+ } -+ -+ resp, err := c.call(req) -+ if err != nil { -+ return err -+ } -+ if _, ok := resp.(*successAgentMsg); ok { -+ return nil -+ } -+ return errors.New("agent: failure") -+} -+ -+// Signers provides a callback for client authentication. -+func (c *client) Signers() ([]ssh.Signer, error) { -+ keys, err := c.List() -+ if err != nil { -+ return nil, err -+ } -+ -+ var result []ssh.Signer -+ for _, k := range keys { -+ result = append(result, &agentKeyringSigner{c, k}) -+ } -+ return result, nil -+} -+ -+type agentKeyringSigner struct { -+ agent *client -+ pub ssh.PublicKey -+} -+ -+func (s *agentKeyringSigner) PublicKey() ssh.PublicKey { -+ return s.pub -+} -+ -+func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { -+ // The agent has its own entropy source, so the rand argument is ignored. -+ return s.agent.Sign(s.pub, data) -+} -+ -+func (s *agentKeyringSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*ssh.Signature, error) { -+ if algorithm == "" || algorithm == underlyingAlgo(s.pub.Type()) { -+ return s.Sign(rand, data) -+ } -+ -+ var flags SignatureFlags -+ switch algorithm { -+ case ssh.KeyAlgoRSASHA256: -+ flags = SignatureFlagRsaSha256 -+ case ssh.KeyAlgoRSASHA512: -+ flags = SignatureFlagRsaSha512 -+ default: -+ return nil, fmt.Errorf("agent: unsupported algorithm %q", algorithm) -+ } -+ -+ return s.agent.SignWithFlags(s.pub, data, flags) -+} -+ -+var _ ssh.AlgorithmSigner = &agentKeyringSigner{} -+ -+// certKeyAlgoNames is a mapping from known certificate algorithm names to the -+// corresponding public key signature algorithm. -+// -+// This map must be kept in sync with the one in certs.go. -+var certKeyAlgoNames = map[string]string{ -+ ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA, -+ ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256, -+ ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512, -+ ssh.CertAlgoDSAv01: ssh.KeyAlgoDSA, -+ ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256, -+ ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384, -+ ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521, -+ ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256, -+ ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519, -+ ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519, -+} -+ -+// underlyingAlgo returns the signature algorithm associated with algo (which is -+// an advertised or negotiated public key or host key algorithm). These are -+// usually the same, except for certificate algorithms. -+func underlyingAlgo(algo string) string { -+ if a, ok := certKeyAlgoNames[algo]; ok { -+ return a -+ } -+ return algo -+} -+ -+// Calls an extension method. It is up to the agent implementation as to whether or not -+// any particular extension is supported and may always return an error. Because the -+// type of the response is up to the implementation, this returns the bytes of the -+// response and does not attempt any type of unmarshalling. -+func (c *client) Extension(extensionType string, contents []byte) ([]byte, error) { -+ req := ssh.Marshal(extensionAgentMsg{ -+ ExtensionType: extensionType, -+ Contents: contents, -+ }) -+ buf, err := c.callRaw(req) -+ if err != nil { -+ return nil, err -+ } -+ if len(buf) == 0 { -+ return nil, errors.New("agent: failure; empty response") -+ } -+ // [PROTOCOL.agent] section 4.7 indicates that an SSH_AGENT_FAILURE message -+ // represents an agent that does not support the extension -+ if buf[0] == agentFailure { -+ return nil, ErrExtensionUnsupported -+ } -+ if buf[0] == agentExtensionFailure { -+ return nil, errors.New("agent: generic extension failure") -+ } -+ -+ return buf, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/client_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/client_test.go -new file mode 100644 -index 00000000000000..fdc8000654c6f3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/client_test.go -@@ -0,0 +1,537 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "errors" -+ "io" -+ "net" -+ "os" -+ "os/exec" -+ "path/filepath" -+ "runtime" -+ "strconv" -+ "strings" -+ "testing" -+ "time" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// startOpenSSHAgent executes ssh-agent, and returns an Agent interface to it. -+func startOpenSSHAgent(t *testing.T) (client ExtendedAgent, socket string, cleanup func()) { -+ if testing.Short() { -+ // ssh-agent is not always available, and the key -+ // types supported vary by platform. -+ t.Skip("skipping test due to -short") -+ } -+ if runtime.GOOS == "windows" { -+ t.Skip("skipping on windows, we don't support connecting to the ssh-agent via a named pipe") -+ } -+ -+ bin, err := exec.LookPath("ssh-agent") -+ if err != nil { -+ t.Skip("could not find ssh-agent") -+ } -+ -+ cmd := exec.Command(bin, "-s") -+ cmd.Env = []string{} // Do not let the user's environment influence ssh-agent behavior. -+ cmd.Stderr = new(bytes.Buffer) -+ out, err := cmd.Output() -+ if err != nil { -+ t.Fatalf("%s failed: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) -+ } -+ -+ // Output looks like: -+ // -+ // SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; -+ // SSH_AGENT_PID=15542; export SSH_AGENT_PID; -+ // echo Agent pid 15542; -+ -+ fields := bytes.Split(out, []byte(";")) -+ line := bytes.SplitN(fields[0], []byte("="), 2) -+ line[0] = bytes.TrimLeft(line[0], "\n") -+ if string(line[0]) != "SSH_AUTH_SOCK" { -+ t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0]) -+ } -+ socket = string(line[1]) -+ -+ line = bytes.SplitN(fields[2], []byte("="), 2) -+ line[0] = bytes.TrimLeft(line[0], "\n") -+ if string(line[0]) != "SSH_AGENT_PID" { -+ t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2]) -+ } -+ pidStr := line[1] -+ pid, err := strconv.Atoi(string(pidStr)) -+ if err != nil { -+ t.Fatalf("Atoi(%q): %v", pidStr, err) -+ } -+ -+ conn, err := net.Dial("unix", string(socket)) -+ if err != nil { -+ t.Fatalf("net.Dial: %v", err) -+ } -+ -+ ac := NewClient(conn) -+ return ac, socket, func() { -+ proc, _ := os.FindProcess(pid) -+ if proc != nil { -+ proc.Kill() -+ } -+ conn.Close() -+ os.RemoveAll(filepath.Dir(socket)) -+ } -+} -+ -+func startAgent(t *testing.T, agent Agent) (client ExtendedAgent, cleanup func()) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ go ServeAgent(agent, c2) -+ -+ return NewClient(c1), func() { -+ c1.Close() -+ c2.Close() -+ } -+} -+ -+// startKeyringAgent uses Keyring to simulate a ssh-agent Server and returns a client. -+func startKeyringAgent(t *testing.T) (client ExtendedAgent, cleanup func()) { -+ return startAgent(t, NewKeyring()) -+} -+ -+func testOpenSSHAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { -+ agent, _, cleanup := startOpenSSHAgent(t) -+ defer cleanup() -+ -+ testAgentInterface(t, agent, key, cert, lifetimeSecs) -+} -+ -+func testKeyringAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { -+ agent, cleanup := startKeyringAgent(t) -+ defer cleanup() -+ -+ testAgentInterface(t, agent, key, cert, lifetimeSecs) -+} -+ -+func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { -+ signer, err := ssh.NewSignerFromKey(key) -+ if err != nil { -+ t.Fatalf("NewSignerFromKey(%T): %v", key, err) -+ } -+ // The agent should start up empty. -+ if keys, err := agent.List(); err != nil { -+ t.Fatalf("RequestIdentities: %v", err) -+ } else if len(keys) > 0 { -+ t.Fatalf("got %d keys, want 0: %v", len(keys), keys) -+ } -+ -+ // Attempt to insert the key, with certificate if specified. -+ var pubKey ssh.PublicKey -+ if cert != nil { -+ err = agent.Add(AddedKey{ -+ PrivateKey: key, -+ Certificate: cert, -+ Comment: "comment", -+ LifetimeSecs: lifetimeSecs, -+ }) -+ pubKey = cert -+ } else { -+ err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs}) -+ pubKey = signer.PublicKey() -+ } -+ if err != nil { -+ t.Fatalf("insert(%T): %v", key, err) -+ } -+ -+ // Did the key get inserted successfully? -+ if keys, err := agent.List(); err != nil { -+ t.Fatalf("List: %v", err) -+ } else if len(keys) != 1 { -+ t.Fatalf("got %v, want 1 key", keys) -+ } else if keys[0].Comment != "comment" { -+ t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment") -+ } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) { -+ t.Fatalf("key mismatch") -+ } -+ -+ // Can the agent make a valid signature? -+ data := []byte("hello") -+ sig, err := agent.Sign(pubKey, data) -+ if err != nil { -+ t.Fatalf("Sign(%s): %v", pubKey.Type(), err) -+ } -+ -+ if err := pubKey.Verify(data, sig); err != nil { -+ t.Fatalf("Verify(%s): %v", pubKey.Type(), err) -+ } -+ -+ // For tests on RSA keys, try signing with SHA-256 and SHA-512 flags -+ if pubKey.Type() == "ssh-rsa" { -+ sshFlagTest := func(flag SignatureFlags, expectedSigFormat string) { -+ sig, err = agent.SignWithFlags(pubKey, data, flag) -+ if err != nil { -+ t.Fatalf("SignWithFlags(%s): %v", pubKey.Type(), err) -+ } -+ if sig.Format != expectedSigFormat { -+ t.Fatalf("Signature format didn't match expected value: %s != %s", sig.Format, expectedSigFormat) -+ } -+ if err := pubKey.Verify(data, sig); err != nil { -+ t.Fatalf("Verify(%s): %v", pubKey.Type(), err) -+ } -+ } -+ sshFlagTest(0, ssh.KeyAlgoRSA) -+ sshFlagTest(SignatureFlagRsaSha256, ssh.KeyAlgoRSASHA256) -+ sshFlagTest(SignatureFlagRsaSha512, ssh.KeyAlgoRSASHA512) -+ } -+ -+ // If the key has a lifetime, is it removed when it should be? -+ if lifetimeSecs > 0 { -+ time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond) -+ keys, err := agent.List() -+ if err != nil { -+ t.Fatalf("List: %v", err) -+ } -+ if len(keys) > 0 { -+ t.Fatalf("key not expired") -+ } -+ } -+ -+} -+ -+func TestMalformedRequests(t *testing.T) { -+ keyringAgent := NewKeyring() -+ -+ testCase := func(t *testing.T, requestBytes []byte, wantServerErr bool) { -+ c, s := net.Pipe() -+ defer c.Close() -+ defer s.Close() -+ go func() { -+ _, err := c.Write(requestBytes) -+ if err != nil { -+ t.Errorf("Unexpected error writing raw bytes on connection: %v", err) -+ } -+ c.Close() -+ }() -+ err := ServeAgent(keyringAgent, s) -+ if err == nil { -+ t.Error("ServeAgent should have returned an error to malformed input") -+ } else { -+ if (err != io.EOF) != wantServerErr { -+ t.Errorf("ServeAgent returned expected error: %v", err) -+ } -+ } -+ } -+ -+ var testCases = []struct { -+ name string -+ requestBytes []byte -+ wantServerErr bool -+ }{ -+ {"Empty request", []byte{}, false}, -+ {"Short header", []byte{0x00}, true}, -+ {"Empty body", []byte{0x00, 0x00, 0x00, 0x00}, true}, -+ {"Short body", []byte{0x00, 0x00, 0x00, 0x01}, false}, -+ } -+ for _, tc := range testCases { -+ t.Run(tc.name, func(t *testing.T) { testCase(t, tc.requestBytes, tc.wantServerErr) }) -+ } -+} -+ -+func TestAgent(t *testing.T) { -+ for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} { -+ testOpenSSHAgent(t, testPrivateKeys[keyType], nil, 0) -+ testKeyringAgent(t, testPrivateKeys[keyType], nil, 0) -+ } -+} -+ -+func TestCert(t *testing.T) { -+ cert := &ssh.Certificate{ -+ Key: testPublicKeys["rsa"], -+ ValidBefore: ssh.CertTimeInfinity, -+ CertType: ssh.UserCert, -+ } -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ -+ testOpenSSHAgent(t, testPrivateKeys["rsa"], cert, 0) -+ testKeyringAgent(t, testPrivateKeys["rsa"], cert, 0) -+} -+ -+// netListener creates a localhost network listener. -+func netListener() (net.Listener, error) { -+ listener, err := net.Listen("tcp", "127.0.0.1:0") -+ if err != nil { -+ listener, err = net.Listen("tcp", "[::1]:0") -+ if err != nil { -+ return nil, err -+ } -+ } -+ return listener, nil -+} -+ -+// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and -+// therefore is buffered (net.Pipe deadlocks if both sides start with -+// a write.) -+func netPipe() (net.Conn, net.Conn, error) { -+ listener, err := netListener() -+ if err != nil { -+ return nil, nil, err -+ } -+ defer listener.Close() -+ c1, err := net.Dial("tcp", listener.Addr().String()) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ c2, err := listener.Accept() -+ if err != nil { -+ c1.Close() -+ return nil, nil, err -+ } -+ -+ return c1, c2, nil -+} -+ -+func TestServerResponseTooLarge(t *testing.T) { -+ a, b, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ done := make(chan struct{}) -+ defer func() { <-done }() -+ -+ defer a.Close() -+ defer b.Close() -+ -+ var response identitiesAnswerAgentMsg -+ response.NumKeys = 1 -+ response.Keys = make([]byte, maxAgentResponseBytes+1) -+ -+ agent := NewClient(a) -+ go func() { -+ defer close(done) -+ n, err := b.Write(ssh.Marshal(response)) -+ if n < 4 { -+ if runtime.GOOS == "plan9" { -+ if e1, ok := err.(*net.OpError); ok { -+ if e2, ok := e1.Err.(*os.PathError); ok { -+ switch e2.Err.Error() { -+ case "Hangup", "i/o on hungup channel": -+ // syscall.Pwrite returns -1 in this case even when some data did get written. -+ return -+ } -+ } -+ } -+ } -+ t.Errorf("At least 4 bytes (the response size) should have been successfully written: %d < 4: %v", n, err) -+ } -+ }() -+ _, err = agent.List() -+ if err == nil { -+ t.Fatal("Did not get error result") -+ } -+ if err.Error() != "agent: client error: response too large" { -+ t.Fatal("Did not get expected error result") -+ } -+} -+ -+func TestAuth(t *testing.T) { -+ agent, _, cleanup := startOpenSSHAgent(t) -+ defer cleanup() -+ -+ a, b, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ -+ defer a.Close() -+ defer b.Close() -+ -+ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil { -+ t.Errorf("Add: %v", err) -+ } -+ -+ serverConf := ssh.ServerConfig{} -+ serverConf.AddHostKey(testSigners["rsa"]) -+ serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { -+ if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { -+ return nil, nil -+ } -+ -+ return nil, errors.New("pubkey rejected") -+ } -+ -+ go func() { -+ conn, _, _, err := ssh.NewServerConn(a, &serverConf) -+ if err != nil { -+ t.Errorf("NewServerConn error: %v", err) -+ return -+ } -+ conn.Close() -+ }() -+ -+ conf := ssh.ClientConfig{ -+ HostKeyCallback: ssh.InsecureIgnoreHostKey(), -+ } -+ conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers)) -+ conn, _, _, err := ssh.NewClientConn(b, "", &conf) -+ if err != nil { -+ t.Fatalf("NewClientConn: %v", err) -+ } -+ conn.Close() -+} -+ -+func TestLockOpenSSHAgent(t *testing.T) { -+ agent, _, cleanup := startOpenSSHAgent(t) -+ defer cleanup() -+ testLockAgent(agent, t) -+} -+ -+func TestLockKeyringAgent(t *testing.T) { -+ agent, cleanup := startKeyringAgent(t) -+ defer cleanup() -+ testLockAgent(agent, t) -+} -+ -+func testLockAgent(agent Agent, t *testing.T) { -+ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil { -+ t.Errorf("Add: %v", err) -+ } -+ if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil { -+ t.Errorf("Add: %v", err) -+ } -+ if keys, err := agent.List(); err != nil { -+ t.Errorf("List: %v", err) -+ } else if len(keys) != 2 { -+ t.Errorf("Want 2 keys, got %v", keys) -+ } -+ -+ passphrase := []byte("secret") -+ if err := agent.Lock(passphrase); err != nil { -+ t.Errorf("Lock: %v", err) -+ } -+ -+ if keys, err := agent.List(); err != nil { -+ t.Errorf("List: %v", err) -+ } else if len(keys) != 0 { -+ t.Errorf("Want 0 keys, got %v", keys) -+ } -+ -+ signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"]) -+ if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil { -+ t.Fatalf("Sign did not fail") -+ } -+ -+ if err := agent.Remove(signer.PublicKey()); err == nil { -+ t.Fatalf("Remove did not fail") -+ } -+ -+ if err := agent.RemoveAll(); err == nil { -+ t.Fatalf("RemoveAll did not fail") -+ } -+ -+ if err := agent.Unlock(nil); err == nil { -+ t.Errorf("Unlock with wrong passphrase succeeded") -+ } -+ if err := agent.Unlock(passphrase); err != nil { -+ t.Errorf("Unlock: %v", err) -+ } -+ -+ if err := agent.Remove(signer.PublicKey()); err != nil { -+ t.Fatalf("Remove: %v", err) -+ } -+ -+ if keys, err := agent.List(); err != nil { -+ t.Errorf("List: %v", err) -+ } else if len(keys) != 1 { -+ t.Errorf("Want 1 keys, got %v", keys) -+ } -+} -+ -+func testOpenSSHAgentLifetime(t *testing.T) { -+ agent, _, cleanup := startOpenSSHAgent(t) -+ defer cleanup() -+ testAgentLifetime(t, agent) -+} -+ -+func testKeyringAgentLifetime(t *testing.T) { -+ agent, cleanup := startKeyringAgent(t) -+ defer cleanup() -+ testAgentLifetime(t, agent) -+} -+ -+func testAgentLifetime(t *testing.T, agent Agent) { -+ for _, keyType := range []string{"rsa", "dsa", "ecdsa"} { -+ // Add private keys to the agent. -+ err := agent.Add(AddedKey{ -+ PrivateKey: testPrivateKeys[keyType], -+ Comment: "comment", -+ LifetimeSecs: 1, -+ }) -+ if err != nil { -+ t.Fatalf("add: %v", err) -+ } -+ // Add certs to the agent. -+ cert := &ssh.Certificate{ -+ Key: testPublicKeys[keyType], -+ ValidBefore: ssh.CertTimeInfinity, -+ CertType: ssh.UserCert, -+ } -+ cert.SignCert(rand.Reader, testSigners[keyType]) -+ err = agent.Add(AddedKey{ -+ PrivateKey: testPrivateKeys[keyType], -+ Certificate: cert, -+ Comment: "comment", -+ LifetimeSecs: 1, -+ }) -+ if err != nil { -+ t.Fatalf("add: %v", err) -+ } -+ } -+ time.Sleep(1100 * time.Millisecond) -+ if keys, err := agent.List(); err != nil { -+ t.Errorf("List: %v", err) -+ } else if len(keys) != 0 { -+ t.Errorf("Want 0 keys, got %v", len(keys)) -+ } -+} -+ -+type keyringExtended struct { -+ *keyring -+} -+ -+func (r *keyringExtended) Extension(extensionType string, contents []byte) ([]byte, error) { -+ if extensionType != "my-extension@example.com" { -+ return []byte{agentExtensionFailure}, nil -+ } -+ return append([]byte{agentSuccess}, contents...), nil -+} -+ -+func TestAgentExtensions(t *testing.T) { -+ agent, _, cleanup := startOpenSSHAgent(t) -+ defer cleanup() -+ _, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02}) -+ if err == nil { -+ t.Fatal("should have gotten agent extension failure") -+ } -+ -+ agent, cleanup = startAgent(t, &keyringExtended{}) -+ defer cleanup() -+ result, err := agent.Extension("my-extension@example.com", []byte{0x00, 0x01, 0x02}) -+ if err != nil { -+ t.Fatalf("agent extension failure: %v", err) -+ } -+ if len(result) != 4 || !bytes.Equal(result, []byte{agentSuccess, 0x00, 0x01, 0x02}) { -+ t.Fatalf("agent extension result invalid: %v", result) -+ } -+ -+ _, err = agent.Extension("bad-extension@example.com", []byte{0x00, 0x01, 0x02}) -+ if err == nil { -+ t.Fatal("should have gotten agent extension failure") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/example_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/example_test.go -new file mode 100644 -index 00000000000000..1fedaea1d6c9c4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/example_test.go -@@ -0,0 +1,41 @@ -+// Copyright 2016 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent_test -+ -+import ( -+ "log" -+ "net" -+ "os" -+ -+ "golang.org/x/crypto/ssh" -+ "golang.org/x/crypto/ssh/agent" -+) -+ -+func ExampleNewClient() { -+ // ssh-agent(1) provides a UNIX socket at $SSH_AUTH_SOCK. -+ socket := os.Getenv("SSH_AUTH_SOCK") -+ conn, err := net.Dial("unix", socket) -+ if err != nil { -+ log.Fatalf("Failed to open SSH_AUTH_SOCK: %v", err) -+ } -+ -+ agentClient := agent.NewClient(conn) -+ config := &ssh.ClientConfig{ -+ User: "gopher", -+ Auth: []ssh.AuthMethod{ -+ // Use a callback rather than PublicKeys so we only consult the -+ // agent once the remote server wants it. -+ ssh.PublicKeysCallback(agentClient.Signers), -+ }, -+ HostKeyCallback: ssh.InsecureIgnoreHostKey(), -+ } -+ -+ sshc, err := ssh.Dial("tcp", "localhost:22", config) -+ if err != nil { -+ log.Fatal(err) -+ } -+ // Use sshc... -+ sshc.Close() -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/forward.go b/ms_mod/golang.org/x/crypto/ssh/agent/forward.go -new file mode 100644 -index 00000000000000..fd24ba900d2541 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/forward.go -@@ -0,0 +1,103 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "errors" -+ "io" -+ "net" -+ "sync" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// RequestAgentForwarding sets up agent forwarding for the session. -+// ForwardToAgent or ForwardToRemote should be called to route -+// the authentication requests. -+func RequestAgentForwarding(session *ssh.Session) error { -+ ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) -+ if err != nil { -+ return err -+ } -+ if !ok { -+ return errors.New("forwarding request denied") -+ } -+ return nil -+} -+ -+// ForwardToAgent routes authentication requests to the given keyring. -+func ForwardToAgent(client *ssh.Client, keyring Agent) error { -+ channels := client.HandleChannelOpen(channelType) -+ if channels == nil { -+ return errors.New("agent: already have handler for " + channelType) -+ } -+ -+ go func() { -+ for ch := range channels { -+ channel, reqs, err := ch.Accept() -+ if err != nil { -+ continue -+ } -+ go ssh.DiscardRequests(reqs) -+ go func() { -+ ServeAgent(keyring, channel) -+ channel.Close() -+ }() -+ } -+ }() -+ return nil -+} -+ -+const channelType = "auth-agent@openssh.com" -+ -+// ForwardToRemote routes authentication requests to the ssh-agent -+// process serving on the given unix socket. -+func ForwardToRemote(client *ssh.Client, addr string) error { -+ channels := client.HandleChannelOpen(channelType) -+ if channels == nil { -+ return errors.New("agent: already have handler for " + channelType) -+ } -+ conn, err := net.Dial("unix", addr) -+ if err != nil { -+ return err -+ } -+ conn.Close() -+ -+ go func() { -+ for ch := range channels { -+ channel, reqs, err := ch.Accept() -+ if err != nil { -+ continue -+ } -+ go ssh.DiscardRequests(reqs) -+ go forwardUnixSocket(channel, addr) -+ } -+ }() -+ return nil -+} -+ -+func forwardUnixSocket(channel ssh.Channel, addr string) { -+ conn, err := net.Dial("unix", addr) -+ if err != nil { -+ return -+ } -+ -+ var wg sync.WaitGroup -+ wg.Add(2) -+ go func() { -+ io.Copy(conn, channel) -+ conn.(*net.UnixConn).CloseWrite() -+ wg.Done() -+ }() -+ go func() { -+ io.Copy(channel, conn) -+ channel.CloseWrite() -+ wg.Done() -+ }() -+ -+ wg.Wait() -+ conn.Close() -+ channel.Close() -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/keyring.go b/ms_mod/golang.org/x/crypto/ssh/agent/keyring.go -new file mode 100644 -index 00000000000000..21bfa870fa4dd2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/keyring.go -@@ -0,0 +1,241 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "crypto/subtle" -+ "errors" -+ "fmt" -+ "sync" -+ "time" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+type privKey struct { -+ signer ssh.Signer -+ comment string -+ expire *time.Time -+} -+ -+type keyring struct { -+ mu sync.Mutex -+ keys []privKey -+ -+ locked bool -+ passphrase []byte -+} -+ -+var errLocked = errors.New("agent: locked") -+ -+// NewKeyring returns an Agent that holds keys in memory. It is safe -+// for concurrent use by multiple goroutines. -+func NewKeyring() Agent { -+ return &keyring{} -+} -+ -+// RemoveAll removes all identities. -+func (r *keyring) RemoveAll() error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ -+ r.keys = nil -+ return nil -+} -+ -+// removeLocked does the actual key removal. The caller must already be holding the -+// keyring mutex. -+func (r *keyring) removeLocked(want []byte) error { -+ found := false -+ for i := 0; i < len(r.keys); { -+ if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { -+ found = true -+ r.keys[i] = r.keys[len(r.keys)-1] -+ r.keys = r.keys[:len(r.keys)-1] -+ continue -+ } else { -+ i++ -+ } -+ } -+ -+ if !found { -+ return errors.New("agent: key not found") -+ } -+ return nil -+} -+ -+// Remove removes all identities with the given public key. -+func (r *keyring) Remove(key ssh.PublicKey) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ -+ return r.removeLocked(key.Marshal()) -+} -+ -+// Lock locks the agent. Sign and Remove will fail, and List will return an empty list. -+func (r *keyring) Lock(passphrase []byte) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ -+ r.locked = true -+ r.passphrase = passphrase -+ return nil -+} -+ -+// Unlock undoes the effect of Lock -+func (r *keyring) Unlock(passphrase []byte) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if !r.locked { -+ return errors.New("agent: not locked") -+ } -+ if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { -+ return fmt.Errorf("agent: incorrect passphrase") -+ } -+ -+ r.locked = false -+ r.passphrase = nil -+ return nil -+} -+ -+// expireKeysLocked removes expired keys from the keyring. If a key was added -+// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have -+// elapsed, it is removed. The caller *must* be holding the keyring mutex. -+func (r *keyring) expireKeysLocked() { -+ for _, k := range r.keys { -+ if k.expire != nil && time.Now().After(*k.expire) { -+ r.removeLocked(k.signer.PublicKey().Marshal()) -+ } -+ } -+} -+ -+// List returns the identities known to the agent. -+func (r *keyring) List() ([]*Key, error) { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ // section 2.7: locked agents return empty. -+ return nil, nil -+ } -+ -+ r.expireKeysLocked() -+ var ids []*Key -+ for _, k := range r.keys { -+ pub := k.signer.PublicKey() -+ ids = append(ids, &Key{ -+ Format: pub.Type(), -+ Blob: pub.Marshal(), -+ Comment: k.comment}) -+ } -+ return ids, nil -+} -+ -+// Insert adds a private key to the keyring. If a certificate -+// is given, that certificate is added as public key. Note that -+// any constraints given are ignored. -+func (r *keyring) Add(key AddedKey) error { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return errLocked -+ } -+ signer, err := ssh.NewSignerFromKey(key.PrivateKey) -+ -+ if err != nil { -+ return err -+ } -+ -+ if cert := key.Certificate; cert != nil { -+ signer, err = ssh.NewCertSigner(cert, signer) -+ if err != nil { -+ return err -+ } -+ } -+ -+ p := privKey{ -+ signer: signer, -+ comment: key.Comment, -+ } -+ -+ if key.LifetimeSecs > 0 { -+ t := time.Now().Add(time.Duration(key.LifetimeSecs) * time.Second) -+ p.expire = &t -+ } -+ -+ r.keys = append(r.keys, p) -+ -+ return nil -+} -+ -+// Sign returns a signature for the data. -+func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { -+ return r.SignWithFlags(key, data, 0) -+} -+ -+func (r *keyring) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFlags) (*ssh.Signature, error) { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return nil, errLocked -+ } -+ -+ r.expireKeysLocked() -+ wanted := key.Marshal() -+ for _, k := range r.keys { -+ if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { -+ if flags == 0 { -+ return k.signer.Sign(rand.Reader, data) -+ } else { -+ if algorithmSigner, ok := k.signer.(ssh.AlgorithmSigner); !ok { -+ return nil, fmt.Errorf("agent: signature does not support non-default signature algorithm: %T", k.signer) -+ } else { -+ var algorithm string -+ switch flags { -+ case SignatureFlagRsaSha256: -+ algorithm = ssh.KeyAlgoRSASHA256 -+ case SignatureFlagRsaSha512: -+ algorithm = ssh.KeyAlgoRSASHA512 -+ default: -+ return nil, fmt.Errorf("agent: unsupported signature flags: %d", flags) -+ } -+ return algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm) -+ } -+ } -+ } -+ } -+ return nil, errors.New("not found") -+} -+ -+// Signers returns signers for all the known keys. -+func (r *keyring) Signers() ([]ssh.Signer, error) { -+ r.mu.Lock() -+ defer r.mu.Unlock() -+ if r.locked { -+ return nil, errLocked -+ } -+ -+ r.expireKeysLocked() -+ s := make([]ssh.Signer, 0, len(r.keys)) -+ for _, k := range r.keys { -+ s = append(s, k.signer) -+ } -+ return s, nil -+} -+ -+// The keyring does not support any extensions -+func (r *keyring) Extension(extensionType string, contents []byte) ([]byte, error) { -+ return nil, ErrExtensionUnsupported -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go -new file mode 100644 -index 00000000000000..e5d50e7e0db559 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/keyring_test.go -@@ -0,0 +1,76 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import "testing" -+ -+func addTestKey(t *testing.T, a Agent, keyName string) { -+ err := a.Add(AddedKey{ -+ PrivateKey: testPrivateKeys[keyName], -+ Comment: keyName, -+ }) -+ if err != nil { -+ t.Fatalf("failed to add key %q: %v", keyName, err) -+ } -+} -+ -+func removeTestKey(t *testing.T, a Agent, keyName string) { -+ err := a.Remove(testPublicKeys[keyName]) -+ if err != nil { -+ t.Fatalf("failed to remove key %q: %v", keyName, err) -+ } -+} -+ -+func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) { -+ listedKeys, err := a.List() -+ if err != nil { -+ t.Fatalf("failed to list keys: %v", err) -+ return -+ } -+ actualKeys := make(map[string]bool) -+ for _, key := range listedKeys { -+ actualKeys[key.Comment] = true -+ } -+ -+ matchedKeys := make(map[string]bool) -+ for _, expectedKey := range expectedKeys { -+ if !actualKeys[expectedKey] { -+ t.Fatalf("expected key %q, but was not found", expectedKey) -+ } else { -+ matchedKeys[expectedKey] = true -+ } -+ } -+ -+ for actualKey := range actualKeys { -+ if !matchedKeys[actualKey] { -+ t.Fatalf("key %q was found, but was not expected", actualKey) -+ } -+ } -+} -+ -+func TestKeyringAddingAndRemoving(t *testing.T) { -+ keyNames := []string{"dsa", "ecdsa", "rsa", "user"} -+ -+ // add all test private keys -+ k := NewKeyring() -+ for _, keyName := range keyNames { -+ addTestKey(t, k, keyName) -+ } -+ validateListedKeys(t, k, keyNames) -+ -+ // remove a key in the middle -+ keyToRemove := keyNames[1] -+ keyNames = append(keyNames[:1], keyNames[2:]...) -+ -+ removeTestKey(t, k, keyToRemove) -+ validateListedKeys(t, k, keyNames) -+ -+ // remove all keys -+ err := k.RemoveAll() -+ if err != nil { -+ t.Fatalf("failed to remove all keys: %v", err) -+ } -+ validateListedKeys(t, k, []string{}) -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/server.go b/ms_mod/golang.org/x/crypto/ssh/agent/server.go -new file mode 100644 -index 00000000000000..9a769de03d13c9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/server.go -@@ -0,0 +1,570 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "log" -+ "math/big" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/ssh" -+) -+ -+// server wraps an Agent and uses it to implement the agent side of -+// the SSH-agent, wire protocol. -+type server struct { -+ agent Agent -+} -+ -+func (s *server) processRequestBytes(reqData []byte) []byte { -+ rep, err := s.processRequest(reqData) -+ if err != nil { -+ if err != errLocked { -+ // TODO(hanwen): provide better logging interface? -+ log.Printf("agent %d: %v", reqData[0], err) -+ } -+ return []byte{agentFailure} -+ } -+ -+ if err == nil && rep == nil { -+ return []byte{agentSuccess} -+ } -+ -+ return ssh.Marshal(rep) -+} -+ -+func marshalKey(k *Key) []byte { -+ var record struct { -+ Blob []byte -+ Comment string -+ } -+ record.Blob = k.Marshal() -+ record.Comment = k.Comment -+ -+ return ssh.Marshal(&record) -+} -+ -+// See [PROTOCOL.agent], section 2.5.1. -+const agentV1IdentitiesAnswer = 2 -+ -+type agentV1IdentityMsg struct { -+ Numkeys uint32 `sshtype:"2"` -+} -+ -+type agentRemoveIdentityMsg struct { -+ KeyBlob []byte `sshtype:"18"` -+} -+ -+type agentLockMsg struct { -+ Passphrase []byte `sshtype:"22"` -+} -+ -+type agentUnlockMsg struct { -+ Passphrase []byte `sshtype:"23"` -+} -+ -+func (s *server) processRequest(data []byte) (interface{}, error) { -+ switch data[0] { -+ case agentRequestV1Identities: -+ return &agentV1IdentityMsg{0}, nil -+ -+ case agentRemoveAllV1Identities: -+ return nil, nil -+ -+ case agentRemoveIdentity: -+ var req agentRemoveIdentityMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ -+ var wk wireKey -+ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { -+ return nil, err -+ } -+ -+ return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) -+ -+ case agentRemoveAllIdentities: -+ return nil, s.agent.RemoveAll() -+ -+ case agentLock: -+ var req agentLockMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ -+ return nil, s.agent.Lock(req.Passphrase) -+ -+ case agentUnlock: -+ var req agentUnlockMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ return nil, s.agent.Unlock(req.Passphrase) -+ -+ case agentSignRequest: -+ var req signRequestAgentMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ -+ var wk wireKey -+ if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { -+ return nil, err -+ } -+ -+ k := &Key{ -+ Format: wk.Format, -+ Blob: req.KeyBlob, -+ } -+ -+ var sig *ssh.Signature -+ var err error -+ if extendedAgent, ok := s.agent.(ExtendedAgent); ok { -+ sig, err = extendedAgent.SignWithFlags(k, req.Data, SignatureFlags(req.Flags)) -+ } else { -+ sig, err = s.agent.Sign(k, req.Data) -+ } -+ -+ if err != nil { -+ return nil, err -+ } -+ return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil -+ -+ case agentRequestIdentities: -+ keys, err := s.agent.List() -+ if err != nil { -+ return nil, err -+ } -+ -+ rep := identitiesAnswerAgentMsg{ -+ NumKeys: uint32(len(keys)), -+ } -+ for _, k := range keys { -+ rep.Keys = append(rep.Keys, marshalKey(k)...) -+ } -+ return rep, nil -+ -+ case agentAddIDConstrained, agentAddIdentity: -+ return nil, s.insertIdentity(data) -+ -+ case agentExtension: -+ // Return a stub object where the whole contents of the response gets marshaled. -+ var responseStub struct { -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if extendedAgent, ok := s.agent.(ExtendedAgent); !ok { -+ // If this agent doesn't implement extensions, [PROTOCOL.agent] section 4.7 -+ // requires that we return a standard SSH_AGENT_FAILURE message. -+ responseStub.Rest = []byte{agentFailure} -+ } else { -+ var req extensionAgentMsg -+ if err := ssh.Unmarshal(data, &req); err != nil { -+ return nil, err -+ } -+ res, err := extendedAgent.Extension(req.ExtensionType, req.Contents) -+ if err != nil { -+ // If agent extensions are unsupported, return a standard SSH_AGENT_FAILURE -+ // message as required by [PROTOCOL.agent] section 4.7. -+ if err == ErrExtensionUnsupported { -+ responseStub.Rest = []byte{agentFailure} -+ } else { -+ // As the result of any other error processing an extension request, -+ // [PROTOCOL.agent] section 4.7 requires that we return a -+ // SSH_AGENT_EXTENSION_FAILURE code. -+ responseStub.Rest = []byte{agentExtensionFailure} -+ } -+ } else { -+ if len(res) == 0 { -+ return nil, nil -+ } -+ responseStub.Rest = res -+ } -+ } -+ -+ return responseStub, nil -+ } -+ -+ return nil, fmt.Errorf("unknown opcode %d", data[0]) -+} -+ -+func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) { -+ for len(constraints) != 0 { -+ switch constraints[0] { -+ case agentConstrainLifetime: -+ lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5]) -+ constraints = constraints[5:] -+ case agentConstrainConfirm: -+ confirmBeforeUse = true -+ constraints = constraints[1:] -+ case agentConstrainExtension: -+ var msg constrainExtensionAgentMsg -+ if err = ssh.Unmarshal(constraints, &msg); err != nil { -+ return 0, false, nil, err -+ } -+ extensions = append(extensions, ConstraintExtension{ -+ ExtensionName: msg.ExtensionName, -+ ExtensionDetails: msg.ExtensionDetails, -+ }) -+ constraints = msg.Rest -+ default: -+ return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0]) -+ } -+ } -+ return -+} -+ -+func setConstraints(key *AddedKey, constraintBytes []byte) error { -+ lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes) -+ if err != nil { -+ return err -+ } -+ -+ key.LifetimeSecs = lifetimeSecs -+ key.ConfirmBeforeUse = confirmBeforeUse -+ key.ConstraintExtensions = constraintExtensions -+ return nil -+} -+ -+func parseRSAKey(req []byte) (*AddedKey, error) { -+ var k rsaKeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ if k.E.BitLen() > 30 { -+ return nil, errors.New("agent: RSA public exponent too large") -+ } -+ priv := &rsa.PrivateKey{ -+ PublicKey: rsa.PublicKey{ -+ E: int(k.E.Int64()), -+ N: k.N, -+ }, -+ D: k.D, -+ Primes: []*big.Int{k.P, k.Q}, -+ } -+ priv.Precompute() -+ -+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseEd25519Key(req []byte) (*AddedKey, error) { -+ var k ed25519KeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ priv := ed25519.PrivateKey(k.Priv) -+ -+ addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseDSAKey(req []byte) (*AddedKey, error) { -+ var k dsaKeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ priv := &dsa.PrivateKey{ -+ PublicKey: dsa.PublicKey{ -+ Parameters: dsa.Parameters{ -+ P: k.P, -+ Q: k.Q, -+ G: k.G, -+ }, -+ Y: k.Y, -+ }, -+ X: k.X, -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) { -+ priv = &ecdsa.PrivateKey{ -+ D: privScalar, -+ } -+ -+ switch curveName { -+ case "nistp256": -+ priv.Curve = elliptic.P256() -+ case "nistp384": -+ priv.Curve = elliptic.P384() -+ case "nistp521": -+ priv.Curve = elliptic.P521() -+ default: -+ return nil, fmt.Errorf("agent: unknown curve %q", curveName) -+ } -+ -+ priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes) -+ if priv.X == nil || priv.Y == nil { -+ return nil, errors.New("agent: point not on curve") -+ } -+ -+ return priv, nil -+} -+ -+func parseEd25519Cert(req []byte) (*AddedKey, error) { -+ var k ed25519CertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ priv := ed25519.PrivateKey(k.Priv) -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad ED25519 certificate") -+ } -+ -+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseECDSAKey(req []byte) (*AddedKey, error) { -+ var k ecdsaKeyMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ -+ priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D) -+ if err != nil { -+ return nil, err -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseRSACert(req []byte) (*AddedKey, error) { -+ var k rsaCertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad RSA certificate") -+ } -+ -+ // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go -+ var rsaPub struct { -+ Name string -+ E *big.Int -+ N *big.Int -+ } -+ if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil { -+ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) -+ } -+ -+ if rsaPub.E.BitLen() > 30 { -+ return nil, errors.New("agent: RSA public exponent too large") -+ } -+ -+ priv := rsa.PrivateKey{ -+ PublicKey: rsa.PublicKey{ -+ E: int(rsaPub.E.Int64()), -+ N: rsaPub.N, -+ }, -+ D: k.D, -+ Primes: []*big.Int{k.Q, k.P}, -+ } -+ priv.Precompute() -+ -+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseDSACert(req []byte) (*AddedKey, error) { -+ var k dsaCertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad DSA certificate") -+ } -+ -+ // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go -+ var w struct { -+ Name string -+ P, Q, G, Y *big.Int -+ } -+ if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil { -+ return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) -+ } -+ -+ priv := &dsa.PrivateKey{ -+ PublicKey: dsa.PublicKey{ -+ Parameters: dsa.Parameters{ -+ P: w.P, -+ Q: w.Q, -+ G: w.G, -+ }, -+ Y: w.Y, -+ }, -+ X: k.X, -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func parseECDSACert(req []byte) (*AddedKey, error) { -+ var k ecdsaCertMsg -+ if err := ssh.Unmarshal(req, &k); err != nil { -+ return nil, err -+ } -+ -+ pubKey, err := ssh.ParsePublicKey(k.CertBytes) -+ if err != nil { -+ return nil, err -+ } -+ cert, ok := pubKey.(*ssh.Certificate) -+ if !ok { -+ return nil, errors.New("agent: bad ECDSA certificate") -+ } -+ -+ // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go -+ var ecdsaPub struct { -+ Name string -+ ID string -+ Key []byte -+ } -+ if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil { -+ return nil, err -+ } -+ -+ priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D) -+ if err != nil { -+ return nil, err -+ } -+ -+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} -+ if err := setConstraints(addedKey, k.Constraints); err != nil { -+ return nil, err -+ } -+ return addedKey, nil -+} -+ -+func (s *server) insertIdentity(req []byte) error { -+ var record struct { -+ Type string `sshtype:"17|25"` -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := ssh.Unmarshal(req, &record); err != nil { -+ return err -+ } -+ -+ var addedKey *AddedKey -+ var err error -+ -+ switch record.Type { -+ case ssh.KeyAlgoRSA: -+ addedKey, err = parseRSAKey(req) -+ case ssh.KeyAlgoDSA: -+ addedKey, err = parseDSAKey(req) -+ case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: -+ addedKey, err = parseECDSAKey(req) -+ case ssh.KeyAlgoED25519: -+ addedKey, err = parseEd25519Key(req) -+ case ssh.CertAlgoRSAv01: -+ addedKey, err = parseRSACert(req) -+ case ssh.CertAlgoDSAv01: -+ addedKey, err = parseDSACert(req) -+ case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: -+ addedKey, err = parseECDSACert(req) -+ case ssh.CertAlgoED25519v01: -+ addedKey, err = parseEd25519Cert(req) -+ default: -+ return fmt.Errorf("agent: not implemented: %q", record.Type) -+ } -+ -+ if err != nil { -+ return err -+ } -+ return s.agent.Add(*addedKey) -+} -+ -+// ServeAgent serves the agent protocol on the given connection. It -+// returns when an I/O error occurs. -+func ServeAgent(agent Agent, c io.ReadWriter) error { -+ s := &server{agent} -+ -+ var length [4]byte -+ for { -+ if _, err := io.ReadFull(c, length[:]); err != nil { -+ return err -+ } -+ l := binary.BigEndian.Uint32(length[:]) -+ if l == 0 { -+ return fmt.Errorf("agent: request size is 0") -+ } -+ if l > maxAgentResponseBytes { -+ // We also cap requests. -+ return fmt.Errorf("agent: request too large: %d", l) -+ } -+ -+ req := make([]byte, l) -+ if _, err := io.ReadFull(c, req); err != nil { -+ return err -+ } -+ -+ repData := s.processRequestBytes(req) -+ if len(repData) > maxAgentResponseBytes { -+ return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) -+ } -+ -+ binary.BigEndian.PutUint32(length[:], uint32(len(repData))) -+ if _, err := c.Write(length[:]); err != nil { -+ return err -+ } -+ if _, err := c.Write(repData); err != nil { -+ return err -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/server_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/server_test.go -new file mode 100644 -index 00000000000000..0af85457e4da9d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/server_test.go -@@ -0,0 +1,262 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package agent -+ -+import ( -+ "crypto" -+ "crypto/rand" -+ "fmt" -+ pseudorand "math/rand" -+ "reflect" -+ "strings" -+ "testing" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+func TestServer(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ client := NewClient(c1) -+ -+ go ServeAgent(NewKeyring(), c2) -+ -+ testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0) -+} -+ -+func TestLockServer(t *testing.T) { -+ testLockAgent(NewKeyring(), t) -+} -+ -+func TestSetupForwardAgent(t *testing.T) { -+ a, b, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ -+ defer a.Close() -+ defer b.Close() -+ -+ _, socket, cleanup := startOpenSSHAgent(t) -+ defer cleanup() -+ -+ serverConf := ssh.ServerConfig{ -+ NoClientAuth: true, -+ } -+ serverConf.AddHostKey(testSigners["rsa"]) -+ incoming := make(chan *ssh.ServerConn, 1) -+ go func() { -+ conn, _, _, err := ssh.NewServerConn(a, &serverConf) -+ incoming <- conn -+ if err != nil { -+ t.Errorf("NewServerConn error: %v", err) -+ return -+ } -+ }() -+ -+ conf := ssh.ClientConfig{ -+ HostKeyCallback: ssh.InsecureIgnoreHostKey(), -+ } -+ conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) -+ if err != nil { -+ t.Fatalf("NewClientConn: %v", err) -+ } -+ client := ssh.NewClient(conn, chans, reqs) -+ -+ if err := ForwardToRemote(client, socket); err != nil { -+ t.Fatalf("SetupForwardAgent: %v", err) -+ } -+ server := <-incoming -+ if server == nil { -+ t.Fatal("Unable to get server") -+ } -+ ch, reqs, err := server.OpenChannel(channelType, nil) -+ if err != nil { -+ t.Fatalf("OpenChannel(%q): %v", channelType, err) -+ } -+ go ssh.DiscardRequests(reqs) -+ -+ agentClient := NewClient(ch) -+ testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0) -+ conn.Close() -+} -+ -+func TestV1ProtocolMessages(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ c := NewClient(c1) -+ -+ go ServeAgent(NewKeyring(), c2) -+ -+ testV1ProtocolMessages(t, c.(*client)) -+} -+ -+func testV1ProtocolMessages(t *testing.T, c *client) { -+ reply, err := c.call([]byte{agentRequestV1Identities}) -+ if err != nil { -+ t.Fatalf("v1 request all failed: %v", err) -+ } -+ if msg, ok := reply.(*agentV1IdentityMsg); !ok || msg.Numkeys != 0 { -+ t.Fatalf("invalid request all response: %#v", reply) -+ } -+ -+ reply, err = c.call([]byte{agentRemoveAllV1Identities}) -+ if err != nil { -+ t.Fatalf("v1 remove all failed: %v", err) -+ } -+ if _, ok := reply.(*successAgentMsg); !ok { -+ t.Fatalf("invalid remove all response: %#v", reply) -+ } -+} -+ -+func verifyKey(sshAgent Agent) error { -+ keys, err := sshAgent.List() -+ if err != nil { -+ return fmt.Errorf("listing keys: %v", err) -+ } -+ -+ if len(keys) != 1 { -+ return fmt.Errorf("bad number of keys found. expected 1, got %d", len(keys)) -+ } -+ -+ buf := make([]byte, 128) -+ if _, err := rand.Read(buf); err != nil { -+ return fmt.Errorf("rand: %v", err) -+ } -+ -+ sig, err := sshAgent.Sign(keys[0], buf) -+ if err != nil { -+ return fmt.Errorf("sign: %v", err) -+ } -+ -+ if err := keys[0].Verify(buf, sig); err != nil { -+ return fmt.Errorf("verify: %v", err) -+ } -+ return nil -+} -+ -+func addKeyToAgent(key crypto.PrivateKey) error { -+ sshAgent := NewKeyring() -+ if err := sshAgent.Add(AddedKey{PrivateKey: key}); err != nil { -+ return fmt.Errorf("add: %v", err) -+ } -+ return verifyKey(sshAgent) -+} -+ -+func TestKeyTypes(t *testing.T) { -+ for k, v := range testPrivateKeys { -+ if err := addKeyToAgent(v); err != nil { -+ t.Errorf("error adding key type %s, %v", k, err) -+ } -+ if err := addCertToAgentSock(v, nil); err != nil { -+ t.Errorf("error adding key type %s, %v", k, err) -+ } -+ } -+} -+ -+func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error { -+ a, b, err := netPipe() -+ if err != nil { -+ return err -+ } -+ agentServer := NewKeyring() -+ go ServeAgent(agentServer, a) -+ -+ agentClient := NewClient(b) -+ if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { -+ return fmt.Errorf("add: %v", err) -+ } -+ return verifyKey(agentClient) -+} -+ -+func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error { -+ sshAgent := NewKeyring() -+ if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { -+ return fmt.Errorf("add: %v", err) -+ } -+ return verifyKey(sshAgent) -+} -+ -+func TestCertTypes(t *testing.T) { -+ for keyType, key := range testPublicKeys { -+ cert := &ssh.Certificate{ -+ ValidPrincipals: []string{"gopher1"}, -+ ValidAfter: 0, -+ ValidBefore: ssh.CertTimeInfinity, -+ Key: key, -+ Serial: 1, -+ CertType: ssh.UserCert, -+ SignatureKey: testPublicKeys["rsa"], -+ Permissions: ssh.Permissions{ -+ CriticalOptions: map[string]string{}, -+ Extensions: map[string]string{}, -+ }, -+ } -+ if err := cert.SignCert(rand.Reader, testSigners["rsa"]); err != nil { -+ t.Fatalf("signcert: %v", err) -+ } -+ if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil { -+ t.Fatalf("%v", err) -+ } -+ if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil { -+ t.Fatalf("%v", err) -+ } -+ } -+} -+ -+func TestParseConstraints(t *testing.T) { -+ // Test LifetimeSecs -+ var msg = constrainLifetimeAgentMsg{pseudorand.Uint32()} -+ lifetimeSecs, _, _, err := parseConstraints(ssh.Marshal(msg)) -+ if err != nil { -+ t.Fatalf("parseConstraints: %v", err) -+ } -+ if lifetimeSecs != msg.LifetimeSecs { -+ t.Errorf("got lifetime %v, want %v", lifetimeSecs, msg.LifetimeSecs) -+ } -+ -+ // Test ConfirmBeforeUse -+ _, confirmBeforeUse, _, err := parseConstraints([]byte{agentConstrainConfirm}) -+ if err != nil { -+ t.Fatalf("%v", err) -+ } -+ if !confirmBeforeUse { -+ t.Error("got comfirmBeforeUse == false") -+ } -+ -+ // Test ConstraintExtensions -+ var data []byte -+ var expect []ConstraintExtension -+ for i := 0; i < 10; i++ { -+ var ext = ConstraintExtension{ -+ ExtensionName: fmt.Sprintf("name%d", i), -+ ExtensionDetails: []byte(fmt.Sprintf("details: %d", i)), -+ } -+ expect = append(expect, ext) -+ data = append(data, agentConstrainExtension) -+ data = append(data, ssh.Marshal(ext)...) -+ } -+ _, _, extensions, err := parseConstraints(data) -+ if err != nil { -+ t.Fatalf("%v", err) -+ } -+ if !reflect.DeepEqual(expect, extensions) { -+ t.Errorf("got extension %v, want %v", extensions, expect) -+ } -+ -+ // Test Unknown Constraint -+ _, _, _, err = parseConstraints([]byte{128}) -+ if err == nil || !strings.Contains(err.Error(), "unknown constraint") { -+ t.Errorf("unexpected error: %v", err) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go b/ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go -new file mode 100644 -index 00000000000000..cc42a87cb967ea ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/agent/testdata_test.go -@@ -0,0 +1,64 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: -+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three -+// instances. -+ -+package agent -+ -+import ( -+ "crypto/rand" -+ "fmt" -+ -+ "golang.org/x/crypto/ssh" -+ "golang.org/x/crypto/ssh/testdata" -+) -+ -+var ( -+ testPrivateKeys map[string]interface{} -+ testSigners map[string]ssh.Signer -+ testPublicKeys map[string]ssh.PublicKey -+) -+ -+func init() { -+ var err error -+ -+ n := len(testdata.PEMBytes) -+ testPrivateKeys = make(map[string]interface{}, n) -+ testSigners = make(map[string]ssh.Signer, n) -+ testPublicKeys = make(map[string]ssh.PublicKey, n) -+ for t, k := range testdata.PEMBytes { -+ testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) -+ } -+ testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) -+ } -+ testPublicKeys[t] = testSigners[t].PublicKey() -+ } -+ -+ // Create a cert and sign it for use in tests. -+ testCert := &ssh.Certificate{ -+ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil -+ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage -+ ValidAfter: 0, // unix epoch -+ ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. -+ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil -+ Key: testPublicKeys["ecdsa"], -+ SignatureKey: testPublicKeys["rsa"], -+ Permissions: ssh.Permissions{ -+ CriticalOptions: map[string]string{}, -+ Extensions: map[string]string{}, -+ }, -+ } -+ testCert.SignCert(rand.Reader, testSigners["rsa"]) -+ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] -+ testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/benchmark_test.go b/ms_mod/golang.org/x/crypto/ssh/benchmark_test.go -new file mode 100644 -index 00000000000000..b356330b469d2e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/benchmark_test.go -@@ -0,0 +1,127 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "errors" -+ "fmt" -+ "io" -+ "net" -+ "testing" -+) -+ -+type server struct { -+ *ServerConn -+ chans <-chan NewChannel -+} -+ -+func newServer(c net.Conn, conf *ServerConfig) (*server, error) { -+ sconn, chans, reqs, err := NewServerConn(c, conf) -+ if err != nil { -+ return nil, err -+ } -+ go DiscardRequests(reqs) -+ return &server{sconn, chans}, nil -+} -+ -+func (s *server) Accept() (NewChannel, error) { -+ n, ok := <-s.chans -+ if !ok { -+ return nil, io.EOF -+ } -+ return n, nil -+} -+ -+func sshPipe() (Conn, *server, error) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ clientConf := ClientConfig{ -+ User: "user", -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ serverConf := ServerConfig{ -+ NoClientAuth: true, -+ } -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ done := make(chan *server, 1) -+ go func() { -+ server, err := newServer(c2, &serverConf) -+ if err != nil { -+ done <- nil -+ } -+ done <- server -+ }() -+ -+ client, _, reqs, err := NewClientConn(c1, "", &clientConf) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ server := <-done -+ if server == nil { -+ return nil, nil, errors.New("server handshake failed.") -+ } -+ go DiscardRequests(reqs) -+ -+ return client, server, nil -+} -+ -+func BenchmarkEndToEnd(b *testing.B) { -+ b.StopTimer() -+ -+ client, server, err := sshPipe() -+ if err != nil { -+ b.Fatalf("sshPipe: %v", err) -+ } -+ -+ defer client.Close() -+ defer server.Close() -+ -+ size := (1 << 20) -+ input := make([]byte, size) -+ output := make([]byte, size) -+ b.SetBytes(int64(size)) -+ done := make(chan int, 1) -+ -+ go func() { -+ newCh, err := server.Accept() -+ if err != nil { -+ panic(fmt.Sprintf("Client: %v", err)) -+ } -+ ch, incoming, err := newCh.Accept() -+ if err != nil { -+ panic(fmt.Sprintf("Accept: %v", err)) -+ } -+ go DiscardRequests(incoming) -+ for i := 0; i < b.N; i++ { -+ if _, err := io.ReadFull(ch, output); err != nil { -+ panic(fmt.Sprintf("ReadFull: %v", err)) -+ } -+ } -+ ch.Close() -+ done <- 1 -+ }() -+ -+ ch, in, err := client.OpenChannel("speed", nil) -+ if err != nil { -+ b.Fatalf("OpenChannel: %v", err) -+ } -+ go DiscardRequests(in) -+ -+ b.ResetTimer() -+ b.StartTimer() -+ for i := 0; i < b.N; i++ { -+ if _, err := ch.Write(input); err != nil { -+ b.Fatalf("WriteFull: %v", err) -+ } -+ } -+ ch.Close() -+ b.StopTimer() -+ -+ <-done -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/buffer.go b/ms_mod/golang.org/x/crypto/ssh/buffer.go -new file mode 100644 -index 00000000000000..1ab07d078db163 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/buffer.go -@@ -0,0 +1,97 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "io" -+ "sync" -+) -+ -+// buffer provides a linked list buffer for data exchange -+// between producer and consumer. Theoretically the buffer is -+// of unlimited capacity as it does no allocation of its own. -+type buffer struct { -+ // protects concurrent access to head, tail and closed -+ *sync.Cond -+ -+ head *element // the buffer that will be read first -+ tail *element // the buffer that will be read last -+ -+ closed bool -+} -+ -+// An element represents a single link in a linked list. -+type element struct { -+ buf []byte -+ next *element -+} -+ -+// newBuffer returns an empty buffer that is not closed. -+func newBuffer() *buffer { -+ e := new(element) -+ b := &buffer{ -+ Cond: newCond(), -+ head: e, -+ tail: e, -+ } -+ return b -+} -+ -+// write makes buf available for Read to receive. -+// buf must not be modified after the call to write. -+func (b *buffer) write(buf []byte) { -+ b.Cond.L.Lock() -+ e := &element{buf: buf} -+ b.tail.next = e -+ b.tail = e -+ b.Cond.Signal() -+ b.Cond.L.Unlock() -+} -+ -+// eof closes the buffer. Reads from the buffer once all -+// the data has been consumed will receive io.EOF. -+func (b *buffer) eof() { -+ b.Cond.L.Lock() -+ b.closed = true -+ b.Cond.Signal() -+ b.Cond.L.Unlock() -+} -+ -+// Read reads data from the internal buffer in buf. Reads will block -+// if no data is available, or until the buffer is closed. -+func (b *buffer) Read(buf []byte) (n int, err error) { -+ b.Cond.L.Lock() -+ defer b.Cond.L.Unlock() -+ -+ for len(buf) > 0 { -+ // if there is data in b.head, copy it -+ if len(b.head.buf) > 0 { -+ r := copy(buf, b.head.buf) -+ buf, b.head.buf = buf[r:], b.head.buf[r:] -+ n += r -+ continue -+ } -+ // if there is a next buffer, make it the head -+ if len(b.head.buf) == 0 && b.head != b.tail { -+ b.head = b.head.next -+ continue -+ } -+ -+ // if at least one byte has been copied, return -+ if n > 0 { -+ break -+ } -+ -+ // if nothing was read, and there is nothing outstanding -+ // check to see if the buffer is closed. -+ if b.closed { -+ err = io.EOF -+ break -+ } -+ // out of buffers, wait for producer -+ b.Cond.Wait() -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/buffer_test.go b/ms_mod/golang.org/x/crypto/ssh/buffer_test.go -new file mode 100644 -index 00000000000000..d5781cb3da997f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/buffer_test.go -@@ -0,0 +1,87 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "io" -+ "testing" -+) -+ -+var alphabet = []byte("abcdefghijklmnopqrstuvwxyz") -+ -+func TestBufferReadwrite(t *testing.T) { -+ b := newBuffer() -+ b.write(alphabet[:10]) -+ r, _ := b.Read(make([]byte, 10)) -+ if r != 10 { -+ t.Fatalf("Expected written == read == 10, written: 10, read %d", r) -+ } -+ -+ b = newBuffer() -+ b.write(alphabet[:5]) -+ r, _ = b.Read(make([]byte, 10)) -+ if r != 5 { -+ t.Fatalf("Expected written == read == 5, written: 5, read %d", r) -+ } -+ -+ b = newBuffer() -+ b.write(alphabet[:10]) -+ r, _ = b.Read(make([]byte, 5)) -+ if r != 5 { -+ t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r) -+ } -+ -+ b = newBuffer() -+ b.write(alphabet[:5]) -+ b.write(alphabet[5:15]) -+ r, _ = b.Read(make([]byte, 10)) -+ r2, _ := b.Read(make([]byte, 10)) -+ if r != 10 || r2 != 5 || 15 != r+r2 { -+ t.Fatal("Expected written == read == 15") -+ } -+} -+ -+func TestBufferClose(t *testing.T) { -+ b := newBuffer() -+ b.write(alphabet[:10]) -+ b.eof() -+ _, err := b.Read(make([]byte, 5)) -+ if err != nil { -+ t.Fatal("expected read of 5 to not return EOF") -+ } -+ b = newBuffer() -+ b.write(alphabet[:10]) -+ b.eof() -+ r, err := b.Read(make([]byte, 5)) -+ r2, err2 := b.Read(make([]byte, 10)) -+ if r != 5 || r2 != 5 || err != nil || err2 != nil { -+ t.Fatal("expected reads of 5 and 5") -+ } -+ -+ b = newBuffer() -+ b.write(alphabet[:10]) -+ b.eof() -+ r, err = b.Read(make([]byte, 5)) -+ r2, err2 = b.Read(make([]byte, 10)) -+ r3, err3 := b.Read(make([]byte, 10)) -+ if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF { -+ t.Fatal("expected reads of 5 and 5 and 0, with EOF") -+ } -+ -+ b = newBuffer() -+ b.write(make([]byte, 5)) -+ b.write(make([]byte, 10)) -+ b.eof() -+ r, err = b.Read(make([]byte, 9)) -+ r2, err2 = b.Read(make([]byte, 3)) -+ r3, err3 = b.Read(make([]byte, 3)) -+ r4, err4 := b.Read(make([]byte, 10)) -+ if err != nil || err2 != nil || err3 != nil || err4 != io.EOF { -+ t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4) -+ } -+ if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 { -+ t.Fatal("Expected written == read == 15", r, r2, r3, r4) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/certs.go b/ms_mod/golang.org/x/crypto/ssh/certs.go -new file mode 100644 -index 00000000000000..fc04d03e19879d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/certs.go -@@ -0,0 +1,589 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "io" -+ "net" -+ "sort" -+ "time" -+) -+ -+// Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear -+// in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. -+// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't -+// appear in the Signature.Format field. -+const ( -+ CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" -+ CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" -+ CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" -+ CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" -+ CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" -+ CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" -+ CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" -+ CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" -+ -+ // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a -+ // Certificate.Type (or PublicKey.Type), but only in -+ // ClientConfig.HostKeyAlgorithms. -+ CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com" -+ CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com" -+) -+ -+const ( -+ // Deprecated: use CertAlgoRSAv01. -+ CertSigAlgoRSAv01 = CertAlgoRSAv01 -+ // Deprecated: use CertAlgoRSASHA256v01. -+ CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01 -+ // Deprecated: use CertAlgoRSASHA512v01. -+ CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01 -+) -+ -+// Certificate types distinguish between host and user -+// certificates. The values can be set in the CertType field of -+// Certificate. -+const ( -+ UserCert = 1 -+ HostCert = 2 -+) -+ -+// Signature represents a cryptographic signature. -+type Signature struct { -+ Format string -+ Blob []byte -+ Rest []byte `ssh:"rest"` -+} -+ -+// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that -+// a certificate does not expire. -+const CertTimeInfinity = 1<<64 - 1 -+ -+// An Certificate represents an OpenSSH certificate as defined in -+// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the -+// PublicKey interface, so it can be unmarshaled using -+// ParsePublicKey. -+type Certificate struct { -+ Nonce []byte -+ Key PublicKey -+ Serial uint64 -+ CertType uint32 -+ KeyId string -+ ValidPrincipals []string -+ ValidAfter uint64 -+ ValidBefore uint64 -+ Permissions -+ Reserved []byte -+ SignatureKey PublicKey -+ Signature *Signature -+} -+ -+// genericCertData holds the key-independent part of the certificate data. -+// Overall, certificates contain an nonce, public key fields and -+// key-independent fields. -+type genericCertData struct { -+ Serial uint64 -+ CertType uint32 -+ KeyId string -+ ValidPrincipals []byte -+ ValidAfter uint64 -+ ValidBefore uint64 -+ CriticalOptions []byte -+ Extensions []byte -+ Reserved []byte -+ SignatureKey []byte -+ Signature []byte -+} -+ -+func marshalStringList(namelist []string) []byte { -+ var to []byte -+ for _, name := range namelist { -+ s := struct{ N string }{name} -+ to = append(to, Marshal(&s)...) -+ } -+ return to -+} -+ -+type optionsTuple struct { -+ Key string -+ Value []byte -+} -+ -+type optionsTupleValue struct { -+ Value string -+} -+ -+// serialize a map of critical options or extensions -+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, -+// we need two length prefixes for a non-empty string value -+func marshalTuples(tups map[string]string) []byte { -+ keys := make([]string, 0, len(tups)) -+ for key := range tups { -+ keys = append(keys, key) -+ } -+ sort.Strings(keys) -+ -+ var ret []byte -+ for _, key := range keys { -+ s := optionsTuple{Key: key} -+ if value := tups[key]; len(value) > 0 { -+ s.Value = Marshal(&optionsTupleValue{value}) -+ } -+ ret = append(ret, Marshal(&s)...) -+ } -+ return ret -+} -+ -+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, -+// we need two length prefixes for a non-empty option value -+func parseTuples(in []byte) (map[string]string, error) { -+ tups := map[string]string{} -+ var lastKey string -+ var haveLastKey bool -+ -+ for len(in) > 0 { -+ var key, val, extra []byte -+ var ok bool -+ -+ if key, in, ok = parseString(in); !ok { -+ return nil, errShortRead -+ } -+ keyStr := string(key) -+ // according to [PROTOCOL.certkeys], the names must be in -+ // lexical order. -+ if haveLastKey && keyStr <= lastKey { -+ return nil, fmt.Errorf("ssh: certificate options are not in lexical order") -+ } -+ lastKey, haveLastKey = keyStr, true -+ // the next field is a data field, which if non-empty has a string embedded -+ if val, in, ok = parseString(in); !ok { -+ return nil, errShortRead -+ } -+ if len(val) > 0 { -+ val, extra, ok = parseString(val) -+ if !ok { -+ return nil, errShortRead -+ } -+ if len(extra) > 0 { -+ return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") -+ } -+ tups[keyStr] = string(val) -+ } else { -+ tups[keyStr] = "" -+ } -+ } -+ return tups, nil -+} -+ -+func parseCert(in []byte, privAlgo string) (*Certificate, error) { -+ nonce, rest, ok := parseString(in) -+ if !ok { -+ return nil, errShortRead -+ } -+ -+ key, rest, err := parsePubKey(rest, privAlgo) -+ if err != nil { -+ return nil, err -+ } -+ -+ var g genericCertData -+ if err := Unmarshal(rest, &g); err != nil { -+ return nil, err -+ } -+ -+ c := &Certificate{ -+ Nonce: nonce, -+ Key: key, -+ Serial: g.Serial, -+ CertType: g.CertType, -+ KeyId: g.KeyId, -+ ValidAfter: g.ValidAfter, -+ ValidBefore: g.ValidBefore, -+ } -+ -+ for principals := g.ValidPrincipals; len(principals) > 0; { -+ principal, rest, ok := parseString(principals) -+ if !ok { -+ return nil, errShortRead -+ } -+ c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) -+ principals = rest -+ } -+ -+ c.CriticalOptions, err = parseTuples(g.CriticalOptions) -+ if err != nil { -+ return nil, err -+ } -+ c.Extensions, err = parseTuples(g.Extensions) -+ if err != nil { -+ return nil, err -+ } -+ c.Reserved = g.Reserved -+ k, err := ParsePublicKey(g.SignatureKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ c.SignatureKey = k -+ c.Signature, rest, ok = parseSignatureBody(g.Signature) -+ if !ok || len(rest) > 0 { -+ return nil, errors.New("ssh: signature parse error") -+ } -+ -+ return c, nil -+} -+ -+type openSSHCertSigner struct { -+ pub *Certificate -+ signer Signer -+} -+ -+type algorithmOpenSSHCertSigner struct { -+ *openSSHCertSigner -+ algorithmSigner AlgorithmSigner -+} -+ -+// NewCertSigner returns a Signer that signs with the given Certificate, whose -+// private key is held by signer. It returns an error if the public key in cert -+// doesn't match the key used by signer. -+func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { -+ if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) { -+ return nil, errors.New("ssh: signer and cert have different public key") -+ } -+ -+ if algorithmSigner, ok := signer.(AlgorithmSigner); ok { -+ return &algorithmOpenSSHCertSigner{ -+ &openSSHCertSigner{cert, signer}, algorithmSigner}, nil -+ } else { -+ return &openSSHCertSigner{cert, signer}, nil -+ } -+} -+ -+func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { -+ return s.signer.Sign(rand, data) -+} -+ -+func (s *openSSHCertSigner) PublicKey() PublicKey { -+ return s.pub -+} -+ -+func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -+ return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm) -+} -+ -+const sourceAddressCriticalOption = "source-address" -+ -+// CertChecker does the work of verifying a certificate. Its methods -+// can be plugged into ClientConfig.HostKeyCallback and -+// ServerConfig.PublicKeyCallback. For the CertChecker to work, -+// minimally, the IsAuthority callback should be set. -+type CertChecker struct { -+ // SupportedCriticalOptions lists the CriticalOptions that the -+ // server application layer understands. These are only used -+ // for user certificates. -+ SupportedCriticalOptions []string -+ -+ // IsUserAuthority should return true if the key is recognized as an -+ // authority for the given user certificate. This allows for -+ // certificates to be signed by other certificates. This must be set -+ // if this CertChecker will be checking user certificates. -+ IsUserAuthority func(auth PublicKey) bool -+ -+ // IsHostAuthority should report whether the key is recognized as -+ // an authority for this host. This allows for certificates to be -+ // signed by other keys, and for those other keys to only be valid -+ // signers for particular hostnames. This must be set if this -+ // CertChecker will be checking host certificates. -+ IsHostAuthority func(auth PublicKey, address string) bool -+ -+ // Clock is used for verifying time stamps. If nil, time.Now -+ // is used. -+ Clock func() time.Time -+ -+ // UserKeyFallback is called when CertChecker.Authenticate encounters a -+ // public key that is not a certificate. It must implement validation -+ // of user keys or else, if nil, all such keys are rejected. -+ UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) -+ -+ // HostKeyFallback is called when CertChecker.CheckHostKey encounters a -+ // public key that is not a certificate. It must implement host key -+ // validation or else, if nil, all such keys are rejected. -+ HostKeyFallback HostKeyCallback -+ -+ // IsRevoked is called for each certificate so that revocation checking -+ // can be implemented. It should return true if the given certificate -+ // is revoked and false otherwise. If nil, no certificates are -+ // considered to have been revoked. -+ IsRevoked func(cert *Certificate) bool -+} -+ -+// CheckHostKey checks a host key certificate. This method can be -+// plugged into ClientConfig.HostKeyCallback. -+func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { -+ cert, ok := key.(*Certificate) -+ if !ok { -+ if c.HostKeyFallback != nil { -+ return c.HostKeyFallback(addr, remote, key) -+ } -+ return errors.New("ssh: non-certificate host key") -+ } -+ if cert.CertType != HostCert { -+ return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) -+ } -+ if !c.IsHostAuthority(cert.SignatureKey, addr) { -+ return fmt.Errorf("ssh: no authorities for hostname: %v", addr) -+ } -+ -+ hostname, _, err := net.SplitHostPort(addr) -+ if err != nil { -+ return err -+ } -+ -+ // Pass hostname only as principal for host certificates (consistent with OpenSSH) -+ return c.CheckCert(hostname, cert) -+} -+ -+// Authenticate checks a user certificate. Authenticate can be used as -+// a value for ServerConfig.PublicKeyCallback. -+func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { -+ cert, ok := pubKey.(*Certificate) -+ if !ok { -+ if c.UserKeyFallback != nil { -+ return c.UserKeyFallback(conn, pubKey) -+ } -+ return nil, errors.New("ssh: normal key pairs not accepted") -+ } -+ -+ if cert.CertType != UserCert { -+ return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) -+ } -+ if !c.IsUserAuthority(cert.SignatureKey) { -+ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") -+ } -+ -+ if err := c.CheckCert(conn.User(), cert); err != nil { -+ return nil, err -+ } -+ -+ return &cert.Permissions, nil -+} -+ -+// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and -+// the signature of the certificate. -+func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { -+ if c.IsRevoked != nil && c.IsRevoked(cert) { -+ return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) -+ } -+ -+ for opt := range cert.CriticalOptions { -+ // sourceAddressCriticalOption will be enforced by -+ // serverAuthenticate -+ if opt == sourceAddressCriticalOption { -+ continue -+ } -+ -+ found := false -+ for _, supp := range c.SupportedCriticalOptions { -+ if supp == opt { -+ found = true -+ break -+ } -+ } -+ if !found { -+ return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) -+ } -+ } -+ -+ if len(cert.ValidPrincipals) > 0 { -+ // By default, certs are valid for all users/hosts. -+ found := false -+ for _, p := range cert.ValidPrincipals { -+ if p == principal { -+ found = true -+ break -+ } -+ } -+ if !found { -+ return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) -+ } -+ } -+ -+ clock := c.Clock -+ if clock == nil { -+ clock = time.Now -+ } -+ -+ unixNow := clock().Unix() -+ if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { -+ return fmt.Errorf("ssh: cert is not yet valid") -+ } -+ if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { -+ return fmt.Errorf("ssh: cert has expired") -+ } -+ if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { -+ return fmt.Errorf("ssh: certificate signature does not verify") -+ } -+ -+ return nil -+} -+ -+// SignCert signs the certificate with an authority, setting the Nonce, -+// SignatureKey, and Signature fields. -+func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { -+ c.Nonce = make([]byte, 32) -+ if _, err := io.ReadFull(rand, c.Nonce); err != nil { -+ return err -+ } -+ c.SignatureKey = authority.PublicKey() -+ -+ // Default to KeyAlgoRSASHA512 for ssh-rsa signers. -+ if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { -+ sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512) -+ if err != nil { -+ return err -+ } -+ c.Signature = sig -+ return nil -+ } -+ -+ sig, err := authority.Sign(rand, c.bytesForSigning()) -+ if err != nil { -+ return err -+ } -+ c.Signature = sig -+ return nil -+} -+ -+// certKeyAlgoNames is a mapping from known certificate algorithm names to the -+// corresponding public key signature algorithm. -+// -+// This map must be kept in sync with the one in agent/client.go. -+var certKeyAlgoNames = map[string]string{ -+ CertAlgoRSAv01: KeyAlgoRSA, -+ CertAlgoRSASHA256v01: KeyAlgoRSASHA256, -+ CertAlgoRSASHA512v01: KeyAlgoRSASHA512, -+ CertAlgoDSAv01: KeyAlgoDSA, -+ CertAlgoECDSA256v01: KeyAlgoECDSA256, -+ CertAlgoECDSA384v01: KeyAlgoECDSA384, -+ CertAlgoECDSA521v01: KeyAlgoECDSA521, -+ CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, -+ CertAlgoED25519v01: KeyAlgoED25519, -+ CertAlgoSKED25519v01: KeyAlgoSKED25519, -+} -+ -+// underlyingAlgo returns the signature algorithm associated with algo (which is -+// an advertised or negotiated public key or host key algorithm). These are -+// usually the same, except for certificate algorithms. -+func underlyingAlgo(algo string) string { -+ if a, ok := certKeyAlgoNames[algo]; ok { -+ return a -+ } -+ return algo -+} -+ -+// certificateAlgo returns the certificate algorithms that uses the provided -+// underlying signature algorithm. -+func certificateAlgo(algo string) (certAlgo string, ok bool) { -+ for certName, algoName := range certKeyAlgoNames { -+ if algoName == algo { -+ return certName, true -+ } -+ } -+ return "", false -+} -+ -+func (cert *Certificate) bytesForSigning() []byte { -+ c2 := *cert -+ c2.Signature = nil -+ out := c2.Marshal() -+ // Drop trailing signature length. -+ return out[:len(out)-4] -+} -+ -+// Marshal serializes c into OpenSSH's wire format. It is part of the -+// PublicKey interface. -+func (c *Certificate) Marshal() []byte { -+ generic := genericCertData{ -+ Serial: c.Serial, -+ CertType: c.CertType, -+ KeyId: c.KeyId, -+ ValidPrincipals: marshalStringList(c.ValidPrincipals), -+ ValidAfter: uint64(c.ValidAfter), -+ ValidBefore: uint64(c.ValidBefore), -+ CriticalOptions: marshalTuples(c.CriticalOptions), -+ Extensions: marshalTuples(c.Extensions), -+ Reserved: c.Reserved, -+ SignatureKey: c.SignatureKey.Marshal(), -+ } -+ if c.Signature != nil { -+ generic.Signature = Marshal(c.Signature) -+ } -+ genericBytes := Marshal(&generic) -+ keyBytes := c.Key.Marshal() -+ _, keyBytes, _ = parseString(keyBytes) -+ prefix := Marshal(&struct { -+ Name string -+ Nonce []byte -+ Key []byte `ssh:"rest"` -+ }{c.Type(), c.Nonce, keyBytes}) -+ -+ result := make([]byte, 0, len(prefix)+len(genericBytes)) -+ result = append(result, prefix...) -+ result = append(result, genericBytes...) -+ return result -+} -+ -+// Type returns the certificate algorithm name. It is part of the PublicKey interface. -+func (c *Certificate) Type() string { -+ certName, ok := certificateAlgo(c.Key.Type()) -+ if !ok { -+ panic("unknown certificate type for key type " + c.Key.Type()) -+ } -+ return certName -+} -+ -+// Verify verifies a signature against the certificate's public -+// key. It is part of the PublicKey interface. -+func (c *Certificate) Verify(data []byte, sig *Signature) error { -+ return c.Key.Verify(data, sig) -+} -+ -+func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { -+ format, in, ok := parseString(in) -+ if !ok { -+ return -+ } -+ -+ out = &Signature{ -+ Format: string(format), -+ } -+ -+ if out.Blob, in, ok = parseString(in); !ok { -+ return -+ } -+ -+ switch out.Format { -+ case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01: -+ out.Rest = in -+ return out, nil, ok -+ } -+ -+ return out, in, ok -+} -+ -+func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { -+ sigBytes, rest, ok := parseString(in) -+ if !ok { -+ return -+ } -+ -+ out, trailing, ok := parseSignatureBody(sigBytes) -+ if !ok || len(trailing) > 0 { -+ return nil, nil, false -+ } -+ return -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/certs_test.go b/ms_mod/golang.org/x/crypto/ssh/certs_test.go -new file mode 100644 -index 00000000000000..e6004835ea411a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/certs_test.go -@@ -0,0 +1,320 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "fmt" -+ "io" -+ "net" -+ "reflect" -+ "testing" -+ "time" -+) -+ -+// Cert generated by ssh-keygen 6.0p1 Debian-4. -+// % ssh-keygen -s ca-key -I test user-key -+const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` -+ -+func TestParseCert(t *testing.T) { -+ authKeyBytes := []byte(exampleSSHCert) -+ -+ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) -+ if err != nil { -+ t.Fatalf("ParseAuthorizedKey: %v", err) -+ } -+ if len(rest) > 0 { -+ t.Errorf("rest: got %q, want empty", rest) -+ } -+ -+ if _, ok := key.(*Certificate); !ok { -+ t.Fatalf("got %v (%T), want *Certificate", key, key) -+ } -+ -+ marshaled := MarshalAuthorizedKey(key) -+ // Before comparison, remove the trailing newline that -+ // MarshalAuthorizedKey adds. -+ marshaled = marshaled[:len(marshaled)-1] -+ if !bytes.Equal(authKeyBytes, marshaled) { -+ t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) -+ } -+} -+ -+// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3 -+// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub -+// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN -+// Critical Options: -+// -+// force-command /bin/sleep -+// source-address 192.168.1.0/24 -+// -+// Extensions: -+// -+// permit-X11-forwarding -+// permit-agent-forwarding -+// permit-port-forwarding -+// permit-pty -+// permit-user-rc -+const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` -+ -+func TestParseCertWithOptions(t *testing.T) { -+ opts := map[string]string{ -+ "source-address": "192.168.1.0/24", -+ "force-command": "/bin/sleep", -+ } -+ exts := map[string]string{ -+ "permit-X11-forwarding": "", -+ "permit-agent-forwarding": "", -+ "permit-port-forwarding": "", -+ "permit-pty": "", -+ "permit-user-rc": "", -+ } -+ authKeyBytes := []byte(exampleSSHCertWithOptions) -+ -+ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) -+ if err != nil { -+ t.Fatalf("ParseAuthorizedKey: %v", err) -+ } -+ if len(rest) > 0 { -+ t.Errorf("rest: got %q, want empty", rest) -+ } -+ cert, ok := key.(*Certificate) -+ if !ok { -+ t.Fatalf("got %v (%T), want *Certificate", key, key) -+ } -+ if !reflect.DeepEqual(cert.CriticalOptions, opts) { -+ t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts) -+ } -+ if !reflect.DeepEqual(cert.Extensions, exts) { -+ t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts) -+ } -+ marshaled := MarshalAuthorizedKey(key) -+ // Before comparison, remove the trailing newline that -+ // MarshalAuthorizedKey adds. -+ marshaled = marshaled[:len(marshaled)-1] -+ if !bytes.Equal(authKeyBytes, marshaled) { -+ t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) -+ } -+} -+ -+func TestValidateCert(t *testing.T) { -+ key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) -+ if err != nil { -+ t.Fatalf("ParseAuthorizedKey: %v", err) -+ } -+ validCert, ok := key.(*Certificate) -+ if !ok { -+ t.Fatalf("got %v (%T), want *Certificate", key, key) -+ } -+ checker := CertChecker{} -+ checker.IsUserAuthority = func(k PublicKey) bool { -+ return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) -+ } -+ -+ if err := checker.CheckCert("user", validCert); err != nil { -+ t.Errorf("Unable to validate certificate: %v", err) -+ } -+ invalidCert := &Certificate{ -+ Key: testPublicKeys["rsa"], -+ SignatureKey: testPublicKeys["ecdsa"], -+ ValidBefore: CertTimeInfinity, -+ Signature: &Signature{}, -+ } -+ if err := checker.CheckCert("user", invalidCert); err == nil { -+ t.Error("Invalid cert signature passed validation") -+ } -+} -+ -+func TestValidateCertTime(t *testing.T) { -+ cert := Certificate{ -+ ValidPrincipals: []string{"user"}, -+ Key: testPublicKeys["rsa"], -+ ValidAfter: 50, -+ ValidBefore: 100, -+ } -+ -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ -+ for ts, ok := range map[int64]bool{ -+ 25: false, -+ 50: true, -+ 99: true, -+ 100: false, -+ 125: false, -+ } { -+ checker := CertChecker{ -+ Clock: func() time.Time { return time.Unix(ts, 0) }, -+ } -+ checker.IsUserAuthority = func(k PublicKey) bool { -+ return bytes.Equal(k.Marshal(), -+ testPublicKeys["ecdsa"].Marshal()) -+ } -+ -+ if v := checker.CheckCert("user", &cert); (v == nil) != ok { -+ t.Errorf("Authenticate(%d): %v", ts, v) -+ } -+ } -+} -+ -+// TODO(hanwen): tests for -+// -+// host keys: -+// * fallbacks -+ -+func TestHostKeyCert(t *testing.T) { -+ cert := &Certificate{ -+ ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"}, -+ Key: testPublicKeys["rsa"], -+ ValidBefore: CertTimeInfinity, -+ CertType: HostCert, -+ } -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ -+ checker := &CertChecker{ -+ IsHostAuthority: func(p PublicKey, addr string) bool { -+ return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) -+ }, -+ } -+ -+ certSigner, err := NewCertSigner(cert, testSigners["rsa"]) -+ if err != nil { -+ t.Errorf("NewCertSigner: %v", err) -+ } -+ -+ for _, test := range []struct { -+ addr string -+ succeed bool -+ }{ -+ {addr: "hostname:22", succeed: true}, -+ {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22' -+ {addr: "lasthost:22", succeed: false}, -+ } { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ errc := make(chan error) -+ -+ go func() { -+ conf := ServerConfig{ -+ NoClientAuth: true, -+ } -+ conf.AddHostKey(certSigner) -+ _, _, _, err := NewServerConn(c1, &conf) -+ errc <- err -+ }() -+ -+ config := &ClientConfig{ -+ User: "user", -+ HostKeyCallback: checker.CheckHostKey, -+ } -+ _, _, _, err = NewClientConn(c2, test.addr, config) -+ -+ if (err == nil) != test.succeed { -+ t.Errorf("NewClientConn(%q): %v", test.addr, err) -+ } -+ -+ err = <-errc -+ if (err == nil) != test.succeed { -+ t.Errorf("NewServerConn(%q): %v", test.addr, err) -+ } -+ } -+} -+ -+type legacyRSASigner struct { -+ Signer -+} -+ -+func (s *legacyRSASigner) Sign(rand io.Reader, data []byte) (*Signature, error) { -+ v, ok := s.Signer.(AlgorithmSigner) -+ if !ok { -+ return nil, fmt.Errorf("invalid signer") -+ } -+ return v.SignWithAlgorithm(rand, data, KeyAlgoRSA) -+} -+ -+func TestCertTypes(t *testing.T) { -+ var testVars = []struct { -+ name string -+ signer Signer -+ algo string -+ }{ -+ {CertAlgoECDSA256v01, testSigners["ecdsap256"], ""}, -+ {CertAlgoECDSA384v01, testSigners["ecdsap384"], ""}, -+ {CertAlgoECDSA521v01, testSigners["ecdsap521"], ""}, -+ {CertAlgoED25519v01, testSigners["ed25519"], ""}, -+ {CertAlgoRSAv01, testSigners["rsa"], KeyAlgoRSASHA512}, -+ {"legacyRSASigner", &legacyRSASigner{testSigners["rsa"]}, KeyAlgoRSA}, -+ {CertAlgoDSAv01, testSigners["dsa"], ""}, -+ } -+ -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("error generating host key: %v", err) -+ } -+ -+ signer, err := NewSignerFromKey(k) -+ if err != nil { -+ t.Fatalf("error generating signer for ssh listener: %v", err) -+ } -+ -+ conf := &ServerConfig{ -+ PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) { -+ return new(Permissions), nil -+ }, -+ } -+ conf.AddHostKey(signer) -+ -+ for _, m := range testVars { -+ t.Run(m.name, func(t *testing.T) { -+ -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go NewServerConn(c1, conf) -+ -+ priv := m.signer -+ if err != nil { -+ t.Fatalf("error generating ssh pubkey: %v", err) -+ } -+ -+ cert := &Certificate{ -+ CertType: UserCert, -+ Key: priv.PublicKey(), -+ } -+ cert.SignCert(rand.Reader, priv) -+ -+ certSigner, err := NewCertSigner(cert, priv) -+ if err != nil { -+ t.Fatalf("error generating cert signer: %v", err) -+ } -+ -+ if m.algo != "" && cert.Signature.Format != m.algo { -+ t.Errorf("expected %q signature format, got %q", m.algo, cert.Signature.Format) -+ } -+ -+ config := &ClientConfig{ -+ User: "user", -+ HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil }, -+ Auth: []AuthMethod{PublicKeys(certSigner)}, -+ } -+ -+ _, _, _, err = NewClientConn(c2, "", config) -+ if err != nil { -+ t.Fatalf("error connecting: %v", err) -+ } -+ }) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/channel.go b/ms_mod/golang.org/x/crypto/ssh/channel.go -new file mode 100644 -index 00000000000000..c0834c00dfee9a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/channel.go -@@ -0,0 +1,633 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "log" -+ "sync" -+) -+ -+const ( -+ minPacketLength = 9 -+ // channelMaxPacket contains the maximum number of bytes that will be -+ // sent in a single packet. As per RFC 4253, section 6.1, 32k is also -+ // the minimum. -+ channelMaxPacket = 1 << 15 -+ // We follow OpenSSH here. -+ channelWindowSize = 64 * channelMaxPacket -+) -+ -+// NewChannel represents an incoming request to a channel. It must either be -+// accepted for use by calling Accept, or rejected by calling Reject. -+type NewChannel interface { -+ // Accept accepts the channel creation request. It returns the Channel -+ // and a Go channel containing SSH requests. The Go channel must be -+ // serviced otherwise the Channel will hang. -+ Accept() (Channel, <-chan *Request, error) -+ -+ // Reject rejects the channel creation request. After calling -+ // this, no other methods on the Channel may be called. -+ Reject(reason RejectionReason, message string) error -+ -+ // ChannelType returns the type of the channel, as supplied by the -+ // client. -+ ChannelType() string -+ -+ // ExtraData returns the arbitrary payload for this channel, as supplied -+ // by the client. This data is specific to the channel type. -+ ExtraData() []byte -+} -+ -+// A Channel is an ordered, reliable, flow-controlled, duplex stream -+// that is multiplexed over an SSH connection. -+type Channel interface { -+ // Read reads up to len(data) bytes from the channel. -+ Read(data []byte) (int, error) -+ -+ // Write writes len(data) bytes to the channel. -+ Write(data []byte) (int, error) -+ -+ // Close signals end of channel use. No data may be sent after this -+ // call. -+ Close() error -+ -+ // CloseWrite signals the end of sending in-band -+ // data. Requests may still be sent, and the other side may -+ // still send data -+ CloseWrite() error -+ -+ // SendRequest sends a channel request. If wantReply is true, -+ // it will wait for a reply and return the result as a -+ // boolean, otherwise the return value will be false. Channel -+ // requests are out-of-band messages so they may be sent even -+ // if the data stream is closed or blocked by flow control. -+ // If the channel is closed before a reply is returned, io.EOF -+ // is returned. -+ SendRequest(name string, wantReply bool, payload []byte) (bool, error) -+ -+ // Stderr returns an io.ReadWriter that writes to this channel -+ // with the extended data type set to stderr. Stderr may -+ // safely be read and written from a different goroutine than -+ // Read and Write respectively. -+ Stderr() io.ReadWriter -+} -+ -+// Request is a request sent outside of the normal stream of -+// data. Requests can either be specific to an SSH channel, or they -+// can be global. -+type Request struct { -+ Type string -+ WantReply bool -+ Payload []byte -+ -+ ch *channel -+ mux *mux -+} -+ -+// Reply sends a response to a request. It must be called for all requests -+// where WantReply is true and is a no-op otherwise. The payload argument is -+// ignored for replies to channel-specific requests. -+func (r *Request) Reply(ok bool, payload []byte) error { -+ if !r.WantReply { -+ return nil -+ } -+ -+ if r.ch == nil { -+ return r.mux.ackRequest(ok, payload) -+ } -+ -+ return r.ch.ackRequest(ok) -+} -+ -+// RejectionReason is an enumeration used when rejecting channel creation -+// requests. See RFC 4254, section 5.1. -+type RejectionReason uint32 -+ -+const ( -+ Prohibited RejectionReason = iota + 1 -+ ConnectionFailed -+ UnknownChannelType -+ ResourceShortage -+) -+ -+// String converts the rejection reason to human readable form. -+func (r RejectionReason) String() string { -+ switch r { -+ case Prohibited: -+ return "administratively prohibited" -+ case ConnectionFailed: -+ return "connect failed" -+ case UnknownChannelType: -+ return "unknown channel type" -+ case ResourceShortage: -+ return "resource shortage" -+ } -+ return fmt.Sprintf("unknown reason %d", int(r)) -+} -+ -+func min(a uint32, b int) uint32 { -+ if a < uint32(b) { -+ return a -+ } -+ return uint32(b) -+} -+ -+type channelDirection uint8 -+ -+const ( -+ channelInbound channelDirection = iota -+ channelOutbound -+) -+ -+// channel is an implementation of the Channel interface that works -+// with the mux class. -+type channel struct { -+ // R/O after creation -+ chanType string -+ extraData []byte -+ localId, remoteId uint32 -+ -+ // maxIncomingPayload and maxRemotePayload are the maximum -+ // payload sizes of normal and extended data packets for -+ // receiving and sending, respectively. The wire packet will -+ // be 9 or 13 bytes larger (excluding encryption overhead). -+ maxIncomingPayload uint32 -+ maxRemotePayload uint32 -+ -+ mux *mux -+ -+ // decided is set to true if an accept or reject message has been sent -+ // (for outbound channels) or received (for inbound channels). -+ decided bool -+ -+ // direction contains either channelOutbound, for channels created -+ // locally, or channelInbound, for channels created by the peer. -+ direction channelDirection -+ -+ // Pending internal channel messages. -+ msg chan interface{} -+ -+ // Since requests have no ID, there can be only one request -+ // with WantReply=true outstanding. This lock is held by a -+ // goroutine that has such an outgoing request pending. -+ sentRequestMu sync.Mutex -+ -+ incomingRequests chan *Request -+ -+ sentEOF bool -+ -+ // thread-safe data -+ remoteWin window -+ pending *buffer -+ extPending *buffer -+ -+ // windowMu protects myWindow, the flow-control window. -+ windowMu sync.Mutex -+ myWindow uint32 -+ -+ // writeMu serializes calls to mux.conn.writePacket() and -+ // protects sentClose and packetPool. This mutex must be -+ // different from windowMu, as writePacket can block if there -+ // is a key exchange pending. -+ writeMu sync.Mutex -+ sentClose bool -+ -+ // packetPool has a buffer for each extended channel ID to -+ // save allocations during writes. -+ packetPool map[uint32][]byte -+} -+ -+// writePacket sends a packet. If the packet is a channel close, it updates -+// sentClose. This method takes the lock c.writeMu. -+func (ch *channel) writePacket(packet []byte) error { -+ ch.writeMu.Lock() -+ if ch.sentClose { -+ ch.writeMu.Unlock() -+ return io.EOF -+ } -+ ch.sentClose = (packet[0] == msgChannelClose) -+ err := ch.mux.conn.writePacket(packet) -+ ch.writeMu.Unlock() -+ return err -+} -+ -+func (ch *channel) sendMessage(msg interface{}) error { -+ if debugMux { -+ log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg) -+ } -+ -+ p := Marshal(msg) -+ binary.BigEndian.PutUint32(p[1:], ch.remoteId) -+ return ch.writePacket(p) -+} -+ -+// WriteExtended writes data to a specific extended stream. These streams are -+// used, for example, for stderr. -+func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { -+ if ch.sentEOF { -+ return 0, io.EOF -+ } -+ // 1 byte message type, 4 bytes remoteId, 4 bytes data length -+ opCode := byte(msgChannelData) -+ headerLength := uint32(9) -+ if extendedCode > 0 { -+ headerLength += 4 -+ opCode = msgChannelExtendedData -+ } -+ -+ ch.writeMu.Lock() -+ packet := ch.packetPool[extendedCode] -+ // We don't remove the buffer from packetPool, so -+ // WriteExtended calls from different goroutines will be -+ // flagged as errors by the race detector. -+ ch.writeMu.Unlock() -+ -+ for len(data) > 0 { -+ space := min(ch.maxRemotePayload, len(data)) -+ if space, err = ch.remoteWin.reserve(space); err != nil { -+ return n, err -+ } -+ if want := headerLength + space; uint32(cap(packet)) < want { -+ packet = make([]byte, want) -+ } else { -+ packet = packet[:want] -+ } -+ -+ todo := data[:space] -+ -+ packet[0] = opCode -+ binary.BigEndian.PutUint32(packet[1:], ch.remoteId) -+ if extendedCode > 0 { -+ binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode)) -+ } -+ binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo))) -+ copy(packet[headerLength:], todo) -+ if err = ch.writePacket(packet); err != nil { -+ return n, err -+ } -+ -+ n += len(todo) -+ data = data[len(todo):] -+ } -+ -+ ch.writeMu.Lock() -+ ch.packetPool[extendedCode] = packet -+ ch.writeMu.Unlock() -+ -+ return n, err -+} -+ -+func (ch *channel) handleData(packet []byte) error { -+ headerLen := 9 -+ isExtendedData := packet[0] == msgChannelExtendedData -+ if isExtendedData { -+ headerLen = 13 -+ } -+ if len(packet) < headerLen { -+ // malformed data packet -+ return parseError(packet[0]) -+ } -+ -+ var extended uint32 -+ if isExtendedData { -+ extended = binary.BigEndian.Uint32(packet[5:]) -+ } -+ -+ length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen]) -+ if length == 0 { -+ return nil -+ } -+ if length > ch.maxIncomingPayload { -+ // TODO(hanwen): should send Disconnect? -+ return errors.New("ssh: incoming packet exceeds maximum payload size") -+ } -+ -+ data := packet[headerLen:] -+ if length != uint32(len(data)) { -+ return errors.New("ssh: wrong packet length") -+ } -+ -+ ch.windowMu.Lock() -+ if ch.myWindow < length { -+ ch.windowMu.Unlock() -+ // TODO(hanwen): should send Disconnect with reason? -+ return errors.New("ssh: remote side wrote too much") -+ } -+ ch.myWindow -= length -+ ch.windowMu.Unlock() -+ -+ if extended == 1 { -+ ch.extPending.write(data) -+ } else if extended > 0 { -+ // discard other extended data. -+ } else { -+ ch.pending.write(data) -+ } -+ return nil -+} -+ -+func (c *channel) adjustWindow(n uint32) error { -+ c.windowMu.Lock() -+ // Since myWindow is managed on our side, and can never exceed -+ // the initial window setting, we don't worry about overflow. -+ c.myWindow += uint32(n) -+ c.windowMu.Unlock() -+ return c.sendMessage(windowAdjustMsg{ -+ AdditionalBytes: uint32(n), -+ }) -+} -+ -+func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) { -+ switch extended { -+ case 1: -+ n, err = c.extPending.Read(data) -+ case 0: -+ n, err = c.pending.Read(data) -+ default: -+ return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended) -+ } -+ -+ if n > 0 { -+ err = c.adjustWindow(uint32(n)) -+ // sendWindowAdjust can return io.EOF if the remote -+ // peer has closed the connection, however we want to -+ // defer forwarding io.EOF to the caller of Read until -+ // the buffer has been drained. -+ if n > 0 && err == io.EOF { -+ err = nil -+ } -+ } -+ -+ return n, err -+} -+ -+func (c *channel) close() { -+ c.pending.eof() -+ c.extPending.eof() -+ close(c.msg) -+ close(c.incomingRequests) -+ c.writeMu.Lock() -+ // This is not necessary for a normal channel teardown, but if -+ // there was another error, it is. -+ c.sentClose = true -+ c.writeMu.Unlock() -+ // Unblock writers. -+ c.remoteWin.close() -+} -+ -+// responseMessageReceived is called when a success or failure message is -+// received on a channel to check that such a message is reasonable for the -+// given channel. -+func (ch *channel) responseMessageReceived() error { -+ if ch.direction == channelInbound { -+ return errors.New("ssh: channel response message received on inbound channel") -+ } -+ if ch.decided { -+ return errors.New("ssh: duplicate response received for channel") -+ } -+ ch.decided = true -+ return nil -+} -+ -+func (ch *channel) handlePacket(packet []byte) error { -+ switch packet[0] { -+ case msgChannelData, msgChannelExtendedData: -+ return ch.handleData(packet) -+ case msgChannelClose: -+ ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId}) -+ ch.mux.chanList.remove(ch.localId) -+ ch.close() -+ return nil -+ case msgChannelEOF: -+ // RFC 4254 is mute on how EOF affects dataExt messages but -+ // it is logical to signal EOF at the same time. -+ ch.extPending.eof() -+ ch.pending.eof() -+ return nil -+ } -+ -+ decoded, err := decode(packet) -+ if err != nil { -+ return err -+ } -+ -+ switch msg := decoded.(type) { -+ case *channelOpenFailureMsg: -+ if err := ch.responseMessageReceived(); err != nil { -+ return err -+ } -+ ch.mux.chanList.remove(msg.PeersID) -+ ch.msg <- msg -+ case *channelOpenConfirmMsg: -+ if err := ch.responseMessageReceived(); err != nil { -+ return err -+ } -+ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { -+ return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize) -+ } -+ ch.remoteId = msg.MyID -+ ch.maxRemotePayload = msg.MaxPacketSize -+ ch.remoteWin.add(msg.MyWindow) -+ ch.msg <- msg -+ case *windowAdjustMsg: -+ if !ch.remoteWin.add(msg.AdditionalBytes) { -+ return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes) -+ } -+ case *channelRequestMsg: -+ req := Request{ -+ Type: msg.Request, -+ WantReply: msg.WantReply, -+ Payload: msg.RequestSpecificData, -+ ch: ch, -+ } -+ -+ ch.incomingRequests <- &req -+ default: -+ ch.msg <- msg -+ } -+ return nil -+} -+ -+func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { -+ ch := &channel{ -+ remoteWin: window{Cond: newCond()}, -+ myWindow: channelWindowSize, -+ pending: newBuffer(), -+ extPending: newBuffer(), -+ direction: direction, -+ incomingRequests: make(chan *Request, chanSize), -+ msg: make(chan interface{}, chanSize), -+ chanType: chanType, -+ extraData: extraData, -+ mux: m, -+ packetPool: make(map[uint32][]byte), -+ } -+ ch.localId = m.chanList.add(ch) -+ return ch -+} -+ -+var errUndecided = errors.New("ssh: must Accept or Reject channel") -+var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") -+ -+type extChannel struct { -+ code uint32 -+ ch *channel -+} -+ -+func (e *extChannel) Write(data []byte) (n int, err error) { -+ return e.ch.WriteExtended(data, e.code) -+} -+ -+func (e *extChannel) Read(data []byte) (n int, err error) { -+ return e.ch.ReadExtended(data, e.code) -+} -+ -+func (ch *channel) Accept() (Channel, <-chan *Request, error) { -+ if ch.decided { -+ return nil, nil, errDecidedAlready -+ } -+ ch.maxIncomingPayload = channelMaxPacket -+ confirm := channelOpenConfirmMsg{ -+ PeersID: ch.remoteId, -+ MyID: ch.localId, -+ MyWindow: ch.myWindow, -+ MaxPacketSize: ch.maxIncomingPayload, -+ } -+ ch.decided = true -+ if err := ch.sendMessage(confirm); err != nil { -+ return nil, nil, err -+ } -+ -+ return ch, ch.incomingRequests, nil -+} -+ -+func (ch *channel) Reject(reason RejectionReason, message string) error { -+ if ch.decided { -+ return errDecidedAlready -+ } -+ reject := channelOpenFailureMsg{ -+ PeersID: ch.remoteId, -+ Reason: reason, -+ Message: message, -+ Language: "en", -+ } -+ ch.decided = true -+ return ch.sendMessage(reject) -+} -+ -+func (ch *channel) Read(data []byte) (int, error) { -+ if !ch.decided { -+ return 0, errUndecided -+ } -+ return ch.ReadExtended(data, 0) -+} -+ -+func (ch *channel) Write(data []byte) (int, error) { -+ if !ch.decided { -+ return 0, errUndecided -+ } -+ return ch.WriteExtended(data, 0) -+} -+ -+func (ch *channel) CloseWrite() error { -+ if !ch.decided { -+ return errUndecided -+ } -+ ch.sentEOF = true -+ return ch.sendMessage(channelEOFMsg{ -+ PeersID: ch.remoteId}) -+} -+ -+func (ch *channel) Close() error { -+ if !ch.decided { -+ return errUndecided -+ } -+ -+ return ch.sendMessage(channelCloseMsg{ -+ PeersID: ch.remoteId}) -+} -+ -+// Extended returns an io.ReadWriter that sends and receives data on the given, -+// SSH extended stream. Such streams are used, for example, for stderr. -+func (ch *channel) Extended(code uint32) io.ReadWriter { -+ if !ch.decided { -+ return nil -+ } -+ return &extChannel{code, ch} -+} -+ -+func (ch *channel) Stderr() io.ReadWriter { -+ return ch.Extended(1) -+} -+ -+func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { -+ if !ch.decided { -+ return false, errUndecided -+ } -+ -+ if wantReply { -+ ch.sentRequestMu.Lock() -+ defer ch.sentRequestMu.Unlock() -+ } -+ -+ msg := channelRequestMsg{ -+ PeersID: ch.remoteId, -+ Request: name, -+ WantReply: wantReply, -+ RequestSpecificData: payload, -+ } -+ -+ if err := ch.sendMessage(msg); err != nil { -+ return false, err -+ } -+ -+ if wantReply { -+ m, ok := (<-ch.msg) -+ if !ok { -+ return false, io.EOF -+ } -+ switch m.(type) { -+ case *channelRequestFailureMsg: -+ return false, nil -+ case *channelRequestSuccessMsg: -+ return true, nil -+ default: -+ return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m) -+ } -+ } -+ -+ return false, nil -+} -+ -+// ackRequest either sends an ack or nack to the channel request. -+func (ch *channel) ackRequest(ok bool) error { -+ if !ch.decided { -+ return errUndecided -+ } -+ -+ var msg interface{} -+ if !ok { -+ msg = channelRequestFailureMsg{ -+ PeersID: ch.remoteId, -+ } -+ } else { -+ msg = channelRequestSuccessMsg{ -+ PeersID: ch.remoteId, -+ } -+ } -+ return ch.sendMessage(msg) -+} -+ -+func (ch *channel) ChannelType() string { -+ return ch.chanType -+} -+ -+func (ch *channel) ExtraData() []byte { -+ return ch.extraData -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/cipher.go b/ms_mod/golang.org/x/crypto/ssh/cipher.go -new file mode 100644 -index 00000000000000..741e984f33cb75 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/cipher.go -@@ -0,0 +1,789 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/des" -+ "crypto/rc4" -+ "crypto/subtle" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "hash" -+ "io" -+ -+ "golang.org/x/crypto/chacha20" -+ "golang.org/x/crypto/internal/poly1305" -+) -+ -+const ( -+ packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. -+ -+ // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations -+ // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC -+ // indicates implementations SHOULD be able to handle larger packet sizes, but then -+ // waffles on about reasonable limits. -+ // -+ // OpenSSH caps their maxPacket at 256kB so we choose to do -+ // the same. maxPacket is also used to ensure that uint32 -+ // length fields do not overflow, so it should remain well -+ // below 4G. -+ maxPacket = 256 * 1024 -+) -+ -+// noneCipher implements cipher.Stream and provides no encryption. It is used -+// by the transport before the first key-exchange. -+type noneCipher struct{} -+ -+func (c noneCipher) XORKeyStream(dst, src []byte) { -+ copy(dst, src) -+} -+ -+func newAESCTR(key, iv []byte) (cipher.Stream, error) { -+ c, err := aes.NewCipher(key) -+ if err != nil { -+ return nil, err -+ } -+ return cipher.NewCTR(c, iv), nil -+} -+ -+func newRC4(key, iv []byte) (cipher.Stream, error) { -+ return rc4.NewCipher(key) -+} -+ -+type cipherMode struct { -+ keySize int -+ ivSize int -+ create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) -+} -+ -+func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { -+ return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { -+ stream, err := createFunc(key, iv) -+ if err != nil { -+ return nil, err -+ } -+ -+ var streamDump []byte -+ if skip > 0 { -+ streamDump = make([]byte, 512) -+ } -+ -+ for remainingToDump := skip; remainingToDump > 0; { -+ dumpThisTime := remainingToDump -+ if dumpThisTime > len(streamDump) { -+ dumpThisTime = len(streamDump) -+ } -+ stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) -+ remainingToDump -= dumpThisTime -+ } -+ -+ mac := macModes[algs.MAC].new(macKey) -+ return &streamPacketCipher{ -+ mac: mac, -+ etm: macModes[algs.MAC].etm, -+ macResult: make([]byte, mac.Size()), -+ cipher: stream, -+ }, nil -+ } -+} -+ -+// cipherModes documents properties of supported ciphers. Ciphers not included -+// are not supported and will not be negotiated, even if explicitly requested in -+// ClientConfig.Crypto.Ciphers. -+var cipherModes = map[string]*cipherMode{ -+ // Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms -+ // are defined in the order specified in the RFC. -+ "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, -+ "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, -+ "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, -+ -+ // Ciphers from RFC 4345, which introduces security-improved arcfour ciphers. -+ // They are defined in the order specified in the RFC. -+ "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, -+ "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, -+ -+ // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. -+ // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and -+ // RC4) has problems with weak keys, and should be used with caution." -+ // RFC 4345 introduces improved versions of Arcfour. -+ "arcfour": {16, 0, streamCipherMode(0, newRC4)}, -+ -+ // AEAD ciphers -+ gcm128CipherID: {16, 12, newGCMCipher}, -+ gcm256CipherID: {32, 12, newGCMCipher}, -+ chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, -+ -+ // CBC mode is insecure and so is not included in the default config. -+ // (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely -+ // needed, it's possible to specify a custom Config to enable it. -+ // You should expect that an active attacker can recover plaintext if -+ // you do. -+ aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, -+ -+ // 3des-cbc is insecure and is not included in the default -+ // config. -+ tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, -+} -+ -+// prefixLen is the length of the packet prefix that contains the packet length -+// and number of padding bytes. -+const prefixLen = 5 -+ -+// streamPacketCipher is a packetCipher using a stream cipher. -+type streamPacketCipher struct { -+ mac hash.Hash -+ cipher cipher.Stream -+ etm bool -+ -+ // The following members are to avoid per-packet allocations. -+ prefix [prefixLen]byte -+ seqNumBytes [4]byte -+ padding [2 * packetSizeMultiple]byte -+ packetData []byte -+ macResult []byte -+} -+ -+// readCipherPacket reads and decrypt a single packet from the reader argument. -+func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { -+ if _, err := io.ReadFull(r, s.prefix[:]); err != nil { -+ return nil, err -+ } -+ -+ var encryptedPaddingLength [1]byte -+ if s.mac != nil && s.etm { -+ copy(encryptedPaddingLength[:], s.prefix[4:5]) -+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) -+ } else { -+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) -+ } -+ -+ length := binary.BigEndian.Uint32(s.prefix[0:4]) -+ paddingLength := uint32(s.prefix[4]) -+ -+ var macSize uint32 -+ if s.mac != nil { -+ s.mac.Reset() -+ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) -+ s.mac.Write(s.seqNumBytes[:]) -+ if s.etm { -+ s.mac.Write(s.prefix[:4]) -+ s.mac.Write(encryptedPaddingLength[:]) -+ } else { -+ s.mac.Write(s.prefix[:]) -+ } -+ macSize = uint32(s.mac.Size()) -+ } -+ -+ if length <= paddingLength+1 { -+ return nil, errors.New("ssh: invalid packet length, packet too small") -+ } -+ -+ if length > maxPacket { -+ return nil, errors.New("ssh: invalid packet length, packet too large") -+ } -+ -+ // the maxPacket check above ensures that length-1+macSize -+ // does not overflow. -+ if uint32(cap(s.packetData)) < length-1+macSize { -+ s.packetData = make([]byte, length-1+macSize) -+ } else { -+ s.packetData = s.packetData[:length-1+macSize] -+ } -+ -+ if _, err := io.ReadFull(r, s.packetData); err != nil { -+ return nil, err -+ } -+ mac := s.packetData[length-1:] -+ data := s.packetData[:length-1] -+ -+ if s.mac != nil && s.etm { -+ s.mac.Write(data) -+ } -+ -+ s.cipher.XORKeyStream(data, data) -+ -+ if s.mac != nil { -+ if !s.etm { -+ s.mac.Write(data) -+ } -+ s.macResult = s.mac.Sum(s.macResult[:0]) -+ if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { -+ return nil, errors.New("ssh: MAC failure") -+ } -+ } -+ -+ return s.packetData[:length-paddingLength-1], nil -+} -+ -+// writeCipherPacket encrypts and sends a packet of data to the writer argument -+func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { -+ if len(packet) > maxPacket { -+ return errors.New("ssh: packet too large") -+ } -+ -+ aadlen := 0 -+ if s.mac != nil && s.etm { -+ // packet length is not encrypted for EtM modes -+ aadlen = 4 -+ } -+ -+ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple -+ if paddingLength < 4 { -+ paddingLength += packetSizeMultiple -+ } -+ -+ length := len(packet) + 1 + paddingLength -+ binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) -+ s.prefix[4] = byte(paddingLength) -+ padding := s.padding[:paddingLength] -+ if _, err := io.ReadFull(rand, padding); err != nil { -+ return err -+ } -+ -+ if s.mac != nil { -+ s.mac.Reset() -+ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) -+ s.mac.Write(s.seqNumBytes[:]) -+ -+ if s.etm { -+ // For EtM algorithms, the packet length must stay unencrypted, -+ // but the following data (padding length) must be encrypted -+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) -+ } -+ -+ s.mac.Write(s.prefix[:]) -+ -+ if !s.etm { -+ // For non-EtM algorithms, the algorithm is applied on unencrypted data -+ s.mac.Write(packet) -+ s.mac.Write(padding) -+ } -+ } -+ -+ if !(s.mac != nil && s.etm) { -+ // For EtM algorithms, the padding length has already been encrypted -+ // and the packet length must remain unencrypted -+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) -+ } -+ -+ s.cipher.XORKeyStream(packet, packet) -+ s.cipher.XORKeyStream(padding, padding) -+ -+ if s.mac != nil && s.etm { -+ // For EtM algorithms, packet and padding must be encrypted -+ s.mac.Write(packet) -+ s.mac.Write(padding) -+ } -+ -+ if _, err := w.Write(s.prefix[:]); err != nil { -+ return err -+ } -+ if _, err := w.Write(packet); err != nil { -+ return err -+ } -+ if _, err := w.Write(padding); err != nil { -+ return err -+ } -+ -+ if s.mac != nil { -+ s.macResult = s.mac.Sum(s.macResult[:0]) -+ if _, err := w.Write(s.macResult); err != nil { -+ return err -+ } -+ } -+ -+ return nil -+} -+ -+type gcmCipher struct { -+ aead cipher.AEAD -+ prefix [4]byte -+ iv []byte -+ buf []byte -+} -+ -+func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { -+ c, err := aes.NewCipher(key) -+ if err != nil { -+ return nil, err -+ } -+ -+ aead, err := cipher.NewGCM(c) -+ if err != nil { -+ return nil, err -+ } -+ -+ return &gcmCipher{ -+ aead: aead, -+ iv: iv, -+ }, nil -+} -+ -+const gcmTagSize = 16 -+ -+func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { -+ // Pad out to multiple of 16 bytes. This is different from the -+ // stream cipher because that encrypts the length too. -+ padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) -+ if padding < 4 { -+ padding += packetSizeMultiple -+ } -+ -+ length := uint32(len(packet) + int(padding) + 1) -+ binary.BigEndian.PutUint32(c.prefix[:], length) -+ if _, err := w.Write(c.prefix[:]); err != nil { -+ return err -+ } -+ -+ if cap(c.buf) < int(length) { -+ c.buf = make([]byte, length) -+ } else { -+ c.buf = c.buf[:length] -+ } -+ -+ c.buf[0] = padding -+ copy(c.buf[1:], packet) -+ if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { -+ return err -+ } -+ c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) -+ if _, err := w.Write(c.buf); err != nil { -+ return err -+ } -+ c.incIV() -+ -+ return nil -+} -+ -+func (c *gcmCipher) incIV() { -+ for i := 4 + 7; i >= 4; i-- { -+ c.iv[i]++ -+ if c.iv[i] != 0 { -+ break -+ } -+ } -+} -+ -+func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { -+ if _, err := io.ReadFull(r, c.prefix[:]); err != nil { -+ return nil, err -+ } -+ length := binary.BigEndian.Uint32(c.prefix[:]) -+ if length > maxPacket { -+ return nil, errors.New("ssh: max packet length exceeded") -+ } -+ -+ if cap(c.buf) < int(length+gcmTagSize) { -+ c.buf = make([]byte, length+gcmTagSize) -+ } else { -+ c.buf = c.buf[:length+gcmTagSize] -+ } -+ -+ if _, err := io.ReadFull(r, c.buf); err != nil { -+ return nil, err -+ } -+ -+ plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) -+ if err != nil { -+ return nil, err -+ } -+ c.incIV() -+ -+ if len(plain) == 0 { -+ return nil, errors.New("ssh: empty packet") -+ } -+ -+ padding := plain[0] -+ if padding < 4 { -+ // padding is a byte, so it automatically satisfies -+ // the maximum size, which is 255. -+ return nil, fmt.Errorf("ssh: illegal padding %d", padding) -+ } -+ -+ if int(padding+1) >= len(plain) { -+ return nil, fmt.Errorf("ssh: padding %d too large", padding) -+ } -+ plain = plain[1 : length-uint32(padding)] -+ return plain, nil -+} -+ -+// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 -+type cbcCipher struct { -+ mac hash.Hash -+ macSize uint32 -+ decrypter cipher.BlockMode -+ encrypter cipher.BlockMode -+ -+ // The following members are to avoid per-packet allocations. -+ seqNumBytes [4]byte -+ packetData []byte -+ macResult []byte -+ -+ // Amount of data we should still read to hide which -+ // verification error triggered. -+ oracleCamouflage uint32 -+} -+ -+func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { -+ cbc := &cbcCipher{ -+ mac: macModes[algs.MAC].new(macKey), -+ decrypter: cipher.NewCBCDecrypter(c, iv), -+ encrypter: cipher.NewCBCEncrypter(c, iv), -+ packetData: make([]byte, 1024), -+ } -+ if cbc.mac != nil { -+ cbc.macSize = uint32(cbc.mac.Size()) -+ } -+ -+ return cbc, nil -+} -+ -+func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { -+ c, err := aes.NewCipher(key) -+ if err != nil { -+ return nil, err -+ } -+ -+ cbc, err := newCBCCipher(c, key, iv, macKey, algs) -+ if err != nil { -+ return nil, err -+ } -+ -+ return cbc, nil -+} -+ -+func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { -+ c, err := des.NewTripleDESCipher(key) -+ if err != nil { -+ return nil, err -+ } -+ -+ cbc, err := newCBCCipher(c, key, iv, macKey, algs) -+ if err != nil { -+ return nil, err -+ } -+ -+ return cbc, nil -+} -+ -+func maxUInt32(a, b int) uint32 { -+ if a > b { -+ return uint32(a) -+ } -+ return uint32(b) -+} -+ -+const ( -+ cbcMinPacketSizeMultiple = 8 -+ cbcMinPacketSize = 16 -+ cbcMinPaddingSize = 4 -+) -+ -+// cbcError represents a verification error that may leak information. -+type cbcError string -+ -+func (e cbcError) Error() string { return string(e) } -+ -+func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { -+ p, err := c.readCipherPacketLeaky(seqNum, r) -+ if err != nil { -+ if _, ok := err.(cbcError); ok { -+ // Verification error: read a fixed amount of -+ // data, to make distinguishing between -+ // failing MAC and failing length check more -+ // difficult. -+ io.CopyN(io.Discard, r, int64(c.oracleCamouflage)) -+ } -+ } -+ return p, err -+} -+ -+func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { -+ blockSize := c.decrypter.BlockSize() -+ -+ // Read the header, which will include some of the subsequent data in the -+ // case of block ciphers - this is copied back to the payload later. -+ // How many bytes of payload/padding will be read with this first read. -+ firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) -+ firstBlock := c.packetData[:firstBlockLength] -+ if _, err := io.ReadFull(r, firstBlock); err != nil { -+ return nil, err -+ } -+ -+ c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength -+ -+ c.decrypter.CryptBlocks(firstBlock, firstBlock) -+ length := binary.BigEndian.Uint32(firstBlock[:4]) -+ if length > maxPacket { -+ return nil, cbcError("ssh: packet too large") -+ } -+ if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { -+ // The minimum size of a packet is 16 (or the cipher block size, whichever -+ // is larger) bytes. -+ return nil, cbcError("ssh: packet too small") -+ } -+ // The length of the packet (including the length field but not the MAC) must -+ // be a multiple of the block size or 8, whichever is larger. -+ if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { -+ return nil, cbcError("ssh: invalid packet length multiple") -+ } -+ -+ paddingLength := uint32(firstBlock[4]) -+ if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { -+ return nil, cbcError("ssh: invalid packet length") -+ } -+ -+ // Positions within the c.packetData buffer: -+ macStart := 4 + length -+ paddingStart := macStart - paddingLength -+ -+ // Entire packet size, starting before length, ending at end of mac. -+ entirePacketSize := macStart + c.macSize -+ -+ // Ensure c.packetData is large enough for the entire packet data. -+ if uint32(cap(c.packetData)) < entirePacketSize { -+ // Still need to upsize and copy, but this should be rare at runtime, only -+ // on upsizing the packetData buffer. -+ c.packetData = make([]byte, entirePacketSize) -+ copy(c.packetData, firstBlock) -+ } else { -+ c.packetData = c.packetData[:entirePacketSize] -+ } -+ -+ n, err := io.ReadFull(r, c.packetData[firstBlockLength:]) -+ if err != nil { -+ return nil, err -+ } -+ c.oracleCamouflage -= uint32(n) -+ -+ remainingCrypted := c.packetData[firstBlockLength:macStart] -+ c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) -+ -+ mac := c.packetData[macStart:] -+ if c.mac != nil { -+ c.mac.Reset() -+ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) -+ c.mac.Write(c.seqNumBytes[:]) -+ c.mac.Write(c.packetData[:macStart]) -+ c.macResult = c.mac.Sum(c.macResult[:0]) -+ if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { -+ return nil, cbcError("ssh: MAC failure") -+ } -+ } -+ -+ return c.packetData[prefixLen:paddingStart], nil -+} -+ -+func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { -+ effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) -+ -+ // Length of encrypted portion of the packet (header, payload, padding). -+ // Enforce minimum padding and packet size. -+ encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) -+ // Enforce block size. -+ encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize -+ -+ length := encLength - 4 -+ paddingLength := int(length) - (1 + len(packet)) -+ -+ // Overall buffer contains: header, payload, padding, mac. -+ // Space for the MAC is reserved in the capacity but not the slice length. -+ bufferSize := encLength + c.macSize -+ if uint32(cap(c.packetData)) < bufferSize { -+ c.packetData = make([]byte, encLength, bufferSize) -+ } else { -+ c.packetData = c.packetData[:encLength] -+ } -+ -+ p := c.packetData -+ -+ // Packet header. -+ binary.BigEndian.PutUint32(p, length) -+ p = p[4:] -+ p[0] = byte(paddingLength) -+ -+ // Payload. -+ p = p[1:] -+ copy(p, packet) -+ -+ // Padding. -+ p = p[len(packet):] -+ if _, err := io.ReadFull(rand, p); err != nil { -+ return err -+ } -+ -+ if c.mac != nil { -+ c.mac.Reset() -+ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) -+ c.mac.Write(c.seqNumBytes[:]) -+ c.mac.Write(c.packetData) -+ // The MAC is now appended into the capacity reserved for it earlier. -+ c.packetData = c.mac.Sum(c.packetData) -+ } -+ -+ c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) -+ -+ if _, err := w.Write(c.packetData); err != nil { -+ return err -+ } -+ -+ return nil -+} -+ -+const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" -+ -+// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com -+// AEAD, which is described here: -+// -+// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 -+// -+// the methods here also implement padding, which RFC 4253 Section 6 -+// also requires of stream ciphers. -+type chacha20Poly1305Cipher struct { -+ lengthKey [32]byte -+ contentKey [32]byte -+ buf []byte -+} -+ -+func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { -+ if len(key) != 64 { -+ panic(len(key)) -+ } -+ -+ c := &chacha20Poly1305Cipher{ -+ buf: make([]byte, 256), -+ } -+ -+ copy(c.contentKey[:], key[:32]) -+ copy(c.lengthKey[:], key[32:]) -+ return c, nil -+} -+ -+func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { -+ nonce := make([]byte, 12) -+ binary.BigEndian.PutUint32(nonce[8:], seqNum) -+ s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) -+ if err != nil { -+ return nil, err -+ } -+ var polyKey, discardBuf [32]byte -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes -+ -+ encryptedLength := c.buf[:4] -+ if _, err := io.ReadFull(r, encryptedLength); err != nil { -+ return nil, err -+ } -+ -+ var lenBytes [4]byte -+ ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) -+ if err != nil { -+ return nil, err -+ } -+ ls.XORKeyStream(lenBytes[:], encryptedLength) -+ -+ length := binary.BigEndian.Uint32(lenBytes[:]) -+ if length > maxPacket { -+ return nil, errors.New("ssh: invalid packet length, packet too large") -+ } -+ -+ contentEnd := 4 + length -+ packetEnd := contentEnd + poly1305.TagSize -+ if uint32(cap(c.buf)) < packetEnd { -+ c.buf = make([]byte, packetEnd) -+ copy(c.buf[:], encryptedLength) -+ } else { -+ c.buf = c.buf[:packetEnd] -+ } -+ -+ if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { -+ return nil, err -+ } -+ -+ var mac [poly1305.TagSize]byte -+ copy(mac[:], c.buf[contentEnd:packetEnd]) -+ if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { -+ return nil, errors.New("ssh: MAC failure") -+ } -+ -+ plain := c.buf[4:contentEnd] -+ s.XORKeyStream(plain, plain) -+ -+ if len(plain) == 0 { -+ return nil, errors.New("ssh: empty packet") -+ } -+ -+ padding := plain[0] -+ if padding < 4 { -+ // padding is a byte, so it automatically satisfies -+ // the maximum size, which is 255. -+ return nil, fmt.Errorf("ssh: illegal padding %d", padding) -+ } -+ -+ if int(padding)+1 >= len(plain) { -+ return nil, fmt.Errorf("ssh: padding %d too large", padding) -+ } -+ -+ plain = plain[1 : len(plain)-int(padding)] -+ -+ return plain, nil -+} -+ -+func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { -+ nonce := make([]byte, 12) -+ binary.BigEndian.PutUint32(nonce[8:], seqNum) -+ s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) -+ if err != nil { -+ return err -+ } -+ var polyKey, discardBuf [32]byte -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes -+ -+ // There is no blocksize, so fall back to multiple of 8 byte -+ // padding, as described in RFC 4253, Sec 6. -+ const packetSizeMultiple = 8 -+ -+ padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple -+ if padding < 4 { -+ padding += packetSizeMultiple -+ } -+ -+ // size (4 bytes), padding (1), payload, padding, tag. -+ totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize -+ if cap(c.buf) < totalLength { -+ c.buf = make([]byte, totalLength) -+ } else { -+ c.buf = c.buf[:totalLength] -+ } -+ -+ binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) -+ ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) -+ if err != nil { -+ return err -+ } -+ ls.XORKeyStream(c.buf, c.buf[:4]) -+ c.buf[4] = byte(padding) -+ copy(c.buf[5:], payload) -+ packetEnd := 5 + len(payload) + padding -+ if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil { -+ return err -+ } -+ -+ s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd]) -+ -+ var mac [poly1305.TagSize]byte -+ poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) -+ -+ copy(c.buf[packetEnd:], mac[:]) -+ -+ if _, err := w.Write(c.buf); err != nil { -+ return err -+ } -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/cipher_test.go b/ms_mod/golang.org/x/crypto/ssh/cipher_test.go -new file mode 100644 -index 00000000000000..f1be0d6db446df ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/cipher_test.go -@@ -0,0 +1,231 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/rand" -+ "encoding/binary" -+ "io" -+ "testing" -+ -+ "golang.org/x/crypto/chacha20" -+ "golang.org/x/crypto/internal/poly1305" -+) -+ -+func TestDefaultCiphersExist(t *testing.T) { -+ for _, cipherAlgo := range supportedCiphers { -+ if _, ok := cipherModes[cipherAlgo]; !ok { -+ t.Errorf("supported cipher %q is unknown", cipherAlgo) -+ } -+ } -+ for _, cipherAlgo := range preferredCiphers { -+ if _, ok := cipherModes[cipherAlgo]; !ok { -+ t.Errorf("preferred cipher %q is unknown", cipherAlgo) -+ } -+ } -+} -+ -+func TestPacketCiphers(t *testing.T) { -+ defaultMac := "hmac-sha2-256" -+ defaultCipher := "aes128-ctr" -+ for cipher := range cipherModes { -+ t.Run("cipher="+cipher, -+ func(t *testing.T) { testPacketCipher(t, cipher, defaultMac) }) -+ } -+ for mac := range macModes { -+ t.Run("mac="+mac, -+ func(t *testing.T) { testPacketCipher(t, defaultCipher, mac) }) -+ } -+} -+ -+func testPacketCipher(t *testing.T, cipher, mac string) { -+ kr := &kexResult{Hash: crypto.SHA1} -+ algs := directionAlgorithms{ -+ Cipher: cipher, -+ MAC: mac, -+ Compression: "none", -+ } -+ client, err := newPacketCipher(clientKeys, algs, kr) -+ if err != nil { -+ t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) -+ } -+ server, err := newPacketCipher(clientKeys, algs, kr) -+ if err != nil { -+ t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) -+ } -+ -+ want := "bla bla" -+ input := []byte(want) -+ buf := &bytes.Buffer{} -+ if err := client.writeCipherPacket(0, buf, rand.Reader, input); err != nil { -+ t.Fatalf("writeCipherPacket(%q, %q): %v", cipher, mac, err) -+ } -+ -+ packet, err := server.readCipherPacket(0, buf) -+ if err != nil { -+ t.Fatalf("readCipherPacket(%q, %q): %v", cipher, mac, err) -+ } -+ -+ if string(packet) != want { -+ t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want) -+ } -+} -+ -+func TestCBCOracleCounterMeasure(t *testing.T) { -+ kr := &kexResult{Hash: crypto.SHA1} -+ algs := directionAlgorithms{ -+ Cipher: aes128cbcID, -+ MAC: "hmac-sha1", -+ Compression: "none", -+ } -+ client, err := newPacketCipher(clientKeys, algs, kr) -+ if err != nil { -+ t.Fatalf("newPacketCipher(client): %v", err) -+ } -+ -+ want := "bla bla" -+ input := []byte(want) -+ buf := &bytes.Buffer{} -+ if err := client.writeCipherPacket(0, buf, rand.Reader, input); err != nil { -+ t.Errorf("writeCipherPacket: %v", err) -+ } -+ -+ packetSize := buf.Len() -+ buf.Write(make([]byte, 2*maxPacket)) -+ -+ // We corrupt each byte, but this usually will only test the -+ // 'packet too large' or 'MAC failure' cases. -+ lastRead := -1 -+ for i := 0; i < packetSize; i++ { -+ server, err := newPacketCipher(clientKeys, algs, kr) -+ if err != nil { -+ t.Fatalf("newPacketCipher(client): %v", err) -+ } -+ -+ fresh := &bytes.Buffer{} -+ fresh.Write(buf.Bytes()) -+ fresh.Bytes()[i] ^= 0x01 -+ -+ before := fresh.Len() -+ _, err = server.readCipherPacket(0, fresh) -+ if err == nil { -+ t.Errorf("corrupt byte %d: readCipherPacket succeeded ", i) -+ continue -+ } -+ if _, ok := err.(cbcError); !ok { -+ t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) -+ continue -+ } -+ -+ after := fresh.Len() -+ bytesRead := before - after -+ if bytesRead < maxPacket { -+ t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) -+ continue -+ } -+ -+ if i > 0 && bytesRead != lastRead { -+ t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead) -+ } -+ lastRead = bytesRead -+ } -+} -+ -+func TestCVE202143565(t *testing.T) { -+ tests := []struct { -+ cipher string -+ constructPacket func(packetCipher) io.Reader -+ }{ -+ { -+ cipher: gcm128CipherID, -+ constructPacket: func(client packetCipher) io.Reader { -+ internalCipher := client.(*gcmCipher) -+ b := &bytes.Buffer{} -+ prefix := [4]byte{} -+ if _, err := b.Write(prefix[:]); err != nil { -+ t.Fatal(err) -+ } -+ internalCipher.buf = internalCipher.aead.Seal(internalCipher.buf[:0], internalCipher.iv, []byte{}, prefix[:]) -+ if _, err := b.Write(internalCipher.buf); err != nil { -+ t.Fatal(err) -+ } -+ internalCipher.incIV() -+ -+ return b -+ }, -+ }, -+ { -+ cipher: chacha20Poly1305ID, -+ constructPacket: func(client packetCipher) io.Reader { -+ internalCipher := client.(*chacha20Poly1305Cipher) -+ b := &bytes.Buffer{} -+ -+ nonce := make([]byte, 12) -+ s, err := chacha20.NewUnauthenticatedCipher(internalCipher.contentKey[:], nonce) -+ if err != nil { -+ t.Fatal(err) -+ } -+ var polyKey, discardBuf [32]byte -+ s.XORKeyStream(polyKey[:], polyKey[:]) -+ s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes -+ -+ internalCipher.buf = make([]byte, 4+poly1305.TagSize) -+ binary.BigEndian.PutUint32(internalCipher.buf, 0) -+ ls, err := chacha20.NewUnauthenticatedCipher(internalCipher.lengthKey[:], nonce) -+ if err != nil { -+ t.Fatal(err) -+ } -+ ls.XORKeyStream(internalCipher.buf, internalCipher.buf[:4]) -+ if _, err := io.ReadFull(rand.Reader, internalCipher.buf[4:4]); err != nil { -+ t.Fatal(err) -+ } -+ -+ s.XORKeyStream(internalCipher.buf[4:], internalCipher.buf[4:4]) -+ -+ var tag [poly1305.TagSize]byte -+ poly1305.Sum(&tag, internalCipher.buf[:4], &polyKey) -+ -+ copy(internalCipher.buf[4:], tag[:]) -+ -+ if _, err := b.Write(internalCipher.buf); err != nil { -+ t.Fatal(err) -+ } -+ -+ return b -+ }, -+ }, -+ } -+ -+ for _, tc := range tests { -+ mac := "hmac-sha2-256" -+ -+ kr := &kexResult{Hash: crypto.SHA1} -+ algs := directionAlgorithms{ -+ Cipher: tc.cipher, -+ MAC: mac, -+ Compression: "none", -+ } -+ client, err := newPacketCipher(clientKeys, algs, kr) -+ if err != nil { -+ t.Fatalf("newPacketCipher(client, %q, %q): %v", tc.cipher, mac, err) -+ } -+ server, err := newPacketCipher(clientKeys, algs, kr) -+ if err != nil { -+ t.Fatalf("newPacketCipher(client, %q, %q): %v", tc.cipher, mac, err) -+ } -+ -+ b := tc.constructPacket(client) -+ -+ wantErr := "ssh: empty packet" -+ _, err = server.readCipherPacket(0, b) -+ if err == nil { -+ t.Fatalf("readCipherPacket(%q, %q): didn't fail with empty packet", tc.cipher, mac) -+ } else if err.Error() != wantErr { -+ t.Fatalf("readCipherPacket(%q, %q): unexpected error, got %q, want %q", tc.cipher, mac, err, wantErr) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/client.go b/ms_mod/golang.org/x/crypto/ssh/client.go -new file mode 100644 -index 00000000000000..bdc356cbdf1eac ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/client.go -@@ -0,0 +1,282 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "net" -+ "os" -+ "sync" -+ "time" -+) -+ -+// Client implements a traditional SSH client that supports shells, -+// subprocesses, TCP port/streamlocal forwarding and tunneled dialing. -+type Client struct { -+ Conn -+ -+ handleForwardsOnce sync.Once // guards calling (*Client).handleForwards -+ -+ forwards forwardList // forwarded tcpip connections from the remote side -+ mu sync.Mutex -+ channelHandlers map[string]chan NewChannel -+} -+ -+// HandleChannelOpen returns a channel on which NewChannel requests -+// for the given type are sent. If the type already is being handled, -+// nil is returned. The channel is closed when the connection is closed. -+func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { -+ c.mu.Lock() -+ defer c.mu.Unlock() -+ if c.channelHandlers == nil { -+ // The SSH channel has been closed. -+ c := make(chan NewChannel) -+ close(c) -+ return c -+ } -+ -+ ch := c.channelHandlers[channelType] -+ if ch != nil { -+ return nil -+ } -+ -+ ch = make(chan NewChannel, chanSize) -+ c.channelHandlers[channelType] = ch -+ return ch -+} -+ -+// NewClient creates a Client on top of the given connection. -+func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { -+ conn := &Client{ -+ Conn: c, -+ channelHandlers: make(map[string]chan NewChannel, 1), -+ } -+ -+ go conn.handleGlobalRequests(reqs) -+ go conn.handleChannelOpens(chans) -+ go func() { -+ conn.Wait() -+ conn.forwards.closeAll() -+ }() -+ return conn -+} -+ -+// NewClientConn establishes an authenticated SSH connection using c -+// as the underlying transport. The Request and NewChannel channels -+// must be serviced or the connection will hang. -+func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { -+ fullConf := *config -+ fullConf.SetDefaults() -+ if fullConf.HostKeyCallback == nil { -+ c.Close() -+ return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback") -+ } -+ -+ conn := &connection{ -+ sshConn: sshConn{conn: c, user: fullConf.User}, -+ } -+ -+ if err := conn.clientHandshake(addr, &fullConf); err != nil { -+ c.Close() -+ return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) -+ } -+ conn.mux = newMux(conn.transport) -+ return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil -+} -+ -+// clientHandshake performs the client side key exchange. See RFC 4253 Section -+// 7. -+func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { -+ if config.ClientVersion != "" { -+ c.clientVersion = []byte(config.ClientVersion) -+ } else { -+ c.clientVersion = []byte(packageVersion) -+ } -+ var err error -+ c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) -+ if err != nil { -+ return err -+ } -+ -+ c.transport = newClientTransport( -+ newTransport(c.sshConn.conn, config.Rand, true /* is client */), -+ c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) -+ if err := c.transport.waitSession(); err != nil { -+ return err -+ } -+ -+ c.sessionID = c.transport.getSessionID() -+ return c.clientAuthenticate(config) -+} -+ -+// verifyHostKeySignature verifies the host key obtained in the key exchange. -+// algo is the negotiated algorithm, and may be a certificate type. -+func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error { -+ sig, rest, ok := parseSignatureBody(result.Signature) -+ if len(rest) > 0 || !ok { -+ return errors.New("ssh: signature parse error") -+ } -+ -+ if a := underlyingAlgo(algo); sig.Format != a { -+ return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, a) -+ } -+ -+ return hostKey.Verify(result.H, sig) -+} -+ -+// NewSession opens a new Session for this client. (A session is a remote -+// execution of a program.) -+func (c *Client) NewSession() (*Session, error) { -+ ch, in, err := c.OpenChannel("session", nil) -+ if err != nil { -+ return nil, err -+ } -+ return newSession(ch, in) -+} -+ -+func (c *Client) handleGlobalRequests(incoming <-chan *Request) { -+ for r := range incoming { -+ // This handles keepalive messages and matches -+ // the behaviour of OpenSSH. -+ r.Reply(false, nil) -+ } -+} -+ -+// handleChannelOpens channel open messages from the remote side. -+func (c *Client) handleChannelOpens(in <-chan NewChannel) { -+ for ch := range in { -+ c.mu.Lock() -+ handler := c.channelHandlers[ch.ChannelType()] -+ c.mu.Unlock() -+ -+ if handler != nil { -+ handler <- ch -+ } else { -+ ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) -+ } -+ } -+ -+ c.mu.Lock() -+ for _, ch := range c.channelHandlers { -+ close(ch) -+ } -+ c.channelHandlers = nil -+ c.mu.Unlock() -+} -+ -+// Dial starts a client connection to the given SSH server. It is a -+// convenience function that connects to the given network address, -+// initiates the SSH handshake, and then sets up a Client. For access -+// to incoming channels and requests, use net.Dial with NewClientConn -+// instead. -+func Dial(network, addr string, config *ClientConfig) (*Client, error) { -+ conn, err := net.DialTimeout(network, addr, config.Timeout) -+ if err != nil { -+ return nil, err -+ } -+ c, chans, reqs, err := NewClientConn(conn, addr, config) -+ if err != nil { -+ return nil, err -+ } -+ return NewClient(c, chans, reqs), nil -+} -+ -+// HostKeyCallback is the function type used for verifying server -+// keys. A HostKeyCallback must return nil if the host key is OK, or -+// an error to reject it. It receives the hostname as passed to Dial -+// or NewClientConn. The remote address is the RemoteAddr of the -+// net.Conn underlying the SSH connection. -+type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error -+ -+// BannerCallback is the function type used for treat the banner sent by -+// the server. A BannerCallback receives the message sent by the remote server. -+type BannerCallback func(message string) error -+ -+// A ClientConfig structure is used to configure a Client. It must not be -+// modified after having been passed to an SSH function. -+type ClientConfig struct { -+ // Config contains configuration that is shared between clients and -+ // servers. -+ Config -+ -+ // User contains the username to authenticate as. -+ User string -+ -+ // Auth contains possible authentication methods to use with the -+ // server. Only the first instance of a particular RFC 4252 method will -+ // be used during authentication. -+ Auth []AuthMethod -+ -+ // HostKeyCallback is called during the cryptographic -+ // handshake to validate the server's host key. The client -+ // configuration must supply this callback for the connection -+ // to succeed. The functions InsecureIgnoreHostKey or -+ // FixedHostKey can be used for simplistic host key checks. -+ HostKeyCallback HostKeyCallback -+ -+ // BannerCallback is called during the SSH dance to display a custom -+ // server's message. The client configuration can supply this callback to -+ // handle it as wished. The function BannerDisplayStderr can be used for -+ // simplistic display on Stderr. -+ BannerCallback BannerCallback -+ -+ // ClientVersion contains the version identification string that will -+ // be used for the connection. If empty, a reasonable default is used. -+ ClientVersion string -+ -+ // HostKeyAlgorithms lists the public key algorithms that the client will -+ // accept from the server for host key authentication, in order of -+ // preference. If empty, a reasonable default is used. Any -+ // string returned from a PublicKey.Type method may be used, or -+ // any of the CertAlgo and KeyAlgo constants. -+ HostKeyAlgorithms []string -+ -+ // Timeout is the maximum amount of time for the TCP connection to establish. -+ // -+ // A Timeout of zero means no timeout. -+ Timeout time.Duration -+} -+ -+// InsecureIgnoreHostKey returns a function that can be used for -+// ClientConfig.HostKeyCallback to accept any host key. It should -+// not be used for production code. -+func InsecureIgnoreHostKey() HostKeyCallback { -+ return func(hostname string, remote net.Addr, key PublicKey) error { -+ return nil -+ } -+} -+ -+type fixedHostKey struct { -+ key PublicKey -+} -+ -+func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error { -+ if f.key == nil { -+ return fmt.Errorf("ssh: required host key was nil") -+ } -+ if !bytes.Equal(key.Marshal(), f.key.Marshal()) { -+ return fmt.Errorf("ssh: host key mismatch") -+ } -+ return nil -+} -+ -+// FixedHostKey returns a function for use in -+// ClientConfig.HostKeyCallback to accept only a specific host key. -+func FixedHostKey(key PublicKey) HostKeyCallback { -+ hk := &fixedHostKey{key} -+ return hk.check -+} -+ -+// BannerDisplayStderr returns a function that can be used for -+// ClientConfig.BannerCallback to display banners on os.Stderr. -+func BannerDisplayStderr() BannerCallback { -+ return func(banner string) error { -+ _, err := os.Stderr.WriteString(banner) -+ -+ return err -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/client_auth.go b/ms_mod/golang.org/x/crypto/ssh/client_auth.go -new file mode 100644 -index 00000000000000..409b5ea1d49dbd ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/client_auth.go -@@ -0,0 +1,725 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "io" -+ "strings" -+) -+ -+type authResult int -+ -+const ( -+ authFailure authResult = iota -+ authPartialSuccess -+ authSuccess -+) -+ -+// clientAuthenticate authenticates with the remote server. See RFC 4252. -+func (c *connection) clientAuthenticate(config *ClientConfig) error { -+ // initiate user auth session -+ if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { -+ return err -+ } -+ packet, err := c.transport.readPacket() -+ if err != nil { -+ return err -+ } -+ // The server may choose to send a SSH_MSG_EXT_INFO at this point (if we -+ // advertised willingness to receive one, which we always do) or not. See -+ // RFC 8308, Section 2.4. -+ extensions := make(map[string][]byte) -+ if len(packet) > 0 && packet[0] == msgExtInfo { -+ var extInfo extInfoMsg -+ if err := Unmarshal(packet, &extInfo); err != nil { -+ return err -+ } -+ payload := extInfo.Payload -+ for i := uint32(0); i < extInfo.NumExtensions; i++ { -+ name, rest, ok := parseString(payload) -+ if !ok { -+ return parseError(msgExtInfo) -+ } -+ value, rest, ok := parseString(rest) -+ if !ok { -+ return parseError(msgExtInfo) -+ } -+ extensions[string(name)] = value -+ payload = rest -+ } -+ packet, err = c.transport.readPacket() -+ if err != nil { -+ return err -+ } -+ } -+ var serviceAccept serviceAcceptMsg -+ if err := Unmarshal(packet, &serviceAccept); err != nil { -+ return err -+ } -+ -+ // during the authentication phase the client first attempts the "none" method -+ // then any untried methods suggested by the server. -+ var tried []string -+ var lastMethods []string -+ -+ sessionID := c.transport.getSessionID() -+ for auth := AuthMethod(new(noneAuth)); auth != nil; { -+ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions) -+ if err != nil { -+ return err -+ } -+ if ok == authSuccess { -+ // success -+ return nil -+ } else if ok == authFailure { -+ if m := auth.method(); !contains(tried, m) { -+ tried = append(tried, m) -+ } -+ } -+ if methods == nil { -+ methods = lastMethods -+ } -+ lastMethods = methods -+ -+ auth = nil -+ -+ findNext: -+ for _, a := range config.Auth { -+ candidateMethod := a.method() -+ if contains(tried, candidateMethod) { -+ continue -+ } -+ for _, meth := range methods { -+ if meth == candidateMethod { -+ auth = a -+ break findNext -+ } -+ } -+ } -+ } -+ return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried) -+} -+ -+func contains(list []string, e string) bool { -+ for _, s := range list { -+ if s == e { -+ return true -+ } -+ } -+ return false -+} -+ -+// An AuthMethod represents an instance of an RFC 4252 authentication method. -+type AuthMethod interface { -+ // auth authenticates user over transport t. -+ // Returns true if authentication is successful. -+ // If authentication is not successful, a []string of alternative -+ // method names is returned. If the slice is nil, it will be ignored -+ // and the previous set of possible methods will be reused. -+ auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) -+ -+ // method returns the RFC 4252 method name. -+ method() string -+} -+ -+// "none" authentication, RFC 4252 section 5.2. -+type noneAuth int -+ -+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { -+ if err := c.writePacket(Marshal(&userAuthRequestMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: "none", -+ })); err != nil { -+ return authFailure, nil, err -+ } -+ -+ return handleAuthResponse(c) -+} -+ -+func (n *noneAuth) method() string { -+ return "none" -+} -+ -+// passwordCallback is an AuthMethod that fetches the password through -+// a function call, e.g. by prompting the user. -+type passwordCallback func() (password string, err error) -+ -+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { -+ type passwordAuthMsg struct { -+ User string `sshtype:"50"` -+ Service string -+ Method string -+ Reply bool -+ Password string -+ } -+ -+ pw, err := cb() -+ // REVIEW NOTE: is there a need to support skipping a password attempt? -+ // The program may only find out that the user doesn't have a password -+ // when prompting. -+ if err != nil { -+ return authFailure, nil, err -+ } -+ -+ if err := c.writePacket(Marshal(&passwordAuthMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: cb.method(), -+ Reply: false, -+ Password: pw, -+ })); err != nil { -+ return authFailure, nil, err -+ } -+ -+ return handleAuthResponse(c) -+} -+ -+func (cb passwordCallback) method() string { -+ return "password" -+} -+ -+// Password returns an AuthMethod using the given password. -+func Password(secret string) AuthMethod { -+ return passwordCallback(func() (string, error) { return secret, nil }) -+} -+ -+// PasswordCallback returns an AuthMethod that uses a callback for -+// fetching a password. -+func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { -+ return passwordCallback(prompt) -+} -+ -+type publickeyAuthMsg struct { -+ User string `sshtype:"50"` -+ Service string -+ Method string -+ // HasSig indicates to the receiver packet that the auth request is signed and -+ // should be used for authentication of the request. -+ HasSig bool -+ Algoname string -+ PubKey []byte -+ // Sig is tagged with "rest" so Marshal will exclude it during -+ // validateKey -+ Sig []byte `ssh:"rest"` -+} -+ -+// publicKeyCallback is an AuthMethod that uses a set of key -+// pairs for authentication. -+type publicKeyCallback func() ([]Signer, error) -+ -+func (cb publicKeyCallback) method() string { -+ return "publickey" -+} -+ -+func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) { -+ keyFormat := signer.PublicKey().Type() -+ -+ // Like in sendKexInit, if the public key implements AlgorithmSigner we -+ // assume it supports all algorithms, otherwise only the key format one. -+ as, ok := signer.(AlgorithmSigner) -+ if !ok { -+ return algorithmSignerWrapper{signer}, keyFormat -+ } -+ -+ extPayload, ok := extensions["server-sig-algs"] -+ if !ok { -+ // If there is no "server-sig-algs" extension, fall back to the key -+ // format algorithm. -+ return as, keyFormat -+ } -+ -+ // The server-sig-algs extension only carries underlying signature -+ // algorithm, but we are trying to select a protocol-level public key -+ // algorithm, which might be a certificate type. Extend the list of server -+ // supported algorithms to include the corresponding certificate algorithms. -+ serverAlgos := strings.Split(string(extPayload), ",") -+ for _, algo := range serverAlgos { -+ if certAlgo, ok := certificateAlgo(algo); ok { -+ serverAlgos = append(serverAlgos, certAlgo) -+ } -+ } -+ -+ keyAlgos := algorithmsForKeyFormat(keyFormat) -+ algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos) -+ if err != nil { -+ // If there is no overlap, try the key anyway with the key format -+ // algorithm, to support servers that fail to list all supported -+ // algorithms. -+ return as, keyFormat -+ } -+ return as, algo -+} -+ -+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { -+ // Authentication is performed by sending an enquiry to test if a key is -+ // acceptable to the remote. If the key is acceptable, the client will -+ // attempt to authenticate with the valid key. If not the client will repeat -+ // the process with the remaining keys. -+ -+ signers, err := cb() -+ if err != nil { -+ return authFailure, nil, err -+ } -+ var methods []string -+ for _, signer := range signers { -+ pub := signer.PublicKey() -+ as, algo := pickSignatureAlgorithm(signer, extensions) -+ -+ ok, err := validateKey(pub, algo, user, c) -+ if err != nil { -+ return authFailure, nil, err -+ } -+ if !ok { -+ continue -+ } -+ -+ pubKey := pub.Marshal() -+ data := buildDataSignedForAuth(session, userAuthRequestMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: cb.method(), -+ }, algo, pubKey) -+ sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) -+ if err != nil { -+ return authFailure, nil, err -+ } -+ -+ // manually wrap the serialized signature in a string -+ s := Marshal(sign) -+ sig := make([]byte, stringLength(len(s))) -+ marshalString(sig, s) -+ msg := publickeyAuthMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: cb.method(), -+ HasSig: true, -+ Algoname: algo, -+ PubKey: pubKey, -+ Sig: sig, -+ } -+ p := Marshal(&msg) -+ if err := c.writePacket(p); err != nil { -+ return authFailure, nil, err -+ } -+ var success authResult -+ success, methods, err = handleAuthResponse(c) -+ if err != nil { -+ return authFailure, nil, err -+ } -+ -+ // If authentication succeeds or the list of available methods does not -+ // contain the "publickey" method, do not attempt to authenticate with any -+ // other keys. According to RFC 4252 Section 7, the latter can occur when -+ // additional authentication methods are required. -+ if success == authSuccess || !containsMethod(methods, cb.method()) { -+ return success, methods, err -+ } -+ } -+ -+ return authFailure, methods, nil -+} -+ -+func containsMethod(methods []string, method string) bool { -+ for _, m := range methods { -+ if m == method { -+ return true -+ } -+ } -+ -+ return false -+} -+ -+// validateKey validates the key provided is acceptable to the server. -+func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) { -+ pubKey := key.Marshal() -+ msg := publickeyAuthMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: "publickey", -+ HasSig: false, -+ Algoname: algo, -+ PubKey: pubKey, -+ } -+ if err := c.writePacket(Marshal(&msg)); err != nil { -+ return false, err -+ } -+ -+ return confirmKeyAck(key, algo, c) -+} -+ -+func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) { -+ pubKey := key.Marshal() -+ -+ for { -+ packet, err := c.readPacket() -+ if err != nil { -+ return false, err -+ } -+ switch packet[0] { -+ case msgUserAuthBanner: -+ if err := handleBannerResponse(c, packet); err != nil { -+ return false, err -+ } -+ case msgUserAuthPubKeyOk: -+ var msg userAuthPubKeyOkMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return false, err -+ } -+ if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) { -+ return false, nil -+ } -+ return true, nil -+ case msgUserAuthFailure: -+ return false, nil -+ default: -+ return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0]) -+ } -+ } -+} -+ -+// PublicKeys returns an AuthMethod that uses the given key -+// pairs. -+func PublicKeys(signers ...Signer) AuthMethod { -+ return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) -+} -+ -+// PublicKeysCallback returns an AuthMethod that runs the given -+// function to obtain a list of key pairs. -+func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { -+ return publicKeyCallback(getSigners) -+} -+ -+// handleAuthResponse returns whether the preceding authentication request succeeded -+// along with a list of remaining authentication methods to try next and -+// an error if an unexpected response was received. -+func handleAuthResponse(c packetConn) (authResult, []string, error) { -+ gotMsgExtInfo := false -+ for { -+ packet, err := c.readPacket() -+ if err != nil { -+ return authFailure, nil, err -+ } -+ -+ switch packet[0] { -+ case msgUserAuthBanner: -+ if err := handleBannerResponse(c, packet); err != nil { -+ return authFailure, nil, err -+ } -+ case msgExtInfo: -+ // Ignore post-authentication RFC 8308 extensions, once. -+ if gotMsgExtInfo { -+ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) -+ } -+ gotMsgExtInfo = true -+ case msgUserAuthFailure: -+ var msg userAuthFailureMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return authFailure, nil, err -+ } -+ if msg.PartialSuccess { -+ return authPartialSuccess, msg.Methods, nil -+ } -+ return authFailure, msg.Methods, nil -+ case msgUserAuthSuccess: -+ return authSuccess, nil, nil -+ default: -+ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) -+ } -+ } -+} -+ -+func handleBannerResponse(c packetConn, packet []byte) error { -+ var msg userAuthBannerMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return err -+ } -+ -+ transport, ok := c.(*handshakeTransport) -+ if !ok { -+ return nil -+ } -+ -+ if transport.bannerCallback != nil { -+ return transport.bannerCallback(msg.Message) -+ } -+ -+ return nil -+} -+ -+// KeyboardInteractiveChallenge should print questions, optionally -+// disabling echoing (e.g. for passwords), and return all the answers. -+// Challenge may be called multiple times in a single session. After -+// successful authentication, the server may send a challenge with no -+// questions, for which the name and instruction messages should be -+// printed. RFC 4256 section 3.3 details how the UI should behave for -+// both CLI and GUI environments. -+type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error) -+ -+// KeyboardInteractive returns an AuthMethod using a prompt/response -+// sequence controlled by the server. -+func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { -+ return challenge -+} -+ -+func (cb KeyboardInteractiveChallenge) method() string { -+ return "keyboard-interactive" -+} -+ -+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { -+ type initiateMsg struct { -+ User string `sshtype:"50"` -+ Service string -+ Method string -+ Language string -+ Submethods string -+ } -+ -+ if err := c.writePacket(Marshal(&initiateMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: "keyboard-interactive", -+ })); err != nil { -+ return authFailure, nil, err -+ } -+ -+ gotMsgExtInfo := false -+ for { -+ packet, err := c.readPacket() -+ if err != nil { -+ return authFailure, nil, err -+ } -+ -+ // like handleAuthResponse, but with less options. -+ switch packet[0] { -+ case msgUserAuthBanner: -+ if err := handleBannerResponse(c, packet); err != nil { -+ return authFailure, nil, err -+ } -+ continue -+ case msgExtInfo: -+ // Ignore post-authentication RFC 8308 extensions, once. -+ if gotMsgExtInfo { -+ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) -+ } -+ gotMsgExtInfo = true -+ continue -+ case msgUserAuthInfoRequest: -+ // OK -+ case msgUserAuthFailure: -+ var msg userAuthFailureMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return authFailure, nil, err -+ } -+ if msg.PartialSuccess { -+ return authPartialSuccess, msg.Methods, nil -+ } -+ return authFailure, msg.Methods, nil -+ case msgUserAuthSuccess: -+ return authSuccess, nil, nil -+ default: -+ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) -+ } -+ -+ var msg userAuthInfoRequestMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return authFailure, nil, err -+ } -+ -+ // Manually unpack the prompt/echo pairs. -+ rest := msg.Prompts -+ var prompts []string -+ var echos []bool -+ for i := 0; i < int(msg.NumPrompts); i++ { -+ prompt, r, ok := parseString(rest) -+ if !ok || len(r) == 0 { -+ return authFailure, nil, errors.New("ssh: prompt format error") -+ } -+ prompts = append(prompts, string(prompt)) -+ echos = append(echos, r[0] != 0) -+ rest = r[1:] -+ } -+ -+ if len(rest) != 0 { -+ return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") -+ } -+ -+ answers, err := cb(msg.Name, msg.Instruction, prompts, echos) -+ if err != nil { -+ return authFailure, nil, err -+ } -+ -+ if len(answers) != len(prompts) { -+ return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts)) -+ } -+ responseLength := 1 + 4 -+ for _, a := range answers { -+ responseLength += stringLength(len(a)) -+ } -+ serialized := make([]byte, responseLength) -+ p := serialized -+ p[0] = msgUserAuthInfoResponse -+ p = p[1:] -+ p = marshalUint32(p, uint32(len(answers))) -+ for _, a := range answers { -+ p = marshalString(p, []byte(a)) -+ } -+ -+ if err := c.writePacket(serialized); err != nil { -+ return authFailure, nil, err -+ } -+ } -+} -+ -+type retryableAuthMethod struct { -+ authMethod AuthMethod -+ maxTries int -+} -+ -+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) { -+ for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { -+ ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions) -+ if ok != authFailure || err != nil { // either success, partial success or error terminate -+ return ok, methods, err -+ } -+ } -+ return ok, methods, err -+} -+ -+func (r *retryableAuthMethod) method() string { -+ return r.authMethod.method() -+} -+ -+// RetryableAuthMethod is a decorator for other auth methods enabling them to -+// be retried up to maxTries before considering that AuthMethod itself failed. -+// If maxTries is <= 0, will retry indefinitely -+// -+// This is useful for interactive clients using challenge/response type -+// authentication (e.g. Keyboard-Interactive, Password, etc) where the user -+// could mistype their response resulting in the server issuing a -+// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4 -+// [keyboard-interactive]); Without this decorator, the non-retryable -+// AuthMethod would be removed from future consideration, and never tried again -+// (and so the user would never be able to retry their entry). -+func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { -+ return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} -+} -+ -+// GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication. -+// See RFC 4462 section 3 -+// gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details. -+// target is the server host you want to log in to. -+func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod { -+ if gssAPIClient == nil { -+ panic("gss-api client must be not nil with enable gssapi-with-mic") -+ } -+ return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target} -+} -+ -+type gssAPIWithMICCallback struct { -+ gssAPIClient GSSAPIClient -+ target string -+} -+ -+func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) { -+ m := &userAuthRequestMsg{ -+ User: user, -+ Service: serviceSSH, -+ Method: g.method(), -+ } -+ // The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST. -+ // See RFC 4462 section 3.2. -+ m.Payload = appendU32(m.Payload, 1) -+ m.Payload = appendString(m.Payload, string(krb5OID)) -+ if err := c.writePacket(Marshal(m)); err != nil { -+ return authFailure, nil, err -+ } -+ // The server responds to the SSH_MSG_USERAUTH_REQUEST with either an -+ // SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or -+ // with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE. -+ // See RFC 4462 section 3.3. -+ // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check -+ // selected mech if it is valid. -+ packet, err := c.readPacket() -+ if err != nil { -+ return authFailure, nil, err -+ } -+ userAuthGSSAPIResp := &userAuthGSSAPIResponse{} -+ if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil { -+ return authFailure, nil, err -+ } -+ // Start the loop into the exchange token. -+ // See RFC 4462 section 3.4. -+ var token []byte -+ defer g.gssAPIClient.DeleteSecContext() -+ for { -+ // Initiates the establishment of a security context between the application and a remote peer. -+ nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false) -+ if err != nil { -+ return authFailure, nil, err -+ } -+ if len(nextToken) > 0 { -+ if err := c.writePacket(Marshal(&userAuthGSSAPIToken{ -+ Token: nextToken, -+ })); err != nil { -+ return authFailure, nil, err -+ } -+ } -+ if !needContinue { -+ break -+ } -+ packet, err = c.readPacket() -+ if err != nil { -+ return authFailure, nil, err -+ } -+ switch packet[0] { -+ case msgUserAuthFailure: -+ var msg userAuthFailureMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return authFailure, nil, err -+ } -+ if msg.PartialSuccess { -+ return authPartialSuccess, msg.Methods, nil -+ } -+ return authFailure, msg.Methods, nil -+ case msgUserAuthGSSAPIError: -+ userAuthGSSAPIErrorResp := &userAuthGSSAPIError{} -+ if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil { -+ return authFailure, nil, err -+ } -+ return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+ -+ "Major Status: %d\n"+ -+ "Minor Status: %d\n"+ -+ "Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus, -+ userAuthGSSAPIErrorResp.Message) -+ case msgUserAuthGSSAPIToken: -+ userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} -+ if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { -+ return authFailure, nil, err -+ } -+ token = userAuthGSSAPITokenReq.Token -+ } -+ } -+ // Binding Encryption Keys. -+ // See RFC 4462 section 3.5. -+ micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic") -+ micToken, err := g.gssAPIClient.GetMIC(micField) -+ if err != nil { -+ return authFailure, nil, err -+ } -+ if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{ -+ MIC: micToken, -+ })); err != nil { -+ return authFailure, nil, err -+ } -+ return handleAuthResponse(c) -+} -+ -+func (g *gssAPIWithMICCallback) method() string { -+ return "gssapi-with-mic" -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/client_auth_test.go b/ms_mod/golang.org/x/crypto/ssh/client_auth_test.go -new file mode 100644 -index 00000000000000..70558a9a77f374 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/client_auth_test.go -@@ -0,0 +1,1078 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "errors" -+ "fmt" -+ "io" -+ "log" -+ "net" -+ "os" -+ "runtime" -+ "strings" -+ "testing" -+) -+ -+type keyboardInteractive map[string]string -+ -+func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) { -+ var answers []string -+ for _, q := range questions { -+ answers = append(answers, cr[q]) -+ } -+ return answers, nil -+} -+ -+// reused internally by tests -+var clientPassword = "tiger" -+ -+// tryAuth runs a handshake with a given config against an SSH server -+// with config serverConfig. Returns both client and server side errors. -+func tryAuth(t *testing.T, config *ClientConfig) error { -+ err, _ := tryAuthBothSides(t, config, nil) -+ return err -+} -+ -+// tryAuth runs a handshake with a given config against an SSH server -+// with a given GSSAPIWithMICConfig and config serverConfig. Returns both client and server side errors. -+func tryAuthWithGSSAPIWithMICConfig(t *testing.T, clientConfig *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) error { -+ err, _ := tryAuthBothSides(t, clientConfig, gssAPIWithMICConfig) -+ return err -+} -+ -+// tryAuthBothSides runs the handshake and returns the resulting errors from both sides of the connection. -+func tryAuthBothSides(t *testing.T, config *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) (clientError error, serverAuthErrors []error) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ certChecker := CertChecker{ -+ IsUserAuthority: func(k PublicKey) bool { -+ return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) -+ }, -+ UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { -+ if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { -+ return nil, nil -+ } -+ -+ return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) -+ }, -+ IsRevoked: func(c *Certificate) bool { -+ return c.Serial == 666 -+ }, -+ } -+ serverConfig := &ServerConfig{ -+ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { -+ if conn.User() == "testuser" && string(pass) == clientPassword { -+ return nil, nil -+ } -+ return nil, errors.New("password auth failed") -+ }, -+ PublicKeyCallback: certChecker.Authenticate, -+ KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) { -+ ans, err := challenge("user", -+ "instruction", -+ []string{"question1", "question2"}, -+ []bool{true, true}) -+ if err != nil { -+ return nil, err -+ } -+ ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" -+ if ok { -+ challenge("user", "motd", nil, nil) -+ return nil, nil -+ } -+ return nil, errors.New("keyboard-interactive failed") -+ }, -+ GSSAPIWithMICConfig: gssAPIWithMICConfig, -+ } -+ serverConfig.AddHostKey(testSigners["rsa"]) -+ -+ serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) { -+ serverAuthErrors = append(serverAuthErrors, err) -+ } -+ -+ go newServer(c1, serverConfig) -+ _, _, _, err = NewClientConn(c2, "", config) -+ return err, serverAuthErrors -+} -+ -+type loggingAlgorithmSigner struct { -+ used []string -+ AlgorithmSigner -+} -+ -+func (l *loggingAlgorithmSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { -+ l.used = append(l.used, "[Sign]") -+ return l.AlgorithmSigner.Sign(rand, data) -+} -+ -+func (l *loggingAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -+ l.used = append(l.used, algorithm) -+ return l.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm) -+} -+ -+func TestClientAuthPublicKey(t *testing.T) { -+ signer := &loggingAlgorithmSigner{AlgorithmSigner: testSigners["rsa"].(AlgorithmSigner)} -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(signer), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+ if len(signer.used) != 1 || signer.used[0] != KeyAlgoRSASHA256 { -+ t.Errorf("unexpected Sign/SignWithAlgorithm calls: %q", signer.used) -+ } -+} -+ -+// TestClientAuthNoSHA2 tests a ssh-rsa Signer that doesn't implement AlgorithmSigner. -+func TestClientAuthNoSHA2(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(&legacyRSASigner{testSigners["rsa"]}), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+} -+ -+// TestClientAuthThirdKey checks that the third configured can succeed. If we -+// were to do three attempts for each key (rsa-sha2-256, rsa-sha2-512, ssh-rsa), -+// we'd hit the six maximum attempts before reaching it. -+func TestClientAuthThirdKey(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["rsa-openssh-format"], -+ testSigners["rsa-openssh-format"], testSigners["rsa"]), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+} -+ -+func TestAuthMethodPassword(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ Password(clientPassword), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+} -+ -+func TestAuthMethodFallback(t *testing.T) { -+ var passwordCalled bool -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["rsa"]), -+ PasswordCallback( -+ func() (string, error) { -+ passwordCalled = true -+ return "WRONG", nil -+ }), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+ -+ if passwordCalled { -+ t.Errorf("password auth tried before public-key auth.") -+ } -+} -+ -+func TestAuthMethodWrongPassword(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ Password("wrong"), -+ PublicKeys(testSigners["rsa"]), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+} -+ -+func TestAuthMethodKeyboardInteractive(t *testing.T) { -+ answers := keyboardInteractive(map[string]string{ -+ "question1": "answer1", -+ "question2": "answer2", -+ }) -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ KeyboardInteractive(answers.Challenge), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+} -+ -+func TestAuthMethodWrongKeyboardInteractive(t *testing.T) { -+ answers := keyboardInteractive(map[string]string{ -+ "question1": "answer1", -+ "question2": "WRONG", -+ }) -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ KeyboardInteractive(answers.Challenge), -+ }, -+ } -+ -+ if err := tryAuth(t, config); err == nil { -+ t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive") -+ } -+} -+ -+// the mock server will only authenticate ssh-rsa keys -+func TestAuthMethodInvalidPublicKey(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["dsa"]), -+ }, -+ } -+ -+ if err := tryAuth(t, config); err == nil { -+ t.Fatalf("dsa private key should not have authenticated with rsa public key") -+ } -+} -+ -+// the client should authenticate with the second key -+func TestAuthMethodRSAandDSA(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["dsa"], testSigners["rsa"]), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("client could not authenticate with rsa key: %v", err) -+ } -+} -+ -+type invalidAlgSigner struct { -+ Signer -+} -+ -+func (s *invalidAlgSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { -+ sig, err := s.Signer.Sign(rand, data) -+ if sig != nil { -+ sig.Format = "invalid" -+ } -+ return sig, err -+} -+ -+func TestMethodInvalidAlgorithm(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(&invalidAlgSigner{testSigners["rsa"]}), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ err, serverErrors := tryAuthBothSides(t, config, nil) -+ if err == nil { -+ t.Fatalf("login succeeded") -+ } -+ -+ found := false -+ want := "algorithm \"invalid\"" -+ -+ var errStrings []string -+ for _, err := range serverErrors { -+ found = found || (err != nil && strings.Contains(err.Error(), want)) -+ errStrings = append(errStrings, err.Error()) -+ } -+ if !found { -+ t.Errorf("server got error %q, want substring %q", errStrings, want) -+ } -+} -+ -+func TestClientHMAC(t *testing.T) { -+ for _, mac := range supportedMACs { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["rsa"]), -+ }, -+ Config: Config{ -+ MACs: []string{mac}, -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err) -+ } -+ } -+} -+ -+// issue 4285. -+func TestClientUnsupportedCipher(t *testing.T) { -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(), -+ }, -+ Config: Config{ -+ Ciphers: []string{"aes128-cbc"}, // not currently supported -+ }, -+ } -+ if err := tryAuth(t, config); err == nil { -+ t.Errorf("expected no ciphers in common") -+ } -+} -+ -+func TestClientUnsupportedKex(t *testing.T) { -+ if os.Getenv("GO_BUILDER_NAME") != "" { -+ t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198") -+ } -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(), -+ }, -+ Config: Config{ -+ KeyExchanges: []string{"non-existent-kex"}, -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") { -+ t.Errorf("got %v, expected 'common algorithm'", err) -+ } -+} -+ -+func TestClientLoginCert(t *testing.T) { -+ cert := &Certificate{ -+ Key: testPublicKeys["rsa"], -+ ValidBefore: CertTimeInfinity, -+ CertType: UserCert, -+ } -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ certSigner, err := NewCertSigner(cert, testSigners["rsa"]) -+ if err != nil { -+ t.Fatalf("NewCertSigner: %v", err) -+ } -+ -+ clientConfig := &ClientConfig{ -+ User: "user", -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner)) -+ -+ // should succeed -+ if err := tryAuth(t, clientConfig); err != nil { -+ t.Errorf("cert login failed: %v", err) -+ } -+ -+ // corrupted signature -+ cert.Signature.Blob[0]++ -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("cert login passed with corrupted sig") -+ } -+ -+ // revoked -+ cert.Serial = 666 -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("revoked cert login succeeded") -+ } -+ cert.Serial = 1 -+ -+ // sign with wrong key -+ cert.SignCert(rand.Reader, testSigners["dsa"]) -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("cert login passed with non-authoritative key") -+ } -+ -+ // host cert -+ cert.CertType = HostCert -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("cert login passed with wrong type") -+ } -+ cert.CertType = UserCert -+ -+ // principal specified -+ cert.ValidPrincipals = []string{"user"} -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err != nil { -+ t.Errorf("cert login failed: %v", err) -+ } -+ -+ // wrong principal specified -+ cert.ValidPrincipals = []string{"fred"} -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("cert login passed with wrong principal") -+ } -+ cert.ValidPrincipals = nil -+ -+ // added critical option -+ cert.CriticalOptions = map[string]string{"root-access": "yes"} -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("cert login passed with unrecognized critical option") -+ } -+ -+ // allowed source address -+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"} -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err != nil { -+ t.Errorf("cert login with source-address failed: %v", err) -+ } -+ -+ // disallowed source address -+ cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"} -+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) -+ if err := tryAuth(t, clientConfig); err == nil { -+ t.Errorf("cert login with source-address succeeded") -+ } -+} -+ -+func testPermissionsPassing(withPermissions bool, t *testing.T) { -+ serverConfig := &ServerConfig{ -+ PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { -+ if conn.User() == "nopermissions" { -+ return nil, nil -+ } -+ return &Permissions{}, nil -+ }, -+ } -+ serverConfig.AddHostKey(testSigners["rsa"]) -+ -+ clientConfig := &ClientConfig{ -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["rsa"]), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if withPermissions { -+ clientConfig.User = "permissions" -+ } else { -+ clientConfig.User = "nopermissions" -+ } -+ -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go NewClientConn(c2, "", clientConfig) -+ serverConn, err := newServer(c1, serverConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if p := serverConn.Permissions; (p != nil) != withPermissions { -+ t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p) -+ } -+} -+ -+func TestPermissionsPassing(t *testing.T) { -+ testPermissionsPassing(true, t) -+} -+ -+func TestNoPermissionsPassing(t *testing.T) { -+ testPermissionsPassing(false, t) -+} -+ -+func TestRetryableAuth(t *testing.T) { -+ n := 0 -+ passwords := []string{"WRONG1", "WRONG2"} -+ -+ config := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ RetryableAuthMethod(PasswordCallback(func() (string, error) { -+ p := passwords[n] -+ n++ -+ return p, nil -+ }), 2), -+ PublicKeys(testSigners["rsa"]), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ if err := tryAuth(t, config); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+ if n != 2 { -+ t.Fatalf("Did not try all passwords") -+ } -+} -+ -+func ExampleRetryableAuthMethod() { -+ user := "testuser" -+ NumberOfPrompts := 3 -+ -+ // Normally this would be a callback that prompts the user to answer the -+ // provided questions -+ Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { -+ return []string{"answer1", "answer2"}, nil -+ } -+ -+ config := &ClientConfig{ -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ User: user, -+ Auth: []AuthMethod{ -+ RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts), -+ }, -+ } -+ -+ host := "mysshserver" -+ netConn, err := net.Dial("tcp", host) -+ if err != nil { -+ log.Fatal(err) -+ } -+ -+ sshConn, _, _, err := NewClientConn(netConn, host, config) -+ if err != nil { -+ log.Fatal(err) -+ } -+ _ = sshConn -+} -+ -+// Test if username is received on server side when NoClientAuth is used -+func TestClientAuthNone(t *testing.T) { -+ user := "testuser" -+ serverConfig := &ServerConfig{ -+ NoClientAuth: true, -+ } -+ serverConfig.AddHostKey(testSigners["rsa"]) -+ -+ clientConfig := &ClientConfig{ -+ User: user, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go NewClientConn(c2, "", clientConfig) -+ serverConn, err := newServer(c1, serverConfig) -+ if err != nil { -+ t.Fatalf("newServer: %v", err) -+ } -+ if serverConn.User() != user { -+ t.Fatalf("server: got %q, want %q", serverConn.User(), user) -+ } -+} -+ -+// Test if authentication attempts are limited on server when MaxAuthTries is set -+func TestClientAuthMaxAuthTries(t *testing.T) { -+ user := "testuser" -+ -+ serverConfig := &ServerConfig{ -+ MaxAuthTries: 2, -+ PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { -+ if conn.User() == "testuser" && string(pass) == "right" { -+ return nil, nil -+ } -+ return nil, errors.New("password auth failed") -+ }, -+ } -+ serverConfig.AddHostKey(testSigners["rsa"]) -+ -+ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ -+ Reason: 2, -+ Message: "too many authentication failures", -+ }) -+ -+ for tries := 2; tries < 4; tries++ { -+ n := tries -+ clientConfig := &ClientConfig{ -+ User: user, -+ Auth: []AuthMethod{ -+ RetryableAuthMethod(PasswordCallback(func() (string, error) { -+ n-- -+ if n == 0 { -+ return "right", nil -+ } -+ return "wrong", nil -+ }), tries), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go newServer(c1, serverConfig) -+ _, _, _, err = NewClientConn(c2, "", clientConfig) -+ if tries > 2 { -+ if err == nil { -+ t.Fatalf("client: got no error, want %s", expectedErr) -+ } else if err.Error() != expectedErr.Error() { -+ t.Fatalf("client: got %s, want %s", err, expectedErr) -+ } -+ } else { -+ if err != nil { -+ t.Fatalf("client: got %s, want no error", err) -+ } -+ } -+ } -+} -+ -+// Test if authentication attempts are correctly limited on server -+// when more public keys are provided then MaxAuthTries -+func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) { -+ signers := []Signer{} -+ for i := 0; i < 6; i++ { -+ signers = append(signers, testSigners["dsa"]) -+ } -+ -+ validConfig := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, validConfig); err != nil { -+ t.Fatalf("unable to dial remote side: %s", err) -+ } -+ -+ expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ -+ Reason: 2, -+ Message: "too many authentication failures", -+ }) -+ invalidConfig := &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ PublicKeys(append(signers, testSigners["rsa"])...), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ if err := tryAuth(t, invalidConfig); err == nil { -+ t.Fatalf("client: got no error, want %s", expectedErr) -+ } else if err.Error() != expectedErr.Error() { -+ // On Windows we can see a WSAECONNABORTED error -+ // if the client writes another authentication request -+ // before the client goroutine reads the disconnection -+ // message. See issue 50805. -+ if runtime.GOOS == "windows" && strings.Contains(err.Error(), "wsarecv: An established connection was aborted") { -+ // OK. -+ } else { -+ t.Fatalf("client: got %s, want %s", err, expectedErr) -+ } -+ } -+} -+ -+// Test whether authentication errors are being properly logged if all -+// authentication methods have been exhausted -+func TestClientAuthErrorList(t *testing.T) { -+ publicKeyErr := errors.New("This is an error from PublicKeyCallback") -+ -+ clientConfig := &ClientConfig{ -+ Auth: []AuthMethod{ -+ PublicKeys(testSigners["rsa"]), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ serverConfig := &ServerConfig{ -+ PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) { -+ return nil, publicKeyErr -+ }, -+ } -+ serverConfig.AddHostKey(testSigners["rsa"]) -+ -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go NewClientConn(c2, "", clientConfig) -+ _, err = newServer(c1, serverConfig) -+ if err == nil { -+ t.Fatal("newServer: got nil, expected errors") -+ } -+ -+ authErrs, ok := err.(*ServerAuthError) -+ if !ok { -+ t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err) -+ } -+ for i, e := range authErrs.Errors { -+ switch i { -+ case 0: -+ if e != ErrNoAuth { -+ t.Fatalf("errors: got error %v, want ErrNoAuth", e) -+ } -+ case 1: -+ if e != publicKeyErr { -+ t.Fatalf("errors: got %v, want %v", e, publicKeyErr) -+ } -+ default: -+ t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors) -+ } -+ } -+} -+ -+func TestAuthMethodGSSAPIWithMIC(t *testing.T) { -+ type testcase struct { -+ config *ClientConfig -+ gssConfig *GSSAPIWithMICConfig -+ clientWantErr string -+ serverWantErr string -+ } -+ testcases := []*testcase{ -+ { -+ config: &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ GSSAPIWithMICAuthMethod( -+ &FakeClient{ -+ exchanges: []*exchange{ -+ { -+ outToken: "client-valid-token-1", -+ }, -+ { -+ expectedToken: "server-valid-token-1", -+ }, -+ }, -+ mic: []byte("valid-mic"), -+ maxRound: 2, -+ }, "testtarget", -+ ), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ }, -+ gssConfig: &GSSAPIWithMICConfig{ -+ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { -+ if srcName != conn.User()+"@DOMAIN" { -+ return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User()) -+ } -+ return nil, nil -+ }, -+ Server: &FakeServer{ -+ exchanges: []*exchange{ -+ { -+ outToken: "server-valid-token-1", -+ expectedToken: "client-valid-token-1", -+ }, -+ }, -+ maxRound: 1, -+ expectedMIC: []byte("valid-mic"), -+ srcName: "testuser@DOMAIN", -+ }, -+ }, -+ }, -+ { -+ config: &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ GSSAPIWithMICAuthMethod( -+ &FakeClient{ -+ exchanges: []*exchange{ -+ { -+ outToken: "client-valid-token-1", -+ }, -+ { -+ expectedToken: "server-valid-token-1", -+ }, -+ }, -+ mic: []byte("valid-mic"), -+ maxRound: 2, -+ }, "testtarget", -+ ), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ }, -+ gssConfig: &GSSAPIWithMICConfig{ -+ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { -+ return nil, fmt.Errorf("user is not allowed to login") -+ }, -+ Server: &FakeServer{ -+ exchanges: []*exchange{ -+ { -+ outToken: "server-valid-token-1", -+ expectedToken: "client-valid-token-1", -+ }, -+ }, -+ maxRound: 1, -+ expectedMIC: []byte("valid-mic"), -+ srcName: "testuser@DOMAIN", -+ }, -+ }, -+ serverWantErr: "user is not allowed to login", -+ clientWantErr: "ssh: handshake failed: ssh: unable to authenticate", -+ }, -+ { -+ config: &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ GSSAPIWithMICAuthMethod( -+ &FakeClient{ -+ exchanges: []*exchange{ -+ { -+ outToken: "client-valid-token-1", -+ }, -+ { -+ expectedToken: "server-valid-token-1", -+ }, -+ }, -+ mic: []byte("valid-mic"), -+ maxRound: 2, -+ }, "testtarget", -+ ), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ }, -+ gssConfig: &GSSAPIWithMICConfig{ -+ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { -+ if srcName != conn.User() { -+ return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User()) -+ } -+ return nil, nil -+ }, -+ Server: &FakeServer{ -+ exchanges: []*exchange{ -+ { -+ outToken: "server-invalid-token-1", -+ expectedToken: "client-valid-token-1", -+ }, -+ }, -+ maxRound: 1, -+ expectedMIC: []byte("valid-mic"), -+ srcName: "testuser@DOMAIN", -+ }, -+ }, -+ clientWantErr: "ssh: handshake failed: got \"server-invalid-token-1\", want token \"server-valid-token-1\"", -+ }, -+ { -+ config: &ClientConfig{ -+ User: "testuser", -+ Auth: []AuthMethod{ -+ GSSAPIWithMICAuthMethod( -+ &FakeClient{ -+ exchanges: []*exchange{ -+ { -+ outToken: "client-valid-token-1", -+ }, -+ { -+ expectedToken: "server-valid-token-1", -+ }, -+ }, -+ mic: []byte("invalid-mic"), -+ maxRound: 2, -+ }, "testtarget", -+ ), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ }, -+ gssConfig: &GSSAPIWithMICConfig{ -+ AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) { -+ if srcName != conn.User() { -+ return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User()) -+ } -+ return nil, nil -+ }, -+ Server: &FakeServer{ -+ exchanges: []*exchange{ -+ { -+ outToken: "server-valid-token-1", -+ expectedToken: "client-valid-token-1", -+ }, -+ }, -+ maxRound: 1, -+ expectedMIC: []byte("valid-mic"), -+ srcName: "testuser@DOMAIN", -+ }, -+ }, -+ serverWantErr: "got MICToken \"invalid-mic\", want \"valid-mic\"", -+ clientWantErr: "ssh: handshake failed: ssh: unable to authenticate", -+ }, -+ } -+ -+ for i, c := range testcases { -+ clientErr, serverErrs := tryAuthBothSides(t, c.config, c.gssConfig) -+ if (c.clientWantErr == "") != (clientErr == nil) { -+ t.Fatalf("client got %v, want %s, case %d", clientErr, c.clientWantErr, i) -+ } -+ if (c.serverWantErr == "") != (len(serverErrs) == 2 && serverErrs[1] == nil || len(serverErrs) == 1) { -+ t.Fatalf("server got err %v, want %s", serverErrs, c.serverWantErr) -+ } -+ if c.clientWantErr != "" { -+ if clientErr != nil && !strings.Contains(clientErr.Error(), c.clientWantErr) { -+ t.Fatalf("client got %v, want %s, case %d", clientErr, c.clientWantErr, i) -+ } -+ } -+ found := false -+ var errStrings []string -+ if c.serverWantErr != "" { -+ for _, err := range serverErrs { -+ found = found || (err != nil && strings.Contains(err.Error(), c.serverWantErr)) -+ errStrings = append(errStrings, err.Error()) -+ } -+ if !found { -+ t.Errorf("server got error %q, want substring %q, case %d", errStrings, c.serverWantErr, i) -+ } -+ } -+ } -+} -+ -+func TestCompatibleAlgoAndSignatures(t *testing.T) { -+ type testcase struct { -+ algo string -+ sigFormat string -+ compatible bool -+ } -+ testcases := []*testcase{ -+ { -+ KeyAlgoRSA, -+ KeyAlgoRSA, -+ true, -+ }, -+ { -+ KeyAlgoRSA, -+ KeyAlgoRSASHA256, -+ true, -+ }, -+ { -+ KeyAlgoRSA, -+ KeyAlgoRSASHA512, -+ true, -+ }, -+ { -+ KeyAlgoRSASHA256, -+ KeyAlgoRSA, -+ true, -+ }, -+ { -+ KeyAlgoRSASHA512, -+ KeyAlgoRSA, -+ true, -+ }, -+ { -+ KeyAlgoRSASHA512, -+ KeyAlgoRSASHA256, -+ true, -+ }, -+ { -+ KeyAlgoRSASHA256, -+ KeyAlgoRSASHA512, -+ true, -+ }, -+ { -+ KeyAlgoRSASHA512, -+ KeyAlgoRSASHA512, -+ true, -+ }, -+ { -+ CertAlgoRSAv01, -+ KeyAlgoRSA, -+ true, -+ }, -+ { -+ CertAlgoRSAv01, -+ KeyAlgoRSASHA256, -+ true, -+ }, -+ { -+ CertAlgoRSAv01, -+ KeyAlgoRSASHA512, -+ true, -+ }, -+ { -+ CertAlgoRSASHA256v01, -+ KeyAlgoRSASHA512, -+ true, -+ }, -+ { -+ CertAlgoRSASHA512v01, -+ KeyAlgoRSASHA512, -+ true, -+ }, -+ { -+ CertAlgoRSASHA512v01, -+ KeyAlgoRSASHA256, -+ true, -+ }, -+ { -+ CertAlgoRSASHA256v01, -+ CertAlgoRSAv01, -+ true, -+ }, -+ { -+ CertAlgoRSAv01, -+ CertAlgoRSASHA512v01, -+ true, -+ }, -+ { -+ KeyAlgoECDSA256, -+ KeyAlgoRSA, -+ false, -+ }, -+ { -+ KeyAlgoECDSA256, -+ KeyAlgoECDSA521, -+ false, -+ }, -+ { -+ KeyAlgoECDSA256, -+ KeyAlgoECDSA256, -+ true, -+ }, -+ { -+ KeyAlgoECDSA256, -+ KeyAlgoED25519, -+ false, -+ }, -+ { -+ KeyAlgoED25519, -+ KeyAlgoED25519, -+ true, -+ }, -+ } -+ -+ for _, c := range testcases { -+ if isAlgoCompatible(c.algo, c.sigFormat) != c.compatible { -+ t.Errorf("algorithm %q, signature format %q, expected compatible to be %t", c.algo, c.sigFormat, c.compatible) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/client_test.go b/ms_mod/golang.org/x/crypto/ssh/client_test.go -new file mode 100644 -index 00000000000000..c114573469431b ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/client_test.go -@@ -0,0 +1,346 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "strings" -+ "testing" -+) -+ -+func TestClientVersion(t *testing.T) { -+ for _, tt := range []struct { -+ name string -+ version string -+ multiLine string -+ wantErr bool -+ }{ -+ { -+ name: "default version", -+ version: packageVersion, -+ }, -+ { -+ name: "custom version", -+ version: "SSH-2.0-CustomClientVersionString", -+ }, -+ { -+ name: "good multi line version", -+ version: packageVersion, -+ multiLine: strings.Repeat("ignored\r\n", 20), -+ }, -+ { -+ name: "bad multi line version", -+ version: packageVersion, -+ multiLine: "bad multi line version", -+ wantErr: true, -+ }, -+ { -+ name: "long multi line version", -+ version: packageVersion, -+ multiLine: strings.Repeat("long multi line version\r\n", 50)[:256], -+ wantErr: true, -+ }, -+ } { -+ t.Run(tt.name, func(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ go func() { -+ if tt.multiLine != "" { -+ c1.Write([]byte(tt.multiLine)) -+ } -+ NewClientConn(c1, "", &ClientConfig{ -+ ClientVersion: tt.version, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ }) -+ c1.Close() -+ }() -+ conf := &ServerConfig{NoClientAuth: true} -+ conf.AddHostKey(testSigners["rsa"]) -+ conn, _, _, err := NewServerConn(c2, conf) -+ if err == nil == tt.wantErr { -+ t.Fatalf("got err %v; wantErr %t", err, tt.wantErr) -+ } -+ if tt.wantErr { -+ // Don't verify the version on an expected error. -+ return -+ } -+ if got := string(conn.ClientVersion()); got != tt.version { -+ t.Fatalf("got %q; want %q", got, tt.version) -+ } -+ }) -+ } -+} -+ -+func TestHostKeyCheck(t *testing.T) { -+ for _, tt := range []struct { -+ name string -+ wantError string -+ key PublicKey -+ }{ -+ {"no callback", "must specify HostKeyCallback", nil}, -+ {"correct key", "", testSigners["rsa"].PublicKey()}, -+ {"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()}, -+ } { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ serverConf := &ServerConfig{ -+ NoClientAuth: true, -+ } -+ serverConf.AddHostKey(testSigners["rsa"]) -+ -+ go NewServerConn(c1, serverConf) -+ clientConf := ClientConfig{ -+ User: "user", -+ } -+ if tt.key != nil { -+ clientConf.HostKeyCallback = FixedHostKey(tt.key) -+ } -+ -+ _, _, _, err = NewClientConn(c2, "", &clientConf) -+ if err != nil { -+ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { -+ t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) -+ } -+ } else if tt.wantError != "" { -+ t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) -+ } -+ } -+} -+ -+func TestVerifyHostKeySignature(t *testing.T) { -+ for _, tt := range []struct { -+ key string -+ signAlgo string -+ verifyAlgo string -+ wantError string -+ }{ -+ {"rsa", KeyAlgoRSA, KeyAlgoRSA, ""}, -+ {"rsa", KeyAlgoRSASHA256, KeyAlgoRSASHA256, ""}, -+ {"rsa", KeyAlgoRSA, KeyAlgoRSASHA512, `ssh: invalid signature algorithm "ssh-rsa", expected "rsa-sha2-512"`}, -+ {"ed25519", KeyAlgoED25519, KeyAlgoED25519, ""}, -+ } { -+ key := testSigners[tt.key].PublicKey() -+ s, ok := testSigners[tt.key].(AlgorithmSigner) -+ if !ok { -+ t.Fatalf("needed an AlgorithmSigner") -+ } -+ sig, err := s.SignWithAlgorithm(rand.Reader, []byte("test"), tt.signAlgo) -+ if err != nil { -+ t.Fatalf("couldn't sign: %q", err) -+ } -+ -+ b := bytes.Buffer{} -+ writeString(&b, []byte(sig.Format)) -+ writeString(&b, sig.Blob) -+ -+ result := kexResult{Signature: b.Bytes(), H: []byte("test")} -+ -+ err = verifyHostKeySignature(key, tt.verifyAlgo, &result) -+ if err != nil { -+ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { -+ t.Errorf("got error %q, expecting %q", err.Error(), tt.wantError) -+ } -+ } else if tt.wantError != "" { -+ t.Errorf("succeeded, but want error string %q", tt.wantError) -+ } -+ } -+} -+ -+func TestBannerCallback(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ serverConf := &ServerConfig{ -+ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { -+ return &Permissions{}, nil -+ }, -+ BannerCallback: func(conn ConnMetadata) string { -+ return "Hello World" -+ }, -+ } -+ serverConf.AddHostKey(testSigners["rsa"]) -+ go NewServerConn(c1, serverConf) -+ -+ var receivedBanner string -+ var bannerCount int -+ clientConf := ClientConfig{ -+ Auth: []AuthMethod{ -+ Password("123"), -+ }, -+ User: "user", -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ BannerCallback: func(message string) error { -+ bannerCount++ -+ receivedBanner = message -+ return nil -+ }, -+ } -+ -+ _, _, _, err = NewClientConn(c2, "", &clientConf) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if bannerCount != 1 { -+ t.Errorf("got %d banners; want 1", bannerCount) -+ } -+ -+ expected := "Hello World" -+ if receivedBanner != expected { -+ t.Fatalf("got %s; want %s", receivedBanner, expected) -+ } -+} -+ -+func TestNewClientConn(t *testing.T) { -+ for _, tt := range []struct { -+ name string -+ user string -+ }{ -+ { -+ name: "good user field for ConnMetadata", -+ user: "testuser", -+ }, -+ { -+ name: "empty user field for ConnMetadata", -+ user: "", -+ }, -+ } { -+ t.Run(tt.name, func(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ serverConf := &ServerConfig{ -+ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { -+ return &Permissions{}, nil -+ }, -+ } -+ serverConf.AddHostKey(testSigners["rsa"]) -+ go NewServerConn(c1, serverConf) -+ -+ clientConf := &ClientConfig{ -+ User: tt.user, -+ Auth: []AuthMethod{ -+ Password("testpw"), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ clientConn, _, _, err := NewClientConn(c2, "", clientConf) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ if userGot := clientConn.User(); userGot != tt.user { -+ t.Errorf("got user %q; want user %q", userGot, tt.user) -+ } -+ }) -+ } -+} -+ -+func TestUnsupportedAlgorithm(t *testing.T) { -+ for _, tt := range []struct { -+ name string -+ config Config -+ wantError string -+ }{ -+ { -+ "unsupported KEX", -+ Config{ -+ KeyExchanges: []string{"unsupported"}, -+ }, -+ "no common algorithm", -+ }, -+ { -+ "unsupported and supported KEXs", -+ Config{ -+ KeyExchanges: []string{"unsupported", kexAlgoCurve25519SHA256}, -+ }, -+ "", -+ }, -+ { -+ "unsupported cipher", -+ Config{ -+ Ciphers: []string{"unsupported"}, -+ }, -+ "no common algorithm", -+ }, -+ { -+ "unsupported and supported ciphers", -+ Config{ -+ Ciphers: []string{"unsupported", chacha20Poly1305ID}, -+ }, -+ "", -+ }, -+ { -+ "unsupported MAC", -+ Config{ -+ MACs: []string{"unsupported"}, -+ // MAC is used for non AAED ciphers. -+ Ciphers: []string{"aes256-ctr"}, -+ }, -+ "no common algorithm", -+ }, -+ { -+ "unsupported and supported MACs", -+ Config{ -+ MACs: []string{"unsupported", "hmac-sha2-256-etm@openssh.com"}, -+ // MAC is used for non AAED ciphers. -+ Ciphers: []string{"aes256-ctr"}, -+ }, -+ "", -+ }, -+ } { -+ t.Run(tt.name, func(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ serverConf := &ServerConfig{ -+ Config: tt.config, -+ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { -+ return &Permissions{}, nil -+ }, -+ } -+ serverConf.AddHostKey(testSigners["rsa"]) -+ go NewServerConn(c1, serverConf) -+ -+ clientConf := &ClientConfig{ -+ User: "testuser", -+ Config: tt.config, -+ Auth: []AuthMethod{ -+ Password("testpw"), -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ _, _, _, err = NewClientConn(c2, "", clientConf) -+ if err != nil { -+ if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { -+ t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) -+ } -+ } else if tt.wantError != "" { -+ t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) -+ } -+ }) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/common.go b/ms_mod/golang.org/x/crypto/ssh/common.go -new file mode 100644 -index 00000000000000..b419c761edbc12 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/common.go -@@ -0,0 +1,471 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "crypto" -+ "crypto/rand" -+ "fmt" -+ "io" -+ "math" -+ "strings" -+ "sync" -+ -+ _ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+) -+ -+// These are string constants in the SSH protocol. -+const ( -+ compressionNone = "none" -+ serviceUserAuth = "ssh-userauth" -+ serviceSSH = "ssh-connection" -+) -+ -+// supportedCiphers lists ciphers we support but might not recommend. -+var supportedCiphers = []string{ -+ "aes128-ctr", "aes192-ctr", "aes256-ctr", -+ "aes128-gcm@openssh.com", gcm256CipherID, -+ chacha20Poly1305ID, -+ "arcfour256", "arcfour128", "arcfour", -+ aes128cbcID, -+ tripledescbcID, -+} -+ -+// preferredCiphers specifies the default preference for ciphers. -+var preferredCiphers = []string{ -+ "aes128-gcm@openssh.com", gcm256CipherID, -+ chacha20Poly1305ID, -+ "aes128-ctr", "aes192-ctr", "aes256-ctr", -+} -+ -+// supportedKexAlgos specifies the supported key-exchange algorithms in -+// preference order. -+var supportedKexAlgos = []string{ -+ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, -+ // P384 and P521 are not constant-time yet, but since we don't -+ // reuse ephemeral keys, using them for ECDH should be OK. -+ kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, -+ kexAlgoDH14SHA256, kexAlgoDH16SHA512, kexAlgoDH14SHA1, -+ kexAlgoDH1SHA1, -+} -+ -+// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden -+// for the server half. -+var serverForbiddenKexAlgos = map[string]struct{}{ -+ kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests -+ kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests -+} -+ -+// preferredKexAlgos specifies the default preference for key-exchange -+// algorithms in preference order. The diffie-hellman-group16-sha512 algorithm -+// is disabled by default because it is a bit slower than the others. -+var preferredKexAlgos = []string{ -+ kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, -+ kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, -+ kexAlgoDH14SHA256, kexAlgoDH14SHA1, -+} -+ -+// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods -+// of authenticating servers) in preference order. -+var supportedHostKeyAlgos = []string{ -+ CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, -+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, -+ CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, -+ -+ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, -+ KeyAlgoRSASHA256, KeyAlgoRSASHA512, -+ KeyAlgoRSA, KeyAlgoDSA, -+ -+ KeyAlgoED25519, -+} -+ -+// supportedMACs specifies a default set of MAC algorithms in preference order. -+// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed -+// because they have reached the end of their useful life. -+var supportedMACs = []string{ -+ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1", "hmac-sha1-96", -+} -+ -+var supportedCompressions = []string{compressionNone} -+ -+// hashFuncs keeps the mapping of supported signature algorithms to their -+// respective hashes needed for signing and verification. -+var hashFuncs = map[string]crypto.Hash{ -+ KeyAlgoRSA: crypto.SHA1, -+ KeyAlgoRSASHA256: crypto.SHA256, -+ KeyAlgoRSASHA512: crypto.SHA512, -+ KeyAlgoDSA: crypto.SHA1, -+ KeyAlgoECDSA256: crypto.SHA256, -+ KeyAlgoECDSA384: crypto.SHA384, -+ KeyAlgoECDSA521: crypto.SHA512, -+ // KeyAlgoED25519 doesn't pre-hash. -+ KeyAlgoSKECDSA256: crypto.SHA256, -+ KeyAlgoSKED25519: crypto.SHA256, -+} -+ -+// algorithmsForKeyFormat returns the supported signature algorithms for a given -+// public key format (PublicKey.Type), in order of preference. See RFC 8332, -+// Section 2. See also the note in sendKexInit on backwards compatibility. -+func algorithmsForKeyFormat(keyFormat string) []string { -+ switch keyFormat { -+ case KeyAlgoRSA: -+ return []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA} -+ case CertAlgoRSAv01: -+ return []string{CertAlgoRSASHA256v01, CertAlgoRSASHA512v01, CertAlgoRSAv01} -+ default: -+ return []string{keyFormat} -+ } -+} -+ -+// isRSA returns whether algo is a supported RSA algorithm, including certificate -+// algorithms. -+func isRSA(algo string) bool { -+ algos := algorithmsForKeyFormat(KeyAlgoRSA) -+ return contains(algos, underlyingAlgo(algo)) -+} -+ -+// supportedPubKeyAuthAlgos specifies the supported client public key -+// authentication algorithms. Note that this doesn't include certificate types -+// since those use the underlying algorithm. This list is sent to the client if -+// it supports the server-sig-algs extension. Order is irrelevant. -+var supportedPubKeyAuthAlgos = []string{ -+ KeyAlgoED25519, -+ KeyAlgoSKED25519, KeyAlgoSKECDSA256, -+ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, -+ KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA, -+ KeyAlgoDSA, -+} -+ -+var supportedPubKeyAuthAlgosList = strings.Join(supportedPubKeyAuthAlgos, ",") -+ -+// unexpectedMessageError results when the SSH message that we received didn't -+// match what we wanted. -+func unexpectedMessageError(expected, got uint8) error { -+ return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) -+} -+ -+// parseError results from a malformed SSH message. -+func parseError(tag uint8) error { -+ return fmt.Errorf("ssh: parse error in message type %d", tag) -+} -+ -+func findCommon(what string, client []string, server []string) (common string, err error) { -+ for _, c := range client { -+ for _, s := range server { -+ if c == s { -+ return c, nil -+ } -+ } -+ } -+ return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) -+} -+ -+// directionAlgorithms records algorithm choices in one direction (either read or write) -+type directionAlgorithms struct { -+ Cipher string -+ MAC string -+ Compression string -+} -+ -+// rekeyBytes returns a rekeying intervals in bytes. -+func (a *directionAlgorithms) rekeyBytes() int64 { -+ // According to RFC 4344 block ciphers should rekey after -+ // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is -+ // 128. -+ switch a.Cipher { -+ case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcm128CipherID, gcm256CipherID, aes128cbcID: -+ return 16 * (1 << 32) -+ -+ } -+ -+ // For others, stick with RFC 4253 recommendation to rekey after 1 Gb of data. -+ return 1 << 30 -+} -+ -+var aeadCiphers = map[string]bool{ -+ gcm128CipherID: true, -+ gcm256CipherID: true, -+ chacha20Poly1305ID: true, -+} -+ -+type algorithms struct { -+ kex string -+ hostKey string -+ w directionAlgorithms -+ r directionAlgorithms -+} -+ -+func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { -+ result := &algorithms{} -+ -+ result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) -+ if err != nil { -+ return -+ } -+ -+ result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) -+ if err != nil { -+ return -+ } -+ -+ stoc, ctos := &result.w, &result.r -+ if isClient { -+ ctos, stoc = stoc, ctos -+ } -+ -+ ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) -+ if err != nil { -+ return -+ } -+ -+ stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) -+ if err != nil { -+ return -+ } -+ -+ if !aeadCiphers[ctos.Cipher] { -+ ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) -+ if err != nil { -+ return -+ } -+ } -+ -+ if !aeadCiphers[stoc.Cipher] { -+ stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) -+ if err != nil { -+ return -+ } -+ } -+ -+ ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) -+ if err != nil { -+ return -+ } -+ -+ stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) -+ if err != nil { -+ return -+ } -+ -+ return result, nil -+} -+ -+// If rekeythreshold is too small, we can't make any progress sending -+// stuff. -+const minRekeyThreshold uint64 = 256 -+ -+// Config contains configuration data common to both ServerConfig and -+// ClientConfig. -+type Config struct { -+ // Rand provides the source of entropy for cryptographic -+ // primitives. If Rand is nil, the cryptographic random reader -+ // in package crypto/rand will be used. -+ Rand io.Reader -+ -+ // The maximum number of bytes sent or received after which a -+ // new key is negotiated. It must be at least 256. If -+ // unspecified, a size suitable for the chosen cipher is used. -+ RekeyThreshold uint64 -+ -+ // The allowed key exchanges algorithms. If unspecified then a default set -+ // of algorithms is used. Unsupported values are silently ignored. -+ KeyExchanges []string -+ -+ // The allowed cipher algorithms. If unspecified then a sensible default is -+ // used. Unsupported values are silently ignored. -+ Ciphers []string -+ -+ // The allowed MAC algorithms. If unspecified then a sensible default is -+ // used. Unsupported values are silently ignored. -+ MACs []string -+} -+ -+// SetDefaults sets sensible values for unset fields in config. This is -+// exported for testing: Configs passed to SSH functions are copied and have -+// default values set automatically. -+func (c *Config) SetDefaults() { -+ if c.Rand == nil { -+ c.Rand = rand.Reader -+ } -+ if c.Ciphers == nil { -+ c.Ciphers = preferredCiphers -+ } -+ var ciphers []string -+ for _, c := range c.Ciphers { -+ if cipherModes[c] != nil { -+ // Ignore the cipher if we have no cipherModes definition. -+ ciphers = append(ciphers, c) -+ } -+ } -+ c.Ciphers = ciphers -+ -+ if c.KeyExchanges == nil { -+ c.KeyExchanges = preferredKexAlgos -+ } -+ var kexs []string -+ for _, k := range c.KeyExchanges { -+ if kexAlgoMap[k] != nil { -+ // Ignore the KEX if we have no kexAlgoMap definition. -+ kexs = append(kexs, k) -+ } -+ } -+ c.KeyExchanges = kexs -+ -+ if c.MACs == nil { -+ c.MACs = supportedMACs -+ } -+ var macs []string -+ for _, m := range c.MACs { -+ if macModes[m] != nil { -+ // Ignore the MAC if we have no macModes definition. -+ macs = append(macs, m) -+ } -+ } -+ c.MACs = macs -+ -+ if c.RekeyThreshold == 0 { -+ // cipher specific default -+ } else if c.RekeyThreshold < minRekeyThreshold { -+ c.RekeyThreshold = minRekeyThreshold -+ } else if c.RekeyThreshold >= math.MaxInt64 { -+ // Avoid weirdness if somebody uses -1 as a threshold. -+ c.RekeyThreshold = math.MaxInt64 -+ } -+} -+ -+// buildDataSignedForAuth returns the data that is signed in order to prove -+// possession of a private key. See RFC 4252, section 7. algo is the advertised -+// algorithm, and may be a certificate type. -+func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo string, pubKey []byte) []byte { -+ data := struct { -+ Session []byte -+ Type byte -+ User string -+ Service string -+ Method string -+ Sign bool -+ Algo string -+ PubKey []byte -+ }{ -+ sessionID, -+ msgUserAuthRequest, -+ req.User, -+ req.Service, -+ req.Method, -+ true, -+ algo, -+ pubKey, -+ } -+ return Marshal(data) -+} -+ -+func appendU16(buf []byte, n uint16) []byte { -+ return append(buf, byte(n>>8), byte(n)) -+} -+ -+func appendU32(buf []byte, n uint32) []byte { -+ return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) -+} -+ -+func appendU64(buf []byte, n uint64) []byte { -+ return append(buf, -+ byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), -+ byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) -+} -+ -+func appendInt(buf []byte, n int) []byte { -+ return appendU32(buf, uint32(n)) -+} -+ -+func appendString(buf []byte, s string) []byte { -+ buf = appendU32(buf, uint32(len(s))) -+ buf = append(buf, s...) -+ return buf -+} -+ -+func appendBool(buf []byte, b bool) []byte { -+ if b { -+ return append(buf, 1) -+ } -+ return append(buf, 0) -+} -+ -+// newCond is a helper to hide the fact that there is no usable zero -+// value for sync.Cond. -+func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } -+ -+// window represents the buffer available to clients -+// wishing to write to a channel. -+type window struct { -+ *sync.Cond -+ win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 -+ writeWaiters int -+ closed bool -+} -+ -+// add adds win to the amount of window available -+// for consumers. -+func (w *window) add(win uint32) bool { -+ // a zero sized window adjust is a noop. -+ if win == 0 { -+ return true -+ } -+ w.L.Lock() -+ if w.win+win < win { -+ w.L.Unlock() -+ return false -+ } -+ w.win += win -+ // It is unusual that multiple goroutines would be attempting to reserve -+ // window space, but not guaranteed. Use broadcast to notify all waiters -+ // that additional window is available. -+ w.Broadcast() -+ w.L.Unlock() -+ return true -+} -+ -+// close sets the window to closed, so all reservations fail -+// immediately. -+func (w *window) close() { -+ w.L.Lock() -+ w.closed = true -+ w.Broadcast() -+ w.L.Unlock() -+} -+ -+// reserve reserves win from the available window capacity. -+// If no capacity remains, reserve will block. reserve may -+// return less than requested. -+func (w *window) reserve(win uint32) (uint32, error) { -+ var err error -+ w.L.Lock() -+ w.writeWaiters++ -+ w.Broadcast() -+ for w.win == 0 && !w.closed { -+ w.Wait() -+ } -+ w.writeWaiters-- -+ if w.win < win { -+ win = w.win -+ } -+ w.win -= win -+ if w.closed { -+ err = io.EOF -+ } -+ w.L.Unlock() -+ return win, err -+} -+ -+// waitWriterBlocked waits until some goroutine is blocked for further -+// writes. It is used in tests only. -+func (w *window) waitWriterBlocked() { -+ w.Cond.L.Lock() -+ for w.writeWaiters == 0 { -+ w.Cond.Wait() -+ } -+ w.Cond.L.Unlock() -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/common_test.go b/ms_mod/golang.org/x/crypto/ssh/common_test.go -new file mode 100644 -index 00000000000000..a7beee8e884e7e ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/common_test.go -@@ -0,0 +1,176 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "reflect" -+ "testing" -+) -+ -+func TestFindAgreedAlgorithms(t *testing.T) { -+ initKex := func(k *kexInitMsg) { -+ if k.KexAlgos == nil { -+ k.KexAlgos = []string{"kex1"} -+ } -+ if k.ServerHostKeyAlgos == nil { -+ k.ServerHostKeyAlgos = []string{"hostkey1"} -+ } -+ if k.CiphersClientServer == nil { -+ k.CiphersClientServer = []string{"cipher1"} -+ -+ } -+ if k.CiphersServerClient == nil { -+ k.CiphersServerClient = []string{"cipher1"} -+ -+ } -+ if k.MACsClientServer == nil { -+ k.MACsClientServer = []string{"mac1"} -+ -+ } -+ if k.MACsServerClient == nil { -+ k.MACsServerClient = []string{"mac1"} -+ -+ } -+ if k.CompressionClientServer == nil { -+ k.CompressionClientServer = []string{"compression1"} -+ -+ } -+ if k.CompressionServerClient == nil { -+ k.CompressionServerClient = []string{"compression1"} -+ -+ } -+ if k.LanguagesClientServer == nil { -+ k.LanguagesClientServer = []string{"language1"} -+ -+ } -+ if k.LanguagesServerClient == nil { -+ k.LanguagesServerClient = []string{"language1"} -+ -+ } -+ } -+ -+ initDirAlgs := func(a *directionAlgorithms) { -+ if a.Cipher == "" { -+ a.Cipher = "cipher1" -+ } -+ if a.MAC == "" { -+ a.MAC = "mac1" -+ } -+ if a.Compression == "" { -+ a.Compression = "compression1" -+ } -+ } -+ -+ initAlgs := func(a *algorithms) { -+ if a.kex == "" { -+ a.kex = "kex1" -+ } -+ if a.hostKey == "" { -+ a.hostKey = "hostkey1" -+ } -+ initDirAlgs(&a.r) -+ initDirAlgs(&a.w) -+ } -+ -+ type testcase struct { -+ name string -+ clientIn, serverIn kexInitMsg -+ wantClient, wantServer algorithms -+ wantErr bool -+ } -+ -+ cases := []testcase{ -+ { -+ name: "standard", -+ }, -+ -+ { -+ name: "no common hostkey", -+ serverIn: kexInitMsg{ -+ ServerHostKeyAlgos: []string{"hostkey2"}, -+ }, -+ wantErr: true, -+ }, -+ -+ { -+ name: "no common kex", -+ serverIn: kexInitMsg{ -+ KexAlgos: []string{"kex2"}, -+ }, -+ wantErr: true, -+ }, -+ -+ { -+ name: "no common cipher", -+ serverIn: kexInitMsg{ -+ CiphersClientServer: []string{"cipher2"}, -+ }, -+ wantErr: true, -+ }, -+ -+ { -+ name: "client decides cipher", -+ serverIn: kexInitMsg{ -+ CiphersClientServer: []string{"cipher1", "cipher2"}, -+ CiphersServerClient: []string{"cipher2", "cipher3"}, -+ }, -+ clientIn: kexInitMsg{ -+ CiphersClientServer: []string{"cipher2", "cipher1"}, -+ CiphersServerClient: []string{"cipher3", "cipher2"}, -+ }, -+ wantClient: algorithms{ -+ r: directionAlgorithms{ -+ Cipher: "cipher3", -+ }, -+ w: directionAlgorithms{ -+ Cipher: "cipher2", -+ }, -+ }, -+ wantServer: algorithms{ -+ w: directionAlgorithms{ -+ Cipher: "cipher3", -+ }, -+ r: directionAlgorithms{ -+ Cipher: "cipher2", -+ }, -+ }, -+ }, -+ -+ // TODO(hanwen): fix and add tests for AEAD ignoring -+ // the MACs field -+ } -+ -+ for i := range cases { -+ initKex(&cases[i].clientIn) -+ initKex(&cases[i].serverIn) -+ initAlgs(&cases[i].wantClient) -+ initAlgs(&cases[i].wantServer) -+ } -+ -+ for _, c := range cases { -+ t.Run(c.name, func(t *testing.T) { -+ serverAlgs, serverErr := findAgreedAlgorithms(false, &c.clientIn, &c.serverIn) -+ clientAlgs, clientErr := findAgreedAlgorithms(true, &c.clientIn, &c.serverIn) -+ -+ serverHasErr := serverErr != nil -+ clientHasErr := clientErr != nil -+ if c.wantErr != serverHasErr || c.wantErr != clientHasErr { -+ t.Fatalf("got client/server error (%v, %v), want hasError %v", -+ clientErr, serverErr, c.wantErr) -+ -+ } -+ if c.wantErr { -+ return -+ } -+ -+ if !reflect.DeepEqual(serverAlgs, &c.wantServer) { -+ t.Errorf("server: got algs %#v, want %#v", serverAlgs, &c.wantServer) -+ } -+ if !reflect.DeepEqual(clientAlgs, &c.wantClient) { -+ t.Errorf("server: got algs %#v, want %#v", clientAlgs, &c.wantClient) -+ } -+ }) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/connection.go b/ms_mod/golang.org/x/crypto/ssh/connection.go -new file mode 100644 -index 00000000000000..8f345ee924e43a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/connection.go -@@ -0,0 +1,143 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "fmt" -+ "net" -+) -+ -+// OpenChannelError is returned if the other side rejects an -+// OpenChannel request. -+type OpenChannelError struct { -+ Reason RejectionReason -+ Message string -+} -+ -+func (e *OpenChannelError) Error() string { -+ return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) -+} -+ -+// ConnMetadata holds metadata for the connection. -+type ConnMetadata interface { -+ // User returns the user ID for this connection. -+ User() string -+ -+ // SessionID returns the session hash, also denoted by H. -+ SessionID() []byte -+ -+ // ClientVersion returns the client's version string as hashed -+ // into the session ID. -+ ClientVersion() []byte -+ -+ // ServerVersion returns the server's version string as hashed -+ // into the session ID. -+ ServerVersion() []byte -+ -+ // RemoteAddr returns the remote address for this connection. -+ RemoteAddr() net.Addr -+ -+ // LocalAddr returns the local address for this connection. -+ LocalAddr() net.Addr -+} -+ -+// Conn represents an SSH connection for both server and client roles. -+// Conn is the basis for implementing an application layer, such -+// as ClientConn, which implements the traditional shell access for -+// clients. -+type Conn interface { -+ ConnMetadata -+ -+ // SendRequest sends a global request, and returns the -+ // reply. If wantReply is true, it returns the response status -+ // and payload. See also RFC 4254, section 4. -+ SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) -+ -+ // OpenChannel tries to open an channel. If the request is -+ // rejected, it returns *OpenChannelError. On success it returns -+ // the SSH Channel and a Go channel for incoming, out-of-band -+ // requests. The Go channel must be serviced, or the -+ // connection will hang. -+ OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) -+ -+ // Close closes the underlying network connection -+ Close() error -+ -+ // Wait blocks until the connection has shut down, and returns the -+ // error causing the shutdown. -+ Wait() error -+ -+ // TODO(hanwen): consider exposing: -+ // RequestKeyChange -+ // Disconnect -+} -+ -+// DiscardRequests consumes and rejects all requests from the -+// passed-in channel. -+func DiscardRequests(in <-chan *Request) { -+ for req := range in { -+ if req.WantReply { -+ req.Reply(false, nil) -+ } -+ } -+} -+ -+// A connection represents an incoming connection. -+type connection struct { -+ transport *handshakeTransport -+ sshConn -+ -+ // The connection protocol. -+ *mux -+} -+ -+func (c *connection) Close() error { -+ return c.sshConn.conn.Close() -+} -+ -+// sshConn provides net.Conn metadata, but disallows direct reads and -+// writes. -+type sshConn struct { -+ conn net.Conn -+ -+ user string -+ sessionID []byte -+ clientVersion []byte -+ serverVersion []byte -+} -+ -+func dup(src []byte) []byte { -+ dst := make([]byte, len(src)) -+ copy(dst, src) -+ return dst -+} -+ -+func (c *sshConn) User() string { -+ return c.user -+} -+ -+func (c *sshConn) RemoteAddr() net.Addr { -+ return c.conn.RemoteAddr() -+} -+ -+func (c *sshConn) Close() error { -+ return c.conn.Close() -+} -+ -+func (c *sshConn) LocalAddr() net.Addr { -+ return c.conn.LocalAddr() -+} -+ -+func (c *sshConn) SessionID() []byte { -+ return dup(c.sessionID) -+} -+ -+func (c *sshConn) ClientVersion() []byte { -+ return dup(c.clientVersion) -+} -+ -+func (c *sshConn) ServerVersion() []byte { -+ return dup(c.serverVersion) -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/doc.go b/ms_mod/golang.org/x/crypto/ssh/doc.go -new file mode 100644 -index 00000000000000..f6bff60dc741ac ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/doc.go -@@ -0,0 +1,22 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+Package ssh implements an SSH client and server. -+ -+SSH is a transport security protocol, an authentication protocol and a -+family of application protocols. The most typical application level -+protocol is a remote shell and this is specifically implemented. However, -+the multiplexed nature of SSH is exposed to users that wish to support -+others. -+ -+References: -+ -+ [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD -+ [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 -+ -+This package does not fall under the stability promise of the Go language itself, -+so its API may be changed when pressing needs arise. -+*/ -+package ssh // import "golang.org/x/crypto/ssh" -diff --git a/ms_mod/golang.org/x/crypto/ssh/example_test.go b/ms_mod/golang.org/x/crypto/ssh/example_test.go -new file mode 100644 -index 00000000000000..bee679603b57a4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/example_test.go -@@ -0,0 +1,320 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh_test -+ -+import ( -+ "bufio" -+ "bytes" -+ "fmt" -+ "log" -+ "net" -+ "net/http" -+ "os" -+ "path/filepath" -+ "strings" -+ -+ "golang.org/x/crypto/ssh" -+ "golang.org/x/crypto/ssh/terminal" -+) -+ -+func ExampleNewServerConn() { -+ // Public key authentication is done by comparing -+ // the public key of a received connection -+ // with the entries in the authorized_keys file. -+ authorizedKeysBytes, err := os.ReadFile("authorized_keys") -+ if err != nil { -+ log.Fatalf("Failed to load authorized_keys, err: %v", err) -+ } -+ -+ authorizedKeysMap := map[string]bool{} -+ for len(authorizedKeysBytes) > 0 { -+ pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes) -+ if err != nil { -+ log.Fatal(err) -+ } -+ -+ authorizedKeysMap[string(pubKey.Marshal())] = true -+ authorizedKeysBytes = rest -+ } -+ -+ // An SSH server is represented by a ServerConfig, which holds -+ // certificate details and handles authentication of ServerConns. -+ config := &ssh.ServerConfig{ -+ // Remove to disable password auth. -+ PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { -+ // Should use constant-time compare (or better, salt+hash) in -+ // a production setting. -+ if c.User() == "testuser" && string(pass) == "tiger" { -+ return nil, nil -+ } -+ return nil, fmt.Errorf("password rejected for %q", c.User()) -+ }, -+ -+ // Remove to disable public key auth. -+ PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { -+ if authorizedKeysMap[string(pubKey.Marshal())] { -+ return &ssh.Permissions{ -+ // Record the public key used for authentication. -+ Extensions: map[string]string{ -+ "pubkey-fp": ssh.FingerprintSHA256(pubKey), -+ }, -+ }, nil -+ } -+ return nil, fmt.Errorf("unknown public key for %q", c.User()) -+ }, -+ } -+ -+ privateBytes, err := os.ReadFile("id_rsa") -+ if err != nil { -+ log.Fatal("Failed to load private key: ", err) -+ } -+ -+ private, err := ssh.ParsePrivateKey(privateBytes) -+ if err != nil { -+ log.Fatal("Failed to parse private key: ", err) -+ } -+ -+ config.AddHostKey(private) -+ -+ // Once a ServerConfig has been configured, connections can be -+ // accepted. -+ listener, err := net.Listen("tcp", "0.0.0.0:2022") -+ if err != nil { -+ log.Fatal("failed to listen for connection: ", err) -+ } -+ nConn, err := listener.Accept() -+ if err != nil { -+ log.Fatal("failed to accept incoming connection: ", err) -+ } -+ -+ // Before use, a handshake must be performed on the incoming -+ // net.Conn. -+ conn, chans, reqs, err := ssh.NewServerConn(nConn, config) -+ if err != nil { -+ log.Fatal("failed to handshake: ", err) -+ } -+ log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"]) -+ -+ // The incoming Request channel must be serviced. -+ go ssh.DiscardRequests(reqs) -+ -+ // Service the incoming Channel channel. -+ for newChannel := range chans { -+ // Channels have a type, depending on the application level -+ // protocol intended. In the case of a shell, the type is -+ // "session" and ServerShell may be used to present a simple -+ // terminal interface. -+ if newChannel.ChannelType() != "session" { -+ newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") -+ continue -+ } -+ channel, requests, err := newChannel.Accept() -+ if err != nil { -+ log.Fatalf("Could not accept channel: %v", err) -+ } -+ -+ // Sessions have out-of-band requests such as "shell", -+ // "pty-req" and "env". Here we handle only the -+ // "shell" request. -+ go func(in <-chan *ssh.Request) { -+ for req := range in { -+ req.Reply(req.Type == "shell", nil) -+ } -+ }(requests) -+ -+ term := terminal.NewTerminal(channel, "> ") -+ -+ go func() { -+ defer channel.Close() -+ for { -+ line, err := term.ReadLine() -+ if err != nil { -+ break -+ } -+ fmt.Println(line) -+ } -+ }() -+ } -+} -+ -+func ExampleClientConfig_HostKeyCallback() { -+ // Every client must provide a host key check. Here is a -+ // simple-minded parse of OpenSSH's known_hosts file -+ host := "hostname" -+ file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts")) -+ if err != nil { -+ log.Fatal(err) -+ } -+ defer file.Close() -+ -+ scanner := bufio.NewScanner(file) -+ var hostKey ssh.PublicKey -+ for scanner.Scan() { -+ fields := strings.Split(scanner.Text(), " ") -+ if len(fields) != 3 { -+ continue -+ } -+ if strings.Contains(fields[0], host) { -+ var err error -+ hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes()) -+ if err != nil { -+ log.Fatalf("error parsing %q: %v", fields[2], err) -+ } -+ break -+ } -+ } -+ -+ if hostKey == nil { -+ log.Fatalf("no hostkey for %s", host) -+ } -+ -+ config := ssh.ClientConfig{ -+ User: os.Getenv("USER"), -+ HostKeyCallback: ssh.FixedHostKey(hostKey), -+ } -+ -+ _, err = ssh.Dial("tcp", host+":22", &config) -+ log.Println(err) -+} -+ -+func ExampleDial() { -+ var hostKey ssh.PublicKey -+ // An SSH client is represented with a ClientConn. -+ // -+ // To authenticate with the remote server you must pass at least one -+ // implementation of AuthMethod via the Auth field in ClientConfig, -+ // and provide a HostKeyCallback. -+ config := &ssh.ClientConfig{ -+ User: "username", -+ Auth: []ssh.AuthMethod{ -+ ssh.Password("yourpassword"), -+ }, -+ HostKeyCallback: ssh.FixedHostKey(hostKey), -+ } -+ client, err := ssh.Dial("tcp", "yourserver.com:22", config) -+ if err != nil { -+ log.Fatal("Failed to dial: ", err) -+ } -+ defer client.Close() -+ -+ // Each ClientConn can support multiple interactive sessions, -+ // represented by a Session. -+ session, err := client.NewSession() -+ if err != nil { -+ log.Fatal("Failed to create session: ", err) -+ } -+ defer session.Close() -+ -+ // Once a Session is created, you can execute a single command on -+ // the remote side using the Run method. -+ var b bytes.Buffer -+ session.Stdout = &b -+ if err := session.Run("/usr/bin/whoami"); err != nil { -+ log.Fatal("Failed to run: " + err.Error()) -+ } -+ fmt.Println(b.String()) -+} -+ -+func ExamplePublicKeys() { -+ var hostKey ssh.PublicKey -+ // A public key may be used to authenticate against the remote -+ // server by using an unencrypted PEM-encoded private key file. -+ // -+ // If you have an encrypted private key, the crypto/x509 package -+ // can be used to decrypt it. -+ key, err := os.ReadFile("/home/user/.ssh/id_rsa") -+ if err != nil { -+ log.Fatalf("unable to read private key: %v", err) -+ } -+ -+ // Create the Signer for this private key. -+ signer, err := ssh.ParsePrivateKey(key) -+ if err != nil { -+ log.Fatalf("unable to parse private key: %v", err) -+ } -+ -+ config := &ssh.ClientConfig{ -+ User: "user", -+ Auth: []ssh.AuthMethod{ -+ // Use the PublicKeys method for remote authentication. -+ ssh.PublicKeys(signer), -+ }, -+ HostKeyCallback: ssh.FixedHostKey(hostKey), -+ } -+ -+ // Connect to the remote server and perform the SSH handshake. -+ client, err := ssh.Dial("tcp", "host.com:22", config) -+ if err != nil { -+ log.Fatalf("unable to connect: %v", err) -+ } -+ defer client.Close() -+} -+ -+func ExampleClient_Listen() { -+ var hostKey ssh.PublicKey -+ config := &ssh.ClientConfig{ -+ User: "username", -+ Auth: []ssh.AuthMethod{ -+ ssh.Password("password"), -+ }, -+ HostKeyCallback: ssh.FixedHostKey(hostKey), -+ } -+ // Dial your ssh server. -+ conn, err := ssh.Dial("tcp", "localhost:22", config) -+ if err != nil { -+ log.Fatal("unable to connect: ", err) -+ } -+ defer conn.Close() -+ -+ // Request the remote side to open port 8080 on all interfaces. -+ l, err := conn.Listen("tcp", "0.0.0.0:8080") -+ if err != nil { -+ log.Fatal("unable to register tcp forward: ", err) -+ } -+ defer l.Close() -+ -+ // Serve HTTP with your SSH server acting as a reverse proxy. -+ http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { -+ fmt.Fprintf(resp, "Hello world!\n") -+ })) -+} -+ -+func ExampleSession_RequestPty() { -+ var hostKey ssh.PublicKey -+ // Create client config -+ config := &ssh.ClientConfig{ -+ User: "username", -+ Auth: []ssh.AuthMethod{ -+ ssh.Password("password"), -+ }, -+ HostKeyCallback: ssh.FixedHostKey(hostKey), -+ } -+ // Connect to ssh server -+ conn, err := ssh.Dial("tcp", "localhost:22", config) -+ if err != nil { -+ log.Fatal("unable to connect: ", err) -+ } -+ defer conn.Close() -+ // Create a session -+ session, err := conn.NewSession() -+ if err != nil { -+ log.Fatal("unable to create session: ", err) -+ } -+ defer session.Close() -+ // Set up terminal modes -+ modes := ssh.TerminalModes{ -+ ssh.ECHO: 0, // disable echoing -+ ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud -+ ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud -+ } -+ // Request pseudo terminal -+ if err := session.RequestPty("xterm", 40, 80, modes); err != nil { -+ log.Fatal("request for pseudo terminal failed: ", err) -+ } -+ // Start remote shell -+ if err := session.Shell(); err != nil { -+ log.Fatal("failed to start shell: ", err) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/handshake.go b/ms_mod/golang.org/x/crypto/ssh/handshake.go -new file mode 100644 -index 00000000000000..07a1843e0a52f8 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/handshake.go -@@ -0,0 +1,735 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "crypto/rand" -+ "errors" -+ "fmt" -+ "io" -+ "log" -+ "net" -+ "sync" -+) -+ -+// debugHandshake, if set, prints messages sent and received. Key -+// exchange messages are printed as if DH were used, so the debug -+// messages are wrong when using ECDH. -+const debugHandshake = false -+ -+// chanSize sets the amount of buffering SSH connections. This is -+// primarily for testing: setting chanSize=0 uncovers deadlocks more -+// quickly. -+const chanSize = 16 -+ -+// keyingTransport is a packet based transport that supports key -+// changes. It need not be thread-safe. It should pass through -+// msgNewKeys in both directions. -+type keyingTransport interface { -+ packetConn -+ -+ // prepareKeyChange sets up a key change. The key change for a -+ // direction will be effected if a msgNewKeys message is sent -+ // or received. -+ prepareKeyChange(*algorithms, *kexResult) error -+} -+ -+// handshakeTransport implements rekeying on top of a keyingTransport -+// and offers a thread-safe writePacket() interface. -+type handshakeTransport struct { -+ conn keyingTransport -+ config *Config -+ -+ serverVersion []byte -+ clientVersion []byte -+ -+ // hostKeys is non-empty if we are the server. In that case, -+ // it contains all host keys that can be used to sign the -+ // connection. -+ hostKeys []Signer -+ -+ // hostKeyAlgorithms is non-empty if we are the client. In that case, -+ // we accept these key types from the server as host key. -+ hostKeyAlgorithms []string -+ -+ // On read error, incoming is closed, and readError is set. -+ incoming chan []byte -+ readError error -+ -+ mu sync.Mutex -+ writeError error -+ sentInitPacket []byte -+ sentInitMsg *kexInitMsg -+ pendingPackets [][]byte // Used when a key exchange is in progress. -+ writePacketsLeft uint32 -+ writeBytesLeft int64 -+ -+ // If the read loop wants to schedule a kex, it pings this -+ // channel, and the write loop will send out a kex -+ // message. -+ requestKex chan struct{} -+ -+ // If the other side requests or confirms a kex, its kexInit -+ // packet is sent here for the write loop to find it. -+ startKex chan *pendingKex -+ kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits -+ -+ // data for host key checking -+ hostKeyCallback HostKeyCallback -+ dialAddress string -+ remoteAddr net.Addr -+ -+ // bannerCallback is non-empty if we are the client and it has been set in -+ // ClientConfig. In that case it is called during the user authentication -+ // dance to handle a custom server's message. -+ bannerCallback BannerCallback -+ -+ // Algorithms agreed in the last key exchange. -+ algorithms *algorithms -+ -+ // Counters exclusively owned by readLoop. -+ readPacketsLeft uint32 -+ readBytesLeft int64 -+ -+ // The session ID or nil if first kex did not complete yet. -+ sessionID []byte -+} -+ -+type pendingKex struct { -+ otherInit []byte -+ done chan error -+} -+ -+func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport { -+ t := &handshakeTransport{ -+ conn: conn, -+ serverVersion: serverVersion, -+ clientVersion: clientVersion, -+ incoming: make(chan []byte, chanSize), -+ requestKex: make(chan struct{}, 1), -+ startKex: make(chan *pendingKex), -+ kexLoopDone: make(chan struct{}), -+ -+ config: config, -+ } -+ t.resetReadThresholds() -+ t.resetWriteThresholds() -+ -+ // We always start with a mandatory key exchange. -+ t.requestKex <- struct{}{} -+ return t -+} -+ -+func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport { -+ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) -+ t.dialAddress = dialAddr -+ t.remoteAddr = addr -+ t.hostKeyCallback = config.HostKeyCallback -+ t.bannerCallback = config.BannerCallback -+ if config.HostKeyAlgorithms != nil { -+ t.hostKeyAlgorithms = config.HostKeyAlgorithms -+ } else { -+ t.hostKeyAlgorithms = supportedHostKeyAlgos -+ } -+ go t.readLoop() -+ go t.kexLoop() -+ return t -+} -+ -+func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { -+ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) -+ t.hostKeys = config.hostKeys -+ go t.readLoop() -+ go t.kexLoop() -+ return t -+} -+ -+func (t *handshakeTransport) getSessionID() []byte { -+ return t.sessionID -+} -+ -+// waitSession waits for the session to be established. This should be -+// the first thing to call after instantiating handshakeTransport. -+func (t *handshakeTransport) waitSession() error { -+ p, err := t.readPacket() -+ if err != nil { -+ return err -+ } -+ if p[0] != msgNewKeys { -+ return fmt.Errorf("ssh: first packet should be msgNewKeys") -+ } -+ -+ return nil -+} -+ -+func (t *handshakeTransport) id() string { -+ if len(t.hostKeys) > 0 { -+ return "server" -+ } -+ return "client" -+} -+ -+func (t *handshakeTransport) printPacket(p []byte, write bool) { -+ action := "got" -+ if write { -+ action = "sent" -+ } -+ -+ if p[0] == msgChannelData || p[0] == msgChannelExtendedData { -+ log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p)) -+ } else { -+ msg, err := decode(p) -+ log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err) -+ } -+} -+ -+func (t *handshakeTransport) readPacket() ([]byte, error) { -+ p, ok := <-t.incoming -+ if !ok { -+ return nil, t.readError -+ } -+ return p, nil -+} -+ -+func (t *handshakeTransport) readLoop() { -+ first := true -+ for { -+ p, err := t.readOnePacket(first) -+ first = false -+ if err != nil { -+ t.readError = err -+ close(t.incoming) -+ break -+ } -+ if p[0] == msgIgnore || p[0] == msgDebug { -+ continue -+ } -+ t.incoming <- p -+ } -+ -+ // Stop writers too. -+ t.recordWriteError(t.readError) -+ -+ // Unblock the writer should it wait for this. -+ close(t.startKex) -+ -+ // Don't close t.requestKex; it's also written to from writePacket. -+} -+ -+func (t *handshakeTransport) pushPacket(p []byte) error { -+ if debugHandshake { -+ t.printPacket(p, true) -+ } -+ return t.conn.writePacket(p) -+} -+ -+func (t *handshakeTransport) getWriteError() error { -+ t.mu.Lock() -+ defer t.mu.Unlock() -+ return t.writeError -+} -+ -+func (t *handshakeTransport) recordWriteError(err error) { -+ t.mu.Lock() -+ defer t.mu.Unlock() -+ if t.writeError == nil && err != nil { -+ t.writeError = err -+ } -+} -+ -+func (t *handshakeTransport) requestKeyExchange() { -+ select { -+ case t.requestKex <- struct{}{}: -+ default: -+ // something already requested a kex, so do nothing. -+ } -+} -+ -+func (t *handshakeTransport) resetWriteThresholds() { -+ t.writePacketsLeft = packetRekeyThreshold -+ if t.config.RekeyThreshold > 0 { -+ t.writeBytesLeft = int64(t.config.RekeyThreshold) -+ } else if t.algorithms != nil { -+ t.writeBytesLeft = t.algorithms.w.rekeyBytes() -+ } else { -+ t.writeBytesLeft = 1 << 30 -+ } -+} -+ -+func (t *handshakeTransport) kexLoop() { -+ -+write: -+ for t.getWriteError() == nil { -+ var request *pendingKex -+ var sent bool -+ -+ for request == nil || !sent { -+ var ok bool -+ select { -+ case request, ok = <-t.startKex: -+ if !ok { -+ break write -+ } -+ case <-t.requestKex: -+ break -+ } -+ -+ if !sent { -+ if err := t.sendKexInit(); err != nil { -+ t.recordWriteError(err) -+ break -+ } -+ sent = true -+ } -+ } -+ -+ if err := t.getWriteError(); err != nil { -+ if request != nil { -+ request.done <- err -+ } -+ break -+ } -+ -+ // We're not servicing t.requestKex, but that is OK: -+ // we never block on sending to t.requestKex. -+ -+ // We're not servicing t.startKex, but the remote end -+ // has just sent us a kexInitMsg, so it can't send -+ // another key change request, until we close the done -+ // channel on the pendingKex request. -+ -+ err := t.enterKeyExchange(request.otherInit) -+ -+ t.mu.Lock() -+ t.writeError = err -+ t.sentInitPacket = nil -+ t.sentInitMsg = nil -+ -+ t.resetWriteThresholds() -+ -+ // we have completed the key exchange. Since the -+ // reader is still blocked, it is safe to clear out -+ // the requestKex channel. This avoids the situation -+ // where: 1) we consumed our own request for the -+ // initial kex, and 2) the kex from the remote side -+ // caused another send on the requestKex channel, -+ clear: -+ for { -+ select { -+ case <-t.requestKex: -+ // -+ default: -+ break clear -+ } -+ } -+ -+ request.done <- t.writeError -+ -+ // kex finished. Push packets that we received while -+ // the kex was in progress. Don't look at t.startKex -+ // and don't increment writtenSinceKex: if we trigger -+ // another kex while we are still busy with the last -+ // one, things will become very confusing. -+ for _, p := range t.pendingPackets { -+ t.writeError = t.pushPacket(p) -+ if t.writeError != nil { -+ break -+ } -+ } -+ t.pendingPackets = t.pendingPackets[:0] -+ t.mu.Unlock() -+ } -+ -+ // Unblock reader. -+ t.conn.Close() -+ -+ // drain startKex channel. We don't service t.requestKex -+ // because nobody does blocking sends there. -+ for request := range t.startKex { -+ request.done <- t.getWriteError() -+ } -+ -+ // Mark that the loop is done so that Close can return. -+ close(t.kexLoopDone) -+} -+ -+// The protocol uses uint32 for packet counters, so we can't let them -+// reach 1<<32. We will actually read and write more packets than -+// this, though: the other side may send more packets, and after we -+// hit this limit on writing we will send a few more packets for the -+// key exchange itself. -+const packetRekeyThreshold = (1 << 31) -+ -+func (t *handshakeTransport) resetReadThresholds() { -+ t.readPacketsLeft = packetRekeyThreshold -+ if t.config.RekeyThreshold > 0 { -+ t.readBytesLeft = int64(t.config.RekeyThreshold) -+ } else if t.algorithms != nil { -+ t.readBytesLeft = t.algorithms.r.rekeyBytes() -+ } else { -+ t.readBytesLeft = 1 << 30 -+ } -+} -+ -+func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) { -+ p, err := t.conn.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ if t.readPacketsLeft > 0 { -+ t.readPacketsLeft-- -+ } else { -+ t.requestKeyExchange() -+ } -+ -+ if t.readBytesLeft > 0 { -+ t.readBytesLeft -= int64(len(p)) -+ } else { -+ t.requestKeyExchange() -+ } -+ -+ if debugHandshake { -+ t.printPacket(p, false) -+ } -+ -+ if first && p[0] != msgKexInit { -+ return nil, fmt.Errorf("ssh: first packet should be msgKexInit") -+ } -+ -+ if p[0] != msgKexInit { -+ return p, nil -+ } -+ -+ firstKex := t.sessionID == nil -+ -+ kex := pendingKex{ -+ done: make(chan error, 1), -+ otherInit: p, -+ } -+ t.startKex <- &kex -+ err = <-kex.done -+ -+ if debugHandshake { -+ log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err) -+ } -+ -+ if err != nil { -+ return nil, err -+ } -+ -+ t.resetReadThresholds() -+ -+ // By default, a key exchange is hidden from higher layers by -+ // translating it into msgIgnore. -+ successPacket := []byte{msgIgnore} -+ if firstKex { -+ // sendKexInit() for the first kex waits for -+ // msgNewKeys so the authentication process is -+ // guaranteed to happen over an encrypted transport. -+ successPacket = []byte{msgNewKeys} -+ } -+ -+ return successPacket, nil -+} -+ -+// sendKexInit sends a key change message. -+func (t *handshakeTransport) sendKexInit() error { -+ t.mu.Lock() -+ defer t.mu.Unlock() -+ if t.sentInitMsg != nil { -+ // kexInits may be sent either in response to the other side, -+ // or because our side wants to initiate a key change, so we -+ // may have already sent a kexInit. In that case, don't send a -+ // second kexInit. -+ return nil -+ } -+ -+ msg := &kexInitMsg{ -+ KexAlgos: t.config.KeyExchanges, -+ CiphersClientServer: t.config.Ciphers, -+ CiphersServerClient: t.config.Ciphers, -+ MACsClientServer: t.config.MACs, -+ MACsServerClient: t.config.MACs, -+ CompressionClientServer: supportedCompressions, -+ CompressionServerClient: supportedCompressions, -+ } -+ io.ReadFull(rand.Reader, msg.Cookie[:]) -+ -+ isServer := len(t.hostKeys) > 0 -+ if isServer { -+ for _, k := range t.hostKeys { -+ // If k is an AlgorithmSigner, presume it supports all signature algorithms -+ // associated with the key format. (Ideally AlgorithmSigner would have a -+ // method to advertise supported algorithms, but it doesn't. This means that -+ // adding support for a new algorithm is a breaking change, as we will -+ // immediately negotiate it even if existing implementations don't support -+ // it. If that ever happens, we'll have to figure something out.) -+ // If k is not an AlgorithmSigner, we can only assume it only supports the -+ // algorithms that matches the key format. (This means that Sign can't pick -+ // a different default.) -+ keyFormat := k.PublicKey().Type() -+ if _, ok := k.(AlgorithmSigner); ok { -+ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...) -+ } else { -+ msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat) -+ } -+ } -+ } else { -+ msg.ServerHostKeyAlgos = t.hostKeyAlgorithms -+ -+ // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what -+ // algorithms the server supports for public key authentication. See RFC -+ // 8308, Section 2.1. -+ if firstKeyExchange := t.sessionID == nil; firstKeyExchange { -+ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1) -+ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) -+ msg.KexAlgos = append(msg.KexAlgos, "ext-info-c") -+ } -+ } -+ -+ packet := Marshal(msg) -+ -+ // writePacket destroys the contents, so save a copy. -+ packetCopy := make([]byte, len(packet)) -+ copy(packetCopy, packet) -+ -+ if err := t.pushPacket(packetCopy); err != nil { -+ return err -+ } -+ -+ t.sentInitMsg = msg -+ t.sentInitPacket = packet -+ -+ return nil -+} -+ -+func (t *handshakeTransport) writePacket(p []byte) error { -+ switch p[0] { -+ case msgKexInit: -+ return errors.New("ssh: only handshakeTransport can send kexInit") -+ case msgNewKeys: -+ return errors.New("ssh: only handshakeTransport can send newKeys") -+ } -+ -+ t.mu.Lock() -+ defer t.mu.Unlock() -+ if t.writeError != nil { -+ return t.writeError -+ } -+ -+ if t.sentInitMsg != nil { -+ // Copy the packet so the writer can reuse the buffer. -+ cp := make([]byte, len(p)) -+ copy(cp, p) -+ t.pendingPackets = append(t.pendingPackets, cp) -+ return nil -+ } -+ -+ if t.writeBytesLeft > 0 { -+ t.writeBytesLeft -= int64(len(p)) -+ } else { -+ t.requestKeyExchange() -+ } -+ -+ if t.writePacketsLeft > 0 { -+ t.writePacketsLeft-- -+ } else { -+ t.requestKeyExchange() -+ } -+ -+ if err := t.pushPacket(p); err != nil { -+ t.writeError = err -+ } -+ -+ return nil -+} -+ -+func (t *handshakeTransport) Close() error { -+ // Close the connection. This should cause the readLoop goroutine to wake up -+ // and close t.startKex, which will shut down kexLoop if running. -+ err := t.conn.Close() -+ -+ // Wait for the kexLoop goroutine to complete. -+ // At that point we know that the readLoop goroutine is complete too, -+ // because kexLoop itself waits for readLoop to close the startKex channel. -+ <-t.kexLoopDone -+ -+ return err -+} -+ -+func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { -+ if debugHandshake { -+ log.Printf("%s entered key exchange", t.id()) -+ } -+ -+ otherInit := &kexInitMsg{} -+ if err := Unmarshal(otherInitPacket, otherInit); err != nil { -+ return err -+ } -+ -+ magics := handshakeMagics{ -+ clientVersion: t.clientVersion, -+ serverVersion: t.serverVersion, -+ clientKexInit: otherInitPacket, -+ serverKexInit: t.sentInitPacket, -+ } -+ -+ clientInit := otherInit -+ serverInit := t.sentInitMsg -+ isClient := len(t.hostKeys) == 0 -+ if isClient { -+ clientInit, serverInit = serverInit, clientInit -+ -+ magics.clientKexInit = t.sentInitPacket -+ magics.serverKexInit = otherInitPacket -+ } -+ -+ var err error -+ t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit) -+ if err != nil { -+ return err -+ } -+ -+ // We don't send FirstKexFollows, but we handle receiving it. -+ // -+ // RFC 4253 section 7 defines the kex and the agreement method for -+ // first_kex_packet_follows. It states that the guessed packet -+ // should be ignored if the "kex algorithm and/or the host -+ // key algorithm is guessed wrong (server and client have -+ // different preferred algorithm), or if any of the other -+ // algorithms cannot be agreed upon". The other algorithms have -+ // already been checked above so the kex algorithm and host key -+ // algorithm are checked here. -+ if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) { -+ // other side sent a kex message for the wrong algorithm, -+ // which we have to ignore. -+ if _, err := t.conn.readPacket(); err != nil { -+ return err -+ } -+ } -+ -+ kex, ok := kexAlgoMap[t.algorithms.kex] -+ if !ok { -+ return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex) -+ } -+ -+ var result *kexResult -+ if len(t.hostKeys) > 0 { -+ result, err = t.server(kex, &magics) -+ } else { -+ result, err = t.client(kex, &magics) -+ } -+ -+ if err != nil { -+ return err -+ } -+ -+ firstKeyExchange := t.sessionID == nil -+ if firstKeyExchange { -+ t.sessionID = result.H -+ } -+ result.SessionID = t.sessionID -+ -+ if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil { -+ return err -+ } -+ if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { -+ return err -+ } -+ -+ // On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO -+ // message with the server-sig-algs extension if the client supports it. See -+ // RFC 8308, Sections 2.4 and 3.1. -+ if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") { -+ extInfo := &extInfoMsg{ -+ NumExtensions: 1, -+ Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)), -+ } -+ extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs")) -+ extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...) -+ extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList)) -+ extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...) -+ if err := t.conn.writePacket(Marshal(extInfo)); err != nil { -+ return err -+ } -+ } -+ -+ if packet, err := t.conn.readPacket(); err != nil { -+ return err -+ } else if packet[0] != msgNewKeys { -+ return unexpectedMessageError(msgNewKeys, packet[0]) -+ } -+ -+ return nil -+} -+ -+// algorithmSignerWrapper is an AlgorithmSigner that only supports the default -+// key format algorithm. -+// -+// This is technically a violation of the AlgorithmSigner interface, but it -+// should be unreachable given where we use this. Anyway, at least it returns an -+// error instead of panicing or producing an incorrect signature. -+type algorithmSignerWrapper struct { -+ Signer -+} -+ -+func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -+ if algorithm != underlyingAlgo(a.PublicKey().Type()) { -+ return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm") -+ } -+ return a.Sign(rand, data) -+} -+ -+func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner { -+ for _, k := range hostKeys { -+ if algo == k.PublicKey().Type() { -+ return algorithmSignerWrapper{k} -+ } -+ k, ok := k.(AlgorithmSigner) -+ if !ok { -+ continue -+ } -+ for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) { -+ if algo == a { -+ return k -+ } -+ } -+ } -+ return nil -+} -+ -+func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { -+ hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey) -+ if hostKey == nil { -+ return nil, errors.New("ssh: internal error: negotiated unsupported signature type") -+ } -+ -+ r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey) -+ return r, err -+} -+ -+func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { -+ result, err := kex.Client(t.conn, t.config.Rand, magics) -+ if err != nil { -+ return nil, err -+ } -+ -+ hostKey, err := ParsePublicKey(result.HostKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil { -+ return nil, err -+ } -+ -+ err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ return result, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/handshake_test.go b/ms_mod/golang.org/x/crypto/ssh/handshake_test.go -new file mode 100644 -index 00000000000000..879143a6b5f2e9 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/handshake_test.go -@@ -0,0 +1,622 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "errors" -+ "fmt" -+ "io" -+ "net" -+ "reflect" -+ "runtime" -+ "strings" -+ "sync" -+ "testing" -+) -+ -+type testChecker struct { -+ calls []string -+} -+ -+func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { -+ if dialAddr == "bad" { -+ return fmt.Errorf("dialAddr is bad") -+ } -+ -+ if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil { -+ return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr) -+ } -+ -+ t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal())) -+ -+ return nil -+} -+ -+// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and -+// therefore is buffered (net.Pipe deadlocks if both sides start with -+// a write.) -+func netPipe() (net.Conn, net.Conn, error) { -+ listener, err := net.Listen("tcp", "127.0.0.1:0") -+ if err != nil { -+ listener, err = net.Listen("tcp", "[::1]:0") -+ if err != nil { -+ return nil, nil, err -+ } -+ } -+ defer listener.Close() -+ c1, err := net.Dial("tcp", listener.Addr().String()) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ c2, err := listener.Accept() -+ if err != nil { -+ c1.Close() -+ return nil, nil, err -+ } -+ -+ return c1, c2, nil -+} -+ -+// noiseTransport inserts ignore messages to check that the read loop -+// and the key exchange filters out these messages. -+type noiseTransport struct { -+ keyingTransport -+} -+ -+func (t *noiseTransport) writePacket(p []byte) error { -+ ignore := []byte{msgIgnore} -+ if err := t.keyingTransport.writePacket(ignore); err != nil { -+ return err -+ } -+ debug := []byte{msgDebug, 1, 2, 3} -+ if err := t.keyingTransport.writePacket(debug); err != nil { -+ return err -+ } -+ -+ return t.keyingTransport.writePacket(p) -+} -+ -+func addNoiseTransport(t keyingTransport) keyingTransport { -+ return &noiseTransport{t} -+} -+ -+// handshakePair creates two handshakeTransports connected with each -+// other. If the noise argument is true, both transports will try to -+// confuse the other side by sending ignore and debug messages. -+func handshakePair(clientConf *ClientConfig, addr string, noise bool) (client *handshakeTransport, server *handshakeTransport, err error) { -+ a, b, err := netPipe() -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ var trC, trS keyingTransport -+ -+ trC = newTransport(a, rand.Reader, true) -+ trS = newTransport(b, rand.Reader, false) -+ if noise { -+ trC = addNoiseTransport(trC) -+ trS = addNoiseTransport(trS) -+ } -+ clientConf.SetDefaults() -+ -+ v := []byte("version") -+ client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr()) -+ -+ serverConf := &ServerConfig{} -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ serverConf.AddHostKey(testSigners["rsa"]) -+ serverConf.SetDefaults() -+ server = newServerTransport(trS, v, v, serverConf) -+ -+ if err := server.waitSession(); err != nil { -+ return nil, nil, fmt.Errorf("server.waitSession: %v", err) -+ } -+ if err := client.waitSession(); err != nil { -+ return nil, nil, fmt.Errorf("client.waitSession: %v", err) -+ } -+ -+ return client, server, nil -+} -+ -+func TestHandshakeBasic(t *testing.T) { -+ if runtime.GOOS == "plan9" { -+ t.Skip("see golang.org/issue/7237") -+ } -+ -+ checker := &syncChecker{ -+ waitCall: make(chan int, 10), -+ called: make(chan int, 10), -+ } -+ -+ checker.waitCall <- 1 -+ trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) -+ if err != nil { -+ t.Fatalf("handshakePair: %v", err) -+ } -+ -+ defer trC.Close() -+ defer trS.Close() -+ -+ // Let first kex complete normally. -+ <-checker.called -+ -+ clientDone := make(chan int, 0) -+ gotHalf := make(chan int, 0) -+ const N = 20 -+ errorCh := make(chan error, 1) -+ -+ go func() { -+ defer close(clientDone) -+ // Client writes a bunch of stuff, and does a key -+ // change in the middle. This should not confuse the -+ // handshake in progress. We do this twice, so we test -+ // that the packet buffer is reset correctly. -+ for i := 0; i < N; i++ { -+ p := []byte{msgRequestSuccess, byte(i)} -+ if err := trC.writePacket(p); err != nil { -+ errorCh <- err -+ trC.Close() -+ return -+ } -+ if (i % 10) == 5 { -+ <-gotHalf -+ // halfway through, we request a key change. -+ trC.requestKeyExchange() -+ -+ // Wait until we can be sure the key -+ // change has really started before we -+ // write more. -+ <-checker.called -+ } -+ if (i % 10) == 7 { -+ // write some packets until the kex -+ // completes, to test buffering of -+ // packets. -+ checker.waitCall <- 1 -+ } -+ } -+ errorCh <- nil -+ }() -+ -+ // Server checks that client messages come in cleanly -+ i := 0 -+ for ; i < N; i++ { -+ p, err := trS.readPacket() -+ if err != nil && err != io.EOF { -+ t.Fatalf("server error: %v", err) -+ } -+ if (i % 10) == 5 { -+ gotHalf <- 1 -+ } -+ -+ want := []byte{msgRequestSuccess, byte(i)} -+ if bytes.Compare(p, want) != 0 { -+ t.Errorf("message %d: got %v, want %v", i, p, want) -+ } -+ } -+ <-clientDone -+ if err := <-errorCh; err != nil { -+ t.Fatalf("sendPacket: %v", err) -+ } -+ if i != N { -+ t.Errorf("received %d messages, want 10.", i) -+ } -+ -+ close(checker.called) -+ if _, ok := <-checker.called; ok { -+ // If all went well, we registered exactly 2 key changes: one -+ // that establishes the session, and one that we requested -+ // additionally. -+ t.Fatalf("got another host key checks after 2 handshakes") -+ } -+} -+ -+func TestForceFirstKex(t *testing.T) { -+ // like handshakePair, but must access the keyingTransport. -+ checker := &testChecker{} -+ clientConf := &ClientConfig{HostKeyCallback: checker.Check} -+ a, b, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ -+ var trC, trS keyingTransport -+ -+ trC = newTransport(a, rand.Reader, true) -+ -+ // This is the disallowed packet: -+ trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})) -+ -+ // Rest of the setup. -+ trS = newTransport(b, rand.Reader, false) -+ clientConf.SetDefaults() -+ -+ v := []byte("version") -+ client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr()) -+ -+ serverConf := &ServerConfig{} -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ serverConf.AddHostKey(testSigners["rsa"]) -+ serverConf.SetDefaults() -+ server := newServerTransport(trS, v, v, serverConf) -+ -+ defer client.Close() -+ defer server.Close() -+ -+ // We setup the initial key exchange, but the remote side -+ // tries to send serviceRequestMsg in cleartext, which is -+ // disallowed. -+ -+ if err := server.waitSession(); err == nil { -+ t.Errorf("server first kex init should reject unexpected packet") -+ } -+} -+ -+func TestHandshakeAutoRekeyWrite(t *testing.T) { -+ checker := &syncChecker{ -+ called: make(chan int, 10), -+ waitCall: nil, -+ } -+ clientConf := &ClientConfig{HostKeyCallback: checker.Check} -+ clientConf.RekeyThreshold = 500 -+ trC, trS, err := handshakePair(clientConf, "addr", false) -+ if err != nil { -+ t.Fatalf("handshakePair: %v", err) -+ } -+ defer trC.Close() -+ defer trS.Close() -+ -+ input := make([]byte, 251) -+ input[0] = msgRequestSuccess -+ -+ done := make(chan int, 1) -+ const numPacket = 5 -+ go func() { -+ defer close(done) -+ j := 0 -+ for ; j < numPacket; j++ { -+ if p, err := trS.readPacket(); err != nil { -+ break -+ } else if !bytes.Equal(input, p) { -+ t.Errorf("got packet type %d, want %d", p[0], input[0]) -+ } -+ } -+ -+ if j != numPacket { -+ t.Errorf("got %d, want 5 messages", j) -+ } -+ }() -+ -+ <-checker.called -+ -+ for i := 0; i < numPacket; i++ { -+ p := make([]byte, len(input)) -+ copy(p, input) -+ if err := trC.writePacket(p); err != nil { -+ t.Errorf("writePacket: %v", err) -+ } -+ if i == 2 { -+ // Make sure the kex is in progress. -+ <-checker.called -+ } -+ -+ } -+ <-done -+} -+ -+type syncChecker struct { -+ waitCall chan int -+ called chan int -+} -+ -+func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { -+ c.called <- 1 -+ if c.waitCall != nil { -+ <-c.waitCall -+ } -+ return nil -+} -+ -+func TestHandshakeAutoRekeyRead(t *testing.T) { -+ sync := &syncChecker{ -+ called: make(chan int, 2), -+ waitCall: nil, -+ } -+ clientConf := &ClientConfig{ -+ HostKeyCallback: sync.Check, -+ } -+ clientConf.RekeyThreshold = 500 -+ -+ trC, trS, err := handshakePair(clientConf, "addr", false) -+ if err != nil { -+ t.Fatalf("handshakePair: %v", err) -+ } -+ defer trC.Close() -+ defer trS.Close() -+ -+ packet := make([]byte, 501) -+ packet[0] = msgRequestSuccess -+ if err := trS.writePacket(packet); err != nil { -+ t.Fatalf("writePacket: %v", err) -+ } -+ -+ // While we read out the packet, a key change will be -+ // initiated. -+ errorCh := make(chan error, 1) -+ go func() { -+ _, err := trC.readPacket() -+ errorCh <- err -+ }() -+ -+ if err := <-errorCh; err != nil { -+ t.Fatalf("readPacket(client): %v", err) -+ } -+ -+ <-sync.called -+} -+ -+// errorKeyingTransport generates errors after a given number of -+// read/write operations. -+type errorKeyingTransport struct { -+ packetConn -+ readLeft, writeLeft int -+} -+ -+func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { -+ return nil -+} -+ -+func (n *errorKeyingTransport) getSessionID() []byte { -+ return nil -+} -+ -+func (n *errorKeyingTransport) writePacket(packet []byte) error { -+ if n.writeLeft == 0 { -+ n.Close() -+ return errors.New("barf") -+ } -+ -+ n.writeLeft-- -+ return n.packetConn.writePacket(packet) -+} -+ -+func (n *errorKeyingTransport) readPacket() ([]byte, error) { -+ if n.readLeft == 0 { -+ n.Close() -+ return nil, errors.New("barf") -+ } -+ -+ n.readLeft-- -+ return n.packetConn.readPacket() -+} -+ -+func TestHandshakeErrorHandlingRead(t *testing.T) { -+ for i := 0; i < 20; i++ { -+ testHandshakeErrorHandlingN(t, i, -1, false) -+ } -+} -+ -+func TestHandshakeErrorHandlingWrite(t *testing.T) { -+ for i := 0; i < 20; i++ { -+ testHandshakeErrorHandlingN(t, -1, i, false) -+ } -+} -+ -+func TestHandshakeErrorHandlingReadCoupled(t *testing.T) { -+ for i := 0; i < 20; i++ { -+ testHandshakeErrorHandlingN(t, i, -1, true) -+ } -+} -+ -+func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) { -+ for i := 0; i < 20; i++ { -+ testHandshakeErrorHandlingN(t, -1, i, true) -+ } -+} -+ -+// testHandshakeErrorHandlingN runs handshakes, injecting errors. If -+// handshakeTransport deadlocks, the go runtime will detect it and -+// panic. -+func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) { -+ if (runtime.GOOS == "js" || runtime.GOOS == "wasip1") && runtime.GOARCH == "wasm" { -+ t.Skipf("skipping on %s/wasm; see golang.org/issue/32840", runtime.GOOS) -+ } -+ msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)}) -+ -+ a, b := memPipe() -+ defer a.Close() -+ defer b.Close() -+ -+ key := testSigners["ecdsa"] -+ serverConf := Config{RekeyThreshold: minRekeyThreshold} -+ serverConf.SetDefaults() -+ serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'}) -+ serverConn.hostKeys = []Signer{key} -+ go serverConn.readLoop() -+ go serverConn.kexLoop() -+ -+ clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold} -+ clientConf.SetDefaults() -+ clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'}) -+ clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()} -+ clientConn.hostKeyCallback = InsecureIgnoreHostKey() -+ go clientConn.readLoop() -+ go clientConn.kexLoop() -+ -+ var wg sync.WaitGroup -+ -+ for _, hs := range []packetConn{serverConn, clientConn} { -+ if !coupled { -+ wg.Add(2) -+ go func(c packetConn) { -+ for i := 0; ; i++ { -+ str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8) -+ err := c.writePacket(Marshal(&serviceRequestMsg{str})) -+ if err != nil { -+ break -+ } -+ } -+ wg.Done() -+ c.Close() -+ }(hs) -+ go func(c packetConn) { -+ for { -+ _, err := c.readPacket() -+ if err != nil { -+ break -+ } -+ } -+ wg.Done() -+ }(hs) -+ } else { -+ wg.Add(1) -+ go func(c packetConn) { -+ for { -+ _, err := c.readPacket() -+ if err != nil { -+ break -+ } -+ if err := c.writePacket(msg); err != nil { -+ break -+ } -+ -+ } -+ wg.Done() -+ }(hs) -+ } -+ } -+ wg.Wait() -+} -+ -+func TestDisconnect(t *testing.T) { -+ if runtime.GOOS == "plan9" { -+ t.Skip("see golang.org/issue/7237") -+ } -+ checker := &testChecker{} -+ trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) -+ if err != nil { -+ t.Fatalf("handshakePair: %v", err) -+ } -+ -+ defer trC.Close() -+ defer trS.Close() -+ -+ trC.writePacket([]byte{msgRequestSuccess, 0, 0}) -+ errMsg := &disconnectMsg{ -+ Reason: 42, -+ Message: "such is life", -+ } -+ trC.writePacket(Marshal(errMsg)) -+ trC.writePacket([]byte{msgRequestSuccess, 0, 0}) -+ -+ packet, err := trS.readPacket() -+ if err != nil { -+ t.Fatalf("readPacket 1: %v", err) -+ } -+ if packet[0] != msgRequestSuccess { -+ t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess) -+ } -+ -+ _, err = trS.readPacket() -+ if err == nil { -+ t.Errorf("readPacket 2 succeeded") -+ } else if !reflect.DeepEqual(err, errMsg) { -+ t.Errorf("got error %#v, want %#v", err, errMsg) -+ } -+ -+ _, err = trS.readPacket() -+ if err == nil { -+ t.Errorf("readPacket 3 succeeded") -+ } -+} -+ -+func TestHandshakeRekeyDefault(t *testing.T) { -+ clientConf := &ClientConfig{ -+ Config: Config{ -+ Ciphers: []string{"aes128-ctr"}, -+ }, -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ trC, trS, err := handshakePair(clientConf, "addr", false) -+ if err != nil { -+ t.Fatalf("handshakePair: %v", err) -+ } -+ defer trC.Close() -+ defer trS.Close() -+ -+ trC.writePacket([]byte{msgRequestSuccess, 0, 0}) -+ trC.Close() -+ -+ rgb := (1024 + trC.readBytesLeft) >> 30 -+ wgb := (1024 + trC.writeBytesLeft) >> 30 -+ -+ if rgb != 64 { -+ t.Errorf("got rekey after %dG read, want 64G", rgb) -+ } -+ if wgb != 64 { -+ t.Errorf("got rekey after %dG write, want 64G", wgb) -+ } -+} -+ -+func TestHandshakeAEADCipherNoMAC(t *testing.T) { -+ for _, cipher := range []string{chacha20Poly1305ID, gcm128CipherID} { -+ checker := &syncChecker{ -+ called: make(chan int, 1), -+ } -+ clientConf := &ClientConfig{ -+ Config: Config{ -+ Ciphers: []string{cipher}, -+ MACs: []string{}, -+ }, -+ HostKeyCallback: checker.Check, -+ } -+ trC, trS, err := handshakePair(clientConf, "addr", false) -+ if err != nil { -+ t.Fatalf("handshakePair: %v", err) -+ } -+ defer trC.Close() -+ defer trS.Close() -+ -+ <-checker.called -+ } -+} -+ -+// TestNoSHA2Support tests a host key Signer that is not an AlgorithmSigner and -+// therefore can't do SHA-2 signatures. Ensures the server does not advertise -+// support for them in this case. -+func TestNoSHA2Support(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ serverConf := &ServerConfig{ -+ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { -+ return &Permissions{}, nil -+ }, -+ } -+ serverConf.AddHostKey(&legacyRSASigner{testSigners["rsa"]}) -+ go func() { -+ _, _, _, err := NewServerConn(c1, serverConf) -+ if err != nil { -+ t.Error(err) -+ } -+ }() -+ -+ clientConf := &ClientConfig{ -+ User: "test", -+ Auth: []AuthMethod{Password("testpw")}, -+ HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()), -+ } -+ -+ if _, _, _, err := NewClientConn(c2, "", clientConf); err != nil { -+ t.Fatal(err) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go -new file mode 100644 -index 00000000000000..af81d266546eaa ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go -@@ -0,0 +1,93 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD. -+// -+// See https://flak.tedunangst.com/post/bcrypt-pbkdf and -+// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c. -+package bcrypt_pbkdf -+ -+import ( -+ "crypto/sha512" -+ "errors" -+ "golang.org/x/crypto/blowfish" -+) -+ -+const blockSize = 32 -+ -+// Key derives a key from the password, salt and rounds count, returning a -+// []byte of length keyLen that can be used as cryptographic key. -+func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) { -+ if rounds < 1 { -+ return nil, errors.New("bcrypt_pbkdf: number of rounds is too small") -+ } -+ if len(password) == 0 { -+ return nil, errors.New("bcrypt_pbkdf: empty password") -+ } -+ if len(salt) == 0 || len(salt) > 1<<20 { -+ return nil, errors.New("bcrypt_pbkdf: bad salt length") -+ } -+ if keyLen > 1024 { -+ return nil, errors.New("bcrypt_pbkdf: keyLen is too large") -+ } -+ -+ numBlocks := (keyLen + blockSize - 1) / blockSize -+ key := make([]byte, numBlocks*blockSize) -+ -+ h := sha512.New() -+ h.Write(password) -+ shapass := h.Sum(nil) -+ -+ shasalt := make([]byte, 0, sha512.Size) -+ cnt, tmp := make([]byte, 4), make([]byte, blockSize) -+ for block := 1; block <= numBlocks; block++ { -+ h.Reset() -+ h.Write(salt) -+ cnt[0] = byte(block >> 24) -+ cnt[1] = byte(block >> 16) -+ cnt[2] = byte(block >> 8) -+ cnt[3] = byte(block) -+ h.Write(cnt) -+ bcryptHash(tmp, shapass, h.Sum(shasalt)) -+ -+ out := make([]byte, blockSize) -+ copy(out, tmp) -+ for i := 2; i <= rounds; i++ { -+ h.Reset() -+ h.Write(tmp) -+ bcryptHash(tmp, shapass, h.Sum(shasalt)) -+ for j := 0; j < len(out); j++ { -+ out[j] ^= tmp[j] -+ } -+ } -+ -+ for i, v := range out { -+ key[i*numBlocks+(block-1)] = v -+ } -+ } -+ return key[:keyLen], nil -+} -+ -+var magic = []byte("OxychromaticBlowfishSwatDynamite") -+ -+func bcryptHash(out, shapass, shasalt []byte) { -+ c, err := blowfish.NewSaltedCipher(shapass, shasalt) -+ if err != nil { -+ panic(err) -+ } -+ for i := 0; i < 64; i++ { -+ blowfish.ExpandKey(shasalt, c) -+ blowfish.ExpandKey(shapass, c) -+ } -+ copy(out, magic) -+ for i := 0; i < 32; i += 8 { -+ for j := 0; j < 64; j++ { -+ c.Encrypt(out[i:i+8], out[i:i+8]) -+ } -+ } -+ // Swap bytes due to different endianness. -+ for i := 0; i < 32; i += 4 { -+ out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3] -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go -new file mode 100644 -index 00000000000000..20b7889bce95a3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf_test.go -@@ -0,0 +1,97 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package bcrypt_pbkdf -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+// Test vectors generated by the reference implementation from OpenBSD. -+var golden = []struct { -+ rounds int -+ password, salt, result []byte -+}{ -+ { -+ 12, -+ []byte("password"), -+ []byte("salt"), -+ []byte{ -+ 0x1a, 0xe4, 0x2c, 0x05, 0xd4, 0x87, 0xbc, 0x02, 0xf6, -+ 0x49, 0x21, 0xa4, 0xeb, 0xe4, 0xea, 0x93, 0xbc, 0xac, -+ 0xfe, 0x13, 0x5f, 0xda, 0x99, 0x97, 0x4c, 0x06, 0xb7, -+ 0xb0, 0x1f, 0xae, 0x14, 0x9a, -+ }, -+ }, -+ { -+ 3, -+ []byte("passwordy\x00PASSWORD\x00"), -+ []byte("salty\x00SALT\x00"), -+ []byte{ -+ 0x7f, 0x31, 0x0b, 0xd3, 0xe7, 0x8c, 0x32, 0x80, 0xc5, -+ 0x9c, 0xe4, 0x59, 0x52, 0x11, 0xa2, 0x92, 0x8e, 0x8d, -+ 0x4e, 0xc7, 0x44, 0xc1, 0xed, 0x2e, 0xfc, 0x9f, 0x76, -+ 0x4e, 0x33, 0x88, 0xe0, 0xad, -+ }, -+ }, -+ { -+ // See http://thread.gmane.org/gmane.os.openbsd.bugs/20542 -+ 8, -+ []byte("сСкрСтноС слово"), -+ []byte("ΠΏΠΎΡΠΎΠ»ΠΈΡ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠΆΠΊΠΎ"), -+ []byte{ -+ 0x8d, 0xf4, 0x3f, 0xc6, 0xfe, 0x13, 0x1f, 0xc4, 0x7f, -+ 0x0c, 0x9e, 0x39, 0x22, 0x4b, 0xd9, 0x4c, 0x70, 0xb6, -+ 0xfc, 0xc8, 0xee, 0x81, 0x35, 0xfa, 0xdd, 0xf6, 0x11, -+ 0x56, 0xe6, 0xcb, 0x27, 0x33, 0xea, 0x76, 0x5f, 0x31, -+ 0x5a, 0x3e, 0x1e, 0x4a, 0xfc, 0x35, 0xbf, 0x86, 0x87, -+ 0xd1, 0x89, 0x25, 0x4c, 0x1e, 0x05, 0xa6, 0xfe, 0x80, -+ 0xc0, 0x61, 0x7f, 0x91, 0x83, 0xd6, 0x72, 0x60, 0xd6, -+ 0xa1, 0x15, 0xc6, 0xc9, 0x4e, 0x36, 0x03, 0xe2, 0x30, -+ 0x3f, 0xbb, 0x43, 0xa7, 0x6a, 0x64, 0x52, 0x3f, 0xfd, -+ 0xa6, 0x86, 0xb1, 0xd4, 0x51, 0x85, 0x43, -+ }, -+ }, -+} -+ -+func TestKey(t *testing.T) { -+ for i, v := range golden { -+ k, err := Key(v.password, v.salt, v.rounds, len(v.result)) -+ if err != nil { -+ t.Errorf("%d: %s", i, err) -+ continue -+ } -+ if !bytes.Equal(k, v.result) { -+ t.Errorf("%d: expected\n%x\n, got\n%x\n", i, v.result, k) -+ } -+ } -+} -+ -+func TestBcryptHash(t *testing.T) { -+ good := []byte{ -+ 0x87, 0x90, 0x48, 0x70, 0xee, 0xf9, 0xde, 0xdd, 0xf8, 0xe7, -+ 0x61, 0x1a, 0x14, 0x01, 0x06, 0xe6, 0xaa, 0xf1, 0xa3, 0x63, -+ 0xd9, 0xa2, 0xc5, 0x04, 0xdb, 0x35, 0x64, 0x43, 0x72, 0x1e, -+ 0xb5, 0x55, -+ } -+ var pass, salt [64]byte -+ var result [32]byte -+ for i := 0; i < 64; i++ { -+ pass[i] = byte(i) -+ salt[i] = byte(i + 64) -+ } -+ bcryptHash(result[:], pass[:], salt[:]) -+ if !bytes.Equal(result[:], good) { -+ t.Errorf("expected %x, got %x", good, result) -+ } -+} -+ -+func BenchmarkKey(b *testing.B) { -+ pass := []byte("password") -+ salt := []byte("salt") -+ for i := 0; i < b.N; i++ { -+ Key(pass, salt, 10, 32) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/kex.go b/ms_mod/golang.org/x/crypto/ssh/kex.go -new file mode 100644 -index 00000000000000..8a05f79902c095 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/kex.go -@@ -0,0 +1,786 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/subtle" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ -+ "golang.org/x/crypto/curve25519" -+) -+ -+const ( -+ kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" -+ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" -+ kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256" -+ kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512" -+ kexAlgoECDH256 = "ecdh-sha2-nistp256" -+ kexAlgoECDH384 = "ecdh-sha2-nistp384" -+ kexAlgoECDH521 = "ecdh-sha2-nistp521" -+ kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org" -+ kexAlgoCurve25519SHA256 = "curve25519-sha256" -+ -+ // For the following kex only the client half contains a production -+ // ready implementation. The server half only consists of a minimal -+ // implementation to satisfy the automated tests. -+ kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1" -+ kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256" -+) -+ -+// kexResult captures the outcome of a key exchange. -+type kexResult struct { -+ // Session hash. See also RFC 4253, section 8. -+ H []byte -+ -+ // Shared secret. See also RFC 4253, section 8. -+ K []byte -+ -+ // Host key as hashed into H. -+ HostKey []byte -+ -+ // Signature of H. -+ Signature []byte -+ -+ // A cryptographic hash function that matches the security -+ // level of the key exchange algorithm. It is used for -+ // calculating H, and for deriving keys from H and K. -+ Hash crypto.Hash -+ -+ // The session ID, which is the first H computed. This is used -+ // to derive key material inside the transport. -+ SessionID []byte -+} -+ -+// handshakeMagics contains data that is always included in the -+// session hash. -+type handshakeMagics struct { -+ clientVersion, serverVersion []byte -+ clientKexInit, serverKexInit []byte -+} -+ -+func (m *handshakeMagics) write(w io.Writer) { -+ writeString(w, m.clientVersion) -+ writeString(w, m.serverVersion) -+ writeString(w, m.clientKexInit) -+ writeString(w, m.serverKexInit) -+} -+ -+// kexAlgorithm abstracts different key exchange algorithms. -+type kexAlgorithm interface { -+ // Server runs server-side key agreement, signing the result -+ // with a hostkey. algo is the negotiated algorithm, and may -+ // be a certificate type. -+ Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error) -+ -+ // Client runs the client-side key agreement. Caller is -+ // responsible for verifying the host key signature. -+ Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) -+} -+ -+// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. -+type dhGroup struct { -+ g, p, pMinus1 *big.Int -+ hashFunc crypto.Hash -+} -+ -+func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { -+ if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 { -+ return nil, errors.New("ssh: DH parameter out of bounds") -+ } -+ return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil -+} -+ -+func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { -+ var x *big.Int -+ for { -+ var err error -+ if x, err = rand.Int(randSource, group.pMinus1); err != nil { -+ return nil, err -+ } -+ if x.Sign() > 0 { -+ break -+ } -+ } -+ -+ X := new(big.Int).Exp(group.g, x, group.p) -+ kexDHInit := kexDHInitMsg{ -+ X: X, -+ } -+ if err := c.writePacket(Marshal(&kexDHInit)); err != nil { -+ return nil, err -+ } -+ -+ packet, err := c.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ var kexDHReply kexDHReplyMsg -+ if err = Unmarshal(packet, &kexDHReply); err != nil { -+ return nil, err -+ } -+ -+ ki, err := group.diffieHellman(kexDHReply.Y, x) -+ if err != nil { -+ return nil, err -+ } -+ -+ h := group.hashFunc.New() -+ magics.write(h) -+ writeString(h, kexDHReply.HostKey) -+ writeInt(h, X) -+ writeInt(h, kexDHReply.Y) -+ K := make([]byte, intLength(ki)) -+ marshalInt(K, ki) -+ h.Write(K) -+ -+ return &kexResult{ -+ H: h.Sum(nil), -+ K: K, -+ HostKey: kexDHReply.HostKey, -+ Signature: kexDHReply.Signature, -+ Hash: group.hashFunc, -+ }, nil -+} -+ -+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { -+ packet, err := c.readPacket() -+ if err != nil { -+ return -+ } -+ var kexDHInit kexDHInitMsg -+ if err = Unmarshal(packet, &kexDHInit); err != nil { -+ return -+ } -+ -+ var y *big.Int -+ for { -+ if y, err = rand.Int(randSource, group.pMinus1); err != nil { -+ return -+ } -+ if y.Sign() > 0 { -+ break -+ } -+ } -+ -+ Y := new(big.Int).Exp(group.g, y, group.p) -+ ki, err := group.diffieHellman(kexDHInit.X, y) -+ if err != nil { -+ return nil, err -+ } -+ -+ hostKeyBytes := priv.PublicKey().Marshal() -+ -+ h := group.hashFunc.New() -+ magics.write(h) -+ writeString(h, hostKeyBytes) -+ writeInt(h, kexDHInit.X) -+ writeInt(h, Y) -+ -+ K := make([]byte, intLength(ki)) -+ marshalInt(K, ki) -+ h.Write(K) -+ -+ H := h.Sum(nil) -+ -+ // H is already a hash, but the hostkey signing will apply its -+ // own key-specific hash algorithm. -+ sig, err := signAndMarshal(priv, randSource, H, algo) -+ if err != nil { -+ return nil, err -+ } -+ -+ kexDHReply := kexDHReplyMsg{ -+ HostKey: hostKeyBytes, -+ Y: Y, -+ Signature: sig, -+ } -+ packet = Marshal(&kexDHReply) -+ -+ err = c.writePacket(packet) -+ return &kexResult{ -+ H: H, -+ K: K, -+ HostKey: hostKeyBytes, -+ Signature: sig, -+ Hash: group.hashFunc, -+ }, err -+} -+ -+// ecdh performs Elliptic Curve Diffie-Hellman key exchange as -+// described in RFC 5656, section 4. -+type ecdh struct { -+ curve elliptic.Curve -+} -+ -+func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { -+ ephKey, err := ecdsa.GenerateKey(kex.curve, rand) -+ if err != nil { -+ return nil, err -+ } -+ -+ kexInit := kexECDHInitMsg{ -+ ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), -+ } -+ -+ serialized := Marshal(&kexInit) -+ if err := c.writePacket(serialized); err != nil { -+ return nil, err -+ } -+ -+ packet, err := c.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ var reply kexECDHReplyMsg -+ if err = Unmarshal(packet, &reply); err != nil { -+ return nil, err -+ } -+ -+ x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ // generate shared secret -+ secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) -+ -+ h := ecHash(kex.curve).New() -+ magics.write(h) -+ writeString(h, reply.HostKey) -+ writeString(h, kexInit.ClientPubKey) -+ writeString(h, reply.EphemeralPubKey) -+ K := make([]byte, intLength(secret)) -+ marshalInt(K, secret) -+ h.Write(K) -+ -+ return &kexResult{ -+ H: h.Sum(nil), -+ K: K, -+ HostKey: reply.HostKey, -+ Signature: reply.Signature, -+ Hash: ecHash(kex.curve), -+ }, nil -+} -+ -+// unmarshalECKey parses and checks an EC key. -+func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { -+ x, y = elliptic.Unmarshal(curve, pubkey) -+ if x == nil { -+ return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") -+ } -+ if !validateECPublicKey(curve, x, y) { -+ return nil, nil, errors.New("ssh: public key not on curve") -+ } -+ return x, y, nil -+} -+ -+// validateECPublicKey checks that the point is a valid public key for -+// the given curve. See [SEC1], 3.2.2 -+func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { -+ if x.Sign() == 0 && y.Sign() == 0 { -+ return false -+ } -+ -+ if x.Cmp(curve.Params().P) >= 0 { -+ return false -+ } -+ -+ if y.Cmp(curve.Params().P) >= 0 { -+ return false -+ } -+ -+ if !curve.IsOnCurve(x, y) { -+ return false -+ } -+ -+ // We don't check if N * PubKey == 0, since -+ // -+ // - the NIST curves have cofactor = 1, so this is implicit. -+ // (We don't foresee an implementation that supports non NIST -+ // curves) -+ // -+ // - for ephemeral keys, we don't need to worry about small -+ // subgroup attacks. -+ return true -+} -+ -+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { -+ packet, err := c.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ var kexECDHInit kexECDHInitMsg -+ if err = Unmarshal(packet, &kexECDHInit); err != nil { -+ return nil, err -+ } -+ -+ clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ // We could cache this key across multiple users/multiple -+ // connection attempts, but the benefit is small. OpenSSH -+ // generates a new key for each incoming connection. -+ ephKey, err := ecdsa.GenerateKey(kex.curve, rand) -+ if err != nil { -+ return nil, err -+ } -+ -+ hostKeyBytes := priv.PublicKey().Marshal() -+ -+ serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) -+ -+ // generate shared secret -+ secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) -+ -+ h := ecHash(kex.curve).New() -+ magics.write(h) -+ writeString(h, hostKeyBytes) -+ writeString(h, kexECDHInit.ClientPubKey) -+ writeString(h, serializedEphKey) -+ -+ K := make([]byte, intLength(secret)) -+ marshalInt(K, secret) -+ h.Write(K) -+ -+ H := h.Sum(nil) -+ -+ // H is already a hash, but the hostkey signing will apply its -+ // own key-specific hash algorithm. -+ sig, err := signAndMarshal(priv, rand, H, algo) -+ if err != nil { -+ return nil, err -+ } -+ -+ reply := kexECDHReplyMsg{ -+ EphemeralPubKey: serializedEphKey, -+ HostKey: hostKeyBytes, -+ Signature: sig, -+ } -+ -+ serialized := Marshal(&reply) -+ if err := c.writePacket(serialized); err != nil { -+ return nil, err -+ } -+ -+ return &kexResult{ -+ H: H, -+ K: K, -+ HostKey: reply.HostKey, -+ Signature: sig, -+ Hash: ecHash(kex.curve), -+ }, nil -+} -+ -+// ecHash returns the hash to match the given elliptic curve, see RFC -+// 5656, section 6.2.1 -+func ecHash(curve elliptic.Curve) crypto.Hash { -+ bitSize := curve.Params().BitSize -+ switch { -+ case bitSize <= 256: -+ return crypto.SHA256 -+ case bitSize <= 384: -+ return crypto.SHA384 -+ } -+ return crypto.SHA512 -+} -+ -+var kexAlgoMap = map[string]kexAlgorithm{} -+ -+func init() { -+ // This is the group called diffie-hellman-group1-sha1 in -+ // RFC 4253 and Oakley Group 2 in RFC 2409. -+ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) -+ kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ -+ g: new(big.Int).SetInt64(2), -+ p: p, -+ pMinus1: new(big.Int).Sub(p, bigOne), -+ hashFunc: crypto.SHA1, -+ } -+ -+ // This are the groups called diffie-hellman-group14-sha1 and -+ // diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268, -+ // and Oakley Group 14 in RFC 3526. -+ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) -+ group14 := &dhGroup{ -+ g: new(big.Int).SetInt64(2), -+ p: p, -+ pMinus1: new(big.Int).Sub(p, bigOne), -+ } -+ -+ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ -+ g: group14.g, p: group14.p, pMinus1: group14.pMinus1, -+ hashFunc: crypto.SHA1, -+ } -+ kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{ -+ g: group14.g, p: group14.p, pMinus1: group14.pMinus1, -+ hashFunc: crypto.SHA256, -+ } -+ -+ // This is the group called diffie-hellman-group16-sha512 in RFC -+ // 8268 and Oakley Group 16 in RFC 3526. -+ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16) -+ -+ kexAlgoMap[kexAlgoDH16SHA512] = &dhGroup{ -+ g: new(big.Int).SetInt64(2), -+ p: p, -+ pMinus1: new(big.Int).Sub(p, bigOne), -+ hashFunc: crypto.SHA512, -+ } -+ -+ kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} -+ kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} -+ kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} -+ kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} -+ kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{} -+ kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} -+ kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} -+} -+ -+// curve25519sha256 implements the curve25519-sha256 (formerly known as -+// curve25519-sha256@libssh.org) key exchange method, as described in RFC 8731. -+type curve25519sha256 struct{} -+ -+type curve25519KeyPair struct { -+ priv [32]byte -+ pub [32]byte -+} -+ -+func (kp *curve25519KeyPair) generate(rand io.Reader) error { -+ if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { -+ return err -+ } -+ curve25519.ScalarBaseMult(&kp.pub, &kp.priv) -+ return nil -+} -+ -+// curve25519Zeros is just an array of 32 zero bytes so that we have something -+// convenient to compare against in order to reject curve25519 points with the -+// wrong order. -+var curve25519Zeros [32]byte -+ -+func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { -+ var kp curve25519KeyPair -+ if err := kp.generate(rand); err != nil { -+ return nil, err -+ } -+ if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { -+ return nil, err -+ } -+ -+ packet, err := c.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ var reply kexECDHReplyMsg -+ if err = Unmarshal(packet, &reply); err != nil { -+ return nil, err -+ } -+ if len(reply.EphemeralPubKey) != 32 { -+ return nil, errors.New("ssh: peer's curve25519 public value has wrong length") -+ } -+ -+ var servPub, secret [32]byte -+ copy(servPub[:], reply.EphemeralPubKey) -+ curve25519.ScalarMult(&secret, &kp.priv, &servPub) -+ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { -+ return nil, errors.New("ssh: peer's curve25519 public value has wrong order") -+ } -+ -+ h := crypto.SHA256.New() -+ magics.write(h) -+ writeString(h, reply.HostKey) -+ writeString(h, kp.pub[:]) -+ writeString(h, reply.EphemeralPubKey) -+ -+ ki := new(big.Int).SetBytes(secret[:]) -+ K := make([]byte, intLength(ki)) -+ marshalInt(K, ki) -+ h.Write(K) -+ -+ return &kexResult{ -+ H: h.Sum(nil), -+ K: K, -+ HostKey: reply.HostKey, -+ Signature: reply.Signature, -+ Hash: crypto.SHA256, -+ }, nil -+} -+ -+func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { -+ packet, err := c.readPacket() -+ if err != nil { -+ return -+ } -+ var kexInit kexECDHInitMsg -+ if err = Unmarshal(packet, &kexInit); err != nil { -+ return -+ } -+ -+ if len(kexInit.ClientPubKey) != 32 { -+ return nil, errors.New("ssh: peer's curve25519 public value has wrong length") -+ } -+ -+ var kp curve25519KeyPair -+ if err := kp.generate(rand); err != nil { -+ return nil, err -+ } -+ -+ var clientPub, secret [32]byte -+ copy(clientPub[:], kexInit.ClientPubKey) -+ curve25519.ScalarMult(&secret, &kp.priv, &clientPub) -+ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { -+ return nil, errors.New("ssh: peer's curve25519 public value has wrong order") -+ } -+ -+ hostKeyBytes := priv.PublicKey().Marshal() -+ -+ h := crypto.SHA256.New() -+ magics.write(h) -+ writeString(h, hostKeyBytes) -+ writeString(h, kexInit.ClientPubKey) -+ writeString(h, kp.pub[:]) -+ -+ ki := new(big.Int).SetBytes(secret[:]) -+ K := make([]byte, intLength(ki)) -+ marshalInt(K, ki) -+ h.Write(K) -+ -+ H := h.Sum(nil) -+ -+ sig, err := signAndMarshal(priv, rand, H, algo) -+ if err != nil { -+ return nil, err -+ } -+ -+ reply := kexECDHReplyMsg{ -+ EphemeralPubKey: kp.pub[:], -+ HostKey: hostKeyBytes, -+ Signature: sig, -+ } -+ if err := c.writePacket(Marshal(&reply)); err != nil { -+ return nil, err -+ } -+ return &kexResult{ -+ H: H, -+ K: K, -+ HostKey: hostKeyBytes, -+ Signature: sig, -+ Hash: crypto.SHA256, -+ }, nil -+} -+ -+// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and -+// diffie-hellman-group-exchange-sha256 key agreement protocols, -+// as described in RFC 4419 -+type dhGEXSHA struct { -+ hashFunc crypto.Hash -+} -+ -+const ( -+ dhGroupExchangeMinimumBits = 2048 -+ dhGroupExchangePreferredBits = 2048 -+ dhGroupExchangeMaximumBits = 8192 -+) -+ -+func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { -+ // Send GexRequest -+ kexDHGexRequest := kexDHGexRequestMsg{ -+ MinBits: dhGroupExchangeMinimumBits, -+ PreferedBits: dhGroupExchangePreferredBits, -+ MaxBits: dhGroupExchangeMaximumBits, -+ } -+ if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil { -+ return nil, err -+ } -+ -+ // Receive GexGroup -+ packet, err := c.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ var msg kexDHGexGroupMsg -+ if err = Unmarshal(packet, &msg); err != nil { -+ return nil, err -+ } -+ -+ // reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits -+ if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits { -+ return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen()) -+ } -+ -+ // Check if g is safe by verifying that 1 < g < p-1 -+ pMinusOne := new(big.Int).Sub(msg.P, bigOne) -+ if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 { -+ return nil, fmt.Errorf("ssh: server provided gex g is not safe") -+ } -+ -+ // Send GexInit -+ pHalf := new(big.Int).Rsh(msg.P, 1) -+ x, err := rand.Int(randSource, pHalf) -+ if err != nil { -+ return nil, err -+ } -+ X := new(big.Int).Exp(msg.G, x, msg.P) -+ kexDHGexInit := kexDHGexInitMsg{ -+ X: X, -+ } -+ if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil { -+ return nil, err -+ } -+ -+ // Receive GexReply -+ packet, err = c.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ -+ var kexDHGexReply kexDHGexReplyMsg -+ if err = Unmarshal(packet, &kexDHGexReply); err != nil { -+ return nil, err -+ } -+ -+ if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 { -+ return nil, errors.New("ssh: DH parameter out of bounds") -+ } -+ kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P) -+ -+ // Check if k is safe by verifying that k > 1 and k < p - 1 -+ if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 { -+ return nil, fmt.Errorf("ssh: derived k is not safe") -+ } -+ -+ h := gex.hashFunc.New() -+ magics.write(h) -+ writeString(h, kexDHGexReply.HostKey) -+ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) -+ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) -+ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) -+ writeInt(h, msg.P) -+ writeInt(h, msg.G) -+ writeInt(h, X) -+ writeInt(h, kexDHGexReply.Y) -+ K := make([]byte, intLength(kInt)) -+ marshalInt(K, kInt) -+ h.Write(K) -+ -+ return &kexResult{ -+ H: h.Sum(nil), -+ K: K, -+ HostKey: kexDHGexReply.HostKey, -+ Signature: kexDHGexReply.Signature, -+ Hash: gex.hashFunc, -+ }, nil -+} -+ -+// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. -+// -+// This is a minimal implementation to satisfy the automated tests. -+func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) { -+ // Receive GexRequest -+ packet, err := c.readPacket() -+ if err != nil { -+ return -+ } -+ var kexDHGexRequest kexDHGexRequestMsg -+ if err = Unmarshal(packet, &kexDHGexRequest); err != nil { -+ return -+ } -+ -+ // Send GexGroup -+ // This is the group called diffie-hellman-group14-sha1 in RFC -+ // 4253 and Oakley Group 14 in RFC 3526. -+ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) -+ g := big.NewInt(2) -+ -+ msg := &kexDHGexGroupMsg{ -+ P: p, -+ G: g, -+ } -+ if err := c.writePacket(Marshal(msg)); err != nil { -+ return nil, err -+ } -+ -+ // Receive GexInit -+ packet, err = c.readPacket() -+ if err != nil { -+ return -+ } -+ var kexDHGexInit kexDHGexInitMsg -+ if err = Unmarshal(packet, &kexDHGexInit); err != nil { -+ return -+ } -+ -+ pHalf := new(big.Int).Rsh(p, 1) -+ -+ y, err := rand.Int(randSource, pHalf) -+ if err != nil { -+ return -+ } -+ Y := new(big.Int).Exp(g, y, p) -+ -+ pMinusOne := new(big.Int).Sub(p, bigOne) -+ if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 { -+ return nil, errors.New("ssh: DH parameter out of bounds") -+ } -+ kInt := new(big.Int).Exp(kexDHGexInit.X, y, p) -+ -+ hostKeyBytes := priv.PublicKey().Marshal() -+ -+ h := gex.hashFunc.New() -+ magics.write(h) -+ writeString(h, hostKeyBytes) -+ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) -+ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) -+ binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) -+ writeInt(h, p) -+ writeInt(h, g) -+ writeInt(h, kexDHGexInit.X) -+ writeInt(h, Y) -+ -+ K := make([]byte, intLength(kInt)) -+ marshalInt(K, kInt) -+ h.Write(K) -+ -+ H := h.Sum(nil) -+ -+ // H is already a hash, but the hostkey signing will apply its -+ // own key-specific hash algorithm. -+ sig, err := signAndMarshal(priv, randSource, H, algo) -+ if err != nil { -+ return nil, err -+ } -+ -+ kexDHGexReply := kexDHGexReplyMsg{ -+ HostKey: hostKeyBytes, -+ Y: Y, -+ Signature: sig, -+ } -+ packet = Marshal(&kexDHGexReply) -+ -+ err = c.writePacket(packet) -+ -+ return &kexResult{ -+ H: H, -+ K: K, -+ HostKey: hostKeyBytes, -+ Signature: sig, -+ Hash: gex.hashFunc, -+ }, err -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/kex_test.go b/ms_mod/golang.org/x/crypto/ssh/kex_test.go -new file mode 100644 -index 00000000000000..cb7f66a5092f61 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/kex_test.go -@@ -0,0 +1,106 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+// Key exchange tests. -+ -+import ( -+ "crypto/rand" -+ "fmt" -+ "reflect" -+ "sync" -+ "testing" -+) -+ -+// Runs multiple key exchanges concurrent to detect potential data races with -+// kex obtained from the global kexAlgoMap. -+// This test needs to be executed using the race detector in order to detect -+// race conditions. -+func TestKexes(t *testing.T) { -+ type kexResultErr struct { -+ result *kexResult -+ err error -+ } -+ -+ for name, kex := range kexAlgoMap { -+ t.Run(name, func(t *testing.T) { -+ wg := sync.WaitGroup{} -+ for i := 0; i < 3; i++ { -+ wg.Add(1) -+ go func() { -+ defer wg.Done() -+ a, b := memPipe() -+ -+ s := make(chan kexResultErr, 1) -+ c := make(chan kexResultErr, 1) -+ var magics handshakeMagics -+ go func() { -+ r, e := kex.Client(a, rand.Reader, &magics) -+ a.Close() -+ c <- kexResultErr{r, e} -+ }() -+ go func() { -+ r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"].(AlgorithmSigner), testSigners["ecdsa"].PublicKey().Type()) -+ b.Close() -+ s <- kexResultErr{r, e} -+ }() -+ -+ clientRes := <-c -+ serverRes := <-s -+ if clientRes.err != nil { -+ t.Errorf("client: %v", clientRes.err) -+ } -+ if serverRes.err != nil { -+ t.Errorf("server: %v", serverRes.err) -+ } -+ if !reflect.DeepEqual(clientRes.result, serverRes.result) { -+ t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) -+ } -+ }() -+ } -+ wg.Wait() -+ }) -+ } -+} -+ -+func BenchmarkKexes(b *testing.B) { -+ type kexResultErr struct { -+ result *kexResult -+ err error -+ } -+ -+ for name, kex := range kexAlgoMap { -+ b.Run(name, func(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ t1, t2 := memPipe() -+ -+ s := make(chan kexResultErr, 1) -+ c := make(chan kexResultErr, 1) -+ var magics handshakeMagics -+ -+ go func() { -+ r, e := kex.Client(t1, rand.Reader, &magics) -+ t1.Close() -+ c <- kexResultErr{r, e} -+ }() -+ go func() { -+ r, e := kex.Server(t2, rand.Reader, &magics, testSigners["ecdsa"].(AlgorithmSigner), testSigners["ecdsa"].PublicKey().Type()) -+ t2.Close() -+ s <- kexResultErr{r, e} -+ }() -+ -+ clientRes := <-c -+ serverRes := <-s -+ -+ if clientRes.err != nil { -+ panic(fmt.Sprintf("client: %v", clientRes.err)) -+ } -+ if serverRes.err != nil { -+ panic(fmt.Sprintf("server: %v", serverRes.err)) -+ } -+ } -+ }) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/keys.go b/ms_mod/golang.org/x/crypto/ssh/keys.go -new file mode 100644 -index 00000000000000..dac8ee72447668 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/keys.go -@@ -0,0 +1,1447 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/md5" -+ "crypto/rsa" -+ "crypto/sha256" -+ "crypto/x509" -+ "encoding/asn1" -+ "encoding/base64" -+ "encoding/hex" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ "strings" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf" -+) -+ -+// Public key algorithms names. These values can appear in PublicKey.Type, -+// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner -+// arguments. -+const ( -+ KeyAlgoRSA = "ssh-rsa" -+ KeyAlgoDSA = "ssh-dss" -+ KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" -+ KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" -+ KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" -+ KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" -+ KeyAlgoED25519 = "ssh-ed25519" -+ KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com" -+ -+ // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not -+ // public key formats, so they can't appear as a PublicKey.Type. The -+ // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. -+ KeyAlgoRSASHA256 = "rsa-sha2-256" -+ KeyAlgoRSASHA512 = "rsa-sha2-512" -+) -+ -+const ( -+ // Deprecated: use KeyAlgoRSA. -+ SigAlgoRSA = KeyAlgoRSA -+ // Deprecated: use KeyAlgoRSASHA256. -+ SigAlgoRSASHA2256 = KeyAlgoRSASHA256 -+ // Deprecated: use KeyAlgoRSASHA512. -+ SigAlgoRSASHA2512 = KeyAlgoRSASHA512 -+) -+ -+// parsePubKey parses a public key of the given algorithm. -+// Use ParsePublicKey for keys with prepended algorithm. -+func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { -+ switch algo { -+ case KeyAlgoRSA: -+ return parseRSA(in) -+ case KeyAlgoDSA: -+ return parseDSA(in) -+ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: -+ return parseECDSA(in) -+ case KeyAlgoSKECDSA256: -+ return parseSKECDSA(in) -+ case KeyAlgoED25519: -+ return parseED25519(in) -+ case KeyAlgoSKED25519: -+ return parseSKEd25519(in) -+ case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: -+ cert, err := parseCert(in, certKeyAlgoNames[algo]) -+ if err != nil { -+ return nil, nil, err -+ } -+ return cert, nil, nil -+ } -+ return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo) -+} -+ -+// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format -+// (see sshd(8) manual page) once the options and key type fields have been -+// removed. -+func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { -+ in = bytes.TrimSpace(in) -+ -+ i := bytes.IndexAny(in, " \t") -+ if i == -1 { -+ i = len(in) -+ } -+ base64Key := in[:i] -+ -+ key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) -+ n, err := base64.StdEncoding.Decode(key, base64Key) -+ if err != nil { -+ return nil, "", err -+ } -+ key = key[:n] -+ out, err = ParsePublicKey(key) -+ if err != nil { -+ return nil, "", err -+ } -+ comment = string(bytes.TrimSpace(in[i:])) -+ return out, comment, nil -+} -+ -+// ParseKnownHosts parses an entry in the format of the known_hosts file. -+// -+// The known_hosts format is documented in the sshd(8) manual page. This -+// function will parse a single entry from in. On successful return, marker -+// will contain the optional marker value (i.e. "cert-authority" or "revoked") -+// or else be empty, hosts will contain the hosts that this entry matches, -+// pubKey will contain the public key and comment will contain any trailing -+// comment at the end of the line. See the sshd(8) manual page for the various -+// forms that a host string can take. -+// -+// The unparsed remainder of the input will be returned in rest. This function -+// can be called repeatedly to parse multiple entries. -+// -+// If no entries were found in the input then err will be io.EOF. Otherwise a -+// non-nil err value indicates a parse error. -+func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) { -+ for len(in) > 0 { -+ end := bytes.IndexByte(in, '\n') -+ if end != -1 { -+ rest = in[end+1:] -+ in = in[:end] -+ } else { -+ rest = nil -+ } -+ -+ end = bytes.IndexByte(in, '\r') -+ if end != -1 { -+ in = in[:end] -+ } -+ -+ in = bytes.TrimSpace(in) -+ if len(in) == 0 || in[0] == '#' { -+ in = rest -+ continue -+ } -+ -+ i := bytes.IndexAny(in, " \t") -+ if i == -1 { -+ in = rest -+ continue -+ } -+ -+ // Strip out the beginning of the known_host key. -+ // This is either an optional marker or a (set of) hostname(s). -+ keyFields := bytes.Fields(in) -+ if len(keyFields) < 3 || len(keyFields) > 5 { -+ return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data") -+ } -+ -+ // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated -+ // list of hosts -+ marker := "" -+ if keyFields[0][0] == '@' { -+ marker = string(keyFields[0][1:]) -+ keyFields = keyFields[1:] -+ } -+ -+ hosts := string(keyFields[0]) -+ // keyFields[1] contains the key type (e.g. β€œssh-rsa”). -+ // However, that information is duplicated inside the -+ // base64-encoded key and so is ignored here. -+ -+ key := bytes.Join(keyFields[2:], []byte(" ")) -+ if pubKey, comment, err = parseAuthorizedKey(key); err != nil { -+ return "", nil, nil, "", nil, err -+ } -+ -+ return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil -+ } -+ -+ return "", nil, nil, "", nil, io.EOF -+} -+ -+// ParseAuthorizedKey parses a public key from an authorized_keys -+// file used in OpenSSH according to the sshd(8) manual page. -+func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { -+ for len(in) > 0 { -+ end := bytes.IndexByte(in, '\n') -+ if end != -1 { -+ rest = in[end+1:] -+ in = in[:end] -+ } else { -+ rest = nil -+ } -+ -+ end = bytes.IndexByte(in, '\r') -+ if end != -1 { -+ in = in[:end] -+ } -+ -+ in = bytes.TrimSpace(in) -+ if len(in) == 0 || in[0] == '#' { -+ in = rest -+ continue -+ } -+ -+ i := bytes.IndexAny(in, " \t") -+ if i == -1 { -+ in = rest -+ continue -+ } -+ -+ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { -+ return out, comment, options, rest, nil -+ } -+ -+ // No key type recognised. Maybe there's an options field at -+ // the beginning. -+ var b byte -+ inQuote := false -+ var candidateOptions []string -+ optionStart := 0 -+ for i, b = range in { -+ isEnd := !inQuote && (b == ' ' || b == '\t') -+ if (b == ',' && !inQuote) || isEnd { -+ if i-optionStart > 0 { -+ candidateOptions = append(candidateOptions, string(in[optionStart:i])) -+ } -+ optionStart = i + 1 -+ } -+ if isEnd { -+ break -+ } -+ if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { -+ inQuote = !inQuote -+ } -+ } -+ for i < len(in) && (in[i] == ' ' || in[i] == '\t') { -+ i++ -+ } -+ if i == len(in) { -+ // Invalid line: unmatched quote -+ in = rest -+ continue -+ } -+ -+ in = in[i:] -+ i = bytes.IndexAny(in, " \t") -+ if i == -1 { -+ in = rest -+ continue -+ } -+ -+ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { -+ options = candidateOptions -+ return out, comment, options, rest, nil -+ } -+ -+ in = rest -+ continue -+ } -+ -+ return nil, "", nil, nil, errors.New("ssh: no key found") -+} -+ -+// ParsePublicKey parses an SSH public key formatted for use in -+// the SSH wire protocol according to RFC 4253, section 6.6. -+func ParsePublicKey(in []byte) (out PublicKey, err error) { -+ algo, in, ok := parseString(in) -+ if !ok { -+ return nil, errShortRead -+ } -+ var rest []byte -+ out, rest, err = parsePubKey(in, string(algo)) -+ if len(rest) > 0 { -+ return nil, errors.New("ssh: trailing junk in public key") -+ } -+ -+ return out, err -+} -+ -+// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH -+// authorized_keys file. The return value ends with newline. -+func MarshalAuthorizedKey(key PublicKey) []byte { -+ b := &bytes.Buffer{} -+ b.WriteString(key.Type()) -+ b.WriteByte(' ') -+ e := base64.NewEncoder(base64.StdEncoding, b) -+ e.Write(key.Marshal()) -+ e.Close() -+ b.WriteByte('\n') -+ return b.Bytes() -+} -+ -+// PublicKey represents a public key using an unspecified algorithm. -+// -+// Some PublicKeys provided by this package also implement CryptoPublicKey. -+type PublicKey interface { -+ // Type returns the key format name, e.g. "ssh-rsa". -+ Type() string -+ -+ // Marshal returns the serialized key data in SSH wire format, with the name -+ // prefix. To unmarshal the returned data, use the ParsePublicKey function. -+ Marshal() []byte -+ -+ // Verify that sig is a signature on the given data using this key. This -+ // method will hash the data appropriately first. sig.Format is allowed to -+ // be any signature algorithm compatible with the key type, the caller -+ // should check if it has more stringent requirements. -+ Verify(data []byte, sig *Signature) error -+} -+ -+// CryptoPublicKey, if implemented by a PublicKey, -+// returns the underlying crypto.PublicKey form of the key. -+type CryptoPublicKey interface { -+ CryptoPublicKey() crypto.PublicKey -+} -+ -+// A Signer can create signatures that verify against a public key. -+// -+// Some Signers provided by this package also implement AlgorithmSigner. -+type Signer interface { -+ // PublicKey returns the associated PublicKey. -+ PublicKey() PublicKey -+ -+ // Sign returns a signature for the given data. This method will hash the -+ // data appropriately first. The signature algorithm is expected to match -+ // the key format returned by the PublicKey.Type method (and not to be any -+ // alternative algorithm supported by the key format). -+ Sign(rand io.Reader, data []byte) (*Signature, error) -+} -+ -+// An AlgorithmSigner is a Signer that also supports specifying an algorithm to -+// use for signing. -+// -+// An AlgorithmSigner can't advertise the algorithms it supports, so it should -+// be prepared to be invoked with every algorithm supported by the public key -+// format. -+type AlgorithmSigner interface { -+ Signer -+ -+ // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired -+ // signing algorithm. Callers may pass an empty string for the algorithm in -+ // which case the AlgorithmSigner will use a default algorithm. This default -+ // doesn't currently control any behavior in this package. -+ SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) -+} -+ -+type rsaPublicKey rsa.PublicKey -+ -+func (r *rsaPublicKey) Type() string { -+ return "ssh-rsa" -+} -+ -+// parseRSA parses an RSA key according to RFC 4253, section 6.6. -+func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { -+ var w struct { -+ E *big.Int -+ N *big.Int -+ Rest []byte `ssh:"rest"` -+ } -+ if err := Unmarshal(in, &w); err != nil { -+ return nil, nil, err -+ } -+ -+ if w.E.BitLen() > 24 { -+ return nil, nil, errors.New("ssh: exponent too large") -+ } -+ e := w.E.Int64() -+ if e < 3 || e&1 == 0 { -+ return nil, nil, errors.New("ssh: incorrect exponent") -+ } -+ -+ var key rsa.PublicKey -+ key.E = int(e) -+ key.N = w.N -+ return (*rsaPublicKey)(&key), w.Rest, nil -+} -+ -+func (r *rsaPublicKey) Marshal() []byte { -+ e := new(big.Int).SetInt64(int64(r.E)) -+ // RSA publickey struct layout should match the struct used by -+ // parseRSACert in the x/crypto/ssh/agent package. -+ wirekey := struct { -+ Name string -+ E *big.Int -+ N *big.Int -+ }{ -+ KeyAlgoRSA, -+ e, -+ r.N, -+ } -+ return Marshal(&wirekey) -+} -+ -+func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { -+ supportedAlgos := algorithmsForKeyFormat(r.Type()) -+ if !contains(supportedAlgos, sig.Format) { -+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) -+ } -+ hash := hashFuncs[sig.Format] -+ h := hash.New() -+ h.Write(data) -+ digest := h.Sum(nil) -+ return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, sig.Blob) -+} -+ -+func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey { -+ return (*rsa.PublicKey)(r) -+} -+ -+type dsaPublicKey dsa.PublicKey -+ -+func (k *dsaPublicKey) Type() string { -+ return "ssh-dss" -+} -+ -+func checkDSAParams(param *dsa.Parameters) error { -+ // SSH specifies FIPS 186-2, which only provided a single size -+ // (1024 bits) DSA key. FIPS 186-3 allows for larger key -+ // sizes, which would confuse SSH. -+ if l := param.P.BitLen(); l != 1024 { -+ return fmt.Errorf("ssh: unsupported DSA key size %d", l) -+ } -+ -+ return nil -+} -+ -+// parseDSA parses an DSA key according to RFC 4253, section 6.6. -+func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { -+ var w struct { -+ P, Q, G, Y *big.Int -+ Rest []byte `ssh:"rest"` -+ } -+ if err := Unmarshal(in, &w); err != nil { -+ return nil, nil, err -+ } -+ -+ param := dsa.Parameters{ -+ P: w.P, -+ Q: w.Q, -+ G: w.G, -+ } -+ if err := checkDSAParams(¶m); err != nil { -+ return nil, nil, err -+ } -+ -+ key := &dsaPublicKey{ -+ Parameters: param, -+ Y: w.Y, -+ } -+ return key, w.Rest, nil -+} -+ -+func (k *dsaPublicKey) Marshal() []byte { -+ // DSA publickey struct layout should match the struct used by -+ // parseDSACert in the x/crypto/ssh/agent package. -+ w := struct { -+ Name string -+ P, Q, G, Y *big.Int -+ }{ -+ k.Type(), -+ k.P, -+ k.Q, -+ k.G, -+ k.Y, -+ } -+ -+ return Marshal(&w) -+} -+ -+func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { -+ if sig.Format != k.Type() { -+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) -+ } -+ h := hashFuncs[sig.Format].New() -+ h.Write(data) -+ digest := h.Sum(nil) -+ -+ // Per RFC 4253, section 6.6, -+ // The value for 'dss_signature_blob' is encoded as a string containing -+ // r, followed by s (which are 160-bit integers, without lengths or -+ // padding, unsigned, and in network byte order). -+ // For DSS purposes, sig.Blob should be exactly 40 bytes in length. -+ if len(sig.Blob) != 40 { -+ return errors.New("ssh: DSA signature parse error") -+ } -+ r := new(big.Int).SetBytes(sig.Blob[:20]) -+ s := new(big.Int).SetBytes(sig.Blob[20:]) -+ if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { -+ return nil -+ } -+ return errors.New("ssh: signature did not verify") -+} -+ -+func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey { -+ return (*dsa.PublicKey)(k) -+} -+ -+type dsaPrivateKey struct { -+ *dsa.PrivateKey -+} -+ -+func (k *dsaPrivateKey) PublicKey() PublicKey { -+ return (*dsaPublicKey)(&k.PrivateKey.PublicKey) -+} -+ -+func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { -+ return k.SignWithAlgorithm(rand, data, k.PublicKey().Type()) -+} -+ -+func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -+ if algorithm != "" && algorithm != k.PublicKey().Type() { -+ return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) -+ } -+ -+ h := hashFuncs[k.PublicKey().Type()].New() -+ h.Write(data) -+ digest := h.Sum(nil) -+ r, s, err := dsa.Sign(rand, k.PrivateKey, digest) -+ if err != nil { -+ return nil, err -+ } -+ -+ sig := make([]byte, 40) -+ rb := r.Bytes() -+ sb := s.Bytes() -+ -+ copy(sig[20-len(rb):20], rb) -+ copy(sig[40-len(sb):], sb) -+ -+ return &Signature{ -+ Format: k.PublicKey().Type(), -+ Blob: sig, -+ }, nil -+} -+ -+type ecdsaPublicKey ecdsa.PublicKey -+ -+func (k *ecdsaPublicKey) Type() string { -+ return "ecdsa-sha2-" + k.nistID() -+} -+ -+func (k *ecdsaPublicKey) nistID() string { -+ switch k.Params().BitSize { -+ case 256: -+ return "nistp256" -+ case 384: -+ return "nistp384" -+ case 521: -+ return "nistp521" -+ } -+ panic("ssh: unsupported ecdsa key size") -+} -+ -+type ed25519PublicKey ed25519.PublicKey -+ -+func (k ed25519PublicKey) Type() string { -+ return KeyAlgoED25519 -+} -+ -+func parseED25519(in []byte) (out PublicKey, rest []byte, err error) { -+ var w struct { -+ KeyBytes []byte -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := Unmarshal(in, &w); err != nil { -+ return nil, nil, err -+ } -+ -+ if l := len(w.KeyBytes); l != ed25519.PublicKeySize { -+ return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) -+ } -+ -+ return ed25519PublicKey(w.KeyBytes), w.Rest, nil -+} -+ -+func (k ed25519PublicKey) Marshal() []byte { -+ w := struct { -+ Name string -+ KeyBytes []byte -+ }{ -+ KeyAlgoED25519, -+ []byte(k), -+ } -+ return Marshal(&w) -+} -+ -+func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error { -+ if sig.Format != k.Type() { -+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) -+ } -+ if l := len(k); l != ed25519.PublicKeySize { -+ return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) -+ } -+ -+ if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok { -+ return errors.New("ssh: signature did not verify") -+ } -+ -+ return nil -+} -+ -+func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey { -+ return ed25519.PublicKey(k) -+} -+ -+func supportedEllipticCurve(curve elliptic.Curve) bool { -+ return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() -+} -+ -+// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. -+func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { -+ var w struct { -+ Curve string -+ KeyBytes []byte -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := Unmarshal(in, &w); err != nil { -+ return nil, nil, err -+ } -+ -+ key := new(ecdsa.PublicKey) -+ -+ switch w.Curve { -+ case "nistp256": -+ key.Curve = elliptic.P256() -+ case "nistp384": -+ key.Curve = elliptic.P384() -+ case "nistp521": -+ key.Curve = elliptic.P521() -+ default: -+ return nil, nil, errors.New("ssh: unsupported curve") -+ } -+ -+ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) -+ if key.X == nil || key.Y == nil { -+ return nil, nil, errors.New("ssh: invalid curve point") -+ } -+ return (*ecdsaPublicKey)(key), w.Rest, nil -+} -+ -+func (k *ecdsaPublicKey) Marshal() []byte { -+ // See RFC 5656, section 3.1. -+ keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) -+ // ECDSA publickey struct layout should match the struct used by -+ // parseECDSACert in the x/crypto/ssh/agent package. -+ w := struct { -+ Name string -+ ID string -+ Key []byte -+ }{ -+ k.Type(), -+ k.nistID(), -+ keyBytes, -+ } -+ -+ return Marshal(&w) -+} -+ -+func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { -+ if sig.Format != k.Type() { -+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) -+ } -+ -+ h := hashFuncs[sig.Format].New() -+ h.Write(data) -+ digest := h.Sum(nil) -+ -+ // Per RFC 5656, section 3.1.2, -+ // The ecdsa_signature_blob value has the following specific encoding: -+ // mpint r -+ // mpint s -+ var ecSig struct { -+ R *big.Int -+ S *big.Int -+ } -+ -+ if err := Unmarshal(sig.Blob, &ecSig); err != nil { -+ return err -+ } -+ -+ if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) { -+ return nil -+ } -+ return errors.New("ssh: signature did not verify") -+} -+ -+func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey { -+ return (*ecdsa.PublicKey)(k) -+} -+ -+// skFields holds the additional fields present in U2F/FIDO2 signatures. -+// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details. -+type skFields struct { -+ // Flags contains U2F/FIDO2 flags such as 'user present' -+ Flags byte -+ // Counter is a monotonic signature counter which can be -+ // used to detect concurrent use of a private key, should -+ // it be extracted from hardware. -+ Counter uint32 -+} -+ -+type skECDSAPublicKey struct { -+ // application is a URL-like string, typically "ssh:" for SSH. -+ // see openssh/PROTOCOL.u2f for details. -+ application string -+ ecdsa.PublicKey -+} -+ -+func (k *skECDSAPublicKey) Type() string { -+ return KeyAlgoSKECDSA256 -+} -+ -+func (k *skECDSAPublicKey) nistID() string { -+ return "nistp256" -+} -+ -+func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) { -+ var w struct { -+ Curve string -+ KeyBytes []byte -+ Application string -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := Unmarshal(in, &w); err != nil { -+ return nil, nil, err -+ } -+ -+ key := new(skECDSAPublicKey) -+ key.application = w.Application -+ -+ if w.Curve != "nistp256" { -+ return nil, nil, errors.New("ssh: unsupported curve") -+ } -+ key.Curve = elliptic.P256() -+ -+ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) -+ if key.X == nil || key.Y == nil { -+ return nil, nil, errors.New("ssh: invalid curve point") -+ } -+ -+ return key, w.Rest, nil -+} -+ -+func (k *skECDSAPublicKey) Marshal() []byte { -+ // See RFC 5656, section 3.1. -+ keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) -+ w := struct { -+ Name string -+ ID string -+ Key []byte -+ Application string -+ }{ -+ k.Type(), -+ k.nistID(), -+ keyBytes, -+ k.application, -+ } -+ -+ return Marshal(&w) -+} -+ -+func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error { -+ if sig.Format != k.Type() { -+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) -+ } -+ -+ h := hashFuncs[sig.Format].New() -+ h.Write([]byte(k.application)) -+ appDigest := h.Sum(nil) -+ -+ h.Reset() -+ h.Write(data) -+ dataDigest := h.Sum(nil) -+ -+ var ecSig struct { -+ R *big.Int -+ S *big.Int -+ } -+ if err := Unmarshal(sig.Blob, &ecSig); err != nil { -+ return err -+ } -+ -+ var skf skFields -+ if err := Unmarshal(sig.Rest, &skf); err != nil { -+ return err -+ } -+ -+ blob := struct { -+ ApplicationDigest []byte `ssh:"rest"` -+ Flags byte -+ Counter uint32 -+ MessageDigest []byte `ssh:"rest"` -+ }{ -+ appDigest, -+ skf.Flags, -+ skf.Counter, -+ dataDigest, -+ } -+ -+ original := Marshal(blob) -+ -+ h.Reset() -+ h.Write(original) -+ digest := h.Sum(nil) -+ -+ if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) { -+ return nil -+ } -+ return errors.New("ssh: signature did not verify") -+} -+ -+type skEd25519PublicKey struct { -+ // application is a URL-like string, typically "ssh:" for SSH. -+ // see openssh/PROTOCOL.u2f for details. -+ application string -+ ed25519.PublicKey -+} -+ -+func (k *skEd25519PublicKey) Type() string { -+ return KeyAlgoSKED25519 -+} -+ -+func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) { -+ var w struct { -+ KeyBytes []byte -+ Application string -+ Rest []byte `ssh:"rest"` -+ } -+ -+ if err := Unmarshal(in, &w); err != nil { -+ return nil, nil, err -+ } -+ -+ if l := len(w.KeyBytes); l != ed25519.PublicKeySize { -+ return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l) -+ } -+ -+ key := new(skEd25519PublicKey) -+ key.application = w.Application -+ key.PublicKey = ed25519.PublicKey(w.KeyBytes) -+ -+ return key, w.Rest, nil -+} -+ -+func (k *skEd25519PublicKey) Marshal() []byte { -+ w := struct { -+ Name string -+ KeyBytes []byte -+ Application string -+ }{ -+ KeyAlgoSKED25519, -+ []byte(k.PublicKey), -+ k.application, -+ } -+ return Marshal(&w) -+} -+ -+func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error { -+ if sig.Format != k.Type() { -+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) -+ } -+ if l := len(k.PublicKey); l != ed25519.PublicKeySize { -+ return fmt.Errorf("invalid size %d for Ed25519 public key", l) -+ } -+ -+ h := hashFuncs[sig.Format].New() -+ h.Write([]byte(k.application)) -+ appDigest := h.Sum(nil) -+ -+ h.Reset() -+ h.Write(data) -+ dataDigest := h.Sum(nil) -+ -+ var edSig struct { -+ Signature []byte `ssh:"rest"` -+ } -+ -+ if err := Unmarshal(sig.Blob, &edSig); err != nil { -+ return err -+ } -+ -+ var skf skFields -+ if err := Unmarshal(sig.Rest, &skf); err != nil { -+ return err -+ } -+ -+ blob := struct { -+ ApplicationDigest []byte `ssh:"rest"` -+ Flags byte -+ Counter uint32 -+ MessageDigest []byte `ssh:"rest"` -+ }{ -+ appDigest, -+ skf.Flags, -+ skf.Counter, -+ dataDigest, -+ } -+ -+ original := Marshal(blob) -+ -+ if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok { -+ return errors.New("ssh: signature did not verify") -+ } -+ -+ return nil -+} -+ -+// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, -+// *ecdsa.PrivateKey or any other crypto.Signer and returns a -+// corresponding Signer instance. ECDSA keys must use P-256, P-384 or -+// P-521. DSA keys must use parameter size L1024N160. -+func NewSignerFromKey(key interface{}) (Signer, error) { -+ switch key := key.(type) { -+ case crypto.Signer: -+ return NewSignerFromSigner(key) -+ case *dsa.PrivateKey: -+ return newDSAPrivateKey(key) -+ default: -+ return nil, fmt.Errorf("ssh: unsupported key type %T", key) -+ } -+} -+ -+func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) { -+ if err := checkDSAParams(&key.PublicKey.Parameters); err != nil { -+ return nil, err -+ } -+ -+ return &dsaPrivateKey{key}, nil -+} -+ -+type wrappedSigner struct { -+ signer crypto.Signer -+ pubKey PublicKey -+} -+ -+// NewSignerFromSigner takes any crypto.Signer implementation and -+// returns a corresponding Signer interface. This can be used, for -+// example, with keys kept in hardware modules. -+func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { -+ pubKey, err := NewPublicKey(signer.Public()) -+ if err != nil { -+ return nil, err -+ } -+ -+ return &wrappedSigner{signer, pubKey}, nil -+} -+ -+func (s *wrappedSigner) PublicKey() PublicKey { -+ return s.pubKey -+} -+ -+func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { -+ return s.SignWithAlgorithm(rand, data, s.pubKey.Type()) -+} -+ -+func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { -+ if algorithm == "" { -+ algorithm = s.pubKey.Type() -+ } -+ -+ supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type()) -+ if !contains(supportedAlgos, algorithm) { -+ return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type()) -+ } -+ -+ hashFunc := hashFuncs[algorithm] -+ var digest []byte -+ if hashFunc != 0 { -+ h := hashFunc.New() -+ h.Write(data) -+ digest = h.Sum(nil) -+ } else { -+ digest = data -+ } -+ -+ signature, err := s.signer.Sign(rand, digest, hashFunc) -+ if err != nil { -+ return nil, err -+ } -+ -+ // crypto.Signer.Sign is expected to return an ASN.1-encoded signature -+ // for ECDSA and DSA, but that's not the encoding expected by SSH, so -+ // re-encode. -+ switch s.pubKey.(type) { -+ case *ecdsaPublicKey, *dsaPublicKey: -+ type asn1Signature struct { -+ R, S *big.Int -+ } -+ asn1Sig := new(asn1Signature) -+ _, err := asn1.Unmarshal(signature, asn1Sig) -+ if err != nil { -+ return nil, err -+ } -+ -+ switch s.pubKey.(type) { -+ case *ecdsaPublicKey: -+ signature = Marshal(asn1Sig) -+ -+ case *dsaPublicKey: -+ signature = make([]byte, 40) -+ r := asn1Sig.R.Bytes() -+ s := asn1Sig.S.Bytes() -+ copy(signature[20-len(r):20], r) -+ copy(signature[40-len(s):40], s) -+ } -+ } -+ -+ return &Signature{ -+ Format: algorithm, -+ Blob: signature, -+ }, nil -+} -+ -+// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, -+// or ed25519.PublicKey returns a corresponding PublicKey instance. -+// ECDSA keys must use P-256, P-384 or P-521. -+func NewPublicKey(key interface{}) (PublicKey, error) { -+ switch key := key.(type) { -+ case *rsa.PublicKey: -+ return (*rsaPublicKey)(key), nil -+ case *ecdsa.PublicKey: -+ if !supportedEllipticCurve(key.Curve) { -+ return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported") -+ } -+ return (*ecdsaPublicKey)(key), nil -+ case *dsa.PublicKey: -+ return (*dsaPublicKey)(key), nil -+ case ed25519.PublicKey: -+ if l := len(key); l != ed25519.PublicKeySize { -+ return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l) -+ } -+ return ed25519PublicKey(key), nil -+ default: -+ return nil, fmt.Errorf("ssh: unsupported key type %T", key) -+ } -+} -+ -+// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports -+// the same keys as ParseRawPrivateKey. If the private key is encrypted, it -+// will return a PassphraseMissingError. -+func ParsePrivateKey(pemBytes []byte) (Signer, error) { -+ key, err := ParseRawPrivateKey(pemBytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ return NewSignerFromKey(key) -+} -+ -+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private -+// key and passphrase. It supports the same keys as -+// ParseRawPrivateKeyWithPassphrase. -+func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) { -+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase) -+ if err != nil { -+ return nil, err -+ } -+ -+ return NewSignerFromKey(key) -+} -+ -+// encryptedBlock tells whether a private key is -+// encrypted by examining its Proc-Type header -+// for a mention of ENCRYPTED -+// according to RFC 1421 Section 4.6.1.1. -+func encryptedBlock(block *pem.Block) bool { -+ return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") -+} -+ -+// A PassphraseMissingError indicates that parsing this private key requires a -+// passphrase. Use ParsePrivateKeyWithPassphrase. -+type PassphraseMissingError struct { -+ // PublicKey will be set if the private key format includes an unencrypted -+ // public key along with the encrypted private key. -+ PublicKey PublicKey -+} -+ -+func (*PassphraseMissingError) Error() string { -+ return "ssh: this private key is passphrase protected" -+} -+ -+// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports -+// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH -+// formats. If the private key is encrypted, it will return a PassphraseMissingError. -+func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { -+ block, _ := pem.Decode(pemBytes) -+ if block == nil { -+ return nil, errors.New("ssh: no key found") -+ } -+ -+ if encryptedBlock(block) { -+ return nil, &PassphraseMissingError{} -+ } -+ -+ switch block.Type { -+ case "RSA PRIVATE KEY": -+ return x509.ParsePKCS1PrivateKey(block.Bytes) -+ // RFC5208 - https://tools.ietf.org/html/rfc5208 -+ case "PRIVATE KEY": -+ return x509.ParsePKCS8PrivateKey(block.Bytes) -+ case "EC PRIVATE KEY": -+ return x509.ParseECPrivateKey(block.Bytes) -+ case "DSA PRIVATE KEY": -+ return ParseDSAPrivateKey(block.Bytes) -+ case "OPENSSH PRIVATE KEY": -+ return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey) -+ default: -+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) -+ } -+} -+ -+// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with -+// passphrase from a PEM encoded private key. If the passphrase is wrong, it -+// will return x509.IncorrectPasswordError. -+func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) { -+ block, _ := pem.Decode(pemBytes) -+ if block == nil { -+ return nil, errors.New("ssh: no key found") -+ } -+ -+ if block.Type == "OPENSSH PRIVATE KEY" { -+ return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase)) -+ } -+ -+ if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) { -+ return nil, errors.New("ssh: not an encrypted key") -+ } -+ -+ buf, err := x509.DecryptPEMBlock(block, passphrase) -+ if err != nil { -+ if err == x509.IncorrectPasswordError { -+ return nil, err -+ } -+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err) -+ } -+ -+ switch block.Type { -+ case "RSA PRIVATE KEY": -+ return x509.ParsePKCS1PrivateKey(buf) -+ case "EC PRIVATE KEY": -+ return x509.ParseECPrivateKey(buf) -+ case "DSA PRIVATE KEY": -+ return ParseDSAPrivateKey(buf) -+ default: -+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) -+ } -+} -+ -+// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as -+// specified by the OpenSSL DSA man page. -+func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { -+ var k struct { -+ Version int -+ P *big.Int -+ Q *big.Int -+ G *big.Int -+ Pub *big.Int -+ Priv *big.Int -+ } -+ rest, err := asn1.Unmarshal(der, &k) -+ if err != nil { -+ return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) -+ } -+ if len(rest) > 0 { -+ return nil, errors.New("ssh: garbage after DSA key") -+ } -+ -+ return &dsa.PrivateKey{ -+ PublicKey: dsa.PublicKey{ -+ Parameters: dsa.Parameters{ -+ P: k.P, -+ Q: k.Q, -+ G: k.G, -+ }, -+ Y: k.Pub, -+ }, -+ X: k.Priv, -+ }, nil -+} -+ -+func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { -+ if kdfName != "none" || cipherName != "none" { -+ return nil, &PassphraseMissingError{} -+ } -+ if kdfOpts != "" { -+ return nil, errors.New("ssh: invalid openssh private key") -+ } -+ return privKeyBlock, nil -+} -+ -+func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc { -+ return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { -+ if kdfName == "none" || cipherName == "none" { -+ return nil, errors.New("ssh: key is not password protected") -+ } -+ if kdfName != "bcrypt" { -+ return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt") -+ } -+ -+ var opts struct { -+ Salt string -+ Rounds uint32 -+ } -+ if err := Unmarshal([]byte(kdfOpts), &opts); err != nil { -+ return nil, err -+ } -+ -+ k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16) -+ if err != nil { -+ return nil, err -+ } -+ key, iv := k[:32], k[32:] -+ -+ c, err := aes.NewCipher(key) -+ if err != nil { -+ return nil, err -+ } -+ switch cipherName { -+ case "aes256-ctr": -+ ctr := cipher.NewCTR(c, iv) -+ ctr.XORKeyStream(privKeyBlock, privKeyBlock) -+ case "aes256-cbc": -+ if len(privKeyBlock)%c.BlockSize() != 0 { -+ return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size") -+ } -+ cbc := cipher.NewCBCDecrypter(c, iv) -+ cbc.CryptBlocks(privKeyBlock, privKeyBlock) -+ default: -+ return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc") -+ } -+ -+ return privKeyBlock, nil -+ } -+} -+ -+type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error) -+ -+// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt -+// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used -+// as the decrypt function to parse an unencrypted private key. See -+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key. -+func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) { -+ const magic = "openssh-key-v1\x00" -+ if len(key) < len(magic) || string(key[:len(magic)]) != magic { -+ return nil, errors.New("ssh: invalid openssh private key format") -+ } -+ remaining := key[len(magic):] -+ -+ var w struct { -+ CipherName string -+ KdfName string -+ KdfOpts string -+ NumKeys uint32 -+ PubKey []byte -+ PrivKeyBlock []byte -+ } -+ -+ if err := Unmarshal(remaining, &w); err != nil { -+ return nil, err -+ } -+ if w.NumKeys != 1 { -+ // We only support single key files, and so does OpenSSH. -+ // https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171 -+ return nil, errors.New("ssh: multi-key files are not supported") -+ } -+ -+ privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock) -+ if err != nil { -+ if err, ok := err.(*PassphraseMissingError); ok { -+ pub, errPub := ParsePublicKey(w.PubKey) -+ if errPub != nil { -+ return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub) -+ } -+ err.PublicKey = pub -+ } -+ return nil, err -+ } -+ -+ pk1 := struct { -+ Check1 uint32 -+ Check2 uint32 -+ Keytype string -+ Rest []byte `ssh:"rest"` -+ }{} -+ -+ if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 { -+ if w.CipherName != "none" { -+ return nil, x509.IncorrectPasswordError -+ } -+ return nil, errors.New("ssh: malformed OpenSSH key") -+ } -+ -+ switch pk1.Keytype { -+ case KeyAlgoRSA: -+ // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 -+ key := struct { -+ N *big.Int -+ E *big.Int -+ D *big.Int -+ Iqmp *big.Int -+ P *big.Int -+ Q *big.Int -+ Comment string -+ Pad []byte `ssh:"rest"` -+ }{} -+ -+ if err := Unmarshal(pk1.Rest, &key); err != nil { -+ return nil, err -+ } -+ -+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil { -+ return nil, err -+ } -+ -+ pk := &rsa.PrivateKey{ -+ PublicKey: rsa.PublicKey{ -+ N: key.N, -+ E: int(key.E.Int64()), -+ }, -+ D: key.D, -+ Primes: []*big.Int{key.P, key.Q}, -+ } -+ -+ if err := pk.Validate(); err != nil { -+ return nil, err -+ } -+ -+ pk.Precompute() -+ -+ return pk, nil -+ case KeyAlgoED25519: -+ key := struct { -+ Pub []byte -+ Priv []byte -+ Comment string -+ Pad []byte `ssh:"rest"` -+ }{} -+ -+ if err := Unmarshal(pk1.Rest, &key); err != nil { -+ return nil, err -+ } -+ -+ if len(key.Priv) != ed25519.PrivateKeySize { -+ return nil, errors.New("ssh: private key unexpected length") -+ } -+ -+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil { -+ return nil, err -+ } -+ -+ pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) -+ copy(pk, key.Priv) -+ return &pk, nil -+ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: -+ key := struct { -+ Curve string -+ Pub []byte -+ D *big.Int -+ Comment string -+ Pad []byte `ssh:"rest"` -+ }{} -+ -+ if err := Unmarshal(pk1.Rest, &key); err != nil { -+ return nil, err -+ } -+ -+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil { -+ return nil, err -+ } -+ -+ var curve elliptic.Curve -+ switch key.Curve { -+ case "nistp256": -+ curve = elliptic.P256() -+ case "nistp384": -+ curve = elliptic.P384() -+ case "nistp521": -+ curve = elliptic.P521() -+ default: -+ return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve) -+ } -+ -+ X, Y := elliptic.Unmarshal(curve, key.Pub) -+ if X == nil || Y == nil { -+ return nil, errors.New("ssh: failed to unmarshal public key") -+ } -+ -+ if key.D.Cmp(curve.Params().N) >= 0 { -+ return nil, errors.New("ssh: scalar is out of range") -+ } -+ -+ x, y := curve.ScalarBaseMult(key.D.Bytes()) -+ if x.Cmp(X) != 0 || y.Cmp(Y) != 0 { -+ return nil, errors.New("ssh: public key does not match private key") -+ } -+ -+ return &ecdsa.PrivateKey{ -+ PublicKey: ecdsa.PublicKey{ -+ Curve: curve, -+ X: X, -+ Y: Y, -+ }, -+ D: key.D, -+ }, nil -+ default: -+ return nil, errors.New("ssh: unhandled key type") -+ } -+} -+ -+func checkOpenSSHKeyPadding(pad []byte) error { -+ for i, b := range pad { -+ if int(b) != i+1 { -+ return errors.New("ssh: padding not as expected") -+ } -+ } -+ return nil -+} -+ -+// FingerprintLegacyMD5 returns the user presentation of the key's -+// fingerprint as described by RFC 4716 section 4. -+func FingerprintLegacyMD5(pubKey PublicKey) string { -+ md5sum := md5.Sum(pubKey.Marshal()) -+ hexarray := make([]string, len(md5sum)) -+ for i, c := range md5sum { -+ hexarray[i] = hex.EncodeToString([]byte{c}) -+ } -+ return strings.Join(hexarray, ":") -+} -+ -+// FingerprintSHA256 returns the user presentation of the key's -+// fingerprint as unpadded base64 encoded sha256 hash. -+// This format was introduced from OpenSSH 6.8. -+// https://www.openssh.com/txt/release-6.8 -+// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding) -+func FingerprintSHA256(pubKey PublicKey) string { -+ sha256sum := sha256.Sum256(pubKey.Marshal()) -+ hash := base64.RawStdEncoding.EncodeToString(sha256sum[:]) -+ return "SHA256:" + hash -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/keys_test.go b/ms_mod/golang.org/x/crypto/ssh/keys_test.go -new file mode 100644 -index 00000000000000..334ef7453266db ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/keys_test.go -@@ -0,0 +1,618 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/x509" -+ "encoding/base64" -+ "encoding/hex" -+ "encoding/pem" -+ "fmt" -+ "io" -+ "reflect" -+ "strings" -+ "testing" -+ -+ "golang.org/x/crypto/ed25519" -+ "golang.org/x/crypto/ssh/testdata" -+) -+ -+func rawKey(pub PublicKey) interface{} { -+ switch k := pub.(type) { -+ case *rsaPublicKey: -+ return (*rsa.PublicKey)(k) -+ case *dsaPublicKey: -+ return (*dsa.PublicKey)(k) -+ case *ecdsaPublicKey: -+ return (*ecdsa.PublicKey)(k) -+ case ed25519PublicKey: -+ return (ed25519.PublicKey)(k) -+ case *Certificate: -+ return k -+ } -+ panic("unknown key type") -+} -+ -+func TestKeyMarshalParse(t *testing.T) { -+ for _, priv := range testSigners { -+ pub := priv.PublicKey() -+ roundtrip, err := ParsePublicKey(pub.Marshal()) -+ if err != nil { -+ t.Errorf("ParsePublicKey(%T): %v", pub, err) -+ } -+ -+ k1 := rawKey(pub) -+ k2 := rawKey(roundtrip) -+ -+ if !reflect.DeepEqual(k1, k2) { -+ t.Errorf("got %#v in roundtrip, want %#v", k2, k1) -+ } -+ } -+} -+ -+func TestUnsupportedCurves(t *testing.T) { -+ raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) -+ if err != nil { -+ t.Fatalf("GenerateKey: %v", err) -+ } -+ -+ if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") { -+ t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err) -+ } -+ -+ if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") { -+ t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err) -+ } -+} -+ -+func TestNewPublicKey(t *testing.T) { -+ for _, k := range testSigners { -+ raw := rawKey(k.PublicKey()) -+ // Skip certificates, as NewPublicKey does not support them. -+ if _, ok := raw.(*Certificate); ok { -+ continue -+ } -+ pub, err := NewPublicKey(raw) -+ if err != nil { -+ t.Errorf("NewPublicKey(%#v): %v", raw, err) -+ } -+ if !reflect.DeepEqual(k.PublicKey(), pub) { -+ t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey()) -+ } -+ } -+} -+ -+func TestKeySignVerify(t *testing.T) { -+ for _, priv := range testSigners { -+ pub := priv.PublicKey() -+ -+ data := []byte("sign me") -+ sig, err := priv.Sign(rand.Reader, data) -+ if err != nil { -+ t.Fatalf("Sign(%T): %v", priv, err) -+ } -+ -+ if err := pub.Verify(data, sig); err != nil { -+ t.Errorf("publicKey.Verify(%T): %v", priv, err) -+ } -+ sig.Blob[5]++ -+ if err := pub.Verify(data, sig); err == nil { -+ t.Errorf("publicKey.Verify on broken sig did not fail") -+ } -+ } -+} -+ -+func TestKeySignWithAlgorithmVerify(t *testing.T) { -+ for _, priv := range testSigners { -+ if algorithmSigner, ok := priv.(AlgorithmSigner); !ok { -+ t.Errorf("Signers constructed by ssh package should always implement the AlgorithmSigner interface: %T", priv) -+ } else { -+ pub := priv.PublicKey() -+ data := []byte("sign me") -+ -+ signWithAlgTestCase := func(algorithm string, expectedAlg string) { -+ sig, err := algorithmSigner.SignWithAlgorithm(rand.Reader, data, algorithm) -+ if err != nil { -+ t.Fatalf("Sign(%T): %v", priv, err) -+ } -+ if sig.Format != expectedAlg { -+ t.Errorf("signature format did not match requested signature algorithm: %s != %s", sig.Format, expectedAlg) -+ } -+ -+ if err := pub.Verify(data, sig); err != nil { -+ t.Errorf("publicKey.Verify(%T): %v", priv, err) -+ } -+ sig.Blob[5]++ -+ if err := pub.Verify(data, sig); err == nil { -+ t.Errorf("publicKey.Verify on broken sig did not fail") -+ } -+ } -+ -+ // Using the empty string as the algorithm name should result in the same signature format as the algorithm-free Sign method. -+ defaultSig, err := priv.Sign(rand.Reader, data) -+ if err != nil { -+ t.Fatalf("Sign(%T): %v", priv, err) -+ } -+ signWithAlgTestCase("", defaultSig.Format) -+ -+ // RSA keys are the only ones which currently support more than one signing algorithm -+ if pub.Type() == KeyAlgoRSA { -+ for _, algorithm := range []string{KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512} { -+ signWithAlgTestCase(algorithm, algorithm) -+ } -+ } -+ } -+ } -+} -+ -+func TestParseRSAPrivateKey(t *testing.T) { -+ key := testPrivateKeys["rsa"] -+ -+ rsa, ok := key.(*rsa.PrivateKey) -+ if !ok { -+ t.Fatalf("got %T, want *rsa.PrivateKey", rsa) -+ } -+ -+ if err := rsa.Validate(); err != nil { -+ t.Errorf("Validate: %v", err) -+ } -+} -+ -+func TestParseECPrivateKey(t *testing.T) { -+ key := testPrivateKeys["ecdsa"] -+ -+ ecKey, ok := key.(*ecdsa.PrivateKey) -+ if !ok { -+ t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey) -+ } -+ -+ if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) { -+ t.Fatalf("public key does not validate.") -+ } -+} -+ -+func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) { -+ data := []byte("sign me") -+ for _, tt := range testdata.PEMEncryptedKeys { -+ t.Run(tt.Name, func(t *testing.T) { -+ _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect")) -+ if err != x509.IncorrectPasswordError { -+ t.Errorf("got %v want IncorrectPasswordError", err) -+ } -+ -+ s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) -+ if err != nil { -+ t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err) -+ } -+ -+ sig, err := s.Sign(rand.Reader, data) -+ if err != nil { -+ t.Fatalf("Signer.Sign: %v", err) -+ } -+ if err := s.PublicKey().Verify(data, sig); err != nil { -+ t.Errorf("Verify failed: %v", err) -+ } -+ -+ _, err = ParsePrivateKey(tt.PEMBytes) -+ if err == nil { -+ t.Fatalf("ParsePrivateKey succeeded, expected an error") -+ } -+ -+ if err, ok := err.(*PassphraseMissingError); !ok { -+ t.Errorf("got error %q, want PassphraseMissingError", err) -+ } else if tt.IncludesPublicKey { -+ if err.PublicKey == nil { -+ t.Fatalf("expected PassphraseMissingError.PublicKey not to be nil") -+ } -+ got, want := err.PublicKey.Marshal(), s.PublicKey().Marshal() -+ if !bytes.Equal(got, want) { -+ t.Errorf("error field %q doesn't match signer public key %q", got, want) -+ } -+ } -+ }) -+ } -+} -+ -+func TestParseDSA(t *testing.T) { -+ // We actually exercise the ParsePrivateKey codepath here, as opposed to -+ // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go -+ // uses. -+ s, err := ParsePrivateKey(testdata.PEMBytes["dsa"]) -+ if err != nil { -+ t.Fatalf("ParsePrivateKey returned error: %s", err) -+ } -+ -+ data := []byte("sign me") -+ sig, err := s.Sign(rand.Reader, data) -+ if err != nil { -+ t.Fatalf("dsa.Sign: %v", err) -+ } -+ -+ if err := s.PublicKey().Verify(data, sig); err != nil { -+ t.Errorf("Verify failed: %v", err) -+ } -+} -+ -+// Tests for authorized_keys parsing. -+ -+// getTestKey returns a public key, and its base64 encoding. -+func getTestKey() (PublicKey, string) { -+ k := testPublicKeys["rsa"] -+ -+ b := &bytes.Buffer{} -+ e := base64.NewEncoder(base64.StdEncoding, b) -+ e.Write(k.Marshal()) -+ e.Close() -+ -+ return k, b.String() -+} -+ -+func TestMarshalParsePublicKey(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized) -+ -+ authKeys := MarshalAuthorizedKey(pub) -+ actualFields := strings.Fields(string(authKeys)) -+ if len(actualFields) == 0 { -+ t.Fatalf("failed authKeys: %v", authKeys) -+ } -+ -+ // drop the comment -+ expectedFields := strings.Fields(line)[0:2] -+ -+ if !reflect.DeepEqual(actualFields, expectedFields) { -+ t.Errorf("got %v, expected %v", actualFields, expectedFields) -+ } -+ -+ actPub, _, _, _, err := ParseAuthorizedKey([]byte(line)) -+ if err != nil { -+ t.Fatalf("cannot parse %v: %v", line, err) -+ } -+ if !reflect.DeepEqual(actPub, pub) { -+ t.Errorf("got %v, expected %v", actPub, pub) -+ } -+} -+ -+type testAuthResult struct { -+ pubKey PublicKey -+ options []string -+ comments string -+ rest string -+ ok bool -+} -+ -+func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []testAuthResult) { -+ rest := authKeys -+ var values []testAuthResult -+ for len(rest) > 0 { -+ var r testAuthResult -+ var err error -+ r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) -+ r.ok = (err == nil) -+ t.Log(err) -+ r.rest = string(rest) -+ values = append(values, r) -+ } -+ -+ if !reflect.DeepEqual(values, expected) { -+ t.Errorf("got %#v, expected %#v", values, expected) -+ } -+} -+ -+func TestAuthorizedKeyBasic(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ line := "ssh-rsa " + pubSerialized + " user@host" -+ testAuthorizedKeys(t, []byte(line), -+ []testAuthResult{ -+ {pub, nil, "user@host", "", true}, -+ }) -+} -+ -+func TestAuth(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ authWithOptions := []string{ -+ `# comments to ignore before any keys...`, -+ ``, -+ `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`, -+ `# comments to ignore, along with a blank line`, -+ ``, -+ `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`, -+ ``, -+ `# more comments, plus a invalid entry`, -+ `ssh-rsa data-that-will-not-parse user@host3`, -+ } -+ for _, eol := range []string{"\n", "\r\n"} { -+ authOptions := strings.Join(authWithOptions, eol) -+ rest2 := strings.Join(authWithOptions[3:], eol) -+ rest3 := strings.Join(authWithOptions[6:], eol) -+ testAuthorizedKeys(t, []byte(authOptions), []testAuthResult{ -+ {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, -+ {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, -+ {nil, nil, "", "", false}, -+ }) -+ } -+} -+ -+func TestAuthWithQuotedSpaceInEnv(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) -+ testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []testAuthResult{ -+ {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, -+ }) -+} -+ -+func TestAuthWithQuotedCommaInEnv(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) -+ testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []testAuthResult{ -+ {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, -+ }) -+} -+ -+func TestAuthWithQuotedQuoteInEnv(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) -+ authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) -+ testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []testAuthResult{ -+ {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, -+ }) -+ -+ testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []testAuthResult{ -+ {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, -+ }) -+} -+ -+func TestAuthWithInvalidSpace(t *testing.T) { -+ _, pubSerialized := getTestKey() -+ authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host -+#more to follow but still no valid keys`) -+ testAuthorizedKeys(t, []byte(authWithInvalidSpace), []testAuthResult{ -+ {nil, nil, "", "", false}, -+ }) -+} -+ -+func TestAuthWithMissingQuote(t *testing.T) { -+ pub, pubSerialized := getTestKey() -+ authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host -+env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) -+ -+ testAuthorizedKeys(t, []byte(authWithMissingQuote), []testAuthResult{ -+ {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, -+ }) -+} -+ -+func TestInvalidEntry(t *testing.T) { -+ authInvalid := []byte(`ssh-rsa`) -+ _, _, _, _, err := ParseAuthorizedKey(authInvalid) -+ if err == nil { -+ t.Errorf("got valid entry for %q", authInvalid) -+ } -+} -+ -+var knownHostsParseTests = []struct { -+ input string -+ err string -+ -+ marker string -+ comment string -+ hosts []string -+ rest string -+}{ -+ { -+ "", -+ "EOF", -+ -+ "", "", nil, "", -+ }, -+ { -+ "# Just a comment", -+ "EOF", -+ -+ "", "", nil, "", -+ }, -+ { -+ " \t ", -+ "EOF", -+ -+ "", "", nil, "", -+ }, -+ { -+ "localhost ssh-rsa {RSAPUB}", -+ "", -+ -+ "", "", []string{"localhost"}, "", -+ }, -+ { -+ "localhost\tssh-rsa {RSAPUB}", -+ "", -+ -+ "", "", []string{"localhost"}, "", -+ }, -+ { -+ "localhost\tssh-rsa {RSAPUB}\tcomment comment", -+ "", -+ -+ "", "comment comment", []string{"localhost"}, "", -+ }, -+ { -+ "localhost\tssh-rsa {RSAPUB}\tcomment comment\n", -+ "", -+ -+ "", "comment comment", []string{"localhost"}, "", -+ }, -+ { -+ "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n", -+ "", -+ -+ "", "comment comment", []string{"localhost"}, "", -+ }, -+ { -+ "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line", -+ "", -+ -+ "", "comment comment", []string{"localhost"}, "next line", -+ }, -+ { -+ "localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment", -+ "", -+ -+ "", "comment comment", []string{"localhost", "[host2:123]"}, "", -+ }, -+ { -+ "@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}", -+ "", -+ -+ "marker", "", []string{"localhost", "[host2:123]"}, "", -+ }, -+ { -+ "@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd", -+ "short read", -+ -+ "", "", nil, "", -+ }, -+} -+ -+func TestKnownHostsParsing(t *testing.T) { -+ rsaPub, rsaPubSerialized := getTestKey() -+ -+ for i, test := range knownHostsParseTests { -+ var expectedKey PublicKey -+ const rsaKeyToken = "{RSAPUB}" -+ -+ input := test.input -+ if strings.Contains(input, rsaKeyToken) { -+ expectedKey = rsaPub -+ input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1) -+ } -+ -+ marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input)) -+ if err != nil { -+ if len(test.err) == 0 { -+ t.Errorf("#%d: unexpectedly failed with %q", i, err) -+ } else if !strings.Contains(err.Error(), test.err) { -+ t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err) -+ } -+ continue -+ } else if len(test.err) != 0 { -+ t.Errorf("#%d: succeeded but expected error including %q", i, test.err) -+ continue -+ } -+ -+ if !reflect.DeepEqual(expectedKey, pubKey) { -+ t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey) -+ } -+ -+ if marker != test.marker { -+ t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker) -+ } -+ -+ if comment != test.comment { -+ t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment) -+ } -+ -+ if !reflect.DeepEqual(test.hosts, hosts) { -+ t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts) -+ } -+ -+ if rest := string(rest); rest != test.rest { -+ t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest) -+ } -+ } -+} -+ -+func TestFingerprintLegacyMD5(t *testing.T) { -+ pub, _ := getTestKey() -+ fingerprint := FingerprintLegacyMD5(pub) -+ want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa -+ if fingerprint != want { -+ t.Errorf("got fingerprint %q want %q", fingerprint, want) -+ } -+} -+ -+func TestFingerprintSHA256(t *testing.T) { -+ pub, _ := getTestKey() -+ fingerprint := FingerprintSHA256(pub) -+ want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa -+ if fingerprint != want { -+ t.Errorf("got fingerprint %q want %q", fingerprint, want) -+ } -+} -+ -+func TestInvalidKeys(t *testing.T) { -+ keyTypes := []string{ -+ "RSA PRIVATE KEY", -+ "PRIVATE KEY", -+ "EC PRIVATE KEY", -+ "DSA PRIVATE KEY", -+ "OPENSSH PRIVATE KEY", -+ } -+ -+ for _, keyType := range keyTypes { -+ for _, dataLen := range []int{0, 1, 2, 5, 10, 20} { -+ data := make([]byte, dataLen) -+ if _, err := io.ReadFull(rand.Reader, data); err != nil { -+ t.Fatal(err) -+ } -+ -+ var buf bytes.Buffer -+ pem.Encode(&buf, &pem.Block{ -+ Type: keyType, -+ Bytes: data, -+ }) -+ -+ // This test is just to ensure that the function -+ // doesn't panic so the return value is ignored. -+ ParseRawPrivateKey(buf.Bytes()) -+ } -+ } -+} -+ -+func TestSKKeys(t *testing.T) { -+ for _, d := range testdata.SKData { -+ pk, _, _, _, err := ParseAuthorizedKey(d.PubKey) -+ if err != nil { -+ t.Fatalf("parseAuthorizedKey returned error: %v", err) -+ } -+ -+ sigBuf := make([]byte, hex.DecodedLen(len(d.HexSignature))) -+ if _, err := hex.Decode(sigBuf, d.HexSignature); err != nil { -+ t.Fatalf("hex.Decode() failed: %v", err) -+ } -+ -+ dataBuf := make([]byte, hex.DecodedLen(len(d.HexData))) -+ if _, err := hex.Decode(dataBuf, d.HexData); err != nil { -+ t.Fatalf("hex.Decode() failed: %v", err) -+ } -+ -+ sig, _, ok := parseSignature(sigBuf) -+ if !ok { -+ t.Fatalf("parseSignature(%v) failed", sigBuf) -+ } -+ -+ // Test that good data and signature pass verification -+ if err := pk.Verify(dataBuf, sig); err != nil { -+ t.Errorf("%s: PublicKey.Verify(%v, %v) failed: %v", d.Name, dataBuf, sig, err) -+ } -+ -+ // Invalid data being passed in -+ invalidData := []byte("INVALID DATA") -+ if err := pk.Verify(invalidData, sig); err == nil { -+ t.Errorf("%s with invalid data: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, invalidData, sig) -+ } -+ -+ // Change byte in blob to corrup signature -+ sig.Blob[5] = byte('A') -+ // Corrupted data being passed in -+ if err := pk.Verify(dataBuf, sig); err == nil { -+ t.Errorf("%s with corrupted signature: PublicKey.Verify(%v, %v) passed unexpectedly", d.Name, dataBuf, sig) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go -new file mode 100644 -index 00000000000000..7376a8dff23f61 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts.go -@@ -0,0 +1,540 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package knownhosts implements a parser for the OpenSSH known_hosts -+// host key database, and provides utility functions for writing -+// OpenSSH compliant known_hosts files. -+package knownhosts -+ -+import ( -+ "bufio" -+ "bytes" -+ "crypto/hmac" -+ "crypto/rand" -+ "crypto/sha1" -+ "encoding/base64" -+ "errors" -+ "fmt" -+ "io" -+ "net" -+ "os" -+ "strings" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// See the sshd manpage -+// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for -+// background. -+ -+type addr struct{ host, port string } -+ -+func (a *addr) String() string { -+ h := a.host -+ if strings.Contains(h, ":") { -+ h = "[" + h + "]" -+ } -+ return h + ":" + a.port -+} -+ -+type matcher interface { -+ match(addr) bool -+} -+ -+type hostPattern struct { -+ negate bool -+ addr addr -+} -+ -+func (p *hostPattern) String() string { -+ n := "" -+ if p.negate { -+ n = "!" -+ } -+ -+ return n + p.addr.String() -+} -+ -+type hostPatterns []hostPattern -+ -+func (ps hostPatterns) match(a addr) bool { -+ matched := false -+ for _, p := range ps { -+ if !p.match(a) { -+ continue -+ } -+ if p.negate { -+ return false -+ } -+ matched = true -+ } -+ return matched -+} -+ -+// See -+// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c -+// The matching of * has no regard for separators, unlike filesystem globs -+func wildcardMatch(pat []byte, str []byte) bool { -+ for { -+ if len(pat) == 0 { -+ return len(str) == 0 -+ } -+ if len(str) == 0 { -+ return false -+ } -+ -+ if pat[0] == '*' { -+ if len(pat) == 1 { -+ return true -+ } -+ -+ for j := range str { -+ if wildcardMatch(pat[1:], str[j:]) { -+ return true -+ } -+ } -+ return false -+ } -+ -+ if pat[0] == '?' || pat[0] == str[0] { -+ pat = pat[1:] -+ str = str[1:] -+ } else { -+ return false -+ } -+ } -+} -+ -+func (p *hostPattern) match(a addr) bool { -+ return wildcardMatch([]byte(p.addr.host), []byte(a.host)) && p.addr.port == a.port -+} -+ -+type keyDBLine struct { -+ cert bool -+ matcher matcher -+ knownKey KnownKey -+} -+ -+func serialize(k ssh.PublicKey) string { -+ return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal()) -+} -+ -+func (l *keyDBLine) match(a addr) bool { -+ return l.matcher.match(a) -+} -+ -+type hostKeyDB struct { -+ // Serialized version of revoked keys -+ revoked map[string]*KnownKey -+ lines []keyDBLine -+} -+ -+func newHostKeyDB() *hostKeyDB { -+ db := &hostKeyDB{ -+ revoked: make(map[string]*KnownKey), -+ } -+ -+ return db -+} -+ -+func keyEq(a, b ssh.PublicKey) bool { -+ return bytes.Equal(a.Marshal(), b.Marshal()) -+} -+ -+// IsHostAuthority can be used as a callback in ssh.CertChecker -+func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool { -+ h, p, err := net.SplitHostPort(address) -+ if err != nil { -+ return false -+ } -+ a := addr{host: h, port: p} -+ -+ for _, l := range db.lines { -+ if l.cert && keyEq(l.knownKey.Key, remote) && l.match(a) { -+ return true -+ } -+ } -+ return false -+} -+ -+// IsRevoked can be used as a callback in ssh.CertChecker -+func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool { -+ _, ok := db.revoked[string(key.Marshal())] -+ return ok -+} -+ -+const markerCert = "@cert-authority" -+const markerRevoked = "@revoked" -+ -+func nextWord(line []byte) (string, []byte) { -+ i := bytes.IndexAny(line, "\t ") -+ if i == -1 { -+ return string(line), nil -+ } -+ -+ return string(line[:i]), bytes.TrimSpace(line[i:]) -+} -+ -+func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) { -+ if w, next := nextWord(line); w == markerCert || w == markerRevoked { -+ marker = w -+ line = next -+ } -+ -+ host, line = nextWord(line) -+ if len(line) == 0 { -+ return "", "", nil, errors.New("knownhosts: missing host pattern") -+ } -+ -+ // ignore the keytype as it's in the key blob anyway. -+ _, line = nextWord(line) -+ if len(line) == 0 { -+ return "", "", nil, errors.New("knownhosts: missing key type pattern") -+ } -+ -+ keyBlob, _ := nextWord(line) -+ -+ keyBytes, err := base64.StdEncoding.DecodeString(keyBlob) -+ if err != nil { -+ return "", "", nil, err -+ } -+ key, err = ssh.ParsePublicKey(keyBytes) -+ if err != nil { -+ return "", "", nil, err -+ } -+ -+ return marker, host, key, nil -+} -+ -+func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error { -+ marker, pattern, key, err := parseLine(line) -+ if err != nil { -+ return err -+ } -+ -+ if marker == markerRevoked { -+ db.revoked[string(key.Marshal())] = &KnownKey{ -+ Key: key, -+ Filename: filename, -+ Line: linenum, -+ } -+ -+ return nil -+ } -+ -+ entry := keyDBLine{ -+ cert: marker == markerCert, -+ knownKey: KnownKey{ -+ Filename: filename, -+ Line: linenum, -+ Key: key, -+ }, -+ } -+ -+ if pattern[0] == '|' { -+ entry.matcher, err = newHashedHost(pattern) -+ } else { -+ entry.matcher, err = newHostnameMatcher(pattern) -+ } -+ -+ if err != nil { -+ return err -+ } -+ -+ db.lines = append(db.lines, entry) -+ return nil -+} -+ -+func newHostnameMatcher(pattern string) (matcher, error) { -+ var hps hostPatterns -+ for _, p := range strings.Split(pattern, ",") { -+ if len(p) == 0 { -+ continue -+ } -+ -+ var a addr -+ var negate bool -+ if p[0] == '!' { -+ negate = true -+ p = p[1:] -+ } -+ -+ if len(p) == 0 { -+ return nil, errors.New("knownhosts: negation without following hostname") -+ } -+ -+ var err error -+ if p[0] == '[' { -+ a.host, a.port, err = net.SplitHostPort(p) -+ if err != nil { -+ return nil, err -+ } -+ } else { -+ a.host, a.port, err = net.SplitHostPort(p) -+ if err != nil { -+ a.host = p -+ a.port = "22" -+ } -+ } -+ hps = append(hps, hostPattern{ -+ negate: negate, -+ addr: a, -+ }) -+ } -+ return hps, nil -+} -+ -+// KnownKey represents a key declared in a known_hosts file. -+type KnownKey struct { -+ Key ssh.PublicKey -+ Filename string -+ Line int -+} -+ -+func (k *KnownKey) String() string { -+ return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key)) -+} -+ -+// KeyError is returned if we did not find the key in the host key -+// database, or there was a mismatch. Typically, in batch -+// applications, this should be interpreted as failure. Interactive -+// applications can offer an interactive prompt to the user. -+type KeyError struct { -+ // Want holds the accepted host keys. For each key algorithm, -+ // there can be one hostkey. If Want is empty, the host is -+ // unknown. If Want is non-empty, there was a mismatch, which -+ // can signify a MITM attack. -+ Want []KnownKey -+} -+ -+func (u *KeyError) Error() string { -+ if len(u.Want) == 0 { -+ return "knownhosts: key is unknown" -+ } -+ return "knownhosts: key mismatch" -+} -+ -+// RevokedError is returned if we found a key that was revoked. -+type RevokedError struct { -+ Revoked KnownKey -+} -+ -+func (r *RevokedError) Error() string { -+ return "knownhosts: key is revoked" -+} -+ -+// check checks a key against the host database. This should not be -+// used for verifying certificates. -+func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error { -+ if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil { -+ return &RevokedError{Revoked: *revoked} -+ } -+ -+ host, port, err := net.SplitHostPort(remote.String()) -+ if err != nil { -+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err) -+ } -+ -+ hostToCheck := addr{host, port} -+ if address != "" { -+ // Give preference to the hostname if available. -+ host, port, err := net.SplitHostPort(address) -+ if err != nil { -+ return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err) -+ } -+ -+ hostToCheck = addr{host, port} -+ } -+ -+ return db.checkAddr(hostToCheck, remoteKey) -+} -+ -+// checkAddr checks if we can find the given public key for the -+// given address. If we only find an entry for the IP address, -+// or only the hostname, then this still succeeds. -+func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { -+ // TODO(hanwen): are these the right semantics? What if there -+ // is just a key for the IP address, but not for the -+ // hostname? -+ -+ // Algorithm => key. -+ knownKeys := map[string]KnownKey{} -+ for _, l := range db.lines { -+ if l.match(a) { -+ typ := l.knownKey.Key.Type() -+ if _, ok := knownKeys[typ]; !ok { -+ knownKeys[typ] = l.knownKey -+ } -+ } -+ } -+ -+ keyErr := &KeyError{} -+ for _, v := range knownKeys { -+ keyErr.Want = append(keyErr.Want, v) -+ } -+ -+ // Unknown remote host. -+ if len(knownKeys) == 0 { -+ return keyErr -+ } -+ -+ // If the remote host starts using a different, unknown key type, we -+ // also interpret that as a mismatch. -+ if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { -+ return keyErr -+ } -+ -+ return nil -+} -+ -+// The Read function parses file contents. -+func (db *hostKeyDB) Read(r io.Reader, filename string) error { -+ scanner := bufio.NewScanner(r) -+ -+ lineNum := 0 -+ for scanner.Scan() { -+ lineNum++ -+ line := scanner.Bytes() -+ line = bytes.TrimSpace(line) -+ if len(line) == 0 || line[0] == '#' { -+ continue -+ } -+ -+ if err := db.parseLine(line, filename, lineNum); err != nil { -+ return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err) -+ } -+ } -+ return scanner.Err() -+} -+ -+// New creates a host key callback from the given OpenSSH host key -+// files. The returned callback is for use in -+// ssh.ClientConfig.HostKeyCallback. By preference, the key check -+// operates on the hostname if available, i.e. if a server changes its -+// IP address, the host key check will still succeed, even though a -+// record of the new IP address is not available. -+func New(files ...string) (ssh.HostKeyCallback, error) { -+ db := newHostKeyDB() -+ for _, fn := range files { -+ f, err := os.Open(fn) -+ if err != nil { -+ return nil, err -+ } -+ defer f.Close() -+ if err := db.Read(f, fn); err != nil { -+ return nil, err -+ } -+ } -+ -+ var certChecker ssh.CertChecker -+ certChecker.IsHostAuthority = db.IsHostAuthority -+ certChecker.IsRevoked = db.IsRevoked -+ certChecker.HostKeyFallback = db.check -+ -+ return certChecker.CheckHostKey, nil -+} -+ -+// Normalize normalizes an address into the form used in known_hosts -+func Normalize(address string) string { -+ host, port, err := net.SplitHostPort(address) -+ if err != nil { -+ host = address -+ port = "22" -+ } -+ entry := host -+ if port != "22" { -+ entry = "[" + entry + "]:" + port -+ } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { -+ entry = "[" + entry + "]" -+ } -+ return entry -+} -+ -+// Line returns a line to add append to the known_hosts files. -+func Line(addresses []string, key ssh.PublicKey) string { -+ var trimmed []string -+ for _, a := range addresses { -+ trimmed = append(trimmed, Normalize(a)) -+ } -+ -+ return strings.Join(trimmed, ",") + " " + serialize(key) -+} -+ -+// HashHostname hashes the given hostname. The hostname is not -+// normalized before hashing. -+func HashHostname(hostname string) string { -+ // TODO(hanwen): check if we can safely normalize this always. -+ salt := make([]byte, sha1.Size) -+ -+ _, err := rand.Read(salt) -+ if err != nil { -+ panic(fmt.Sprintf("crypto/rand failure %v", err)) -+ } -+ -+ hash := hashHost(hostname, salt) -+ return encodeHash(sha1HashType, salt, hash) -+} -+ -+func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) { -+ if len(encoded) == 0 || encoded[0] != '|' { -+ err = errors.New("knownhosts: hashed host must start with '|'") -+ return -+ } -+ components := strings.Split(encoded, "|") -+ if len(components) != 4 { -+ err = fmt.Errorf("knownhosts: got %d components, want 3", len(components)) -+ return -+ } -+ -+ hashType = components[1] -+ if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil { -+ return -+ } -+ if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil { -+ return -+ } -+ return -+} -+ -+func encodeHash(typ string, salt []byte, hash []byte) string { -+ return strings.Join([]string{"", -+ typ, -+ base64.StdEncoding.EncodeToString(salt), -+ base64.StdEncoding.EncodeToString(hash), -+ }, "|") -+} -+ -+// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 -+func hashHost(hostname string, salt []byte) []byte { -+ mac := hmac.New(sha1.New, salt) -+ mac.Write([]byte(hostname)) -+ return mac.Sum(nil) -+} -+ -+type hashedHost struct { -+ salt []byte -+ hash []byte -+} -+ -+const sha1HashType = "1" -+ -+func newHashedHost(encoded string) (*hashedHost, error) { -+ typ, salt, hash, err := decodeHash(encoded) -+ if err != nil { -+ return nil, err -+ } -+ -+ // The type field seems for future algorithm agility, but it's -+ // actually hardcoded in openssh currently, see -+ // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 -+ if typ != sha1HashType { -+ return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ) -+ } -+ -+ return &hashedHost{salt: salt, hash: hash}, nil -+} -+ -+func (h *hashedHost) match(a addr) bool { -+ return bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go -new file mode 100644 -index 00000000000000..464dd592493ab3 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go -@@ -0,0 +1,356 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package knownhosts -+ -+import ( -+ "bytes" -+ "fmt" -+ "net" -+ "reflect" -+ "testing" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX" -+const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx" -+const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs=" -+ -+var ecKey, alternateEdKey, edKey ssh.PublicKey -+var testAddr = &net.TCPAddr{ -+ IP: net.IP{198, 41, 30, 196}, -+ Port: 22, -+} -+ -+var testAddr6 = &net.TCPAddr{ -+ IP: net.IP{198, 41, 30, 196, -+ 1, 2, 3, 4, -+ 1, 2, 3, 4, -+ 1, 2, 3, 4, -+ }, -+ Port: 22, -+} -+ -+func init() { -+ var err error -+ ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr)) -+ if err != nil { -+ panic(err) -+ } -+ edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr)) -+ if err != nil { -+ panic(err) -+ } -+ alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr)) -+ if err != nil { -+ panic(err) -+ } -+} -+ -+func testDB(t *testing.T, s string) *hostKeyDB { -+ db := newHostKeyDB() -+ if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil { -+ t.Fatalf("Read: %v", err) -+ } -+ -+ return db -+} -+ -+func TestRevoked(t *testing.T) { -+ db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n") -+ want := &RevokedError{ -+ Revoked: KnownKey{ -+ Key: edKey, -+ Filename: "testdb", -+ Line: 3, -+ }, -+ } -+ if err := db.check("", &net.TCPAddr{ -+ Port: 42, -+ }, edKey); err == nil { -+ t.Fatal("no error for revoked key") -+ } else if !reflect.DeepEqual(want, err) { -+ t.Fatalf("got %#v, want %#v", want, err) -+ } -+} -+ -+func TestHostAuthority(t *testing.T) { -+ for _, m := range []struct { -+ authorityFor string -+ address string -+ -+ good bool -+ }{ -+ {authorityFor: "localhost", address: "localhost:22", good: true}, -+ {authorityFor: "localhost", address: "localhost", good: false}, -+ {authorityFor: "localhost", address: "localhost:1234", good: false}, -+ {authorityFor: "[localhost]:1234", address: "localhost:1234", good: true}, -+ {authorityFor: "[localhost]:1234", address: "localhost:22", good: false}, -+ {authorityFor: "[localhost]:1234", address: "localhost", good: false}, -+ } { -+ db := testDB(t, `@cert-authority `+m.authorityFor+` `+edKeyStr) -+ if ok := db.IsHostAuthority(db.lines[0].knownKey.Key, m.address); ok != m.good { -+ t.Errorf("IsHostAuthority: authority %s, address %s, wanted good = %v, got good = %v", -+ m.authorityFor, m.address, m.good, ok) -+ } -+ } -+} -+ -+func TestBracket(t *testing.T) { -+ db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr) -+ -+ if err := db.check("git.eclipse.org:29418", &net.TCPAddr{ -+ IP: net.IP{198, 41, 30, 196}, -+ Port: 29418, -+ }, edKey); err != nil { -+ t.Errorf("got error %v, want none", err) -+ } -+ -+ if err := db.check("git.eclipse.org:29419", &net.TCPAddr{ -+ Port: 42, -+ }, edKey); err == nil { -+ t.Fatalf("no error for unknown address") -+ } else if ke, ok := err.(*KeyError); !ok { -+ t.Fatalf("got type %T, want *KeyError", err) -+ } else if len(ke.Want) > 0 { -+ t.Fatalf("got Want %v, want []", ke.Want) -+ } -+} -+ -+func TestNewKeyType(t *testing.T) { -+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr) -+ db := testDB(t, str) -+ if err := db.check("", testAddr, ecKey); err == nil { -+ t.Fatalf("no error for unknown address") -+ } else if ke, ok := err.(*KeyError); !ok { -+ t.Fatalf("got type %T, want *KeyError", err) -+ } else if len(ke.Want) == 0 { -+ t.Fatalf("got empty KeyError.Want") -+ } -+} -+ -+func TestSameKeyType(t *testing.T) { -+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr) -+ db := testDB(t, str) -+ if err := db.check("", testAddr, alternateEdKey); err == nil { -+ t.Fatalf("no error for unknown address") -+ } else if ke, ok := err.(*KeyError); !ok { -+ t.Fatalf("got type %T, want *KeyError", err) -+ } else if len(ke.Want) == 0 { -+ t.Fatalf("got empty KeyError.Want") -+ } else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) { -+ t.Fatalf("got key %q, want %q", got, want) -+ } -+} -+ -+func TestIPAddress(t *testing.T) { -+ str := fmt.Sprintf("%s %s", testAddr, edKeyStr) -+ db := testDB(t, str) -+ if err := db.check("", testAddr, edKey); err != nil { -+ t.Errorf("got error %q, want none", err) -+ } -+} -+ -+func TestIPv6Address(t *testing.T) { -+ str := fmt.Sprintf("%s %s", testAddr6, edKeyStr) -+ db := testDB(t, str) -+ -+ if err := db.check("", testAddr6, edKey); err != nil { -+ t.Errorf("got error %q, want none", err) -+ } -+} -+ -+func TestBasic(t *testing.T) { -+ str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr) -+ db := testDB(t, str) -+ if err := db.check("server.org:22", testAddr, edKey); err != nil { -+ t.Errorf("got error %v, want none", err) -+ } -+ -+ want := KnownKey{ -+ Key: edKey, -+ Filename: "testdb", -+ Line: 3, -+ } -+ if err := db.check("server.org:22", testAddr, ecKey); err == nil { -+ t.Errorf("succeeded, want KeyError") -+ } else if ke, ok := err.(*KeyError); !ok { -+ t.Errorf("got %T, want *KeyError", err) -+ } else if len(ke.Want) != 1 { -+ t.Errorf("got %v, want 1 entry", ke) -+ } else if !reflect.DeepEqual(ke.Want[0], want) { -+ t.Errorf("got %v, want %v", ke.Want[0], want) -+ } -+} -+ -+func TestHostNamePrecedence(t *testing.T) { -+ var evilAddr = &net.TCPAddr{ -+ IP: net.IP{66, 66, 66, 66}, -+ Port: 22, -+ } -+ -+ str := fmt.Sprintf("server.org,%s %s\nevil.org,%s %s", testAddr, edKeyStr, evilAddr, ecKeyStr) -+ db := testDB(t, str) -+ -+ if err := db.check("server.org:22", evilAddr, ecKey); err == nil { -+ t.Errorf("check succeeded") -+ } else if _, ok := err.(*KeyError); !ok { -+ t.Errorf("got %T, want *KeyError", err) -+ } -+} -+ -+func TestDBOrderingPrecedenceKeyType(t *testing.T) { -+ str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr) -+ db := testDB(t, str) -+ -+ if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil { -+ t.Errorf("check succeeded") -+ } else if _, ok := err.(*KeyError); !ok { -+ t.Errorf("got %T, want *KeyError", err) -+ } -+} -+ -+func TestNegate(t *testing.T) { -+ str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) -+ db := testDB(t, str) -+ if err := db.check("server.org:22", testAddr, ecKey); err == nil { -+ t.Errorf("succeeded") -+ } else if ke, ok := err.(*KeyError); !ok { -+ t.Errorf("got error type %T, want *KeyError", err) -+ } else if len(ke.Want) != 0 { -+ t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type()) -+ } -+} -+ -+func TestWildcard(t *testing.T) { -+ str := fmt.Sprintf("server*.domain %s", edKeyStr) -+ db := testDB(t, str) -+ -+ want := &KeyError{ -+ Want: []KnownKey{{ -+ Filename: "testdb", -+ Line: 1, -+ Key: edKey, -+ }}, -+ } -+ -+ got := db.check("server.domain:22", &net.TCPAddr{}, ecKey) -+ if !reflect.DeepEqual(got, want) { -+ t.Errorf("got %s, want %s", got, want) -+ } -+} -+ -+func TestLine(t *testing.T) { -+ for in, want := range map[string]string{ -+ "server.org": "server.org " + edKeyStr, -+ "server.org:22": "server.org " + edKeyStr, -+ "server.org:23": "[server.org]:23 " + edKeyStr, -+ "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr, -+ "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr, -+ } { -+ if got := Line([]string{in}, edKey); got != want { -+ t.Errorf("Line(%q) = %q, want %q", in, got, want) -+ } -+ } -+} -+ -+func TestWildcardMatch(t *testing.T) { -+ for _, c := range []struct { -+ pat, str string -+ want bool -+ }{ -+ {"a?b", "abb", true}, -+ {"ab", "abc", false}, -+ {"abc", "ab", false}, -+ {"a*b", "axxxb", true}, -+ {"a*b", "axbxb", true}, -+ {"a*b", "axbxbc", false}, -+ {"a*?", "axbxc", true}, -+ {"a*b*", "axxbxxxxxx", true}, -+ {"a*b*c", "axxbxxxxxxc", true}, -+ {"a*b*?", "axxbxxxxxxc", true}, -+ {"a*b*z", "axxbxxbxxxz", true}, -+ {"a*b*z", "axxbxxzxxxz", true}, -+ {"a*b*z", "axxbxxzxxx", false}, -+ } { -+ got := wildcardMatch([]byte(c.pat), []byte(c.str)) -+ if got != c.want { -+ t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want) -+ } -+ -+ } -+} -+ -+// TODO(hanwen): test coverage for certificates. -+ -+const testHostname = "hostname" -+ -+// generated with keygen -H -f -+const encodedTestHostnameHash = "|1|IHXZvQMvTcZTUU29+2vXFgx8Frs=|UGccIWfRVDwilMBnA3WJoRAC75Y=" -+ -+func TestHostHash(t *testing.T) { -+ testHostHash(t, testHostname, encodedTestHostnameHash) -+} -+ -+func TestHashList(t *testing.T) { -+ encoded := HashHostname(testHostname) -+ testHostHash(t, testHostname, encoded) -+} -+ -+func testHostHash(t *testing.T, hostname, encoded string) { -+ typ, salt, hash, err := decodeHash(encoded) -+ if err != nil { -+ t.Fatalf("decodeHash: %v", err) -+ } -+ -+ if got := encodeHash(typ, salt, hash); got != encoded { -+ t.Errorf("got encoding %s want %s", got, encoded) -+ } -+ -+ if typ != sha1HashType { -+ t.Fatalf("got hash type %q, want %q", typ, sha1HashType) -+ } -+ -+ got := hashHost(hostname, salt) -+ if !bytes.Equal(got, hash) { -+ t.Errorf("got hash %x want %x", got, hash) -+ } -+} -+ -+func TestNormalize(t *testing.T) { -+ for in, want := range map[string]string{ -+ "127.0.0.1:22": "127.0.0.1", -+ "[127.0.0.1]:22": "127.0.0.1", -+ "[127.0.0.1]:23": "[127.0.0.1]:23", -+ "127.0.0.1:23": "[127.0.0.1]:23", -+ "[a.b.c]:22": "a.b.c", -+ "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]", -+ "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]", -+ "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23", -+ } { -+ got := Normalize(in) -+ if got != want { -+ t.Errorf("Normalize(%q) = %q, want %q", in, got, want) -+ } -+ } -+} -+ -+func TestHashedHostkeyCheck(t *testing.T) { -+ str := fmt.Sprintf("%s %s", HashHostname(testHostname), edKeyStr) -+ db := testDB(t, str) -+ if err := db.check(testHostname+":22", testAddr, edKey); err != nil { -+ t.Errorf("check(%s): %v", testHostname, err) -+ } -+ want := &KeyError{ -+ Want: []KnownKey{{ -+ Filename: "testdb", -+ Line: 1, -+ Key: edKey, -+ }}, -+ } -+ if got := db.check(testHostname+":22", testAddr, alternateEdKey); !reflect.DeepEqual(got, want) { -+ t.Errorf("got error %v, want %v", got, want) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/mac.go b/ms_mod/golang.org/x/crypto/ssh/mac.go -new file mode 100644 -index 00000000000000..06a1b27507ee3a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/mac.go -@@ -0,0 +1,68 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+// Message authentication support -+ -+import ( -+ "crypto/hmac" -+ "crypto/sha1" -+ "crypto/sha256" -+ "crypto/sha512" -+ "hash" -+) -+ -+type macMode struct { -+ keySize int -+ etm bool -+ new func(key []byte) hash.Hash -+} -+ -+// truncatingMAC wraps around a hash.Hash and truncates the output digest to -+// a given size. -+type truncatingMAC struct { -+ length int -+ hmac hash.Hash -+} -+ -+func (t truncatingMAC) Write(data []byte) (int, error) { -+ return t.hmac.Write(data) -+} -+ -+func (t truncatingMAC) Sum(in []byte) []byte { -+ out := t.hmac.Sum(in) -+ return out[:len(in)+t.length] -+} -+ -+func (t truncatingMAC) Reset() { -+ t.hmac.Reset() -+} -+ -+func (t truncatingMAC) Size() int { -+ return t.length -+} -+ -+func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } -+ -+var macModes = map[string]*macMode{ -+ "hmac-sha2-512-etm@openssh.com": {64, true, func(key []byte) hash.Hash { -+ return hmac.New(sha512.New, key) -+ }}, -+ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { -+ return hmac.New(sha256.New, key) -+ }}, -+ "hmac-sha2-512": {64, false, func(key []byte) hash.Hash { -+ return hmac.New(sha512.New, key) -+ }}, -+ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash { -+ return hmac.New(sha256.New, key) -+ }}, -+ "hmac-sha1": {20, false, func(key []byte) hash.Hash { -+ return hmac.New(sha1.New, key) -+ }}, -+ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash { -+ return truncatingMAC{12, hmac.New(sha1.New, key)} -+ }}, -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/mempipe_test.go b/ms_mod/golang.org/x/crypto/ssh/mempipe_test.go -new file mode 100644 -index 00000000000000..8697cd6140a737 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/mempipe_test.go -@@ -0,0 +1,110 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "io" -+ "sync" -+ "testing" -+) -+ -+// An in-memory packetConn. It is safe to call Close and writePacket -+// from different goroutines. -+type memTransport struct { -+ eof bool -+ pending [][]byte -+ write *memTransport -+ sync.Mutex -+ *sync.Cond -+} -+ -+func (t *memTransport) readPacket() ([]byte, error) { -+ t.Lock() -+ defer t.Unlock() -+ for { -+ if len(t.pending) > 0 { -+ r := t.pending[0] -+ t.pending = t.pending[1:] -+ return r, nil -+ } -+ if t.eof { -+ return nil, io.EOF -+ } -+ t.Cond.Wait() -+ } -+} -+ -+func (t *memTransport) closeSelf() error { -+ t.Lock() -+ defer t.Unlock() -+ if t.eof { -+ return io.EOF -+ } -+ t.eof = true -+ t.Cond.Broadcast() -+ return nil -+} -+ -+func (t *memTransport) Close() error { -+ err := t.write.closeSelf() -+ t.closeSelf() -+ return err -+} -+ -+func (t *memTransport) writePacket(p []byte) error { -+ t.write.Lock() -+ defer t.write.Unlock() -+ if t.write.eof { -+ return io.EOF -+ } -+ c := make([]byte, len(p)) -+ copy(c, p) -+ t.write.pending = append(t.write.pending, c) -+ t.write.Cond.Signal() -+ return nil -+} -+ -+func memPipe() (a, b packetConn) { -+ t1 := memTransport{} -+ t2 := memTransport{} -+ t1.write = &t2 -+ t2.write = &t1 -+ t1.Cond = sync.NewCond(&t1.Mutex) -+ t2.Cond = sync.NewCond(&t2.Mutex) -+ return &t1, &t2 -+} -+ -+func TestMemPipe(t *testing.T) { -+ a, b := memPipe() -+ if err := a.writePacket([]byte{42}); err != nil { -+ t.Fatalf("writePacket: %v", err) -+ } -+ if err := a.Close(); err != nil { -+ t.Fatal("Close: ", err) -+ } -+ p, err := b.readPacket() -+ if err != nil { -+ t.Fatal("readPacket: ", err) -+ } -+ if len(p) != 1 || p[0] != 42 { -+ t.Fatalf("got %v, want {42}", p) -+ } -+ p, err = b.readPacket() -+ if err != io.EOF { -+ t.Fatalf("got %v, %v, want EOF", p, err) -+ } -+} -+ -+func TestDoubleClose(t *testing.T) { -+ a, _ := memPipe() -+ err := a.Close() -+ if err != nil { -+ t.Errorf("Close: %v", err) -+ } -+ err = a.Close() -+ if err != io.EOF { -+ t.Errorf("expect EOF on double close.") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/messages.go b/ms_mod/golang.org/x/crypto/ssh/messages.go -new file mode 100644 -index 00000000000000..922032d9525604 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/messages.go -@@ -0,0 +1,877 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "math/big" -+ "reflect" -+ "strconv" -+ "strings" -+) -+ -+// These are SSH message type numbers. They are scattered around several -+// documents but many were taken from [SSH-PARAMETERS]. -+const ( -+ msgIgnore = 2 -+ msgUnimplemented = 3 -+ msgDebug = 4 -+ msgNewKeys = 21 -+) -+ -+// SSH messages: -+// -+// These structures mirror the wire format of the corresponding SSH messages. -+// They are marshaled using reflection with the marshal and unmarshal functions -+// in this file. The only wrinkle is that a final member of type []byte with a -+// ssh tag of "rest" receives the remainder of a packet when unmarshaling. -+ -+// See RFC 4253, section 11.1. -+const msgDisconnect = 1 -+ -+// disconnectMsg is the message that signals a disconnect. It is also -+// the error type returned from mux.Wait() -+type disconnectMsg struct { -+ Reason uint32 `sshtype:"1"` -+ Message string -+ Language string -+} -+ -+func (d *disconnectMsg) Error() string { -+ return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message) -+} -+ -+// See RFC 4253, section 7.1. -+const msgKexInit = 20 -+ -+type kexInitMsg struct { -+ Cookie [16]byte `sshtype:"20"` -+ KexAlgos []string -+ ServerHostKeyAlgos []string -+ CiphersClientServer []string -+ CiphersServerClient []string -+ MACsClientServer []string -+ MACsServerClient []string -+ CompressionClientServer []string -+ CompressionServerClient []string -+ LanguagesClientServer []string -+ LanguagesServerClient []string -+ FirstKexFollows bool -+ Reserved uint32 -+} -+ -+// See RFC 4253, section 8. -+ -+// Diffie-Hellman -+const msgKexDHInit = 30 -+ -+type kexDHInitMsg struct { -+ X *big.Int `sshtype:"30"` -+} -+ -+const msgKexECDHInit = 30 -+ -+type kexECDHInitMsg struct { -+ ClientPubKey []byte `sshtype:"30"` -+} -+ -+const msgKexECDHReply = 31 -+ -+type kexECDHReplyMsg struct { -+ HostKey []byte `sshtype:"31"` -+ EphemeralPubKey []byte -+ Signature []byte -+} -+ -+const msgKexDHReply = 31 -+ -+type kexDHReplyMsg struct { -+ HostKey []byte `sshtype:"31"` -+ Y *big.Int -+ Signature []byte -+} -+ -+// See RFC 4419, section 5. -+const msgKexDHGexGroup = 31 -+ -+type kexDHGexGroupMsg struct { -+ P *big.Int `sshtype:"31"` -+ G *big.Int -+} -+ -+const msgKexDHGexInit = 32 -+ -+type kexDHGexInitMsg struct { -+ X *big.Int `sshtype:"32"` -+} -+ -+const msgKexDHGexReply = 33 -+ -+type kexDHGexReplyMsg struct { -+ HostKey []byte `sshtype:"33"` -+ Y *big.Int -+ Signature []byte -+} -+ -+const msgKexDHGexRequest = 34 -+ -+type kexDHGexRequestMsg struct { -+ MinBits uint32 `sshtype:"34"` -+ PreferedBits uint32 -+ MaxBits uint32 -+} -+ -+// See RFC 4253, section 10. -+const msgServiceRequest = 5 -+ -+type serviceRequestMsg struct { -+ Service string `sshtype:"5"` -+} -+ -+// See RFC 4253, section 10. -+const msgServiceAccept = 6 -+ -+type serviceAcceptMsg struct { -+ Service string `sshtype:"6"` -+} -+ -+// See RFC 8308, section 2.3 -+const msgExtInfo = 7 -+ -+type extInfoMsg struct { -+ NumExtensions uint32 `sshtype:"7"` -+ Payload []byte `ssh:"rest"` -+} -+ -+// See RFC 4252, section 5. -+const msgUserAuthRequest = 50 -+ -+type userAuthRequestMsg struct { -+ User string `sshtype:"50"` -+ Service string -+ Method string -+ Payload []byte `ssh:"rest"` -+} -+ -+// Used for debug printouts of packets. -+type userAuthSuccessMsg struct { -+} -+ -+// See RFC 4252, section 5.1 -+const msgUserAuthFailure = 51 -+ -+type userAuthFailureMsg struct { -+ Methods []string `sshtype:"51"` -+ PartialSuccess bool -+} -+ -+// See RFC 4252, section 5.1 -+const msgUserAuthSuccess = 52 -+ -+// See RFC 4252, section 5.4 -+const msgUserAuthBanner = 53 -+ -+type userAuthBannerMsg struct { -+ Message string `sshtype:"53"` -+ // unused, but required to allow message parsing -+ Language string -+} -+ -+// See RFC 4256, section 3.2 -+const msgUserAuthInfoRequest = 60 -+const msgUserAuthInfoResponse = 61 -+ -+type userAuthInfoRequestMsg struct { -+ Name string `sshtype:"60"` -+ Instruction string -+ Language string -+ NumPrompts uint32 -+ Prompts []byte `ssh:"rest"` -+} -+ -+// See RFC 4254, section 5.1. -+const msgChannelOpen = 90 -+ -+type channelOpenMsg struct { -+ ChanType string `sshtype:"90"` -+ PeersID uint32 -+ PeersWindow uint32 -+ MaxPacketSize uint32 -+ TypeSpecificData []byte `ssh:"rest"` -+} -+ -+const msgChannelExtendedData = 95 -+const msgChannelData = 94 -+ -+// Used for debug print outs of packets. -+type channelDataMsg struct { -+ PeersID uint32 `sshtype:"94"` -+ Length uint32 -+ Rest []byte `ssh:"rest"` -+} -+ -+// See RFC 4254, section 5.1. -+const msgChannelOpenConfirm = 91 -+ -+type channelOpenConfirmMsg struct { -+ PeersID uint32 `sshtype:"91"` -+ MyID uint32 -+ MyWindow uint32 -+ MaxPacketSize uint32 -+ TypeSpecificData []byte `ssh:"rest"` -+} -+ -+// See RFC 4254, section 5.1. -+const msgChannelOpenFailure = 92 -+ -+type channelOpenFailureMsg struct { -+ PeersID uint32 `sshtype:"92"` -+ Reason RejectionReason -+ Message string -+ Language string -+} -+ -+const msgChannelRequest = 98 -+ -+type channelRequestMsg struct { -+ PeersID uint32 `sshtype:"98"` -+ Request string -+ WantReply bool -+ RequestSpecificData []byte `ssh:"rest"` -+} -+ -+// See RFC 4254, section 5.4. -+const msgChannelSuccess = 99 -+ -+type channelRequestSuccessMsg struct { -+ PeersID uint32 `sshtype:"99"` -+} -+ -+// See RFC 4254, section 5.4. -+const msgChannelFailure = 100 -+ -+type channelRequestFailureMsg struct { -+ PeersID uint32 `sshtype:"100"` -+} -+ -+// See RFC 4254, section 5.3 -+const msgChannelClose = 97 -+ -+type channelCloseMsg struct { -+ PeersID uint32 `sshtype:"97"` -+} -+ -+// See RFC 4254, section 5.3 -+const msgChannelEOF = 96 -+ -+type channelEOFMsg struct { -+ PeersID uint32 `sshtype:"96"` -+} -+ -+// See RFC 4254, section 4 -+const msgGlobalRequest = 80 -+ -+type globalRequestMsg struct { -+ Type string `sshtype:"80"` -+ WantReply bool -+ Data []byte `ssh:"rest"` -+} -+ -+// See RFC 4254, section 4 -+const msgRequestSuccess = 81 -+ -+type globalRequestSuccessMsg struct { -+ Data []byte `ssh:"rest" sshtype:"81"` -+} -+ -+// See RFC 4254, section 4 -+const msgRequestFailure = 82 -+ -+type globalRequestFailureMsg struct { -+ Data []byte `ssh:"rest" sshtype:"82"` -+} -+ -+// See RFC 4254, section 5.2 -+const msgChannelWindowAdjust = 93 -+ -+type windowAdjustMsg struct { -+ PeersID uint32 `sshtype:"93"` -+ AdditionalBytes uint32 -+} -+ -+// See RFC 4252, section 7 -+const msgUserAuthPubKeyOk = 60 -+ -+type userAuthPubKeyOkMsg struct { -+ Algo string `sshtype:"60"` -+ PubKey []byte -+} -+ -+// See RFC 4462, section 3 -+const msgUserAuthGSSAPIResponse = 60 -+ -+type userAuthGSSAPIResponse struct { -+ SupportMech []byte `sshtype:"60"` -+} -+ -+const msgUserAuthGSSAPIToken = 61 -+ -+type userAuthGSSAPIToken struct { -+ Token []byte `sshtype:"61"` -+} -+ -+const msgUserAuthGSSAPIMIC = 66 -+ -+type userAuthGSSAPIMIC struct { -+ MIC []byte `sshtype:"66"` -+} -+ -+// See RFC 4462, section 3.9 -+const msgUserAuthGSSAPIErrTok = 64 -+ -+type userAuthGSSAPIErrTok struct { -+ ErrorToken []byte `sshtype:"64"` -+} -+ -+// See RFC 4462, section 3.8 -+const msgUserAuthGSSAPIError = 65 -+ -+type userAuthGSSAPIError struct { -+ MajorStatus uint32 `sshtype:"65"` -+ MinorStatus uint32 -+ Message string -+ LanguageTag string -+} -+ -+// typeTags returns the possible type bytes for the given reflect.Type, which -+// should be a struct. The possible values are separated by a '|' character. -+func typeTags(structType reflect.Type) (tags []byte) { -+ tagStr := structType.Field(0).Tag.Get("sshtype") -+ -+ for _, tag := range strings.Split(tagStr, "|") { -+ i, err := strconv.Atoi(tag) -+ if err == nil { -+ tags = append(tags, byte(i)) -+ } -+ } -+ -+ return tags -+} -+ -+func fieldError(t reflect.Type, field int, problem string) error { -+ if problem != "" { -+ problem = ": " + problem -+ } -+ return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem) -+} -+ -+var errShortRead = errors.New("ssh: short read") -+ -+// Unmarshal parses data in SSH wire format into a structure. The out -+// argument should be a pointer to struct. If the first member of the -+// struct has the "sshtype" tag set to a '|'-separated set of numbers -+// in decimal, the packet must start with one of those numbers. In -+// case of error, Unmarshal returns a ParseError or -+// UnexpectedMessageError. -+func Unmarshal(data []byte, out interface{}) error { -+ v := reflect.ValueOf(out).Elem() -+ structType := v.Type() -+ expectedTypes := typeTags(structType) -+ -+ var expectedType byte -+ if len(expectedTypes) > 0 { -+ expectedType = expectedTypes[0] -+ } -+ -+ if len(data) == 0 { -+ return parseError(expectedType) -+ } -+ -+ if len(expectedTypes) > 0 { -+ goodType := false -+ for _, e := range expectedTypes { -+ if e > 0 && data[0] == e { -+ goodType = true -+ break -+ } -+ } -+ if !goodType { -+ return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes) -+ } -+ data = data[1:] -+ } -+ -+ var ok bool -+ for i := 0; i < v.NumField(); i++ { -+ field := v.Field(i) -+ t := field.Type() -+ switch t.Kind() { -+ case reflect.Bool: -+ if len(data) < 1 { -+ return errShortRead -+ } -+ field.SetBool(data[0] != 0) -+ data = data[1:] -+ case reflect.Array: -+ if t.Elem().Kind() != reflect.Uint8 { -+ return fieldError(structType, i, "array of unsupported type") -+ } -+ if len(data) < t.Len() { -+ return errShortRead -+ } -+ for j, n := 0, t.Len(); j < n; j++ { -+ field.Index(j).Set(reflect.ValueOf(data[j])) -+ } -+ data = data[t.Len():] -+ case reflect.Uint64: -+ var u64 uint64 -+ if u64, data, ok = parseUint64(data); !ok { -+ return errShortRead -+ } -+ field.SetUint(u64) -+ case reflect.Uint32: -+ var u32 uint32 -+ if u32, data, ok = parseUint32(data); !ok { -+ return errShortRead -+ } -+ field.SetUint(uint64(u32)) -+ case reflect.Uint8: -+ if len(data) < 1 { -+ return errShortRead -+ } -+ field.SetUint(uint64(data[0])) -+ data = data[1:] -+ case reflect.String: -+ var s []byte -+ if s, data, ok = parseString(data); !ok { -+ return fieldError(structType, i, "") -+ } -+ field.SetString(string(s)) -+ case reflect.Slice: -+ switch t.Elem().Kind() { -+ case reflect.Uint8: -+ if structType.Field(i).Tag.Get("ssh") == "rest" { -+ field.Set(reflect.ValueOf(data)) -+ data = nil -+ } else { -+ var s []byte -+ if s, data, ok = parseString(data); !ok { -+ return errShortRead -+ } -+ field.Set(reflect.ValueOf(s)) -+ } -+ case reflect.String: -+ var nl []string -+ if nl, data, ok = parseNameList(data); !ok { -+ return errShortRead -+ } -+ field.Set(reflect.ValueOf(nl)) -+ default: -+ return fieldError(structType, i, "slice of unsupported type") -+ } -+ case reflect.Ptr: -+ if t == bigIntType { -+ var n *big.Int -+ if n, data, ok = parseInt(data); !ok { -+ return errShortRead -+ } -+ field.Set(reflect.ValueOf(n)) -+ } else { -+ return fieldError(structType, i, "pointer to unsupported type") -+ } -+ default: -+ return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t)) -+ } -+ } -+ -+ if len(data) != 0 { -+ return parseError(expectedType) -+ } -+ -+ return nil -+} -+ -+// Marshal serializes the message in msg to SSH wire format. The msg -+// argument should be a struct or pointer to struct. If the first -+// member has the "sshtype" tag set to a number in decimal, that -+// number is prepended to the result. If the last of member has the -+// "ssh" tag set to "rest", its contents are appended to the output. -+func Marshal(msg interface{}) []byte { -+ out := make([]byte, 0, 64) -+ return marshalStruct(out, msg) -+} -+ -+func marshalStruct(out []byte, msg interface{}) []byte { -+ v := reflect.Indirect(reflect.ValueOf(msg)) -+ msgTypes := typeTags(v.Type()) -+ if len(msgTypes) > 0 { -+ out = append(out, msgTypes[0]) -+ } -+ -+ for i, n := 0, v.NumField(); i < n; i++ { -+ field := v.Field(i) -+ switch t := field.Type(); t.Kind() { -+ case reflect.Bool: -+ var v uint8 -+ if field.Bool() { -+ v = 1 -+ } -+ out = append(out, v) -+ case reflect.Array: -+ if t.Elem().Kind() != reflect.Uint8 { -+ panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface())) -+ } -+ for j, l := 0, t.Len(); j < l; j++ { -+ out = append(out, uint8(field.Index(j).Uint())) -+ } -+ case reflect.Uint32: -+ out = appendU32(out, uint32(field.Uint())) -+ case reflect.Uint64: -+ out = appendU64(out, uint64(field.Uint())) -+ case reflect.Uint8: -+ out = append(out, uint8(field.Uint())) -+ case reflect.String: -+ s := field.String() -+ out = appendInt(out, len(s)) -+ out = append(out, s...) -+ case reflect.Slice: -+ switch t.Elem().Kind() { -+ case reflect.Uint8: -+ if v.Type().Field(i).Tag.Get("ssh") != "rest" { -+ out = appendInt(out, field.Len()) -+ } -+ out = append(out, field.Bytes()...) -+ case reflect.String: -+ offset := len(out) -+ out = appendU32(out, 0) -+ if n := field.Len(); n > 0 { -+ for j := 0; j < n; j++ { -+ f := field.Index(j) -+ if j != 0 { -+ out = append(out, ',') -+ } -+ out = append(out, f.String()...) -+ } -+ // overwrite length value -+ binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4)) -+ } -+ default: -+ panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface())) -+ } -+ case reflect.Ptr: -+ if t == bigIntType { -+ var n *big.Int -+ nValue := reflect.ValueOf(&n) -+ nValue.Elem().Set(field) -+ needed := intLength(n) -+ oldLength := len(out) -+ -+ if cap(out)-len(out) < needed { -+ newOut := make([]byte, len(out), 2*(len(out)+needed)) -+ copy(newOut, out) -+ out = newOut -+ } -+ out = out[:oldLength+needed] -+ marshalInt(out[oldLength:], n) -+ } else { -+ panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface())) -+ } -+ } -+ } -+ -+ return out -+} -+ -+var bigOne = big.NewInt(1) -+ -+func parseString(in []byte) (out, rest []byte, ok bool) { -+ if len(in) < 4 { -+ return -+ } -+ length := binary.BigEndian.Uint32(in) -+ in = in[4:] -+ if uint32(len(in)) < length { -+ return -+ } -+ out = in[:length] -+ rest = in[length:] -+ ok = true -+ return -+} -+ -+var ( -+ comma = []byte{','} -+ emptyNameList = []string{} -+) -+ -+func parseNameList(in []byte) (out []string, rest []byte, ok bool) { -+ contents, rest, ok := parseString(in) -+ if !ok { -+ return -+ } -+ if len(contents) == 0 { -+ out = emptyNameList -+ return -+ } -+ parts := bytes.Split(contents, comma) -+ out = make([]string, len(parts)) -+ for i, part := range parts { -+ out[i] = string(part) -+ } -+ return -+} -+ -+func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { -+ contents, rest, ok := parseString(in) -+ if !ok { -+ return -+ } -+ out = new(big.Int) -+ -+ if len(contents) > 0 && contents[0]&0x80 == 0x80 { -+ // This is a negative number -+ notBytes := make([]byte, len(contents)) -+ for i := range notBytes { -+ notBytes[i] = ^contents[i] -+ } -+ out.SetBytes(notBytes) -+ out.Add(out, bigOne) -+ out.Neg(out) -+ } else { -+ // Positive number -+ out.SetBytes(contents) -+ } -+ ok = true -+ return -+} -+ -+func parseUint32(in []byte) (uint32, []byte, bool) { -+ if len(in) < 4 { -+ return 0, nil, false -+ } -+ return binary.BigEndian.Uint32(in), in[4:], true -+} -+ -+func parseUint64(in []byte) (uint64, []byte, bool) { -+ if len(in) < 8 { -+ return 0, nil, false -+ } -+ return binary.BigEndian.Uint64(in), in[8:], true -+} -+ -+func intLength(n *big.Int) int { -+ length := 4 /* length bytes */ -+ if n.Sign() < 0 { -+ nMinus1 := new(big.Int).Neg(n) -+ nMinus1.Sub(nMinus1, bigOne) -+ bitLen := nMinus1.BitLen() -+ if bitLen%8 == 0 { -+ // The number will need 0xff padding -+ length++ -+ } -+ length += (bitLen + 7) / 8 -+ } else if n.Sign() == 0 { -+ // A zero is the zero length string -+ } else { -+ bitLen := n.BitLen() -+ if bitLen%8 == 0 { -+ // The number will need 0x00 padding -+ length++ -+ } -+ length += (bitLen + 7) / 8 -+ } -+ -+ return length -+} -+ -+func marshalUint32(to []byte, n uint32) []byte { -+ binary.BigEndian.PutUint32(to, n) -+ return to[4:] -+} -+ -+func marshalUint64(to []byte, n uint64) []byte { -+ binary.BigEndian.PutUint64(to, n) -+ return to[8:] -+} -+ -+func marshalInt(to []byte, n *big.Int) []byte { -+ lengthBytes := to -+ to = to[4:] -+ length := 0 -+ -+ if n.Sign() < 0 { -+ // A negative number has to be converted to two's-complement -+ // form. So we'll subtract 1 and invert. If the -+ // most-significant-bit isn't set then we'll need to pad the -+ // beginning with 0xff in order to keep the number negative. -+ nMinus1 := new(big.Int).Neg(n) -+ nMinus1.Sub(nMinus1, bigOne) -+ bytes := nMinus1.Bytes() -+ for i := range bytes { -+ bytes[i] ^= 0xff -+ } -+ if len(bytes) == 0 || bytes[0]&0x80 == 0 { -+ to[0] = 0xff -+ to = to[1:] -+ length++ -+ } -+ nBytes := copy(to, bytes) -+ to = to[nBytes:] -+ length += nBytes -+ } else if n.Sign() == 0 { -+ // A zero is the zero length string -+ } else { -+ bytes := n.Bytes() -+ if len(bytes) > 0 && bytes[0]&0x80 != 0 { -+ // We'll have to pad this with a 0x00 in order to -+ // stop it looking like a negative number. -+ to[0] = 0 -+ to = to[1:] -+ length++ -+ } -+ nBytes := copy(to, bytes) -+ to = to[nBytes:] -+ length += nBytes -+ } -+ -+ lengthBytes[0] = byte(length >> 24) -+ lengthBytes[1] = byte(length >> 16) -+ lengthBytes[2] = byte(length >> 8) -+ lengthBytes[3] = byte(length) -+ return to -+} -+ -+func writeInt(w io.Writer, n *big.Int) { -+ length := intLength(n) -+ buf := make([]byte, length) -+ marshalInt(buf, n) -+ w.Write(buf) -+} -+ -+func writeString(w io.Writer, s []byte) { -+ var lengthBytes [4]byte -+ lengthBytes[0] = byte(len(s) >> 24) -+ lengthBytes[1] = byte(len(s) >> 16) -+ lengthBytes[2] = byte(len(s) >> 8) -+ lengthBytes[3] = byte(len(s)) -+ w.Write(lengthBytes[:]) -+ w.Write(s) -+} -+ -+func stringLength(n int) int { -+ return 4 + n -+} -+ -+func marshalString(to []byte, s []byte) []byte { -+ to[0] = byte(len(s) >> 24) -+ to[1] = byte(len(s) >> 16) -+ to[2] = byte(len(s) >> 8) -+ to[3] = byte(len(s)) -+ to = to[4:] -+ copy(to, s) -+ return to[len(s):] -+} -+ -+var bigIntType = reflect.TypeOf((*big.Int)(nil)) -+ -+// Decode a packet into its corresponding message. -+func decode(packet []byte) (interface{}, error) { -+ var msg interface{} -+ switch packet[0] { -+ case msgDisconnect: -+ msg = new(disconnectMsg) -+ case msgServiceRequest: -+ msg = new(serviceRequestMsg) -+ case msgServiceAccept: -+ msg = new(serviceAcceptMsg) -+ case msgExtInfo: -+ msg = new(extInfoMsg) -+ case msgKexInit: -+ msg = new(kexInitMsg) -+ case msgKexDHInit: -+ msg = new(kexDHInitMsg) -+ case msgKexDHReply: -+ msg = new(kexDHReplyMsg) -+ case msgUserAuthRequest: -+ msg = new(userAuthRequestMsg) -+ case msgUserAuthSuccess: -+ return new(userAuthSuccessMsg), nil -+ case msgUserAuthFailure: -+ msg = new(userAuthFailureMsg) -+ case msgUserAuthPubKeyOk: -+ msg = new(userAuthPubKeyOkMsg) -+ case msgGlobalRequest: -+ msg = new(globalRequestMsg) -+ case msgRequestSuccess: -+ msg = new(globalRequestSuccessMsg) -+ case msgRequestFailure: -+ msg = new(globalRequestFailureMsg) -+ case msgChannelOpen: -+ msg = new(channelOpenMsg) -+ case msgChannelData: -+ msg = new(channelDataMsg) -+ case msgChannelOpenConfirm: -+ msg = new(channelOpenConfirmMsg) -+ case msgChannelOpenFailure: -+ msg = new(channelOpenFailureMsg) -+ case msgChannelWindowAdjust: -+ msg = new(windowAdjustMsg) -+ case msgChannelEOF: -+ msg = new(channelEOFMsg) -+ case msgChannelClose: -+ msg = new(channelCloseMsg) -+ case msgChannelRequest: -+ msg = new(channelRequestMsg) -+ case msgChannelSuccess: -+ msg = new(channelRequestSuccessMsg) -+ case msgChannelFailure: -+ msg = new(channelRequestFailureMsg) -+ case msgUserAuthGSSAPIToken: -+ msg = new(userAuthGSSAPIToken) -+ case msgUserAuthGSSAPIMIC: -+ msg = new(userAuthGSSAPIMIC) -+ case msgUserAuthGSSAPIErrTok: -+ msg = new(userAuthGSSAPIErrTok) -+ case msgUserAuthGSSAPIError: -+ msg = new(userAuthGSSAPIError) -+ default: -+ return nil, unexpectedMessageError(0, packet[0]) -+ } -+ if err := Unmarshal(packet, msg); err != nil { -+ return nil, err -+ } -+ return msg, nil -+} -+ -+var packetTypeNames = map[byte]string{ -+ msgDisconnect: "disconnectMsg", -+ msgServiceRequest: "serviceRequestMsg", -+ msgServiceAccept: "serviceAcceptMsg", -+ msgExtInfo: "extInfoMsg", -+ msgKexInit: "kexInitMsg", -+ msgKexDHInit: "kexDHInitMsg", -+ msgKexDHReply: "kexDHReplyMsg", -+ msgUserAuthRequest: "userAuthRequestMsg", -+ msgUserAuthSuccess: "userAuthSuccessMsg", -+ msgUserAuthFailure: "userAuthFailureMsg", -+ msgUserAuthPubKeyOk: "userAuthPubKeyOkMsg", -+ msgGlobalRequest: "globalRequestMsg", -+ msgRequestSuccess: "globalRequestSuccessMsg", -+ msgRequestFailure: "globalRequestFailureMsg", -+ msgChannelOpen: "channelOpenMsg", -+ msgChannelData: "channelDataMsg", -+ msgChannelOpenConfirm: "channelOpenConfirmMsg", -+ msgChannelOpenFailure: "channelOpenFailureMsg", -+ msgChannelWindowAdjust: "windowAdjustMsg", -+ msgChannelEOF: "channelEOFMsg", -+ msgChannelClose: "channelCloseMsg", -+ msgChannelRequest: "channelRequestMsg", -+ msgChannelSuccess: "channelRequestSuccessMsg", -+ msgChannelFailure: "channelRequestFailureMsg", -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/messages_test.go b/ms_mod/golang.org/x/crypto/ssh/messages_test.go -new file mode 100644 -index 00000000000000..e79076412ab49f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/messages_test.go -@@ -0,0 +1,288 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "math/big" -+ "math/rand" -+ "reflect" -+ "testing" -+ "testing/quick" -+) -+ -+var intLengthTests = []struct { -+ val, length int -+}{ -+ {0, 4 + 0}, -+ {1, 4 + 1}, -+ {127, 4 + 1}, -+ {128, 4 + 2}, -+ {-1, 4 + 1}, -+} -+ -+func TestIntLength(t *testing.T) { -+ for _, test := range intLengthTests { -+ v := new(big.Int).SetInt64(int64(test.val)) -+ length := intLength(v) -+ if length != test.length { -+ t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) -+ } -+ } -+} -+ -+type msgAllTypes struct { -+ Bool bool `sshtype:"21"` -+ Array [16]byte -+ Uint64 uint64 -+ Uint32 uint32 -+ Uint8 uint8 -+ String string -+ Strings []string -+ Bytes []byte -+ Int *big.Int -+ Rest []byte `ssh:"rest"` -+} -+ -+func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value { -+ m := &msgAllTypes{} -+ m.Bool = rand.Intn(2) == 1 -+ randomBytes(m.Array[:], rand) -+ m.Uint64 = uint64(rand.Int63n(1<<63 - 1)) -+ m.Uint32 = uint32(rand.Intn((1 << 31) - 1)) -+ m.Uint8 = uint8(rand.Intn(1 << 8)) -+ m.String = string(m.Array[:]) -+ m.Strings = randomNameList(rand) -+ m.Bytes = m.Array[:] -+ m.Int = randomInt(rand) -+ m.Rest = m.Array[:] -+ return reflect.ValueOf(m) -+} -+ -+func TestMarshalUnmarshal(t *testing.T) { -+ rand := rand.New(rand.NewSource(0)) -+ iface := &msgAllTypes{} -+ ty := reflect.ValueOf(iface).Type() -+ -+ n := 100 -+ if testing.Short() { -+ n = 5 -+ } -+ for j := 0; j < n; j++ { -+ v, ok := quick.Value(ty, rand) -+ if !ok { -+ t.Errorf("failed to create value") -+ break -+ } -+ -+ m1 := v.Elem().Interface() -+ m2 := iface -+ -+ marshaled := Marshal(m1) -+ if err := Unmarshal(marshaled, m2); err != nil { -+ t.Errorf("Unmarshal %#v: %s", m1, err) -+ break -+ } -+ -+ if !reflect.DeepEqual(v.Interface(), m2) { -+ t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled) -+ break -+ } -+ } -+} -+ -+func TestUnmarshalEmptyPacket(t *testing.T) { -+ var b []byte -+ var m channelRequestSuccessMsg -+ if err := Unmarshal(b, &m); err == nil { -+ t.Fatalf("unmarshal of empty slice succeeded") -+ } -+} -+ -+func TestUnmarshalUnexpectedPacket(t *testing.T) { -+ type S struct { -+ I uint32 `sshtype:"43"` -+ S string -+ B bool -+ } -+ -+ s := S{11, "hello", true} -+ packet := Marshal(s) -+ packet[0] = 42 -+ roundtrip := S{} -+ err := Unmarshal(packet, &roundtrip) -+ if err == nil { -+ t.Fatal("expected error, not nil") -+ } -+} -+ -+func TestMarshalPtr(t *testing.T) { -+ s := struct { -+ S string -+ }{"hello"} -+ -+ m1 := Marshal(s) -+ m2 := Marshal(&s) -+ if !bytes.Equal(m1, m2) { -+ t.Errorf("got %q, want %q for marshaled pointer", m2, m1) -+ } -+} -+ -+func TestBareMarshalUnmarshal(t *testing.T) { -+ type S struct { -+ I uint32 -+ S string -+ B bool -+ } -+ -+ s := S{42, "hello", true} -+ packet := Marshal(s) -+ roundtrip := S{} -+ Unmarshal(packet, &roundtrip) -+ -+ if !reflect.DeepEqual(s, roundtrip) { -+ t.Errorf("got %#v, want %#v", roundtrip, s) -+ } -+} -+ -+func TestBareMarshal(t *testing.T) { -+ type S2 struct { -+ I uint32 -+ } -+ s := S2{42} -+ packet := Marshal(s) -+ i, rest, ok := parseUint32(packet) -+ if len(rest) > 0 || !ok { -+ t.Errorf("parseInt(%q): parse error", packet) -+ } -+ if i != s.I { -+ t.Errorf("got %d, want %d", i, s.I) -+ } -+} -+ -+func TestUnmarshalShortKexInitPacket(t *testing.T) { -+ // This used to panic. -+ // Issue 11348 -+ packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff} -+ kim := &kexInitMsg{} -+ if err := Unmarshal(packet, kim); err == nil { -+ t.Error("truncated packet unmarshaled without error") -+ } -+} -+ -+func TestMarshalMultiTag(t *testing.T) { -+ var res struct { -+ A uint32 `sshtype:"1|2"` -+ } -+ -+ good1 := struct { -+ A uint32 `sshtype:"1"` -+ }{ -+ 1, -+ } -+ good2 := struct { -+ A uint32 `sshtype:"2"` -+ }{ -+ 1, -+ } -+ -+ if e := Unmarshal(Marshal(good1), &res); e != nil { -+ t.Errorf("error unmarshaling multipart tag: %v", e) -+ } -+ -+ if e := Unmarshal(Marshal(good2), &res); e != nil { -+ t.Errorf("error unmarshaling multipart tag: %v", e) -+ } -+ -+ bad1 := struct { -+ A uint32 `sshtype:"3"` -+ }{ -+ 1, -+ } -+ if e := Unmarshal(Marshal(bad1), &res); e == nil { -+ t.Errorf("bad struct unmarshaled without error") -+ } -+} -+ -+func randomBytes(out []byte, rand *rand.Rand) { -+ for i := 0; i < len(out); i++ { -+ out[i] = byte(rand.Int31()) -+ } -+} -+ -+func randomNameList(rand *rand.Rand) []string { -+ ret := make([]string, rand.Int31()&15) -+ for i := range ret { -+ s := make([]byte, 1+(rand.Int31()&15)) -+ for j := range s { -+ s[j] = 'a' + uint8(rand.Int31()&15) -+ } -+ ret[i] = string(s) -+ } -+ return ret -+} -+ -+func randomInt(rand *rand.Rand) *big.Int { -+ return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) -+} -+ -+func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { -+ ki := &kexInitMsg{} -+ randomBytes(ki.Cookie[:], rand) -+ ki.KexAlgos = randomNameList(rand) -+ ki.ServerHostKeyAlgos = randomNameList(rand) -+ ki.CiphersClientServer = randomNameList(rand) -+ ki.CiphersServerClient = randomNameList(rand) -+ ki.MACsClientServer = randomNameList(rand) -+ ki.MACsServerClient = randomNameList(rand) -+ ki.CompressionClientServer = randomNameList(rand) -+ ki.CompressionServerClient = randomNameList(rand) -+ ki.LanguagesClientServer = randomNameList(rand) -+ ki.LanguagesServerClient = randomNameList(rand) -+ if rand.Int31()&1 == 1 { -+ ki.FirstKexFollows = true -+ } -+ return reflect.ValueOf(ki) -+} -+ -+func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { -+ dhi := &kexDHInitMsg{} -+ dhi.X = randomInt(rand) -+ return reflect.ValueOf(dhi) -+} -+ -+var ( -+ _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() -+ _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() -+ -+ _kexInit = Marshal(_kexInitMsg) -+ _kexDHInit = Marshal(_kexDHInitMsg) -+) -+ -+func BenchmarkMarshalKexInitMsg(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ Marshal(_kexInitMsg) -+ } -+} -+ -+func BenchmarkUnmarshalKexInitMsg(b *testing.B) { -+ m := new(kexInitMsg) -+ for i := 0; i < b.N; i++ { -+ Unmarshal(_kexInit, m) -+ } -+} -+ -+func BenchmarkMarshalKexDHInitMsg(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ Marshal(_kexDHInitMsg) -+ } -+} -+ -+func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) { -+ m := new(kexDHInitMsg) -+ for i := 0; i < b.N; i++ { -+ Unmarshal(_kexDHInit, m) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/mux.go b/ms_mod/golang.org/x/crypto/ssh/mux.go -new file mode 100644 -index 00000000000000..9654c01869ad1f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/mux.go -@@ -0,0 +1,351 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "encoding/binary" -+ "fmt" -+ "io" -+ "log" -+ "sync" -+ "sync/atomic" -+) -+ -+// debugMux, if set, causes messages in the connection protocol to be -+// logged. -+const debugMux = false -+ -+// chanList is a thread safe channel list. -+type chanList struct { -+ // protects concurrent access to chans -+ sync.Mutex -+ -+ // chans are indexed by the local id of the channel, which the -+ // other side should send in the PeersId field. -+ chans []*channel -+ -+ // This is a debugging aid: it offsets all IDs by this -+ // amount. This helps distinguish otherwise identical -+ // server/client muxes -+ offset uint32 -+} -+ -+// Assigns a channel ID to the given channel. -+func (c *chanList) add(ch *channel) uint32 { -+ c.Lock() -+ defer c.Unlock() -+ for i := range c.chans { -+ if c.chans[i] == nil { -+ c.chans[i] = ch -+ return uint32(i) + c.offset -+ } -+ } -+ c.chans = append(c.chans, ch) -+ return uint32(len(c.chans)-1) + c.offset -+} -+ -+// getChan returns the channel for the given ID. -+func (c *chanList) getChan(id uint32) *channel { -+ id -= c.offset -+ -+ c.Lock() -+ defer c.Unlock() -+ if id < uint32(len(c.chans)) { -+ return c.chans[id] -+ } -+ return nil -+} -+ -+func (c *chanList) remove(id uint32) { -+ id -= c.offset -+ c.Lock() -+ if id < uint32(len(c.chans)) { -+ c.chans[id] = nil -+ } -+ c.Unlock() -+} -+ -+// dropAll forgets all channels it knows, returning them in a slice. -+func (c *chanList) dropAll() []*channel { -+ c.Lock() -+ defer c.Unlock() -+ var r []*channel -+ -+ for _, ch := range c.chans { -+ if ch == nil { -+ continue -+ } -+ r = append(r, ch) -+ } -+ c.chans = nil -+ return r -+} -+ -+// mux represents the state for the SSH connection protocol, which -+// multiplexes many channels onto a single packet transport. -+type mux struct { -+ conn packetConn -+ chanList chanList -+ -+ incomingChannels chan NewChannel -+ -+ globalSentMu sync.Mutex -+ globalResponses chan interface{} -+ incomingRequests chan *Request -+ -+ errCond *sync.Cond -+ err error -+} -+ -+// When debugging, each new chanList instantiation has a different -+// offset. -+var globalOff uint32 -+ -+func (m *mux) Wait() error { -+ m.errCond.L.Lock() -+ defer m.errCond.L.Unlock() -+ for m.err == nil { -+ m.errCond.Wait() -+ } -+ return m.err -+} -+ -+// newMux returns a mux that runs over the given connection. -+func newMux(p packetConn) *mux { -+ m := &mux{ -+ conn: p, -+ incomingChannels: make(chan NewChannel, chanSize), -+ globalResponses: make(chan interface{}, 1), -+ incomingRequests: make(chan *Request, chanSize), -+ errCond: newCond(), -+ } -+ if debugMux { -+ m.chanList.offset = atomic.AddUint32(&globalOff, 1) -+ } -+ -+ go m.loop() -+ return m -+} -+ -+func (m *mux) sendMessage(msg interface{}) error { -+ p := Marshal(msg) -+ if debugMux { -+ log.Printf("send global(%d): %#v", m.chanList.offset, msg) -+ } -+ return m.conn.writePacket(p) -+} -+ -+func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { -+ if wantReply { -+ m.globalSentMu.Lock() -+ defer m.globalSentMu.Unlock() -+ } -+ -+ if err := m.sendMessage(globalRequestMsg{ -+ Type: name, -+ WantReply: wantReply, -+ Data: payload, -+ }); err != nil { -+ return false, nil, err -+ } -+ -+ if !wantReply { -+ return false, nil, nil -+ } -+ -+ msg, ok := <-m.globalResponses -+ if !ok { -+ return false, nil, io.EOF -+ } -+ switch msg := msg.(type) { -+ case *globalRequestFailureMsg: -+ return false, msg.Data, nil -+ case *globalRequestSuccessMsg: -+ return true, msg.Data, nil -+ default: -+ return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) -+ } -+} -+ -+// ackRequest must be called after processing a global request that -+// has WantReply set. -+func (m *mux) ackRequest(ok bool, data []byte) error { -+ if ok { -+ return m.sendMessage(globalRequestSuccessMsg{Data: data}) -+ } -+ return m.sendMessage(globalRequestFailureMsg{Data: data}) -+} -+ -+func (m *mux) Close() error { -+ return m.conn.Close() -+} -+ -+// loop runs the connection machine. It will process packets until an -+// error is encountered. To synchronize on loop exit, use mux.Wait. -+func (m *mux) loop() { -+ var err error -+ for err == nil { -+ err = m.onePacket() -+ } -+ -+ for _, ch := range m.chanList.dropAll() { -+ ch.close() -+ } -+ -+ close(m.incomingChannels) -+ close(m.incomingRequests) -+ close(m.globalResponses) -+ -+ m.conn.Close() -+ -+ m.errCond.L.Lock() -+ m.err = err -+ m.errCond.Broadcast() -+ m.errCond.L.Unlock() -+ -+ if debugMux { -+ log.Println("loop exit", err) -+ } -+} -+ -+// onePacket reads and processes one packet. -+func (m *mux) onePacket() error { -+ packet, err := m.conn.readPacket() -+ if err != nil { -+ return err -+ } -+ -+ if debugMux { -+ if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { -+ log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) -+ } else { -+ p, _ := decode(packet) -+ log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) -+ } -+ } -+ -+ switch packet[0] { -+ case msgChannelOpen: -+ return m.handleChannelOpen(packet) -+ case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: -+ return m.handleGlobalPacket(packet) -+ } -+ -+ // assume a channel packet. -+ if len(packet) < 5 { -+ return parseError(packet[0]) -+ } -+ id := binary.BigEndian.Uint32(packet[1:]) -+ ch := m.chanList.getChan(id) -+ if ch == nil { -+ return m.handleUnknownChannelPacket(id, packet) -+ } -+ -+ return ch.handlePacket(packet) -+} -+ -+func (m *mux) handleGlobalPacket(packet []byte) error { -+ msg, err := decode(packet) -+ if err != nil { -+ return err -+ } -+ -+ switch msg := msg.(type) { -+ case *globalRequestMsg: -+ m.incomingRequests <- &Request{ -+ Type: msg.Type, -+ WantReply: msg.WantReply, -+ Payload: msg.Data, -+ mux: m, -+ } -+ case *globalRequestSuccessMsg, *globalRequestFailureMsg: -+ m.globalResponses <- msg -+ default: -+ panic(fmt.Sprintf("not a global message %#v", msg)) -+ } -+ -+ return nil -+} -+ -+// handleChannelOpen schedules a channel to be Accept()ed. -+func (m *mux) handleChannelOpen(packet []byte) error { -+ var msg channelOpenMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return err -+ } -+ -+ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { -+ failMsg := channelOpenFailureMsg{ -+ PeersID: msg.PeersID, -+ Reason: ConnectionFailed, -+ Message: "invalid request", -+ Language: "en_US.UTF-8", -+ } -+ return m.sendMessage(failMsg) -+ } -+ -+ c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) -+ c.remoteId = msg.PeersID -+ c.maxRemotePayload = msg.MaxPacketSize -+ c.remoteWin.add(msg.PeersWindow) -+ m.incomingChannels <- c -+ return nil -+} -+ -+func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { -+ ch, err := m.openChannel(chanType, extra) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ return ch, ch.incomingRequests, nil -+} -+ -+func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { -+ ch := m.newChannel(chanType, channelOutbound, extra) -+ -+ ch.maxIncomingPayload = channelMaxPacket -+ -+ open := channelOpenMsg{ -+ ChanType: chanType, -+ PeersWindow: ch.myWindow, -+ MaxPacketSize: ch.maxIncomingPayload, -+ TypeSpecificData: extra, -+ PeersID: ch.localId, -+ } -+ if err := m.sendMessage(open); err != nil { -+ return nil, err -+ } -+ -+ switch msg := (<-ch.msg).(type) { -+ case *channelOpenConfirmMsg: -+ return ch, nil -+ case *channelOpenFailureMsg: -+ return nil, &OpenChannelError{msg.Reason, msg.Message} -+ default: -+ return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) -+ } -+} -+ -+func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) error { -+ msg, err := decode(packet) -+ if err != nil { -+ return err -+ } -+ -+ switch msg := msg.(type) { -+ // RFC 4254 section 5.4 says unrecognized channel requests should -+ // receive a failure response. -+ case *channelRequestMsg: -+ if msg.WantReply { -+ return m.sendMessage(channelRequestFailureMsg{ -+ PeersID: msg.PeersID, -+ }) -+ } -+ return nil -+ default: -+ return fmt.Errorf("ssh: invalid channel %d", id) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/mux_test.go b/ms_mod/golang.org/x/crypto/ssh/mux_test.go -new file mode 100644 -index 00000000000000..1db3be54a0318f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/mux_test.go -@@ -0,0 +1,761 @@ -+// Copyright 2013 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "errors" -+ "fmt" -+ "io" -+ "sync" -+ "testing" -+ "time" -+) -+ -+func muxPair() (*mux, *mux) { -+ a, b := memPipe() -+ -+ s := newMux(a) -+ c := newMux(b) -+ -+ return s, c -+} -+ -+// Returns both ends of a channel, and the mux for the 2nd -+// channel. -+func channelPair(t *testing.T) (*channel, *channel, *mux) { -+ c, s := muxPair() -+ -+ res := make(chan *channel, 1) -+ go func() { -+ newCh, ok := <-s.incomingChannels -+ if !ok { -+ t.Error("no incoming channel") -+ close(res) -+ return -+ } -+ if newCh.ChannelType() != "chan" { -+ t.Errorf("got type %q want chan", newCh.ChannelType()) -+ newCh.Reject(Prohibited, fmt.Sprintf("got type %q want chan", newCh.ChannelType())) -+ close(res) -+ return -+ } -+ ch, _, err := newCh.Accept() -+ if err != nil { -+ t.Errorf("accept: %v", err) -+ close(res) -+ return -+ } -+ res <- ch.(*channel) -+ }() -+ -+ ch, err := c.openChannel("chan", nil) -+ if err != nil { -+ t.Fatalf("OpenChannel: %v", err) -+ } -+ w := <-res -+ if w == nil { -+ t.Fatal("unable to get write channel") -+ } -+ -+ return w, ch, c -+} -+ -+// Test that stderr and stdout can be addressed from different -+// goroutines. This is intended for use with the race detector. -+func TestMuxChannelExtendedThreadSafety(t *testing.T) { -+ writer, reader, mux := channelPair(t) -+ defer writer.Close() -+ defer reader.Close() -+ defer mux.Close() -+ -+ var wr, rd sync.WaitGroup -+ magic := "hello world" -+ -+ wr.Add(2) -+ go func() { -+ io.WriteString(writer, magic) -+ wr.Done() -+ }() -+ go func() { -+ io.WriteString(writer.Stderr(), magic) -+ wr.Done() -+ }() -+ -+ rd.Add(2) -+ go func() { -+ c, err := io.ReadAll(reader) -+ if string(c) != magic { -+ t.Errorf("stdout read got %q, want %q (error %s)", c, magic, err) -+ } -+ rd.Done() -+ }() -+ go func() { -+ c, err := io.ReadAll(reader.Stderr()) -+ if string(c) != magic { -+ t.Errorf("stderr read got %q, want %q (error %s)", c, magic, err) -+ } -+ rd.Done() -+ }() -+ -+ wr.Wait() -+ writer.CloseWrite() -+ rd.Wait() -+} -+ -+func TestMuxReadWrite(t *testing.T) { -+ s, c, mux := channelPair(t) -+ defer s.Close() -+ defer c.Close() -+ defer mux.Close() -+ -+ magic := "hello world" -+ magicExt := "hello stderr" -+ go func() { -+ _, err := s.Write([]byte(magic)) -+ if err != nil { -+ t.Errorf("Write: %v", err) -+ return -+ } -+ _, err = s.Extended(1).Write([]byte(magicExt)) -+ if err != nil { -+ t.Errorf("Write: %v", err) -+ return -+ } -+ }() -+ -+ var buf [1024]byte -+ n, err := c.Read(buf[:]) -+ if err != nil { -+ t.Fatalf("server Read: %v", err) -+ } -+ got := string(buf[:n]) -+ if got != magic { -+ t.Fatalf("server: got %q want %q", got, magic) -+ } -+ -+ n, err = c.Extended(1).Read(buf[:]) -+ if err != nil { -+ t.Fatalf("server Read: %v", err) -+ } -+ -+ got = string(buf[:n]) -+ if got != magicExt { -+ t.Fatalf("server: got %q want %q", got, magic) -+ } -+} -+ -+func TestMuxChannelOverflow(t *testing.T) { -+ reader, writer, mux := channelPair(t) -+ defer reader.Close() -+ defer writer.Close() -+ defer mux.Close() -+ -+ wDone := make(chan int, 1) -+ go func() { -+ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { -+ t.Errorf("could not fill window: %v", err) -+ } -+ writer.Write(make([]byte, 1)) -+ wDone <- 1 -+ }() -+ writer.remoteWin.waitWriterBlocked() -+ -+ // Send 1 byte. -+ packet := make([]byte, 1+4+4+1) -+ packet[0] = msgChannelData -+ marshalUint32(packet[1:], writer.remoteId) -+ marshalUint32(packet[5:], uint32(1)) -+ packet[9] = 42 -+ -+ if err := writer.mux.conn.writePacket(packet); err != nil { -+ t.Errorf("could not send packet") -+ } -+ if _, err := reader.SendRequest("hello", true, nil); err == nil { -+ t.Errorf("SendRequest succeeded.") -+ } -+ <-wDone -+} -+ -+func TestMuxChannelCloseWriteUnblock(t *testing.T) { -+ reader, writer, mux := channelPair(t) -+ defer reader.Close() -+ defer writer.Close() -+ defer mux.Close() -+ -+ wDone := make(chan int, 1) -+ go func() { -+ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { -+ t.Errorf("could not fill window: %v", err) -+ } -+ if _, err := writer.Write(make([]byte, 1)); err != io.EOF { -+ t.Errorf("got %v, want EOF for unblock write", err) -+ } -+ wDone <- 1 -+ }() -+ -+ writer.remoteWin.waitWriterBlocked() -+ reader.Close() -+ <-wDone -+} -+ -+func TestMuxConnectionCloseWriteUnblock(t *testing.T) { -+ reader, writer, mux := channelPair(t) -+ defer reader.Close() -+ defer writer.Close() -+ defer mux.Close() -+ -+ wDone := make(chan int, 1) -+ go func() { -+ if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { -+ t.Errorf("could not fill window: %v", err) -+ } -+ if _, err := writer.Write(make([]byte, 1)); err != io.EOF { -+ t.Errorf("got %v, want EOF for unblock write", err) -+ } -+ wDone <- 1 -+ }() -+ -+ writer.remoteWin.waitWriterBlocked() -+ mux.Close() -+ <-wDone -+} -+ -+func TestMuxReject(t *testing.T) { -+ client, server := muxPair() -+ defer server.Close() -+ defer client.Close() -+ -+ go func() { -+ ch, ok := <-server.incomingChannels -+ if !ok { -+ t.Error("cannot accept channel") -+ return -+ } -+ if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" { -+ t.Errorf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) -+ ch.Reject(RejectionReason(UnknownChannelType), UnknownChannelType.String()) -+ return -+ } -+ ch.Reject(RejectionReason(42), "message") -+ }() -+ -+ ch, err := client.openChannel("ch", []byte("extra")) -+ if ch != nil { -+ t.Fatal("openChannel not rejected") -+ } -+ -+ ocf, ok := err.(*OpenChannelError) -+ if !ok { -+ t.Errorf("got %#v want *OpenChannelError", err) -+ } else if ocf.Reason != 42 || ocf.Message != "message" { -+ t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message") -+ } -+ -+ want := "ssh: rejected: unknown reason 42 (message)" -+ if err.Error() != want { -+ t.Errorf("got %q, want %q", err.Error(), want) -+ } -+} -+ -+func TestMuxChannelRequest(t *testing.T) { -+ client, server, mux := channelPair(t) -+ defer server.Close() -+ defer client.Close() -+ defer mux.Close() -+ -+ var received int -+ var wg sync.WaitGroup -+ wg.Add(1) -+ go func() { -+ for r := range server.incomingRequests { -+ received++ -+ r.Reply(r.Type == "yes", nil) -+ } -+ wg.Done() -+ }() -+ _, err := client.SendRequest("yes", false, nil) -+ if err != nil { -+ t.Fatalf("SendRequest: %v", err) -+ } -+ ok, err := client.SendRequest("yes", true, nil) -+ if err != nil { -+ t.Fatalf("SendRequest: %v", err) -+ } -+ -+ if !ok { -+ t.Errorf("SendRequest(yes): %v", ok) -+ -+ } -+ -+ ok, err = client.SendRequest("no", true, nil) -+ if err != nil { -+ t.Fatalf("SendRequest: %v", err) -+ } -+ if ok { -+ t.Errorf("SendRequest(no): %v", ok) -+ -+ } -+ -+ client.Close() -+ wg.Wait() -+ -+ if received != 3 { -+ t.Errorf("got %d requests, want %d", received, 3) -+ } -+} -+ -+func TestMuxUnknownChannelRequests(t *testing.T) { -+ clientPipe, serverPipe := memPipe() -+ client := newMux(clientPipe) -+ defer serverPipe.Close() -+ defer client.Close() -+ -+ kDone := make(chan error, 1) -+ go func() { -+ // Ignore unknown channel messages that don't want a reply. -+ err := serverPipe.writePacket(Marshal(channelRequestMsg{ -+ PeersID: 1, -+ Request: "keepalive@openssh.com", -+ WantReply: false, -+ RequestSpecificData: []byte{}, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("send: %w", err) -+ return -+ } -+ -+ // Send a keepalive, which should get a channel failure message -+ // in response. -+ err = serverPipe.writePacket(Marshal(channelRequestMsg{ -+ PeersID: 2, -+ Request: "keepalive@openssh.com", -+ WantReply: true, -+ RequestSpecificData: []byte{}, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("send: %w", err) -+ return -+ } -+ -+ packet, err := serverPipe.readPacket() -+ if err != nil { -+ kDone <- fmt.Errorf("read packet: %w", err) -+ return -+ } -+ decoded, err := decode(packet) -+ if err != nil { -+ kDone <- fmt.Errorf("decode failed: %w", err) -+ return -+ } -+ -+ switch msg := decoded.(type) { -+ case *channelRequestFailureMsg: -+ if msg.PeersID != 2 { -+ kDone <- fmt.Errorf("received response to wrong message: %v", msg) -+ return -+ -+ } -+ default: -+ kDone <- fmt.Errorf("unexpected channel message: %v", msg) -+ return -+ } -+ -+ kDone <- nil -+ -+ // Receive and respond to the keepalive to confirm the mux is -+ // still processing requests. -+ packet, err = serverPipe.readPacket() -+ if err != nil { -+ kDone <- fmt.Errorf("read packet: %w", err) -+ return -+ } -+ if packet[0] != msgGlobalRequest { -+ kDone <- errors.New("expected global request") -+ return -+ } -+ -+ err = serverPipe.writePacket(Marshal(globalRequestFailureMsg{ -+ Data: []byte{}, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("failed to send failure msg: %w", err) -+ return -+ } -+ -+ close(kDone) -+ }() -+ -+ // Wait for the server to send the keepalive message and receive back a -+ // response. -+ select { -+ case err := <-kDone: -+ if err != nil { -+ t.Fatal(err) -+ } -+ case <-time.After(10 * time.Second): -+ t.Fatalf("server never received ack") -+ } -+ -+ // Confirm client hasn't closed. -+ if _, _, err := client.SendRequest("keepalive@golang.org", true, nil); err != nil { -+ t.Fatalf("failed to send keepalive: %v", err) -+ } -+ -+ select { -+ case err := <-kDone: -+ if err != nil { -+ t.Fatal(err) -+ } -+ case <-time.After(10 * time.Second): -+ t.Fatalf("server never shut down") -+ } -+} -+ -+func TestMuxClosedChannel(t *testing.T) { -+ clientPipe, serverPipe := memPipe() -+ client := newMux(clientPipe) -+ defer serverPipe.Close() -+ defer client.Close() -+ -+ kDone := make(chan error, 1) -+ go func() { -+ // Open the channel. -+ packet, err := serverPipe.readPacket() -+ if err != nil { -+ kDone <- fmt.Errorf("read packet: %w", err) -+ return -+ } -+ if packet[0] != msgChannelOpen { -+ kDone <- errors.New("expected chan open") -+ return -+ } -+ -+ var openMsg channelOpenMsg -+ if err := Unmarshal(packet, &openMsg); err != nil { -+ kDone <- fmt.Errorf("unmarshal: %w", err) -+ return -+ } -+ -+ // Send back the opened channel confirmation. -+ err = serverPipe.writePacket(Marshal(channelOpenConfirmMsg{ -+ PeersID: openMsg.PeersID, -+ MyID: 0, -+ MyWindow: 0, -+ MaxPacketSize: channelMaxPacket, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("send: %w", err) -+ return -+ } -+ -+ // Close the channel. -+ err = serverPipe.writePacket(Marshal(channelCloseMsg{ -+ PeersID: openMsg.PeersID, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("send: %w", err) -+ return -+ } -+ -+ // Send a keepalive message on the channel we just closed. -+ err = serverPipe.writePacket(Marshal(channelRequestMsg{ -+ PeersID: openMsg.PeersID, -+ Request: "keepalive@openssh.com", -+ WantReply: true, -+ RequestSpecificData: []byte{}, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("send: %w", err) -+ return -+ } -+ -+ // Receive the channel closed response. -+ packet, err = serverPipe.readPacket() -+ if err != nil { -+ kDone <- fmt.Errorf("read packet: %w", err) -+ return -+ } -+ if packet[0] != msgChannelClose { -+ kDone <- errors.New("expected channel close") -+ return -+ } -+ -+ // Receive the keepalive response failure. -+ packet, err = serverPipe.readPacket() -+ if err != nil { -+ kDone <- fmt.Errorf("read packet: %w", err) -+ return -+ } -+ if packet[0] != msgChannelFailure { -+ kDone <- errors.New("expected channel failure") -+ return -+ } -+ kDone <- nil -+ -+ // Receive and respond to the keepalive to confirm the mux is -+ // still processing requests. -+ packet, err = serverPipe.readPacket() -+ if err != nil { -+ kDone <- fmt.Errorf("read packet: %w", err) -+ return -+ } -+ if packet[0] != msgGlobalRequest { -+ kDone <- errors.New("expected global request") -+ return -+ } -+ -+ err = serverPipe.writePacket(Marshal(globalRequestFailureMsg{ -+ Data: []byte{}, -+ })) -+ if err != nil { -+ kDone <- fmt.Errorf("failed to send failure msg: %w", err) -+ return -+ } -+ -+ close(kDone) -+ }() -+ -+ // Open a channel. -+ ch, err := client.openChannel("chan", nil) -+ if err != nil { -+ t.Fatalf("OpenChannel: %v", err) -+ } -+ defer ch.Close() -+ -+ // Wait for the server to close the channel and send the keepalive. -+ select { -+ case <-kDone: -+ case <-time.After(10 * time.Second): -+ t.Fatalf("server never received ack") -+ } -+ -+ // Make sure the channel closed. -+ if _, ok := <-ch.incomingRequests; ok { -+ t.Fatalf("channel not closed") -+ } -+ -+ // Confirm client hasn't closed -+ if _, _, err := client.SendRequest("keepalive@golang.org", true, nil); err != nil { -+ t.Fatalf("failed to send keepalive: %v", err) -+ } -+ -+ select { -+ case <-kDone: -+ case <-time.After(10 * time.Second): -+ t.Fatalf("server never shut down") -+ } -+} -+ -+func TestMuxGlobalRequest(t *testing.T) { -+ clientMux, serverMux := muxPair() -+ defer serverMux.Close() -+ defer clientMux.Close() -+ -+ var seen bool -+ go func() { -+ for r := range serverMux.incomingRequests { -+ seen = seen || r.Type == "peek" -+ if r.WantReply { -+ err := r.Reply(r.Type == "yes", -+ append([]byte(r.Type), r.Payload...)) -+ if err != nil { -+ t.Errorf("AckRequest: %v", err) -+ } -+ } -+ } -+ }() -+ -+ _, _, err := clientMux.SendRequest("peek", false, nil) -+ if err != nil { -+ t.Errorf("SendRequest: %v", err) -+ } -+ -+ ok, data, err := clientMux.SendRequest("yes", true, []byte("a")) -+ if !ok || string(data) != "yesa" || err != nil { -+ t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", -+ ok, data, err) -+ } -+ if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil { -+ t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", -+ ok, data, err) -+ } -+ -+ if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil { -+ t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v", -+ ok, data, err) -+ } -+ -+ if !seen { -+ t.Errorf("never saw 'peek' request") -+ } -+} -+ -+func TestMuxGlobalRequestUnblock(t *testing.T) { -+ clientMux, serverMux := muxPair() -+ defer serverMux.Close() -+ defer clientMux.Close() -+ -+ result := make(chan error, 1) -+ go func() { -+ _, _, err := clientMux.SendRequest("hello", true, nil) -+ result <- err -+ }() -+ -+ <-serverMux.incomingRequests -+ serverMux.conn.Close() -+ err := <-result -+ -+ if err != io.EOF { -+ t.Errorf("want EOF, got %v", io.EOF) -+ } -+} -+ -+func TestMuxChannelRequestUnblock(t *testing.T) { -+ a, b, connB := channelPair(t) -+ defer a.Close() -+ defer b.Close() -+ defer connB.Close() -+ -+ result := make(chan error, 1) -+ go func() { -+ _, err := a.SendRequest("hello", true, nil) -+ result <- err -+ }() -+ -+ <-b.incomingRequests -+ connB.conn.Close() -+ err := <-result -+ -+ if err != io.EOF { -+ t.Errorf("want EOF, got %v", err) -+ } -+} -+ -+func TestMuxCloseChannel(t *testing.T) { -+ r, w, mux := channelPair(t) -+ defer mux.Close() -+ defer r.Close() -+ defer w.Close() -+ -+ result := make(chan error, 1) -+ go func() { -+ var b [1024]byte -+ _, err := r.Read(b[:]) -+ result <- err -+ }() -+ if err := w.Close(); err != nil { -+ t.Errorf("w.Close: %v", err) -+ } -+ -+ if _, err := w.Write([]byte("hello")); err != io.EOF { -+ t.Errorf("got err %v, want io.EOF after Close", err) -+ } -+ -+ if err := <-result; err != io.EOF { -+ t.Errorf("got %v (%T), want io.EOF", err, err) -+ } -+} -+ -+func TestMuxCloseWriteChannel(t *testing.T) { -+ r, w, mux := channelPair(t) -+ defer mux.Close() -+ -+ result := make(chan error, 1) -+ go func() { -+ var b [1024]byte -+ _, err := r.Read(b[:]) -+ result <- err -+ }() -+ if err := w.CloseWrite(); err != nil { -+ t.Errorf("w.CloseWrite: %v", err) -+ } -+ -+ if _, err := w.Write([]byte("hello")); err != io.EOF { -+ t.Errorf("got err %v, want io.EOF after CloseWrite", err) -+ } -+ -+ if err := <-result; err != io.EOF { -+ t.Errorf("got %v (%T), want io.EOF", err, err) -+ } -+} -+ -+func TestMuxInvalidRecord(t *testing.T) { -+ a, b := muxPair() -+ defer a.Close() -+ defer b.Close() -+ -+ packet := make([]byte, 1+4+4+1) -+ packet[0] = msgChannelData -+ marshalUint32(packet[1:], 29348723 /* invalid channel id */) -+ marshalUint32(packet[5:], 1) -+ packet[9] = 42 -+ -+ a.conn.writePacket(packet) -+ go a.SendRequest("hello", false, nil) -+ // 'a' wrote an invalid packet, so 'b' has exited. -+ req, ok := <-b.incomingRequests -+ if ok { -+ t.Errorf("got request %#v after receiving invalid packet", req) -+ } -+} -+ -+func TestZeroWindowAdjust(t *testing.T) { -+ a, b, mux := channelPair(t) -+ defer a.Close() -+ defer b.Close() -+ defer mux.Close() -+ -+ go func() { -+ io.WriteString(a, "hello") -+ // bogus adjust. -+ a.sendMessage(windowAdjustMsg{}) -+ io.WriteString(a, "world") -+ a.Close() -+ }() -+ -+ want := "helloworld" -+ c, _ := io.ReadAll(b) -+ if string(c) != want { -+ t.Errorf("got %q want %q", c, want) -+ } -+} -+ -+func TestMuxMaxPacketSize(t *testing.T) { -+ a, b, mux := channelPair(t) -+ defer a.Close() -+ defer b.Close() -+ defer mux.Close() -+ -+ large := make([]byte, a.maxRemotePayload+1) -+ packet := make([]byte, 1+4+4+1+len(large)) -+ packet[0] = msgChannelData -+ marshalUint32(packet[1:], a.remoteId) -+ marshalUint32(packet[5:], uint32(len(large))) -+ packet[9] = 42 -+ -+ if err := a.mux.conn.writePacket(packet); err != nil { -+ t.Errorf("could not send packet") -+ } -+ -+ go a.SendRequest("hello", false, nil) -+ -+ _, ok := <-b.incomingRequests -+ if ok { -+ t.Errorf("connection still alive after receiving large packet.") -+ } -+} -+ -+// Don't ship code with debug=true. -+func TestDebug(t *testing.T) { -+ if debugMux { -+ t.Error("mux debug switched on") -+ } -+ if debugHandshake { -+ t.Error("handshake debug switched on") -+ } -+ if debugTransport { -+ t.Error("transport debug switched on") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/server.go b/ms_mod/golang.org/x/crypto/ssh/server.go -new file mode 100644 -index 00000000000000..b21322affa8a7a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/server.go -@@ -0,0 +1,774 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "io" -+ "net" -+ "strings" -+) -+ -+// The Permissions type holds fine-grained permissions that are -+// specific to a user or a specific authentication method for a user. -+// The Permissions value for a successful authentication attempt is -+// available in ServerConn, so it can be used to pass information from -+// the user-authentication phase to the application layer. -+type Permissions struct { -+ // CriticalOptions indicate restrictions to the default -+ // permissions, and are typically used in conjunction with -+ // user certificates. The standard for SSH certificates -+ // defines "force-command" (only allow the given command to -+ // execute) and "source-address" (only allow connections from -+ // the given address). The SSH package currently only enforces -+ // the "source-address" critical option. It is up to server -+ // implementations to enforce other critical options, such as -+ // "force-command", by checking them after the SSH handshake -+ // is successful. In general, SSH servers should reject -+ // connections that specify critical options that are unknown -+ // or not supported. -+ CriticalOptions map[string]string -+ -+ // Extensions are extra functionality that the server may -+ // offer on authenticated connections. Lack of support for an -+ // extension does not preclude authenticating a user. Common -+ // extensions are "permit-agent-forwarding", -+ // "permit-X11-forwarding". The Go SSH library currently does -+ // not act on any extension, and it is up to server -+ // implementations to honor them. Extensions can be used to -+ // pass data from the authentication callbacks to the server -+ // application layer. -+ Extensions map[string]string -+} -+ -+type GSSAPIWithMICConfig struct { -+ // AllowLogin, must be set, is called when gssapi-with-mic -+ // authentication is selected (RFC 4462 section 3). The srcName is from the -+ // results of the GSS-API authentication. The format is username@DOMAIN. -+ // GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions. -+ // This callback is called after the user identity is established with GSSAPI to decide if the user can login with -+ // which permissions. If the user is allowed to login, it should return a nil error. -+ AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error) -+ -+ // Server must be set. It's the implementation -+ // of the GSSAPIServer interface. See GSSAPIServer interface for details. -+ Server GSSAPIServer -+} -+ -+// ServerConfig holds server specific configuration data. -+type ServerConfig struct { -+ // Config contains configuration shared between client and server. -+ Config -+ -+ hostKeys []Signer -+ -+ // NoClientAuth is true if clients are allowed to connect without -+ // authenticating. -+ // To determine NoClientAuth at runtime, set NoClientAuth to true -+ // and the optional NoClientAuthCallback to a non-nil value. -+ NoClientAuth bool -+ -+ // NoClientAuthCallback, if non-nil, is called when a user -+ // attempts to authenticate with auth method "none". -+ // NoClientAuth must also be set to true for this be used, or -+ // this func is unused. -+ NoClientAuthCallback func(ConnMetadata) (*Permissions, error) -+ -+ // MaxAuthTries specifies the maximum number of authentication attempts -+ // permitted per connection. If set to a negative number, the number of -+ // attempts are unlimited. If set to zero, the number of attempts are limited -+ // to 6. -+ MaxAuthTries int -+ -+ // PasswordCallback, if non-nil, is called when a user -+ // attempts to authenticate using a password. -+ PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) -+ -+ // PublicKeyCallback, if non-nil, is called when a client -+ // offers a public key for authentication. It must return a nil error -+ // if the given public key can be used to authenticate the -+ // given user. For example, see CertChecker.Authenticate. A -+ // call to this function does not guarantee that the key -+ // offered is in fact used to authenticate. To record any data -+ // depending on the public key, store it inside a -+ // Permissions.Extensions entry. -+ PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) -+ -+ // KeyboardInteractiveCallback, if non-nil, is called when -+ // keyboard-interactive authentication is selected (RFC -+ // 4256). The client object's Challenge function should be -+ // used to query the user. The callback may offer multiple -+ // Challenge rounds. To avoid information leaks, the client -+ // should be presented a challenge even if the user is -+ // unknown. -+ KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) -+ -+ // AuthLogCallback, if non-nil, is called to log all authentication -+ // attempts. -+ AuthLogCallback func(conn ConnMetadata, method string, err error) -+ -+ // ServerVersion is the version identification string to announce in -+ // the public handshake. -+ // If empty, a reasonable default is used. -+ // Note that RFC 4253 section 4.2 requires that this string start with -+ // "SSH-2.0-". -+ ServerVersion string -+ -+ // BannerCallback, if present, is called and the return string is sent to -+ // the client after key exchange completed but before authentication. -+ BannerCallback func(conn ConnMetadata) string -+ -+ // GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used -+ // when gssapi-with-mic authentication is selected (RFC 4462 section 3). -+ GSSAPIWithMICConfig *GSSAPIWithMICConfig -+} -+ -+// AddHostKey adds a private key as a host key. If an existing host -+// key exists with the same public key format, it is replaced. Each server -+// config must have at least one host key. -+func (s *ServerConfig) AddHostKey(key Signer) { -+ for i, k := range s.hostKeys { -+ if k.PublicKey().Type() == key.PublicKey().Type() { -+ s.hostKeys[i] = key -+ return -+ } -+ } -+ -+ s.hostKeys = append(s.hostKeys, key) -+} -+ -+// cachedPubKey contains the results of querying whether a public key is -+// acceptable for a user. -+type cachedPubKey struct { -+ user string -+ pubKeyData []byte -+ result error -+ perms *Permissions -+} -+ -+const maxCachedPubKeys = 16 -+ -+// pubKeyCache caches tests for public keys. Since SSH clients -+// will query whether a public key is acceptable before attempting to -+// authenticate with it, we end up with duplicate queries for public -+// key validity. The cache only applies to a single ServerConn. -+type pubKeyCache struct { -+ keys []cachedPubKey -+} -+ -+// get returns the result for a given user/algo/key tuple. -+func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { -+ for _, k := range c.keys { -+ if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) { -+ return k, true -+ } -+ } -+ return cachedPubKey{}, false -+} -+ -+// add adds the given tuple to the cache. -+func (c *pubKeyCache) add(candidate cachedPubKey) { -+ if len(c.keys) < maxCachedPubKeys { -+ c.keys = append(c.keys, candidate) -+ } -+} -+ -+// ServerConn is an authenticated SSH connection, as seen from the -+// server -+type ServerConn struct { -+ Conn -+ -+ // If the succeeding authentication callback returned a -+ // non-nil Permissions pointer, it is stored here. -+ Permissions *Permissions -+} -+ -+// NewServerConn starts a new SSH server with c as the underlying -+// transport. It starts with a handshake and, if the handshake is -+// unsuccessful, it closes the connection and returns an error. The -+// Request and NewChannel channels must be serviced, or the connection -+// will hang. -+// -+// The returned error may be of type *ServerAuthError for -+// authentication errors. -+func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { -+ fullConf := *config -+ fullConf.SetDefaults() -+ if fullConf.MaxAuthTries == 0 { -+ fullConf.MaxAuthTries = 6 -+ } -+ // Check if the config contains any unsupported key exchanges -+ for _, kex := range fullConf.KeyExchanges { -+ if _, ok := serverForbiddenKexAlgos[kex]; ok { -+ return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex) -+ } -+ } -+ -+ s := &connection{ -+ sshConn: sshConn{conn: c}, -+ } -+ perms, err := s.serverHandshake(&fullConf) -+ if err != nil { -+ c.Close() -+ return nil, nil, nil, err -+ } -+ return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil -+} -+ -+// signAndMarshal signs the data with the appropriate algorithm, -+// and serializes the result in SSH wire format. algo is the negotiate -+// algorithm and may be a certificate type. -+func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) { -+ sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo)) -+ if err != nil { -+ return nil, err -+ } -+ -+ return Marshal(sig), nil -+} -+ -+// handshake performs key exchange and user authentication. -+func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) { -+ if len(config.hostKeys) == 0 { -+ return nil, errors.New("ssh: server has no host keys") -+ } -+ -+ if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && -+ config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil || -+ config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) { -+ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") -+ } -+ -+ if config.ServerVersion != "" { -+ s.serverVersion = []byte(config.ServerVersion) -+ } else { -+ s.serverVersion = []byte(packageVersion) -+ } -+ var err error -+ s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) -+ if err != nil { -+ return nil, err -+ } -+ -+ tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */) -+ s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config) -+ -+ if err := s.transport.waitSession(); err != nil { -+ return nil, err -+ } -+ -+ // We just did the key change, so the session ID is established. -+ s.sessionID = s.transport.getSessionID() -+ -+ var packet []byte -+ if packet, err = s.transport.readPacket(); err != nil { -+ return nil, err -+ } -+ -+ var serviceRequest serviceRequestMsg -+ if err = Unmarshal(packet, &serviceRequest); err != nil { -+ return nil, err -+ } -+ if serviceRequest.Service != serviceUserAuth { -+ return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating") -+ } -+ serviceAccept := serviceAcceptMsg{ -+ Service: serviceUserAuth, -+ } -+ if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil { -+ return nil, err -+ } -+ -+ perms, err := s.serverAuthenticate(config) -+ if err != nil { -+ return nil, err -+ } -+ s.mux = newMux(s.transport) -+ return perms, err -+} -+ -+func checkSourceAddress(addr net.Addr, sourceAddrs string) error { -+ if addr == nil { -+ return errors.New("ssh: no address known for client, but source-address match required") -+ } -+ -+ tcpAddr, ok := addr.(*net.TCPAddr) -+ if !ok { -+ return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) -+ } -+ -+ for _, sourceAddr := range strings.Split(sourceAddrs, ",") { -+ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { -+ if allowedIP.Equal(tcpAddr.IP) { -+ return nil -+ } -+ } else { -+ _, ipNet, err := net.ParseCIDR(sourceAddr) -+ if err != nil { -+ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) -+ } -+ -+ if ipNet.Contains(tcpAddr.IP) { -+ return nil -+ } -+ } -+ } -+ -+ return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) -+} -+ -+func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection, -+ sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) { -+ gssAPIServer := gssapiConfig.Server -+ defer gssAPIServer.DeleteSecContext() -+ var srcName string -+ for { -+ var ( -+ outToken []byte -+ needContinue bool -+ ) -+ outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken) -+ if err != nil { -+ return err, nil, nil -+ } -+ if len(outToken) != 0 { -+ if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{ -+ Token: outToken, -+ })); err != nil { -+ return nil, nil, err -+ } -+ } -+ if !needContinue { -+ break -+ } -+ packet, err := s.transport.readPacket() -+ if err != nil { -+ return nil, nil, err -+ } -+ userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} -+ if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { -+ return nil, nil, err -+ } -+ } -+ packet, err := s.transport.readPacket() -+ if err != nil { -+ return nil, nil, err -+ } -+ userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{} -+ if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil { -+ return nil, nil, err -+ } -+ mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method) -+ if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil { -+ return err, nil, nil -+ } -+ perms, authErr = gssapiConfig.AllowLogin(s, srcName) -+ return authErr, perms, nil -+} -+ -+// isAlgoCompatible checks if the signature format is compatible with the -+// selected algorithm taking into account edge cases that occur with old -+// clients. -+func isAlgoCompatible(algo, sigFormat string) bool { -+ // Compatibility for old clients. -+ // -+ // For certificate authentication with OpenSSH 7.2-7.7 signature format can -+ // be rsa-sha2-256 or rsa-sha2-512 for the algorithm -+ // ssh-rsa-cert-v01@openssh.com. -+ // -+ // With gpg-agent < 2.2.6 the algorithm can be rsa-sha2-256 or rsa-sha2-512 -+ // for signature format ssh-rsa. -+ if isRSA(algo) && isRSA(sigFormat) { -+ return true -+ } -+ // Standard case: the underlying algorithm must match the signature format. -+ return underlyingAlgo(algo) == sigFormat -+} -+ -+// ServerAuthError represents server authentication errors and is -+// sometimes returned by NewServerConn. It appends any authentication -+// errors that may occur, and is returned if all of the authentication -+// methods provided by the user failed to authenticate. -+type ServerAuthError struct { -+ // Errors contains authentication errors returned by the authentication -+ // callback methods. The first entry is typically ErrNoAuth. -+ Errors []error -+} -+ -+func (l ServerAuthError) Error() string { -+ var errs []string -+ for _, err := range l.Errors { -+ errs = append(errs, err.Error()) -+ } -+ return "[" + strings.Join(errs, ", ") + "]" -+} -+ -+// ErrNoAuth is the error value returned if no -+// authentication method has been passed yet. This happens as a normal -+// part of the authentication loop, since the client first tries -+// 'none' authentication to discover available methods. -+// It is returned in ServerAuthError.Errors from NewServerConn. -+var ErrNoAuth = errors.New("ssh: no auth passed yet") -+ -+func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { -+ sessionID := s.transport.getSessionID() -+ var cache pubKeyCache -+ var perms *Permissions -+ -+ authFailures := 0 -+ var authErrs []error -+ var displayedBanner bool -+ -+userAuthLoop: -+ for { -+ if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 { -+ discMsg := &disconnectMsg{ -+ Reason: 2, -+ Message: "too many authentication failures", -+ } -+ -+ if err := s.transport.writePacket(Marshal(discMsg)); err != nil { -+ return nil, err -+ } -+ -+ return nil, discMsg -+ } -+ -+ var userAuthReq userAuthRequestMsg -+ if packet, err := s.transport.readPacket(); err != nil { -+ if err == io.EOF { -+ return nil, &ServerAuthError{Errors: authErrs} -+ } -+ return nil, err -+ } else if err = Unmarshal(packet, &userAuthReq); err != nil { -+ return nil, err -+ } -+ -+ if userAuthReq.Service != serviceSSH { -+ return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) -+ } -+ -+ s.user = userAuthReq.User -+ -+ if !displayedBanner && config.BannerCallback != nil { -+ displayedBanner = true -+ msg := config.BannerCallback(s) -+ if msg != "" { -+ bannerMsg := &userAuthBannerMsg{ -+ Message: msg, -+ } -+ if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { -+ return nil, err -+ } -+ } -+ } -+ -+ perms = nil -+ authErr := ErrNoAuth -+ -+ switch userAuthReq.Method { -+ case "none": -+ if config.NoClientAuth { -+ if config.NoClientAuthCallback != nil { -+ perms, authErr = config.NoClientAuthCallback(s) -+ } else { -+ authErr = nil -+ } -+ } -+ -+ // allow initial attempt of 'none' without penalty -+ if authFailures == 0 { -+ authFailures-- -+ } -+ case "password": -+ if config.PasswordCallback == nil { -+ authErr = errors.New("ssh: password auth not configured") -+ break -+ } -+ payload := userAuthReq.Payload -+ if len(payload) < 1 || payload[0] != 0 { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ payload = payload[1:] -+ password, payload, ok := parseString(payload) -+ if !ok || len(payload) > 0 { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ -+ perms, authErr = config.PasswordCallback(s, password) -+ case "keyboard-interactive": -+ if config.KeyboardInteractiveCallback == nil { -+ authErr = errors.New("ssh: keyboard-interactive auth not configured") -+ break -+ } -+ -+ prompter := &sshClientKeyboardInteractive{s} -+ perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) -+ case "publickey": -+ if config.PublicKeyCallback == nil { -+ authErr = errors.New("ssh: publickey auth not configured") -+ break -+ } -+ payload := userAuthReq.Payload -+ if len(payload) < 1 { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ isQuery := payload[0] == 0 -+ payload = payload[1:] -+ algoBytes, payload, ok := parseString(payload) -+ if !ok { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ algo := string(algoBytes) -+ if !contains(supportedPubKeyAuthAlgos, underlyingAlgo(algo)) { -+ authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) -+ break -+ } -+ -+ pubKeyData, payload, ok := parseString(payload) -+ if !ok { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ -+ pubKey, err := ParsePublicKey(pubKeyData) -+ if err != nil { -+ return nil, err -+ } -+ -+ candidate, ok := cache.get(s.user, pubKeyData) -+ if !ok { -+ candidate.user = s.user -+ candidate.pubKeyData = pubKeyData -+ candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) -+ if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { -+ candidate.result = checkSourceAddress( -+ s.RemoteAddr(), -+ candidate.perms.CriticalOptions[sourceAddressCriticalOption]) -+ } -+ cache.add(candidate) -+ } -+ -+ if isQuery { -+ // The client can query if the given public key -+ // would be okay. -+ -+ if len(payload) > 0 { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ -+ if candidate.result == nil { -+ okMsg := userAuthPubKeyOkMsg{ -+ Algo: algo, -+ PubKey: pubKeyData, -+ } -+ if err = s.transport.writePacket(Marshal(&okMsg)); err != nil { -+ return nil, err -+ } -+ continue userAuthLoop -+ } -+ authErr = candidate.result -+ } else { -+ sig, payload, ok := parseSignature(payload) -+ if !ok || len(payload) > 0 { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ -+ // Ensure the public key algo and signature algo -+ // are supported. Compare the private key -+ // algorithm name that corresponds to algo with -+ // sig.Format. This is usually the same, but -+ // for certs, the names differ. -+ if !contains(supportedPubKeyAuthAlgos, sig.Format) { -+ authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format) -+ break -+ } -+ if !isAlgoCompatible(algo, sig.Format) { -+ authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo) -+ break -+ } -+ -+ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData) -+ -+ if err := pubKey.Verify(signedData, sig); err != nil { -+ return nil, err -+ } -+ -+ authErr = candidate.result -+ perms = candidate.perms -+ } -+ case "gssapi-with-mic": -+ if config.GSSAPIWithMICConfig == nil { -+ authErr = errors.New("ssh: gssapi-with-mic auth not configured") -+ break -+ } -+ gssapiConfig := config.GSSAPIWithMICConfig -+ userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload) -+ if err != nil { -+ return nil, parseError(msgUserAuthRequest) -+ } -+ // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication. -+ if userAuthRequestGSSAPI.N == 0 { -+ authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported") -+ break -+ } -+ var i uint32 -+ present := false -+ for i = 0; i < userAuthRequestGSSAPI.N; i++ { -+ if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) { -+ present = true -+ break -+ } -+ } -+ if !present { -+ authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism") -+ break -+ } -+ // Initial server response, see RFC 4462 section 3.3. -+ if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{ -+ SupportMech: krb5OID, -+ })); err != nil { -+ return nil, err -+ } -+ // Exchange token, see RFC 4462 section 3.4. -+ packet, err := s.transport.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} -+ if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { -+ return nil, err -+ } -+ authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID, -+ userAuthReq) -+ if err != nil { -+ return nil, err -+ } -+ default: -+ authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) -+ } -+ -+ authErrs = append(authErrs, authErr) -+ -+ if config.AuthLogCallback != nil { -+ config.AuthLogCallback(s, userAuthReq.Method, authErr) -+ } -+ -+ if authErr == nil { -+ break userAuthLoop -+ } -+ -+ authFailures++ -+ if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries { -+ // If we have hit the max attempts, don't bother sending the -+ // final SSH_MSG_USERAUTH_FAILURE message, since there are -+ // no more authentication methods which can be attempted, -+ // and this message may cause the client to re-attempt -+ // authentication while we send the disconnect message. -+ // Continue, and trigger the disconnect at the start of -+ // the loop. -+ // -+ // The SSH specification is somewhat confusing about this, -+ // RFC 4252 Section 5.1 requires each authentication failure -+ // be responded to with a respective SSH_MSG_USERAUTH_FAILURE -+ // message, but Section 4 says the server should disconnect -+ // after some number of attempts, but it isn't explicit which -+ // message should take precedence (i.e. should there be a failure -+ // message than a disconnect message, or if we are going to -+ // disconnect, should we only send that message.) -+ // -+ // Either way, OpenSSH disconnects immediately after the last -+ // failed authnetication attempt, and given they are typically -+ // considered the golden implementation it seems reasonable -+ // to match that behavior. -+ continue -+ } -+ -+ var failureMsg userAuthFailureMsg -+ if config.PasswordCallback != nil { -+ failureMsg.Methods = append(failureMsg.Methods, "password") -+ } -+ if config.PublicKeyCallback != nil { -+ failureMsg.Methods = append(failureMsg.Methods, "publickey") -+ } -+ if config.KeyboardInteractiveCallback != nil { -+ failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") -+ } -+ if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil && -+ config.GSSAPIWithMICConfig.AllowLogin != nil { -+ failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic") -+ } -+ -+ if len(failureMsg.Methods) == 0 { -+ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") -+ } -+ -+ if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil { -+ return nil, err -+ } -+ } -+ -+ if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil { -+ return nil, err -+ } -+ return perms, nil -+} -+ -+// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by -+// asking the client on the other side of a ServerConn. -+type sshClientKeyboardInteractive struct { -+ *connection -+} -+ -+func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) { -+ if len(questions) != len(echos) { -+ return nil, errors.New("ssh: echos and questions must have equal length") -+ } -+ -+ var prompts []byte -+ for i := range questions { -+ prompts = appendString(prompts, questions[i]) -+ prompts = appendBool(prompts, echos[i]) -+ } -+ -+ if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ -+ Name: name, -+ Instruction: instruction, -+ NumPrompts: uint32(len(questions)), -+ Prompts: prompts, -+ })); err != nil { -+ return nil, err -+ } -+ -+ packet, err := c.transport.readPacket() -+ if err != nil { -+ return nil, err -+ } -+ if packet[0] != msgUserAuthInfoResponse { -+ return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0]) -+ } -+ packet = packet[1:] -+ -+ n, packet, ok := parseUint32(packet) -+ if !ok || int(n) != len(questions) { -+ return nil, parseError(msgUserAuthInfoResponse) -+ } -+ -+ for i := uint32(0); i < n; i++ { -+ ans, rest, ok := parseString(packet) -+ if !ok { -+ return nil, parseError(msgUserAuthInfoResponse) -+ } -+ -+ answers = append(answers, string(ans)) -+ packet = rest -+ } -+ if len(packet) != 0 { -+ return nil, errors.New("ssh: junk at end of message") -+ } -+ -+ return answers, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/session.go b/ms_mod/golang.org/x/crypto/ssh/session.go -new file mode 100644 -index 00000000000000..acef62259fdee5 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/session.go -@@ -0,0 +1,647 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+// Session implements an interactive session described in -+// "RFC 4254, section 6". -+ -+import ( -+ "bytes" -+ "encoding/binary" -+ "errors" -+ "fmt" -+ "io" -+ "sync" -+) -+ -+type Signal string -+ -+// POSIX signals as listed in RFC 4254 Section 6.10. -+const ( -+ SIGABRT Signal = "ABRT" -+ SIGALRM Signal = "ALRM" -+ SIGFPE Signal = "FPE" -+ SIGHUP Signal = "HUP" -+ SIGILL Signal = "ILL" -+ SIGINT Signal = "INT" -+ SIGKILL Signal = "KILL" -+ SIGPIPE Signal = "PIPE" -+ SIGQUIT Signal = "QUIT" -+ SIGSEGV Signal = "SEGV" -+ SIGTERM Signal = "TERM" -+ SIGUSR1 Signal = "USR1" -+ SIGUSR2 Signal = "USR2" -+) -+ -+var signals = map[Signal]int{ -+ SIGABRT: 6, -+ SIGALRM: 14, -+ SIGFPE: 8, -+ SIGHUP: 1, -+ SIGILL: 4, -+ SIGINT: 2, -+ SIGKILL: 9, -+ SIGPIPE: 13, -+ SIGQUIT: 3, -+ SIGSEGV: 11, -+ SIGTERM: 15, -+} -+ -+type TerminalModes map[uint8]uint32 -+ -+// POSIX terminal mode flags as listed in RFC 4254 Section 8. -+const ( -+ tty_OP_END = 0 -+ VINTR = 1 -+ VQUIT = 2 -+ VERASE = 3 -+ VKILL = 4 -+ VEOF = 5 -+ VEOL = 6 -+ VEOL2 = 7 -+ VSTART = 8 -+ VSTOP = 9 -+ VSUSP = 10 -+ VDSUSP = 11 -+ VREPRINT = 12 -+ VWERASE = 13 -+ VLNEXT = 14 -+ VFLUSH = 15 -+ VSWTCH = 16 -+ VSTATUS = 17 -+ VDISCARD = 18 -+ IGNPAR = 30 -+ PARMRK = 31 -+ INPCK = 32 -+ ISTRIP = 33 -+ INLCR = 34 -+ IGNCR = 35 -+ ICRNL = 36 -+ IUCLC = 37 -+ IXON = 38 -+ IXANY = 39 -+ IXOFF = 40 -+ IMAXBEL = 41 -+ IUTF8 = 42 // RFC 8160 -+ ISIG = 50 -+ ICANON = 51 -+ XCASE = 52 -+ ECHO = 53 -+ ECHOE = 54 -+ ECHOK = 55 -+ ECHONL = 56 -+ NOFLSH = 57 -+ TOSTOP = 58 -+ IEXTEN = 59 -+ ECHOCTL = 60 -+ ECHOKE = 61 -+ PENDIN = 62 -+ OPOST = 70 -+ OLCUC = 71 -+ ONLCR = 72 -+ OCRNL = 73 -+ ONOCR = 74 -+ ONLRET = 75 -+ CS7 = 90 -+ CS8 = 91 -+ PARENB = 92 -+ PARODD = 93 -+ TTY_OP_ISPEED = 128 -+ TTY_OP_OSPEED = 129 -+) -+ -+// A Session represents a connection to a remote command or shell. -+type Session struct { -+ // Stdin specifies the remote process's standard input. -+ // If Stdin is nil, the remote process reads from an empty -+ // bytes.Buffer. -+ Stdin io.Reader -+ -+ // Stdout and Stderr specify the remote process's standard -+ // output and error. -+ // -+ // If either is nil, Run connects the corresponding file -+ // descriptor to an instance of io.Discard. There is a -+ // fixed amount of buffering that is shared for the two streams. -+ // If either blocks it may eventually cause the remote -+ // command to block. -+ Stdout io.Writer -+ Stderr io.Writer -+ -+ ch Channel // the channel backing this session -+ started bool // true once Start, Run or Shell is invoked. -+ copyFuncs []func() error -+ errors chan error // one send per copyFunc -+ -+ // true if pipe method is active -+ stdinpipe, stdoutpipe, stderrpipe bool -+ -+ // stdinPipeWriter is non-nil if StdinPipe has not been called -+ // and Stdin was specified by the user; it is the write end of -+ // a pipe connecting Session.Stdin to the stdin channel. -+ stdinPipeWriter io.WriteCloser -+ -+ exitStatus chan error -+} -+ -+// SendRequest sends an out-of-band channel request on the SSH channel -+// underlying the session. -+func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { -+ return s.ch.SendRequest(name, wantReply, payload) -+} -+ -+func (s *Session) Close() error { -+ return s.ch.Close() -+} -+ -+// RFC 4254 Section 6.4. -+type setenvRequest struct { -+ Name string -+ Value string -+} -+ -+// Setenv sets an environment variable that will be applied to any -+// command executed by Shell or Run. -+func (s *Session) Setenv(name, value string) error { -+ msg := setenvRequest{ -+ Name: name, -+ Value: value, -+ } -+ ok, err := s.ch.SendRequest("env", true, Marshal(&msg)) -+ if err == nil && !ok { -+ err = errors.New("ssh: setenv failed") -+ } -+ return err -+} -+ -+// RFC 4254 Section 6.2. -+type ptyRequestMsg struct { -+ Term string -+ Columns uint32 -+ Rows uint32 -+ Width uint32 -+ Height uint32 -+ Modelist string -+} -+ -+// RequestPty requests the association of a pty with the session on the remote host. -+func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error { -+ var tm []byte -+ for k, v := range termmodes { -+ kv := struct { -+ Key byte -+ Val uint32 -+ }{k, v} -+ -+ tm = append(tm, Marshal(&kv)...) -+ } -+ tm = append(tm, tty_OP_END) -+ req := ptyRequestMsg{ -+ Term: term, -+ Columns: uint32(w), -+ Rows: uint32(h), -+ Width: uint32(w * 8), -+ Height: uint32(h * 8), -+ Modelist: string(tm), -+ } -+ ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req)) -+ if err == nil && !ok { -+ err = errors.New("ssh: pty-req failed") -+ } -+ return err -+} -+ -+// RFC 4254 Section 6.5. -+type subsystemRequestMsg struct { -+ Subsystem string -+} -+ -+// RequestSubsystem requests the association of a subsystem with the session on the remote host. -+// A subsystem is a predefined command that runs in the background when the ssh session is initiated -+func (s *Session) RequestSubsystem(subsystem string) error { -+ msg := subsystemRequestMsg{ -+ Subsystem: subsystem, -+ } -+ ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg)) -+ if err == nil && !ok { -+ err = errors.New("ssh: subsystem request failed") -+ } -+ return err -+} -+ -+// RFC 4254 Section 6.7. -+type ptyWindowChangeMsg struct { -+ Columns uint32 -+ Rows uint32 -+ Width uint32 -+ Height uint32 -+} -+ -+// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns. -+func (s *Session) WindowChange(h, w int) error { -+ req := ptyWindowChangeMsg{ -+ Columns: uint32(w), -+ Rows: uint32(h), -+ Width: uint32(w * 8), -+ Height: uint32(h * 8), -+ } -+ _, err := s.ch.SendRequest("window-change", false, Marshal(&req)) -+ return err -+} -+ -+// RFC 4254 Section 6.9. -+type signalMsg struct { -+ Signal string -+} -+ -+// Signal sends the given signal to the remote process. -+// sig is one of the SIG* constants. -+func (s *Session) Signal(sig Signal) error { -+ msg := signalMsg{ -+ Signal: string(sig), -+ } -+ -+ _, err := s.ch.SendRequest("signal", false, Marshal(&msg)) -+ return err -+} -+ -+// RFC 4254 Section 6.5. -+type execMsg struct { -+ Command string -+} -+ -+// Start runs cmd on the remote host. Typically, the remote -+// server passes cmd to the shell for interpretation. -+// A Session only accepts one call to Run, Start or Shell. -+func (s *Session) Start(cmd string) error { -+ if s.started { -+ return errors.New("ssh: session already started") -+ } -+ req := execMsg{ -+ Command: cmd, -+ } -+ -+ ok, err := s.ch.SendRequest("exec", true, Marshal(&req)) -+ if err == nil && !ok { -+ err = fmt.Errorf("ssh: command %v failed", cmd) -+ } -+ if err != nil { -+ return err -+ } -+ return s.start() -+} -+ -+// Run runs cmd on the remote host. Typically, the remote -+// server passes cmd to the shell for interpretation. -+// A Session only accepts one call to Run, Start, Shell, Output, -+// or CombinedOutput. -+// -+// The returned error is nil if the command runs, has no problems -+// copying stdin, stdout, and stderr, and exits with a zero exit -+// status. -+// -+// If the remote server does not send an exit status, an error of type -+// *ExitMissingError is returned. If the command completes -+// unsuccessfully or is interrupted by a signal, the error is of type -+// *ExitError. Other error types may be returned for I/O problems. -+func (s *Session) Run(cmd string) error { -+ err := s.Start(cmd) -+ if err != nil { -+ return err -+ } -+ return s.Wait() -+} -+ -+// Output runs cmd on the remote host and returns its standard output. -+func (s *Session) Output(cmd string) ([]byte, error) { -+ if s.Stdout != nil { -+ return nil, errors.New("ssh: Stdout already set") -+ } -+ var b bytes.Buffer -+ s.Stdout = &b -+ err := s.Run(cmd) -+ return b.Bytes(), err -+} -+ -+type singleWriter struct { -+ b bytes.Buffer -+ mu sync.Mutex -+} -+ -+func (w *singleWriter) Write(p []byte) (int, error) { -+ w.mu.Lock() -+ defer w.mu.Unlock() -+ return w.b.Write(p) -+} -+ -+// CombinedOutput runs cmd on the remote host and returns its combined -+// standard output and standard error. -+func (s *Session) CombinedOutput(cmd string) ([]byte, error) { -+ if s.Stdout != nil { -+ return nil, errors.New("ssh: Stdout already set") -+ } -+ if s.Stderr != nil { -+ return nil, errors.New("ssh: Stderr already set") -+ } -+ var b singleWriter -+ s.Stdout = &b -+ s.Stderr = &b -+ err := s.Run(cmd) -+ return b.b.Bytes(), err -+} -+ -+// Shell starts a login shell on the remote host. A Session only -+// accepts one call to Run, Start, Shell, Output, or CombinedOutput. -+func (s *Session) Shell() error { -+ if s.started { -+ return errors.New("ssh: session already started") -+ } -+ -+ ok, err := s.ch.SendRequest("shell", true, nil) -+ if err == nil && !ok { -+ return errors.New("ssh: could not start shell") -+ } -+ if err != nil { -+ return err -+ } -+ return s.start() -+} -+ -+func (s *Session) start() error { -+ s.started = true -+ -+ type F func(*Session) -+ for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} { -+ setupFd(s) -+ } -+ -+ s.errors = make(chan error, len(s.copyFuncs)) -+ for _, fn := range s.copyFuncs { -+ go func(fn func() error) { -+ s.errors <- fn() -+ }(fn) -+ } -+ return nil -+} -+ -+// Wait waits for the remote command to exit. -+// -+// The returned error is nil if the command runs, has no problems -+// copying stdin, stdout, and stderr, and exits with a zero exit -+// status. -+// -+// If the remote server does not send an exit status, an error of type -+// *ExitMissingError is returned. If the command completes -+// unsuccessfully or is interrupted by a signal, the error is of type -+// *ExitError. Other error types may be returned for I/O problems. -+func (s *Session) Wait() error { -+ if !s.started { -+ return errors.New("ssh: session not started") -+ } -+ waitErr := <-s.exitStatus -+ -+ if s.stdinPipeWriter != nil { -+ s.stdinPipeWriter.Close() -+ } -+ var copyError error -+ for range s.copyFuncs { -+ if err := <-s.errors; err != nil && copyError == nil { -+ copyError = err -+ } -+ } -+ if waitErr != nil { -+ return waitErr -+ } -+ return copyError -+} -+ -+func (s *Session) wait(reqs <-chan *Request) error { -+ wm := Waitmsg{status: -1} -+ // Wait for msg channel to be closed before returning. -+ for msg := range reqs { -+ switch msg.Type { -+ case "exit-status": -+ wm.status = int(binary.BigEndian.Uint32(msg.Payload)) -+ case "exit-signal": -+ var sigval struct { -+ Signal string -+ CoreDumped bool -+ Error string -+ Lang string -+ } -+ if err := Unmarshal(msg.Payload, &sigval); err != nil { -+ return err -+ } -+ -+ // Must sanitize strings? -+ wm.signal = sigval.Signal -+ wm.msg = sigval.Error -+ wm.lang = sigval.Lang -+ default: -+ // This handles keepalives and matches -+ // OpenSSH's behaviour. -+ if msg.WantReply { -+ msg.Reply(false, nil) -+ } -+ } -+ } -+ if wm.status == 0 { -+ return nil -+ } -+ if wm.status == -1 { -+ // exit-status was never sent from server -+ if wm.signal == "" { -+ // signal was not sent either. RFC 4254 -+ // section 6.10 recommends against this -+ // behavior, but it is allowed, so we let -+ // clients handle it. -+ return &ExitMissingError{} -+ } -+ wm.status = 128 -+ if _, ok := signals[Signal(wm.signal)]; ok { -+ wm.status += signals[Signal(wm.signal)] -+ } -+ } -+ -+ return &ExitError{wm} -+} -+ -+// ExitMissingError is returned if a session is torn down cleanly, but -+// the server sends no confirmation of the exit status. -+type ExitMissingError struct{} -+ -+func (e *ExitMissingError) Error() string { -+ return "wait: remote command exited without exit status or exit signal" -+} -+ -+func (s *Session) stdin() { -+ if s.stdinpipe { -+ return -+ } -+ var stdin io.Reader -+ if s.Stdin == nil { -+ stdin = new(bytes.Buffer) -+ } else { -+ r, w := io.Pipe() -+ go func() { -+ _, err := io.Copy(w, s.Stdin) -+ w.CloseWithError(err) -+ }() -+ stdin, s.stdinPipeWriter = r, w -+ } -+ s.copyFuncs = append(s.copyFuncs, func() error { -+ _, err := io.Copy(s.ch, stdin) -+ if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF { -+ err = err1 -+ } -+ return err -+ }) -+} -+ -+func (s *Session) stdout() { -+ if s.stdoutpipe { -+ return -+ } -+ if s.Stdout == nil { -+ s.Stdout = io.Discard -+ } -+ s.copyFuncs = append(s.copyFuncs, func() error { -+ _, err := io.Copy(s.Stdout, s.ch) -+ return err -+ }) -+} -+ -+func (s *Session) stderr() { -+ if s.stderrpipe { -+ return -+ } -+ if s.Stderr == nil { -+ s.Stderr = io.Discard -+ } -+ s.copyFuncs = append(s.copyFuncs, func() error { -+ _, err := io.Copy(s.Stderr, s.ch.Stderr()) -+ return err -+ }) -+} -+ -+// sessionStdin reroutes Close to CloseWrite. -+type sessionStdin struct { -+ io.Writer -+ ch Channel -+} -+ -+func (s *sessionStdin) Close() error { -+ return s.ch.CloseWrite() -+} -+ -+// StdinPipe returns a pipe that will be connected to the -+// remote command's standard input when the command starts. -+func (s *Session) StdinPipe() (io.WriteCloser, error) { -+ if s.Stdin != nil { -+ return nil, errors.New("ssh: Stdin already set") -+ } -+ if s.started { -+ return nil, errors.New("ssh: StdinPipe after process started") -+ } -+ s.stdinpipe = true -+ return &sessionStdin{s.ch, s.ch}, nil -+} -+ -+// StdoutPipe returns a pipe that will be connected to the -+// remote command's standard output when the command starts. -+// There is a fixed amount of buffering that is shared between -+// stdout and stderr streams. If the StdoutPipe reader is -+// not serviced fast enough it may eventually cause the -+// remote command to block. -+func (s *Session) StdoutPipe() (io.Reader, error) { -+ if s.Stdout != nil { -+ return nil, errors.New("ssh: Stdout already set") -+ } -+ if s.started { -+ return nil, errors.New("ssh: StdoutPipe after process started") -+ } -+ s.stdoutpipe = true -+ return s.ch, nil -+} -+ -+// StderrPipe returns a pipe that will be connected to the -+// remote command's standard error when the command starts. -+// There is a fixed amount of buffering that is shared between -+// stdout and stderr streams. If the StderrPipe reader is -+// not serviced fast enough it may eventually cause the -+// remote command to block. -+func (s *Session) StderrPipe() (io.Reader, error) { -+ if s.Stderr != nil { -+ return nil, errors.New("ssh: Stderr already set") -+ } -+ if s.started { -+ return nil, errors.New("ssh: StderrPipe after process started") -+ } -+ s.stderrpipe = true -+ return s.ch.Stderr(), nil -+} -+ -+// newSession returns a new interactive session on the remote host. -+func newSession(ch Channel, reqs <-chan *Request) (*Session, error) { -+ s := &Session{ -+ ch: ch, -+ } -+ s.exitStatus = make(chan error, 1) -+ go func() { -+ s.exitStatus <- s.wait(reqs) -+ }() -+ -+ return s, nil -+} -+ -+// An ExitError reports unsuccessful completion of a remote command. -+type ExitError struct { -+ Waitmsg -+} -+ -+func (e *ExitError) Error() string { -+ return e.Waitmsg.String() -+} -+ -+// Waitmsg stores the information about an exited remote command -+// as reported by Wait. -+type Waitmsg struct { -+ status int -+ signal string -+ msg string -+ lang string -+} -+ -+// ExitStatus returns the exit status of the remote command. -+func (w Waitmsg) ExitStatus() int { -+ return w.status -+} -+ -+// Signal returns the exit signal of the remote command if -+// it was terminated violently. -+func (w Waitmsg) Signal() string { -+ return w.signal -+} -+ -+// Msg returns the exit message given by the remote command -+func (w Waitmsg) Msg() string { -+ return w.msg -+} -+ -+// Lang returns the language tag. See RFC 3066 -+func (w Waitmsg) Lang() string { -+ return w.lang -+} -+ -+func (w Waitmsg) String() string { -+ str := fmt.Sprintf("Process exited with status %v", w.status) -+ if w.signal != "" { -+ str += fmt.Sprintf(" from signal %v", w.signal) -+ } -+ if w.msg != "" { -+ str += fmt.Sprintf(". Reason was: %v", w.msg) -+ } -+ return str -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/session_test.go b/ms_mod/golang.org/x/crypto/ssh/session_test.go -new file mode 100644 -index 00000000000000..521677f9b106bc ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/session_test.go -@@ -0,0 +1,845 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+// Session tests. -+ -+import ( -+ "bytes" -+ crypto_rand "crypto/rand" -+ "errors" -+ "io" -+ "math/rand" -+ "net" -+ "testing" -+ -+ "golang.org/x/crypto/ssh/terminal" -+) -+ -+type serverType func(Channel, <-chan *Request, *testing.T) -+ -+// dial constructs a new test server and returns a *ClientConn. -+func dial(handler serverType, t *testing.T) *Client { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ -+ go func() { -+ defer c1.Close() -+ conf := ServerConfig{ -+ NoClientAuth: true, -+ } -+ conf.AddHostKey(testSigners["rsa"]) -+ -+ conn, chans, reqs, err := NewServerConn(c1, &conf) -+ if err != nil { -+ t.Errorf("Unable to handshake: %v", err) -+ return -+ } -+ go DiscardRequests(reqs) -+ -+ for newCh := range chans { -+ if newCh.ChannelType() != "session" { -+ newCh.Reject(UnknownChannelType, "unknown channel type") -+ continue -+ } -+ -+ ch, inReqs, err := newCh.Accept() -+ if err != nil { -+ t.Errorf("Accept: %v", err) -+ continue -+ } -+ go func() { -+ handler(ch, inReqs, t) -+ }() -+ } -+ if err := conn.Wait(); err != io.EOF { -+ t.Logf("server exit reason: %v", err) -+ } -+ }() -+ -+ config := &ClientConfig{ -+ User: "testuser", -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ -+ conn, chans, reqs, err := NewClientConn(c2, "", config) -+ if err != nil { -+ t.Fatalf("unable to dial remote side: %v", err) -+ } -+ -+ return NewClient(conn, chans, reqs) -+} -+ -+// Test a simple string is returned to session.Stdout. -+func TestSessionShell(t *testing.T) { -+ conn := dial(shellHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ stdout := new(bytes.Buffer) -+ session.Stdout = stdout -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %s", err) -+ } -+ if err := session.Wait(); err != nil { -+ t.Fatalf("Remote command did not exit cleanly: %v", err) -+ } -+ actual := stdout.String() -+ if actual != "golang" { -+ t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) -+ } -+} -+ -+// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it. -+ -+// Test a simple string is returned via StdoutPipe. -+func TestSessionStdoutPipe(t *testing.T) { -+ conn := dial(shellHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ stdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Fatalf("Unable to request StdoutPipe(): %v", err) -+ } -+ var buf bytes.Buffer -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ done := make(chan bool, 1) -+ go func() { -+ if _, err := io.Copy(&buf, stdout); err != nil { -+ t.Errorf("Copy of stdout failed: %v", err) -+ } -+ done <- true -+ }() -+ if err := session.Wait(); err != nil { -+ t.Fatalf("Remote command did not exit cleanly: %v", err) -+ } -+ <-done -+ actual := buf.String() -+ if actual != "golang" { -+ t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) -+ } -+} -+ -+// Test that a simple string is returned via the Output helper, -+// and that stderr is discarded. -+func TestSessionOutput(t *testing.T) { -+ conn := dial(fixedOutputHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ -+ buf, err := session.Output("") // cmd is ignored by fixedOutputHandler -+ if err != nil { -+ t.Error("Remote command did not exit cleanly:", err) -+ } -+ w := "this-is-stdout." -+ g := string(buf) -+ if g != w { -+ t.Error("Remote command did not return expected string:") -+ t.Logf("want %q", w) -+ t.Logf("got %q", g) -+ } -+} -+ -+// Test that both stdout and stderr are returned -+// via the CombinedOutput helper. -+func TestSessionCombinedOutput(t *testing.T) { -+ conn := dial(fixedOutputHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ -+ buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler -+ if err != nil { -+ t.Error("Remote command did not exit cleanly:", err) -+ } -+ const stdout = "this-is-stdout." -+ const stderr = "this-is-stderr." -+ g := string(buf) -+ if g != stdout+stderr && g != stderr+stdout { -+ t.Error("Remote command did not return expected string:") -+ t.Logf("want %q, or %q", stdout+stderr, stderr+stdout) -+ t.Logf("got %q", g) -+ } -+} -+ -+// Test non-0 exit status is returned correctly. -+func TestExitStatusNonZero(t *testing.T) { -+ conn := dial(exitStatusNonZeroHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err == nil { -+ t.Fatalf("expected command to fail but it didn't") -+ } -+ e, ok := err.(*ExitError) -+ if !ok { -+ t.Fatalf("expected *ExitError but got %T", err) -+ } -+ if e.ExitStatus() != 15 { -+ t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus()) -+ } -+} -+ -+// Test 0 exit status is returned correctly. -+func TestExitStatusZero(t *testing.T) { -+ conn := dial(exitStatusZeroHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err != nil { -+ t.Fatalf("expected nil but got %v", err) -+ } -+} -+ -+// Test exit signal and status are both returned correctly. -+func TestExitSignalAndStatus(t *testing.T) { -+ conn := dial(exitSignalAndStatusHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err == nil { -+ t.Fatalf("expected command to fail but it didn't") -+ } -+ e, ok := err.(*ExitError) -+ if !ok { -+ t.Fatalf("expected *ExitError but got %T", err) -+ } -+ if e.Signal() != "TERM" || e.ExitStatus() != 15 { -+ t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus()) -+ } -+} -+ -+// Test exit signal and status are both returned correctly. -+func TestKnownExitSignalOnly(t *testing.T) { -+ conn := dial(exitSignalHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err == nil { -+ t.Fatalf("expected command to fail but it didn't") -+ } -+ e, ok := err.(*ExitError) -+ if !ok { -+ t.Fatalf("expected *ExitError but got %T", err) -+ } -+ if e.Signal() != "TERM" || e.ExitStatus() != 143 { -+ t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus()) -+ } -+} -+ -+// Test exit signal and status are both returned correctly. -+func TestUnknownExitSignal(t *testing.T) { -+ conn := dial(exitSignalUnknownHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err == nil { -+ t.Fatalf("expected command to fail but it didn't") -+ } -+ e, ok := err.(*ExitError) -+ if !ok { -+ t.Fatalf("expected *ExitError but got %T", err) -+ } -+ if e.Signal() != "SYS" || e.ExitStatus() != 128 { -+ t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus()) -+ } -+} -+ -+func TestExitWithoutStatusOrSignal(t *testing.T) { -+ conn := dial(exitWithoutSignalOrStatus, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("Unable to request new session: %v", err) -+ } -+ defer session.Close() -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err == nil { -+ t.Fatalf("expected command to fail but it didn't") -+ } -+ if _, ok := err.(*ExitMissingError); !ok { -+ t.Fatalf("got %T want *ExitMissingError", err) -+ } -+} -+ -+// windowTestBytes is the number of bytes that we'll send to the SSH server. -+const windowTestBytes = 16000 * 200 -+ -+// TestServerWindow writes random data to the server. The server is expected to echo -+// the same data back, which is compared against the original. -+func TestServerWindow(t *testing.T) { -+ origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) -+ io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes) -+ origBytes := origBuf.Bytes() -+ -+ conn := dial(echoHandler, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer session.Close() -+ result := make(chan []byte) -+ -+ go func() { -+ defer close(result) -+ echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) -+ serverStdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Errorf("StdoutPipe failed: %v", err) -+ return -+ } -+ n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes) -+ if err != nil && err != io.EOF { -+ t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err) -+ } -+ result <- echoedBuf.Bytes() -+ }() -+ -+ serverStdin, err := session.StdinPipe() -+ if err != nil { -+ t.Fatalf("StdinPipe failed: %v", err) -+ } -+ written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes) -+ if err != nil { -+ t.Errorf("failed to copy origBuf to serverStdin: %v", err) -+ } else if written != windowTestBytes { -+ t.Errorf("Wrote only %d of %d bytes to server", written, windowTestBytes) -+ } -+ -+ echoedBytes := <-result -+ -+ if !bytes.Equal(origBytes, echoedBytes) { -+ t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes)) -+ } -+} -+ -+// Verify the client can handle a keepalive packet from the server. -+func TestClientHandlesKeepalives(t *testing.T) { -+ conn := dial(channelKeepaliveSender, t) -+ defer conn.Close() -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer session.Close() -+ if err := session.Shell(); err != nil { -+ t.Fatalf("Unable to execute command: %v", err) -+ } -+ err = session.Wait() -+ if err != nil { -+ t.Fatalf("expected nil but got: %v", err) -+ } -+} -+ -+type exitStatusMsg struct { -+ Status uint32 -+} -+ -+type exitSignalMsg struct { -+ Signal string -+ CoreDumped bool -+ Errmsg string -+ Lang string -+} -+ -+func handleTerminalRequests(in <-chan *Request) { -+ for req := range in { -+ ok := false -+ switch req.Type { -+ case "shell": -+ ok = true -+ if len(req.Payload) > 0 { -+ // We don't accept any commands, only the default shell. -+ ok = false -+ } -+ case "env": -+ ok = true -+ } -+ req.Reply(ok, nil) -+ } -+} -+ -+func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal { -+ term := terminal.NewTerminal(ch, prompt) -+ go handleTerminalRequests(in) -+ return term -+} -+ -+func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ // this string is returned to stdout -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+ sendStatus(0, ch, t) -+} -+ -+func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+ sendStatus(15, ch, t) -+} -+ -+func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+ sendStatus(15, ch, t) -+ sendSignal("TERM", ch, t) -+} -+ -+func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+ sendSignal("TERM", ch, t) -+} -+ -+func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+ sendSignal("SYS", ch, t) -+} -+ -+func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+} -+ -+func shellHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ // this string is returned to stdout -+ shell := newServerShell(ch, in, "golang") -+ readLine(shell, t) -+ sendStatus(0, ch, t) -+} -+ -+// Ignores the command, writes fixed strings to stderr and stdout. -+// Strings are "this-is-stdout." and "this-is-stderr.". -+func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ _, err := ch.Read(nil) -+ -+ req, ok := <-in -+ if !ok { -+ t.Fatalf("error: expected channel request, got: %#v", err) -+ return -+ } -+ -+ // ignore request, always send some text -+ req.Reply(true, nil) -+ -+ _, err = io.WriteString(ch, "this-is-stdout.") -+ if err != nil { -+ t.Fatalf("error writing on server: %v", err) -+ } -+ _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") -+ if err != nil { -+ t.Fatalf("error writing on server: %v", err) -+ } -+ sendStatus(0, ch, t) -+} -+ -+func readLine(shell *terminal.Terminal, t *testing.T) { -+ if _, err := shell.ReadLine(); err != nil && err != io.EOF { -+ t.Errorf("unable to read line: %v", err) -+ } -+} -+ -+func sendStatus(status uint32, ch Channel, t *testing.T) { -+ msg := exitStatusMsg{ -+ Status: status, -+ } -+ if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil { -+ t.Errorf("unable to send status: %v", err) -+ } -+} -+ -+func sendSignal(signal string, ch Channel, t *testing.T) { -+ sig := exitSignalMsg{ -+ Signal: signal, -+ CoreDumped: false, -+ Errmsg: "Process terminated", -+ Lang: "en-GB-oed", -+ } -+ if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil { -+ t.Errorf("unable to send signal: %v", err) -+ } -+} -+ -+func discardHandler(ch Channel, t *testing.T) { -+ defer ch.Close() -+ io.Copy(io.Discard, ch) -+} -+ -+func echoHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil { -+ t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err) -+ } -+} -+ -+// copyNRandomly copies n bytes from src to dst. It uses a variable, and random, -+// buffer size to exercise more code paths. -+func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) { -+ var ( -+ buf = make([]byte, 32*1024) -+ written int -+ remaining = n -+ ) -+ for remaining > 0 { -+ l := rand.Intn(1 << 15) -+ if remaining < l { -+ l = remaining -+ } -+ nr, er := src.Read(buf[:l]) -+ nw, ew := dst.Write(buf[:nr]) -+ remaining -= nw -+ written += nw -+ if ew != nil { -+ return written, ew -+ } -+ if nr != nw { -+ return written, io.ErrShortWrite -+ } -+ if er != nil && er != io.EOF { -+ return written, er -+ } -+ } -+ return written, nil -+} -+ -+func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ shell := newServerShell(ch, in, "> ") -+ readLine(shell, t) -+ if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil { -+ t.Errorf("unable to send channel keepalive request: %v", err) -+ } -+ sendStatus(0, ch, t) -+} -+ -+func TestClientWriteEOF(t *testing.T) { -+ conn := dial(simpleEchoHandler, t) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer session.Close() -+ stdin, err := session.StdinPipe() -+ if err != nil { -+ t.Fatalf("StdinPipe failed: %v", err) -+ } -+ stdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Fatalf("StdoutPipe failed: %v", err) -+ } -+ -+ data := []byte(`0000`) -+ _, err = stdin.Write(data) -+ if err != nil { -+ t.Fatalf("Write failed: %v", err) -+ } -+ stdin.Close() -+ -+ res, err := io.ReadAll(stdout) -+ if err != nil { -+ t.Fatalf("Read failed: %v", err) -+ } -+ -+ if !bytes.Equal(data, res) { -+ t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) -+ } -+} -+ -+func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) { -+ defer ch.Close() -+ data, err := io.ReadAll(ch) -+ if err != nil { -+ t.Errorf("handler read error: %v", err) -+ } -+ _, err = ch.Write(data) -+ if err != nil { -+ t.Errorf("handler write error: %v", err) -+ } -+} -+ -+func TestSessionID(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ serverID := make(chan []byte, 1) -+ clientID := make(chan []byte, 1) -+ -+ serverConf := &ServerConfig{ -+ NoClientAuth: true, -+ } -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ clientConf := &ClientConfig{ -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ User: "user", -+ } -+ -+ srvErrCh := make(chan error, 1) -+ go func() { -+ conn, chans, reqs, err := NewServerConn(c1, serverConf) -+ srvErrCh <- err -+ if err != nil { -+ return -+ } -+ serverID <- conn.SessionID() -+ go DiscardRequests(reqs) -+ for ch := range chans { -+ ch.Reject(Prohibited, "") -+ } -+ }() -+ -+ cliErrCh := make(chan error, 1) -+ go func() { -+ conn, chans, reqs, err := NewClientConn(c2, "", clientConf) -+ cliErrCh <- err -+ if err != nil { -+ return -+ } -+ clientID <- conn.SessionID() -+ go DiscardRequests(reqs) -+ for ch := range chans { -+ ch.Reject(Prohibited, "") -+ } -+ }() -+ -+ if err := <-srvErrCh; err != nil { -+ t.Fatalf("server handshake: %v", err) -+ } -+ -+ if err := <-cliErrCh; err != nil { -+ t.Fatalf("client handshake: %v", err) -+ } -+ -+ s := <-serverID -+ c := <-clientID -+ if bytes.Compare(s, c) != 0 { -+ t.Errorf("server session ID (%x) != client session ID (%x)", s, c) -+ } else if len(s) == 0 { -+ t.Errorf("client and server SessionID were empty.") -+ } -+} -+ -+type noReadConn struct { -+ readSeen bool -+ net.Conn -+} -+ -+func (c *noReadConn) Close() error { -+ return nil -+} -+ -+func (c *noReadConn) Read(b []byte) (int, error) { -+ c.readSeen = true -+ return 0, errors.New("noReadConn error") -+} -+ -+func TestInvalidServerConfiguration(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ serveConn := noReadConn{Conn: c1} -+ serverConf := &ServerConfig{} -+ -+ NewServerConn(&serveConn, serverConf) -+ if serveConn.readSeen { -+ t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key") -+ } -+ -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ -+ NewServerConn(&serveConn, serverConf) -+ if serveConn.readSeen { -+ t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method") -+ } -+} -+ -+func TestHostKeyAlgorithms(t *testing.T) { -+ serverConf := &ServerConfig{ -+ NoClientAuth: true, -+ } -+ serverConf.AddHostKey(testSigners["rsa"]) -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ -+ connect := func(clientConf *ClientConfig, want string) { -+ var alg string -+ clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error { -+ alg = key.Type() -+ return nil -+ } -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go NewServerConn(c1, serverConf) -+ _, _, _, err = NewClientConn(c2, "", clientConf) -+ if err != nil { -+ t.Fatalf("NewClientConn: %v", err) -+ } -+ if alg != want { -+ t.Errorf("selected key algorithm %s, want %s", alg, want) -+ } -+ } -+ -+ // By default, we get the preferred algorithm, which is ECDSA 256. -+ -+ clientConf := &ClientConfig{ -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ } -+ connect(clientConf, KeyAlgoECDSA256) -+ -+ // Client asks for RSA explicitly. -+ clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} -+ connect(clientConf, KeyAlgoRSA) -+ -+ // Client asks for RSA-SHA2-512 explicitly. -+ clientConf.HostKeyAlgorithms = []string{KeyAlgoRSASHA512} -+ // We get back an "ssh-rsa" key but the verification happened -+ // with an RSA-SHA2-512 signature. -+ connect(clientConf, KeyAlgoRSA) -+ -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ go NewServerConn(c1, serverConf) -+ clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"} -+ _, _, _, err = NewClientConn(c2, "", clientConf) -+ if err == nil { -+ t.Fatal("succeeded connecting with unknown hostkey algorithm") -+ } -+} -+ -+func TestServerClientAuthCallback(t *testing.T) { -+ c1, c2, err := netPipe() -+ if err != nil { -+ t.Fatalf("netPipe: %v", err) -+ } -+ defer c1.Close() -+ defer c2.Close() -+ -+ userCh := make(chan string, 1) -+ -+ serverConf := &ServerConfig{ -+ NoClientAuth: true, -+ NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) { -+ userCh <- conn.User() -+ return nil, nil -+ }, -+ } -+ const someUsername = "some-username" -+ -+ serverConf.AddHostKey(testSigners["ecdsa"]) -+ clientConf := &ClientConfig{ -+ HostKeyCallback: InsecureIgnoreHostKey(), -+ User: someUsername, -+ } -+ -+ go func() { -+ _, chans, reqs, err := NewServerConn(c1, serverConf) -+ if err != nil { -+ t.Errorf("server handshake: %v", err) -+ userCh <- "error" -+ return -+ } -+ go DiscardRequests(reqs) -+ for ch := range chans { -+ ch.Reject(Prohibited, "") -+ } -+ }() -+ -+ conn, _, _, err := NewClientConn(c2, "", clientConf) -+ if err != nil { -+ t.Fatalf("client handshake: %v", err) -+ return -+ } -+ conn.Close() -+ -+ got := <-userCh -+ if got != someUsername { -+ t.Errorf("username = %q; want %q", got, someUsername) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/ssh_gss.go b/ms_mod/golang.org/x/crypto/ssh/ssh_gss.go -new file mode 100644 -index 00000000000000..24bd7c8e830484 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/ssh_gss.go -@@ -0,0 +1,139 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "encoding/asn1" -+ "errors" -+) -+ -+var krb5OID []byte -+ -+func init() { -+ krb5OID, _ = asn1.Marshal(krb5Mesh) -+} -+ -+// GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins. -+type GSSAPIClient interface { -+ // InitSecContext initiates the establishment of a security context for GSS-API between the -+ // ssh client and ssh server. Initially the token parameter should be specified as nil. -+ // The routine may return a outputToken which should be transferred to -+ // the ssh server, where the ssh server will present it to -+ // AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting -+ // needContinue to false. To complete the context -+ // establishment, one or more reply tokens may be required from the ssh -+ // server;if so, InitSecContext will return a needContinue which is true. -+ // In this case, InitSecContext should be called again when the -+ // reply token is received from the ssh server, passing the reply -+ // token to InitSecContext via the token parameters. -+ // See RFC 2743 section 2.2.1 and RFC 4462 section 3.4. -+ InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) -+ // GetMIC generates a cryptographic MIC for the SSH2 message, and places -+ // the MIC in a token for transfer to the ssh server. -+ // The contents of the MIC field are obtained by calling GSS_GetMIC() -+ // over the following, using the GSS-API context that was just -+ // established: -+ // string session identifier -+ // byte SSH_MSG_USERAUTH_REQUEST -+ // string user name -+ // string service -+ // string "gssapi-with-mic" -+ // See RFC 2743 section 2.3.1 and RFC 4462 3.5. -+ GetMIC(micFiled []byte) ([]byte, error) -+ // Whenever possible, it should be possible for -+ // DeleteSecContext() calls to be successfully processed even -+ // if other calls cannot succeed, thereby enabling context-related -+ // resources to be released. -+ // In addition to deleting established security contexts, -+ // gss_delete_sec_context must also be able to delete "half-built" -+ // security contexts resulting from an incomplete sequence of -+ // InitSecContext()/AcceptSecContext() calls. -+ // See RFC 2743 section 2.2.3. -+ DeleteSecContext() error -+} -+ -+// GSSAPIServer provides the API to plug in GSSAPI authentication for server logins. -+type GSSAPIServer interface { -+ // AcceptSecContext allows a remotely initiated security context between the application -+ // and a remote peer to be established by the ssh client. The routine may return a -+ // outputToken which should be transferred to the ssh client, -+ // where the ssh client will present it to InitSecContext. -+ // If no token need be sent, AcceptSecContext will indicate this -+ // by setting the needContinue to false. To -+ // complete the context establishment, one or more reply tokens may be -+ // required from the ssh client. if so, AcceptSecContext -+ // will return a needContinue which is true, in which case it -+ // should be called again when the reply token is received from the ssh -+ // client, passing the token to AcceptSecContext via the -+ // token parameters. -+ // The srcName return value is the authenticated username. -+ // See RFC 2743 section 2.2.2 and RFC 4462 section 3.4. -+ AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) -+ // VerifyMIC verifies that a cryptographic MIC, contained in the token parameter, -+ // fits the supplied message is received from the ssh client. -+ // See RFC 2743 section 2.3.2. -+ VerifyMIC(micField []byte, micToken []byte) error -+ // Whenever possible, it should be possible for -+ // DeleteSecContext() calls to be successfully processed even -+ // if other calls cannot succeed, thereby enabling context-related -+ // resources to be released. -+ // In addition to deleting established security contexts, -+ // gss_delete_sec_context must also be able to delete "half-built" -+ // security contexts resulting from an incomplete sequence of -+ // InitSecContext()/AcceptSecContext() calls. -+ // See RFC 2743 section 2.2.3. -+ DeleteSecContext() error -+} -+ -+var ( -+ // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication, -+ // so we also support the krb5 mechanism only. -+ // See RFC 1964 section 1. -+ krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2} -+) -+ -+// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST -+// See RFC 4462 section 3.2. -+type userAuthRequestGSSAPI struct { -+ N uint32 -+ OIDS []asn1.ObjectIdentifier -+} -+ -+func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) { -+ n, rest, ok := parseUint32(payload) -+ if !ok { -+ return nil, errors.New("parse uint32 failed") -+ } -+ s := &userAuthRequestGSSAPI{ -+ N: n, -+ OIDS: make([]asn1.ObjectIdentifier, n), -+ } -+ for i := 0; i < int(n); i++ { -+ var ( -+ desiredMech []byte -+ err error -+ ) -+ desiredMech, rest, ok = parseString(rest) -+ if !ok { -+ return nil, errors.New("parse string failed") -+ } -+ if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil { -+ return nil, err -+ } -+ -+ } -+ return s, nil -+} -+ -+// See RFC 4462 section 3.6. -+func buildMIC(sessionID string, username string, service string, authMethod string) []byte { -+ out := make([]byte, 0, 0) -+ out = appendString(out, sessionID) -+ out = append(out, msgUserAuthRequest) -+ out = appendString(out, username) -+ out = appendString(out, service) -+ out = appendString(out, authMethod) -+ return out -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go b/ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go -new file mode 100644 -index 00000000000000..39a111288af097 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/ssh_gss_test.go -@@ -0,0 +1,109 @@ -+package ssh -+ -+import ( -+ "fmt" -+ "testing" -+) -+ -+func TestParseGSSAPIPayload(t *testing.T) { -+ payload := []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x09, -+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02} -+ res, err := parseGSSAPIPayload(payload) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if ok := res.OIDS[0].Equal(krb5Mesh); !ok { -+ t.Fatalf("got %v, want %v", res, krb5Mesh) -+ } -+} -+ -+func TestBuildMIC(t *testing.T) { -+ sessionID := []byte{134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53, -+ 183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121} -+ username := "testuser" -+ service := "ssh-connection" -+ authMethod := "gssapi-with-mic" -+ expected := []byte{0, 0, 0, 32, 134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53, 183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121, 50, 0, 0, 0, 8, 116, 101, 115, 116, 117, 115, 101, 114, 0, 0, 0, 14, 115, 115, 104, 45, 99, 111, 110, 110, 101, 99, 116, 105, 111, 110, 0, 0, 0, 15, 103, 115, 115, 97, 112, 105, 45, 119, 105, 116, 104, 45, 109, 105, 99} -+ result := buildMIC(string(sessionID), username, service, authMethod) -+ if string(result) != string(expected) { -+ t.Fatalf("buildMic: got %v, want %v", result, expected) -+ } -+} -+ -+type exchange struct { -+ outToken string -+ expectedToken string -+} -+ -+type FakeClient struct { -+ exchanges []*exchange -+ round int -+ mic []byte -+ maxRound int -+} -+ -+func (f *FakeClient) InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) { -+ if token == nil { -+ if f.exchanges[f.round].expectedToken != "" { -+ err = fmt.Errorf("got empty token, want %q", f.exchanges[f.round].expectedToken) -+ } else { -+ outputToken = []byte(f.exchanges[f.round].outToken) -+ } -+ } else { -+ if string(token) != string(f.exchanges[f.round].expectedToken) { -+ err = fmt.Errorf("got %q, want token %q", token, f.exchanges[f.round].expectedToken) -+ } else { -+ outputToken = []byte(f.exchanges[f.round].outToken) -+ } -+ } -+ f.round++ -+ needContinue = f.round < f.maxRound -+ return -+} -+ -+func (f *FakeClient) GetMIC(micField []byte) ([]byte, error) { -+ return f.mic, nil -+} -+ -+func (f *FakeClient) DeleteSecContext() error { -+ return nil -+} -+ -+type FakeServer struct { -+ exchanges []*exchange -+ round int -+ expectedMIC []byte -+ srcName string -+ maxRound int -+} -+ -+func (f *FakeServer) AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) { -+ if token == nil { -+ if f.exchanges[f.round].expectedToken != "" { -+ err = fmt.Errorf("got empty token, want %q", f.exchanges[f.round].expectedToken) -+ } else { -+ outputToken = []byte(f.exchanges[f.round].outToken) -+ } -+ } else { -+ if string(token) != string(f.exchanges[f.round].expectedToken) { -+ err = fmt.Errorf("got %q, want token %q", token, f.exchanges[f.round].expectedToken) -+ } else { -+ outputToken = []byte(f.exchanges[f.round].outToken) -+ } -+ } -+ f.round++ -+ needContinue = f.round < f.maxRound -+ srcName = f.srcName -+ return -+} -+ -+func (f *FakeServer) VerifyMIC(micField []byte, micToken []byte) error { -+ if string(micToken) != string(f.expectedMIC) { -+ return fmt.Errorf("got MICToken %q, want %q", micToken, f.expectedMIC) -+ } -+ return nil -+} -+ -+func (f *FakeServer) DeleteSecContext() error { -+ return nil -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/streamlocal.go b/ms_mod/golang.org/x/crypto/ssh/streamlocal.go -new file mode 100644 -index 00000000000000..b171b330bc380a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/streamlocal.go -@@ -0,0 +1,116 @@ -+package ssh -+ -+import ( -+ "errors" -+ "io" -+ "net" -+) -+ -+// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message -+// with "direct-streamlocal@openssh.com" string. -+// -+// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding -+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235 -+type streamLocalChannelOpenDirectMsg struct { -+ socketPath string -+ reserved0 string -+ reserved1 uint32 -+} -+ -+// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message -+// with "forwarded-streamlocal@openssh.com" string. -+type forwardedStreamLocalPayload struct { -+ SocketPath string -+ Reserved0 string -+} -+ -+// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message -+// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string. -+type streamLocalChannelForwardMsg struct { -+ socketPath string -+} -+ -+// ListenUnix is similar to ListenTCP but uses a Unix domain socket. -+func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { -+ c.handleForwardsOnce.Do(c.handleForwards) -+ m := streamLocalChannelForwardMsg{ -+ socketPath, -+ } -+ // send message -+ ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m)) -+ if err != nil { -+ return nil, err -+ } -+ if !ok { -+ return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer") -+ } -+ ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"}) -+ -+ return &unixListener{socketPath, c, ch}, nil -+} -+ -+func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { -+ msg := streamLocalChannelOpenDirectMsg{ -+ socketPath: socketPath, -+ } -+ ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg)) -+ if err != nil { -+ return nil, err -+ } -+ go DiscardRequests(in) -+ return ch, err -+} -+ -+type unixListener struct { -+ socketPath string -+ -+ conn *Client -+ in <-chan forward -+} -+ -+// Accept waits for and returns the next connection to the listener. -+func (l *unixListener) Accept() (net.Conn, error) { -+ s, ok := <-l.in -+ if !ok { -+ return nil, io.EOF -+ } -+ ch, incoming, err := s.newCh.Accept() -+ if err != nil { -+ return nil, err -+ } -+ go DiscardRequests(incoming) -+ -+ return &chanConn{ -+ Channel: ch, -+ laddr: &net.UnixAddr{ -+ Name: l.socketPath, -+ Net: "unix", -+ }, -+ raddr: &net.UnixAddr{ -+ Name: "@", -+ Net: "unix", -+ }, -+ }, nil -+} -+ -+// Close closes the listener. -+func (l *unixListener) Close() error { -+ // this also closes the listener. -+ l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"}) -+ m := streamLocalChannelForwardMsg{ -+ l.socketPath, -+ } -+ ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m)) -+ if err == nil && !ok { -+ err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed") -+ } -+ return err -+} -+ -+// Addr returns the listener's network address. -+func (l *unixListener) Addr() net.Addr { -+ return &net.UnixAddr{ -+ Name: l.socketPath, -+ Net: "unix", -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/tcpip.go b/ms_mod/golang.org/x/crypto/ssh/tcpip.go -new file mode 100644 -index 00000000000000..80d35f5ec187a4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/tcpip.go -@@ -0,0 +1,474 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "errors" -+ "fmt" -+ "io" -+ "math/rand" -+ "net" -+ "strconv" -+ "strings" -+ "sync" -+ "time" -+) -+ -+// Listen requests the remote peer open a listening socket on -+// addr. Incoming connections will be available by calling Accept on -+// the returned net.Listener. The listener must be serviced, or the -+// SSH connection may hang. -+// N must be "tcp", "tcp4", "tcp6", or "unix". -+func (c *Client) Listen(n, addr string) (net.Listener, error) { -+ switch n { -+ case "tcp", "tcp4", "tcp6": -+ laddr, err := net.ResolveTCPAddr(n, addr) -+ if err != nil { -+ return nil, err -+ } -+ return c.ListenTCP(laddr) -+ case "unix": -+ return c.ListenUnix(addr) -+ default: -+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) -+ } -+} -+ -+// Automatic port allocation is broken with OpenSSH before 6.0. See -+// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In -+// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, -+// rather than the actual port number. This means you can never open -+// two different listeners with auto allocated ports. We work around -+// this by trying explicit ports until we succeed. -+ -+const openSSHPrefix = "OpenSSH_" -+ -+var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) -+ -+// isBrokenOpenSSHVersion returns true if the given version string -+// specifies a version of OpenSSH that is known to have a bug in port -+// forwarding. -+func isBrokenOpenSSHVersion(versionStr string) bool { -+ i := strings.Index(versionStr, openSSHPrefix) -+ if i < 0 { -+ return false -+ } -+ i += len(openSSHPrefix) -+ j := i -+ for ; j < len(versionStr); j++ { -+ if versionStr[j] < '0' || versionStr[j] > '9' { -+ break -+ } -+ } -+ version, _ := strconv.Atoi(versionStr[i:j]) -+ return version < 6 -+} -+ -+// autoPortListenWorkaround simulates automatic port allocation by -+// trying random ports repeatedly. -+func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { -+ var sshListener net.Listener -+ var err error -+ const tries = 10 -+ for i := 0; i < tries; i++ { -+ addr := *laddr -+ addr.Port = 1024 + portRandomizer.Intn(60000) -+ sshListener, err = c.ListenTCP(&addr) -+ if err == nil { -+ laddr.Port = addr.Port -+ return sshListener, err -+ } -+ } -+ return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) -+} -+ -+// RFC 4254 7.1 -+type channelForwardMsg struct { -+ addr string -+ rport uint32 -+} -+ -+// handleForwards starts goroutines handling forwarded connections. -+// It's called on first use by (*Client).ListenTCP to not launch -+// goroutines until needed. -+func (c *Client) handleForwards() { -+ go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip")) -+ go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com")) -+} -+ -+// ListenTCP requests the remote peer open a listening socket -+// on laddr. Incoming connections will be available by calling -+// Accept on the returned net.Listener. -+func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { -+ c.handleForwardsOnce.Do(c.handleForwards) -+ if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { -+ return c.autoPortListenWorkaround(laddr) -+ } -+ -+ m := channelForwardMsg{ -+ laddr.IP.String(), -+ uint32(laddr.Port), -+ } -+ // send message -+ ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) -+ if err != nil { -+ return nil, err -+ } -+ if !ok { -+ return nil, errors.New("ssh: tcpip-forward request denied by peer") -+ } -+ -+ // If the original port was 0, then the remote side will -+ // supply a real port number in the response. -+ if laddr.Port == 0 { -+ var p struct { -+ Port uint32 -+ } -+ if err := Unmarshal(resp, &p); err != nil { -+ return nil, err -+ } -+ laddr.Port = int(p.Port) -+ } -+ -+ // Register this forward, using the port number we obtained. -+ ch := c.forwards.add(laddr) -+ -+ return &tcpListener{laddr, c, ch}, nil -+} -+ -+// forwardList stores a mapping between remote -+// forward requests and the tcpListeners. -+type forwardList struct { -+ sync.Mutex -+ entries []forwardEntry -+} -+ -+// forwardEntry represents an established mapping of a laddr on a -+// remote ssh server to a channel connected to a tcpListener. -+type forwardEntry struct { -+ laddr net.Addr -+ c chan forward -+} -+ -+// forward represents an incoming forwarded tcpip connection. The -+// arguments to add/remove/lookup should be address as specified in -+// the original forward-request. -+type forward struct { -+ newCh NewChannel // the ssh client channel underlying this forward -+ raddr net.Addr // the raddr of the incoming connection -+} -+ -+func (l *forwardList) add(addr net.Addr) chan forward { -+ l.Lock() -+ defer l.Unlock() -+ f := forwardEntry{ -+ laddr: addr, -+ c: make(chan forward, 1), -+ } -+ l.entries = append(l.entries, f) -+ return f.c -+} -+ -+// See RFC 4254, section 7.2 -+type forwardedTCPPayload struct { -+ Addr string -+ Port uint32 -+ OriginAddr string -+ OriginPort uint32 -+} -+ -+// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. -+func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { -+ if port == 0 || port > 65535 { -+ return nil, fmt.Errorf("ssh: port number out of range: %d", port) -+ } -+ ip := net.ParseIP(string(addr)) -+ if ip == nil { -+ return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) -+ } -+ return &net.TCPAddr{IP: ip, Port: int(port)}, nil -+} -+ -+func (l *forwardList) handleChannels(in <-chan NewChannel) { -+ for ch := range in { -+ var ( -+ laddr net.Addr -+ raddr net.Addr -+ err error -+ ) -+ switch channelType := ch.ChannelType(); channelType { -+ case "forwarded-tcpip": -+ var payload forwardedTCPPayload -+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil { -+ ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) -+ continue -+ } -+ -+ // RFC 4254 section 7.2 specifies that incoming -+ // addresses should list the address, in string -+ // format. It is implied that this should be an IP -+ // address, as it would be impossible to connect to it -+ // otherwise. -+ laddr, err = parseTCPAddr(payload.Addr, payload.Port) -+ if err != nil { -+ ch.Reject(ConnectionFailed, err.Error()) -+ continue -+ } -+ raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort) -+ if err != nil { -+ ch.Reject(ConnectionFailed, err.Error()) -+ continue -+ } -+ -+ case "forwarded-streamlocal@openssh.com": -+ var payload forwardedStreamLocalPayload -+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil { -+ ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error()) -+ continue -+ } -+ laddr = &net.UnixAddr{ -+ Name: payload.SocketPath, -+ Net: "unix", -+ } -+ raddr = &net.UnixAddr{ -+ Name: "@", -+ Net: "unix", -+ } -+ default: -+ panic(fmt.Errorf("ssh: unknown channel type %s", channelType)) -+ } -+ if ok := l.forward(laddr, raddr, ch); !ok { -+ // Section 7.2, implementations MUST reject spurious incoming -+ // connections. -+ ch.Reject(Prohibited, "no forward for address") -+ continue -+ } -+ -+ } -+} -+ -+// remove removes the forward entry, and the channel feeding its -+// listener. -+func (l *forwardList) remove(addr net.Addr) { -+ l.Lock() -+ defer l.Unlock() -+ for i, f := range l.entries { -+ if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() { -+ l.entries = append(l.entries[:i], l.entries[i+1:]...) -+ close(f.c) -+ return -+ } -+ } -+} -+ -+// closeAll closes and clears all forwards. -+func (l *forwardList) closeAll() { -+ l.Lock() -+ defer l.Unlock() -+ for _, f := range l.entries { -+ close(f.c) -+ } -+ l.entries = nil -+} -+ -+func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool { -+ l.Lock() -+ defer l.Unlock() -+ for _, f := range l.entries { -+ if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() { -+ f.c <- forward{newCh: ch, raddr: raddr} -+ return true -+ } -+ } -+ return false -+} -+ -+type tcpListener struct { -+ laddr *net.TCPAddr -+ -+ conn *Client -+ in <-chan forward -+} -+ -+// Accept waits for and returns the next connection to the listener. -+func (l *tcpListener) Accept() (net.Conn, error) { -+ s, ok := <-l.in -+ if !ok { -+ return nil, io.EOF -+ } -+ ch, incoming, err := s.newCh.Accept() -+ if err != nil { -+ return nil, err -+ } -+ go DiscardRequests(incoming) -+ -+ return &chanConn{ -+ Channel: ch, -+ laddr: l.laddr, -+ raddr: s.raddr, -+ }, nil -+} -+ -+// Close closes the listener. -+func (l *tcpListener) Close() error { -+ m := channelForwardMsg{ -+ l.laddr.IP.String(), -+ uint32(l.laddr.Port), -+ } -+ -+ // this also closes the listener. -+ l.conn.forwards.remove(l.laddr) -+ ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) -+ if err == nil && !ok { -+ err = errors.New("ssh: cancel-tcpip-forward failed") -+ } -+ return err -+} -+ -+// Addr returns the listener's network address. -+func (l *tcpListener) Addr() net.Addr { -+ return l.laddr -+} -+ -+// Dial initiates a connection to the addr from the remote host. -+// The resulting connection has a zero LocalAddr() and RemoteAddr(). -+func (c *Client) Dial(n, addr string) (net.Conn, error) { -+ var ch Channel -+ switch n { -+ case "tcp", "tcp4", "tcp6": -+ // Parse the address into host and numeric port. -+ host, portString, err := net.SplitHostPort(addr) -+ if err != nil { -+ return nil, err -+ } -+ port, err := strconv.ParseUint(portString, 10, 16) -+ if err != nil { -+ return nil, err -+ } -+ ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port)) -+ if err != nil { -+ return nil, err -+ } -+ // Use a zero address for local and remote address. -+ zeroAddr := &net.TCPAddr{ -+ IP: net.IPv4zero, -+ Port: 0, -+ } -+ return &chanConn{ -+ Channel: ch, -+ laddr: zeroAddr, -+ raddr: zeroAddr, -+ }, nil -+ case "unix": -+ var err error -+ ch, err = c.dialStreamLocal(addr) -+ if err != nil { -+ return nil, err -+ } -+ return &chanConn{ -+ Channel: ch, -+ laddr: &net.UnixAddr{ -+ Name: "@", -+ Net: "unix", -+ }, -+ raddr: &net.UnixAddr{ -+ Name: addr, -+ Net: "unix", -+ }, -+ }, nil -+ default: -+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) -+ } -+} -+ -+// DialTCP connects to the remote address raddr on the network net, -+// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used -+// as the local address for the connection. -+func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { -+ if laddr == nil { -+ laddr = &net.TCPAddr{ -+ IP: net.IPv4zero, -+ Port: 0, -+ } -+ } -+ ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) -+ if err != nil { -+ return nil, err -+ } -+ return &chanConn{ -+ Channel: ch, -+ laddr: laddr, -+ raddr: raddr, -+ }, nil -+} -+ -+// RFC 4254 7.2 -+type channelOpenDirectMsg struct { -+ raddr string -+ rport uint32 -+ laddr string -+ lport uint32 -+} -+ -+func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { -+ msg := channelOpenDirectMsg{ -+ raddr: raddr, -+ rport: uint32(rport), -+ laddr: laddr, -+ lport: uint32(lport), -+ } -+ ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) -+ if err != nil { -+ return nil, err -+ } -+ go DiscardRequests(in) -+ return ch, err -+} -+ -+type tcpChan struct { -+ Channel // the backing channel -+} -+ -+// chanConn fulfills the net.Conn interface without -+// the tcpChan having to hold laddr or raddr directly. -+type chanConn struct { -+ Channel -+ laddr, raddr net.Addr -+} -+ -+// LocalAddr returns the local network address. -+func (t *chanConn) LocalAddr() net.Addr { -+ return t.laddr -+} -+ -+// RemoteAddr returns the remote network address. -+func (t *chanConn) RemoteAddr() net.Addr { -+ return t.raddr -+} -+ -+// SetDeadline sets the read and write deadlines associated -+// with the connection. -+func (t *chanConn) SetDeadline(deadline time.Time) error { -+ if err := t.SetReadDeadline(deadline); err != nil { -+ return err -+ } -+ return t.SetWriteDeadline(deadline) -+} -+ -+// SetReadDeadline sets the read deadline. -+// A zero value for t means Read will not time out. -+// After the deadline, the error from Read will implement net.Error -+// with Timeout() == true. -+func (t *chanConn) SetReadDeadline(deadline time.Time) error { -+ // for compatibility with previous version, -+ // the error message contains "tcpChan" -+ return errors.New("ssh: tcpChan: deadline not supported") -+} -+ -+// SetWriteDeadline exists to satisfy the net.Conn interface -+// but is not implemented by this type. It always returns an error. -+func (t *chanConn) SetWriteDeadline(deadline time.Time) error { -+ return errors.New("ssh: tcpChan: deadline not supported") -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/tcpip_test.go b/ms_mod/golang.org/x/crypto/ssh/tcpip_test.go -new file mode 100644 -index 00000000000000..f1265cb4964ede ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/tcpip_test.go -@@ -0,0 +1,20 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "testing" -+) -+ -+func TestAutoPortListenBroken(t *testing.T) { -+ broken := "SSH-2.0-OpenSSH_5.9hh11" -+ works := "SSH-2.0-OpenSSH_6.1" -+ if !isBrokenOpenSSHVersion(broken) { -+ t.Errorf("version %q not marked as broken", broken) -+ } -+ if isBrokenOpenSSHVersion(works) { -+ t.Errorf("version %q marked as broken", works) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go b/ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go -new file mode 100644 -index 00000000000000..a4d1919a9e7d64 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/terminal/terminal.go -@@ -0,0 +1,76 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package terminal provides support functions for dealing with terminals, as -+// commonly found on UNIX systems. -+// -+// Deprecated: this package moved to golang.org/x/term. -+package terminal -+ -+import ( -+ "io" -+ -+ "golang.org/x/term" -+) -+ -+// EscapeCodes contains escape sequences that can be written to the terminal in -+// order to achieve different styles of text. -+type EscapeCodes = term.EscapeCodes -+ -+// Terminal contains the state for running a VT100 terminal that is capable of -+// reading lines of input. -+type Terminal = term.Terminal -+ -+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is -+// a local terminal, that terminal must first have been put into raw mode. -+// prompt is a string that is written at the start of each input line (i.e. -+// "> "). -+func NewTerminal(c io.ReadWriter, prompt string) *Terminal { -+ return term.NewTerminal(c, prompt) -+} -+ -+// ErrPasteIndicator may be returned from ReadLine as the error, in addition -+// to valid line data. It indicates that bracketed paste mode is enabled and -+// that the returned line consists only of pasted data. Programs may wish to -+// interpret pasted data more literally than typed data. -+var ErrPasteIndicator = term.ErrPasteIndicator -+ -+// State contains the state of a terminal. -+type State = term.State -+ -+// IsTerminal returns whether the given file descriptor is a terminal. -+func IsTerminal(fd int) bool { -+ return term.IsTerminal(fd) -+} -+ -+// ReadPassword reads a line of input from a terminal without local echo. This -+// is commonly used for inputting passwords and other sensitive data. The slice -+// returned does not include the \n. -+func ReadPassword(fd int) ([]byte, error) { -+ return term.ReadPassword(fd) -+} -+ -+// MakeRaw puts the terminal connected to the given file descriptor into raw -+// mode and returns the previous state of the terminal so that it can be -+// restored. -+func MakeRaw(fd int) (*State, error) { -+ return term.MakeRaw(fd) -+} -+ -+// Restore restores the terminal connected to the given file descriptor to a -+// previous state. -+func Restore(fd int, oldState *State) error { -+ return term.Restore(fd, oldState) -+} -+ -+// GetState returns the current state of a terminal which may be useful to -+// restore the terminal after a signal. -+func GetState(fd int) (*State, error) { -+ return term.GetState(fd) -+} -+ -+// GetSize returns the dimensions of the given terminal. -+func GetSize(fd int) (width, height int, err error) { -+ return term.GetSize(fd) -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go -new file mode 100644 -index 00000000000000..43fbdb22eb4e74 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/agent_unix_test.go -@@ -0,0 +1,59 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris -+ -+package test -+ -+import ( -+ "bytes" -+ "testing" -+ -+ "golang.org/x/crypto/ssh" -+ "golang.org/x/crypto/ssh/agent" -+) -+ -+func TestAgentForward(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ keyring := agent.NewKeyring() -+ if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil { -+ t.Fatalf("Error adding key: %s", err) -+ } -+ if err := keyring.Add(agent.AddedKey{ -+ PrivateKey: testPrivateKeys["dsa"], -+ ConfirmBeforeUse: true, -+ LifetimeSecs: 3600, -+ }); err != nil { -+ t.Fatalf("Error adding key with constraints: %s", err) -+ } -+ pub := testPublicKeys["dsa"] -+ -+ sess, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("NewSession: %v", err) -+ } -+ if err := agent.RequestAgentForwarding(sess); err != nil { -+ t.Fatalf("RequestAgentForwarding: %v", err) -+ } -+ -+ if err := agent.ForwardToAgent(conn, keyring); err != nil { -+ t.Fatalf("SetupForwardKeyring: %v", err) -+ } -+ out, err := sess.CombinedOutput("ssh-add -L") -+ if err != nil { -+ t.Fatalf("running ssh-add: %v, out %s", err, out) -+ } -+ key, _, _, _, err := ssh.ParseAuthorizedKey(out) -+ if err != nil { -+ t.Fatalf("ParseAuthorizedKey(%q): %v", out, err) -+ } -+ -+ if !bytes.Equal(key.Marshal(), pub.Marshal()) { -+ t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub)) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/banner_test.go b/ms_mod/golang.org/x/crypto/ssh/test/banner_test.go -new file mode 100644 -index 00000000000000..3bfdd4b059094f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/banner_test.go -@@ -0,0 +1,32 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris -+ -+package test -+ -+import ( -+ "testing" -+) -+ -+func TestBannerCallbackAgainstOpenSSH(t *testing.T) { -+ server := newServer(t) -+ -+ clientConf := clientConfig() -+ -+ var receivedBanner string -+ clientConf.BannerCallback = func(message string) error { -+ receivedBanner = message -+ return nil -+ } -+ -+ conn := server.Dial(clientConf) -+ defer conn.Close() -+ -+ expected := "Server Banner" -+ if receivedBanner != expected { -+ t.Fatalf("got %v; want %v", receivedBanner, expected) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/cert_test.go b/ms_mod/golang.org/x/crypto/ssh/test/cert_test.go -new file mode 100644 -index 00000000000000..83dd534c5ca5db ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/cert_test.go -@@ -0,0 +1,77 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris -+ -+package test -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "testing" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly -+func TestCertLogin(t *testing.T) { -+ s := newServer(t) -+ -+ // Use a key different from the default. -+ clientKey := testSigners["dsa"] -+ caAuthKey := testSigners["ecdsa"] -+ cert := &ssh.Certificate{ -+ Key: clientKey.PublicKey(), -+ ValidPrincipals: []string{username()}, -+ CertType: ssh.UserCert, -+ ValidBefore: ssh.CertTimeInfinity, -+ } -+ if err := cert.SignCert(rand.Reader, caAuthKey); err != nil { -+ t.Fatalf("SetSignature: %v", err) -+ } -+ -+ certSigner, err := ssh.NewCertSigner(cert, clientKey) -+ if err != nil { -+ t.Fatalf("NewCertSigner: %v", err) -+ } -+ -+ conf := &ssh.ClientConfig{ -+ User: username(), -+ HostKeyCallback: (&ssh.CertChecker{ -+ IsHostAuthority: func(pk ssh.PublicKey, addr string) bool { -+ return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal()) -+ }, -+ }).CheckHostKey, -+ } -+ conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner)) -+ -+ for _, test := range []struct { -+ addr string -+ succeed bool -+ }{ -+ {addr: "host.example.com:22", succeed: true}, -+ {addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK -+ {addr: "host.example.com", succeed: false}, // port must be specified -+ {addr: "host.ex4mple.com:22", succeed: false}, // wrong host -+ } { -+ client, err := s.TryDialWithAddr(conf, test.addr) -+ -+ // Always close client if opened successfully -+ if err == nil { -+ client.Close() -+ } -+ -+ // Now evaluate whether the test failed or passed -+ if test.succeed { -+ if err != nil { -+ t.Fatalf("TryDialWithAddr: %v", err) -+ } -+ } else { -+ if err == nil { -+ t.Fatalf("TryDialWithAddr, unexpected success") -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go -new file mode 100644 -index 00000000000000..4a7ec31737581a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/dial_unix_test.go -@@ -0,0 +1,127 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !windows && !js && !wasip1 -+// +build !windows,!js,!wasip1 -+ -+package test -+ -+// direct-tcpip and direct-streamlocal functional tests -+ -+import ( -+ "fmt" -+ "io" -+ "net" -+ "strings" -+ "testing" -+) -+ -+type dialTester interface { -+ TestServerConn(t *testing.T, c net.Conn) -+ TestClientConn(t *testing.T, c net.Conn) -+} -+ -+func testDial(t *testing.T, n, listenAddr string, x dialTester) { -+ server := newServer(t) -+ sshConn := server.Dial(clientConfig()) -+ defer sshConn.Close() -+ -+ l, err := net.Listen(n, listenAddr) -+ if err != nil { -+ t.Fatalf("Listen: %v", err) -+ } -+ defer l.Close() -+ -+ testData := fmt.Sprintf("hello from %s, %s", n, listenAddr) -+ go func() { -+ for { -+ c, err := l.Accept() -+ if err != nil { -+ break -+ } -+ x.TestServerConn(t, c) -+ -+ io.WriteString(c, testData) -+ c.Close() -+ } -+ }() -+ -+ conn, err := sshConn.Dial(n, l.Addr().String()) -+ if err != nil { -+ t.Fatalf("Dial: %v", err) -+ } -+ x.TestClientConn(t, conn) -+ defer conn.Close() -+ b, err := io.ReadAll(conn) -+ if err != nil { -+ t.Fatalf("ReadAll: %v", err) -+ } -+ t.Logf("got %q", string(b)) -+ if string(b) != testData { -+ t.Fatalf("expected %q, got %q", testData, string(b)) -+ } -+} -+ -+type tcpDialTester struct { -+ listenAddr string -+} -+ -+func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) { -+ host := strings.Split(x.listenAddr, ":")[0] -+ prefix := host + ":" -+ if !strings.HasPrefix(c.LocalAddr().String(), prefix) { -+ t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String()) -+ } -+ if !strings.HasPrefix(c.RemoteAddr().String(), prefix) { -+ t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String()) -+ } -+} -+ -+func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) { -+ // we use zero addresses. see *Client.Dial. -+ if c.LocalAddr().String() != "0.0.0.0:0" { -+ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String()) -+ } -+ if c.RemoteAddr().String() != "0.0.0.0:0" { -+ t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String()) -+ } -+} -+ -+func TestDialTCP(t *testing.T) { -+ x := &tcpDialTester{ -+ listenAddr: "127.0.0.1:0", -+ } -+ testDial(t, "tcp", x.listenAddr, x) -+} -+ -+type unixDialTester struct { -+ listenAddr string -+} -+ -+func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) { -+ if c.LocalAddr().String() != x.listenAddr { -+ t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String()) -+ } -+ if c.RemoteAddr().String() != "@" && c.RemoteAddr().String() != "" { -+ t.Fatalf("expected \"@\" or \"\", got %q", c.RemoteAddr().String()) -+ } -+} -+ -+func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) { -+ if c.RemoteAddr().String() != x.listenAddr { -+ t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String()) -+ } -+ if c.LocalAddr().String() != "@" { -+ t.Fatalf("expected \"@\", got %q", c.LocalAddr().String()) -+ } -+} -+ -+func TestDialUnix(t *testing.T) { -+ addr, cleanup := newTempSocket(t) -+ defer cleanup() -+ x := &unixDialTester{ -+ listenAddr: addr, -+ } -+ testDial(t, "unix", x.listenAddr, x) -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/doc.go b/ms_mod/golang.org/x/crypto/ssh/test/doc.go -new file mode 100644 -index 00000000000000..198f0ca1e20570 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/doc.go -@@ -0,0 +1,7 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package test contains integration tests for the -+// golang.org/x/crypto/ssh package. -+package test // import "golang.org/x/crypto/ssh/test" -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go -new file mode 100644 -index 00000000000000..1171bc3a14ef01 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/forward_unix_test.go -@@ -0,0 +1,198 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -+// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris -+ -+package test -+ -+import ( -+ "bytes" -+ "fmt" -+ "io" -+ "math/rand" -+ "net" -+ "testing" -+ "time" -+) -+ -+type closeWriter interface { -+ CloseWrite() error -+} -+ -+func testPortForward(t *testing.T, n, listenAddr string) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ sshListener, err := conn.Listen(n, listenAddr) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ errCh := make(chan error, 1) -+ -+ go func() { -+ defer close(errCh) -+ sshConn, err := sshListener.Accept() -+ if err != nil { -+ errCh <- fmt.Errorf("listen.Accept failed: %v", err) -+ return -+ } -+ defer sshConn.Close() -+ -+ _, err = io.Copy(sshConn, sshConn) -+ if err != nil && err != io.EOF { -+ errCh <- fmt.Errorf("ssh client copy: %v", err) -+ } -+ }() -+ -+ forwardedAddr := sshListener.Addr().String() -+ netConn, err := net.Dial(n, forwardedAddr) -+ if err != nil { -+ t.Fatalf("net dial failed: %v", err) -+ } -+ -+ readChan := make(chan []byte) -+ go func() { -+ data, _ := io.ReadAll(netConn) -+ readChan <- data -+ }() -+ -+ // Invent some data. -+ data := make([]byte, 100*1000) -+ for i := range data { -+ data[i] = byte(i % 255) -+ } -+ -+ var sent []byte -+ for len(sent) < 1000*1000 { -+ // Send random sized chunks -+ m := rand.Intn(len(data)) -+ n, err := netConn.Write(data[:m]) -+ if err != nil { -+ break -+ } -+ sent = append(sent, data[:n]...) -+ } -+ if err := netConn.(closeWriter).CloseWrite(); err != nil { -+ t.Errorf("netConn.CloseWrite: %v", err) -+ } -+ -+ // Check for errors on server goroutine -+ err = <-errCh -+ if err != nil { -+ t.Fatalf("server: %v", err) -+ } -+ -+ read := <-readChan -+ -+ if len(sent) != len(read) { -+ t.Fatalf("got %d bytes, want %d", len(read), len(sent)) -+ } -+ if bytes.Compare(sent, read) != 0 { -+ t.Fatalf("read back data does not match") -+ } -+ -+ if err := sshListener.Close(); err != nil { -+ t.Fatalf("sshListener.Close: %v", err) -+ } -+ -+ // Check that the forward disappeared. -+ netConn, err = net.Dial(n, forwardedAddr) -+ if err == nil { -+ netConn.Close() -+ t.Errorf("still listening to %s after closing", forwardedAddr) -+ } -+} -+ -+func TestPortForwardTCP(t *testing.T) { -+ testPortForward(t, "tcp", "localhost:0") -+} -+ -+func TestPortForwardUnix(t *testing.T) { -+ addr, cleanup := newTempSocket(t) -+ defer cleanup() -+ testPortForward(t, "unix", addr) -+} -+ -+func testAcceptClose(t *testing.T, n, listenAddr string) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ -+ sshListener, err := conn.Listen(n, listenAddr) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ quit := make(chan error, 1) -+ go func() { -+ for { -+ c, err := sshListener.Accept() -+ if err != nil { -+ quit <- err -+ break -+ } -+ c.Close() -+ } -+ }() -+ sshListener.Close() -+ -+ select { -+ case <-time.After(1 * time.Second): -+ t.Errorf("timeout: listener did not close.") -+ case err := <-quit: -+ t.Logf("quit as expected (error %v)", err) -+ } -+} -+ -+func TestAcceptCloseTCP(t *testing.T) { -+ testAcceptClose(t, "tcp", "localhost:0") -+} -+ -+func TestAcceptCloseUnix(t *testing.T) { -+ addr, cleanup := newTempSocket(t) -+ defer cleanup() -+ testAcceptClose(t, "unix", addr) -+} -+ -+// Check that listeners exit if the underlying client transport dies. -+func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) { -+ server := newServer(t) -+ client := server.Dial(clientConfig()) -+ -+ sshListener, err := client.Listen(n, listenAddr) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ quit := make(chan error, 1) -+ go func() { -+ for { -+ c, err := sshListener.Accept() -+ if err != nil { -+ quit <- err -+ break -+ } -+ c.Close() -+ } -+ }() -+ -+ // It would be even nicer if we closed the server side, but it -+ // is more involved as the fd for that side is dup()ed. -+ server.lastDialConn.Close() -+ -+ err = <-quit -+ t.Logf("quit as expected (error %v)", err) -+} -+ -+func TestPortForwardConnectionCloseTCP(t *testing.T) { -+ testPortForwardConnectionClose(t, "tcp", "localhost:0") -+} -+ -+func TestPortForwardConnectionCloseUnix(t *testing.T) { -+ addr, cleanup := newTempSocket(t) -+ defer cleanup() -+ testPortForwardConnectionClose(t, "unix", addr) -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go b/ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go -new file mode 100644 -index 00000000000000..403d7363ab0206 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/multi_auth_test.go -@@ -0,0 +1,144 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Tests for ssh client multi-auth -+// -+// These tests run a simple go ssh client against OpenSSH server -+// over unix domain sockets. The tests use multiple combinations -+// of password, keyboard-interactive and publickey authentication -+// methods. -+// -+// A wrapper library for making sshd PAM authentication use test -+// passwords is required in ./sshd_test_pw.so. If the library does -+// not exist these tests will be skipped. See compile instructions -+// (for linux) in file ./sshd_test_pw.c. -+ -+//go:build linux -+// +build linux -+ -+package test -+ -+import ( -+ "fmt" -+ "strings" -+ "testing" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+// test cases -+type multiAuthTestCase struct { -+ authMethods []string -+ expectedPasswordCbs int -+ expectedKbdIntCbs int -+} -+ -+// test context -+type multiAuthTestCtx struct { -+ password string -+ numPasswordCbs int -+ numKbdIntCbs int -+} -+ -+// create test context -+func newMultiAuthTestCtx(t *testing.T) *multiAuthTestCtx { -+ password, err := randomPassword() -+ if err != nil { -+ t.Fatalf("Failed to generate random test password: %s", err.Error()) -+ } -+ -+ return &multiAuthTestCtx{ -+ password: password, -+ } -+} -+ -+// password callback -+func (ctx *multiAuthTestCtx) passwordCb() (secret string, err error) { -+ ctx.numPasswordCbs++ -+ return ctx.password, nil -+} -+ -+// keyboard-interactive callback -+func (ctx *multiAuthTestCtx) kbdIntCb(user, instruction string, questions []string, echos []bool) (answers []string, err error) { -+ if len(questions) == 0 { -+ return nil, nil -+ } -+ -+ ctx.numKbdIntCbs++ -+ if len(questions) == 1 { -+ return []string{ctx.password}, nil -+ } -+ -+ return nil, fmt.Errorf("unsupported keyboard-interactive flow") -+} -+ -+// TestMultiAuth runs several subtests for different combinations of password, keyboard-interactive and publickey authentication methods -+func TestMultiAuth(t *testing.T) { -+ testCases := []multiAuthTestCase{ -+ // Test password,publickey authentication, assert that password callback is called 1 time -+ { -+ authMethods: []string{"password", "publickey"}, -+ expectedPasswordCbs: 1, -+ }, -+ // Test keyboard-interactive,publickey authentication, assert that keyboard-interactive callback is called 1 time -+ { -+ authMethods: []string{"keyboard-interactive", "publickey"}, -+ expectedKbdIntCbs: 1, -+ }, -+ // Test publickey,password authentication, assert that password callback is called 1 time -+ { -+ authMethods: []string{"publickey", "password"}, -+ expectedPasswordCbs: 1, -+ }, -+ // Test publickey,keyboard-interactive authentication, assert that keyboard-interactive callback is called 1 time -+ { -+ authMethods: []string{"publickey", "keyboard-interactive"}, -+ expectedKbdIntCbs: 1, -+ }, -+ // Test password,password authentication, assert that password callback is called 2 times -+ { -+ authMethods: []string{"password", "password"}, -+ expectedPasswordCbs: 2, -+ }, -+ } -+ -+ for _, testCase := range testCases { -+ t.Run(strings.Join(testCase.authMethods, ","), func(t *testing.T) { -+ ctx := newMultiAuthTestCtx(t) -+ -+ server := newServerForConfig(t, "MultiAuth", map[string]string{"AuthMethods": strings.Join(testCase.authMethods, ",")}) -+ -+ clientConfig := clientConfig() -+ server.setTestPassword(clientConfig.User, ctx.password) -+ -+ publicKeyAuthMethod := clientConfig.Auth[0] -+ clientConfig.Auth = nil -+ for _, authMethod := range testCase.authMethods { -+ switch authMethod { -+ case "publickey": -+ clientConfig.Auth = append(clientConfig.Auth, publicKeyAuthMethod) -+ case "password": -+ clientConfig.Auth = append(clientConfig.Auth, -+ ssh.RetryableAuthMethod(ssh.PasswordCallback(ctx.passwordCb), 5)) -+ case "keyboard-interactive": -+ clientConfig.Auth = append(clientConfig.Auth, -+ ssh.RetryableAuthMethod(ssh.KeyboardInteractive(ctx.kbdIntCb), 5)) -+ default: -+ t.Fatalf("Unknown authentication method %s", authMethod) -+ } -+ } -+ -+ conn := server.Dial(clientConfig) -+ defer conn.Close() -+ -+ if ctx.numPasswordCbs != testCase.expectedPasswordCbs { -+ t.Fatalf("passwordCallback was called %d times, expected %d times", ctx.numPasswordCbs, testCase.expectedPasswordCbs) -+ } -+ -+ if ctx.numKbdIntCbs != testCase.expectedKbdIntCbs { -+ t.Fatalf("keyboardInteractiveCallback was called %d times, expected %d times", ctx.numKbdIntCbs, testCase.expectedKbdIntCbs) -+ } -+ }) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/session_test.go b/ms_mod/golang.org/x/crypto/ssh/test/session_test.go -new file mode 100644 -index 00000000000000..4745ed9dbb1a92 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/session_test.go -@@ -0,0 +1,455 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !windows && !js && !wasip1 -+// +build !windows,!js,!wasip1 -+ -+package test -+ -+// Session functional tests. -+ -+import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "io" -+ "path/filepath" -+ "regexp" -+ "runtime" -+ "strings" -+ "testing" -+ -+ "golang.org/x/crypto/ssh" -+) -+ -+func TestRunCommandSuccess(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ defer session.Close() -+ err = session.Run("true") -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+} -+ -+func TestHostKeyCheck(t *testing.T) { -+ server := newServer(t) -+ -+ conf := clientConfig() -+ hostDB := hostKeyDB() -+ conf.HostKeyCallback = hostDB.Check -+ -+ // change the keys. -+ hostDB.keys[ssh.KeyAlgoRSA][25]++ -+ hostDB.keys[ssh.KeyAlgoDSA][25]++ -+ hostDB.keys[ssh.KeyAlgoECDSA256][25]++ -+ -+ conn, err := server.TryDial(conf) -+ if err == nil { -+ conn.Close() -+ t.Fatalf("dial should have failed.") -+ } else if !strings.Contains(err.Error(), "host key mismatch") { -+ t.Fatalf("'host key mismatch' not found in %v", err) -+ } -+} -+ -+func TestRunCommandStdin(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ defer session.Close() -+ -+ r, w := io.Pipe() -+ defer r.Close() -+ defer w.Close() -+ session.Stdin = r -+ -+ err = session.Run("true") -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+} -+ -+func TestRunCommandStdinError(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ defer session.Close() -+ -+ r, w := io.Pipe() -+ defer r.Close() -+ session.Stdin = r -+ pipeErr := errors.New("closing write end of pipe") -+ w.CloseWithError(pipeErr) -+ -+ err = session.Run("true") -+ if err != pipeErr { -+ t.Fatalf("expected %v, found %v", pipeErr, err) -+ } -+} -+ -+func TestRunCommandFailed(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ defer session.Close() -+ err = session.Run(`bash -c "kill -9 $$"`) -+ if err == nil { -+ t.Fatalf("session succeeded: %v", err) -+ } -+} -+ -+func TestRunCommandWeClosed(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ err = session.Shell() -+ if err != nil { -+ t.Fatalf("shell failed: %v", err) -+ } -+ err = session.Close() -+ if err != nil { -+ t.Fatalf("shell failed: %v", err) -+ } -+} -+ -+func TestFuncLargeRead(t *testing.T) { -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("unable to create new session: %s", err) -+ } -+ -+ stdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Fatalf("unable to acquire stdout pipe: %s", err) -+ } -+ -+ err = session.Start("dd if=/dev/urandom bs=2048 count=1024") -+ if err != nil { -+ t.Fatalf("unable to execute remote command: %s", err) -+ } -+ -+ buf := new(bytes.Buffer) -+ n, err := io.Copy(buf, stdout) -+ if err != nil { -+ t.Fatalf("error reading from remote stdout: %s", err) -+ } -+ -+ if n != 2048*1024 { -+ t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n) -+ } -+} -+ -+func TestKeyChange(t *testing.T) { -+ server := newServer(t) -+ conf := clientConfig() -+ hostDB := hostKeyDB() -+ conf.HostKeyCallback = hostDB.Check -+ conf.RekeyThreshold = 1024 -+ conn := server.Dial(conf) -+ defer conn.Close() -+ -+ for i := 0; i < 4; i++ { -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("unable to create new session: %s", err) -+ } -+ -+ stdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Fatalf("unable to acquire stdout pipe: %s", err) -+ } -+ -+ err = session.Start("dd if=/dev/urandom bs=1024 count=1") -+ if err != nil { -+ t.Fatalf("unable to execute remote command: %s", err) -+ } -+ buf := new(bytes.Buffer) -+ n, err := io.Copy(buf, stdout) -+ if err != nil { -+ t.Fatalf("error reading from remote stdout: %s", err) -+ } -+ -+ want := int64(1024) -+ if n != want { -+ t.Fatalf("Expected %d bytes but read only %d from remote command", want, n) -+ } -+ } -+ -+ if changes := hostDB.checkCount; changes < 4 { -+ t.Errorf("got %d key changes, want 4", changes) -+ } -+} -+ -+func TestValidTerminalMode(t *testing.T) { -+ if runtime.GOOS == "aix" { -+ // On AIX, sshd cannot acquire /dev/pts/* if launched as -+ // a non-root user. -+ t.Skipf("skipping on %s", runtime.GOOS) -+ } -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ defer session.Close() -+ -+ stdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Fatalf("unable to acquire stdout pipe: %s", err) -+ } -+ -+ stdin, err := session.StdinPipe() -+ if err != nil { -+ t.Fatalf("unable to acquire stdin pipe: %s", err) -+ } -+ -+ tm := ssh.TerminalModes{ssh.ECHO: 0} -+ if err = session.RequestPty("xterm", 80, 40, tm); err != nil { -+ t.Fatalf("req-pty failed: %s", err) -+ } -+ -+ err = session.Shell() -+ if err != nil { -+ t.Fatalf("session failed: %s", err) -+ } -+ -+ if _, err := io.WriteString(stdin, "echo && echo SHELL $SHELL && stty -a && exit\n"); err != nil { -+ t.Fatal(err) -+ } -+ -+ buf := new(strings.Builder) -+ if _, err := io.Copy(buf, stdout); err != nil { -+ t.Fatalf("reading failed: %s", err) -+ } -+ -+ if testing.Verbose() { -+ t.Logf("echo && echo SHELL $SHELL && stty -a && exit:\n%s", buf) -+ } -+ -+ shellLine := regexp.MustCompile("(?m)^SHELL (.*)$").FindStringSubmatch(buf.String()) -+ if len(shellLine) != 2 { -+ t.Fatalf("missing output from echo SHELL $SHELL") -+ } -+ switch shell := filepath.Base(strings.TrimSpace(shellLine[1])); shell { -+ case "sh", "bash": -+ default: -+ t.Skipf("skipping test on non-Bourne shell %q", shell) -+ } -+ -+ if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { -+ t.Fatal("terminal mode failure: expected -echo in stty output") -+ } -+} -+ -+func TestWindowChange(t *testing.T) { -+ if runtime.GOOS == "aix" { -+ // On AIX, sshd cannot acquire /dev/pts/* if launched as -+ // a non-root user. -+ t.Skipf("skipping on %s", runtime.GOOS) -+ } -+ server := newServer(t) -+ conn := server.Dial(clientConfig()) -+ defer conn.Close() -+ -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("session failed: %v", err) -+ } -+ defer session.Close() -+ -+ stdout, err := session.StdoutPipe() -+ if err != nil { -+ t.Fatalf("unable to acquire stdout pipe: %s", err) -+ } -+ -+ stdin, err := session.StdinPipe() -+ if err != nil { -+ t.Fatalf("unable to acquire stdin pipe: %s", err) -+ } -+ -+ tm := ssh.TerminalModes{ssh.ECHO: 0} -+ if err = session.RequestPty("xterm", 80, 40, tm); err != nil { -+ t.Fatalf("req-pty failed: %s", err) -+ } -+ -+ if err := session.WindowChange(100, 100); err != nil { -+ t.Fatalf("window-change failed: %s", err) -+ } -+ -+ err = session.Shell() -+ if err != nil { -+ t.Fatalf("session failed: %s", err) -+ } -+ -+ stdin.Write([]byte("stty size && exit\n")) -+ -+ var buf bytes.Buffer -+ if _, err := io.Copy(&buf, stdout); err != nil { -+ t.Fatalf("reading failed: %s", err) -+ } -+ -+ if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") { -+ t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput) -+ } -+} -+ -+func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { -+ server := newServer(t) -+ conf := clientConfig() -+ conf.Ciphers = []string{cipher} -+ // Don't fail if sshd doesn't have the cipher. -+ conf.Ciphers = append(conf.Ciphers, cipherOrder...) -+ conn, err := server.TryDial(conf) -+ if err != nil { -+ t.Fatalf("TryDial: %v", err) -+ } -+ defer conn.Close() -+ -+ numBytes := 4096 -+ -+ // Exercise sending data to the server -+ if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { -+ t.Fatalf("SendRequest: %v", err) -+ } -+ -+ // Exercise receiving data from the server -+ session, err := conn.NewSession() -+ if err != nil { -+ t.Fatalf("NewSession: %v", err) -+ } -+ -+ out, err := session.Output(fmt.Sprintf("dd if=/dev/zero bs=%d count=1", numBytes)) -+ if err != nil { -+ t.Fatalf("Output: %v", err) -+ } -+ -+ if len(out) != numBytes { -+ t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) -+ } -+} -+ -+var deprecatedCiphers = []string{ -+ "aes128-cbc", "3des-cbc", -+ "arcfour128", "arcfour256", -+} -+ -+func TestCiphers(t *testing.T) { -+ var config ssh.Config -+ config.SetDefaults() -+ cipherOrder := append(config.Ciphers, deprecatedCiphers...) -+ -+ for _, ciph := range cipherOrder { -+ t.Run(ciph, func(t *testing.T) { -+ testOneCipher(t, ciph, cipherOrder) -+ }) -+ } -+} -+ -+func TestMACs(t *testing.T) { -+ var config ssh.Config -+ config.SetDefaults() -+ macOrder := config.MACs -+ -+ for _, mac := range macOrder { -+ t.Run(mac, func(t *testing.T) { -+ server := newServer(t) -+ conf := clientConfig() -+ conf.MACs = []string{mac} -+ // Don't fail if sshd doesn't have the MAC. -+ conf.MACs = append(conf.MACs, macOrder...) -+ if conn, err := server.TryDial(conf); err == nil { -+ conn.Close() -+ } else { -+ t.Fatalf("failed for MAC %q", mac) -+ } -+ }) -+ } -+} -+ -+func TestKeyExchanges(t *testing.T) { -+ var config ssh.Config -+ config.SetDefaults() -+ kexOrder := config.KeyExchanges -+ // Based on the discussion in #17230, the key exchange algorithms -+ // diffie-hellman-group-exchange-sha1 and diffie-hellman-group-exchange-sha256 -+ // are not included in the default list of supported kex so we have to add them -+ // here manually. -+ kexOrder = append(kexOrder, "diffie-hellman-group-exchange-sha1", "diffie-hellman-group-exchange-sha256") -+ // The key exchange algorithms diffie-hellman-group16-sha512 is disabled by -+ // default so we add it here manually. -+ kexOrder = append(kexOrder, "diffie-hellman-group16-sha512") -+ for _, kex := range kexOrder { -+ t.Run(kex, func(t *testing.T) { -+ server := newServer(t) -+ conf := clientConfig() -+ // Don't fail if sshd doesn't have the kex. -+ conf.KeyExchanges = append([]string{kex}, kexOrder...) -+ conn, err := server.TryDial(conf) -+ if err == nil { -+ conn.Close() -+ } else { -+ t.Errorf("failed for kex %q", kex) -+ } -+ }) -+ } -+} -+ -+func TestClientAuthAlgorithms(t *testing.T) { -+ for _, key := range []string{ -+ "rsa", -+ "dsa", -+ "ecdsa", -+ "ed25519", -+ } { -+ t.Run(key, func(t *testing.T) { -+ server := newServer(t) -+ conf := clientConfig() -+ conf.SetDefaults() -+ conf.Auth = []ssh.AuthMethod{ -+ ssh.PublicKeys(testSigners[key]), -+ } -+ -+ conn, err := server.TryDial(conf) -+ if err == nil { -+ conn.Close() -+ } else { -+ t.Errorf("failed for key %q", key) -+ } -+ }) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c b/ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c -new file mode 100644 -index 00000000000000..2794a563a41726 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/sshd_test_pw.c -@@ -0,0 +1,173 @@ -+// Copyright 2017 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// sshd_test_pw.c -+// Wrapper to inject test password data for sshd PAM authentication -+// -+// This wrapper implements custom versions of getpwnam, getpwnam_r, -+// getspnam and getspnam_r. These functions first call their real -+// libc versions, then check if the requested user matches test user -+// specified in env variable TEST_USER and if so replace the password -+// with crypted() value of TEST_PASSWD env variable. -+// -+// Compile: -+// gcc -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c -+// -+// Compile with debug: -+// gcc -DVERBOSE -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c -+// -+// Run sshd: -+// LD_PRELOAD="sshd_test_pw.so" TEST_USER="..." TEST_PASSWD="..." sshd ... -+ -+// +build ignore -+ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef VERBOSE -+#define DEBUG(X...) fprintf(stderr, X) -+#else -+#define DEBUG(X...) while (0) { } -+#endif -+ -+/* crypt() password */ -+static char * -+pwhash(char *passwd) { -+ return strdup(crypt(passwd, "$6$")); -+} -+ -+/* Pointers to real functions in libc */ -+static struct passwd * (*real_getpwnam)(const char *) = NULL; -+static int (*real_getpwnam_r)(const char *, struct passwd *, char *, size_t, struct passwd **) = NULL; -+static struct spwd * (*real_getspnam)(const char *) = NULL; -+static int (*real_getspnam_r)(const char *, struct spwd *, char *, size_t, struct spwd **) = NULL; -+ -+/* Cached test user and test password */ -+static char *test_user = NULL; -+static char *test_passwd_hash = NULL; -+ -+static void -+init(void) { -+ /* Fetch real libc function pointers */ -+ real_getpwnam = dlsym(RTLD_NEXT, "getpwnam"); -+ real_getpwnam_r = dlsym(RTLD_NEXT, "getpwnam_r"); -+ real_getspnam = dlsym(RTLD_NEXT, "getspnam"); -+ real_getspnam_r = dlsym(RTLD_NEXT, "getspnam_r"); -+ -+ /* abort if env variables are not defined */ -+ if (getenv("TEST_USER") == NULL || getenv("TEST_PASSWD") == NULL) { -+ fprintf(stderr, "env variables TEST_USER and TEST_PASSWD are missing\n"); -+ abort(); -+ } -+ -+ /* Fetch test user and test password from env */ -+ test_user = strdup(getenv("TEST_USER")); -+ test_passwd_hash = pwhash(getenv("TEST_PASSWD")); -+ -+ DEBUG("sshd_test_pw init():\n"); -+ DEBUG("\treal_getpwnam: %p\n", real_getpwnam); -+ DEBUG("\treal_getpwnam_r: %p\n", real_getpwnam_r); -+ DEBUG("\treal_getspnam: %p\n", real_getspnam); -+ DEBUG("\treal_getspnam_r: %p\n", real_getspnam_r); -+ DEBUG("\tTEST_USER: '%s'\n", test_user); -+ DEBUG("\tTEST_PASSWD: '%s'\n", getenv("TEST_PASSWD")); -+ DEBUG("\tTEST_PASSWD_HASH: '%s'\n", test_passwd_hash); -+} -+ -+static int -+is_test_user(const char *name) { -+ if (test_user != NULL && strcmp(test_user, name) == 0) -+ return 1; -+ return 0; -+} -+ -+/* getpwnam */ -+ -+struct passwd * -+getpwnam(const char *name) { -+ struct passwd *pw; -+ -+ DEBUG("sshd_test_pw getpwnam(%s)\n", name); -+ -+ if (real_getpwnam == NULL) -+ init(); -+ if ((pw = real_getpwnam(name)) == NULL) -+ return NULL; -+ -+ if (is_test_user(name)) -+ pw->pw_passwd = strdup(test_passwd_hash); -+ -+ return pw; -+} -+ -+/* getpwnam_r */ -+ -+int -+getpwnam_r(const char *name, -+ struct passwd *pwd, -+ char *buf, -+ size_t buflen, -+ struct passwd **result) { -+ int r; -+ -+ DEBUG("sshd_test_pw getpwnam_r(%s)\n", name); -+ -+ if (real_getpwnam_r == NULL) -+ init(); -+ if ((r = real_getpwnam_r(name, pwd, buf, buflen, result)) != 0 || *result == NULL) -+ return r; -+ -+ if (is_test_user(name)) -+ pwd->pw_passwd = strdup(test_passwd_hash); -+ -+ return 0; -+} -+ -+/* getspnam */ -+ -+struct spwd * -+getspnam(const char *name) { -+ struct spwd *sp; -+ -+ DEBUG("sshd_test_pw getspnam(%s)\n", name); -+ -+ if (real_getspnam == NULL) -+ init(); -+ if ((sp = real_getspnam(name)) == NULL) -+ return NULL; -+ -+ if (is_test_user(name)) -+ sp->sp_pwdp = strdup(test_passwd_hash); -+ -+ return sp; -+} -+ -+/* getspnam_r */ -+ -+int -+getspnam_r(const char *name, -+ struct spwd *spbuf, -+ char *buf, -+ size_t buflen, -+ struct spwd **spbufp) { -+ int r; -+ -+ DEBUG("sshd_test_pw getspnam_r(%s)\n", name); -+ -+ if (real_getspnam_r == NULL) -+ init(); -+ if ((r = real_getspnam_r(name, spbuf, buf, buflen, spbufp)) != 0) -+ return r; -+ -+ if (is_test_user(name)) -+ spbuf->sp_pwdp = strdup(test_passwd_hash); -+ -+ return r; -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go b/ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go -new file mode 100644 -index 00000000000000..f3f55db1288e45 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/test_unix_test.go -@@ -0,0 +1,364 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || plan9 || solaris -+// +build aix darwin dragonfly freebsd linux netbsd openbsd plan9 solaris -+ -+package test -+ -+// functional test harness for unix. -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/base64" -+ "fmt" -+ "log" -+ "net" -+ "os" -+ "os/exec" -+ "os/user" -+ "path/filepath" -+ "testing" -+ "text/template" -+ -+ "golang.org/x/crypto/internal/testenv" -+ "golang.org/x/crypto/ssh" -+ "golang.org/x/crypto/ssh/testdata" -+) -+ -+const ( -+ defaultSshdConfig = ` -+Protocol 2 -+Banner {{.Dir}}/banner -+HostKey {{.Dir}}/id_rsa -+HostKey {{.Dir}}/id_dsa -+HostKey {{.Dir}}/id_ecdsa -+HostCertificate {{.Dir}}/id_rsa-sha2-512-cert.pub -+Pidfile {{.Dir}}/sshd.pid -+#UsePrivilegeSeparation no -+KeyRegenerationInterval 3600 -+ServerKeyBits 768 -+SyslogFacility AUTH -+LogLevel DEBUG2 -+LoginGraceTime 120 -+PermitRootLogin no -+StrictModes no -+RSAAuthentication yes -+PubkeyAuthentication yes -+AuthorizedKeysFile {{.Dir}}/authorized_keys -+TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub -+IgnoreRhosts yes -+RhostsRSAAuthentication no -+HostbasedAuthentication no -+PubkeyAcceptedKeyTypes=* -+` -+ multiAuthSshdConfigTail = ` -+UsePAM yes -+PasswordAuthentication yes -+ChallengeResponseAuthentication yes -+AuthenticationMethods {{.AuthMethods}} -+` -+) -+ -+var configTmpl = map[string]*template.Template{ -+ "default": template.Must(template.New("").Parse(defaultSshdConfig)), -+ "MultiAuth": template.Must(template.New("").Parse(defaultSshdConfig + multiAuthSshdConfigTail))} -+ -+type server struct { -+ t *testing.T -+ configfile string -+ -+ testUser string // test username for sshd -+ testPasswd string // test password for sshd -+ sshdTestPwSo string // dynamic library to inject a custom password into sshd -+ -+ lastDialConn net.Conn -+} -+ -+func username() string { -+ var username string -+ if user, err := user.Current(); err == nil { -+ username = user.Username -+ } else { -+ // user.Current() currently requires cgo. If an error is -+ // returned attempt to get the username from the environment. -+ log.Printf("user.Current: %v; falling back on $USER", err) -+ username = os.Getenv("USER") -+ } -+ if username == "" { -+ panic("Unable to get username") -+ } -+ return username -+} -+ -+type storedHostKey struct { -+ // keys map from an algorithm string to binary key data. -+ keys map[string][]byte -+ -+ // checkCount counts the Check calls. Used for testing -+ // rekeying. -+ checkCount int -+} -+ -+func (k *storedHostKey) Add(key ssh.PublicKey) { -+ if k.keys == nil { -+ k.keys = map[string][]byte{} -+ } -+ k.keys[key.Type()] = key.Marshal() -+} -+ -+func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { -+ k.checkCount++ -+ algo := key.Type() -+ -+ if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { -+ return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) -+ } -+ return nil -+} -+ -+func hostKeyDB() *storedHostKey { -+ keyChecker := &storedHostKey{} -+ keyChecker.Add(testPublicKeys["ecdsa"]) -+ keyChecker.Add(testPublicKeys["rsa"]) -+ keyChecker.Add(testPublicKeys["dsa"]) -+ return keyChecker -+} -+ -+func clientConfig() *ssh.ClientConfig { -+ config := &ssh.ClientConfig{ -+ User: username(), -+ Auth: []ssh.AuthMethod{ -+ ssh.PublicKeys(testSigners["user"]), -+ }, -+ HostKeyCallback: hostKeyDB().Check, -+ HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker -+ ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, -+ ssh.KeyAlgoRSA, ssh.KeyAlgoDSA, -+ ssh.KeyAlgoED25519, -+ }, -+ } -+ return config -+} -+ -+// unixConnection creates two halves of a connected net.UnixConn. It -+// is used for connecting the Go SSH client with sshd without opening -+// ports. -+func unixConnection() (*net.UnixConn, *net.UnixConn, error) { -+ dir, err := os.MkdirTemp("", "unixConnection") -+ if err != nil { -+ return nil, nil, err -+ } -+ defer os.Remove(dir) -+ -+ addr := filepath.Join(dir, "ssh") -+ listener, err := net.Listen("unix", addr) -+ if err != nil { -+ return nil, nil, err -+ } -+ defer listener.Close() -+ c1, err := net.Dial("unix", addr) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ c2, err := listener.Accept() -+ if err != nil { -+ c1.Close() -+ return nil, nil, err -+ } -+ -+ return c1.(*net.UnixConn), c2.(*net.UnixConn), nil -+} -+ -+func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { -+ return s.TryDialWithAddr(config, "") -+} -+ -+// addr is the user specified host:port. While we don't actually dial it, -+// we need to know this for host key matching -+func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) { -+ sshd, err := exec.LookPath("sshd") -+ if err != nil { -+ s.t.Skipf("skipping test: %v", err) -+ } -+ -+ c1, c2, err := unixConnection() -+ if err != nil { -+ s.t.Fatalf("unixConnection: %v", err) -+ } -+ -+ cmd := testenv.Command(s.t, sshd, "-f", s.configfile, "-i", "-e") -+ f, err := c2.File() -+ if err != nil { -+ s.t.Fatalf("UnixConn.File: %v", err) -+ } -+ defer f.Close() -+ cmd.Stdin = f -+ cmd.Stdout = f -+ cmd.Stderr = new(bytes.Buffer) -+ -+ if s.sshdTestPwSo != "" { -+ if s.testUser == "" { -+ s.t.Fatal("user missing from sshd_test_pw.so config") -+ } -+ if s.testPasswd == "" { -+ s.t.Fatal("password missing from sshd_test_pw.so config") -+ } -+ cmd.Env = append(os.Environ(), -+ fmt.Sprintf("LD_PRELOAD=%s", s.sshdTestPwSo), -+ fmt.Sprintf("TEST_USER=%s", s.testUser), -+ fmt.Sprintf("TEST_PASSWD=%s", s.testPasswd)) -+ } -+ -+ if err := cmd.Start(); err != nil { -+ s.t.Fatalf("s.cmd.Start: %v", err) -+ } -+ s.lastDialConn = c1 -+ s.t.Cleanup(func() { -+ // Don't check for errors; if it fails it's most -+ // likely "os: process already finished", and we don't -+ // care about that. Use os.Interrupt, so child -+ // processes are killed too. -+ cmd.Process.Signal(os.Interrupt) -+ cmd.Wait() -+ if s.t.Failed() { -+ // log any output from sshd process -+ s.t.Logf("sshd:\n%s", cmd.Stderr) -+ } -+ }) -+ -+ conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config) -+ if err != nil { -+ return nil, err -+ } -+ return ssh.NewClient(conn, chans, reqs), nil -+} -+ -+func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { -+ conn, err := s.TryDial(config) -+ if err != nil { -+ s.t.Fatalf("ssh.Client: %v", err) -+ } -+ return conn -+} -+ -+func writeFile(path string, contents []byte) { -+ f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) -+ if err != nil { -+ panic(err) -+ } -+ defer f.Close() -+ if _, err := f.Write(contents); err != nil { -+ panic(err) -+ } -+} -+ -+// generate random password -+func randomPassword() (string, error) { -+ b := make([]byte, 12) -+ _, err := rand.Read(b) -+ if err != nil { -+ return "", err -+ } -+ return base64.RawURLEncoding.EncodeToString(b), nil -+} -+ -+// setTestPassword is used for setting user and password data for sshd_test_pw.so -+// This function also checks that ./sshd_test_pw.so exists and if not calls s.t.Skip() -+func (s *server) setTestPassword(user, passwd string) error { -+ wd, _ := os.Getwd() -+ wrapper := filepath.Join(wd, "sshd_test_pw.so") -+ if _, err := os.Stat(wrapper); err != nil { -+ s.t.Skip(fmt.Errorf("sshd_test_pw.so is not available")) -+ return err -+ } -+ -+ s.sshdTestPwSo = wrapper -+ s.testUser = user -+ s.testPasswd = passwd -+ return nil -+} -+ -+// newServer returns a new mock ssh server. -+func newServer(t *testing.T) *server { -+ return newServerForConfig(t, "default", map[string]string{}) -+} -+ -+// newServerForConfig returns a new mock ssh server. -+func newServerForConfig(t *testing.T, config string, configVars map[string]string) *server { -+ if testing.Short() { -+ t.Skip("skipping test due to -short") -+ } -+ u, err := user.Current() -+ if err != nil { -+ t.Fatalf("user.Current: %v", err) -+ } -+ uname := u.Name -+ if uname == "" { -+ // Check the value of u.Username as u.Name -+ // can be "" on some OSes like AIX. -+ uname = u.Username -+ } -+ if uname == "root" { -+ t.Skip("skipping test because current user is root") -+ } -+ dir, err := os.MkdirTemp("", "sshtest") -+ if err != nil { -+ t.Fatal(err) -+ } -+ f, err := os.Create(filepath.Join(dir, "sshd_config")) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if _, ok := configTmpl[config]; ok == false { -+ t.Fatal(fmt.Errorf("Invalid server config '%s'", config)) -+ } -+ configVars["Dir"] = dir -+ err = configTmpl[config].Execute(f, configVars) -+ if err != nil { -+ t.Fatal(err) -+ } -+ f.Close() -+ -+ writeFile(filepath.Join(dir, "banner"), []byte("Server Banner")) -+ -+ for k, v := range testdata.PEMBytes { -+ filename := "id_" + k -+ writeFile(filepath.Join(dir, filename), v) -+ writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) -+ } -+ -+ for k, v := range testdata.SSHCertificates { -+ filename := "id_" + k + "-cert.pub" -+ writeFile(filepath.Join(dir, filename), v) -+ } -+ -+ var authkeys bytes.Buffer -+ for k := range testdata.PEMBytes { -+ authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k])) -+ } -+ writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes()) -+ t.Cleanup(func() { -+ if err := os.RemoveAll(dir); err != nil { -+ t.Error(err) -+ } -+ }) -+ -+ return &server{ -+ t: t, -+ configfile: f.Name(), -+ } -+} -+ -+func newTempSocket(t *testing.T) (string, func()) { -+ dir, err := os.MkdirTemp("", "socket") -+ if err != nil { -+ t.Fatal(err) -+ } -+ deferFunc := func() { os.RemoveAll(dir) } -+ addr := filepath.Join(dir, "sock") -+ return addr, deferFunc -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go b/ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go -new file mode 100644 -index 00000000000000..a053f67eabed4c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/test/testdata_test.go -@@ -0,0 +1,64 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: -+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three -+// instances. -+ -+package test -+ -+import ( -+ "crypto/rand" -+ "fmt" -+ -+ "golang.org/x/crypto/ssh" -+ "golang.org/x/crypto/ssh/testdata" -+) -+ -+var ( -+ testPrivateKeys map[string]interface{} -+ testSigners map[string]ssh.Signer -+ testPublicKeys map[string]ssh.PublicKey -+) -+ -+func init() { -+ var err error -+ -+ n := len(testdata.PEMBytes) -+ testPrivateKeys = make(map[string]interface{}, n) -+ testSigners = make(map[string]ssh.Signer, n) -+ testPublicKeys = make(map[string]ssh.PublicKey, n) -+ for t, k := range testdata.PEMBytes { -+ testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) -+ } -+ testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) -+ } -+ testPublicKeys[t] = testSigners[t].PublicKey() -+ } -+ -+ // Create a cert and sign it for use in tests. -+ testCert := &ssh.Certificate{ -+ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil -+ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage -+ ValidAfter: 0, // unix epoch -+ ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. -+ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil -+ Key: testPublicKeys["ecdsa"], -+ SignatureKey: testPublicKeys["rsa"], -+ Permissions: ssh.Permissions{ -+ CriticalOptions: map[string]string{}, -+ Extensions: map[string]string{}, -+ }, -+ } -+ testCert.SignCert(rand.Reader, testSigners["rsa"]) -+ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] -+ testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/testdata/doc.go b/ms_mod/golang.org/x/crypto/ssh/testdata/doc.go -new file mode 100644 -index 00000000000000..fcae47ca6878b4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/testdata/doc.go -@@ -0,0 +1,8 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// This package contains test data shared between the various subpackages of -+// the golang.org/x/crypto/ssh package. Under no circumstance should -+// this data be used for production code. -+package testdata // import "golang.org/x/crypto/ssh/testdata" -diff --git a/ms_mod/golang.org/x/crypto/ssh/testdata/keys.go b/ms_mod/golang.org/x/crypto/ssh/testdata/keys.go -new file mode 100644 -index 00000000000000..ad95a81929b829 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/testdata/keys.go -@@ -0,0 +1,314 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package testdata -+ -+var PEMBytes = map[string][]byte{ -+ "dsa": []byte(`-----BEGIN DSA PRIVATE KEY----- -+MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB -+lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3 -+EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD -+nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV -+2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r -+juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr -+FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz -+DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj -+nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY -+Fmsr0W6fHB9nhS4/UXM8 -+-----END DSA PRIVATE KEY----- -+`), -+ "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY----- -+MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 -+AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ -+6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== -+-----END EC PRIVATE KEY----- -+`), -+ "ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY----- -+MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49 -+AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU -+qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg== -+-----END EC PRIVATE KEY----- -+`), -+ "ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY----- -+MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS -+qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43 -+VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz -+hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI= -+-----END EC PRIVATE KEY----- -+`), -+ "ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY----- -+MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF -+iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV -+UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+ -+uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn -+FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ== -+-----END EC PRIVATE KEY----- -+`), -+ "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- -+MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2 -+a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8 -+Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB -+AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R -+38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT -+Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq -+2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9 -+6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR -+fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu -+X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa -+NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM -+z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 -+KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= -+-----END RSA PRIVATE KEY----- -+`), -+ "pkcs8": []byte(`-----BEGIN PRIVATE KEY----- -+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCitzS2KiRQTccf -+VApb0mbPpo1lt29JjeLBYAehXHWfQ+w8sXpd8e04n/020spx1R94yg+v0NjXyh2R -+NFXNBYdhNei33VJxUeKNlExaecvW2yxfuZqka+ZxT1aI8zrAsjh3Rwc6wayAJS4R -+wZuzlDv4jZitWqwD+mb/22Zwq/WSs4YX5dUHDklfdWSVnoBfue8K/00n8f5yMTdJ -+vFF0qAJwf9spPEHla0lYcozJk64CO5lRkqfLor4UnsXXOiA7aRIoaUSKa+rlhiqt -+1EMGYiBjblPt4SwMelGGU2UfywPb4d85gpQ/s8SBARbpPxNVs2IbHDMwj70P3uZc -+74M3c4VJAgMBAAECggEAFIzY3mziGzZHgMBncoNXMsCRORh6uKpvygZr0EhSHqRA -+cMXlc3n7gNxL6aGjqc7F48Z5RrY0vMQtCcq3T2Z0W6WoV5hfMiqqV0E0h3S8ds1F -+hG13h26NMyBXCILXl8Cqev4Afr45IBISCHIQTRTaoiCX+MTr1rDIU2YNQQumvzkz -+fMw2XiFTFTgxAtJUAgKoTqLtm7/T+az7TKw+Hesgbx7yaJoMh9DWGBh4Y61DnIDA -+fcxJboAfxxnFiXvdBVmzo72pCsRXrWOsjW6WxQmCKuXHvyB1FZTmMaEFNCGSJDa6 -+U+OCzA3m65loAZAE7ffFHhYgssz/h9TBaOjKO0BX1QKBgQDZiCBvu+bFh9pEodcS -+VxaI+ATlsYcmGdLtnZw5pxuEdr60iNWhpEcV6lGkbdiv5aL43QaGFDLagqeHI77b -++ITFbPPdCiYNaqlk6wyiXv4pdN7V683EDmGWSQlPeC9IhUilt2c+fChK2EB/XlkO -+q8c3Vk1MsC6JOxDXNgJxylNpswKBgQC/fYBTb9iD+uM2n3SzJlct/ZlPaONKnNDR -+pbTOdxBFHsu2VkfY858tfnEPkmSRX0yKmjHni6e8/qIzfzLwWBY4NmxhNZE5v+qJ -+qZF26ULFdrZB4oWXAOliy/1S473OpQnp2MZp2asd0LPcg/BNaMuQrz44hxHb76R7 -+qWD0ebIfEwKBgQCRCIiP1pjbVGN7ZOgPS080DSC+wClahtcyI+ZYLglTvRQTLDQ7 -+LFtUykCav748MIADKuJBnM/3DiuCF5wV71EejDDfS/fo9BdyuKBY1brhixFTUX+E -+Ww5Hc/SoLnpgALVZ/7jvWTpIBHykLxRziqYtR/YLzl+IkX/97P2ePoZ0rwKBgHNC -+/7M5Z4JJyepfIMeVFHTCaT27TNTkf20x6Rs937U7TDN8y9JzEiU4LqXI4HAAhPoI -+xnExRs4kF04YCnlRDE7Zs3Lv43J3ap1iTATfcymYwyv1RaQXEGQ/lUQHgYCZJtZz -+fTrJoo5XyWu6nzJ5Gc8FLNaptr5ECSXGVm3Rsr2xAoGBAJWqEEQS/ejhO05QcPqh -+y4cUdLr0269ILVsvic4Ot6zgfPIntXAK6IsHGKcg57kYm6W9k1CmmlA4ENGryJnR -+vxyyqA9eyTFc1CQNuc2frKFA9It49JzjXahKc0aDHEHmTR787Tmk1LbuT0/gm9kA -+L4INU6g+WqF0fatJxd+IJPrp -+-----END PRIVATE KEY----- -+`), -+ "ed25519": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW -+QyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8DvvwAAAJhAFfkOQBX5 -+DgAAAAtzc2gtZWQyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8Dvvw -+AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb -+HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg== -+-----END OPENSSH PRIVATE KEY----- -+`), -+ "rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn -+NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l -+oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz -+a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH -+c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE -+uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+ -+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4 -+IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE -+pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk -+kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk -+pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju -+X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB -+ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ -+wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID -+-----END OPENSSH PRIVATE KEY-----`), -+ "p256-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS -+1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSN5Ld/DFy8LJK0yrWg+Ryhq4/ifHry -+QyCQeT4UXSB+UGdRct7kWA0hARbTaSCh+8U/Gs5O+IkDNoTKVsgxKUMQAAAAsO3C7nPtwu -+5zAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI3kt38MXLwskrTK -+taD5HKGrj+J8evJDIJB5PhRdIH5QZ1Fy3uRYDSEBFtNpIKH7xT8azk74iQM2hMpWyDEpQx -+AAAAAhAIHB48R+goZaiXndfYTrwk4BT1+MeLPC2/dwe0J5d1QDAAAAE21hcmlhbm9AZW5k -+b3IubG9jYWwBAgME -+-----END OPENSSH PRIVATE KEY-----`), -+ "p384-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS -+1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTZb2VzEPs2NN/i1qHddKTVfwoIq3Tf -+PeQ/kcWBvuCVJfIygvpm9MeusawEPuLSEXwiNDew+YHZ9xHIvFjCmZsLuEOzuh9t9KotwM -+57H+7N+RDFzhM2j8hAaOuT5XDLKfUAAADgn/Sny5/0p8sAAAATZWNkc2Etc2hhMi1uaXN0 -+cDM4NAAAAAhuaXN0cDM4NAAAAGEE2W9lcxD7NjTf4tah3XSk1X8KCKt03z3kP5HFgb7glS -+XyMoL6ZvTHrrGsBD7i0hF8IjQ3sPmB2fcRyLxYwpmbC7hDs7ofbfSqLcDOex/uzfkQxc4T -+No/IQGjrk+Vwyyn1AAAAMQDg0hwGKB/9Eq+e2FeTspi8QHW5xTD6prqsHDFx4cKk0ccgFV -+61dhFhD/8SEbYlHzEAAAATbWFyaWFub0BlbmRvci5sb2NhbAECAwQ= -+-----END OPENSSH PRIVATE KEY-----`), -+ "p521-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS -+1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBKzI3QSp1a2e1zMulZl1uFF1Y2Dnv -+LSIwEu837hOV1epYEgNveAhGNm57TuBqYtnZeVfd2pzaz7CKX6N4B33N1XABQ5Ngji7lF2 -+dUbmhNqJoMh43ioIsQNBaBenhmRpYP6f5k8P/7JZMIsLhkJk2hykb8maSZ+B3PYwPMNBdS -+vP+0sHQAAAEYIsr2CCLK9ggAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ -+AAAIUEASsyN0EqdWtntczLpWZdbhRdWNg57y0iMBLvN+4TldXqWBIDb3gIRjZue07gamLZ -+2XlX3dqc2s+wil+jeAd9zdVwAUOTYI4u5RdnVG5oTaiaDIeN4qCLEDQWgXp4ZkaWD+n+ZP -+D/+yWTCLC4ZCZNocpG/Jmkmfgdz2MDzDQXUrz/tLB0AAAAQgEdeH+im6iRcP/juTAoeSHo -+ExLtWhgL4JYqRwcOnzCKuLOPjEY/HSOuc+HRrbN9rbjsq+PcPHYe1NnkzXk0IW8hxQAAAB -+NtYXJpYW5vQGVuZG9yLmxvY2FsAQIDBAUGBw== -+-----END OPENSSH PRIVATE KEY-----`), -+ "user": []byte(`-----BEGIN EC PRIVATE KEY----- -+MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 -+AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD -+PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w== -+-----END EC PRIVATE KEY----- -+`), -+ "ca": []byte(`-----BEGIN RSA PRIVATE KEY----- -+MIIEpAIBAAKCAQEAvg9dQ9IRG59lYJb+GESfKWTch4yBpr7Ydw1jkK6vvtrx9jLo -+5hkA8X6+ElRPRqTAZSlN5cBm6YCAcQIOsmXDUn6Oj1lVPQAoOjTBTvsjM3NjGhvv -+52kHTY0nsMsBeY9q5DTtlzmlYkVUq2a6Htgf2mNi01dIw5fJ7uTTo8EbNf7O0i3u -+c9a8P19HaZl5NKiWN4EIZkfB2WdXYRJCVBsGgQj3dE/GrEmH9QINq1A+GkNvK96u -+vZm8H1jjmuqzHplWa7lFeXcx8FTVTbVb/iJrZ2Lc/JvIPitKZWhqbR59yrGjpwEp -+Id7bo4WhO5L3OB0fSIJYvfu+o4WYnt4f3UzecwIDAQABAoIBABRD9yHgKErVuC2Q -+bA+SYZY8VvdtF/X7q4EmQFORDNRA7EPgMc03JU6awRGbQ8i4kHs46EFzPoXvWcKz -+AXYsO6N0Myc900Tp22A5d9NAHATEbPC/wdje7hRq1KyZONMJY9BphFv3nZbY5apR -+Dc90JBFZP5RhXjTc3n9GjvqLAKfFEKVmPRCvqxCOZunw6XR+SgIQLJo36nsIsbhW -+QUXIVaCI6cXMN8bRPm8EITdBNZu06Fpu4ZHm6VaxlXN9smERCDkgBSNXNWHKxmmA -+c3Glo2DByUr2/JFBOrLEe9fkYgr24KNCQkHVcSaFxEcZvTggr7StjKISVHlCNEaB -+7Q+kPoECgYEA3zE9FmvFGoQCU4g4Nl3dpQHs6kaAW8vJlrmq3xsireIuaJoa2HMe -+wYdIvgCnK9DIjyxd5OWnE4jXtAEYPsyGD32B5rSLQrRO96lgb3f4bESCLUb3Bsn/ -+sdgeE3p1xZMA0B59htqCrvVgN9k8WxyevBxYl3/gSBm/p8OVH1RTW/ECgYEA2f9Z -+95OLj0KQHQtxQXf+I3VjhCw3LkLW39QZOXVI0QrCJfqqP7uxsJXH9NYX0l0GFTcR -+kRrlyoaSU1EGQosZh+n1MvplGBTkTSV47/bPsTzFpgK2NfEZuFm9RoWgltS+nYeH -+Y2k4mnAN3PhReCMwuprmJz8GRLsO3Cs2s2YylKMCgYEA2UX+uO/q7jgqZ5UJW+ue -+1H5+W0aMuFA3i7JtZEnvRaUVFqFGlwXin/WJ2+WY1++k/rPrJ+Rk9IBXtBUIvEGw -+FC5TIfsKQsJyyWgqx/jbbtJ2g4s8+W/1qfTAuqeRNOg5d2DnRDs90wJuS4//0JaY -+9HkHyVwkQyxFxhSA/AHEMJECgYA2MvyFR1O9bIk0D3I7GsA+xKLXa77Ua53MzIjw -+9i4CezBGDQpjCiFli/fI8am+jY5DnAtsDknvjoG24UAzLy5L0mk6IXMdB6SzYYut -+7ak5oahqW+Y9hxIj+XvLmtGQbphtxhJtLu35x75KoBpxSh6FZpmuTEccs31AVCYn -+eFM/DQKBgQDOPUwbLKqVi6ddFGgrV9MrWw+SWsDa43bPuyvYppMM3oqesvyaX1Dt -+qDvN7owaNxNM4OnfKcZr91z8YPVCFo4RbBif3DXRzjNNBlxEjHBtuMOikwvsmucN -+vIrbeEpjTiUMTEAr6PoTiVHjsfS8WAM6MDlF5M+2PNswDsBpa2yLgA== -+-----END RSA PRIVATE KEY----- -+`), -+} -+ -+var SSHCertificates = map[string][]byte{ -+ // The following are corresponding certificates for the private keys above, signed by the CA key -+ // Generated by the following commands: -+ // -+ // 1. Assumes "rsa" key above in file named "rsa", write out the public key to "rsa.pub": -+ // ssh-keygen -y -f rsa > rsa.pub -+ // -+ // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub": -+ // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub -+ "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com -+`), -+ "rsa-sha2-256": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOyK28gunJkM60qp4EbsYAjgbUsyjS8u742OLjipIgc0AAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMJ4AAAAAHBPBLwAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi0yNTYAAAEAbG4De/+QiqopPS3O1H7ySeEUCY56qmdgr02sFErnihdXPDaWXUXxacvJHaEtLrSTSaPL/3v3iKvjLWDOHaQ5c+cN9J7Tqzso7RQCXZD2nK9bwCUyBoiDyBCRe8w4DQEtfL5okpVzQsSAiojQ8hBohMOpy3gFfXrdm4PVC1ZKqlZh4fAc7ajieRq/Tpq2xOLdHwxkcgPNR83WVHva6K9/xjev/5n227/gkHo0qbGs8YYDOFXIEhENi+B23IzxdNVieWdyQpYpe0C2i95Jhyo0wJmaFY2ArruTS+D1jGQQpMPvAQRy26/A5hI83GLhpwyhrN/M8wCxzAhyPL6Ieuh5tQ== host.example.com -+`), -+ "rsa-sha2-512": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgFGv4IpXfs4L/Y0b3rmUdPFhWoUrVnXuPxXr6aHGs7wgAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMRYAAAAAHBPBp4AAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAnF4fVj6mm+UFeNCIf9AKJCv9WzymjjPvzzmaMWWkPWqoV0P0m5SiYfvbY9SbA73Blpv8SOr0DmpublF183kodREia4KyVuC8hLhSCV2Y16hy9MBegOZMepn80w+apj7Rn9QCz5OfEakDdztp6OWTBtqxnZFcTQ4XrgFkNWeWRElGdEvAVNn2WHwHi4EIdz0mdv48Imv5SPlOuW862ZdFG4Do1dUfDIiGsBofLlgcyIYlf+eNHul6sBeUkuwFxisMpI5DQzNp8PX1g/QJA2wzwT674PTqDXNttKjyh50Fdr4sXxm9Gz1+jVLoESvFNa55ERdSyAqNu4wTy11MZsWwSA== host.example.com -+`), -+} -+ -+var PEMEncryptedKeys = []struct { -+ Name string -+ EncryptionKey string -+ IncludesPublicKey bool -+ PEMBytes []byte -+}{ -+ 0: { -+ Name: "rsa-encrypted", -+ EncryptionKey: "r54-G0pher_t3st$", -+ PEMBytes: []byte(`-----BEGIN RSA PRIVATE KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-128-CBC,3E1714DE130BC5E81327F36564B05462 -+ -+MqW88sud4fnWk/Jk3fkjh7ydu51ZkHLN5qlQgA4SkAXORPPMj2XvqZOv1v2LOgUV -+dUevUn8PZK7a9zbZg4QShUSzwE5k6wdB7XKPyBgI39mJ79GBd2U4W3h6KT6jIdWA -+goQpluxkrzr2/X602IaxLEre97FT9mpKC6zxKCLvyFWVIP9n3OSFS47cTTXyFr+l -+7PdRhe60nn6jSBgUNk/Q1lAvEQ9fufdPwDYY93F1wyJ6lOr0F1+mzRrMbH67NyKs -+rG8J1Fa7cIIre7ueKIAXTIne7OAWqpU9UDgQatDtZTbvA7ciqGsSFgiwwW13N+Rr -+hN8MkODKs9cjtONxSKi05s206A3NDU6STtZ3KuPDjFE1gMJODotOuqSM+cxKfyFq -+wxpk/CHYCDdMAVBSwxb/vraOHamylL4uCHpJdBHypzf2HABt+lS8Su23uAmL87DR -+yvyCS/lmpuNTndef6qHPRkoW2EV3xqD3ovosGf7kgwGJUk2ZpCLVteqmYehKlZDK -+r/Jy+J26ooI2jIg9bjvD1PZq+Mv+2dQ1RlDrPG3PB+rEixw6vBaL9x3jatCd4ej7 -+XG7lb3qO9xFpLsx89tkEcvpGR+broSpUJ6Mu5LBCVmrvqHjvnDhrZVz1brMiQtU9 -+iMZbgXqDLXHd6ERWygk7OTU03u+l1gs+KGMfmS0h0ZYw6KGVLgMnsoxqd6cFSKNB -+8Ohk9ZTZGCiovlXBUepyu8wKat1k8YlHSfIHoRUJRhhcd7DrmojC+bcbMIZBU22T -+Pl2ftVRGtcQY23lYd0NNKfebF7ncjuLWQGy+vZW+7cgfI6wPIbfYfP6g7QAutk6W -+KQx0AoX5woZ6cNxtpIrymaVjSMRRBkKQrJKmRp3pC/lul5E5P2cueMs1fj4OHTbJ -+lAUv88ywr+R+mRgYQlFW/XQ653f6DT4t6+njfO9oBcPrQDASZel3LjXLpjjYG/N5 -++BWnVexuJX9ika8HJiFl55oqaKb+WknfNhk5cPY+x7SDV9ywQeMiDZpr0ffeYAEP -+LlwwiWRDYpO+uwXHSFF3+JjWwjhs8m8g99iFb7U93yKgBB12dCEPPa2ZeH9wUHMJ -+sreYhNuq6f4iWWSXpzN45inQqtTi8jrJhuNLTT543ErW7DtntBO2rWMhff3aiXbn -+Uy3qzZM1nPbuCGuBmP9L2dJ3Z5ifDWB4JmOyWY4swTZGt9AVmUxMIKdZpRONx8vz -+I9u9nbVPGZBcou50Pa0qTLbkWsSL94MNXrARBxzhHC9Zs6XNEtwN7mOuii7uMkVc -+adrxgknBH1J1N+NX/eTKzUwJuPvDtA+Z5ILWNN9wpZT/7ed8zEnKHPNUexyeT5g3 -+uw9z9jH7ffGxFYlx87oiVPHGOrCXYZYW5uoZE31SCBkbtNuffNRJRKIFeipmpJ3P -+7bpAG+kGHMelQH6b+5K1Qgsv4tpuSyKeTKpPFH9Av5nN4P1ZBm9N80tzbNWqjSJm -+S7rYdHnuNEVnUGnRmEUMmVuYZnNBEVN/fP2m2SEwXcP3Uh7TiYlcWw10ygaGmOr7 -+MvMLGkYgQ4Utwnd98mtqa0jr0hK2TcOSFir3AqVvXN3XJj4cVULkrXe4Im1laWgp -+-----END RSA PRIVATE KEY----- -+`), -+ }, -+ -+ 1: { -+ Name: "dsa-encrypted", -+ EncryptionKey: "qG0pher-dsa_t3st$", -+ PEMBytes: []byte(`-----BEGIN DSA PRIVATE KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-128-CBC,7CE7A6E4A647DC01AF860210B15ADE3E -+ -+hvnBpI99Hceq/55pYRdOzBLntIEis02JFNXuLEydWL+RJBFDn7tA+vXec0ERJd6J -+G8JXlSOAhmC2H4uK3q2xR8/Y3yL95n6OIcjvCBiLsV+o3jj1MYJmErxP6zRtq4w3 -+JjIjGHWmaYFSxPKQ6e8fs74HEqaeMV9ONUoTtB+aISmgaBL15Fcoayg245dkBvVl -+h5Kqspe7yvOBmzA3zjRuxmSCqKJmasXM7mqs3vIrMxZE3XPo1/fWKcPuExgpVQoT -+HkJZEoIEIIPnPMwT2uYbFJSGgPJVMDT84xz7yvjCdhLmqrsXgs5Qw7Pw0i0c0BUJ -+b7fDJ2UhdiwSckWGmIhTLlJZzr8K+JpjCDlP+REYBI5meB7kosBnlvCEHdw2EJkH -+0QDc/2F4xlVrHOLbPRFyu1Oi2Gvbeoo9EsM/DThpd1hKAlb0sF5Y0y0d+owv0PnE -+R/4X3HWfIdOHsDUvJ8xVWZ4BZk9Zk9qol045DcFCehpr/3hslCrKSZHakLt9GI58 -+vVQJ4L0aYp5nloLfzhViZtKJXRLkySMKdzYkIlNmW1oVGl7tce5UCNI8Nok4j6yn -+IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8= -+-----END DSA PRIVATE KEY----- -+`), -+ }, -+ -+ 2: { -+ Name: "ed25519-encrypted", -+ EncryptionKey: "password", -+ IncludesPublicKey: true, -+ PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKj29BlC -+ocEWuVhQ94/RjoAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIw1gSurPTDwZidA -+2AIjQZgoQi3IFn9jBtFdP10/Jj7DAAAAoFGkQbB2teSU7ikUsnc7ct2aH3pitM359lNVUh -+7DQbJWMjbQFbrBYyDJP+ALj1/RZmP2yoIf7/wr99q53/pm28Xp1gGP5V2RGRJYCA6kgFIH -+xdB6KEw1Ce7Bz8JaDIeagAGd3xtQTH3cuuleVxCZZnk9NspsPxigADKCls/RUiK7F+z3Qf -+Lvs9+PH8nIuhFMYZgo3liqZbVS5z4Fqhyzyq4= -+-----END OPENSSH PRIVATE KEY----- -+`), -+ }, -+ -+ 3: { -+ Name: "ed25519-encrypted-cbc", -+ EncryptionKey: "password", -+ IncludesPublicKey: true, -+ PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- -+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABDzGKF3uX -+G1gXALZKFd6Ir4AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDne4/teO42zTDdj -+NwxUMNpbfmp/dxgU4ZNkC3ydgcugAAAAoJ3J/oA7+iqVOz0CIUUk9ufdP1VP4jDf2um+0s -+Sgs7x6Gpyjq67Ps7wLRdSmxr/G5b+Z8dRGFYS/wUCQEe3whwuImvLyPwWjXLzkAyMzc01f -+ywBGSrHnvP82ppenc2HuTI+E05Xc02i6JVyI1ShiekQL5twoqtR6pEBZnD17UonIx7cRzZ -+gbDGyT3bXMQtagvCwoW+/oMTKXiZP5jCJpEO8= -+-----END OPENSSH PRIVATE KEY----- -+`), -+ }, -+} -+ -+// SKData contains a list of PubKeys backed by U2F/FIDO2 Security Keys and their test data. -+var SKData = []struct { -+ Name string -+ PubKey []byte -+ HexData []byte -+ HexSignature []byte -+}{ -+ { -+ Name: "sk-ecdsa-sha2-nistp256@openssh.com", -+ PubKey: []byte("sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGRNqlFgED/pf4zXz8IzqA6CALNwYcwgd4MQDmIS1GOtn1SySFObiuyJaOlpqkV5FeEifhxfIC2ejKKtNyO4CysAAAAEc3NoOg== user@host"), -+ HexData: []byte("00000020A4DE1F50DE0EF3F66DCD156C78F5C93B07EEE89D5B5A6531656E835FA1C87B323200000006736B696E6E650000000E7373682D636F6E6E656374696F6E000000097075626C69636B65790100000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D0000007F00000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D000000086E697374703235360000004104644DAA5160103FE97F8CD7CFC233A80E8200B37061CC207783100E6212D463AD9F54B248539B8AEC8968E969AA457915E1227E1C5F202D9E8CA2AD3723B80B2B000000047373683A"), -+ HexSignature: []byte("0000007800000022736B2D65636473612D736861322D6E69737470323536406F70656E7373682E636F6D000000490000002016CC1A3070E180621CB206C2C6313D1CC5F094DB844A61D06001E243C608875F0000002100E4BD45D6B9DAA11489AEA8D76C222AA3FD6D50FBFFDA8049526D5D61F63B2C5601000000F9"), -+ }, -+ { -+ Name: "sk-ssh-ed25519@openssh.com", -+ PubKey: []byte("sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJjzc2a20RjCvN/0ibH6UpGuN9F9hDvD7x182bOesNhHAAAABHNzaDo= user@host"), -+ HexData: []byte("000000204CFE6EA65CCB99B69348339165C7F38E359D95807A377EEE8E603C71DC3316FA3200000006736B696E6E650000000E7373682D636F6E6E656374696F6E000000097075626C69636B6579010000001A736B2D7373682D65643235353139406F70656E7373682E636F6D0000004A0000001A736B2D7373682D65643235353139406F70656E7373682E636F6D0000002098F37366B6D118C2BCDFF489B1FA5291AE37D17D843BC3EF1D7CD9B39EB0D847000000047373683A"), -+ HexSignature: []byte("000000670000001A736B2D7373682D65643235353139406F70656E7373682E636F6D000000404BF5CA0CAA553099306518732317B3FE4BA6C75365BC0CB02019FBE65A1647016CBD7A682C26928DF234C378ADDBC5077B47F72381144840BF00FB2DA2FB6A0A010000009E"), -+ }, -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/testdata_test.go b/ms_mod/golang.org/x/crypto/ssh/testdata_test.go -new file mode 100644 -index 00000000000000..2da8c79dc64a43 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/testdata_test.go -@@ -0,0 +1,63 @@ -+// Copyright 2014 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: -+// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three -+// instances. -+ -+package ssh -+ -+import ( -+ "crypto/rand" -+ "fmt" -+ -+ "golang.org/x/crypto/ssh/testdata" -+) -+ -+var ( -+ testPrivateKeys map[string]interface{} -+ testSigners map[string]Signer -+ testPublicKeys map[string]PublicKey -+) -+ -+func init() { -+ var err error -+ -+ n := len(testdata.PEMBytes) -+ testPrivateKeys = make(map[string]interface{}, n) -+ testSigners = make(map[string]Signer, n) -+ testPublicKeys = make(map[string]PublicKey, n) -+ for t, k := range testdata.PEMBytes { -+ testPrivateKeys[t], err = ParseRawPrivateKey(k) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) -+ } -+ testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) -+ } -+ testPublicKeys[t] = testSigners[t].PublicKey() -+ } -+ -+ // Create a cert and sign it for use in tests. -+ testCert := &Certificate{ -+ Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil -+ ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage -+ ValidAfter: 0, // unix epoch -+ ValidBefore: CertTimeInfinity, // The end of currently representable time. -+ Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil -+ Key: testPublicKeys["ecdsa"], -+ SignatureKey: testPublicKeys["rsa"], -+ Permissions: Permissions{ -+ CriticalOptions: map[string]string{}, -+ Extensions: map[string]string{}, -+ }, -+ } -+ testCert.SignCert(rand.Reader, testSigners["rsa"]) -+ testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] -+ testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"]) -+ if err != nil { -+ panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/transport.go b/ms_mod/golang.org/x/crypto/ssh/transport.go -new file mode 100644 -index 00000000000000..da015801ea5bf2 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/transport.go -@@ -0,0 +1,358 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bufio" -+ "bytes" -+ "errors" -+ "io" -+ "log" -+) -+ -+// debugTransport if set, will print packet types as they go over the -+// wire. No message decoding is done, to minimize the impact on timing. -+const debugTransport = false -+ -+const ( -+ gcm128CipherID = "aes128-gcm@openssh.com" -+ gcm256CipherID = "aes256-gcm@openssh.com" -+ aes128cbcID = "aes128-cbc" -+ tripledescbcID = "3des-cbc" -+) -+ -+// packetConn represents a transport that implements packet based -+// operations. -+type packetConn interface { -+ // Encrypt and send a packet of data to the remote peer. -+ writePacket(packet []byte) error -+ -+ // Read a packet from the connection. The read is blocking, -+ // i.e. if error is nil, then the returned byte slice is -+ // always non-empty. -+ readPacket() ([]byte, error) -+ -+ // Close closes the write-side of the connection. -+ Close() error -+} -+ -+// transport is the keyingTransport that implements the SSH packet -+// protocol. -+type transport struct { -+ reader connectionState -+ writer connectionState -+ -+ bufReader *bufio.Reader -+ bufWriter *bufio.Writer -+ rand io.Reader -+ isClient bool -+ io.Closer -+} -+ -+// packetCipher represents a combination of SSH encryption/MAC -+// protocol. A single instance should be used for one direction only. -+type packetCipher interface { -+ // writeCipherPacket encrypts the packet and writes it to w. The -+ // contents of the packet are generally scrambled. -+ writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error -+ -+ // readCipherPacket reads and decrypts a packet of data. The -+ // returned packet may be overwritten by future calls of -+ // readPacket. -+ readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error) -+} -+ -+// connectionState represents one side (read or write) of the -+// connection. This is necessary because each direction has its own -+// keys, and can even have its own algorithms -+type connectionState struct { -+ packetCipher -+ seqNum uint32 -+ dir direction -+ pendingKeyChange chan packetCipher -+} -+ -+// prepareKeyChange sets up key material for a keychange. The key changes in -+// both directions are triggered by reading and writing a msgNewKey packet -+// respectively. -+func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { -+ ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) -+ if err != nil { -+ return err -+ } -+ t.reader.pendingKeyChange <- ciph -+ -+ ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) -+ if err != nil { -+ return err -+ } -+ t.writer.pendingKeyChange <- ciph -+ -+ return nil -+} -+ -+func (t *transport) printPacket(p []byte, write bool) { -+ if len(p) == 0 { -+ return -+ } -+ who := "server" -+ if t.isClient { -+ who = "client" -+ } -+ what := "read" -+ if write { -+ what = "write" -+ } -+ -+ log.Println(what, who, p[0]) -+} -+ -+// Read and decrypt next packet. -+func (t *transport) readPacket() (p []byte, err error) { -+ for { -+ p, err = t.reader.readPacket(t.bufReader) -+ if err != nil { -+ break -+ } -+ if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { -+ break -+ } -+ } -+ if debugTransport { -+ t.printPacket(p, false) -+ } -+ -+ return p, err -+} -+ -+func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { -+ packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) -+ s.seqNum++ -+ if err == nil && len(packet) == 0 { -+ err = errors.New("ssh: zero length packet") -+ } -+ -+ if len(packet) > 0 { -+ switch packet[0] { -+ case msgNewKeys: -+ select { -+ case cipher := <-s.pendingKeyChange: -+ s.packetCipher = cipher -+ default: -+ return nil, errors.New("ssh: got bogus newkeys message") -+ } -+ -+ case msgDisconnect: -+ // Transform a disconnect message into an -+ // error. Since this is lowest level at which -+ // we interpret message types, doing it here -+ // ensures that we don't have to handle it -+ // elsewhere. -+ var msg disconnectMsg -+ if err := Unmarshal(packet, &msg); err != nil { -+ return nil, err -+ } -+ return nil, &msg -+ } -+ } -+ -+ // The packet may point to an internal buffer, so copy the -+ // packet out here. -+ fresh := make([]byte, len(packet)) -+ copy(fresh, packet) -+ -+ return fresh, err -+} -+ -+func (t *transport) writePacket(packet []byte) error { -+ if debugTransport { -+ t.printPacket(packet, true) -+ } -+ return t.writer.writePacket(t.bufWriter, t.rand, packet) -+} -+ -+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { -+ changeKeys := len(packet) > 0 && packet[0] == msgNewKeys -+ -+ err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) -+ if err != nil { -+ return err -+ } -+ if err = w.Flush(); err != nil { -+ return err -+ } -+ s.seqNum++ -+ if changeKeys { -+ select { -+ case cipher := <-s.pendingKeyChange: -+ s.packetCipher = cipher -+ default: -+ panic("ssh: no key material for msgNewKeys") -+ } -+ } -+ return err -+} -+ -+func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { -+ t := &transport{ -+ bufReader: bufio.NewReader(rwc), -+ bufWriter: bufio.NewWriter(rwc), -+ rand: rand, -+ reader: connectionState{ -+ packetCipher: &streamPacketCipher{cipher: noneCipher{}}, -+ pendingKeyChange: make(chan packetCipher, 1), -+ }, -+ writer: connectionState{ -+ packetCipher: &streamPacketCipher{cipher: noneCipher{}}, -+ pendingKeyChange: make(chan packetCipher, 1), -+ }, -+ Closer: rwc, -+ } -+ t.isClient = isClient -+ -+ if isClient { -+ t.reader.dir = serverKeys -+ t.writer.dir = clientKeys -+ } else { -+ t.reader.dir = clientKeys -+ t.writer.dir = serverKeys -+ } -+ -+ return t -+} -+ -+type direction struct { -+ ivTag []byte -+ keyTag []byte -+ macKeyTag []byte -+} -+ -+var ( -+ serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} -+ clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} -+) -+ -+// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as -+// described in RFC 4253, section 6.4. direction should either be serverKeys -+// (to setup server->client keys) or clientKeys (for client->server keys). -+func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { -+ cipherMode := cipherModes[algs.Cipher] -+ -+ iv := make([]byte, cipherMode.ivSize) -+ key := make([]byte, cipherMode.keySize) -+ -+ generateKeyMaterial(iv, d.ivTag, kex) -+ generateKeyMaterial(key, d.keyTag, kex) -+ -+ var macKey []byte -+ if !aeadCiphers[algs.Cipher] { -+ macMode := macModes[algs.MAC] -+ macKey = make([]byte, macMode.keySize) -+ generateKeyMaterial(macKey, d.macKeyTag, kex) -+ } -+ -+ return cipherModes[algs.Cipher].create(key, iv, macKey, algs) -+} -+ -+// generateKeyMaterial fills out with key material generated from tag, K, H -+// and sessionId, as specified in RFC 4253, section 7.2. -+func generateKeyMaterial(out, tag []byte, r *kexResult) { -+ var digestsSoFar []byte -+ -+ h := r.Hash.New() -+ for len(out) > 0 { -+ h.Reset() -+ h.Write(r.K) -+ h.Write(r.H) -+ -+ if len(digestsSoFar) == 0 { -+ h.Write(tag) -+ h.Write(r.SessionID) -+ } else { -+ h.Write(digestsSoFar) -+ } -+ -+ digest := h.Sum(nil) -+ n := copy(out, digest) -+ out = out[n:] -+ if len(out) > 0 { -+ digestsSoFar = append(digestsSoFar, digest...) -+ } -+ } -+} -+ -+const packageVersion = "SSH-2.0-Go" -+ -+// Sends and receives a version line. The versionLine string should -+// be US ASCII, start with "SSH-2.0-", and should not include a -+// newline. exchangeVersions returns the other side's version line. -+func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { -+ // Contrary to the RFC, we do not ignore lines that don't -+ // start with "SSH-2.0-" to make the library usable with -+ // nonconforming servers. -+ for _, c := range versionLine { -+ // The spec disallows non US-ASCII chars, and -+ // specifically forbids null chars. -+ if c < 32 { -+ return nil, errors.New("ssh: junk character in version line") -+ } -+ } -+ if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { -+ return -+ } -+ -+ them, err = readVersion(rw) -+ return them, err -+} -+ -+// maxVersionStringBytes is the maximum number of bytes that we'll -+// accept as a version string. RFC 4253 section 4.2 limits this at 255 -+// chars -+const maxVersionStringBytes = 255 -+ -+// Read version string as specified by RFC 4253, section 4.2. -+func readVersion(r io.Reader) ([]byte, error) { -+ versionString := make([]byte, 0, 64) -+ var ok bool -+ var buf [1]byte -+ -+ for length := 0; length < maxVersionStringBytes; length++ { -+ _, err := io.ReadFull(r, buf[:]) -+ if err != nil { -+ return nil, err -+ } -+ // The RFC says that the version should be terminated with \r\n -+ // but several SSH servers actually only send a \n. -+ if buf[0] == '\n' { -+ if !bytes.HasPrefix(versionString, []byte("SSH-")) { -+ // RFC 4253 says we need to ignore all version string lines -+ // except the one containing the SSH version (provided that -+ // all the lines do not exceed 255 bytes in total). -+ versionString = versionString[:0] -+ continue -+ } -+ ok = true -+ break -+ } -+ -+ // non ASCII chars are disallowed, but we are lenient, -+ // since Go doesn't use null-terminated strings. -+ -+ // The RFC allows a comment after a space, however, -+ // all of it (version and comments) goes into the -+ // session hash. -+ versionString = append(versionString, buf[0]) -+ } -+ -+ if !ok { -+ return nil, errors.New("ssh: overflow reading version string") -+ } -+ -+ // There might be a '\r' on the end which we should remove. -+ if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { -+ versionString = versionString[:len(versionString)-1] -+ } -+ return versionString, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/ssh/transport_test.go b/ms_mod/golang.org/x/crypto/ssh/transport_test.go -new file mode 100644 -index 00000000000000..8445e1e561c15a ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/ssh/transport_test.go -@@ -0,0 +1,113 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ssh -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/binary" -+ "strings" -+ "testing" -+) -+ -+func TestReadVersion(t *testing.T) { -+ longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] -+ multiLineVersion := strings.Repeat("ignored\r\n", 20) + "SSH-2.0-bla\r\n" -+ cases := map[string]string{ -+ "SSH-2.0-bla\r\n": "SSH-2.0-bla", -+ "SSH-2.0-bla\n": "SSH-2.0-bla", -+ multiLineVersion: "SSH-2.0-bla", -+ longVersion + "\r\n": longVersion, -+ } -+ -+ for in, want := range cases { -+ result, err := readVersion(bytes.NewBufferString(in)) -+ if err != nil { -+ t.Errorf("readVersion(%q): %s", in, err) -+ } -+ got := string(result) -+ if got != want { -+ t.Errorf("got %q, want %q", got, want) -+ } -+ } -+} -+ -+func TestReadVersionError(t *testing.T) { -+ longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] -+ multiLineVersion := strings.Repeat("ignored\r\n", 50) + "SSH-2.0-bla\r\n" -+ cases := []string{ -+ longVersion + "too-long\r\n", -+ multiLineVersion, -+ } -+ for _, in := range cases { -+ if _, err := readVersion(bytes.NewBufferString(in)); err == nil { -+ t.Errorf("readVersion(%q) should have failed", in) -+ } -+ } -+} -+ -+func TestExchangeVersionsBasic(t *testing.T) { -+ v := "SSH-2.0-bla" -+ buf := bytes.NewBufferString(v + "\r\n") -+ them, err := exchangeVersions(buf, []byte("xyz")) -+ if err != nil { -+ t.Errorf("exchangeVersions: %v", err) -+ } -+ -+ if want := "SSH-2.0-bla"; string(them) != want { -+ t.Errorf("got %q want %q for our version", them, want) -+ } -+} -+ -+func TestExchangeVersions(t *testing.T) { -+ cases := []string{ -+ "not\x000allowed", -+ "not allowed\x01\r\n", -+ } -+ for _, c := range cases { -+ buf := bytes.NewBufferString("SSH-2.0-bla\r\n") -+ if _, err := exchangeVersions(buf, []byte(c)); err == nil { -+ t.Errorf("exchangeVersions(%q): should have failed", c) -+ } -+ } -+} -+ -+type closerBuffer struct { -+ bytes.Buffer -+} -+ -+func (b *closerBuffer) Close() error { -+ return nil -+} -+ -+func TestTransportMaxPacketWrite(t *testing.T) { -+ buf := &closerBuffer{} -+ tr := newTransport(buf, rand.Reader, true) -+ huge := make([]byte, maxPacket+1) -+ err := tr.writePacket(huge) -+ if err == nil { -+ t.Errorf("transport accepted write for a huge packet.") -+ } -+} -+ -+func TestTransportMaxPacketReader(t *testing.T) { -+ var header [5]byte -+ huge := make([]byte, maxPacket+128) -+ binary.BigEndian.PutUint32(header[0:], uint32(len(huge))) -+ // padding. -+ header[4] = 0 -+ -+ buf := &closerBuffer{} -+ buf.Write(header[:]) -+ buf.Write(huge) -+ -+ tr := newTransport(buf, rand.Reader, true) -+ _, err := tr.readPacket() -+ if err == nil { -+ t.Errorf("transport succeeded reading huge packet.") -+ } else if !strings.Contains(err.Error(), "large") { -+ t.Errorf("got %q, should mention %q", err.Error(), "large") -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/tea/cipher.go b/ms_mod/golang.org/x/crypto/tea/cipher.go -new file mode 100644 -index 00000000000000..c1ff90e048d005 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/tea/cipher.go -@@ -0,0 +1,116 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package tea implements the TEA algorithm, as defined in Needham and -+// Wheeler's 1994 technical report, β€œTEA, a Tiny Encryption Algorithm”. See -+// http://www.cix.co.uk/~klockstone/tea.pdf for details. -+// -+// TEA is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package tea -+ -+import ( -+ "crypto/cipher" -+ "encoding/binary" -+ "errors" -+) -+ -+const ( -+ // BlockSize is the size of a TEA block, in bytes. -+ BlockSize = 8 -+ -+ // KeySize is the size of a TEA key, in bytes. -+ KeySize = 16 -+ -+ // delta is the TEA key schedule constant. -+ delta = 0x9e3779b9 -+ -+ // numRounds is the standard number of rounds in TEA. -+ numRounds = 64 -+) -+ -+// tea is an instance of the TEA cipher with a particular key. -+type tea struct { -+ key [16]byte -+ rounds int -+} -+ -+// NewCipher returns an instance of the TEA cipher with the standard number of -+// rounds. The key argument must be 16 bytes long. -+func NewCipher(key []byte) (cipher.Block, error) { -+ return NewCipherWithRounds(key, numRounds) -+} -+ -+// NewCipherWithRounds returns an instance of the TEA cipher with a given -+// number of rounds, which must be even. The key argument must be 16 bytes -+// long. -+func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { -+ if len(key) != 16 { -+ return nil, errors.New("tea: incorrect key size") -+ } -+ -+ if rounds&1 != 0 { -+ return nil, errors.New("tea: odd number of rounds specified") -+ } -+ -+ c := &tea{ -+ rounds: rounds, -+ } -+ copy(c.key[:], key) -+ -+ return c, nil -+} -+ -+// BlockSize returns the TEA block size, which is eight bytes. It is necessary -+// to satisfy the Block interface in the package "crypto/cipher". -+func (*tea) BlockSize() int { -+ return BlockSize -+} -+ -+// Encrypt encrypts the 8 byte buffer src using the key in t and stores the -+// result in dst. Note that for amounts of data larger than a block, it is not -+// safe to just call Encrypt on successive blocks; instead, use an encryption -+// mode like CBC (see crypto/cipher/cbc.go). -+func (t *tea) Encrypt(dst, src []byte) { -+ e := binary.BigEndian -+ v0, v1 := e.Uint32(src), e.Uint32(src[4:]) -+ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) -+ -+ sum := uint32(0) -+ delta := uint32(delta) -+ -+ for i := 0; i < t.rounds/2; i++ { -+ sum += delta -+ v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) -+ v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) -+ } -+ -+ e.PutUint32(dst, v0) -+ e.PutUint32(dst[4:], v1) -+} -+ -+// Decrypt decrypts the 8 byte buffer src using the key in t and stores the -+// result in dst. -+func (t *tea) Decrypt(dst, src []byte) { -+ e := binary.BigEndian -+ v0, v1 := e.Uint32(src), e.Uint32(src[4:]) -+ k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) -+ -+ delta := uint32(delta) -+ sum := delta * uint32(t.rounds/2) // in general, sum = delta * n -+ -+ for i := 0; i < t.rounds/2; i++ { -+ v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) -+ v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) -+ sum -= delta -+ } -+ -+ e.PutUint32(dst, v0) -+ e.PutUint32(dst[4:], v1) -+} -diff --git a/ms_mod/golang.org/x/crypto/tea/tea_test.go b/ms_mod/golang.org/x/crypto/tea/tea_test.go -new file mode 100644 -index 00000000000000..eb98d1e0e03e64 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/tea/tea_test.go -@@ -0,0 +1,93 @@ -+// Copyright 2015 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package tea -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+// A sample test key for when we just want to initialize a cipher -+var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} -+ -+// Test that the block size for tea is correct -+func TestBlocksize(t *testing.T) { -+ c, err := NewCipher(testKey) -+ if err != nil { -+ t.Fatalf("NewCipher returned error: %s", err) -+ } -+ -+ if result := c.BlockSize(); result != BlockSize { -+ t.Errorf("cipher.BlockSize returned %d, but expected %d", result, BlockSize) -+ } -+} -+ -+// Test that invalid key sizes return an error -+func TestInvalidKeySize(t *testing.T) { -+ var key [KeySize + 1]byte -+ -+ if _, err := NewCipher(key[:]); err == nil { -+ t.Errorf("invalid key size %d didn't result in an error.", len(key)) -+ } -+ -+ if _, err := NewCipher(key[:KeySize-1]); err == nil { -+ t.Errorf("invalid key size %d didn't result in an error.", KeySize-1) -+ } -+} -+ -+// Test Vectors -+type teaTest struct { -+ rounds int -+ key []byte -+ plaintext []byte -+ ciphertext []byte -+} -+ -+var teaTests = []teaTest{ -+ // These were sourced from https://github.com/froydnj/ironclad/blob/master/testing/test-vectors/tea.testvec -+ { -+ numRounds, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x41, 0xea, 0x3a, 0x0a, 0x94, 0xba, 0xa9, 0x40}, -+ }, -+ { -+ numRounds, -+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, -+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, -+ []byte{0x31, 0x9b, 0xbe, 0xfb, 0x01, 0x6a, 0xbd, 0xb2}, -+ }, -+ { -+ 16, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0xed, 0x28, 0x5d, 0xa1, 0x45, 0x5b, 0x33, 0xc1}, -+ }, -+} -+ -+// Test encryption -+func TestCipherEncrypt(t *testing.T) { -+ // Test encryption with standard 64 rounds -+ for i, test := range teaTests { -+ c, err := NewCipherWithRounds(test.key, test.rounds) -+ if err != nil { -+ t.Fatalf("#%d: NewCipher returned error: %s", i, err) -+ } -+ -+ var ciphertext [BlockSize]byte -+ c.Encrypt(ciphertext[:], test.plaintext) -+ -+ if !bytes.Equal(ciphertext[:], test.ciphertext) { -+ t.Errorf("#%d: incorrect ciphertext. Got %x, wanted %x", i, ciphertext, test.ciphertext) -+ } -+ -+ var plaintext2 [BlockSize]byte -+ c.Decrypt(plaintext2[:], ciphertext[:]) -+ -+ if !bytes.Equal(plaintext2[:], test.plaintext) { -+ t.Errorf("#%d: incorrect plaintext. Got %x, wanted %x", i, plaintext2, test.plaintext) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/twofish/twofish.go b/ms_mod/golang.org/x/crypto/twofish/twofish.go -new file mode 100644 -index 00000000000000..e4eeae17f4040f ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/twofish/twofish.go -@@ -0,0 +1,341 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package twofish implements Bruce Schneier's Twofish encryption algorithm. -+// -+// Deprecated: Twofish is a legacy cipher and should not be used for new -+// applications. Also, this package does not and will not provide an optimized -+// implementation. Instead, use AES (from crypto/aes, if necessary in an AEAD -+// mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package twofish // import "golang.org/x/crypto/twofish" -+ -+// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH] -+ -+// This code is a port of the LibTom C implementation. -+// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. -+// LibTomCrypt is free for all purposes under the public domain. -+// It was heavily inspired by the go blowfish package. -+ -+import ( -+ "math/bits" -+ "strconv" -+) -+ -+// BlockSize is the constant block size of Twofish. -+const BlockSize = 16 -+ -+const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 -+const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 -+ -+// A Cipher is an instance of Twofish encryption using a particular key. -+type Cipher struct { -+ s [4][256]uint32 -+ k [40]uint32 -+} -+ -+type KeySizeError int -+ -+func (k KeySizeError) Error() string { -+ return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) -+} -+ -+// NewCipher creates and returns a Cipher. -+// The key argument should be the Twofish key, 16, 24 or 32 bytes. -+func NewCipher(key []byte) (*Cipher, error) { -+ keylen := len(key) -+ -+ if keylen != 16 && keylen != 24 && keylen != 32 { -+ return nil, KeySizeError(keylen) -+ } -+ -+ // k is the number of 64 bit words in key -+ k := keylen / 8 -+ -+ // Create the S[..] words -+ var S [4 * 4]byte -+ for i := 0; i < k; i++ { -+ // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] -+ for j, rsRow := range rs { -+ for k, rsVal := range rsRow { -+ S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial) -+ } -+ } -+ } -+ -+ // Calculate subkeys -+ c := new(Cipher) -+ var tmp [4]byte -+ for i := byte(0); i < 20; i++ { -+ // A = h(p * 2x, Me) -+ for j := range tmp { -+ tmp[j] = 2 * i -+ } -+ A := h(tmp[:], key, 0) -+ -+ // B = rolc(h(p * (2x + 1), Mo), 8) -+ for j := range tmp { -+ tmp[j] = 2*i + 1 -+ } -+ B := h(tmp[:], key, 1) -+ B = bits.RotateLeft32(B, 8) -+ -+ c.k[2*i] = A + B -+ -+ // K[2i+1] = (A + 2B) <<< 9 -+ c.k[2*i+1] = bits.RotateLeft32(2*B+A, 9) -+ } -+ -+ // Calculate sboxes -+ switch k { -+ case 2: -+ for i := range c.s[0] { -+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0) -+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1) -+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2) -+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3) -+ } -+ case 3: -+ for i := range c.s[0] { -+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0) -+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1) -+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2) -+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3) -+ } -+ default: -+ for i := range c.s[0] { -+ c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) -+ c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) -+ c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) -+ c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) -+ } -+ } -+ -+ return c, nil -+} -+ -+// BlockSize returns the Twofish block size, 16 bytes. -+func (c *Cipher) BlockSize() int { return BlockSize } -+ -+// store32l stores src in dst in little-endian form. -+func store32l(dst []byte, src uint32) { -+ dst[0] = byte(src) -+ dst[1] = byte(src >> 8) -+ dst[2] = byte(src >> 16) -+ dst[3] = byte(src >> 24) -+ return -+} -+ -+// load32l reads a little-endian uint32 from src. -+func load32l(src []byte) uint32 { -+ return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24 -+} -+ -+// The RS matrix. See [TWOFISH] 4.3 -+var rs = [4][8]byte{ -+ {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E}, -+ {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5}, -+ {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19}, -+ {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03}, -+} -+ -+// sbox tables -+var sbox = [2][256]byte{ -+ { -+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, -+ 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, -+ 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, -+ 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61, -+ 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, -+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, -+ 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, -+ 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, -+ 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, -+ 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, -+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, -+ 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a, -+ 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, -+ 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, -+ 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, -+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0, -+ }, -+ { -+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, -+ 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f, -+ 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, -+ 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, -+ 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, -+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, -+ 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, -+ 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, -+ 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, -+ 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, -+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, -+ 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64, -+ 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, -+ 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, -+ 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, -+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91, -+ }, -+} -+ -+// gfMult returns aΒ·b in GF(2^8)/p -+func gfMult(a, b byte, p uint32) byte { -+ B := [2]uint32{0, uint32(b)} -+ P := [2]uint32{0, p} -+ var result uint32 -+ -+ // branchless GF multiplier -+ for i := 0; i < 7; i++ { -+ result ^= B[a&1] -+ a >>= 1 -+ B[1] = P[B[1]>>7] ^ (B[1] << 1) -+ } -+ result ^= B[a&1] -+ return byte(result) -+} -+ -+// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS Β· [x0] -+func mdsColumnMult(in byte, col int) uint32 { -+ mul01 := in -+ mul5B := gfMult(in, 0x5B, mdsPolynomial) -+ mulEF := gfMult(in, 0xEF, mdsPolynomial) -+ -+ switch col { -+ case 0: -+ return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24 -+ case 1: -+ return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24 -+ case 2: -+ return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24 -+ case 3: -+ return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24 -+ } -+ -+ panic("unreachable") -+} -+ -+// h implements the S-box generation function. See [TWOFISH] 4.3.5 -+func h(in, key []byte, offset int) uint32 { -+ var y [4]byte -+ for x := range y { -+ y[x] = in[x] -+ } -+ switch len(key) / 8 { -+ case 4: -+ y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] -+ y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] -+ y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] -+ y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] -+ fallthrough -+ case 3: -+ y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] -+ y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] -+ y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] -+ y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] -+ fallthrough -+ case 2: -+ y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]] -+ y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]] -+ y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]] -+ y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]] -+ } -+ // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] -+ var mdsMult uint32 -+ for i := range y { -+ mdsMult ^= mdsColumnMult(y[i], i) -+ } -+ return mdsMult -+} -+ -+// Encrypt encrypts a 16-byte block from src to dst, which may overlap. -+// Note that for amounts of data larger than a block, -+// it is not safe to just call Encrypt on successive blocks; -+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -+func (c *Cipher) Encrypt(dst, src []byte) { -+ S1 := c.s[0] -+ S2 := c.s[1] -+ S3 := c.s[2] -+ S4 := c.s[3] -+ -+ // Load input -+ ia := load32l(src[0:4]) -+ ib := load32l(src[4:8]) -+ ic := load32l(src[8:12]) -+ id := load32l(src[12:16]) -+ -+ // Pre-whitening -+ ia ^= c.k[0] -+ ib ^= c.k[1] -+ ic ^= c.k[2] -+ id ^= c.k[3] -+ -+ for i := 0; i < 8; i++ { -+ k := c.k[8+i*4 : 12+i*4] -+ t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] -+ t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 -+ ic = bits.RotateLeft32(ic^(t1+k[0]), -1) -+ id = bits.RotateLeft32(id, 1) ^ (t2 + t1 + k[1]) -+ -+ t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] -+ t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 -+ ia = bits.RotateLeft32(ia^(t1+k[2]), -1) -+ ib = bits.RotateLeft32(ib, 1) ^ (t2 + t1 + k[3]) -+ } -+ -+ // Output with "undo last swap" -+ ta := ic ^ c.k[4] -+ tb := id ^ c.k[5] -+ tc := ia ^ c.k[6] -+ td := ib ^ c.k[7] -+ -+ store32l(dst[0:4], ta) -+ store32l(dst[4:8], tb) -+ store32l(dst[8:12], tc) -+ store32l(dst[12:16], td) -+} -+ -+// Decrypt decrypts a 16-byte block from src to dst, which may overlap. -+func (c *Cipher) Decrypt(dst, src []byte) { -+ S1 := c.s[0] -+ S2 := c.s[1] -+ S3 := c.s[2] -+ S4 := c.s[3] -+ -+ // Load input -+ ta := load32l(src[0:4]) -+ tb := load32l(src[4:8]) -+ tc := load32l(src[8:12]) -+ td := load32l(src[12:16]) -+ -+ // Undo undo final swap -+ ia := tc ^ c.k[6] -+ ib := td ^ c.k[7] -+ ic := ta ^ c.k[4] -+ id := tb ^ c.k[5] -+ -+ for i := 8; i > 0; i-- { -+ k := c.k[4+i*4 : 8+i*4] -+ t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] -+ t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 -+ ia = bits.RotateLeft32(ia, 1) ^ (t1 + k[2]) -+ ib = bits.RotateLeft32(ib^(t2+t1+k[3]), -1) -+ -+ t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] -+ t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 -+ ic = bits.RotateLeft32(ic, 1) ^ (t1 + k[0]) -+ id = bits.RotateLeft32(id^(t2+t1+k[1]), -1) -+ } -+ -+ // Undo pre-whitening -+ ia ^= c.k[0] -+ ib ^= c.k[1] -+ ic ^= c.k[2] -+ id ^= c.k[3] -+ -+ store32l(dst[0:4], ia) -+ store32l(dst[4:8], ib) -+ store32l(dst[8:12], ic) -+ store32l(dst[12:16], id) -+} -diff --git a/ms_mod/golang.org/x/crypto/twofish/twofish_test.go b/ms_mod/golang.org/x/crypto/twofish/twofish_test.go -new file mode 100644 -index 00000000000000..ed6a1a8fdbb788 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/twofish/twofish_test.go -@@ -0,0 +1,129 @@ -+// Copyright 2011 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package twofish -+ -+import ( -+ "bytes" -+ "testing" -+) -+ -+var qbox = [2][4][16]byte{ -+ { -+ {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4}, -+ {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD}, -+ {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1}, -+ {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA}, -+ }, -+ { -+ {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5}, -+ {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8}, -+ {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF}, -+ {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA}, -+ }, -+} -+ -+// genSbox generates the variable sbox -+func genSbox(qi int, x byte) byte { -+ a0, b0 := x/16, x%16 -+ for i := 0; i < 2; i++ { -+ a1 := a0 ^ b0 -+ b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15 -+ a0 = qbox[qi][2*i][a1] -+ b0 = qbox[qi][2*i+1][b1] -+ } -+ return (b0 << 4) + a0 -+} -+ -+func TestSbox(t *testing.T) { -+ for n := range sbox { -+ for m := range sbox[n] { -+ if genSbox(n, byte(m)) != sbox[n][m] { -+ t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m))) -+ } -+ } -+ } -+} -+ -+var testVectors = []struct { -+ key []byte -+ dec []byte -+ enc []byte -+}{ -+ // These tests are extracted from LibTom -+ { -+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, -+ []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19}, -+ []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3}, -+ }, -+ { -+ []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, -+ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44}, -+ []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2}, -+ []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65}, -+ }, -+ { -+ []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, -+ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F}, -+ []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6}, -+ []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA}, -+ }, -+ // These tests are derived from https://www.schneier.com/code/ecb_ival.txt -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, -+ }, -+ { -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, -+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, -+ }, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48}, -+ }, -+ { -+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, -+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, -+ }, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20}, -+ }, -+} -+ -+func TestCipher(t *testing.T) { -+ for n, tt := range testVectors { -+ // Test if the plaintext (dec) is encrypts to the given -+ // ciphertext (enc) using the given key. Test also if enc can -+ // be decrypted again into dec. -+ c, err := NewCipher(tt.key) -+ if err != nil { -+ t.Errorf("#%d: NewCipher: %v", n, err) -+ return -+ } -+ -+ buf := make([]byte, 16) -+ c.Encrypt(buf, tt.dec) -+ if !bytes.Equal(buf, tt.enc) { -+ t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc) -+ } -+ c.Decrypt(buf, tt.enc) -+ if !bytes.Equal(buf, tt.dec) { -+ t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec) -+ } -+ -+ // Test that 16 zero bytes, encrypted 1000 times then decrypted -+ // 1000 times results in zero bytes again. -+ zero := make([]byte, 16) -+ buf = make([]byte, 16) -+ for i := 0; i < 1000; i++ { -+ c.Encrypt(buf, buf) -+ } -+ for i := 0; i < 1000; i++ { -+ c.Decrypt(buf, buf) -+ } -+ if !bytes.Equal(buf, zero) { -+ t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero) -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go b/ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go -new file mode 100644 -index 00000000000000..542ac87217b110 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/bundle.go -@@ -0,0 +1,3827 @@ -+// Code generated by gen_fallback_bundle.go; DO NOT EDIT. -+ -+//go:build go1.20 -+ -+package fallback -+ -+import "crypto/x509" -+import "encoding/pem" -+ -+func mustParse(b []byte) []*x509.Certificate { -+ var roots []*x509.Certificate -+ for len(b) > 0 { -+ var block *pem.Block -+ block, b = pem.Decode(b) -+ if block == nil { -+ break -+ } -+ if block.Type != "CERTIFICATE" { -+ panic("unexpected PEM block type: " + block.Type) -+ } -+ cert, err := x509.ParseCertificate(block.Bytes) -+ if err != nil { -+ panic(err) -+ } -+ roots = append(roots, cert) -+ } -+ return roots -+} -+ -+var bundle = mustParse([]byte(pemRoots)) -+ -+// Format of the PEM list is: -+// * Subject common name -+// * SHA256 hash -+// * PEM block -+ -+const pemRoots = ` -+# CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4 -+-----BEGIN CERTIFICATE----- -+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -+-----END CERTIFICATE----- -+# CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS,OU=Ceres,O=FNMT-RCM,C=ES,2.5.4.97=#130f56415445532d51323832363030344a -+# 554153b13d2cf9ddb753bfbe1a4e0ae08d0aa4187058fe60a2b862b2e4b87bcb -+-----BEGIN CERTIFICATE----- -+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw -+CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw -+FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S -+Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 -+MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL -+DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS -+QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB -+BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH -+sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK -+Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -+VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu -+SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC -+MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy -+v+c= -+-----END CERTIFICATE----- -+# CN=ACCVRAIZ1,OU=PKIACCV,O=ACCV,C=ES -+# 9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113 -+-----BEGIN CERTIFICATE----- -+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE -+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw -+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ -+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND -+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb -+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY -+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo -+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA -+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr -+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ -+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH -+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 -+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO -+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa -+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl -+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI -+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls -+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG -+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT -+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG -+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA -+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA -+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA -+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA -+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA -+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA -+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu -+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt -+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud -+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF -+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp -+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU -+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m -+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD -+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms -+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH -+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA -+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF -+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H -+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 -+-----END CERTIFICATE----- -+# CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT -+# 55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066 -+-----BEGIN CERTIFICATE----- -+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE -+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w -+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC -+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 -+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB -+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv -+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX -+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 -+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ -+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb -+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ -+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F -+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe -+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F -+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn -+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 -+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz -+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL -+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 -+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz -+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V -+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j -+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX -+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok -+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R -+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU -+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU -+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT -+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -+-----END CERTIFICATE----- -+# CN=AffirmTrust Commercial,O=AffirmTrust,C=US -+# 0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7 -+-----BEGIN CERTIFICATE----- -+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -+-----END CERTIFICATE----- -+# CN=AffirmTrust Networking,O=AffirmTrust,C=US -+# 0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b -+-----BEGIN CERTIFICATE----- -+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -+-----END CERTIFICATE----- -+# CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US -+# bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423 -+-----BEGIN CERTIFICATE----- -+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== -+-----END CERTIFICATE----- -+# CN=AffirmTrust Premium,O=AffirmTrust,C=US -+# 70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a -+-----BEGIN CERTIFICATE----- -+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -+KeC2uAloGRwYQw== -+-----END CERTIFICATE----- -+# CN=Amazon Root CA 1,O=Amazon,C=US -+# 8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e -+-----BEGIN CERTIFICATE----- -+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -+rqXRfboQnoZsG4q5WTP468SQvvG5 -+-----END CERTIFICATE----- -+# CN=Amazon Root CA 2,O=Amazon,C=US -+# 1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4 -+-----BEGIN CERTIFICATE----- -+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF -+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL -+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK -+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ -+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg -+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K -+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r -+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me -+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR -+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj -+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz -+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 -++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI -+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB -+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm -+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 -+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS -+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl -+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm -+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl -+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ -+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 -+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE -+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H -+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT -+4PsJYGw= -+-----END CERTIFICATE----- -+# CN=Amazon Root CA 3,O=Amazon,C=US -+# 18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4 -+-----BEGIN CERTIFICATE----- -+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 -+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl -+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j -+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr -+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr -+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM -+YyRIHN8wfdVoOw== -+-----END CERTIFICATE----- -+# CN=Amazon Root CA 4,O=Amazon,C=US -+# e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092 -+-----BEGIN CERTIFICATE----- -+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 -+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi -+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk -+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB -+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB -+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw -+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW -+1KyLa2tJElMzrdfkviT8tQp21KW8EA== -+-----END CERTIFICATE----- -+# CN=Atos TrustedRoot 2011,O=Atos,C=DE -+# f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474 -+-----BEGIN CERTIFICATE----- -+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE -+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG -+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM -+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC -+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp -+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM -+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ -+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ -+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L -+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi -+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV -+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG -+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 -+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j -+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP -+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc -+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D -+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv -+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -+-----END CERTIFICATE----- -+# CN=Atos TrustedRoot Root CA ECC TLS 2021,O=Atos,C=DE -+# b2fae53e14ccd7ab9212064701ae279c1d8988facb775fa8a008914e663988a8 -+-----BEGIN CERTIFICATE----- -+MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w -+LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w -+CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 -+MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF -+Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI -+zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X -+tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 -+AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 -+KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD -+aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu -+CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo -+9H1/IISpQuQo -+-----END CERTIFICATE----- -+# CN=Atos TrustedRoot Root CA RSA TLS 2021,O=Atos,C=DE -+# 81a9088ea59fb364c548a6f85559099b6f0405efbf18e5324ec9f457ba00112f -+-----BEGIN CERTIFICATE----- -+MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM -+MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx -+MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 -+MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD -+QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN -+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z -+4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv -+Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ -+kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs -+GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln -+nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh -+3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD -+0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy -+geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 -+ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB -+c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI -+pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -+dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -+DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS -+4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs -+o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ -+qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw -+xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM -+rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 -+AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR -+0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY -+o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 -+dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE -+oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== -+-----END CERTIFICATE----- -+# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES -+# 57de0583efd2b26e0361da99da9df4648def7ee8441c3b728afa9bcde0f9b26a -+-----BEGIN CERTIFICATE----- -+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE -+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 -+MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg -+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi -+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 -+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM -+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG -+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i -+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h -+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b -+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy -+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja -+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T -+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF -+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh -+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc -+tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd -+IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j -+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC -+AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw -+ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m -+iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF -+Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ -+hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P -+Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE -+EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV -+1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t -+CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR -+5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw -+f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 -+ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK -+GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV -+-----END CERTIFICATE----- -+# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES -+# 04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef -+-----BEGIN CERTIFICATE----- -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 -+jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -+-----END CERTIFICATE----- -+# CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN -+# f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae -+-----BEGIN CERTIFICATE----- -+MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU -+MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI -+T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz -+MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF -+SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh -+bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z -+xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ -+spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 -+58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR -+at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll -+5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq -+nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK -+V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ -+pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO -+z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn -+jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ -+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF -+7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -+AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 -+YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli -+awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u -++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 -+X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN -+SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo -+P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI -++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz -+znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 -+eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 -+YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy -+r/6zcCwupvI= -+-----END CERTIFICATE----- -+# CN=BJCA Global Root CA2,O=BEIJING CERTIFICATE AUTHORITY,C=CN -+# 574df6931e278039667b720afdc1600fc27eb66dd3092979fb73856487212882 -+-----BEGIN CERTIFICATE----- -+MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw -+CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ -+VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy -+MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ -+TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS -+b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B -+IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ -++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK -+sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -+AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA -+94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B -+43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== -+-----END CERTIFICATE----- -+# CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE -+# 16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb -+-----BEGIN CERTIFICATE----- -+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -+-----END CERTIFICATE----- -+# CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO -+# 9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48 -+-----BEGIN CERTIFICATE----- -+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow -+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr -+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV -+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 -+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx -+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ -+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB -+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr -+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi -+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS -+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN -+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP -+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz -+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h -+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t -+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo -++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 -+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 -+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us -+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ -+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 -+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h -+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz -+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= -+-----END CERTIFICATE----- -+# CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO -+# edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d -+-----BEGIN CERTIFICATE----- -+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow -+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y -+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E -+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 -+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX -+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c -+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X -+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY -+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS -+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D -+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP -+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 -+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv -+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj -+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS -+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 -+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa -+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv -+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u -+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE -+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 -+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD -+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq -+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= -+-----END CERTIFICATE----- -+# CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK -+# e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703 -+-----BEGIN CERTIFICATE----- -+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV -+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu -+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy -+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx -+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw -+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe -+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH -+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I -+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe -+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR -+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO -+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 -+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ -+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD -+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs -+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 -+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI -+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf -+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb -+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka -++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal -+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i -+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 -+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr -+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os -+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x -+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL -+-----END CERTIFICATE----- -+# CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN -+# 5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd -+-----BEGIN CERTIFICATE----- -+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD -+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y -+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx -+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j -+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP -+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 -+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL -+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 -+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp -+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz -+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt -+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP -+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot -+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg -+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV -+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv -+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL -+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd -+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT -+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL -+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS -+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy -+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 -+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d -+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN -+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe -+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z -+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ -+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -+-----END CERTIFICATE----- -+# CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# 0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66 -+-----BEGIN CERTIFICATE----- -+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -+ZQ== -+-----END CERTIFICATE----- -+# CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# 1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7 -+-----BEGIN CERTIFICATE----- -+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -+-----END CERTIFICATE----- -+# CN=COMODO RSA Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# 52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234 -+-----BEGIN CERTIFICATE----- -+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB -+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV -+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 -+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT -+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh -+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR -+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X -+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC -+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV -+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf -+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z -++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w -+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah -+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC -+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf -+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq -+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E -+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB -+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl -+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM -+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV -+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna -+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ -+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK -+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke -+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL -+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb -+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl -+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB -+NVOFBkpdn627G190 -+-----END CERTIFICATE----- -+# CN=Certainly Root E1,O=Certainly,C=US -+# b4585f22e4ac756a4e8612a1361c5d9d031a93fd84febb778fa3068b0fc42dc2 -+-----BEGIN CERTIFICATE----- -+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw -+CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu -+bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ -+BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s -+eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK -++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 -+QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E -+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 -+hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm -+ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG -+BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -+-----END CERTIFICATE----- -+# CN=Certainly Root R1,O=Certainly,C=US -+# 77b82cd8644c4305f7acc5cb156b45675004033d51c60c6202a8e0c33467d3a0 -+-----BEGIN CERTIFICATE----- -+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw -+PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy -+dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 -+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 -+YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 -+1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT -+vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed -+aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 -+1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 -+r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 -+cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ -+wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ -+6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA -+2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH -+Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR -+eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB -+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u -+d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr -+PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d -+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi -+1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd -+rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di -+taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 -+lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj -+yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn -+Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy -+yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n -+wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 -+OV+KmalBWQewLK8= -+-----END CERTIFICATE----- -+# CN=Certigna Root CA,OU=0002 48146308100036,O=Dhimyotis,C=FR -+# d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168 -+-----BEGIN CERTIFICATE----- -+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw -+WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw -+MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x -+MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD -+VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX -+BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -+ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO -+ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M -+CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu -+I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm -+TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh -+C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf -+ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz -+IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT -+Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k -+JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 -+hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB -+GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -+FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of -+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov -+L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo -+dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr -+aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq -+hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L -+6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG -+HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 -+0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB -+lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi -+o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 -+gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v -+faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 -+Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh -+jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw -+3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= -+-----END CERTIFICATE----- -+# CN=Certigna,O=Dhimyotis,C=FR -+# e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d -+-----BEGIN CERTIFICATE----- -+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV -+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X -+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ -+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 -+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 -+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny -+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw -+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q -+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 -+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw -+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw -+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT -+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj -+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG -+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h -+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc -+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu -+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w -+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -+-----END CERTIFICATE----- -+# CN=Certum EC-384 CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL -+# 6b328085625318aa50d173c98d8bda09d57e27413d114cf787a0f5d06c030cf6 -+-----BEGIN CERTIFICATE----- -+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw -+CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw -+JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT -+EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 -+WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT -+LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX -+BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE -+KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm -+Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj -+QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 -+EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J -+UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn -+nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= -+-----END CERTIFICATE----- -+# CN=Certum Trusted Network CA 2,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL -+# b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804 -+-----BEGIN CERTIFICATE----- -+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB -+gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu -+QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG -+A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz -+OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ -+VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp -+ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 -+b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA -+DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn -+0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB -+OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE -+fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E -+Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m -+o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i -+sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW -+OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez -+Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS -+adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n -+3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC -+AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ -+F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf -+CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 -+XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm -+djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ -+WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb -+AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq -+P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko -+b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj -+XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P -+5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi -+DrW5viSP -+-----END CERTIFICATE----- -+# CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL -+# 5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e -+-----BEGIN CERTIFICATE----- -+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM -+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D -+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU -+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 -+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg -+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw -+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B -+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH -+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM -+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU -+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM -+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x -+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV -+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV -+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y -+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL -+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 -+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY -+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -+-----END CERTIFICATE----- -+# CN=Certum Trusted Root CA,OU=Certum Certification Authority,O=Asseco Data Systems S.A.,C=PL -+# fe7696573855773e37a95e7ad4d9cc96c30157c15d31765ba9b15704e1ae78fd -+-----BEGIN CERTIFICATE----- -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 -+-----END CERTIFICATE----- -+# CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE -+# e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044 -+-----BEGIN CERTIFICATE----- -+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw -+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS -+VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 -+NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG -+A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB -+BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS -+zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 -+QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ -+VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g -+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf -+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l -+dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 -+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO -+PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW -+wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV -+dWNbFJWcHwHP2NVypw87 -+-----END CERTIFICATE----- -+# CN=D-TRUST EV Root CA 1 2020,O=D-Trust GmbH,C=DE -+# 08170d1aa36453901a2f959245e347db0c8d37abaabc56b81aa100dc958970db -+-----BEGIN CERTIFICATE----- -+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw -+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS -+VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 -+NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG -+A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB -+BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC -+/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD -+wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 -+OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g -+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf -+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l -+dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 -+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO -+PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA -+y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb -+gfM0agPnIjhQW+0ZT0MW -+-----END CERTIFICATE----- -+# CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE -+# 49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1 -+-----BEGIN CERTIFICATE----- -+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF -+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD -+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha -+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM -+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB -+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 -+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 -+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R -+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM -+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp -+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G -+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G -+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj -+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy -+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl -+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js -+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL -+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni -+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K -+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 -+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y -+Johw1+qRzT65ysCQblrGXnRl11z+o+I= -+-----END CERTIFICATE----- -+# CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE -+# eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881 -+-----BEGIN CERTIFICATE----- -+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF -+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD -+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw -+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV -+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI -+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn -+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 -+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z -+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR -+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 -+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw -+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea -+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw -+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh -+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E -+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt -+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku -+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp -+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF -+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na -+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX -+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 -+-----END CERTIFICATE----- -+# CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c -+-----BEGIN CERTIFICATE----- -+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -+-----END CERTIFICATE----- -+# CN=DigiCert Assured ID Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185 -+-----BEGIN CERTIFICATE----- -+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG -+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi -+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA -+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc -+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp -+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA -+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu -+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB -+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW -+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI -+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I -+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni -+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 -+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv -+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -+IhNzbM8m9Yop5w== -+-----END CERTIFICATE----- -+# CN=DigiCert Assured ID Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2 -+-----BEGIN CERTIFICATE----- -+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw -+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg -+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV -+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq -+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf -+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q -+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD -+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY -+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv -+6pZjamVFkpUBtA== -+-----END CERTIFICATE----- -+# CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161 -+-----BEGIN CERTIFICATE----- -+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -+-----END CERTIFICATE----- -+# CN=DigiCert Global Root G2,OU=www.digicert.com,O=DigiCert Inc,C=US -+# cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f -+-----BEGIN CERTIFICATE----- -+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -+MrY= -+-----END CERTIFICATE----- -+# CN=DigiCert Global Root G3,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0 -+-----BEGIN CERTIFICATE----- -+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw -+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe -+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw -+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x -+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF -+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG -+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO -+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd -+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx -+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ -+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 -+sycX -+-----END CERTIFICATE----- -+# CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf -+-----BEGIN CERTIFICATE----- -+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -++OkuE6N36B9K -+-----END CERTIFICATE----- -+# CN=DigiCert TLS ECC P384 Root G5,O=DigiCert\, Inc.,C=US -+# 018e13f0772532cf809bd1b17281867283fc48c6e13be9c69812854a490c1b05 -+-----BEGIN CERTIFICATE----- -+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw -+CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp -+Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 -+MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ -+bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG -+ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS -+7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp -+0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS -+B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 -+BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ -+LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 -+DXZDjC5Ty3zfDBeWUA== -+-----END CERTIFICATE----- -+# CN=DigiCert TLS RSA4096 Root G5,O=DigiCert\, Inc.,C=US -+# 371a00dc0533b3721a7eeb40e8419e70799d2b0a0f2c1d80693165f7cec4ad75 -+-----BEGIN CERTIFICATE----- -+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN -+MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT -+HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN -+NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs -+IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi -+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ -+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 -+2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp -+wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM -+pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD -+nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po -+sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx -+Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd -+Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX -+KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe -+XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL -+tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv -+TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN -+AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw -+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H -+PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF -+O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ -+REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik -+AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv -+/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ -+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw -+MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF -+qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK -+ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ -+-----END CERTIFICATE----- -+# CN=DigiCert Trusted Root G4,OU=www.digicert.com,O=DigiCert Inc,C=US -+# 552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988 -+-----BEGIN CERTIFICATE----- -+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg -+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV -+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG -+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y -+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If -+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV -+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO -+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ -+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ -+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi -+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM -+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY -+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK -+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t -+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 -+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd -++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc -+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa -+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N -+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N -+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie -+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI -+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 -+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm -+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ -+-----END CERTIFICATE----- -+# CN=Entrust Root Certification Authority - EC1,OU=See www.entrust.net/legal-terms+OU=(c) 2012 Entrust\, Inc. - for authorized use only,O=Entrust\, Inc.,C=US -+# 02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5 -+-----BEGIN CERTIFICATE----- -+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG -+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 -+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu -+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq -+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy -+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD -+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 -+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g -+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD -+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi -+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt -+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH -+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC -+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX -+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G -+-----END CERTIFICATE----- -+# CN=Entrust Root Certification Authority - G2,OU=See www.entrust.net/legal-terms+OU=(c) 2009 Entrust\, Inc. - for authorized use only,O=Entrust\, Inc.,C=US -+# 43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339 -+-----BEGIN CERTIFICATE----- -+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC -+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 -+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs -+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz -+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy -+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu -+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt -+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 -+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj -+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T -+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN -+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW -+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 -+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 -+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP -+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN -+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ -+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v -+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R -+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH -+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== -+-----END CERTIFICATE----- -+# CN=Entrust Root Certification Authority - G4,OU=See www.entrust.net/legal-terms+OU=(c) 2015 Entrust\, Inc. - for authorized use only,O=Entrust\, Inc.,C=US -+# db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88 -+-----BEGIN CERTIFICATE----- -+MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw -+gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL -+Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg -+MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw -+BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 -+MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT -+MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 -+c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ -+bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg -+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B -+AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ -+2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E -+T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j -+5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM -+C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T -+DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX -+wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A -+2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm -+nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 -+dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl -+N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj -+c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -+VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS -+5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS -+Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr -+hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ -+B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI -+AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw -+H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ -+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk -+2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol -+IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk -+5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY -+n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== -+-----END CERTIFICATE----- -+# CN=Entrust Root Certification Authority,OU=www.entrust.net/CPS is incorporated by reference+OU=(c) 2006 Entrust\, Inc.,O=Entrust\, Inc.,C=US -+# 73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c -+-----BEGIN CERTIFICATE----- -+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -+0vdXcDazv/wor3ElhVsT/h5/WrQ8 -+-----END CERTIFICATE----- -+# CN=Entrust.net Certification Authority (2048),OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)+OU=(c) 1999 Entrust.net Limited,O=Entrust.net -+# 6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177 -+-----BEGIN CERTIFICATE----- -+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 -+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub -+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo -+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b -+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ -+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er -+fF6adulZkMV8gzURZVE= -+-----END CERTIFICATE----- -+# CN=GDCA TrustAUTH R5 ROOT,O=GUANG DONG CERTIFICATE AUTHORITY CO.\,LTD.,C=CN -+# bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893 -+-----BEGIN CERTIFICATE----- -+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE -+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 -+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV -+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w -+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF -+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj -+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj -+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u -+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj -+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm -+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 -+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP -+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk -+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC -+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA -+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC -+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB -+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm -+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 -+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry -+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf -+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg -+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io -+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV -+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ -+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq -+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe -+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== -+-----END CERTIFICATE----- -+# CN=GLOBALTRUST 2020,O=e-commerce monitoring GmbH,C=AT -+# 9a296a5182d1d451a2e37f439b74daafa267523329f90f9a0d2007c334e23c9a -+-----BEGIN CERTIFICATE----- -+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG -+A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw -+FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx -+MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u -+aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq -+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b -+RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z -+YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 -+QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw -+yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ -+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ -+SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH -+r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 -+4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me -+dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw -+q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 -+nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -+AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu -+H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA -+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC -+XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd -+6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf -++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi -+kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 -+wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB -+TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C -+MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn -+4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I -+aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy -+qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== -+-----END CERTIFICATE----- -+# CN=GTS Root R1,O=Google Trust Services LLC,C=US -+# d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf -+-----BEGIN CERTIFICATE----- -+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw -+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA -+A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo -+27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w -+Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw -+TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl -+qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH -+szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 -+Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk -+MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 -+wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p -+aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN -+VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID -+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -+FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb -+C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe -+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy -+h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 -+7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J -+ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef -+MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ -+Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT -+6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ -+0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm -+2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb -+bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c -+-----END CERTIFICATE----- -+# CN=GTS Root R2,O=Google Trust Services LLC,C=US -+# 8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8 -+-----BEGIN CERTIFICATE----- -+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw -+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -+MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA -+A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt -+nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY -+6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu -+MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k -+RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg -+f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV -++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo -+dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW -+Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa -+G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq -+gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID -+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -+FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H -+vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 -+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC -+B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u -+NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg -+yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev -+HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 -+xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR -+TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg -+JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV -+7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl -+6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL -+-----END CERTIFICATE----- -+# CN=GTS Root R3,O=Google Trust Services LLC,C=US -+# 34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48 -+-----BEGIN CERTIFICATE----- -+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD -+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -+A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -+AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G -+jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 -+4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -+BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 -+VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm -+ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X -+-----END CERTIFICATE----- -+# CN=GTS Root R4,O=Google Trust Services LLC,C=US -+# 349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d -+-----BEGIN CERTIFICATE----- -+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD -+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -+A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -+AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi -+QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR -+HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -+BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D -+9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 -+p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD -+-----END CERTIFICATE----- -+# CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE -+# ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99 -+-----BEGIN CERTIFICATE----- -+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -+-----END CERTIFICATE----- -+# CN=GlobalSign Root E46,O=GlobalSign nv-sa,C=BE -+# cbb9c44d84b8043e1050ea31a69f514955d7bfd2e2c6b49301019ad61d9f5058 -+-----BEGIN CERTIFICATE----- -+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx -+CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD -+ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw -+MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex -+HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -+IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq -+R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd -+yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -+DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ -+7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 -++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= -+-----END CERTIFICATE----- -+# CN=GlobalSign Root R46,O=GlobalSign nv-sa,C=BE -+# 4fa3126d8d3a11d1c4855a4f807cbad6cf919d3a5a88b03bea2c6372d93c40c9 -+-----BEGIN CERTIFICATE----- -+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA -+MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD -+VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy -+MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt -+c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -+AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ -+OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG -+vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud -+316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo -+0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE -+y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF -+zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE -++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN -+I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs -+x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa -+ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC -+4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -+HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 -+7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg -+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti -+2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk -+pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF -+FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt -+rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk -+ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 -+u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP -+4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 -+N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 -+vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 -+-----END CERTIFICATE----- -+# CN=GlobalSign,OU=GlobalSign ECC Root CA - R4,O=GlobalSign -+# b085d70b964f191a73e4af0d54ae7a0e07aafdaf9b71dd0862138ab7325a24a2 -+-----BEGIN CERTIFICATE----- -+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD -+VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh -+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw -+MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g -+UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT -+BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx -+uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV -+HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ -++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 -+bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm -+-----END CERTIFICATE----- -+# CN=GlobalSign,OU=GlobalSign ECC Root CA - R5,O=GlobalSign -+# 179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924 -+-----BEGIN CERTIFICATE----- -+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk -+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH -+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc -+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke -+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI -+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg -+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO -+xwy8p2Fp8fc74SrL+SvzZpA3 -+-----END CERTIFICATE----- -+# CN=GlobalSign,OU=GlobalSign Root CA - R3,O=GlobalSign -+# cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b -+-----BEGIN CERTIFICATE----- -+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -+WD9f -+-----END CERTIFICATE----- -+# CN=GlobalSign,OU=GlobalSign Root CA - R6,O=GlobalSign -+# 2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69 -+-----BEGIN CERTIFICATE----- -+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg -+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh -+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx -+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET -+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ -+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI -+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k -+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD -+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw -+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw -+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX -+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 -+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h -+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n -+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY -+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce -+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD -+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu -+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN -+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt -+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 -+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj -+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf -+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz -+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp -+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs -+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v -+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R -+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 -+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= -+-----END CERTIFICATE----- -+# CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\, Inc.,L=Scottsdale,ST=Arizona,C=US -+# 45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda -+-----BEGIN CERTIFICATE----- -+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -+4uJEvlz36hz1 -+-----END CERTIFICATE----- -+# CN=HARICA TLS ECC Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR -+# 3f99cc474acfce4dfed58794665e478d1547739f2e780f1bb4ca9b133097d401 -+-----BEGIN CERTIFICATE----- -+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw -+CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh -+cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v -+dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG -+A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj -+aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg -+Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 -+KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y -+STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw -+AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD -+AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw -+SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN -+nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps -+-----END CERTIFICATE----- -+# CN=HARICA TLS RSA Root CA 2021,O=Hellenic Academic and Research Institutions CA,C=GR -+# d95d0e8eda79525bf9beb11b14d2100d3294985f0c62d9fabd9cd999eccb7b1d -+-----BEGIN CERTIFICATE----- -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 -+63ZTGI0RmLo= -+-----END CERTIFICATE----- -+# CN=Hellenic Academic and Research Institutions ECC RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR -+# 44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833 -+-----BEGIN CERTIFICATE----- -+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN -+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl -+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv -+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ -+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj -+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 -+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 -+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg -+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa -+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC -+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi -+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep -+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof -+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -+-----END CERTIFICATE----- -+# CN=Hellenic Academic and Research Institutions RootCA 2015,O=Hellenic Academic and Research Institutions Cert. Authority,L=Athens,C=GR -+# a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36 -+-----BEGIN CERTIFICATE----- -+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix -+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k -+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT -+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v -+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG -+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh -+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx -+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA -+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 -+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 -+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C -+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV -+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD -+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 -+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq -+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko -+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV -+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd -+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I -+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI -+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot -+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V -+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea -+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh -+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ -+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf -+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 -+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK -+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 -+vm9qp/UsQu0yrbYhnr68 -+-----END CERTIFICATE----- -+# CN=HiPKI Root CA - G1,O=Chunghwa Telecom Co.\, Ltd.,C=TW -+# f015ce3cc239bfef064be9f1d2c417e1a0264a0a94be1f0c8d121864eb6949cc -+-----BEGIN CERTIFICATE----- -+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP -+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -+ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa -+Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 -+YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx -+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw -+qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv -+Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 -+lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz -+Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ -+KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK -+FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj -+HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr -+y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ -+/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM -+a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 -+fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -+HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG -+SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi -+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc -+SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza -+ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc -+XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg -+iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho -+L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF -+Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr -+kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ -+vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU -+YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== -+-----END CERTIFICATE----- -+# CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK -+# 5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6 -+-----BEGIN CERTIFICATE----- -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 -+mpv0 -+-----END CERTIFICATE----- -+# CN=ISRG Root X1,O=Internet Security Research Group,C=US -+# 96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6 -+-----BEGIN CERTIFICATE----- -+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= -+-----END CERTIFICATE----- -+# CN=ISRG Root X2,O=Internet Security Research Group,C=US -+# 69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470 -+-----BEGIN CERTIFICATE----- -+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw -+CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg -+R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 -+MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT -+ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw -+EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW -++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 -+ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T -+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI -+zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW -+tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 -+/q4AaOeMSQ+2b1tbFfLn -+-----END CERTIFICATE----- -+# CN=IdenTrust Commercial Root CA 1,O=IdenTrust,C=US -+# 5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae -+-----BEGIN CERTIFICATE----- -+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK -+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu -+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw -+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw -+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG -+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT -+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU -++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp -+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 -+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi -+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL -+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK -+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK -+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT -+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv -+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N -+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD -+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt -+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 -+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 -++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK -+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT -+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq -+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG -+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ -+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A -+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H -+-----END CERTIFICATE----- -+# CN=IdenTrust Public Sector Root CA 1,O=IdenTrust,C=US -+# 30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f -+-----BEGIN CERTIFICATE----- -+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN -+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu -+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN -+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 -+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi -+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 -+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy -+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS -+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF -+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R -+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw -+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy -+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V -+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ -+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV -+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD -+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN -+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV -+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 -+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G -+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW -+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df -+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 -++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ -+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA -+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv -+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c -+-----END CERTIFICATE----- -+# CN=Izenpe.com,O=IZENPE S.A.,C=ES -+# 2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f -+-----BEGIN CERTIFICATE----- -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 -+-----END CERTIFICATE----- -+# CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU,1.2.840.113549.1.9.1=#0c10696e666f40652d737a69676e6f2e6875 -+# 3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378 -+-----BEGIN CERTIFICATE----- -+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 -+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G -+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y -+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx -+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp -+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP -+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc -+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U -+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 -+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC -+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 -++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM -+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG -+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h -+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk -+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c -+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t -+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW -+-----END CERTIFICATE----- -+# CN=Microsoft ECC Root Certificate Authority 2017,O=Microsoft Corporation,C=US -+# 358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02 -+-----BEGIN CERTIFICATE----- -+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw -+CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD -+VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw -+MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV -+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy -+b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq -+hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR -+ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb -+hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E -+BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 -+FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV -+L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB -+iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= -+-----END CERTIFICATE----- -+# CN=Microsoft RSA Root Certificate Authority 2017,O=Microsoft Corporation,C=US -+# c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0 -+-----BEGIN CERTIFICATE----- -+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl -+MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw -+NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -+IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG -+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N -+aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi -+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ -+Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 -+ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 -+HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm -+gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ -+jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc -+aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG -+YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 -+W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K -+UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH -++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q -+W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ -+BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC -+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC -+LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC -+gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 -+tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh -+SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 -+TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 -+pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR -+xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp -+GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 -+dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN -+AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB -+RA+GsCyRxj3qrg+E -+-----END CERTIFICATE----- -+# CN=NAVER Global Root Certification Authority,O=NAVER BUSINESS PLATFORM Corp.,C=KR -+# 88f438dcf8ffd1fa8f429115ffe5f82ae1e06e0c70c375faad717b34a49e7265 -+-----BEGIN CERTIFICATE----- -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 -+9XXeifdy -+-----END CERTIFICATE----- -+# CN=NetLock Arany (Class Gold) FΕ‘tanΓΊsΓ­tvΓ‘ny,OU=TanΓΊsΓ­tvΓ‘nykiadΓ³k (Certification Services),O=NetLock Kft.,L=Budapest,C=HU -+# 6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98 -+-----BEGIN CERTIFICATE----- -+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG -+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 -+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl -+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR -+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB -+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM -+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm -+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz -+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT -+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz -+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 -+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG -+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 -+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG -+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M -+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh -+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C -++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F -+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 -+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -+-----END CERTIFICATE----- -+# CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH -+# 6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6 -+-----BEGIN CERTIFICATE----- -+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt -+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg -+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i -+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x -+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG -+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh -+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 -+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx -+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX -+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk -+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P -+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r -+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB -+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh -+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 -+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO -+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf -+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -+-----END CERTIFICATE----- -+# CN=OISTE WISeKey Global Root GC CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH -+# 8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d -+-----BEGIN CERTIFICATE----- -+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw -+CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 -+bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg -+Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ -+BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu -+ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS -+b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni -+eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W -+p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E -+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T -+rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV -+57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg -+Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 -+-----END CERTIFICATE----- -+# CN=QuoVadis Root CA 1 G3,O=QuoVadis Limited,C=BM -+# 8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74 -+-----BEGIN CERTIFICATE----- -+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL -+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 -+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG -+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV -+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe -+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 -+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh -+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp -+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o -+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc -+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G -+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt -+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO -+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt -+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD -+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 -+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN -+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 -+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv -+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 -+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k -+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj -+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp -+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt -+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD -+-----END CERTIFICATE----- -+# CN=QuoVadis Root CA 2 G3,O=QuoVadis Limited,C=BM -+# 8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840 -+-----BEGIN CERTIFICATE----- -+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL -+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 -+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG -+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf -+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW -+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym -+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ -+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 -+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j -+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq -+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz -+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh -+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l -+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG -+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD -+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC -+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga -+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n -+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE -++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV -+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd -+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg -+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM -+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 -+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M -+-----END CERTIFICATE----- -+# CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM -+# 85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86 -+-----BEGIN CERTIFICATE----- -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 -+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -+-----END CERTIFICATE----- -+# CN=QuoVadis Root CA 3 G3,O=QuoVadis Limited,C=BM -+# 88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46 -+-----BEGIN CERTIFICATE----- -+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL -+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 -+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG -+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR -+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu -+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR -+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c -+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR -+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k -+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw -+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl -+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp -+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q -+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ -+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD -+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI -+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv -+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg -+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP -+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf -+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl -+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ -+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN -+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ -+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 -+-----END CERTIFICATE----- -+# CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM -+# 18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35 -+-----BEGIN CERTIFICATE----- -+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x -+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv -+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV -+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W -+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM -+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB -+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr -+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd -+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv -+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT -+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe -+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc -+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt -+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ -+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A -+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD -+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG -+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 -+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu -+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw -+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G -+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC -+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg -+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 -+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem -+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd -++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B -+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN -+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x -+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 -+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s -+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j -+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT -+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK -+4SVhM7JZG+Ju1zdXtg2pEto= -+-----END CERTIFICATE----- -+# CN=SSL.com EV Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US -+# 22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8 -+-----BEGIN CERTIFICATE----- -+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC -+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp -+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx -+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv -+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 -+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA -+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku -+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP -+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX -+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ -+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg -+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== -+-----END CERTIFICATE----- -+# CN=SSL.com EV Root Certification Authority RSA R2,O=SSL Corporation,L=Houston,ST=Texas,C=US -+# 2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c -+-----BEGIN CERTIFICATE----- -+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV -+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE -+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy -+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy -+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G -+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD -+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq -+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf -+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa -+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 -+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR -+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA -+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ -+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV -+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO -+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu -+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY -+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 -+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW -+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 -+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg -+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM -+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz -+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt -+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm -+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK -+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ -+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi -+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 -+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== -+-----END CERTIFICATE----- -+# CN=SSL.com Root Certification Authority ECC,O=SSL Corporation,L=Houston,ST=Texas,C=US -+# 3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65 -+-----BEGIN CERTIFICATE----- -+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC -+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 -+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz -+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 -+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS -+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI -+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg -+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud -+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD -+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T -+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ -+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl -+-----END CERTIFICATE----- -+# CN=SSL.com Root Certification Authority RSA,O=SSL Corporation,L=Houston,ST=Texas,C=US -+# 85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69 -+-----BEGIN CERTIFICATE----- -+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE -+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK -+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp -+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz -+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN -+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R -+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX -+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC -+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 -+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh -+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF -+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E -+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc -+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 -+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm -++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi -+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV -+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G -+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV -+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc -+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs -+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ -+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 -+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr -+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I -+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y -+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu -+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf -+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY -+Ic2wBlX7Jz9TkHCpBB5XJ7k= -+-----END CERTIFICATE----- -+# CN=SSL.com TLS ECC Root CA 2022,O=SSL Corporation,C=US -+# c32ffd9f46f936d16c3673990959434b9ad60aafbb9e7cf33654f144cc1ba143 -+-----BEGIN CERTIFICATE----- -+MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw -+CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT -+U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 -+MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh -+dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG -+ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm -+acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN -+SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME -+GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW -+uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp -+15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN -+b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== -+-----END CERTIFICATE----- -+# CN=SSL.com TLS RSA Root CA 2022,O=SSL Corporation,C=US -+# 8faf7d2e2cb4709bb8e0b33666bf75a5dd45b5de480f8ea8d4bfe6bebc17f2ed -+-----BEGIN CERTIFICATE----- -+MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO -+MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD -+DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX -+DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw -+b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC -+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP -+L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY -+t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins -+S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 -+PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO -+L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 -+R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w -+dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS -++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS -+d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG -+AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f -+gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j -+BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z -+NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt -+hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM -+QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf -+R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ -+DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW -+P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy -+lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq -+bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w -+AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q -+r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji -+Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU -+98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= -+-----END CERTIFICATE----- -+# CN=SZAFIR ROOT CA2,O=Krajowa Izba Rozliczeniowa S.A.,C=PL -+# a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe -+-----BEGIN CERTIFICATE----- -+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL -+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 -+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw -+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L -+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg -+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN -+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT -+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw -+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 -+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 -+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN -+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF -+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw -+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG -+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP -+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy -+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg -+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== -+-----END CERTIFICATE----- -+# CN=Sectigo Public Server Authentication Root E46,O=Sectigo Limited,C=GB -+# c90f26f0fb1b4018b22227519b5ca2b53e2ca5b3be5cf18efe1bef47380c5383 -+-----BEGIN CERTIFICATE----- -+MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw -+CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T -+ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN -+MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG -+A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT -+ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -+IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC -+WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ -+6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B -+Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa -+qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q -+4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== -+-----END CERTIFICATE----- -+# CN=Sectigo Public Server Authentication Root R46,O=Sectigo Limited,C=GB -+# 7bb647a62aeeac88bf257aa522d01ffea395e0ab45c73f93f65654ec38f25a06 -+-----BEGIN CERTIFICATE----- -+MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf -+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD -+Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw -+HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY -+MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp -+YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -+AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa -+ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz -+SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf -+iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X -+ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 -+IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS -+VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE -+SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu -++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt -+8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L -+HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt -+zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P -+AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c -+mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ -+YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 -+gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA -+Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB -+JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX -+DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui -+TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 -+dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 -+LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp -+0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY -+QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL -+-----END CERTIFICATE----- -+# CN=Secure Global CA,O=SecureTrust Corporation,C=US -+# 4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69 -+-----BEGIN CERTIFICATE----- -+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK -+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx -+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg -+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG -+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ -+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa -+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ -+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI -+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 -+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w -+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF -+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw -+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG -+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L -+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO -+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm -+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY -+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -+-----END CERTIFICATE----- -+# CN=SecureSign RootCA11,O=Japan Certification Services\, Inc.,C=JP -+# bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612 -+-----BEGIN CERTIFICATE----- -+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr -+MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG -+A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 -+MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp -+Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD -+QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz -+i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 -+h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV -+MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 -+UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni -+8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC -+h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD -+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB -+AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm -+KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ -+X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr -+QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 -+pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN -+QSdJQO7e5iNEOdyhIta6A/I= -+-----END CERTIFICATE----- -+# CN=SecureTrust CA,O=SecureTrust Corporation,C=US -+# f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73 -+-----BEGIN CERTIFICATE----- -+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI -+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x -+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz -+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv -+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN -+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz -+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO -+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao -+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj -+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS -+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT -+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg -+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC -+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 -+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ -+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm -+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS -+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -+-----END CERTIFICATE----- -+# CN=Security Communication ECC RootCA1,O=SECOM Trust Systems CO.\,LTD.,C=JP -+# e74fbda55bd564c473a36b441aa799c8a68e077440e8288b9fa1e50e4bbaca11 -+-----BEGIN CERTIFICATE----- -+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT -+AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD -+VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx -+NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT -+HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 -+IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -+AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl -+dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK -+ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E -+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu -+9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O -+be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= -+-----END CERTIFICATE----- -+# CN=Security Communication RootCA3,O=SECOM Trust Systems CO.\,LTD.,C=JP -+# 24a55c2ab051442d0617766541239a4ad032d7c55175aa34ffde2fbc4f5c5294 -+-----BEGIN CERTIFICATE----- -+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV -+BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw -+JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2 -+MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc -+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg -+Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -+CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r -+CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA -+lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG -+TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7 -+9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7 -+8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4 -+g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we -+GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst -++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M -+0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ -+T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw -+HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP -+BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS -+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA -+FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd -+9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI -+UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+ -+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke -+gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf -+iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV -+nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD -+2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI// -+1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad -+TdJ0MN1kURXbg4NR16/9M51NZg== -+-----END CERTIFICATE----- -+# CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US -+# 2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5 -+-----BEGIN CERTIFICATE----- -+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -+-----END CERTIFICATE----- -+# CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US -+# 568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5 -+-----BEGIN CERTIFICATE----- -+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -+sSi6 -+-----END CERTIFICATE----- -+# CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH -+# 62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95 -+-----BEGIN CERTIFICATE----- -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 -+-----END CERTIFICATE----- -+# CN=SwissSign Silver CA - G2,O=SwissSign AG,C=CH -+# be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5 -+-----BEGIN CERTIFICATE----- -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 -+-----END CERTIFICATE----- -+# CN=T-TeleSec GlobalRoot Class 2,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE -+# 91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552 -+-----BEGIN CERTIFICATE----- -+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 -+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G -+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd -+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC -+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi -+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq -+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ -+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj -+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ -+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy -+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC -+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw -+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 -+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP -+BSeOE6Fuwg== -+-----END CERTIFICATE----- -+# CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE -+# fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd -+-----BEGIN CERTIFICATE----- -+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 -+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G -+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN -+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ -+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 -+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 -+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM -+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj -+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 -+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy -+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ -+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 -+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT -+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p -+TpPDpFQUWw== -+-----END CERTIFICATE----- -+# CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1,OU=Kamu Sertifikasyon Merkezi - Kamu SM,O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK,L=Gebze - Kocaeli,C=TR -+# 46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716 -+-----BEGIN CERTIFICATE----- -+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx -+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp -+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w -+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 -+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy -+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG -+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll -+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU -+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT -+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg -+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 -+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr -+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr -+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X -+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ -+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f -+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH -+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf -+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 -+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c -+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf -+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= -+-----END CERTIFICATE----- -+# CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW -+# 59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b -+-----BEGIN CERTIFICATE----- -+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx -+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT -+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 -+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT -+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG -+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF -+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz -+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh -+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH -+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc -+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 -+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi -+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP -+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA -+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE -+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm -+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL -+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF -+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo -+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ -+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh -+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW -+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW -+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j -+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz -+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy -+KwbQBM0= -+-----END CERTIFICATE----- -+# CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW -+# bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44 -+-----BEGIN CERTIFICATE----- -+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES -+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU -+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz -+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO -+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm -+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE -+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH -+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX -+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z -+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx -+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq -+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC -+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls -+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D -+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn -+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ -+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -+-----END CERTIFICATE----- -+# CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI -+# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c -+-----BEGIN CERTIFICATE----- -+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx -+CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE -+AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 -+NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ -+MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -+ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq -+AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 -+vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 -+lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD -+n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT -+7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o -+6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC -+TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 -+WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R -+DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI -+pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj -+YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy -+rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw -+AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ -+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi -+0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM -+A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS -+SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K -+TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF -+6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er -+3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt -+Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT -+VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW -+ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA -+rBPuUBQemMc= -+-----END CERTIFICATE----- -+# CN=TeliaSonera Root CA v1,O=TeliaSonera -+# dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389 -+-----BEGIN CERTIFICATE----- -+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw -+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv -+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD -+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 -+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F -+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 -+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X -+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ -+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs -+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm -+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe -+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu -+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 -+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs -+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ -+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD -+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG -+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl -+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj -+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed -+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 -+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI -+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 -+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW -+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn -+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx -+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -+-----END CERTIFICATE----- -+# CN=Trustwave Global Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US -+# 97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8 -+-----BEGIN CERTIFICATE----- -+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw -+CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x -+ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 -+c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx -+OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI -+SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI -+b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp -+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -+ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn -+swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu -+7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 -+1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW -+80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP -+JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l -+RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw -+hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 -+coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc -+BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n -+twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud -+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud -+DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W -+0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe -+uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q -+lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB -+aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE -+sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT -+MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe -+qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh -+VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 -+h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 -+EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK -+yeC2nOnOcXHebD8WpHk= -+-----END CERTIFICATE----- -+# CN=Trustwave Global ECC P256 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US -+# 945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4 -+-----BEGIN CERTIFICATE----- -+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD -+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf -+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 -+YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x -+NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G -+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 -+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF -+Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG -+SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN -+FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w -+DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw -+CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh -+DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 -+-----END CERTIFICATE----- -+# CN=Trustwave Global ECC P384 Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US -+# 55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097 -+-----BEGIN CERTIFICATE----- -+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD -+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf -+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 -+YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x -+NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G -+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 -+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF -+Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB -+BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ -+j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF -+1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G -+A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 -+AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC -+MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu -+Sw== -+-----END CERTIFICATE----- -+# CN=TunTrust Root CA,O=Agence Nationale de Certification Electronique,C=TN -+# 2e44102ab58cb85419451c8e19d9acf3662cafbc614b6a53960a30f7d0e2eb41 -+-----BEGIN CERTIFICATE----- -+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL -+BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg -+Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv -+b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG -+EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u -+IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ -+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ -+n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd -+2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF -+VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ -+GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF -+li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU -+r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 -+eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb -+MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg -+jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB -+7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW -+5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE -+ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 -+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z -+xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu -+QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 -+FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH -+22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP -+xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn -+dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 -+Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b -+nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ -+CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH -+u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj -+d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= -+-----END CERTIFICATE----- -+# CN=UCA Extended Validation Root,O=UniTrust,C=CN -+# d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24 -+-----BEGIN CERTIFICATE----- -+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH -+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF -+eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx -+MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV -+BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB -+AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog -+D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS -+sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop -+O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk -+sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi -+c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj -+VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz -+KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ -+TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G -+sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs -+1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD -+fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T -+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN -+l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR -+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ -+VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 -+c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp -+4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s -+t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj -+2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO -+vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C -+xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx -+cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM -+fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax -+-----END CERTIFICATE----- -+# CN=UCA Global G2 Root,O=UniTrust,C=CN -+# 9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c -+-----BEGIN CERTIFICATE----- -+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 -+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH -+bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x -+CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds -+b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr -+b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 -+kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm -+VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R -+VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc -+C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj -+tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY -+D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv -+j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl -+NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 -+iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP -+O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ -+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV -+ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj -+L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 -+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl -+1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU -+b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV -+PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj -+y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb -+EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg -+DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI -++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy -+YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX -+UB+K+wb1whnw0A== -+-----END CERTIFICATE----- -+# CN=USERTrust ECC Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US -+# 4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a -+-----BEGIN CERTIFICATE----- -+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL -+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl -+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT -+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx -+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg -+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm -+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo -+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng -+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G -+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD -+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB -+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW -+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -+-----END CERTIFICATE----- -+# CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US -+# e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2 -+-----BEGIN CERTIFICATE----- -+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB -+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl -+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV -+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw -+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV -+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy -+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B -+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY -+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ -+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 -+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT -+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 -+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT -+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l -+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee -+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE -+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd -+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G -+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF -+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO -+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 -+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs -+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR -+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze -+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ -+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ -+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB -+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB -+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG -+jjxDah2nGN59PRbxYvnKkKj9 -+-----END CERTIFICATE----- -+# CN=XRamp Global Certification Authority,OU=www.xrampsecurity.com,O=XRamp Security Services Inc,C=US -+# cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2 -+-----BEGIN CERTIFICATE----- -+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -+O+7ETPTsJ3xCwnR8gooJybQDJbw= -+-----END CERTIFICATE----- -+# CN=e-Szigno Root CA 2017,O=Microsec Ltd.,L=Budapest,C=HU,2.5.4.97=#130e56415448552d3233353834343937 -+# beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99 -+-----BEGIN CERTIFICATE----- -+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV -+BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk -+LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv -+b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ -+BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg -+THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v -+IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv -+xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H -+Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -+A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB -+eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo -+jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ -++efcMQ== -+-----END CERTIFICATE----- -+# CN=emSign ECC Root CA - C3,OU=emSign PKI,O=eMudhra Inc,C=US -+# bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3 -+-----BEGIN CERTIFICATE----- -+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG -+EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx -+IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw -+MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND -+IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci -+MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti -+sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O -+BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB -+Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c -+3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J -+0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== -+-----END CERTIFICATE----- -+# CN=emSign ECC Root CA - G3,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN -+# 86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b -+-----BEGIN CERTIFICATE----- -+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG -+EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo -+bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g -+RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ -+TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s -+b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw -+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 -+WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS -+fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB -+zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq -+hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB -+CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD -++JbNR6iC8hZVdyR+EhCVBCyj -+-----END CERTIFICATE----- -+# CN=emSign Root CA - C1,OU=emSign PKI,O=eMudhra Inc,C=US -+# 125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f -+-----BEGIN CERTIFICATE----- -+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG -+A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg -+SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw -+MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v -+dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ -+BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ -+HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH -+3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH -+GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c -+xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 -+aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq -+TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -+BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 -+/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 -+kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG -+YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT -++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo -+WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= -+-----END CERTIFICATE----- -+# CN=emSign Root CA - G1,OU=emSign PKI,O=eMudhra Technologies Limited,C=IN -+# 40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367 -+-----BEGIN CERTIFICATE----- -+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD -+VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU -+ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH -+MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO -+MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv -+Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN -+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz -+f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO -+8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq -+d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM -+tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt -+Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB -+o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD -+AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x -+PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM -+wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d -+GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH -+6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby -+RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx -+iN66zB+Afko= -+-----END CERTIFICATE----- -+# CN=vTrus ECC Root CA,O=iTrusChina Co.\,Ltd.,C=CN -+# 30fbba2c32238e2a98547af97931e550428b9b3f1c8eeb6633dcfa86c5b27dd3 -+-----BEGIN CERTIFICATE----- -+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw -+RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY -+BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz -+MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u -+LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF -+K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 -+v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd -+e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD -+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw -+V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA -+AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG -+GJTO -+-----END CERTIFICATE----- -+# CN=vTrus Root CA,O=iTrusChina Co.\,Ltd.,C=CN -+# 8a71de6559336f426c26e53880d00d88a18da4c6a91f0dcb6194e206c5c96387 -+-----BEGIN CERTIFICATE----- -+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL -+BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x -+FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx -+MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s -+THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD -+ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc -+IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU -+AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ -+GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 -+8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH -+flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt -+J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim -+0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN -+pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ -+UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW -+OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB -+AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E -+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet -+8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd -+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j -+bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM -+Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv -+TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS -+S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr -+I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 -+b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB -+UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P -+Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven -+sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= -+-----END CERTIFICATE----- -+# OU=AC RAIZ FNMT-RCM,O=FNMT-RCM,C=ES -+# ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa -+-----BEGIN CERTIFICATE----- -+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx -+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ -+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ -+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG -+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ -+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf -+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz -+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF -+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z -+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC -+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL -+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 -+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS -+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 -+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet -+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw -+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H -+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 -+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 -+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM -+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf -+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N -+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm -+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp -+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp -+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B -+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok -+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv -+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= -+-----END CERTIFICATE----- -+# OU=Go Daddy Class 2 Certification Authority,O=The Go Daddy Group\, Inc.,C=US -+# c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4 -+-----BEGIN CERTIFICATE----- -+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -+ReYNnyicsbkqWletNw+vHX/bvZ8= -+-----END CERTIFICATE----- -+# OU=Security Communication RootCA1,O=SECOM Trust.net,C=JP -+# e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c -+-----BEGIN CERTIFICATE----- -+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY -+MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t -+dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 -+WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD -+VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 -+DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 -+9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ -+DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 -+Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N -+QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ -+xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G -+A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T -+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG -+kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr -+Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 -+Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU -+JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot -+RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== -+-----END CERTIFICATE----- -+# OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\,LTD.,C=JP -+# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6 -+-----BEGIN CERTIFICATE----- -+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl -+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe -+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX -+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy -+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj -+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV -+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr -+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM -+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ -+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO -+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw -+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs -+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF -+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc -+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 -+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy -+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ -+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -+-----END CERTIFICATE----- -+# OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\, Inc.,C=US -+# 1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658 -+-----BEGIN CERTIFICATE----- -+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= -+-----END CERTIFICATE----- -+# OU=certSIGN ROOT CA G2,O=CERTSIGN SA,C=RO -+# 657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305 -+-----BEGIN CERTIFICATE----- -+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV -+BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g -+Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ -+BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ -+R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF -+dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw -+vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ -+uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp -+n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs -+cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW -+xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P -+rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF -+DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx -+DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy -+LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C -+eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB -+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ -+d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq -+kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC -+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl -+qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 -+OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c -+NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk -+ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO -+pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj -+03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk -+PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE -+1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX -+QRBdJ3NghVdJIgc= -+-----END CERTIFICATE----- -+# OU=certSIGN ROOT CA,O=certSIGN,C=RO -+# eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb -+-----BEGIN CERTIFICATE----- -+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT -+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD -+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP -+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC -+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do -+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ -+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d -+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ -+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv -+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C -+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O -+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ -+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY -+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ -+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I -+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw -+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN -+9u6wWk5JRFRYX0KD -+-----END CERTIFICATE----- -+# OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\, Ltd.,C=TW -+# c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5 -+-----BEGIN CERTIFICATE----- -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 -+hNQ+IIX3Sj0rnP0qCglN6oH4EZw= -+-----END CERTIFICATE----- -+# SERIALNUMBER=G63287510,CN=ANF Secure Server Root CA,OU=ANF CA Raiz,O=ANF Autoridad de Certificacion,C=ES -+# fb8fec759169b9106b1e511644c618c51304373f6c0643088d8beffd1b997599 -+-----BEGIN CERTIFICATE----- -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 -+-----END CERTIFICATE----- -+` -diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go b/ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go -new file mode 100644 -index 00000000000000..31413595fa8826 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/fallback.go -@@ -0,0 +1,31 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build go1.20 -+ -+// Package fallback embeds a set of fallback X.509 trusted roots in the -+// application by automatically invoking [x509.SetFallbackRoots]. This allows -+// the application to work correctly even if the operating system does not -+// provide a verifier or system roots pool. -+// -+// To use it, import the package like -+// -+// import _ "golang.org/x/crypto/x509roots/fallback" -+// -+// It's recommended that only binaries, and not libraries, import this package. -+// -+// This package must be kept up to date for security and compatibility reasons. -+// Use govulncheck to be notified of when new versions of the package are -+// available. -+package fallback -+ -+import "crypto/x509" -+ -+func init() { -+ p := x509.NewCertPool() -+ for _, c := range bundle { -+ p.AddCert(c) -+ } -+ x509.SetFallbackRoots(p) -+} -diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod b/ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod -new file mode 100644 -index 00000000000000..d8974bf9fe0a79 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/go.mod -@@ -0,0 +1,3 @@ -+module golang.org/x/crypto/x509roots/fallback -+ -+go 1.20 -diff --git a/ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go b/ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go -new file mode 100644 -index 00000000000000..d946a527db79a4 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/fallback/internal/goissue52287/goissue52287.go -@@ -0,0 +1,8 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package goissue52287 is an empty internal package. -+// It exists only to work around go.dev/issue/52287 and -+// can be removed after Go 1.19 stops being supported. -+package goissue52287 -diff --git a/ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go b/ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go -new file mode 100644 -index 00000000000000..c22d1b0c381b64 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/gen_fallback_bundle.go -@@ -0,0 +1,135 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build generate -+// +build generate -+ -+//go:generate go run gen_fallback_bundle.go -+ -+package main -+ -+import ( -+ "bytes" -+ "crypto/sha256" -+ "encoding/pem" -+ "flag" -+ "fmt" -+ "go/format" -+ "io" -+ "log" -+ "net/http" -+ "os" -+ "sort" -+ -+ "golang.org/x/crypto/x509roots/nss" -+) -+ -+const tmpl = `// Code generated by gen_fallback_bundle.go; DO NOT EDIT. -+ -+//go:build go1.20 -+ -+package fallback -+ -+import "crypto/x509" -+import "encoding/pem" -+ -+func mustParse(b []byte) []*x509.Certificate { -+ var roots []*x509.Certificate -+ for len(b) > 0 { -+ var block *pem.Block -+ block, b = pem.Decode(b) -+ if block == nil { -+ break -+ } -+ if block.Type != "CERTIFICATE" { -+ panic("unexpected PEM block type: " + block.Type) -+ } -+ cert, err := x509.ParseCertificate(block.Bytes) -+ if err != nil { -+ panic(err) -+ } -+ roots = append(roots, cert) -+ } -+ return roots -+} -+ -+var bundle = mustParse([]byte(pemRoots)) -+ -+// Format of the PEM list is: -+// * Subject common name -+// * SHA256 hash -+// * PEM block -+ -+` -+ -+var ( -+ certDataURL = flag.String("certdata-url", "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt", "URL to the raw certdata.txt file to parse (certdata-path overrides this, if provided)") -+ certDataPath = flag.String("certdata-path", "", "Path to the NSS certdata.txt file to parse (this overrides certdata-url, if provided)") -+ output = flag.String("output", "fallback/bundle.go", "Path to file to write output to") -+) -+ -+func main() { -+ flag.Parse() -+ -+ var certdata io.Reader -+ -+ if *certDataPath != "" { -+ f, err := os.Open(*certDataPath) -+ if err != nil { -+ log.Fatalf("unable to open %q: %s", *certDataPath, err) -+ } -+ defer f.Close() -+ certdata = f -+ } else { -+ resp, err := http.Get(*certDataURL) -+ if err != nil { -+ log.Fatalf("failed to request %q: %s", *certDataURL, err) -+ } -+ defer resp.Body.Close() -+ certdata = resp.Body -+ } -+ -+ certs, err := nss.Parse(certdata) -+ if err != nil { -+ log.Fatalf("failed to parse %q: %s", *certDataPath, err) -+ } -+ -+ sort.Slice(certs, func(i, j int) bool { -+ // Sort based on the stringified subject (which may not be unique), and -+ // break any ties by just sorting on the raw DER (which will be unique, -+ // but is expensive). This should produce a stable sorting, which should -+ // be mostly readable by a human looking for a specific root or set of -+ // roots. -+ subjI, subjJ := certs[i].X509.Subject.String(), certs[j].X509.Subject.String() -+ if subjI == subjJ { -+ return string(certs[i].X509.Raw) < string(certs[j].X509.Raw) -+ } -+ return subjI < subjJ -+ }) -+ -+ b := new(bytes.Buffer) -+ b.WriteString(tmpl) -+ fmt.Fprintln(b, "const pemRoots = `") -+ for _, c := range certs { -+ if len(c.Constraints) > 0 { -+ // Until the constrained roots API lands, skip anything that has any -+ // additional constraints. Once that API is available, we can add -+ // build constraints that support both the current version and the -+ // new version. -+ continue -+ } -+ fmt.Fprintf(b, "# %s\n# %x\n", c.X509.Subject.String(), sha256.Sum256(c.X509.Raw)) -+ pem.Encode(b, &pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw}) -+ } -+ fmt.Fprintln(b, "`") -+ -+ formatted, err := format.Source(b.Bytes()) -+ if err != nil { -+ log.Fatalf("failed to format source: %s", err) -+ } -+ -+ if err := os.WriteFile(*output, formatted, 0644); err != nil { -+ log.Fatalf("failed to write to %q: %s", *output, err) -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/x509roots/nss/parser.go b/ms_mod/golang.org/x/crypto/x509roots/nss/parser.go -new file mode 100644 -index 00000000000000..1af3e0ae46fe1c ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/nss/parser.go -@@ -0,0 +1,259 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package nss provides functionality for parsing NSS certdata.txt -+// formatted certificate lists and extracting serverAuth roots. Most -+// users should not use this package themselves, and should instead -+// rely on the golang.org/x/crypto/x509roots/fallback package which -+// calls x509.SetFallbackRoots on a pre-parsed set of roots. -+package nss -+ -+import ( -+ "bufio" -+ "bytes" -+ "crypto/sha1" -+ "crypto/x509" -+ "errors" -+ "fmt" -+ "io" -+ "strconv" -+ "strings" -+ "time" -+) -+ -+// Constraint is a constraint to be applied to a certificate or -+// certificate chain. -+type Constraint interface { -+ Kind() Kind -+} -+ -+// Kind is the constraint kind, using the NSS enumeration. -+type Kind int -+ -+const ( -+ CKA_NSS_SERVER_DISTRUST_AFTER Kind = iota -+) -+ -+// DistrustAfter is a Constraint that indicates a certificate has a -+// CKA_NSS_SERVER_DISTRUST_AFTER constraint. This constraint defines a date -+// after which any certificate issued which is rooted by the constrained -+// certificate should be distrusted. -+type DistrustAfter time.Time -+ -+func (DistrustAfter) Kind() Kind { -+ return CKA_NSS_SERVER_DISTRUST_AFTER -+} -+ -+// A Certificate represents a single trusted serverAuth certificate in the NSS -+// certdata.txt list and any constraints that should be applied to chains -+// rooted by it. -+type Certificate struct { -+ // Certificate is the parsed certificate -+ X509 *x509.Certificate -+ // Constraints contains a list of additional constraints that should be -+ // applied to any certificates that chain to Certificate. If there are -+ // any unknown constraints in the slice, Certificate should not be -+ // trusted. -+ Constraints []Constraint -+} -+ -+func parseMulitLineOctal(s *bufio.Scanner) ([]byte, error) { -+ buf := bytes.NewBuffer(nil) -+ for s.Scan() { -+ if s.Text() == "END" { -+ break -+ } -+ b, err := strconv.Unquote(fmt.Sprintf("\"%s\"", s.Text())) -+ if err != nil { -+ return nil, err -+ } -+ buf.Write([]byte(b)) -+ } -+ return buf.Bytes(), nil -+} -+ -+type certObj struct { -+ c *x509.Certificate -+ DistrustAfter *time.Time -+} -+ -+func parseCertClass(s *bufio.Scanner) ([sha1.Size]byte, *certObj, error) { -+ var h [sha1.Size]byte -+ co := &certObj{} -+ for s.Scan() { -+ l := s.Text() -+ if l == "" { -+ // assume an empty newline indicates the end of a block -+ break -+ } -+ if strings.HasPrefix(l, "CKA_VALUE") { -+ b, err := parseMulitLineOctal(s) -+ if err != nil { -+ return h, nil, err -+ } -+ co.c, err = x509.ParseCertificate(b) -+ if err != nil { -+ return h, nil, err -+ } -+ h = sha1.Sum(b) -+ } else if strings.HasPrefix(l, "CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE") { -+ // we don't want it -+ return h, nil, nil -+ } else if l == "CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL" { -+ dateStr, err := parseMulitLineOctal(s) -+ if err != nil { -+ return h, nil, err -+ } -+ t, err := time.Parse("060102150405Z0700", string(dateStr)) -+ if err != nil { -+ return h, nil, err -+ } -+ co.DistrustAfter = &t -+ } -+ } -+ if co.c == nil { -+ return h, nil, errors.New("malformed CKO_CERTIFICATE object") -+ } -+ return h, co, nil -+} -+ -+type trustObj struct { -+ trusted bool -+} -+ -+func parseTrustClass(s *bufio.Scanner) ([sha1.Size]byte, *trustObj, error) { -+ var h [sha1.Size]byte -+ to := &trustObj{trusted: false} // default to untrusted -+ -+ for s.Scan() { -+ l := s.Text() -+ if l == "" { -+ // assume an empty newline indicates the end of a block -+ break -+ } -+ if l == "CKA_CERT_SHA1_HASH MULTILINE_OCTAL" { -+ hash, err := parseMulitLineOctal(s) -+ if err != nil { -+ return h, nil, err -+ } -+ copy(h[:], hash) -+ } else if l == "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR" { -+ // we only care about server auth -+ to.trusted = true -+ } -+ } -+ -+ return h, to, nil -+} -+ -+// Parse parses a NSS certdata.txt formatted file, returning only -+// trusted serverAuth roots, as well as any additional constraints. This parser -+// is very opinionated, only returning roots that are currently trusted for -+// serverAuth. As such roots returned by this package should only be used for -+// making trust decisions about serverAuth certificates, as the trust status for -+// other uses is not considered. Using the roots returned by this package for -+// trust decisions should be done carefully. -+// -+// Some roots returned by the parser may include additional constraints -+// (currently only DistrustAfter) which need to be considered when verifying -+// certificates which chain to them. -+// -+// Parse is not intended to be a general purpose parser for certdata.txt. -+func Parse(r io.Reader) ([]*Certificate, error) { -+ // certdata.txt is a rather strange format. It is essentially a list of -+ // textual PKCS#11 objects, delimited by empty lines. There are two main -+ // types of objects, certificates (CKO_CERTIFICATE) and trust definitions -+ // (CKO_NSS_TRUST). These objects appear to alternate, but this ordering is -+ // not defined anywhere, and should probably not be relied on. A single root -+ // certificate requires both the certificate object and the trust definition -+ // object in order to be properly understood. -+ // -+ // The list contains not just serverAuth certificates, so we need to be -+ // careful to only extract certificates which have the serverAuth trust bit -+ // set. Similarly there are a number of trust related bool fields that -+ // appear to _always_ be CKA_TRUE, but it seems unsafe to assume this is the -+ // case, so we should always double check. -+ // -+ // Since we only really care about a couple of fields, this parser throws -+ // away a lot of information, essentially just consuming CKA_CLASS objects -+ // and looking for the individual fields we care about. We could write a -+ // siginificantly more complex parser, which handles the entire format, but -+ // it feels like that would be over engineered for the little information -+ // that we really care about. -+ -+ scanner := bufio.NewScanner(r) -+ -+ type nssEntry struct { -+ cert *certObj -+ trust *trustObj -+ } -+ entries := map[[sha1.Size]byte]*nssEntry{} -+ -+ for scanner.Scan() { -+ // scan until we hit CKA_CLASS -+ if !strings.HasPrefix(scanner.Text(), "CKA_CLASS") { -+ continue -+ } -+ -+ f := strings.Fields(scanner.Text()) -+ if len(f) != 3 { -+ return nil, errors.New("malformed CKA_CLASS") -+ } -+ switch f[2] { -+ case "CKO_CERTIFICATE": -+ h, co, err := parseCertClass(scanner) -+ if err != nil { -+ return nil, err -+ } -+ if co != nil { -+ e, ok := entries[h] -+ if !ok { -+ e = &nssEntry{} -+ entries[h] = e -+ } -+ e.cert = co -+ } -+ -+ case "CKO_NSS_TRUST": -+ h, to, err := parseTrustClass(scanner) -+ if err != nil { -+ return nil, err -+ } -+ if to != nil { -+ e, ok := entries[h] -+ if !ok { -+ e = &nssEntry{} -+ entries[h] = e -+ } -+ e.trust = to -+ } -+ } -+ } -+ if err := scanner.Err(); err != nil { -+ return nil, err -+ } -+ -+ var certs []*Certificate -+ for h, e := range entries { -+ if e.cert == nil && e.trust != nil { -+ // We may skip some certificates which are distrusted due to mozilla -+ // policy (CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE), which means -+ // we might get entries that appear to have a trust object, but no -+ // certificate. We can just continue on here. -+ continue -+ } else if e.cert != nil && e.trust == nil { -+ return nil, fmt.Errorf("missing trust object for certificate with SHA1 hash: %x", h) -+ } -+ if !e.trust.trusted { -+ continue -+ } -+ nssCert := &Certificate{X509: e.cert.c} -+ if e.cert.DistrustAfter != nil { -+ nssCert.Constraints = append(nssCert.Constraints, DistrustAfter(*e.cert.DistrustAfter)) -+ } -+ certs = append(certs, nssCert) -+ } -+ -+ return certs, nil -+} -diff --git a/ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go b/ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go -new file mode 100644 -index 00000000000000..581b02cf06c583 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/x509roots/nss/parser_test.go -@@ -0,0 +1,1216 @@ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package nss -+ -+import ( -+ "crypto/x509" -+ "encoding/pem" -+ "reflect" -+ "sort" -+ "strings" -+ "testing" -+ "time" -+) -+ -+func mustParse(b []byte) *x509.Certificate { -+ block, _ := pem.Decode(b) -+ cert, err := x509.ParseCertificate(block.Bytes) -+ if err != nil { -+ panic(err) -+ } -+ return cert -+} -+ -+var testComodo = mustParse([]byte(`-----BEGIN CERTIFICATE----- -+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -+-----END CERTIFICATE-----`)) -+ -+var testTrustcor = mustParse([]byte(`-----BEGIN CERTIFICATE----- -+MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV -+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig -+Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk -+MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg -+Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD -+VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy -+dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -+AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ -+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq -+1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp -+2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK -+DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape -+az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF -+3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 -+oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM -+g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 -+mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -+8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd -+BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U -+nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw -+DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX -+dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ -+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL -+/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX -+CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa -+ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW -+2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 -+N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 -+Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB -+As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp -+5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu -+1uwJ -+-----END CERTIFICATE-----`)) -+ -+func TestParseCertData(t *testing.T) { -+ trustcorDistrust, err := time.Parse("060102150405Z0700", "221130000000Z") -+ if err != nil { -+ t.Fatalf("failed to parse distrust time: %s", err) -+ } -+ -+ for _, tc := range []struct { -+ name string -+ data string -+ output []*Certificate -+ err string -+ }{ -+ { -+ name: "valid certs", -+ data: validCertdata, -+ output: []*Certificate{ -+ &Certificate{X509: testComodo}, -+ &Certificate{X509: testTrustcor, Constraints: []Constraint{DistrustAfter(trustcorDistrust)}}, -+ }, -+ }, -+ { -+ name: "cert obj, no trust obj", -+ data: certNoTrust, -+ err: "missing trust object for certificate with SHA1 hash: d1eb23a46d17d68fd92564c2f1f1601764d8e349", -+ }, -+ { -+ name: "trust obj, no cert obj", -+ data: trustNoCert, -+ }, -+ { -+ name: "missing certificate der", -+ data: missingCertificateOctal, -+ err: "malformed CKO_CERTIFICATE object", -+ }, -+ { -+ name: "untrusted cert (cert)", -+ data: untrustedCertCert, -+ }, -+ { -+ name: "untrusted cert (trust)", -+ data: untrustedCertTrust, -+ }, -+ { -+ name: "malformed class", -+ data: malformedClass, -+ err: "malformed CKA_CLASS", -+ }, -+ { -+ name: "malformed cert octal", -+ data: malformedOctalCert, -+ err: "invalid syntax", -+ }, -+ { -+ name: "malformed hash octal", -+ data: malformedOctalhash, -+ err: "invalid syntax", -+ }, -+ { -+ name: "malformed distrust octal", -+ data: malformedOctalDistrust, -+ err: "invalid syntax", -+ }, -+ } { -+ t.Run(tc.name, func(t *testing.T) { -+ r := strings.NewReader(tc.data) -+ nc, err := Parse(r) -+ if err != nil { -+ if tc.err == "" { -+ t.Fatalf("unexpected error: %s", err) -+ } else if tc.err != err.Error() { -+ t.Fatalf("unexpected error: want %q, got %q", tc.err, err) -+ } -+ } else if tc.err != "" { -+ t.Fatal("expected error, got nil") -+ } -+ -+ if len(tc.output) != len(nc) { -+ t.Fatalf("unexpected number of parsed certs: want %d, got %d", len(tc.output), len(nc)) -+ } -+ -+ // sort so we can check equality -+ sort.Slice(nc, func(i, j int) bool { -+ return nc[i].X509.Subject.String() < nc[j].X509.Subject.String() -+ }) -+ -+ if !reflect.DeepEqual(tc.output, nc) { -+ t.Fatal("unexpected results") -+ } -+ }) -+ } -+} -+ -+const validCertdata = `# -+# Certificate "Comodo AAA Services root" -+# -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_VALUE MULTILINE_OCTAL -+\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 -+\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 -+\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 -+\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 -+\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 -+\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 -+\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 -+\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 -+\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 -+\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 -+\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 -+\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 -+\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 -+\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 -+\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 -+\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 -+\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 -+\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 -+\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 -+\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 -+\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 -+\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 -+\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 -+\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 -+\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 -+\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 -+\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 -+\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 -+\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 -+\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 -+\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 -+\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 -+\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 -+\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 -+\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 -+\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 -+\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 -+\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 -+\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 -+\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 -+\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 -+\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 -+\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 -+\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 -+\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 -+\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 -+\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 -+\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 -+\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 -+\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 -+\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 -+\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 -+\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 -+\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 -+\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 -+\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 -+\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 -+\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 -+\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 -+\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 -+\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 -+\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 -+\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 -+\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 -+\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 -+\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 -+\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 -+\225\351\066\226\230\156 -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -+CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -+CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE -+ -+# Trust for "Comodo AAA Services root" -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERT_SHA1_HASH MULTILINE_OCTAL -+\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 -+\144\330\343\111 -+END -+CKA_CERT_MD5_HASH MULTILINE_OCTAL -+\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 -+END -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -+ -+# -+# Certificate "TrustCor RootCert CA-2" -+# -+# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA -+# Serial Number:25:a1:df:ca:33:cb:59:02 -+# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA -+# Not Valid Before: Thu Feb 04 12:32:23 2016 -+# Not Valid After : Sun Dec 31 17:26:39 2034 -+# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 -+# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 -+CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "TrustCor RootCert CA-2" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 -+\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 -+\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 -+\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 -+\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 -+\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 -+\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 -+\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 -+\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 -+\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 -+\162\164\040\103\101\055\062 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 -+\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 -+\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 -+\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 -+\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 -+\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 -+\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 -+\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 -+\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 -+\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 -+\162\164\040\103\101\055\062 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\010\045\241\337\312\063\313\131\002 -+END -+CKA_VALUE MULTILINE_OCTAL -+\060\202\006\057\060\202\004\027\240\003\002\001\002\002\010\045 -+\241\337\312\063\313\131\002\060\015\006\011\052\206\110\206\367 -+\015\001\001\013\005\000\060\201\244\061\013\060\011\006\003\125 -+\004\006\023\002\120\101\061\017\060\015\006\003\125\004\010\014 -+\006\120\141\156\141\155\141\061\024\060\022\006\003\125\004\007 -+\014\013\120\141\156\141\155\141\040\103\151\164\171\061\044\060 -+\042\006\003\125\004\012\014\033\124\162\165\163\164\103\157\162 -+\040\123\171\163\164\145\155\163\040\123\056\040\144\145\040\122 -+\056\114\056\061\047\060\045\006\003\125\004\013\014\036\124\162 -+\165\163\164\103\157\162\040\103\145\162\164\151\146\151\143\141 -+\164\145\040\101\165\164\150\157\162\151\164\171\061\037\060\035 -+\006\003\125\004\003\014\026\124\162\165\163\164\103\157\162\040 -+\122\157\157\164\103\145\162\164\040\103\101\055\062\060\036\027 -+\015\061\066\060\062\060\064\061\062\063\062\062\063\132\027\015 -+\063\064\061\062\063\061\061\067\062\066\063\071\132\060\201\244 -+\061\013\060\011\006\003\125\004\006\023\002\120\101\061\017\060 -+\015\006\003\125\004\010\014\006\120\141\156\141\155\141\061\024 -+\060\022\006\003\125\004\007\014\013\120\141\156\141\155\141\040 -+\103\151\164\171\061\044\060\042\006\003\125\004\012\014\033\124 -+\162\165\163\164\103\157\162\040\123\171\163\164\145\155\163\040 -+\123\056\040\144\145\040\122\056\114\056\061\047\060\045\006\003 -+\125\004\013\014\036\124\162\165\163\164\103\157\162\040\103\145 -+\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157\162 -+\151\164\171\061\037\060\035\006\003\125\004\003\014\026\124\162 -+\165\163\164\103\157\162\040\122\157\157\164\103\145\162\164\040 -+\103\101\055\062\060\202\002\042\060\015\006\011\052\206\110\206 -+\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 -+\002\202\002\001\000\247\040\156\302\052\242\142\044\225\220\166 -+\310\070\176\200\322\253\301\233\145\005\224\364\301\012\020\325 -+\002\254\355\237\223\307\207\310\260\047\053\102\014\075\012\076 -+\101\132\236\165\335\215\312\340\233\354\150\062\244\151\222\150 -+\214\013\201\016\126\240\076\032\335\054\045\024\202\057\227\323 -+\144\106\364\124\251\334\072\124\055\061\053\231\202\362\331\052 -+\327\357\161\000\270\061\244\276\172\044\007\303\102\040\362\212 -+\324\222\004\033\145\126\114\154\324\373\266\141\132\107\043\264 -+\330\151\264\267\072\320\164\074\014\165\241\214\116\166\241\351 -+\333\052\245\073\372\316\260\377\176\152\050\375\047\034\310\261 -+\351\051\361\127\156\144\264\320\301\025\155\016\276\056\016\106 -+\310\136\364\121\376\357\016\143\072\073\161\272\317\157\131\312 -+\014\343\233\135\111\270\114\342\127\261\230\212\102\127\234\166 -+\357\357\275\321\150\250\322\364\011\273\167\065\276\045\202\010 -+\304\026\054\104\040\126\251\104\021\167\357\135\264\035\252\136 -+\153\076\213\062\366\007\057\127\004\222\312\365\376\235\302\351 -+\350\263\216\114\113\002\061\331\344\074\110\202\047\367\030\202 -+\166\110\072\161\261\023\241\071\325\056\305\064\302\035\142\205 -+\337\003\376\115\364\257\075\337\134\133\215\372\160\341\245\176 -+\047\307\206\056\152\217\022\306\204\136\103\121\120\234\031\233 -+\170\346\374\366\355\107\176\173\075\146\357\023\023\210\137\074 -+\241\143\373\371\254\207\065\237\363\202\236\244\077\012\234\061 -+\151\213\231\244\210\112\216\156\146\115\357\026\304\017\171\050 -+\041\140\015\205\026\175\327\124\070\361\222\126\375\265\063\114 -+\203\334\327\020\237\113\375\306\370\102\275\272\174\163\002\340 -+\377\175\315\133\341\324\254\141\173\127\325\112\173\133\324\205 -+\130\047\135\277\370\053\140\254\240\046\256\024\041\047\306\167 -+\232\063\200\074\136\106\077\367\303\261\243\206\063\306\350\136 -+\015\271\065\054\252\106\301\205\002\165\200\240\353\044\373\025 -+\252\344\147\177\156\167\077\364\004\212\057\174\173\343\027\141 -+\360\335\011\251\040\310\276\011\244\320\176\104\303\262\060\112 -+\070\252\251\354\030\232\007\202\053\333\270\234\030\255\332\340 -+\106\027\254\317\135\002\003\001\000\001\243\143\060\141\060\035 -+\006\003\125\035\016\004\026\004\024\331\376\041\100\156\224\236 -+\274\233\075\234\175\230\040\031\345\214\060\142\262\060\037\006 -+\003\125\035\043\004\030\060\026\200\024\331\376\041\100\156\224 -+\236\274\233\075\234\175\230\040\031\345\214\060\142\262\060\017 -+\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 -+\016\006\003\125\035\017\001\001\377\004\004\003\002\001\206\060 -+\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 -+\002\001\000\236\105\236\014\073\266\357\341\072\310\174\321\000 -+\075\317\342\352\006\265\262\072\273\006\113\150\172\320\043\227 -+\164\247\054\360\010\330\171\132\327\132\204\212\330\022\232\033 -+\331\175\134\115\160\305\245\371\253\345\243\211\211\335\001\372 -+\354\335\371\351\222\227\333\260\106\102\363\323\142\252\225\376 -+\061\147\024\151\130\220\012\252\013\356\067\043\307\120\121\264 -+\365\176\236\343\173\367\344\314\102\062\055\111\014\313\377\111 -+\014\233\036\064\375\156\156\226\212\171\003\266\157\333\011\313 -+\375\137\145\024\067\341\070\365\363\141\026\130\344\265\155\015 -+\013\004\033\077\120\055\177\263\307\172\032\026\200\140\370\212 -+\037\351\033\052\306\371\272\001\032\151\277\322\130\307\124\127 -+\010\217\341\071\140\167\113\254\131\204\032\210\361\335\313\117 -+\170\327\347\341\063\055\374\356\101\372\040\260\276\313\367\070 -+\224\300\341\320\205\017\273\355\054\163\253\355\376\222\166\032 -+\144\177\133\015\063\011\007\063\173\006\077\021\244\134\160\074 -+\205\300\317\343\220\250\203\167\372\333\346\305\214\150\147\020 -+\147\245\122\055\360\304\231\217\177\277\321\153\342\265\107\326 -+\331\320\205\231\115\224\233\017\113\215\356\000\132\107\035\021 -+\003\254\101\030\257\207\267\157\014\072\217\312\317\334\003\301 -+\242\011\310\345\375\200\136\310\140\102\001\033\032\123\132\273 -+\067\246\267\274\272\204\351\036\154\032\324\144\332\324\103\376 -+\223\213\113\362\054\171\026\020\324\223\013\210\217\241\330\206 -+\024\106\221\107\233\050\044\357\127\122\116\134\102\234\252\367 -+\111\354\047\350\100\036\263\246\211\042\162\234\365\015\063\264 -+\130\243\060\073\335\324\152\124\223\276\032\115\363\223\224\367 -+\374\204\013\077\204\040\134\064\003\104\305\332\255\274\012\301 -+\002\317\036\345\224\331\363\216\133\330\114\360\235\354\141\027 -+\273\024\062\124\014\002\051\223\036\222\206\366\177\357\347\222 -+\005\016\131\335\231\010\056\056\372\234\000\122\323\305\146\051 -+\344\247\227\104\244\016\050\201\023\065\305\366\157\144\346\101 -+\304\325\057\314\064\105\045\317\101\000\226\075\112\056\302\226 -+\230\117\116\112\234\227\267\333\037\222\062\310\377\017\121\156 -+\326\354\011 -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -+# For Server Distrust After: Wed Nov 30 00:00:00 2022 -+CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL -+\062\062\061\061\063\060\060\060\060\060\060\060\132 -+END -+# For Email Distrust After: Wed Nov 30 00:00:00 2022 -+CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL -+\062\062\061\061\063\060\060\060\060\060\060\060\132 -+END -+ -+ -+# Trust for "TrustCor RootCert CA-2" -+# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA -+# Serial Number:25:a1:df:ca:33:cb:59:02 -+# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA -+# Not Valid Before: Thu Feb 04 12:32:23 2016 -+# Not Valid After : Sun Dec 31 17:26:39 2034 -+# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 -+# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 -+CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "TrustCor RootCert CA-2" -+CKA_CERT_SHA1_HASH MULTILINE_OCTAL -+\270\276\155\313\126\361\125\271\143\324\022\312\116\006\064\307 -+\224\262\034\300 -+END -+CKA_CERT_MD5_HASH MULTILINE_OCTAL -+\242\341\370\030\013\272\105\325\307\101\052\273\067\122\105\144 -+END -+CKA_ISSUER MULTILINE_OCTAL -+\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 -+\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 -+\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 -+\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 -+\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 -+\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 -+\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 -+\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 -+\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 -+\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 -+\162\164\040\103\101\055\062 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\010\045\241\337\312\063\313\131\002 -+END -+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -+` -+ -+const trustNoCert = `CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERT_SHA1_HASH MULTILINE_OCTAL -+\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 -+\144\330\343\111 -+END -+CKA_CERT_MD5_HASH MULTILINE_OCTAL -+\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 -+END -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` -+ -+const certNoTrust = `CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_VALUE MULTILINE_OCTAL -+\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 -+\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 -+\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 -+\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 -+\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 -+\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 -+\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 -+\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 -+\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 -+\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 -+\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 -+\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 -+\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 -+\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 -+\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 -+\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 -+\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 -+\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 -+\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 -+\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 -+\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 -+\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 -+\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 -+\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 -+\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 -+\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 -+\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 -+\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 -+\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 -+\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 -+\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 -+\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 -+\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 -+\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 -+\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 -+\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 -+\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 -+\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 -+\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 -+\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 -+\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 -+\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 -+\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 -+\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 -+\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 -+\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 -+\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 -+\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 -+\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 -+\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 -+\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 -+\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 -+\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 -+\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 -+\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 -+\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 -+\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 -+\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 -+\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 -+\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 -+\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 -+\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 -+\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 -+\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 -+\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 -+\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 -+\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 -+\225\351\066\226\230\156 -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -+CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -+CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE` -+ -+const missingCertificateOctal = `CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE` -+ -+const untrustedCertCert = `# -+# Certificate "Comodo AAA Services root" -+# -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_VALUE MULTILINE_OCTAL -+\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 -+\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 -+\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 -+\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 -+\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 -+\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 -+\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 -+\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 -+\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 -+\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 -+\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 -+\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 -+\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 -+\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 -+\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 -+\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 -+\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 -+\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 -+\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 -+\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 -+\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 -+\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 -+\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 -+\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 -+\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 -+\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 -+\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 -+\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 -+\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 -+\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 -+\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 -+\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 -+\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 -+\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 -+\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 -+\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 -+\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 -+\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 -+\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 -+\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 -+\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 -+\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 -+\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 -+\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 -+\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 -+\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 -+\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 -+\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 -+\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 -+\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 -+\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 -+\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 -+\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 -+\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 -+\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 -+\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 -+\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 -+\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 -+\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 -+\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 -+\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 -+\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 -+\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 -+\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 -+\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 -+\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 -+\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 -+\225\351\066\226\230\156 -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE -+CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -+CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE -+ -+# Trust for "Comodo AAA Services root" -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERT_SHA1_HASH MULTILINE_OCTAL -+\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 -+\144\330\343\111 -+END -+CKA_CERT_MD5_HASH MULTILINE_OCTAL -+\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 -+END -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` -+ -+const untrustedCertTrust = `# -+# Certificate "Comodo AAA Services root" -+# -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_VALUE MULTILINE_OCTAL -+\060\202\004\062\060\202\003\032\240\003\002\001\002\002\001\001 -+\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 -+\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061\033 -+\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145\162 -+\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016\006 -+\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032\060 -+\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040\103 -+\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003\125 -+\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151\143 -+\141\164\145\040\123\145\162\166\151\143\145\163\060\036\027\015 -+\060\064\060\061\060\061\060\060\060\060\060\060\132\027\015\062 -+\070\061\062\063\061\062\063\065\071\065\071\132\060\173\061\013 -+\060\011\006\003\125\004\006\023\002\107\102\061\033\060\031\006 -+\003\125\004\010\014\022\107\162\145\141\164\145\162\040\115\141 -+\156\143\150\145\163\164\145\162\061\020\060\016\006\003\125\004 -+\007\014\007\123\141\154\146\157\162\144\061\032\060\030\006\003 -+\125\004\012\014\021\103\157\155\157\144\157\040\103\101\040\114 -+\151\155\151\164\145\144\061\041\060\037\006\003\125\004\003\014 -+\030\101\101\101\040\103\145\162\164\151\146\151\143\141\164\145 -+\040\123\145\162\166\151\143\145\163\060\202\001\042\060\015\006 -+\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 -+\000\060\202\001\012\002\202\001\001\000\276\100\235\364\156\341 -+\352\166\207\034\115\105\104\216\276\106\310\203\006\235\301\052 -+\376\030\037\216\344\002\372\363\253\135\120\212\026\061\013\232 -+\006\320\305\160\042\315\111\055\124\143\314\266\156\150\106\013 -+\123\352\313\114\044\300\274\162\116\352\361\025\256\364\124\232 -+\022\012\303\172\262\063\140\342\332\211\125\363\042\130\363\336 -+\334\317\357\203\206\242\214\224\117\237\150\362\230\220\106\204 -+\047\307\166\277\343\314\065\054\213\136\007\144\145\202\300\110 -+\260\250\221\371\141\237\166\040\120\250\221\307\146\265\353\170 -+\142\003\126\360\212\032\023\352\061\243\036\240\231\375\070\366 -+\366\047\062\130\157\007\365\153\270\373\024\053\257\267\252\314 -+\326\143\137\163\214\332\005\231\250\070\250\313\027\170\066\121 -+\254\351\236\364\170\072\215\317\017\331\102\342\230\014\253\057 -+\237\016\001\336\357\237\231\111\361\055\337\254\164\115\033\230 -+\265\107\305\345\051\321\371\220\030\307\142\234\276\203\307\046 -+\173\076\212\045\307\300\335\235\346\065\150\020\040\235\217\330 -+\336\322\303\204\234\015\136\350\057\311\002\003\001\000\001\243 -+\201\300\060\201\275\060\035\006\003\125\035\016\004\026\004\024 -+\240\021\012\043\076\226\361\007\354\342\257\051\357\202\245\177 -+\320\060\244\264\060\016\006\003\125\035\017\001\001\377\004\004 -+\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 -+\060\003\001\001\377\060\173\006\003\125\035\037\004\164\060\162 -+\060\070\240\066\240\064\206\062\150\164\164\160\072\057\057\143 -+\162\154\056\143\157\155\157\144\157\143\141\056\143\157\155\057 -+\101\101\101\103\145\162\164\151\146\151\143\141\164\145\123\145 -+\162\166\151\143\145\163\056\143\162\154\060\066\240\064\240\062 -+\206\060\150\164\164\160\072\057\057\143\162\154\056\143\157\155 -+\157\144\157\056\156\145\164\057\101\101\101\103\145\162\164\151 -+\146\151\143\141\164\145\123\145\162\166\151\143\145\163\056\143 -+\162\154\060\015\006\011\052\206\110\206\367\015\001\001\005\005 -+\000\003\202\001\001\000\010\126\374\002\360\233\350\377\244\372 -+\326\173\306\104\200\316\117\304\305\366\000\130\314\246\266\274 -+\024\111\150\004\166\350\346\356\135\354\002\017\140\326\215\120 -+\030\117\046\116\001\343\346\260\245\356\277\274\164\124\101\277 -+\375\374\022\270\307\117\132\364\211\140\005\177\140\267\005\112 -+\363\366\361\302\277\304\271\164\206\266\055\175\153\314\322\363 -+\106\335\057\306\340\152\303\303\064\003\054\175\226\335\132\302 -+\016\247\012\231\301\005\213\253\014\057\363\134\072\317\154\067 -+\125\011\207\336\123\100\154\130\357\374\266\253\145\156\004\366 -+\033\334\074\340\132\025\306\236\331\361\131\110\060\041\145\003 -+\154\354\351\041\163\354\233\003\241\340\067\255\240\025\030\217 -+\372\272\002\316\247\054\251\020\023\054\324\345\010\046\253\042 -+\227\140\370\220\136\164\324\242\232\123\275\362\251\150\340\242 -+\156\302\327\154\261\243\017\236\277\353\150\347\126\362\256\362 -+\343\053\070\072\011\201\265\153\205\327\276\055\355\077\032\267 -+\262\143\342\365\142\054\202\324\152\000\101\120\361\071\203\237 -+\225\351\066\226\230\156 -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -+CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -+CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE -+ -+# Trust for "Comodo AAA Services root" -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERT_SHA1_HASH MULTILINE_OCTAL -+\321\353\043\244\155\027\326\217\331\045\144\302\361\361\140\027 -+\144\330\343\111 -+END -+CKA_CERT_MD5_HASH MULTILINE_OCTAL -+\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 -+END -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_TRUST_SERVER_AUTH CK_TRUST -+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` -+ -+const malformedClass = `CKA_CLASS` -+ -+const malformedOctalCert = `# -+# Certificate "Comodo AAA Services root" -+# -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_VALUE MULTILINE_OCTAL -+hello\xxxxxxx -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -+CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -+CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE` -+ -+const malformedOctalhash = `# Trust for "Comodo AAA Services root" -+# Issuer: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Serial Number: 1 (0x1) -+# Subject: CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB -+# Not Valid Before: Thu Jan 01 00:00:00 2004 -+# Not Valid After : Sun Dec 31 23:59:59 2028 -+# Fingerprint (SHA-256): D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4 -+# Fingerprint (SHA1): D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 -+CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "Comodo AAA Services root" -+CKA_CERT_SHA1_HASH MULTILINE_OCTAL -+\xxxxx -+END -+CKA_CERT_MD5_HASH MULTILINE_OCTAL -+\111\171\004\260\353\207\031\254\107\260\274\021\121\233\164\320 -+END -+CKA_ISSUER MULTILINE_OCTAL -+\060\173\061\013\060\011\006\003\125\004\006\023\002\107\102\061 -+\033\060\031\006\003\125\004\010\014\022\107\162\145\141\164\145 -+\162\040\115\141\156\143\150\145\163\164\145\162\061\020\060\016 -+\006\003\125\004\007\014\007\123\141\154\146\157\162\144\061\032 -+\060\030\006\003\125\004\012\014\021\103\157\155\157\144\157\040 -+\103\101\040\114\151\155\151\164\145\144\061\041\060\037\006\003 -+\125\004\003\014\030\101\101\101\040\103\145\162\164\151\146\151 -+\143\141\164\145\040\123\145\162\166\151\143\145\163 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\001\001 -+END -+CKA_TRUST_SERVER_AUTH CK_TRUST -+CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -+CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE` -+ -+const malformedOctalDistrust = `# -+# Certificate "TrustCor RootCert CA-2" -+# -+# Issuer: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA -+# Serial Number:25:a1:df:ca:33:cb:59:02 -+# Subject: CN=TrustCor RootCert CA-2,OU=TrustCor Certificate Authority,O=TrustCor Systems S. de R.L.,L=Panama City,ST=Panama,C=PA -+# Not Valid Before: Thu Feb 04 12:32:23 2016 -+# Not Valid After : Sun Dec 31 17:26:39 2034 -+# Fingerprint (SHA-256): 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65 -+# Fingerprint (SHA1): B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 -+CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -+CKA_TOKEN CK_BBOOL CK_TRUE -+CKA_PRIVATE CK_BBOOL CK_FALSE -+CKA_MODIFIABLE CK_BBOOL CK_FALSE -+CKA_LABEL UTF8 "TrustCor RootCert CA-2" -+CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -+CKA_SUBJECT MULTILINE_OCTAL -+\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 -+\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 -+\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 -+\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 -+\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 -+\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 -+\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 -+\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 -+\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 -+\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 -+\162\164\040\103\101\055\062 -+END -+CKA_ID UTF8 "0" -+CKA_ISSUER MULTILINE_OCTAL -+\060\201\244\061\013\060\011\006\003\125\004\006\023\002\120\101 -+\061\017\060\015\006\003\125\004\010\014\006\120\141\156\141\155 -+\141\061\024\060\022\006\003\125\004\007\014\013\120\141\156\141 -+\155\141\040\103\151\164\171\061\044\060\042\006\003\125\004\012 -+\014\033\124\162\165\163\164\103\157\162\040\123\171\163\164\145 -+\155\163\040\123\056\040\144\145\040\122\056\114\056\061\047\060 -+\045\006\003\125\004\013\014\036\124\162\165\163\164\103\157\162 -+\040\103\145\162\164\151\146\151\143\141\164\145\040\101\165\164 -+\150\157\162\151\164\171\061\037\060\035\006\003\125\004\003\014 -+\026\124\162\165\163\164\103\157\162\040\122\157\157\164\103\145 -+\162\164\040\103\101\055\062 -+END -+CKA_SERIAL_NUMBER MULTILINE_OCTAL -+\002\010\045\241\337\312\063\313\131\002 -+END -+CKA_VALUE MULTILINE_OCTAL -+\060\202\006\057\060\202\004\027\240\003\002\001\002\002\010\045 -+\241\337\312\063\313\131\002\060\015\006\011\052\206\110\206\367 -+\015\001\001\013\005\000\060\201\244\061\013\060\011\006\003\125 -+\004\006\023\002\120\101\061\017\060\015\006\003\125\004\010\014 -+\006\120\141\156\141\155\141\061\024\060\022\006\003\125\004\007 -+\014\013\120\141\156\141\155\141\040\103\151\164\171\061\044\060 -+\042\006\003\125\004\012\014\033\124\162\165\163\164\103\157\162 -+\040\123\171\163\164\145\155\163\040\123\056\040\144\145\040\122 -+\056\114\056\061\047\060\045\006\003\125\004\013\014\036\124\162 -+\165\163\164\103\157\162\040\103\145\162\164\151\146\151\143\141 -+\164\145\040\101\165\164\150\157\162\151\164\171\061\037\060\035 -+\006\003\125\004\003\014\026\124\162\165\163\164\103\157\162\040 -+\122\157\157\164\103\145\162\164\040\103\101\055\062\060\036\027 -+\015\061\066\060\062\060\064\061\062\063\062\062\063\132\027\015 -+\063\064\061\062\063\061\061\067\062\066\063\071\132\060\201\244 -+\061\013\060\011\006\003\125\004\006\023\002\120\101\061\017\060 -+\015\006\003\125\004\010\014\006\120\141\156\141\155\141\061\024 -+\060\022\006\003\125\004\007\014\013\120\141\156\141\155\141\040 -+\103\151\164\171\061\044\060\042\006\003\125\004\012\014\033\124 -+\162\165\163\164\103\157\162\040\123\171\163\164\145\155\163\040 -+\123\056\040\144\145\040\122\056\114\056\061\047\060\045\006\003 -+\125\004\013\014\036\124\162\165\163\164\103\157\162\040\103\145 -+\162\164\151\146\151\143\141\164\145\040\101\165\164\150\157\162 -+\151\164\171\061\037\060\035\006\003\125\004\003\014\026\124\162 -+\165\163\164\103\157\162\040\122\157\157\164\103\145\162\164\040 -+\103\101\055\062\060\202\002\042\060\015\006\011\052\206\110\206 -+\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 -+\002\202\002\001\000\247\040\156\302\052\242\142\044\225\220\166 -+\310\070\176\200\322\253\301\233\145\005\224\364\301\012\020\325 -+\002\254\355\237\223\307\207\310\260\047\053\102\014\075\012\076 -+\101\132\236\165\335\215\312\340\233\354\150\062\244\151\222\150 -+\214\013\201\016\126\240\076\032\335\054\045\024\202\057\227\323 -+\144\106\364\124\251\334\072\124\055\061\053\231\202\362\331\052 -+\327\357\161\000\270\061\244\276\172\044\007\303\102\040\362\212 -+\324\222\004\033\145\126\114\154\324\373\266\141\132\107\043\264 -+\330\151\264\267\072\320\164\074\014\165\241\214\116\166\241\351 -+\333\052\245\073\372\316\260\377\176\152\050\375\047\034\310\261 -+\351\051\361\127\156\144\264\320\301\025\155\016\276\056\016\106 -+\310\136\364\121\376\357\016\143\072\073\161\272\317\157\131\312 -+\014\343\233\135\111\270\114\342\127\261\230\212\102\127\234\166 -+\357\357\275\321\150\250\322\364\011\273\167\065\276\045\202\010 -+\304\026\054\104\040\126\251\104\021\167\357\135\264\035\252\136 -+\153\076\213\062\366\007\057\127\004\222\312\365\376\235\302\351 -+\350\263\216\114\113\002\061\331\344\074\110\202\047\367\030\202 -+\166\110\072\161\261\023\241\071\325\056\305\064\302\035\142\205 -+\337\003\376\115\364\257\075\337\134\133\215\372\160\341\245\176 -+\047\307\206\056\152\217\022\306\204\136\103\121\120\234\031\233 -+\170\346\374\366\355\107\176\173\075\146\357\023\023\210\137\074 -+\241\143\373\371\254\207\065\237\363\202\236\244\077\012\234\061 -+\151\213\231\244\210\112\216\156\146\115\357\026\304\017\171\050 -+\041\140\015\205\026\175\327\124\070\361\222\126\375\265\063\114 -+\203\334\327\020\237\113\375\306\370\102\275\272\174\163\002\340 -+\377\175\315\133\341\324\254\141\173\127\325\112\173\133\324\205 -+\130\047\135\277\370\053\140\254\240\046\256\024\041\047\306\167 -+\232\063\200\074\136\106\077\367\303\261\243\206\063\306\350\136 -+\015\271\065\054\252\106\301\205\002\165\200\240\353\044\373\025 -+\252\344\147\177\156\167\077\364\004\212\057\174\173\343\027\141 -+\360\335\011\251\040\310\276\011\244\320\176\104\303\262\060\112 -+\070\252\251\354\030\232\007\202\053\333\270\234\030\255\332\340 -+\106\027\254\317\135\002\003\001\000\001\243\143\060\141\060\035 -+\006\003\125\035\016\004\026\004\024\331\376\041\100\156\224\236 -+\274\233\075\234\175\230\040\031\345\214\060\142\262\060\037\006 -+\003\125\035\043\004\030\060\026\200\024\331\376\041\100\156\224 -+\236\274\233\075\234\175\230\040\031\345\214\060\142\262\060\017 -+\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 -+\016\006\003\125\035\017\001\001\377\004\004\003\002\001\206\060 -+\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 -+\002\001\000\236\105\236\014\073\266\357\341\072\310\174\321\000 -+\075\317\342\352\006\265\262\072\273\006\113\150\172\320\043\227 -+\164\247\054\360\010\330\171\132\327\132\204\212\330\022\232\033 -+\331\175\134\115\160\305\245\371\253\345\243\211\211\335\001\372 -+\354\335\371\351\222\227\333\260\106\102\363\323\142\252\225\376 -+\061\147\024\151\130\220\012\252\013\356\067\043\307\120\121\264 -+\365\176\236\343\173\367\344\314\102\062\055\111\014\313\377\111 -+\014\233\036\064\375\156\156\226\212\171\003\266\157\333\011\313 -+\375\137\145\024\067\341\070\365\363\141\026\130\344\265\155\015 -+\013\004\033\077\120\055\177\263\307\172\032\026\200\140\370\212 -+\037\351\033\052\306\371\272\001\032\151\277\322\130\307\124\127 -+\010\217\341\071\140\167\113\254\131\204\032\210\361\335\313\117 -+\170\327\347\341\063\055\374\356\101\372\040\260\276\313\367\070 -+\224\300\341\320\205\017\273\355\054\163\253\355\376\222\166\032 -+\144\177\133\015\063\011\007\063\173\006\077\021\244\134\160\074 -+\205\300\317\343\220\250\203\167\372\333\346\305\214\150\147\020 -+\147\245\122\055\360\304\231\217\177\277\321\153\342\265\107\326 -+\331\320\205\231\115\224\233\017\113\215\356\000\132\107\035\021 -+\003\254\101\030\257\207\267\157\014\072\217\312\317\334\003\301 -+\242\011\310\345\375\200\136\310\140\102\001\033\032\123\132\273 -+\067\246\267\274\272\204\351\036\154\032\324\144\332\324\103\376 -+\223\213\113\362\054\171\026\020\324\223\013\210\217\241\330\206 -+\024\106\221\107\233\050\044\357\127\122\116\134\102\234\252\367 -+\111\354\047\350\100\036\263\246\211\042\162\234\365\015\063\264 -+\130\243\060\073\335\324\152\124\223\276\032\115\363\223\224\367 -+\374\204\013\077\204\040\134\064\003\104\305\332\255\274\012\301 -+\002\317\036\345\224\331\363\216\133\330\114\360\235\354\141\027 -+\273\024\062\124\014\002\051\223\036\222\206\366\177\357\347\222 -+\005\016\131\335\231\010\056\056\372\234\000\122\323\305\146\051 -+\344\247\227\104\244\016\050\201\023\065\305\366\157\144\346\101 -+\304\325\057\314\064\105\045\317\101\000\226\075\112\056\302\226 -+\230\117\116\112\234\227\267\333\037\222\062\310\377\017\121\156 -+\326\354\011 -+END -+CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -+# For Server Distrust After: Wed Nov 30 00:00:00 2022 -+CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL -+\xxxxxxxx -+END -+# For Email Distrust After: Wed Nov 30 00:00:00 2022 -+CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL -+\062\062\061\061\063\060\060\060\060\060\060\060\132 -+END` -diff --git a/ms_mod/golang.org/x/crypto/xtea/block.go b/ms_mod/golang.org/x/crypto/xtea/block.go -new file mode 100644 -index 00000000000000..fcb4e4d0003c2d ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/xtea/block.go -@@ -0,0 +1,66 @@ -+// Copyright 2009 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+/* -+ Implementation adapted from Needham and Wheeler's paper: -+ http://www.cix.co.uk/~klockstone/xtea.pdf -+ -+ A precalculated look up table is used during encryption/decryption for values that are based purely on the key. -+*/ -+ -+package xtea -+ -+// XTEA is based on 64 rounds. -+const numRounds = 64 -+ -+// blockToUint32 reads an 8 byte slice into two uint32s. -+// The block is treated as big endian. -+func blockToUint32(src []byte) (uint32, uint32) { -+ r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) -+ r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) -+ return r0, r1 -+} -+ -+// uint32ToBlock writes two uint32s into an 8 byte data block. -+// Values are written as big endian. -+func uint32ToBlock(v0, v1 uint32, dst []byte) { -+ dst[0] = byte(v0 >> 24) -+ dst[1] = byte(v0 >> 16) -+ dst[2] = byte(v0 >> 8) -+ dst[3] = byte(v0) -+ dst[4] = byte(v1 >> 24) -+ dst[5] = byte(v1 >> 16) -+ dst[6] = byte(v1 >> 8) -+ dst[7] = byte(v1 >> 0) -+} -+ -+// encryptBlock encrypts a single 8 byte block using XTEA. -+func encryptBlock(c *Cipher, dst, src []byte) { -+ v0, v1 := blockToUint32(src) -+ -+ // Two rounds of XTEA applied per loop -+ for i := 0; i < numRounds; { -+ v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] -+ i++ -+ v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] -+ i++ -+ } -+ -+ uint32ToBlock(v0, v1, dst) -+} -+ -+// decryptBlock decrypts a single 8 byte block using XTEA. -+func decryptBlock(c *Cipher, dst, src []byte) { -+ v0, v1 := blockToUint32(src) -+ -+ // Two rounds of XTEA applied per loop -+ for i := numRounds; i > 0; { -+ i-- -+ v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] -+ i-- -+ v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] -+ } -+ -+ uint32ToBlock(v0, v1, dst) -+} -diff --git a/ms_mod/golang.org/x/crypto/xtea/cipher.go b/ms_mod/golang.org/x/crypto/xtea/cipher.go -new file mode 100644 -index 00000000000000..a4c2fd02b32003 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/xtea/cipher.go -@@ -0,0 +1,90 @@ -+// Copyright 2009 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's -+// 1997 technical report, "Tea extensions." -+// -+// XTEA is a legacy cipher and its short block size makes it vulnerable to -+// birthday bound attacks (see https://sweet32.info). It should only be used -+// where compatibility with legacy systems, not security, is the goal. -+// -+// Deprecated: any new system should use AES (from crypto/aes, if necessary in -+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from -+// golang.org/x/crypto/chacha20poly1305). -+package xtea // import "golang.org/x/crypto/xtea" -+ -+// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf -+ -+import "strconv" -+ -+// The XTEA block size in bytes. -+const BlockSize = 8 -+ -+// A Cipher is an instance of an XTEA cipher using a particular key. -+type Cipher struct { -+ // table contains a series of precalculated values that are used each round. -+ table [64]uint32 -+} -+ -+type KeySizeError int -+ -+func (k KeySizeError) Error() string { -+ return "crypto/xtea: invalid key size " + strconv.Itoa(int(k)) -+} -+ -+// NewCipher creates and returns a new Cipher. -+// The key argument should be the XTEA key. -+// XTEA only supports 128 bit (16 byte) keys. -+func NewCipher(key []byte) (*Cipher, error) { -+ k := len(key) -+ switch k { -+ default: -+ return nil, KeySizeError(k) -+ case 16: -+ break -+ } -+ -+ c := new(Cipher) -+ initCipher(c, key) -+ -+ return c, nil -+} -+ -+// BlockSize returns the XTEA block size, 8 bytes. -+// It is necessary to satisfy the Block interface in the -+// package "crypto/cipher". -+func (c *Cipher) BlockSize() int { return BlockSize } -+ -+// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst. -+// Note that for amounts of data larger than a block, -+// it is not safe to just call Encrypt on successive blocks; -+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -+func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) } -+ -+// Decrypt decrypts the 8 byte buffer src using the key and stores the result in dst. -+func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) } -+ -+// initCipher initializes the cipher context by creating a look up table -+// of precalculated values that are based on the key. -+func initCipher(c *Cipher, key []byte) { -+ // Load the key into four uint32s -+ var k [4]uint32 -+ for i := 0; i < len(k); i++ { -+ j := i << 2 // Multiply by 4 -+ k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3]) -+ } -+ -+ // Precalculate the table -+ const delta = 0x9E3779B9 -+ var sum uint32 -+ -+ // Two rounds of XTEA applied per loop -+ for i := 0; i < numRounds; { -+ c.table[i] = sum + k[sum&3] -+ i++ -+ sum += delta -+ c.table[i] = sum + k[(sum>>11)&3] -+ i++ -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/xtea/xtea_test.go b/ms_mod/golang.org/x/crypto/xtea/xtea_test.go -new file mode 100644 -index 00000000000000..be711bf5af0032 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/xtea/xtea_test.go -@@ -0,0 +1,229 @@ -+// Copyright 2009 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package xtea -+ -+import ( -+ "testing" -+) -+ -+// A sample test key for when we just want to initialize a cipher -+var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} -+ -+// Test that the block size for XTEA is correct -+func TestBlocksize(t *testing.T) { -+ if BlockSize != 8 { -+ t.Errorf("BlockSize constant - expected 8, got %d", BlockSize) -+ return -+ } -+ -+ c, err := NewCipher(testKey) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) -+ return -+ } -+ -+ result := c.BlockSize() -+ if result != 8 { -+ t.Errorf("BlockSize function - expected 8, got %d", result) -+ return -+ } -+} -+ -+// A series of test values to confirm that the Cipher.table array was initialized correctly -+var testTable = []uint32{ -+ 0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917, -+ 0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F, -+ 0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67, -+ 0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F, -+ 0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7, -+ 0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF, -+ 0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7, -+ 0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB, -+} -+ -+// Test that the cipher context is initialized correctly -+func TestCipherInit(t *testing.T) { -+ c, err := NewCipher(testKey) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) -+ return -+ } -+ -+ for i := 0; i < len(c.table); i++ { -+ if c.table[i] != testTable[i] { -+ t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i]) -+ break -+ } -+ } -+} -+ -+// Test that invalid key sizes return an error -+func TestInvalidKeySize(t *testing.T) { -+ // Test a long key -+ key := []byte{ -+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, -+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, -+ } -+ -+ _, err := NewCipher(key) -+ if err == nil { -+ t.Errorf("Invalid key size %d didn't result in an error.", len(key)) -+ } -+ -+ // Test a short key -+ key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} -+ -+ _, err = NewCipher(key) -+ if err == nil { -+ t.Errorf("Invalid key size %d didn't result in an error.", len(key)) -+ } -+} -+ -+// Test that we can correctly decode some bytes we have encoded -+func TestEncodeDecode(t *testing.T) { -+ original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} -+ input := original -+ output := make([]byte, BlockSize) -+ -+ c, err := NewCipher(testKey) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) -+ return -+ } -+ -+ // Encrypt the input block -+ c.Encrypt(output, input) -+ -+ // Check that the output does not match the input -+ differs := false -+ for i := 0; i < len(input); i++ { -+ if output[i] != input[i] { -+ differs = true -+ break -+ } -+ } -+ if differs == false { -+ t.Error("Cipher.Encrypt: Failed to encrypt the input block.") -+ return -+ } -+ -+ // Decrypt the block we just encrypted -+ input = output -+ output = make([]byte, BlockSize) -+ c.Decrypt(output, input) -+ -+ // Check that the output from decrypt matches our initial input -+ for i := 0; i < len(input); i++ { -+ if output[i] != original[i] { -+ t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i]) -+ return -+ } -+ } -+} -+ -+// Test Vectors -+type CryptTest struct { -+ key []byte -+ plainText []byte -+ cipherText []byte -+} -+ -+var CryptTests = []CryptTest{ -+ // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors -+ { -+ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, -+ []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, -+ []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5}, -+ }, -+ { -+ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, -+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, -+ []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8}, -+ }, -+ { -+ []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, -+ []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f}, -+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, -+ }, -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, -+ []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5}, -+ }, -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, -+ []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d}, -+ }, -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55}, -+ []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, -+ }, -+ -+ // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9}, -+ }, -+ { -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, -+ []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16}, -+ }, -+ { -+ []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, -+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, -+ []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64}, -+ }, -+ { -+ []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, -+ []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, -+ []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD}, -+ }, -+} -+ -+// Test encryption -+func TestCipherEncrypt(t *testing.T) { -+ for i, tt := range CryptTests { -+ c, err := NewCipher(tt.key) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) -+ continue -+ } -+ -+ out := make([]byte, len(tt.plainText)) -+ c.Encrypt(out, tt.plainText) -+ -+ for j := 0; j < len(out); j++ { -+ if out[j] != tt.cipherText[j] { -+ t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j]) -+ break -+ } -+ } -+ } -+} -+ -+// Test decryption -+func TestCipherDecrypt(t *testing.T) { -+ for i, tt := range CryptTests { -+ c, err := NewCipher(tt.key) -+ if err != nil { -+ t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) -+ continue -+ } -+ -+ out := make([]byte, len(tt.cipherText)) -+ c.Decrypt(out, tt.cipherText) -+ -+ for j := 0; j < len(out); j++ { -+ if out[j] != tt.plainText[j] { -+ t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j]) -+ break -+ } -+ } -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/xts/xts.go b/ms_mod/golang.org/x/crypto/xts/xts.go -new file mode 100644 -index 00000000000000..8c16a8301460eb ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/xts/xts.go -@@ -0,0 +1,164 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package xts implements the XTS cipher mode as specified in IEEE P1619/D16. -+// -+// XTS mode is typically used for disk encryption, which presents a number of -+// novel problems that make more common modes inapplicable. The disk is -+// conceptually an array of sectors and we must be able to encrypt and decrypt -+// a sector in isolation. However, an attacker must not be able to transpose -+// two sectors of plaintext by transposing their ciphertext. -+// -+// XTS wraps a block cipher with Rogaway's XEX mode in order to build a -+// tweakable block cipher. This allows each sector to have a unique tweak and -+// effectively create a unique key for each sector. -+// -+// XTS does not provide any authentication. An attacker can manipulate the -+// ciphertext and randomise a block (16 bytes) of the plaintext. This package -+// does not implement ciphertext-stealing so sectors must be a multiple of 16 -+// bytes. -+// -+// Note that XTS is usually not appropriate for any use besides disk encryption. -+// Most users should use an AEAD mode like GCM (from crypto/cipher.NewGCM) instead. -+package xts // import "golang.org/x/crypto/xts" -+ -+import ( -+ "crypto/cipher" -+ "encoding/binary" -+ "errors" -+ "sync" -+ -+ "golang.org/x/crypto/internal/alias" -+) -+ -+// Cipher contains an expanded key structure. It is safe for concurrent use if -+// the underlying block cipher is safe for concurrent use. -+type Cipher struct { -+ k1, k2 cipher.Block -+} -+ -+// blockSize is the block size that the underlying cipher must have. XTS is -+// only defined for 16-byte ciphers. -+const blockSize = 16 -+ -+var tweakPool = sync.Pool{ -+ New: func() interface{} { -+ return new([blockSize]byte) -+ }, -+} -+ -+// NewCipher creates a Cipher given a function for creating the underlying -+// block cipher (which must have a block size of 16 bytes). The key must be -+// twice the length of the underlying cipher's key. -+func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) { -+ c = new(Cipher) -+ if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil { -+ return -+ } -+ c.k2, err = cipherFunc(key[len(key)/2:]) -+ -+ if c.k1.BlockSize() != blockSize { -+ err = errors.New("xts: cipher does not have a block size of 16") -+ } -+ -+ return -+} -+ -+// Encrypt encrypts a sector of plaintext and puts the result into ciphertext. -+// Plaintext and ciphertext must overlap entirely or not at all. -+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. -+func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { -+ if len(ciphertext) < len(plaintext) { -+ panic("xts: ciphertext is smaller than plaintext") -+ } -+ if len(plaintext)%blockSize != 0 { -+ panic("xts: plaintext is not a multiple of the block size") -+ } -+ if alias.InexactOverlap(ciphertext[:len(plaintext)], plaintext) { -+ panic("xts: invalid buffer overlap") -+ } -+ -+ tweak := tweakPool.Get().(*[blockSize]byte) -+ for i := range tweak { -+ tweak[i] = 0 -+ } -+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum) -+ -+ c.k2.Encrypt(tweak[:], tweak[:]) -+ -+ for len(plaintext) > 0 { -+ for j := range tweak { -+ ciphertext[j] = plaintext[j] ^ tweak[j] -+ } -+ c.k1.Encrypt(ciphertext, ciphertext) -+ for j := range tweak { -+ ciphertext[j] ^= tweak[j] -+ } -+ plaintext = plaintext[blockSize:] -+ ciphertext = ciphertext[blockSize:] -+ -+ mul2(tweak) -+ } -+ -+ tweakPool.Put(tweak) -+} -+ -+// Decrypt decrypts a sector of ciphertext and puts the result into plaintext. -+// Plaintext and ciphertext must overlap entirely or not at all. -+// Sectors must be a multiple of 16 bytes and less than 2²⁴ bytes. -+func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { -+ if len(plaintext) < len(ciphertext) { -+ panic("xts: plaintext is smaller than ciphertext") -+ } -+ if len(ciphertext)%blockSize != 0 { -+ panic("xts: ciphertext is not a multiple of the block size") -+ } -+ if alias.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) { -+ panic("xts: invalid buffer overlap") -+ } -+ -+ tweak := tweakPool.Get().(*[blockSize]byte) -+ for i := range tweak { -+ tweak[i] = 0 -+ } -+ binary.LittleEndian.PutUint64(tweak[:8], sectorNum) -+ -+ c.k2.Encrypt(tweak[:], tweak[:]) -+ -+ for len(ciphertext) > 0 { -+ for j := range tweak { -+ plaintext[j] = ciphertext[j] ^ tweak[j] -+ } -+ c.k1.Decrypt(plaintext, plaintext) -+ for j := range tweak { -+ plaintext[j] ^= tweak[j] -+ } -+ plaintext = plaintext[blockSize:] -+ ciphertext = ciphertext[blockSize:] -+ -+ mul2(tweak) -+ } -+ -+ tweakPool.Put(tweak) -+} -+ -+// mul2 multiplies tweak by 2 in GF(2¹²⁸) with an irreducible polynomial of -+// x¹²⁸ + x⁷ + xΒ² + x + 1. -+func mul2(tweak *[blockSize]byte) { -+ var carryIn byte -+ for j := range tweak { -+ carryOut := tweak[j] >> 7 -+ tweak[j] = (tweak[j] << 1) + carryIn -+ carryIn = carryOut -+ } -+ if carryIn != 0 { -+ // If we have a carry bit then we need to subtract a multiple -+ // of the irreducible polynomial (x¹²⁸ + x⁷ + xΒ² + x + 1). -+ // By dropping the carry bit, we're subtracting the x^128 term -+ // so all that remains is to subtract x⁷ + xΒ² + x + 1. -+ // Subtraction (and addition) in this representation is just -+ // XOR. -+ tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1 -+ } -+} -diff --git a/ms_mod/golang.org/x/crypto/xts/xts_test.go b/ms_mod/golang.org/x/crypto/xts/xts_test.go -new file mode 100644 -index 00000000000000..75db1c509b5910 ---- /dev/null -+++ b/ms_mod/golang.org/x/crypto/xts/xts_test.go -@@ -0,0 +1,121 @@ -+// Copyright 2012 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package xts -+ -+import ( -+ "bytes" -+ "crypto/aes" -+ "encoding/hex" -+ "testing" -+) -+ -+// These test vectors have been taken from IEEE P1619/D16, Annex B. -+var xtsTestVectors = []struct { -+ key string -+ sector uint64 -+ plaintext string -+ ciphertext string -+}{ -+ { -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ 0, -+ "0000000000000000000000000000000000000000000000000000000000000000", -+ "917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e", -+ }, { -+ "1111111111111111111111111111111122222222222222222222222222222222", -+ 0x3333333333, -+ "4444444444444444444444444444444444444444444444444444444444444444", -+ "c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0", -+ }, { -+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222", -+ 0x3333333333, -+ "4444444444444444444444444444444444444444444444444444444444444444", -+ "af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89", -+ }, { -+ "2718281828459045235360287471352631415926535897932384626433832795", -+ 0, -+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", -+ "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", -+ }, { -+ "2718281828459045235360287471352631415926535897932384626433832795", -+ 1, -+ "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", -+ "264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd", -+ }, { -+ "27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592", -+ 0xff, -+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", -+ "1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151", -+ }, -+} -+ -+func fromHex(s string) []byte { -+ ret, err := hex.DecodeString(s) -+ if err != nil { -+ panic("xts: invalid hex in test") -+ } -+ return ret -+} -+ -+func TestXTS(t *testing.T) { -+ for i, test := range xtsTestVectors { -+ c, err := NewCipher(aes.NewCipher, fromHex(test.key)) -+ if err != nil { -+ t.Errorf("#%d: failed to create cipher: %s", i, err) -+ continue -+ } -+ plaintext := fromHex(test.plaintext) -+ ciphertext := make([]byte, len(plaintext)) -+ c.Encrypt(ciphertext, plaintext, test.sector) -+ -+ expectedCiphertext := fromHex(test.ciphertext) -+ if !bytes.Equal(ciphertext, expectedCiphertext) { -+ t.Errorf("#%d: encrypted failed, got: %x, want: %x", i, ciphertext, expectedCiphertext) -+ continue -+ } -+ -+ decrypted := make([]byte, len(ciphertext)) -+ c.Decrypt(decrypted, ciphertext, test.sector) -+ if !bytes.Equal(decrypted, plaintext) { -+ t.Errorf("#%d: decryption failed, got: %x, want: %x", i, decrypted, plaintext) -+ } -+ } -+} -+ -+func TestShorterCiphertext(t *testing.T) { -+ // Decrypt used to panic if the input was shorter than the output. See -+ // https://go-review.googlesource.com/c/39954/ -+ c, err := NewCipher(aes.NewCipher, make([]byte, 32)) -+ if err != nil { -+ t.Fatalf("NewCipher failed: %s", err) -+ } -+ -+ plaintext := make([]byte, 32) -+ encrypted := make([]byte, 48) -+ decrypted := make([]byte, 48) -+ -+ c.Encrypt(encrypted, plaintext, 0) -+ c.Decrypt(decrypted, encrypted[:len(plaintext)], 0) -+ -+ if !bytes.Equal(plaintext, decrypted[:len(plaintext)]) { -+ t.Errorf("En/Decryption is not inverse") -+ } -+} -+ -+func BenchmarkXTS(b *testing.B) { -+ b.ReportAllocs() -+ c, err := NewCipher(aes.NewCipher, make([]byte, 32)) -+ if err != nil { -+ b.Fatalf("NewCipher failed: %s", err) -+ } -+ plaintext := make([]byte, 32) -+ encrypted := make([]byte, 48) -+ decrypted := make([]byte, 48) -+ -+ for i := 0; i < b.N; i++ { -+ c.Encrypt(encrypted, plaintext, 0) -+ c.Decrypt(decrypted, encrypted[:len(plaintext)], 0) -+ } -+} From fc10693c4ad51666d93ee57656da12b2131b0b78 Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Tue, 26 Sep 2023 17:49:17 -0500 Subject: [PATCH 4/7] MS_MODROOT -> GOMSMODROOT --- eng/_core/cmd/build/build.go | 2 +- patches/0009-Add-xcryptobackendswap.patch | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/eng/_core/cmd/build/build.go b/eng/_core/cmd/build/build.go index d180036e830..dddb41e6ab1 100644 --- a/eng/_core/cmd/build/build.go +++ b/eng/_core/cmd/build/build.go @@ -54,7 +54,7 @@ func main() { &o.SkipMSMod, "skipmsmod", false, "Skip creating the _ms_mod directory with the x/crypto fork to be used by the XCryptoSwap experiment.\n"+ "Note: tests will fail. The patched standard library test suite will notice if the the backend isn't used for x/crypto.\n"+ - "A alternate way to fix tests without _ms_mod generation is to set MS_MODROOT to a manually created fork.") + "A alternate way to fix tests without _ms_mod generation is to set GOMSMODROOT to a manually created fork.") flag.BoolVar( &o.CleanMSMod, "cleanmsmod", false, "Remove _ms_mod directory when the build is complete.\n"+ diff --git a/patches/0009-Add-xcryptobackendswap.patch b/patches/0009-Add-xcryptobackendswap.patch index e982ed1e81c..9d1d60fe507 100644 --- a/patches/0009-Add-xcryptobackendswap.patch +++ b/patches/0009-Add-xcryptobackendswap.patch @@ -130,7 +130,7 @@ index b2cb44100ec4d2..23bee33d44d1ba 100644 diff --git a/src/cmd/go/internal/modload/xcryptoswap.go b/src/cmd/go/internal/modload/xcryptoswap.go new file mode 100644 -index 00000000000000..5b367cd14385f1 +index 00000000000000..8262bd64e7c6c5 --- /dev/null +++ b/src/cmd/go/internal/modload/xcryptoswap.go @@ -0,0 +1,165 @@ @@ -272,10 +272,10 @@ index 00000000000000..5b367cd14385f1 +// toolsetOverrideModuleDir returns the path to a directory in GOROOT where +// copies of modules are kept that may be used when building a program with that +// particular toolset. It is similar to a vendor directory, but only contains -+// the modules, no modules.txt. For development purposes, the MS_MODROOT ++// the modules, no modules.txt. For development purposes, the GOMSMODROOT +// environment variable can redirect to a specified directory. +func toolsetOverrideModuleDir() string { -+ if msModRoot := cfg.Getenv("MS_MODROOT"); msModRoot != "" { ++ if msModRoot := cfg.Getenv("GOMSMODROOT"); msModRoot != "" { + return msModRoot + } + return filepath.Join(cfg.BuildContext.GOROOT, "_ms_mod") @@ -594,14 +594,14 @@ index 00000000000000..03cbd2ca4a81ac + } +} diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go -index 2af0ec70786894..585cc01a9137e3 100644 +index 2af0ec70786894..5739e06a6aaacd 100644 --- a/src/internal/cfg/cfg.go +++ b/src/internal/cfg/cfg.go @@ -67,4 +67,5 @@ const KnownEnv = ` GOWORK GO_EXTLINK_ENABLED PKG_CONFIG -+ MS_MODROOT ++ GOMSMODROOT ` diff --git a/src/internal/goexperiment/exp_xcryptobackendswap_off.go b/src/internal/goexperiment/exp_xcryptobackendswap_off.go new file mode 100644 @@ -634,7 +634,7 @@ index 00000000000000..77018702a444be +const XCryptoBackendSwap = true +const XCryptoBackendSwapInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go -index d4134300ca0269..9f4058556cb751 100644 +index 60a1dda7376e38..08e527c2866520 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -85,6 +85,12 @@ type Flags struct { From ce4649eccf0e0021a5920c75886bb30daece2538 Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Tue, 26 Sep 2023 18:17:23 -0500 Subject: [PATCH 5/7] Fix eng modules: tidy, go 1.18 for generics --- eng/_core/go.mod | 4 +- eng/_core/go.sum | 389 +---------- .../github.com/microsoft/go-infra/LICENSE | 21 + .../microsoft/go-infra/executil/executil.go | 67 ++ .../microsoft/go-infra/xcryptofork/backend.go | 535 +++++++++++++++ .../microsoft/go-infra/xcryptofork/git.go | 59 ++ eng/_core/vendor/golang.org/x/tools/LICENSE | 27 + eng/_core/vendor/golang.org/x/tools/PATENTS | 22 + .../x/tools/go/ast/astutil/enclosing.go | 636 ++++++++++++++++++ .../x/tools/go/ast/astutil/imports.go | 485 +++++++++++++ .../x/tools/go/ast/astutil/rewrite.go | 488 ++++++++++++++ .../golang.org/x/tools/go/ast/astutil/util.go | 18 + .../x/tools/internal/typeparams/common.go | 179 +++++ .../x/tools/internal/typeparams/coretype.go | 122 ++++ .../internal/typeparams/enabled_go117.go | 12 + .../internal/typeparams/enabled_go118.go | 15 + .../x/tools/internal/typeparams/normalize.go | 218 ++++++ .../x/tools/internal/typeparams/termlist.go | 163 +++++ .../internal/typeparams/typeparams_go117.go | 197 ++++++ .../internal/typeparams/typeparams_go118.go | 151 +++++ .../x/tools/internal/typeparams/typeterm.go | 170 +++++ eng/_core/vendor/modules.txt | 8 + eng/_util/go.mod | 21 +- eng/_util/go.sum | 14 +- 24 files changed, 3624 insertions(+), 397 deletions(-) create mode 100644 eng/_core/vendor/github.com/microsoft/go-infra/LICENSE create mode 100644 eng/_core/vendor/github.com/microsoft/go-infra/executil/executil.go create mode 100644 eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/backend.go create mode 100644 eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/git.go create mode 100644 eng/_core/vendor/golang.org/x/tools/LICENSE create mode 100644 eng/_core/vendor/golang.org/x/tools/PATENTS create mode 100644 eng/_core/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go create mode 100644 eng/_core/vendor/golang.org/x/tools/go/ast/astutil/imports.go create mode 100644 eng/_core/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go create mode 100644 eng/_core/vendor/golang.org/x/tools/go/ast/astutil/util.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/common.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/coretype.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/normalize.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/termlist.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go create mode 100644 eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeterm.go create mode 100644 eng/_core/vendor/modules.txt diff --git a/eng/_core/go.mod b/eng/_core/go.mod index 7c3e504ffb4..23a7e777323 100644 --- a/eng/_core/go.mod +++ b/eng/_core/go.mod @@ -4,6 +4,8 @@ module github.com/microsoft/go/_core -go 1.16 +go 1.18 require github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d + +require golang.org/x/tools v0.1.12 // indirect diff --git a/eng/_core/go.sum b/eng/_core/go.sum index cbcd037b401..58499e86700 100644 --- a/eng/_core/go.sum +++ b/eng/_core/go.sum @@ -1,392 +1,5 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY= github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d h1:2dYhK+YQIwmN5n/AImhvU6Krn48vgWGCcuvwLb1wEJ4= github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d/go.mod h1:hGTlq0ZBZVmZwHgV+JezVdi8jZ2f4/UydeYvMVjAJLM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/eng/_core/vendor/github.com/microsoft/go-infra/LICENSE b/eng/_core/vendor/github.com/microsoft/go-infra/LICENSE new file mode 100644 index 00000000000..9e841e7a26e --- /dev/null +++ b/eng/_core/vendor/github.com/microsoft/go-infra/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/eng/_core/vendor/github.com/microsoft/go-infra/executil/executil.go b/eng/_core/vendor/github.com/microsoft/go-infra/executil/executil.go new file mode 100644 index 00000000000..fd46a6d13fe --- /dev/null +++ b/eng/_core/vendor/github.com/microsoft/go-infra/executil/executil.go @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Package executil contains some common wrappers for simple use of exec.Cmd. +package executil + +import ( + "fmt" + "os" + "os/exec" + "strings" + "time" +) + +// Run sets up the command to log directly to our stdout/stderr streams, then runs it. +func Run(c *exec.Cmd) error { + c.Stdout = os.Stdout + c.Stderr = os.Stderr + return RunQuiet(c) +} + +// RunQuiet logs the command line and runs the given command, but sends the output to os.DevNull. +func RunQuiet(c *exec.Cmd) error { + fmt.Printf("---- Running command: %v %v\n", c.Path, c.Args) + return c.Run() +} + +// CombinedOutput runs a command and returns the output string of c.CombinedOutput. +func CombinedOutput(c *exec.Cmd) (string, error) { + fmt.Printf("---- Running command: %v %v\n", c.Path, c.Args) + out, err := c.CombinedOutput() + if err != nil { + return "", err + } + return string(out), nil +} + +// SpaceTrimmedCombinedOutput runs CombinedOutput and trims leading/trailing spaces from the result. +func SpaceTrimmedCombinedOutput(c *exec.Cmd) (string, error) { + out, err := CombinedOutput(c) + if err != nil { + return "", err + } + return strings.TrimSpace(out), nil +} + +// Dir returns a command that runs in the given dir. The command can be passed to one of the other +// funcs in this package to evaluate it and optionally get the output as a string. Dir is useful to +// construct one-liner command calls, because setting the dir is commonly needed and not settable +// with exec.Command directly. +func Dir(dir, name string, args ...string) *exec.Cmd { + cmd := exec.Command(name, args...) + cmd.Dir = dir + return cmd +} + +// MakeWorkDir creates a unique path inside the given root dir to use as a workspace. The name +// starts with the local time in a sortable format to help with browsing multiple workspaces. This +// function allows a command to run multiple times in sequence without overwriting or deleting the +// old data, for diagnostic purposes. This function uses os.MkdirAll to ensure the root dir exists. +func MakeWorkDir(rootDir string) (string, error) { + pathDate := time.Now().Format("2006-01-02_15-04-05") + if err := os.MkdirAll(rootDir, os.ModePerm); err != nil { + return "", err + } + return os.MkdirTemp(rootDir, fmt.Sprintf("%s_*", pathDate)) +} diff --git a/eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/backend.go b/eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/backend.go new file mode 100644 index 00000000000..18dfd045f60 --- /dev/null +++ b/eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/backend.go @@ -0,0 +1,535 @@ +package xcryptofork + +import ( + "errors" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "io" + "path/filepath" + "strconv" + "strings" + + "golang.org/x/tools/go/ast/astutil" +) + +// XCryptoBackendProxyPath is the path within an x/crypto fork of the backend proxy. +var XCryptoBackendProxyPath = filepath.Join("internal", "backend") + +// xCryptoBackendMapPrefix is the prefix for command comments. It would be nice +// to omit the " ", but the Go formatter adds it back in. (Sometimes? It does +// in VS Code. It doesn't seem like Go formatters should, though.) +const xCryptoBackendMapPrefix = "// xcrypto_backend_map:" + +func commands(n ast.Node) []string { + var cmds []string + ast.Inspect(n, func(n ast.Node) bool { + if n, ok := n.(*ast.Comment); !ok { + return true + } else if cmd, ok := strings.CutPrefix(n.Text, xCryptoBackendMapPrefix); !ok { + return true + } else { + cmds = append(cmds, cmd) + } + return false + }) + return cmds +} + +// FindBackendFiles returns the Go files that appear to be backends in the +// given directory. Returns the parsed trees rather than only the filenames: we +// parsed the file to determine if it's a backend, and the parsed data is +// useful later. +func FindBackendFiles(dir string) ([]*BackendFile, error) { + matches, err := filepath.Glob(filepath.Join(dir, "*.go")) + if err != nil { + return nil, err + } + var backends []*BackendFile + for _, match := range matches { + b, err := NewBackendFile(match) + if err != nil { + if errors.Is(err, errNotBackend) { + continue + } + return nil, err + } + backends = append(backends, b) + } + return backends, nil +} + +type FormattedWriterTo interface { + Format(w io.Writer) error +} + +var errNotBackend = errors.New("not a crypto backend file") + +type BackendFile struct { + // Filename is the absolute path to the original file. + Filename string + Constraint string + + f *ast.File + fset *token.FileSet + + enabledDecl *ast.ValueSpec +} + +func NewBackendFile(filename string) (*BackendFile, error) { + b := &BackendFile{ + Filename: filename, + fset: token.NewFileSet(), + } + f, err := parser.ParseFile(b.fset, filename, nil, parser.ParseComments) + if err != nil { + return nil, err + } + b.f = f + // Super simple heuristic that works for "crypto/internal/backend": does + // the file define "Enabled"? + enabledObj := f.Scope.Lookup("Enabled") + if enabledObj == nil { + return nil, errNotBackend + } + var ok bool + if b.enabledDecl, ok = enabledObj.Decl.(*ast.ValueSpec); !ok { + return nil, fmt.Errorf( + "found Enabled symbol, but not a ValueSpec: %q defined at %v", + enabledObj.Name, b.fset.Position(enabledObj.Pos())) + } + // Preserve the build constraint. + for _, cg := range f.Comments { + for _, c := range cg.List { + if strings.HasPrefix(c.Text, "//go:build ") { + b.Constraint = c.Text + break + } + } + } + return b, nil +} + +// APITrim changes b to include a placeholder API, following conventions that +// assume b is a "nobackend" crypto backend. The placeholder API is buildable, +// but panics if used. +func (b *BackendFile) APITrim() error { + var err error + localPackageType := make(map[string]*ast.TypeSpec) + _ = astutil.Apply(b.f, func(c *astutil.Cursor) bool { + switch n := (c.Node()).(type) { + // Only look into top-level declarations, nothing else. + case *ast.File, *ast.GenDecl: + return true + + case *ast.TypeSpec: + // Remove type names declared in this package and keep track of + // them to remove any functions that use them in another pass. + localPackageType[n.Name.Name] = n + c.Delete() + + case *ast.ValueSpec: + // Remove all var/const declarations other than Enabled. + declaresEnabled := false + for _, name := range n.Names { + if name.Name == "Enabled" { + declaresEnabled = true + } + } + if !declaresEnabled { + c.Delete() + } else if len(n.Names) != 1 { + err = fmt.Errorf( + "declaration for Enabled %v includes multiple names", + b.fset.Position(n.Pos())) + } + // We could detect "const RandReader = ..." and change it to + // "var RandReader io.Reader". go:linkname supports mapping a var + // to a const in this way. However, this is already accessible via + // "crypto/rand" and there is no need to provide direct access. + // So, simply leave it out. + } + return false + }, func(c *astutil.Cursor) bool { + switch n := (c.Node()).(type) { + case *ast.GenDecl: + // Removing a ValueSpec or TypeSpec could leave a node with zero + // specs. format.Node fails if there are zero specs. Clean it up. + if len(n.Specs) == 0 { + c.Delete() + } + } + return true + }) + if err != nil { + return err + } + _ = astutil.Apply(b.f, func(c *astutil.Cursor) bool { + switch n := (c.Node()).(type) { + case *ast.File: + return true + case *ast.FuncDecl: + // Remove unexported functions and all methods. + if !n.Name.IsExported() || n.Recv != nil { + c.Delete() + return false + } + var remove bool + ast.Inspect(n.Type, func(tn ast.Node) bool { + switch tn := tn.(type) { + case *ast.Ident: + if _, ok := localPackageType[tn.Name]; ok { + remove = true + return false + } + } + return true + }) + if remove { + c.Delete() + } + } + return false + }, nil) + return cleanImports(b.f) +} + +// ProxyAPI creates a proxy for b implementing each var/func in the given api. +// If b is missing some part of api, it is skipped and recorded in the returned +// BackendProxy to be included in a comment by Format. +// +// If a func in b uses the "noescape" command, the proxy includes +// "//go:noescape" on that func. +func (b *BackendFile) ProxyAPI(api *BackendFile) (*BackendProxy, error) { + p := &BackendProxy{ + backend: b, + api: api, + f: &ast.File{Name: b.f.Name}, + fset: token.NewFileSet(), + } + + // Keep track of the first err hit by each AST walk in this variable. + // Note that walks don't necessarily stop immediately when "return false" is + // used, so take care that an error isn't cleared out by a later iteration. + var err error + failFalse := func(walkErr error) bool { + if err == nil && walkErr != nil { + err = walkErr + } + return false + } + + // Copy the imports that are used to define the API. + // Ignore the imports used by b: those will include internal packages and + // backend-specific packages that we don't have access to. + ast.Inspect(api.f, func(n ast.Node) bool { + switch n := n.(type) { + case *ast.File: + return true + case *ast.GenDecl: + if n.Tok == token.IMPORT { + return true + } + case *ast.ImportSpec: + var name string + if n.Name != nil { + name = n.Name.Name + } + path, err := strconv.Unquote(n.Path.Value) + if err != nil { + return failFalse(err) + } + astutil.AddNamedImport(p.fset, p.f, name, path) + } + return false + }) + if err != nil { + return nil, err + } + + // Add unsafe import needed for go:linkname. + astutil.AddNamedImport(p.fset, p.f, "_", "unsafe") + + // Add Enabled const. + if len(b.enabledDecl.Values) != 1 { + return nil, fmt.Errorf( + "declaration for Enabled %v includes 0 or multiple values", + b.fset.Position(b.enabledDecl.Pos())) + } + v, err := deepCopyExpression(b.enabledDecl.Values[0]) + if err != nil { + return nil, err + } + p.f.Decls = append(p.f.Decls, &ast.GenDecl{ + Tok: token.CONST, + Specs: []ast.Spec{ + &ast.ValueSpec{ + Names: []*ast.Ident{{Name: "Enabled"}}, + Values: []ast.Expr{v}, + }, + }, + }) + + // For each API, find it in b. If exists, generate linkname "proxy" func. + ast.Inspect(api.f, func(n ast.Node) bool { + switch n := n.(type) { + case *ast.File: + return true + case *ast.FuncDecl: + apiFnType, err := deepCopyExpression(n.Type) + if err != nil { + return failFalse(err) + } + // Find the corresponding func in b. + o := b.f.Scope.Lookup(n.Name.Name) + if o == nil { + p.missing = append(p.missing, n) + p.f.Decls = append(p.f.Decls, + newPanicFunc(n, apiFnType, "not implemented by this backend")) + return false + } + fn, ok := o.Decl.(*ast.FuncDecl) + if !ok { + return failFalse(fmt.Errorf( + "found symbol, but not a function: %q defined at %v", + n.Name.Name, api.fset.Position(n.Pos()))) + } + comments := []*ast.Comment{ + {Text: "//go:linkname " + n.Name.Name + " crypto/internal/backend." + n.Name.Name}, + } + for _, cmd := range commands(fn) { + switch cmd { + case "noescape": + comments = append(comments, &ast.Comment{Text: "//go:noescape"}) + default: + return failFalse(fmt.Errorf("unknown command %q (%v)", cmd, b.fset.Position(n.Pos()))) + } + } + proxyFnType, err := deepCopyExpression(fn.Type) + if err != nil { + return failFalse(err) + } + proxyFn := &ast.FuncDecl{ + // Don't use the original data: make sure the token position is + // not copied. Including a non-zero position causes the + // formatter to write the comment in strange locations within + // the function declaration: it tries to reconcile specific + // token positions vs. the zero position of the comment. + Name: ast.NewIdent(n.Name.Name), + Type: proxyFnType, + Doc: &ast.CommentGroup{List: comments}, + } + p.f.Decls = append(p.f.Decls, proxyFn) + } + return false + }) + if err != nil { + return nil, err + } + + if err := cleanImports(p.f); err != nil { + return nil, err + } + return p, nil +} + +func (b *BackendFile) Format(w io.Writer) error { + io.WriteString(w, "// Generated code. DO NOT EDIT.\n\n") + if b.Constraint != "" { + io.WriteString(w, b.Constraint) + io.WriteString(w, "\n\n") + } + return write(b.f, b.fset, w) +} + +type BackendProxy struct { + backend *BackendFile + api *BackendFile + + f *ast.File + fset *token.FileSet + + missing []*ast.FuncDecl +} + +func (p *BackendProxy) Format(w io.Writer) error { + io.WriteString(w, "// Generated code. DO NOT EDIT.\n\n") + io.WriteString(w, "// This file implements a proxy that links into a specific crypto backend.\n\n") + if p.backend.Constraint != "" { + io.WriteString(w, p.backend.Constraint) + io.WriteString(w, "\n\n") + } + if len(p.missing) > 0 { + io.WriteString(w, "// The following functions defined in the API are not implemented by the backend and panic instead:\n//\n") + for _, fn := range p.missing { + io.WriteString(w, "//\t") + io.WriteString(w, fn.Name.Name) + io.WriteString(w, "\n") + } + io.WriteString(w, "\n") + } + return write(p.f, p.fset, w) +} + +func write(f *ast.File, fset *token.FileSet, w io.Writer) error { + // Force the printer to use the comments associated with the nodes by + // clearing the cache-like (but not just a cache) Comments slice. + f.Comments = nil + return format.Node(w, fset, f) +} + +func cleanImports(f *ast.File) error { + var err error + var cleanedImports []ast.Spec + _ = astutil.Apply(f, func(c *astutil.Cursor) bool { + switch n := (c.Node()).(type) { + case *ast.GenDecl: + // Support multiple import declarations. Import blocks can't be + // nested, so simply reset the slice. + if n.Tok == token.IMPORT { + cleanedImports = cleanedImports[:0] + } + case *ast.ImportSpec: + var p string + if p, err = strconv.Unquote(n.Path.Value); err != nil { + return false + } + if n.Name != nil && n.Name.Name == "_" || astutil.UsesImport(f, p) { + // Reset the position to remove unnecessary newlines when + // imports are omitted. + n.Path.ValuePos = 0 + cleanedImports = append(cleanedImports, n) + } + return false + } + return true + }, func(c *astutil.Cursor) bool { + switch n := (c.Node()).(type) { + case *ast.GenDecl: + if n.Tok == token.IMPORT { + n.Specs = cleanedImports + } + } + return true + }) + return nil +} + +func newPanicFunc(n *ast.FuncDecl, fnType *ast.FuncType, message string) *ast.FuncDecl { + return &ast.FuncDecl{ + Name: ast.NewIdent(n.Name.Name), + Type: fnType, + Doc: &ast.CommentGroup{ + List: []*ast.Comment{{Text: "// Not implemented by this backend."}}, + }, + Body: &ast.BlockStmt{ + List: []ast.Stmt{ + &ast.ExprStmt{ + X: &ast.CallExpr{ + Fun: &ast.Ident{Name: "panic"}, + Args: []ast.Expr{ + &ast.BasicLit{ + Kind: token.STRING, + Value: strconv.Quote(message), + }, + }, + }, + }, + }, + }, + } +} + +// Deep copy functions for the AST, but without copying token positions. + +func deepCopyFieldList(src *ast.FieldList) (*ast.FieldList, error) { + var dst ast.FieldList + for _, x := range src.List { + xCopy, err := deepCopyField(x) + if err != nil { + return nil, err + } + dst.List = append(dst.List, xCopy) + } + return &dst, nil +} + +func deepCopyField(src *ast.Field) (*ast.Field, error) { + var dst ast.Field + for _, n := range src.Names { + nCopy, err := deepCopyExpression(n) + if err != nil { + return nil, err + } + dst.Names = append(dst.Names, nCopy) + } + var err error + dst.Type, err = deepCopyExpression(src.Type) + if err != nil { + return nil, err + } + return &dst, nil +} + +func deepCopyExpression[T ast.Expr](src T) (T, error) { + var err error + var f func(ast.Expr) ast.Expr + f = func(src ast.Expr) ast.Expr { + if src == nil { + return nil + } + switch src := src.(type) { + + case *ast.ArrayType: + return &ast.ArrayType{ + Elt: f(src.Elt), + Len: f(src.Len), + } + + case *ast.FuncType: + if src.TypeParams != nil { + err = fmt.Errorf("unsupported type params %v", src.TypeParams) + return nil + } + var ft ast.FuncType + ft.Params, err = deepCopyFieldList(src.Params) + if err != nil { + return nil + } + ft.Results, err = deepCopyFieldList(src.Results) + if err != nil { + return nil + } + return &ft + + case *ast.Ident: + return ast.NewIdent(src.Name) + + case *ast.SelectorExpr: + return &ast.SelectorExpr{ + X: f(src.X), + Sel: f(src.Sel).(*ast.Ident), + } + + case *ast.BasicLit: + return &ast.BasicLit{ + Kind: src.Kind, + Value: src.Value, + } + + case *ast.StarExpr: + return &ast.StarExpr{ + X: f(src.X), + } + } + err = fmt.Errorf("unsupported expression type %T", src) + return nil + } + r := f(src) + if err != nil { + return *new(T), err + } + return r.(T), nil +} diff --git a/eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/git.go b/eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/git.go new file mode 100644 index 00000000000..2b77f21451d --- /dev/null +++ b/eng/_core/vendor/github.com/microsoft/go-infra/xcryptofork/git.go @@ -0,0 +1,59 @@ +package xcryptofork + +import ( + "bufio" + "errors" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" +) + +func GitCheckoutTo(gitDir, outDir string) error { + outDir, err := filepath.Abs(outDir) + if err != nil { + return err + } + cmd := exec.Command( + "git", + "checkout-index", + "--all", + "-f", + "--prefix="+outDir+"/", + ) + cmd.Dir = gitDir + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("In %#q, running %v", cmd.Dir, cmd) + return cmd.Run() +} + +func RemoveDirContent(dir string, prompt bool) error { + if prompt { + fmt.Printf("Delete %#q? [y/N] ", dir) + s := bufio.NewScanner(os.Stdin) + _ = s.Scan() + if s.Text() != "y" { + return fmt.Errorf("aborting: %q not %q\n", s.Text(), "y") + } + if err := s.Err(); err != nil { + return err + } + fmt.Println() + } + entries, err := os.ReadDir(dir) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + // Nothing to do. + return nil + } + return err + } + for _, entry := range entries { + if err := os.RemoveAll(filepath.Join(dir, entry.Name())); err != nil { + return err + } + } + return nil +} diff --git a/eng/_core/vendor/golang.org/x/tools/LICENSE b/eng/_core/vendor/golang.org/x/tools/LICENSE new file mode 100644 index 00000000000..6a66aea5eaf --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/eng/_core/vendor/golang.org/x/tools/PATENTS b/eng/_core/vendor/golang.org/x/tools/PATENTS new file mode 100644 index 00000000000..733099041f8 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go new file mode 100644 index 00000000000..9fa5aa192c2 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -0,0 +1,636 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package astutil + +// This file defines utilities for working with source positions. + +import ( + "fmt" + "go/ast" + "go/token" + "sort" + + "golang.org/x/tools/internal/typeparams" +) + +// PathEnclosingInterval returns the node that encloses the source +// interval [start, end), and all its ancestors up to the AST root. +// +// The definition of "enclosing" used by this function considers +// additional whitespace abutting a node to be enclosed by it. +// In this example: +// +// z := x + y // add them +// <-A-> +// <----B-----> +// +// the ast.BinaryExpr(+) node is considered to enclose interval B +// even though its [Pos()..End()) is actually only interval A. +// This behaviour makes user interfaces more tolerant of imperfect +// input. +// +// This function treats tokens as nodes, though they are not included +// in the result. e.g. PathEnclosingInterval("+") returns the +// enclosing ast.BinaryExpr("x + y"). +// +// If start==end, the 1-char interval following start is used instead. +// +// The 'exact' result is true if the interval contains only path[0] +// and perhaps some adjacent whitespace. It is false if the interval +// overlaps multiple children of path[0], or if it contains only +// interior whitespace of path[0]. +// In this example: +// +// z := x + y // add them +// <--C--> <---E--> +// ^ +// D +// +// intervals C, D and E are inexact. C is contained by the +// z-assignment statement, because it spans three of its children (:=, +// x, +). So too is the 1-char interval D, because it contains only +// interior whitespace of the assignment. E is considered interior +// whitespace of the BlockStmt containing the assignment. +// +// The resulting path is never empty; it always contains at least the +// 'root' *ast.File. Ideally PathEnclosingInterval would reject +// intervals that lie wholly or partially outside the range of the +// file, but unfortunately ast.File records only the token.Pos of +// the 'package' keyword, but not of the start of the file itself. +func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) { + // fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging + + // Precondition: node.[Pos..End) and adjoining whitespace contain [start, end). + var visit func(node ast.Node) bool + visit = func(node ast.Node) bool { + path = append(path, node) + + nodePos := node.Pos() + nodeEnd := node.End() + + // fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging + + // Intersect [start, end) with interval of node. + if start < nodePos { + start = nodePos + } + if end > nodeEnd { + end = nodeEnd + } + + // Find sole child that contains [start, end). + children := childrenOf(node) + l := len(children) + for i, child := range children { + // [childPos, childEnd) is unaugmented interval of child. + childPos := child.Pos() + childEnd := child.End() + + // [augPos, augEnd) is whitespace-augmented interval of child. + augPos := childPos + augEnd := childEnd + if i > 0 { + augPos = children[i-1].End() // start of preceding whitespace + } + if i < l-1 { + nextChildPos := children[i+1].Pos() + // Does [start, end) lie between child and next child? + if start >= augEnd && end <= nextChildPos { + return false // inexact match + } + augEnd = nextChildPos // end of following whitespace + } + + // fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n", + // i, augPos, augEnd, start, end) // debugging + + // Does augmented child strictly contain [start, end)? + if augPos <= start && end <= augEnd { + _, isToken := child.(tokenNode) + return isToken || visit(child) + } + + // Does [start, end) overlap multiple children? + // i.e. left-augmented child contains start + // but LR-augmented child does not contain end. + if start < childEnd && end > augEnd { + break + } + } + + // No single child contained [start, end), + // so node is the result. Is it exact? + + // (It's tempting to put this condition before the + // child loop, but it gives the wrong result in the + // case where a node (e.g. ExprStmt) and its sole + // child have equal intervals.) + if start == nodePos && end == nodeEnd { + return true // exact match + } + + return false // inexact: overlaps multiple children + } + + // Ensure [start,end) is nondecreasing. + if start > end { + start, end = end, start + } + + if start < root.End() && end > root.Pos() { + if start == end { + end = start + 1 // empty interval => interval of size 1 + } + exact = visit(root) + + // Reverse the path: + for i, l := 0, len(path); i < l/2; i++ { + path[i], path[l-1-i] = path[l-1-i], path[i] + } + } else { + // Selection lies within whitespace preceding the + // first (or following the last) declaration in the file. + // The result nonetheless always includes the ast.File. + path = append(path, root) + } + + return +} + +// tokenNode is a dummy implementation of ast.Node for a single token. +// They are used transiently by PathEnclosingInterval but never escape +// this package. +type tokenNode struct { + pos token.Pos + end token.Pos +} + +func (n tokenNode) Pos() token.Pos { + return n.pos +} + +func (n tokenNode) End() token.Pos { + return n.end +} + +func tok(pos token.Pos, len int) ast.Node { + return tokenNode{pos, pos + token.Pos(len)} +} + +// childrenOf returns the direct non-nil children of ast.Node n. +// It may include fake ast.Node implementations for bare tokens. +// it is not safe to call (e.g.) ast.Walk on such nodes. +func childrenOf(n ast.Node) []ast.Node { + var children []ast.Node + + // First add nodes for all true subtrees. + ast.Inspect(n, func(node ast.Node) bool { + if node == n { // push n + return true // recur + } + if node != nil { // push child + children = append(children, node) + } + return false // no recursion + }) + + // Then add fake Nodes for bare tokens. + switch n := n.(type) { + case *ast.ArrayType: + children = append(children, + tok(n.Lbrack, len("[")), + tok(n.Elt.End(), len("]"))) + + case *ast.AssignStmt: + children = append(children, + tok(n.TokPos, len(n.Tok.String()))) + + case *ast.BasicLit: + children = append(children, + tok(n.ValuePos, len(n.Value))) + + case *ast.BinaryExpr: + children = append(children, tok(n.OpPos, len(n.Op.String()))) + + case *ast.BlockStmt: + children = append(children, + tok(n.Lbrace, len("{")), + tok(n.Rbrace, len("}"))) + + case *ast.BranchStmt: + children = append(children, + tok(n.TokPos, len(n.Tok.String()))) + + case *ast.CallExpr: + children = append(children, + tok(n.Lparen, len("(")), + tok(n.Rparen, len(")"))) + if n.Ellipsis != 0 { + children = append(children, tok(n.Ellipsis, len("..."))) + } + + case *ast.CaseClause: + if n.List == nil { + children = append(children, + tok(n.Case, len("default"))) + } else { + children = append(children, + tok(n.Case, len("case"))) + } + children = append(children, tok(n.Colon, len(":"))) + + case *ast.ChanType: + switch n.Dir { + case ast.RECV: + children = append(children, tok(n.Begin, len("<-chan"))) + case ast.SEND: + children = append(children, tok(n.Begin, len("chan<-"))) + case ast.RECV | ast.SEND: + children = append(children, tok(n.Begin, len("chan"))) + } + + case *ast.CommClause: + if n.Comm == nil { + children = append(children, + tok(n.Case, len("default"))) + } else { + children = append(children, + tok(n.Case, len("case"))) + } + children = append(children, tok(n.Colon, len(":"))) + + case *ast.Comment: + // nop + + case *ast.CommentGroup: + // nop + + case *ast.CompositeLit: + children = append(children, + tok(n.Lbrace, len("{")), + tok(n.Rbrace, len("{"))) + + case *ast.DeclStmt: + // nop + + case *ast.DeferStmt: + children = append(children, + tok(n.Defer, len("defer"))) + + case *ast.Ellipsis: + children = append(children, + tok(n.Ellipsis, len("..."))) + + case *ast.EmptyStmt: + // nop + + case *ast.ExprStmt: + // nop + + case *ast.Field: + // TODO(adonovan): Field.{Doc,Comment,Tag}? + + case *ast.FieldList: + children = append(children, + tok(n.Opening, len("(")), // or len("[") + tok(n.Closing, len(")"))) // or len("]") + + case *ast.File: + // TODO test: Doc + children = append(children, + tok(n.Package, len("package"))) + + case *ast.ForStmt: + children = append(children, + tok(n.For, len("for"))) + + case *ast.FuncDecl: + // TODO(adonovan): FuncDecl.Comment? + + // Uniquely, FuncDecl breaks the invariant that + // preorder traversal yields tokens in lexical order: + // in fact, FuncDecl.Recv precedes FuncDecl.Type.Func. + // + // As a workaround, we inline the case for FuncType + // here and order things correctly. + // + children = nil // discard ast.Walk(FuncDecl) info subtrees + children = append(children, tok(n.Type.Func, len("func"))) + if n.Recv != nil { + children = append(children, n.Recv) + } + children = append(children, n.Name) + if tparams := typeparams.ForFuncType(n.Type); tparams != nil { + children = append(children, tparams) + } + if n.Type.Params != nil { + children = append(children, n.Type.Params) + } + if n.Type.Results != nil { + children = append(children, n.Type.Results) + } + if n.Body != nil { + children = append(children, n.Body) + } + + case *ast.FuncLit: + // nop + + case *ast.FuncType: + if n.Func != 0 { + children = append(children, + tok(n.Func, len("func"))) + } + + case *ast.GenDecl: + children = append(children, + tok(n.TokPos, len(n.Tok.String()))) + if n.Lparen != 0 { + children = append(children, + tok(n.Lparen, len("(")), + tok(n.Rparen, len(")"))) + } + + case *ast.GoStmt: + children = append(children, + tok(n.Go, len("go"))) + + case *ast.Ident: + children = append(children, + tok(n.NamePos, len(n.Name))) + + case *ast.IfStmt: + children = append(children, + tok(n.If, len("if"))) + + case *ast.ImportSpec: + // TODO(adonovan): ImportSpec.{Doc,EndPos}? + + case *ast.IncDecStmt: + children = append(children, + tok(n.TokPos, len(n.Tok.String()))) + + case *ast.IndexExpr: + children = append(children, + tok(n.Lbrack, len("[")), + tok(n.Rbrack, len("]"))) + + case *typeparams.IndexListExpr: + children = append(children, + tok(n.Lbrack, len("[")), + tok(n.Rbrack, len("]"))) + + case *ast.InterfaceType: + children = append(children, + tok(n.Interface, len("interface"))) + + case *ast.KeyValueExpr: + children = append(children, + tok(n.Colon, len(":"))) + + case *ast.LabeledStmt: + children = append(children, + tok(n.Colon, len(":"))) + + case *ast.MapType: + children = append(children, + tok(n.Map, len("map"))) + + case *ast.ParenExpr: + children = append(children, + tok(n.Lparen, len("(")), + tok(n.Rparen, len(")"))) + + case *ast.RangeStmt: + children = append(children, + tok(n.For, len("for")), + tok(n.TokPos, len(n.Tok.String()))) + + case *ast.ReturnStmt: + children = append(children, + tok(n.Return, len("return"))) + + case *ast.SelectStmt: + children = append(children, + tok(n.Select, len("select"))) + + case *ast.SelectorExpr: + // nop + + case *ast.SendStmt: + children = append(children, + tok(n.Arrow, len("<-"))) + + case *ast.SliceExpr: + children = append(children, + tok(n.Lbrack, len("[")), + tok(n.Rbrack, len("]"))) + + case *ast.StarExpr: + children = append(children, tok(n.Star, len("*"))) + + case *ast.StructType: + children = append(children, tok(n.Struct, len("struct"))) + + case *ast.SwitchStmt: + children = append(children, tok(n.Switch, len("switch"))) + + case *ast.TypeAssertExpr: + children = append(children, + tok(n.Lparen-1, len(".")), + tok(n.Lparen, len("(")), + tok(n.Rparen, len(")"))) + + case *ast.TypeSpec: + // TODO(adonovan): TypeSpec.{Doc,Comment}? + + case *ast.TypeSwitchStmt: + children = append(children, tok(n.Switch, len("switch"))) + + case *ast.UnaryExpr: + children = append(children, tok(n.OpPos, len(n.Op.String()))) + + case *ast.ValueSpec: + // TODO(adonovan): ValueSpec.{Doc,Comment}? + + case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt: + // nop + } + + // TODO(adonovan): opt: merge the logic of ast.Inspect() into + // the switch above so we can make interleaved callbacks for + // both Nodes and Tokens in the right order and avoid the need + // to sort. + sort.Sort(byPos(children)) + + return children +} + +type byPos []ast.Node + +func (sl byPos) Len() int { + return len(sl) +} +func (sl byPos) Less(i, j int) bool { + return sl[i].Pos() < sl[j].Pos() +} +func (sl byPos) Swap(i, j int) { + sl[i], sl[j] = sl[j], sl[i] +} + +// NodeDescription returns a description of the concrete type of n suitable +// for a user interface. +// +// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident, +// StarExpr) we could be much more specific given the path to the AST +// root. Perhaps we should do that. +func NodeDescription(n ast.Node) string { + switch n := n.(type) { + case *ast.ArrayType: + return "array type" + case *ast.AssignStmt: + return "assignment" + case *ast.BadDecl: + return "bad declaration" + case *ast.BadExpr: + return "bad expression" + case *ast.BadStmt: + return "bad statement" + case *ast.BasicLit: + return "basic literal" + case *ast.BinaryExpr: + return fmt.Sprintf("binary %s operation", n.Op) + case *ast.BlockStmt: + return "block" + case *ast.BranchStmt: + switch n.Tok { + case token.BREAK: + return "break statement" + case token.CONTINUE: + return "continue statement" + case token.GOTO: + return "goto statement" + case token.FALLTHROUGH: + return "fall-through statement" + } + case *ast.CallExpr: + if len(n.Args) == 1 && !n.Ellipsis.IsValid() { + return "function call (or conversion)" + } + return "function call" + case *ast.CaseClause: + return "case clause" + case *ast.ChanType: + return "channel type" + case *ast.CommClause: + return "communication clause" + case *ast.Comment: + return "comment" + case *ast.CommentGroup: + return "comment group" + case *ast.CompositeLit: + return "composite literal" + case *ast.DeclStmt: + return NodeDescription(n.Decl) + " statement" + case *ast.DeferStmt: + return "defer statement" + case *ast.Ellipsis: + return "ellipsis" + case *ast.EmptyStmt: + return "empty statement" + case *ast.ExprStmt: + return "expression statement" + case *ast.Field: + // Can be any of these: + // struct {x, y int} -- struct field(s) + // struct {T} -- anon struct field + // interface {I} -- interface embedding + // interface {f()} -- interface method + // func (A) func(B) C -- receiver, param(s), result(s) + return "field/method/parameter" + case *ast.FieldList: + return "field/method/parameter list" + case *ast.File: + return "source file" + case *ast.ForStmt: + return "for loop" + case *ast.FuncDecl: + return "function declaration" + case *ast.FuncLit: + return "function literal" + case *ast.FuncType: + return "function type" + case *ast.GenDecl: + switch n.Tok { + case token.IMPORT: + return "import declaration" + case token.CONST: + return "constant declaration" + case token.TYPE: + return "type declaration" + case token.VAR: + return "variable declaration" + } + case *ast.GoStmt: + return "go statement" + case *ast.Ident: + return "identifier" + case *ast.IfStmt: + return "if statement" + case *ast.ImportSpec: + return "import specification" + case *ast.IncDecStmt: + if n.Tok == token.INC { + return "increment statement" + } + return "decrement statement" + case *ast.IndexExpr: + return "index expression" + case *typeparams.IndexListExpr: + return "index list expression" + case *ast.InterfaceType: + return "interface type" + case *ast.KeyValueExpr: + return "key/value association" + case *ast.LabeledStmt: + return "statement label" + case *ast.MapType: + return "map type" + case *ast.Package: + return "package" + case *ast.ParenExpr: + return "parenthesized " + NodeDescription(n.X) + case *ast.RangeStmt: + return "range loop" + case *ast.ReturnStmt: + return "return statement" + case *ast.SelectStmt: + return "select statement" + case *ast.SelectorExpr: + return "selector" + case *ast.SendStmt: + return "channel send" + case *ast.SliceExpr: + return "slice expression" + case *ast.StarExpr: + return "*-operation" // load/store expr or pointer type + case *ast.StructType: + return "struct type" + case *ast.SwitchStmt: + return "switch statement" + case *ast.TypeAssertExpr: + return "type assertion" + case *ast.TypeSpec: + return "type specification" + case *ast.TypeSwitchStmt: + return "type switch" + case *ast.UnaryExpr: + return fmt.Sprintf("unary %s operation", n.Op) + case *ast.ValueSpec: + return "value specification" + + } + panic(fmt.Sprintf("unexpected node type: %T", n)) +} diff --git a/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/imports.go new file mode 100644 index 00000000000..18d1adb05dd --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/imports.go @@ -0,0 +1,485 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package astutil contains common utilities for working with the Go AST. +package astutil // import "golang.org/x/tools/go/ast/astutil" + +import ( + "fmt" + "go/ast" + "go/token" + "strconv" + "strings" +) + +// AddImport adds the import path to the file f, if absent. +func AddImport(fset *token.FileSet, f *ast.File, path string) (added bool) { + return AddNamedImport(fset, f, "", path) +} + +// AddNamedImport adds the import with the given name and path to the file f, if absent. +// If name is not empty, it is used to rename the import. +// +// For example, calling +// +// AddNamedImport(fset, f, "pathpkg", "path") +// +// adds +// +// import pathpkg "path" +func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added bool) { + if imports(f, name, path) { + return false + } + + newImport := &ast.ImportSpec{ + Path: &ast.BasicLit{ + Kind: token.STRING, + Value: strconv.Quote(path), + }, + } + if name != "" { + newImport.Name = &ast.Ident{Name: name} + } + + // Find an import decl to add to. + // The goal is to find an existing import + // whose import path has the longest shared + // prefix with path. + var ( + bestMatch = -1 // length of longest shared prefix + lastImport = -1 // index in f.Decls of the file's final import decl + impDecl *ast.GenDecl // import decl containing the best match + impIndex = -1 // spec index in impDecl containing the best match + + isThirdPartyPath = isThirdParty(path) + ) + for i, decl := range f.Decls { + gen, ok := decl.(*ast.GenDecl) + if ok && gen.Tok == token.IMPORT { + lastImport = i + // Do not add to import "C", to avoid disrupting the + // association with its doc comment, breaking cgo. + if declImports(gen, "C") { + continue + } + + // Match an empty import decl if that's all that is available. + if len(gen.Specs) == 0 && bestMatch == -1 { + impDecl = gen + } + + // Compute longest shared prefix with imports in this group and find best + // matched import spec. + // 1. Always prefer import spec with longest shared prefix. + // 2. While match length is 0, + // - for stdlib package: prefer first import spec. + // - for third party package: prefer first third party import spec. + // We cannot use last import spec as best match for third party package + // because grouped imports are usually placed last by goimports -local + // flag. + // See issue #19190. + seenAnyThirdParty := false + for j, spec := range gen.Specs { + impspec := spec.(*ast.ImportSpec) + p := importPath(impspec) + n := matchLen(p, path) + if n > bestMatch || (bestMatch == 0 && !seenAnyThirdParty && isThirdPartyPath) { + bestMatch = n + impDecl = gen + impIndex = j + } + seenAnyThirdParty = seenAnyThirdParty || isThirdParty(p) + } + } + } + + // If no import decl found, add one after the last import. + if impDecl == nil { + impDecl = &ast.GenDecl{ + Tok: token.IMPORT, + } + if lastImport >= 0 { + impDecl.TokPos = f.Decls[lastImport].End() + } else { + // There are no existing imports. + // Our new import, preceded by a blank line, goes after the package declaration + // and after the comment, if any, that starts on the same line as the + // package declaration. + impDecl.TokPos = f.Package + + file := fset.File(f.Package) + pkgLine := file.Line(f.Package) + for _, c := range f.Comments { + if file.Line(c.Pos()) > pkgLine { + break + } + // +2 for a blank line + impDecl.TokPos = c.End() + 2 + } + } + f.Decls = append(f.Decls, nil) + copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:]) + f.Decls[lastImport+1] = impDecl + } + + // Insert new import at insertAt. + insertAt := 0 + if impIndex >= 0 { + // insert after the found import + insertAt = impIndex + 1 + } + impDecl.Specs = append(impDecl.Specs, nil) + copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:]) + impDecl.Specs[insertAt] = newImport + pos := impDecl.Pos() + if insertAt > 0 { + // If there is a comment after an existing import, preserve the comment + // position by adding the new import after the comment. + if spec, ok := impDecl.Specs[insertAt-1].(*ast.ImportSpec); ok && spec.Comment != nil { + pos = spec.Comment.End() + } else { + // Assign same position as the previous import, + // so that the sorter sees it as being in the same block. + pos = impDecl.Specs[insertAt-1].Pos() + } + } + if newImport.Name != nil { + newImport.Name.NamePos = pos + } + newImport.Path.ValuePos = pos + newImport.EndPos = pos + + // Clean up parens. impDecl contains at least one spec. + if len(impDecl.Specs) == 1 { + // Remove unneeded parens. + impDecl.Lparen = token.NoPos + } else if !impDecl.Lparen.IsValid() { + // impDecl needs parens added. + impDecl.Lparen = impDecl.Specs[0].Pos() + } + + f.Imports = append(f.Imports, newImport) + + if len(f.Decls) <= 1 { + return true + } + + // Merge all the import declarations into the first one. + var first *ast.GenDecl + for i := 0; i < len(f.Decls); i++ { + decl := f.Decls[i] + gen, ok := decl.(*ast.GenDecl) + if !ok || gen.Tok != token.IMPORT || declImports(gen, "C") { + continue + } + if first == nil { + first = gen + continue // Don't touch the first one. + } + // We now know there is more than one package in this import + // declaration. Ensure that it ends up parenthesized. + first.Lparen = first.Pos() + // Move the imports of the other import declaration to the first one. + for _, spec := range gen.Specs { + spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() + first.Specs = append(first.Specs, spec) + } + f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) + i-- + } + + return true +} + +func isThirdParty(importPath string) bool { + // Third party package import path usually contains "." (".com", ".org", ...) + // This logic is taken from golang.org/x/tools/imports package. + return strings.Contains(importPath, ".") +} + +// DeleteImport deletes the import path from the file f, if present. +// If there are duplicate import declarations, all matching ones are deleted. +func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) { + return DeleteNamedImport(fset, f, "", path) +} + +// DeleteNamedImport deletes the import with the given name and path from the file f, if present. +// If there are duplicate import declarations, all matching ones are deleted. +func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) { + var delspecs []*ast.ImportSpec + var delcomments []*ast.CommentGroup + + // Find the import nodes that import path, if any. + for i := 0; i < len(f.Decls); i++ { + decl := f.Decls[i] + gen, ok := decl.(*ast.GenDecl) + if !ok || gen.Tok != token.IMPORT { + continue + } + for j := 0; j < len(gen.Specs); j++ { + spec := gen.Specs[j] + impspec := spec.(*ast.ImportSpec) + if importName(impspec) != name || importPath(impspec) != path { + continue + } + + // We found an import spec that imports path. + // Delete it. + delspecs = append(delspecs, impspec) + deleted = true + copy(gen.Specs[j:], gen.Specs[j+1:]) + gen.Specs = gen.Specs[:len(gen.Specs)-1] + + // If this was the last import spec in this decl, + // delete the decl, too. + if len(gen.Specs) == 0 { + copy(f.Decls[i:], f.Decls[i+1:]) + f.Decls = f.Decls[:len(f.Decls)-1] + i-- + break + } else if len(gen.Specs) == 1 { + if impspec.Doc != nil { + delcomments = append(delcomments, impspec.Doc) + } + if impspec.Comment != nil { + delcomments = append(delcomments, impspec.Comment) + } + for _, cg := range f.Comments { + // Found comment on the same line as the import spec. + if cg.End() < impspec.Pos() && fset.Position(cg.End()).Line == fset.Position(impspec.Pos()).Line { + delcomments = append(delcomments, cg) + break + } + } + + spec := gen.Specs[0].(*ast.ImportSpec) + + // Move the documentation right after the import decl. + if spec.Doc != nil { + for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Doc.Pos()).Line { + fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) + } + } + for _, cg := range f.Comments { + if cg.End() < spec.Pos() && fset.Position(cg.End()).Line == fset.Position(spec.Pos()).Line { + for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Pos()).Line { + fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) + } + break + } + } + } + if j > 0 { + lastImpspec := gen.Specs[j-1].(*ast.ImportSpec) + lastLine := fset.PositionFor(lastImpspec.Path.ValuePos, false).Line + line := fset.PositionFor(impspec.Path.ValuePos, false).Line + + // We deleted an entry but now there may be + // a blank line-sized hole where the import was. + if line-lastLine > 1 || !gen.Rparen.IsValid() { + // There was a blank line immediately preceding the deleted import, + // so there's no need to close the hole. The right parenthesis is + // invalid after AddImport to an import statement without parenthesis. + // Do nothing. + } else if line != fset.File(gen.Rparen).LineCount() { + // There was no blank line. Close the hole. + fset.File(gen.Rparen).MergeLine(line) + } + } + j-- + } + } + + // Delete imports from f.Imports. + for i := 0; i < len(f.Imports); i++ { + imp := f.Imports[i] + for j, del := range delspecs { + if imp == del { + copy(f.Imports[i:], f.Imports[i+1:]) + f.Imports = f.Imports[:len(f.Imports)-1] + copy(delspecs[j:], delspecs[j+1:]) + delspecs = delspecs[:len(delspecs)-1] + i-- + break + } + } + } + + // Delete comments from f.Comments. + for i := 0; i < len(f.Comments); i++ { + cg := f.Comments[i] + for j, del := range delcomments { + if cg == del { + copy(f.Comments[i:], f.Comments[i+1:]) + f.Comments = f.Comments[:len(f.Comments)-1] + copy(delcomments[j:], delcomments[j+1:]) + delcomments = delcomments[:len(delcomments)-1] + i-- + break + } + } + } + + if len(delspecs) > 0 { + panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs)) + } + + return +} + +// RewriteImport rewrites any import of path oldPath to path newPath. +func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) { + for _, imp := range f.Imports { + if importPath(imp) == oldPath { + rewrote = true + // record old End, because the default is to compute + // it using the length of imp.Path.Value. + imp.EndPos = imp.End() + imp.Path.Value = strconv.Quote(newPath) + } + } + return +} + +// UsesImport reports whether a given import is used. +func UsesImport(f *ast.File, path string) (used bool) { + spec := importSpec(f, path) + if spec == nil { + return + } + + name := spec.Name.String() + switch name { + case "": + // If the package name is not explicitly specified, + // make an educated guess. This is not guaranteed to be correct. + lastSlash := strings.LastIndex(path, "/") + if lastSlash == -1 { + name = path + } else { + name = path[lastSlash+1:] + } + case "_", ".": + // Not sure if this import is used - err on the side of caution. + return true + } + + ast.Walk(visitFn(func(n ast.Node) { + sel, ok := n.(*ast.SelectorExpr) + if ok && isTopName(sel.X, name) { + used = true + } + }), f) + + return +} + +type visitFn func(node ast.Node) + +func (fn visitFn) Visit(node ast.Node) ast.Visitor { + fn(node) + return fn +} + +// imports reports whether f has an import with the specified name and path. +func imports(f *ast.File, name, path string) bool { + for _, s := range f.Imports { + if importName(s) == name && importPath(s) == path { + return true + } + } + return false +} + +// importSpec returns the import spec if f imports path, +// or nil otherwise. +func importSpec(f *ast.File, path string) *ast.ImportSpec { + for _, s := range f.Imports { + if importPath(s) == path { + return s + } + } + return nil +} + +// importName returns the name of s, +// or "" if the import is not named. +func importName(s *ast.ImportSpec) string { + if s.Name == nil { + return "" + } + return s.Name.Name +} + +// importPath returns the unquoted import path of s, +// or "" if the path is not properly quoted. +func importPath(s *ast.ImportSpec) string { + t, err := strconv.Unquote(s.Path.Value) + if err != nil { + return "" + } + return t +} + +// declImports reports whether gen contains an import of path. +func declImports(gen *ast.GenDecl, path string) bool { + if gen.Tok != token.IMPORT { + return false + } + for _, spec := range gen.Specs { + impspec := spec.(*ast.ImportSpec) + if importPath(impspec) == path { + return true + } + } + return false +} + +// matchLen returns the length of the longest path segment prefix shared by x and y. +func matchLen(x, y string) int { + n := 0 + for i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ { + if x[i] == '/' { + n++ + } + } + return n +} + +// isTopName returns true if n is a top-level unresolved identifier with the given name. +func isTopName(n ast.Expr, name string) bool { + id, ok := n.(*ast.Ident) + return ok && id.Name == name && id.Obj == nil +} + +// Imports returns the file imports grouped by paragraph. +func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec { + var groups [][]*ast.ImportSpec + + for _, decl := range f.Decls { + genDecl, ok := decl.(*ast.GenDecl) + if !ok || genDecl.Tok != token.IMPORT { + break + } + + group := []*ast.ImportSpec{} + + var lastLine int + for _, spec := range genDecl.Specs { + importSpec := spec.(*ast.ImportSpec) + pos := importSpec.Path.ValuePos + line := fset.Position(pos).Line + if lastLine > 0 && pos > 0 && line-lastLine > 1 { + groups = append(groups, group) + group = []*ast.ImportSpec{} + } + group = append(group, importSpec) + lastLine = line + } + groups = append(groups, group) + } + + return groups +} diff --git a/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go new file mode 100644 index 00000000000..f430b21b9b9 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -0,0 +1,488 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package astutil + +import ( + "fmt" + "go/ast" + "reflect" + "sort" + + "golang.org/x/tools/internal/typeparams" +) + +// An ApplyFunc is invoked by Apply for each node n, even if n is nil, +// before and/or after the node's children, using a Cursor describing +// the current node and providing operations on it. +// +// The return value of ApplyFunc controls the syntax tree traversal. +// See Apply for details. +type ApplyFunc func(*Cursor) bool + +// Apply traverses a syntax tree recursively, starting with root, +// and calling pre and post for each node as described below. +// Apply returns the syntax tree, possibly modified. +// +// If pre is not nil, it is called for each node before the node's +// children are traversed (pre-order). If pre returns false, no +// children are traversed, and post is not called for that node. +// +// If post is not nil, and a prior call of pre didn't return false, +// post is called for each node after its children are traversed +// (post-order). If post returns false, traversal is terminated and +// Apply returns immediately. +// +// Only fields that refer to AST nodes are considered children; +// i.e., token.Pos, Scopes, Objects, and fields of basic types +// (strings, etc.) are ignored. +// +// Children are traversed in the order in which they appear in the +// respective node's struct definition. A package's files are +// traversed in the filenames' alphabetical order. +func Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) { + parent := &struct{ ast.Node }{root} + defer func() { + if r := recover(); r != nil && r != abort { + panic(r) + } + result = parent.Node + }() + a := &application{pre: pre, post: post} + a.apply(parent, "Node", nil, root) + return +} + +var abort = new(int) // singleton, to signal termination of Apply + +// A Cursor describes a node encountered during Apply. +// Information about the node and its parent is available +// from the Node, Parent, Name, and Index methods. +// +// If p is a variable of type and value of the current parent node +// c.Parent(), and f is the field identifier with name c.Name(), +// the following invariants hold: +// +// p.f == c.Node() if c.Index() < 0 +// p.f[c.Index()] == c.Node() if c.Index() >= 0 +// +// The methods Replace, Delete, InsertBefore, and InsertAfter +// can be used to change the AST without disrupting Apply. +type Cursor struct { + parent ast.Node + name string + iter *iterator // valid if non-nil + node ast.Node +} + +// Node returns the current Node. +func (c *Cursor) Node() ast.Node { return c.node } + +// Parent returns the parent of the current Node. +func (c *Cursor) Parent() ast.Node { return c.parent } + +// Name returns the name of the parent Node field that contains the current Node. +// If the parent is a *ast.Package and the current Node is a *ast.File, Name returns +// the filename for the current Node. +func (c *Cursor) Name() string { return c.name } + +// Index reports the index >= 0 of the current Node in the slice of Nodes that +// contains it, or a value < 0 if the current Node is not part of a slice. +// The index of the current node changes if InsertBefore is called while +// processing the current node. +func (c *Cursor) Index() int { + if c.iter != nil { + return c.iter.index + } + return -1 +} + +// field returns the current node's parent field value. +func (c *Cursor) field() reflect.Value { + return reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name) +} + +// Replace replaces the current Node with n. +// The replacement node is not walked by Apply. +func (c *Cursor) Replace(n ast.Node) { + if _, ok := c.node.(*ast.File); ok { + file, ok := n.(*ast.File) + if !ok { + panic("attempt to replace *ast.File with non-*ast.File") + } + c.parent.(*ast.Package).Files[c.name] = file + return + } + + v := c.field() + if i := c.Index(); i >= 0 { + v = v.Index(i) + } + v.Set(reflect.ValueOf(n)) +} + +// Delete deletes the current Node from its containing slice. +// If the current Node is not part of a slice, Delete panics. +// As a special case, if the current node is a package file, +// Delete removes it from the package's Files map. +func (c *Cursor) Delete() { + if _, ok := c.node.(*ast.File); ok { + delete(c.parent.(*ast.Package).Files, c.name) + return + } + + i := c.Index() + if i < 0 { + panic("Delete node not contained in slice") + } + v := c.field() + l := v.Len() + reflect.Copy(v.Slice(i, l), v.Slice(i+1, l)) + v.Index(l - 1).Set(reflect.Zero(v.Type().Elem())) + v.SetLen(l - 1) + c.iter.step-- +} + +// InsertAfter inserts n after the current Node in its containing slice. +// If the current Node is not part of a slice, InsertAfter panics. +// Apply does not walk n. +func (c *Cursor) InsertAfter(n ast.Node) { + i := c.Index() + if i < 0 { + panic("InsertAfter node not contained in slice") + } + v := c.field() + v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) + l := v.Len() + reflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l)) + v.Index(i + 1).Set(reflect.ValueOf(n)) + c.iter.step++ +} + +// InsertBefore inserts n before the current Node in its containing slice. +// If the current Node is not part of a slice, InsertBefore panics. +// Apply will not walk n. +func (c *Cursor) InsertBefore(n ast.Node) { + i := c.Index() + if i < 0 { + panic("InsertBefore node not contained in slice") + } + v := c.field() + v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) + l := v.Len() + reflect.Copy(v.Slice(i+1, l), v.Slice(i, l)) + v.Index(i).Set(reflect.ValueOf(n)) + c.iter.index++ +} + +// application carries all the shared data so we can pass it around cheaply. +type application struct { + pre, post ApplyFunc + cursor Cursor + iter iterator +} + +func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) { + // convert typed nil into untyped nil + if v := reflect.ValueOf(n); v.Kind() == reflect.Ptr && v.IsNil() { + n = nil + } + + // avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead + saved := a.cursor + a.cursor.parent = parent + a.cursor.name = name + a.cursor.iter = iter + a.cursor.node = n + + if a.pre != nil && !a.pre(&a.cursor) { + a.cursor = saved + return + } + + // walk children + // (the order of the cases matches the order of the corresponding node types in go/ast) + switch n := n.(type) { + case nil: + // nothing to do + + // Comments and fields + case *ast.Comment: + // nothing to do + + case *ast.CommentGroup: + if n != nil { + a.applyList(n, "List") + } + + case *ast.Field: + a.apply(n, "Doc", nil, n.Doc) + a.applyList(n, "Names") + a.apply(n, "Type", nil, n.Type) + a.apply(n, "Tag", nil, n.Tag) + a.apply(n, "Comment", nil, n.Comment) + + case *ast.FieldList: + a.applyList(n, "List") + + // Expressions + case *ast.BadExpr, *ast.Ident, *ast.BasicLit: + // nothing to do + + case *ast.Ellipsis: + a.apply(n, "Elt", nil, n.Elt) + + case *ast.FuncLit: + a.apply(n, "Type", nil, n.Type) + a.apply(n, "Body", nil, n.Body) + + case *ast.CompositeLit: + a.apply(n, "Type", nil, n.Type) + a.applyList(n, "Elts") + + case *ast.ParenExpr: + a.apply(n, "X", nil, n.X) + + case *ast.SelectorExpr: + a.apply(n, "X", nil, n.X) + a.apply(n, "Sel", nil, n.Sel) + + case *ast.IndexExpr: + a.apply(n, "X", nil, n.X) + a.apply(n, "Index", nil, n.Index) + + case *typeparams.IndexListExpr: + a.apply(n, "X", nil, n.X) + a.applyList(n, "Indices") + + case *ast.SliceExpr: + a.apply(n, "X", nil, n.X) + a.apply(n, "Low", nil, n.Low) + a.apply(n, "High", nil, n.High) + a.apply(n, "Max", nil, n.Max) + + case *ast.TypeAssertExpr: + a.apply(n, "X", nil, n.X) + a.apply(n, "Type", nil, n.Type) + + case *ast.CallExpr: + a.apply(n, "Fun", nil, n.Fun) + a.applyList(n, "Args") + + case *ast.StarExpr: + a.apply(n, "X", nil, n.X) + + case *ast.UnaryExpr: + a.apply(n, "X", nil, n.X) + + case *ast.BinaryExpr: + a.apply(n, "X", nil, n.X) + a.apply(n, "Y", nil, n.Y) + + case *ast.KeyValueExpr: + a.apply(n, "Key", nil, n.Key) + a.apply(n, "Value", nil, n.Value) + + // Types + case *ast.ArrayType: + a.apply(n, "Len", nil, n.Len) + a.apply(n, "Elt", nil, n.Elt) + + case *ast.StructType: + a.apply(n, "Fields", nil, n.Fields) + + case *ast.FuncType: + if tparams := typeparams.ForFuncType(n); tparams != nil { + a.apply(n, "TypeParams", nil, tparams) + } + a.apply(n, "Params", nil, n.Params) + a.apply(n, "Results", nil, n.Results) + + case *ast.InterfaceType: + a.apply(n, "Methods", nil, n.Methods) + + case *ast.MapType: + a.apply(n, "Key", nil, n.Key) + a.apply(n, "Value", nil, n.Value) + + case *ast.ChanType: + a.apply(n, "Value", nil, n.Value) + + // Statements + case *ast.BadStmt: + // nothing to do + + case *ast.DeclStmt: + a.apply(n, "Decl", nil, n.Decl) + + case *ast.EmptyStmt: + // nothing to do + + case *ast.LabeledStmt: + a.apply(n, "Label", nil, n.Label) + a.apply(n, "Stmt", nil, n.Stmt) + + case *ast.ExprStmt: + a.apply(n, "X", nil, n.X) + + case *ast.SendStmt: + a.apply(n, "Chan", nil, n.Chan) + a.apply(n, "Value", nil, n.Value) + + case *ast.IncDecStmt: + a.apply(n, "X", nil, n.X) + + case *ast.AssignStmt: + a.applyList(n, "Lhs") + a.applyList(n, "Rhs") + + case *ast.GoStmt: + a.apply(n, "Call", nil, n.Call) + + case *ast.DeferStmt: + a.apply(n, "Call", nil, n.Call) + + case *ast.ReturnStmt: + a.applyList(n, "Results") + + case *ast.BranchStmt: + a.apply(n, "Label", nil, n.Label) + + case *ast.BlockStmt: + a.applyList(n, "List") + + case *ast.IfStmt: + a.apply(n, "Init", nil, n.Init) + a.apply(n, "Cond", nil, n.Cond) + a.apply(n, "Body", nil, n.Body) + a.apply(n, "Else", nil, n.Else) + + case *ast.CaseClause: + a.applyList(n, "List") + a.applyList(n, "Body") + + case *ast.SwitchStmt: + a.apply(n, "Init", nil, n.Init) + a.apply(n, "Tag", nil, n.Tag) + a.apply(n, "Body", nil, n.Body) + + case *ast.TypeSwitchStmt: + a.apply(n, "Init", nil, n.Init) + a.apply(n, "Assign", nil, n.Assign) + a.apply(n, "Body", nil, n.Body) + + case *ast.CommClause: + a.apply(n, "Comm", nil, n.Comm) + a.applyList(n, "Body") + + case *ast.SelectStmt: + a.apply(n, "Body", nil, n.Body) + + case *ast.ForStmt: + a.apply(n, "Init", nil, n.Init) + a.apply(n, "Cond", nil, n.Cond) + a.apply(n, "Post", nil, n.Post) + a.apply(n, "Body", nil, n.Body) + + case *ast.RangeStmt: + a.apply(n, "Key", nil, n.Key) + a.apply(n, "Value", nil, n.Value) + a.apply(n, "X", nil, n.X) + a.apply(n, "Body", nil, n.Body) + + // Declarations + case *ast.ImportSpec: + a.apply(n, "Doc", nil, n.Doc) + a.apply(n, "Name", nil, n.Name) + a.apply(n, "Path", nil, n.Path) + a.apply(n, "Comment", nil, n.Comment) + + case *ast.ValueSpec: + a.apply(n, "Doc", nil, n.Doc) + a.applyList(n, "Names") + a.apply(n, "Type", nil, n.Type) + a.applyList(n, "Values") + a.apply(n, "Comment", nil, n.Comment) + + case *ast.TypeSpec: + a.apply(n, "Doc", nil, n.Doc) + a.apply(n, "Name", nil, n.Name) + if tparams := typeparams.ForTypeSpec(n); tparams != nil { + a.apply(n, "TypeParams", nil, tparams) + } + a.apply(n, "Type", nil, n.Type) + a.apply(n, "Comment", nil, n.Comment) + + case *ast.BadDecl: + // nothing to do + + case *ast.GenDecl: + a.apply(n, "Doc", nil, n.Doc) + a.applyList(n, "Specs") + + case *ast.FuncDecl: + a.apply(n, "Doc", nil, n.Doc) + a.apply(n, "Recv", nil, n.Recv) + a.apply(n, "Name", nil, n.Name) + a.apply(n, "Type", nil, n.Type) + a.apply(n, "Body", nil, n.Body) + + // Files and packages + case *ast.File: + a.apply(n, "Doc", nil, n.Doc) + a.apply(n, "Name", nil, n.Name) + a.applyList(n, "Decls") + // Don't walk n.Comments; they have either been walked already if + // they are Doc comments, or they can be easily walked explicitly. + + case *ast.Package: + // collect and sort names for reproducible behavior + var names []string + for name := range n.Files { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + a.apply(n, name, nil, n.Files[name]) + } + + default: + panic(fmt.Sprintf("Apply: unexpected node type %T", n)) + } + + if a.post != nil && !a.post(&a.cursor) { + panic(abort) + } + + a.cursor = saved +} + +// An iterator controls iteration over a slice of nodes. +type iterator struct { + index, step int +} + +func (a *application) applyList(parent ast.Node, name string) { + // avoid heap-allocating a new iterator for each applyList call; reuse a.iter instead + saved := a.iter + a.iter.index = 0 + for { + // must reload parent.name each time, since cursor modifications might change it + v := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name) + if a.iter.index >= v.Len() { + break + } + + // element x may be nil in a bad AST - be cautious + var x ast.Node + if e := v.Index(a.iter.index); e.IsValid() { + x = e.Interface().(ast.Node) + } + + a.iter.step = 1 + a.apply(parent, name, &a.iter, x) + a.iter.index += a.iter.step + } + a.iter = saved +} diff --git a/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/util.go b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/util.go new file mode 100644 index 00000000000..919d5305ab4 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/go/ast/astutil/util.go @@ -0,0 +1,18 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package astutil + +import "go/ast" + +// Unparen returns e with any enclosing parentheses stripped. +func Unparen(e ast.Expr) ast.Expr { + for { + p, ok := e.(*ast.ParenExpr) + if !ok { + return e + } + e = p.X + } +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/common.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/common.go new file mode 100644 index 00000000000..25a1426d30e --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -0,0 +1,179 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package typeparams contains common utilities for writing tools that interact +// with generic Go code, as introduced with Go 1.18. +// +// Many of the types and functions in this package are proxies for the new APIs +// introduced in the standard library with Go 1.18. For example, the +// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec +// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go +// versions older than 1.18 these helpers are implemented as stubs, allowing +// users of this package to write code that handles generic constructs inline, +// even if the Go version being used to compile does not support generics. +// +// Additionally, this package contains common utilities for working with the +// new generic constructs, to supplement the standard library APIs. Notably, +// the StructuralTerms API computes a minimal representation of the structural +// restrictions on a type parameter. +// +// An external version of these APIs is available in the +// golang.org/x/exp/typeparams module. +package typeparams + +import ( + "go/ast" + "go/token" + "go/types" +) + +// UnpackIndexExpr extracts data from AST nodes that represent index +// expressions. +// +// For an ast.IndexExpr, the resulting indices slice will contain exactly one +// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable +// number of index expressions. +// +// For nodes that don't represent index expressions, the first return value of +// UnpackIndexExpr will be nil. +func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) { + switch e := n.(type) { + case *ast.IndexExpr: + return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack + case *IndexListExpr: + return e.X, e.Lbrack, e.Indices, e.Rbrack + } + return nil, token.NoPos, nil, token.NoPos +} + +// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on +// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0 +// will panic. +func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr { + switch len(indices) { + case 0: + panic("empty indices") + case 1: + return &ast.IndexExpr{ + X: x, + Lbrack: lbrack, + Index: indices[0], + Rbrack: rbrack, + } + default: + return &IndexListExpr{ + X: x, + Lbrack: lbrack, + Indices: indices, + Rbrack: rbrack, + } + } +} + +// IsTypeParam reports whether t is a type parameter. +func IsTypeParam(t types.Type) bool { + _, ok := t.(*TypeParam) + return ok +} + +// OriginMethod returns the origin method associated with the method fn. +// For methods on a non-generic receiver base type, this is just +// fn. However, for methods with a generic receiver, OriginMethod returns the +// corresponding method in the method set of the origin type. +// +// As a special case, if fn is not a method (has no receiver), OriginMethod +// returns fn. +func OriginMethod(fn *types.Func) *types.Func { + recv := fn.Type().(*types.Signature).Recv() + if recv == nil { + + return fn + } + base := recv.Type() + p, isPtr := base.(*types.Pointer) + if isPtr { + base = p.Elem() + } + named, isNamed := base.(*types.Named) + if !isNamed { + // Receiver is a *types.Interface. + return fn + } + if ForNamed(named).Len() == 0 { + // Receiver base has no type parameters, so we can avoid the lookup below. + return fn + } + orig := NamedTypeOrigin(named) + gfn, _, _ := types.LookupFieldOrMethod(orig, true, fn.Pkg(), fn.Name()) + return gfn.(*types.Func) +} + +// GenericAssignableTo is a generalization of types.AssignableTo that +// implements the following rule for uninstantiated generic types: +// +// If V and T are generic named types, then V is considered assignable to T if, +// for every possible instantation of V[A_1, ..., A_N], the instantiation +// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N]. +// +// If T has structural constraints, they must be satisfied by V. +// +// For example, consider the following type declarations: +// +// type Interface[T any] interface { +// Accept(T) +// } +// +// type Container[T any] struct { +// Element T +// } +// +// func (c Container[T]) Accept(t T) { c.Element = t } +// +// In this case, GenericAssignableTo reports that instantiations of Container +// are assignable to the corresponding instantiation of Interface. +func GenericAssignableTo(ctxt *Context, V, T types.Type) bool { + // If V and T are not both named, or do not have matching non-empty type + // parameter lists, fall back on types.AssignableTo. + + VN, Vnamed := V.(*types.Named) + TN, Tnamed := T.(*types.Named) + if !Vnamed || !Tnamed { + return types.AssignableTo(V, T) + } + + vtparams := ForNamed(VN) + ttparams := ForNamed(TN) + if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || NamedTypeArgs(VN).Len() != 0 || NamedTypeArgs(TN).Len() != 0 { + return types.AssignableTo(V, T) + } + + // V and T have the same (non-zero) number of type params. Instantiate both + // with the type parameters of V. This must always succeed for V, and will + // succeed for T if and only if the type set of each type parameter of V is a + // subset of the type set of the corresponding type parameter of T, meaning + // that every instantiation of V corresponds to a valid instantiation of T. + + // Minor optimization: ensure we share a context across the two + // instantiations below. + if ctxt == nil { + ctxt = NewContext() + } + + var targs []types.Type + for i := 0; i < vtparams.Len(); i++ { + targs = append(targs, vtparams.At(i)) + } + + vinst, err := Instantiate(ctxt, V, targs, true) + if err != nil { + panic("type parameters should satisfy their own constraints") + } + + tinst, err := Instantiate(ctxt, T, targs, true) + if err != nil { + return false + } + + return types.AssignableTo(vinst, tinst) +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/coretype.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/coretype.go new file mode 100644 index 00000000000..993135ec90e --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/coretype.go @@ -0,0 +1,122 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeparams + +import ( + "go/types" +) + +// CoreType returns the core type of T or nil if T does not have a core type. +// +// See https://go.dev/ref/spec#Core_types for the definition of a core type. +func CoreType(T types.Type) types.Type { + U := T.Underlying() + if _, ok := U.(*types.Interface); !ok { + return U // for non-interface types, + } + + terms, err := _NormalTerms(U) + if len(terms) == 0 || err != nil { + // len(terms) -> empty type set of interface. + // err != nil => U is invalid, exceeds complexity bounds, or has an empty type set. + return nil // no core type. + } + + U = terms[0].Type().Underlying() + var identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying()) + for identical = 1; identical < len(terms); identical++ { + if !types.Identical(U, terms[identical].Type().Underlying()) { + break + } + } + + if identical == len(terms) { + // https://go.dev/ref/spec#Core_types + // "There is a single type U which is the underlying type of all types in the type set of T" + return U + } + ch, ok := U.(*types.Chan) + if !ok { + return nil // no core type as identical < len(terms) and U is not a channel. + } + // https://go.dev/ref/spec#Core_types + // "the type chan E if T contains only bidirectional channels, or the type chan<- E or + // <-chan E depending on the direction of the directional channels present." + for chans := identical; chans < len(terms); chans++ { + curr, ok := terms[chans].Type().Underlying().(*types.Chan) + if !ok { + return nil + } + if !types.Identical(ch.Elem(), curr.Elem()) { + return nil // channel elements are not identical. + } + if ch.Dir() == types.SendRecv { + // ch is bidirectional. We can safely always use curr's direction. + ch = curr + } else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() { + // ch and curr are not bidirectional and not the same direction. + return nil + } + } + return ch +} + +// _NormalTerms returns a slice of terms representing the normalized structural +// type restrictions of a type, if any. +// +// For all types other than *types.TypeParam, *types.Interface, and +// *types.Union, this is just a single term with Tilde() == false and +// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see +// below. +// +// Structural type restrictions of a type parameter are created via +// non-interface types embedded in its constraint interface (directly, or via a +// chain of interface embeddings). For example, in the declaration type +// T[P interface{~int; m()}] int the structural restriction of the type +// parameter P is ~int. +// +// With interface embedding and unions, the specification of structural type +// restrictions may be arbitrarily complex. For example, consider the +// following: +// +// type A interface{ ~string|~[]byte } +// +// type B interface{ int|string } +// +// type C interface { ~string|~int } +// +// type T[P interface{ A|B; C }] int +// +// In this example, the structural type restriction of P is ~string|int: A|B +// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int, +// which when intersected with C (~string|~int) yields ~string|int. +// +// _NormalTerms computes these expansions and reductions, producing a +// "normalized" form of the embeddings. A structural restriction is normalized +// if it is a single union containing no interface terms, and is minimal in the +// sense that removing any term changes the set of types satisfying the +// constraint. It is left as a proof for the reader that, modulo sorting, there +// is exactly one such normalized form. +// +// Because the minimal representation always takes this form, _NormalTerms +// returns a slice of tilde terms corresponding to the terms of the union in +// the normalized structural restriction. An error is returned if the type is +// invalid, exceeds complexity bounds, or has an empty type set. In the latter +// case, _NormalTerms returns ErrEmptyTypeSet. +// +// _NormalTerms makes no guarantees about the order of terms, except that it +// is deterministic. +func _NormalTerms(typ types.Type) ([]*Term, error) { + switch typ := typ.(type) { + case *TypeParam: + return StructuralTerms(typ) + case *Union: + return UnionTermSet(typ) + case *types.Interface: + return InterfaceTermSet(typ) + default: + return []*Term{NewTerm(false, typ)}, nil + } +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go new file mode 100644 index 00000000000..18212390e19 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package typeparams + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = false diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go new file mode 100644 index 00000000000..d67148823c4 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.18 +// +build go1.18 + +package typeparams + +// Note: this constant is in a separate file as this is the only acceptable +// diff between the <1.18 API of this package and the 1.18 API. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = true diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/normalize.go new file mode 100644 index 00000000000..9c631b6512d --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -0,0 +1,218 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typeparams + +import ( + "errors" + "fmt" + "go/types" + "os" + "strings" +) + +//go:generate go run copytermlist.go + +const debug = false + +var ErrEmptyTypeSet = errors.New("empty type set") + +// StructuralTerms returns a slice of terms representing the normalized +// structural type restrictions of a type parameter, if any. +// +// Structural type restrictions of a type parameter are created via +// non-interface types embedded in its constraint interface (directly, or via a +// chain of interface embeddings). For example, in the declaration +// +// type T[P interface{~int; m()}] int +// +// the structural restriction of the type parameter P is ~int. +// +// With interface embedding and unions, the specification of structural type +// restrictions may be arbitrarily complex. For example, consider the +// following: +// +// type A interface{ ~string|~[]byte } +// +// type B interface{ int|string } +// +// type C interface { ~string|~int } +// +// type T[P interface{ A|B; C }] int +// +// In this example, the structural type restriction of P is ~string|int: A|B +// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int, +// which when intersected with C (~string|~int) yields ~string|int. +// +// StructuralTerms computes these expansions and reductions, producing a +// "normalized" form of the embeddings. A structural restriction is normalized +// if it is a single union containing no interface terms, and is minimal in the +// sense that removing any term changes the set of types satisfying the +// constraint. It is left as a proof for the reader that, modulo sorting, there +// is exactly one such normalized form. +// +// Because the minimal representation always takes this form, StructuralTerms +// returns a slice of tilde terms corresponding to the terms of the union in +// the normalized structural restriction. An error is returned if the +// constraint interface is invalid, exceeds complexity bounds, or has an empty +// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet. +// +// StructuralTerms makes no guarantees about the order of terms, except that it +// is deterministic. +func StructuralTerms(tparam *TypeParam) ([]*Term, error) { + constraint := tparam.Constraint() + if constraint == nil { + return nil, fmt.Errorf("%s has nil constraint", tparam) + } + iface, _ := constraint.Underlying().(*types.Interface) + if iface == nil { + return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying()) + } + return InterfaceTermSet(iface) +} + +// InterfaceTermSet computes the normalized terms for a constraint interface, +// returning an error if the term set cannot be computed or is empty. In the +// latter case, the error will be ErrEmptyTypeSet. +// +// See the documentation of StructuralTerms for more information on +// normalization. +func InterfaceTermSet(iface *types.Interface) ([]*Term, error) { + return computeTermSet(iface) +} + +// UnionTermSet computes the normalized terms for a union, returning an error +// if the term set cannot be computed or is empty. In the latter case, the +// error will be ErrEmptyTypeSet. +// +// See the documentation of StructuralTerms for more information on +// normalization. +func UnionTermSet(union *Union) ([]*Term, error) { + return computeTermSet(union) +} + +func computeTermSet(typ types.Type) ([]*Term, error) { + tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0) + if err != nil { + return nil, err + } + if tset.terms.isEmpty() { + return nil, ErrEmptyTypeSet + } + if tset.terms.isAll() { + return nil, nil + } + var terms []*Term + for _, term := range tset.terms { + terms = append(terms, NewTerm(term.tilde, term.typ)) + } + return terms, nil +} + +// A termSet holds the normalized set of terms for a given type. +// +// The name termSet is intentionally distinct from 'type set': a type set is +// all types that implement a type (and includes method restrictions), whereas +// a term set just represents the structural restrictions on a type. +type termSet struct { + complete bool + terms termlist +} + +func indentf(depth int, format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...) +} + +func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) { + if t == nil { + panic("nil type") + } + + if debug { + indentf(depth, "%s", t.String()) + defer func() { + if err != nil { + indentf(depth, "=> %s", err) + } else { + indentf(depth, "=> %s", res.terms.String()) + } + }() + } + + const maxTermCount = 100 + if tset, ok := seen[t]; ok { + if !tset.complete { + return nil, fmt.Errorf("cycle detected in the declaration of %s", t) + } + return tset, nil + } + + // Mark the current type as seen to avoid infinite recursion. + tset := new(termSet) + defer func() { + tset.complete = true + }() + seen[t] = tset + + switch u := t.Underlying().(type) { + case *types.Interface: + // The term set of an interface is the intersection of the term sets of its + // embedded types. + tset.terms = allTermlist + for i := 0; i < u.NumEmbeddeds(); i++ { + embedded := u.EmbeddedType(i) + if _, ok := embedded.Underlying().(*TypeParam); ok { + return nil, fmt.Errorf("invalid embedded type %T", embedded) + } + tset2, err := computeTermSetInternal(embedded, seen, depth+1) + if err != nil { + return nil, err + } + tset.terms = tset.terms.intersect(tset2.terms) + } + case *Union: + // The term set of a union is the union of term sets of its terms. + tset.terms = nil + for i := 0; i < u.Len(); i++ { + t := u.Term(i) + var terms termlist + switch t.Type().Underlying().(type) { + case *types.Interface: + tset2, err := computeTermSetInternal(t.Type(), seen, depth+1) + if err != nil { + return nil, err + } + terms = tset2.terms + case *TypeParam, *Union: + // A stand-alone type parameter or union is not permitted as union + // term. + return nil, fmt.Errorf("invalid union term %T", t) + default: + if t.Type() == types.Typ[types.Invalid] { + continue + } + terms = termlist{{t.Tilde(), t.Type()}} + } + tset.terms = tset.terms.union(terms) + if len(tset.terms) > maxTermCount { + return nil, fmt.Errorf("exceeded max term count %d", maxTermCount) + } + } + case *TypeParam: + panic("unreachable") + default: + // For all other types, the term set is just a single non-tilde term + // holding the type itself. + if u != types.Typ[types.Invalid] { + tset.terms = termlist{{false, t}} + } + } + return tset, nil +} + +// under is a facade for the go/types internal function of the same name. It is +// used by typeterm.go. +func under(t types.Type) types.Type { + return t.Underlying() +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/termlist.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/termlist.go new file mode 100644 index 00000000000..933106a23dd --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/termlist.go @@ -0,0 +1,163 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by copytermlist.go DO NOT EDIT. + +package typeparams + +import ( + "bytes" + "go/types" +) + +// A termlist represents the type set represented by the union +// t1 βˆͺ y2 βˆͺ ... tn of the type sets of the terms t1 to tn. +// A termlist is in normal form if all terms are disjoint. +// termlist operations don't require the operands to be in +// normal form. +type termlist []*term + +// allTermlist represents the set of all types. +// It is in normal form. +var allTermlist = termlist{new(term)} + +// String prints the termlist exactly (without normalization). +func (xl termlist) String() string { + if len(xl) == 0 { + return "βˆ…" + } + var buf bytes.Buffer + for i, x := range xl { + if i > 0 { + buf.WriteString(" βˆͺ ") + } + buf.WriteString(x.String()) + } + return buf.String() +} + +// isEmpty reports whether the termlist xl represents the empty set of types. +func (xl termlist) isEmpty() bool { + // If there's a non-nil term, the entire list is not empty. + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil { + return false + } + } + return true +} + +// isAll reports whether the termlist xl represents the set of all types. +func (xl termlist) isAll() bool { + // If there's a 𝓀 term, the entire list is 𝓀. + // If the termlist is in normal form, this requires at most + // one iteration. + for _, x := range xl { + if x != nil && x.typ == nil { + return true + } + } + return false +} + +// norm returns the normal form of xl. +func (xl termlist) norm() termlist { + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + used := make([]bool, len(xl)) + var rl termlist + for i, xi := range xl { + if xi == nil || used[i] { + continue + } + for j := i + 1; j < len(xl); j++ { + xj := xl[j] + if xj == nil || used[j] { + continue + } + if u1, u2 := xi.union(xj); u2 == nil { + // If we encounter a 𝓀 term, the entire list is 𝓀. + // Exit early. + // (Note that this is not just an optimization; + // if we continue, we may end up with a 𝓀 term + // and other terms and the result would not be + // in normal form.) + if u1.typ == nil { + return allTermlist + } + xi = u1 + used[j] = true // xj is now unioned into xi - ignore it in future iterations + } + } + rl = append(rl, xi) + } + return rl +} + +// union returns the union xl βˆͺ yl. +func (xl termlist) union(yl termlist) termlist { + return append(xl, yl...).norm() +} + +// intersect returns the intersection xl ∩ yl. +func (xl termlist) intersect(yl termlist) termlist { + if xl.isEmpty() || yl.isEmpty() { + return nil + } + + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix asymptotic performance + var rl termlist + for _, x := range xl { + for _, y := range yl { + if r := x.intersect(y); r != nil { + rl = append(rl, r) + } + } + } + return rl.norm() +} + +// equal reports whether xl and yl represent the same type set. +func (xl termlist) equal(yl termlist) bool { + // TODO(gri) this should be more efficient + return xl.subsetOf(yl) && yl.subsetOf(xl) +} + +// includes reports whether t ∈ xl. +func (xl termlist) includes(t types.Type) bool { + for _, x := range xl { + if x.includes(t) { + return true + } + } + return false +} + +// supersetOf reports whether y βŠ† xl. +func (xl termlist) supersetOf(y *term) bool { + for _, x := range xl { + if y.subsetOf(x) { + return true + } + } + return false +} + +// subsetOf reports whether xl βŠ† yl. +func (xl termlist) subsetOf(yl termlist) bool { + if yl.isEmpty() { + return xl.isEmpty() + } + + // each term x of xl must be a subset of yl + for _, x := range xl { + if !yl.supersetOf(x) { + return false // x is not a subset yl + } + } + return true +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go new file mode 100644 index 00000000000..b4788978ff4 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go @@ -0,0 +1,197 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package typeparams + +import ( + "go/ast" + "go/token" + "go/types" +) + +func unsupported() { + panic("type parameters are unsupported at this go version") +} + +// IndexListExpr is a placeholder type, as type parameters are not supported at +// this Go version. Its methods panic on use. +type IndexListExpr struct { + ast.Expr + X ast.Expr // expression + Lbrack token.Pos // position of "[" + Indices []ast.Expr // index expressions + Rbrack token.Pos // position of "]" +} + +// ForTypeSpec returns an empty field list, as type parameters on not supported +// at this Go version. +func ForTypeSpec(*ast.TypeSpec) *ast.FieldList { + return nil +} + +// ForFuncType returns an empty field list, as type parameters are not +// supported at this Go version. +func ForFuncType(*ast.FuncType) *ast.FieldList { + return nil +} + +// TypeParam is a placeholder type, as type parameters are not supported at +// this Go version. Its methods panic on use. +type TypeParam struct{ types.Type } + +func (*TypeParam) Index() int { unsupported(); return 0 } +func (*TypeParam) Constraint() types.Type { unsupported(); return nil } +func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil } + +// TypeParamList is a placeholder for an empty type parameter list. +type TypeParamList struct{} + +func (*TypeParamList) Len() int { return 0 } +func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil } + +// TypeList is a placeholder for an empty type list. +type TypeList struct{} + +func (*TypeList) Len() int { return 0 } +func (*TypeList) At(int) types.Type { unsupported(); return nil } + +// NewTypeParam is unsupported at this Go version, and panics. +func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { + unsupported() + return nil +} + +// SetTypeParamConstraint is unsupported at this Go version, and panics. +func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { + unsupported() +} + +// NewSignatureType calls types.NewSignature, panicking if recvTypeParams or +// typeParams is non-empty. +func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature { + if len(recvTypeParams) != 0 || len(typeParams) != 0 { + panic("signatures cannot have type parameters at this Go version") + } + return types.NewSignature(recv, params, results, variadic) +} + +// ForSignature returns an empty slice. +func ForSignature(*types.Signature) *TypeParamList { + return nil +} + +// RecvTypeParams returns a nil slice. +func RecvTypeParams(sig *types.Signature) *TypeParamList { + return nil +} + +// IsComparable returns false, as no interfaces are type-restricted at this Go +// version. +func IsComparable(*types.Interface) bool { + return false +} + +// IsMethodSet returns true, as no interfaces are type-restricted at this Go +// version. +func IsMethodSet(*types.Interface) bool { + return true +} + +// IsImplicit returns false, as no interfaces are implicit at this Go version. +func IsImplicit(*types.Interface) bool { + return false +} + +// MarkImplicit does nothing, because this Go version does not have implicit +// interfaces. +func MarkImplicit(*types.Interface) {} + +// ForNamed returns an empty type parameter list, as type parameters are not +// supported at this Go version. +func ForNamed(*types.Named) *TypeParamList { + return nil +} + +// SetForNamed panics if tparams is non-empty. +func SetForNamed(_ *types.Named, tparams []*TypeParam) { + if len(tparams) > 0 { + unsupported() + } +} + +// NamedTypeArgs returns nil. +func NamedTypeArgs(*types.Named) *TypeList { + return nil +} + +// NamedTypeOrigin is the identity method at this Go version. +func NamedTypeOrigin(named *types.Named) types.Type { + return named +} + +// Term holds information about a structural type restriction. +type Term struct { + tilde bool + typ types.Type +} + +func (m *Term) Tilde() bool { return m.tilde } +func (m *Term) Type() types.Type { return m.typ } +func (m *Term) String() string { + pre := "" + if m.tilde { + pre = "~" + } + return pre + m.typ.String() +} + +// NewTerm is unsupported at this Go version, and panics. +func NewTerm(tilde bool, typ types.Type) *Term { + return &Term{tilde, typ} +} + +// Union is a placeholder type, as type parameters are not supported at this Go +// version. Its methods panic on use. +type Union struct{ types.Type } + +func (*Union) Len() int { return 0 } +func (*Union) Term(i int) *Term { unsupported(); return nil } + +// NewUnion is unsupported at this Go version, and panics. +func NewUnion(terms []*Term) *Union { + unsupported() + return nil +} + +// InitInstanceInfo is a noop at this Go version. +func InitInstanceInfo(*types.Info) {} + +// Instance is a placeholder type, as type parameters are not supported at this +// Go version. +type Instance struct { + TypeArgs *TypeList + Type types.Type +} + +// GetInstances returns a nil map, as type parameters are not supported at this +// Go version. +func GetInstances(info *types.Info) map[*ast.Ident]Instance { return nil } + +// Context is a placeholder type, as type parameters are not supported at +// this Go version. +type Context struct{} + +// NewContext returns a placeholder Context instance. +func NewContext() *Context { + return &Context{} +} + +// Instantiate is unsupported on this Go version, and panics. +func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { + unsupported() + return nil, nil +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go new file mode 100644 index 00000000000..114a36b866b --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go @@ -0,0 +1,151 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.18 +// +build go1.18 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +// IndexListExpr is an alias for ast.IndexListExpr. +type IndexListExpr = ast.IndexListExpr + +// ForTypeSpec returns n.TypeParams. +func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList { + if n == nil { + return nil + } + return n.TypeParams +} + +// ForFuncType returns n.TypeParams. +func ForFuncType(n *ast.FuncType) *ast.FieldList { + if n == nil { + return nil + } + return n.TypeParams +} + +// TypeParam is an alias for types.TypeParam +type TypeParam = types.TypeParam + +// TypeParamList is an alias for types.TypeParamList +type TypeParamList = types.TypeParamList + +// TypeList is an alias for types.TypeList +type TypeList = types.TypeList + +// NewTypeParam calls types.NewTypeParam. +func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { + return types.NewTypeParam(name, constraint) +} + +// SetTypeParamConstraint calls tparam.SetConstraint(constraint). +func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { + tparam.SetConstraint(constraint) +} + +// NewSignatureType calls types.NewSignatureType. +func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature { + return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic) +} + +// ForSignature returns sig.TypeParams() +func ForSignature(sig *types.Signature) *TypeParamList { + return sig.TypeParams() +} + +// RecvTypeParams returns sig.RecvTypeParams(). +func RecvTypeParams(sig *types.Signature) *TypeParamList { + return sig.RecvTypeParams() +} + +// IsComparable calls iface.IsComparable(). +func IsComparable(iface *types.Interface) bool { + return iface.IsComparable() +} + +// IsMethodSet calls iface.IsMethodSet(). +func IsMethodSet(iface *types.Interface) bool { + return iface.IsMethodSet() +} + +// IsImplicit calls iface.IsImplicit(). +func IsImplicit(iface *types.Interface) bool { + return iface.IsImplicit() +} + +// MarkImplicit calls iface.MarkImplicit(). +func MarkImplicit(iface *types.Interface) { + iface.MarkImplicit() +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(named *types.Named) *TypeParamList { + return named.TypeParams() +} + +// SetForNamed sets the type params tparams on n. Each tparam must be of +// dynamic type *types.TypeParam. +func SetForNamed(n *types.Named, tparams []*TypeParam) { + n.SetTypeParams(tparams) +} + +// NamedTypeArgs returns named.TypeArgs(). +func NamedTypeArgs(named *types.Named) *TypeList { + return named.TypeArgs() +} + +// NamedTypeOrigin returns named.Orig(). +func NamedTypeOrigin(named *types.Named) types.Type { + return named.Origin() +} + +// Term is an alias for types.Term. +type Term = types.Term + +// NewTerm calls types.NewTerm. +func NewTerm(tilde bool, typ types.Type) *Term { + return types.NewTerm(tilde, typ) +} + +// Union is an alias for types.Union +type Union = types.Union + +// NewUnion calls types.NewUnion. +func NewUnion(terms []*Term) *Union { + return types.NewUnion(terms) +} + +// InitInstanceInfo initializes info to record information about type and +// function instances. +func InitInstanceInfo(info *types.Info) { + info.Instances = make(map[*ast.Ident]types.Instance) +} + +// Instance is an alias for types.Instance. +type Instance = types.Instance + +// GetInstances returns info.Instances. +func GetInstances(info *types.Info) map[*ast.Ident]Instance { + return info.Instances +} + +// Context is an alias for types.Context. +type Context = types.Context + +// NewContext calls types.NewContext. +func NewContext() *Context { + return types.NewContext() +} + +// Instantiate calls types.Instantiate. +func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { + return types.Instantiate(ctxt, typ, targs, validate) +} diff --git a/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeterm.go b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeterm.go new file mode 100644 index 00000000000..7ddee28d987 --- /dev/null +++ b/eng/_core/vendor/golang.org/x/tools/internal/typeparams/typeterm.go @@ -0,0 +1,170 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by copytermlist.go DO NOT EDIT. + +package typeparams + +import "go/types" + +// A term describes elementary type sets: +// +// βˆ…: (*term)(nil) == βˆ… // set of no types (empty set) +// 𝓀: &term{} == 𝓀 // set of all types (𝓀niverse) +// T: &term{false, T} == {T} // set of type T +// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t +// +type term struct { + tilde bool // valid if typ != nil + typ types.Type +} + +func (x *term) String() string { + switch { + case x == nil: + return "βˆ…" + case x.typ == nil: + return "𝓀" + case x.tilde: + return "~" + x.typ.String() + default: + return x.typ.String() + } +} + +// equal reports whether x and y represent the same type set. +func (x *term) equal(y *term) bool { + // easy cases + switch { + case x == nil || y == nil: + return x == y + case x.typ == nil || y.typ == nil: + return x.typ == y.typ + } + // βˆ… βŠ‚ x, y βŠ‚ 𝓀 + + return x.tilde == y.tilde && types.Identical(x.typ, y.typ) +} + +// union returns the union x βˆͺ y: zero, one, or two non-nil terms. +func (x *term) union(y *term) (_, _ *term) { + // easy cases + switch { + case x == nil && y == nil: + return nil, nil // βˆ… βˆͺ βˆ… == βˆ… + case x == nil: + return y, nil // βˆ… βˆͺ y == y + case y == nil: + return x, nil // x βˆͺ βˆ… == x + case x.typ == nil: + return x, nil // 𝓀 βˆͺ y == 𝓀 + case y.typ == nil: + return y, nil // x βˆͺ 𝓀 == 𝓀 + } + // βˆ… βŠ‚ x, y βŠ‚ 𝓀 + + if x.disjoint(y) { + return x, y // x βˆͺ y == (x, y) if x ∩ y == βˆ… + } + // x.typ == y.typ + + // ~t βˆͺ ~t == ~t + // ~t βˆͺ T == ~t + // T βˆͺ ~t == ~t + // T βˆͺ T == T + if x.tilde || !y.tilde { + return x, nil + } + return y, nil +} + +// intersect returns the intersection x ∩ y. +func (x *term) intersect(y *term) *term { + // easy cases + switch { + case x == nil || y == nil: + return nil // βˆ… ∩ y == βˆ… and ∩ βˆ… == βˆ… + case x.typ == nil: + return y // 𝓀 ∩ y == y + case y.typ == nil: + return x // x ∩ 𝓀 == x + } + // βˆ… βŠ‚ x, y βŠ‚ 𝓀 + + if x.disjoint(y) { + return nil // x ∩ y == βˆ… if x ∩ y == βˆ… + } + // x.typ == y.typ + + // ~t ∩ ~t == ~t + // ~t ∩ T == T + // T ∩ ~t == T + // T ∩ T == T + if !x.tilde || y.tilde { + return x + } + return y +} + +// includes reports whether t ∈ x. +func (x *term) includes(t types.Type) bool { + // easy cases + switch { + case x == nil: + return false // t ∈ βˆ… == false + case x.typ == nil: + return true // t ∈ 𝓀 == true + } + // βˆ… βŠ‚ x βŠ‚ 𝓀 + + u := t + if x.tilde { + u = under(u) + } + return types.Identical(x.typ, u) +} + +// subsetOf reports whether x βŠ† y. +func (x *term) subsetOf(y *term) bool { + // easy cases + switch { + case x == nil: + return true // βˆ… βŠ† y == true + case y == nil: + return false // x βŠ† βˆ… == false since x != βˆ… + case y.typ == nil: + return true // x βŠ† 𝓀 == true + case x.typ == nil: + return false // 𝓀 βŠ† y == false since y != 𝓀 + } + // βˆ… βŠ‚ x, y βŠ‚ 𝓀 + + if x.disjoint(y) { + return false // x βŠ† y == false if x ∩ y == βˆ… + } + // x.typ == y.typ + + // ~t βŠ† ~t == true + // ~t βŠ† T == false + // T βŠ† ~t == true + // T βŠ† T == true + return !x.tilde || y.tilde +} + +// disjoint reports whether x ∩ y == βˆ…. +// x.typ and y.typ must not be nil. +func (x *term) disjoint(y *term) bool { + if debug && (x.typ == nil || y.typ == nil) { + panic("invalid argument(s)") + } + ux := x.typ + if y.tilde { + ux = under(ux) + } + uy := y.typ + if x.tilde { + uy = under(uy) + } + return !types.Identical(ux, uy) +} diff --git a/eng/_core/vendor/modules.txt b/eng/_core/vendor/modules.txt new file mode 100644 index 00000000000..1e80b49eebd --- /dev/null +++ b/eng/_core/vendor/modules.txt @@ -0,0 +1,8 @@ +# github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d +## explicit; go 1.18 +github.com/microsoft/go-infra/executil +github.com/microsoft/go-infra/xcryptofork +# golang.org/x/tools v0.1.12 +## explicit; go 1.18 +golang.org/x/tools/go/ast/astutil +golang.org/x/tools/internal/typeparams diff --git a/eng/_util/go.mod b/eng/_util/go.mod index 8dec8a11486..680ab676ae8 100644 --- a/eng/_util/go.mod +++ b/eng/_util/go.mod @@ -4,13 +4,28 @@ module github.com/microsoft/go/_util -go 1.16 +go 1.18 require ( - github.com/microsoft/go-infra v0.0.0-20220419195018-e437e0d7a6f9 + github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d github.com/microsoft/go/_core v0.0.0 - golang.org/x/sys v0.1.0 + golang.org/x/sys v0.5.0 gotest.tools/gotestsum v1.6.5-0.20210515201937-ecb7c6956f6d ) +require ( + github.com/dnephin/pflag v1.0.7 // indirect + github.com/fatih/color v1.10.0 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 // indirect + github.com/pkg/errors v0.9.1 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect +) + replace github.com/microsoft/go/_core => ../_core diff --git a/eng/_util/go.sum b/eng/_util/go.sum index 8a2f3a638fa..b9962ee2710 100644 --- a/eng/_util/go.sum +++ b/eng/_util/go.sum @@ -5,20 +5,24 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/microsoft/go-infra v0.0.0-20220419195018-e437e0d7a6f9 h1:TztudEX3sCZvuB9ZrKclZtxNRRE87GF5v7/U7DsLOVo= -github.com/microsoft/go-infra v0.0.0-20220419195018-e437e0d7a6f9/go.mod h1:eGPzRx36eMvtr8J3LLHYyP720NNE6kWLn78BcK/APOs= +github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 h1:YH424zrwLTlyHSH/GzLMJeu5zhYVZSx5RQxGKm1h96s= +github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY= +github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d h1:2dYhK+YQIwmN5n/AImhvU6Krn48vgWGCcuvwLb1wEJ4= +github.com/microsoft/go-infra v0.0.0-20230921065609-974951356d4d/go.mod h1:hGTlq0ZBZVmZwHgV+JezVdi8jZ2f4/UydeYvMVjAJLM= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -43,8 +47,8 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 252ea96a2b1c0f4832e4db736c14c58e7c18a691 Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Thu, 28 Sep 2023 17:48:26 -0500 Subject: [PATCH 6/7] Generate placeholder.go for x/crypto fork (always) --- eng/_core/submodule/submodule.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/eng/_core/submodule/submodule.go b/eng/_core/submodule/submodule.go index a544fac6b44..8cec5752d33 100644 --- a/eng/_core/submodule/submodule.go +++ b/eng/_core/submodule/submodule.go @@ -139,6 +139,17 @@ func GenerateMSMod(rootDir string) error { return fmt.Errorf("failed to write proxy based on %q: %v", b.Filename, err) } } + // Also generate a placeholder based on nobackend for the x/crypto fork + // itself. This is intended to be used during dev so x/crypto will build, + // but avoid making it specific to the proxies generated for our fork. + backendAPI.Constraint = "" + placeholderDir := filepath.Join(rootDir, "eng", "artifacts", "xcrypto-backend-placeholder") + if err := os.MkdirAll(placeholderDir, 0o777); err != nil { + return err + } + if err := writeBackend(backendAPI, filepath.Join(placeholderDir, "placeholder.go")); err != nil { + return fmt.Errorf("failed to write placeholder backend based on %q: %v", backendAPI.Filename, err) + } return nil } From 1bc0fca57701f71ca981df0e93d146a4994f8a40 Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Thu, 28 Sep 2023 23:46:12 -0500 Subject: [PATCH 7/7] Append PBKDF and MD4 backend APIs --- patches/0010-Add-PBKDF2-MD4.patch | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 patches/0010-Add-PBKDF2-MD4.patch diff --git a/patches/0010-Add-PBKDF2-MD4.patch b/patches/0010-Add-PBKDF2-MD4.patch new file mode 100644 index 00000000000..9f206ef1a72 --- /dev/null +++ b/patches/0010-Add-PBKDF2-MD4.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Davis Goodin +Date: Thu, 28 Sep 2023 23:39:50 -0500 +Subject: [PATCH] Add PBKDF2, MD4 + +--- + src/crypto/internal/backend/boring_linux.go | 9 +++++++++ + src/crypto/internal/backend/cng_windows.go | 9 +++++++++ + src/crypto/internal/backend/nobackend.go | 9 +++++++++ + src/crypto/internal/backend/openssl_linux.go | 9 +++++++++ + 4 files changed, 36 insertions(+) + +diff --git a/src/crypto/internal/backend/boring_linux.go b/src/crypto/internal/backend/boring_linux.go +index 35e1d00d29980d..86e74b68f87c77 100644 +--- a/src/crypto/internal/backend/boring_linux.go ++++ b/src/crypto/internal/backend/boring_linux.go +@@ -159,3 +159,12 @@ func SupportsTLS1PRF() bool { return false } + func TLS1PRF(result, secret, label, seed []byte, h func() hash.Hash) error { + panic("cryptobackend: not available") + } ++ ++func SupportsPBKDF2() bool { return false } ++ ++func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) ([]byte, error) { ++ panic("cryptobackend: not available") ++} ++ ++func NewMD4() hash.Hash { panic("cryptobackend: not available") } ++func MD4(p []byte) (sum [16]byte) { panic("cryptobackend: not available") } +diff --git a/src/crypto/internal/backend/cng_windows.go b/src/crypto/internal/backend/cng_windows.go +index b21f212d7d19d2..efec8b885694de 100644 +--- a/src/crypto/internal/backend/cng_windows.go ++++ b/src/crypto/internal/backend/cng_windows.go +@@ -257,3 +257,12 @@ func SupportsTLS1PRF() bool { + func TLS1PRF(result, secret, label, seed []byte, h func() hash.Hash) error { + return cng.TLS1PRF(result, secret, label, seed, h) + } ++ ++func SupportsPBKDF2() bool { return true } ++ ++func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) ([]byte, error) { ++ return cng.PBKDF2(password, salt, iter, keyLen, h) ++} ++ ++func NewMD4() hash.Hash { return cng.NewMD4() } ++func MD4(p []byte) (sum [16]byte) { return cng.MD4(p) } +diff --git a/src/crypto/internal/backend/nobackend.go b/src/crypto/internal/backend/nobackend.go +index 4a7c4893b2357f..82ab6505583d34 100644 +--- a/src/crypto/internal/backend/nobackend.go ++++ b/src/crypto/internal/backend/nobackend.go +@@ -141,3 +141,12 @@ func SupportsTLS1PRF() bool { panic("cryptobackend: not available") } + func TLS1PRF(result, secret, label, seed []byte, h func() hash.Hash) error { + panic("cryptobackend: not available") + } ++ ++func SupportsPBKDF2() bool { panic("cryptobackend: not available") } ++ ++func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) ([]byte, error) { ++ panic("cryptobackend: not available") ++} ++ ++func NewMD4() hash.Hash { panic("cryptobackend: not available") } ++func MD4(p []byte) (sum [16]byte) { panic("cryptobackend: not available") } +diff --git a/src/crypto/internal/backend/openssl_linux.go b/src/crypto/internal/backend/openssl_linux.go +index 39ad98afdb9bc7..99802ebfde7ddf 100644 +--- a/src/crypto/internal/backend/openssl_linux.go ++++ b/src/crypto/internal/backend/openssl_linux.go +@@ -275,3 +275,12 @@ func SupportsTLS1PRF() bool { + func TLS1PRF(result, secret, label, seed []byte, h func() hash.Hash) error { + return openssl.TLS1PRF(result, secret, label, seed, h) + } ++ ++func SupportsPBKDF2() bool { return true } ++ ++func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) ([]byte, error) { ++ return openssl.PBKDF2(password, salt, iter, keyLen, h) ++} ++ ++func NewMD4() hash.Hash { return openssl.NewMD4() } ++func MD4(p []byte) (sum [16]byte) { return openssl.MD4(p) }